RPATH与RUNPATH

时间 2011-11-01 21:46:44 Qt Labs China
主题 Qt

原文链接: ckammRPATH and RUNPATH

DT_RPATH通常设置在这样一种可执行程序中,它依赖的库无法在默认位置中被找到。举例来说,Qt Creator自带一个Qt库的副本,而且有一个指向库文件所在目录的rpath。当你构建自己的Qt库而不将其安装到全局位置时,这也是很有用的:qmlviewer之类的二进制文件之所以能够工作,是因为它们包含了一个指向了编译时所用Qt库的rpath。

如果这些文件没有设置rpath,在启动它们之前你需要显式地设置LD_LIBRARY_PATH,或写一个替你做这些事情的脚本。由于LD_LIBRARY_PATH是一个环境变量,它也有自身的一些问题。

很不幸的是:在基于glibc的系统中,动态加载器的搜索路径有些混乱。尤其是在RPATH和RUNPATH二者的区别上。这方面的文档非常匮乏: Google给出的第一个结果 是不正确的,可能只是过时了。ld和ld.so的man页面是不完整的,而且dlopen中对 RUNPATH如何起作用的描述是错的Debain Wiki 一开始说得不错,但是和dlopen页面有同样的错误,而且后面有些自相矛盾。

另一个混乱的来源是:根据你的发行版的不同,“ld”的-rpath参数表现出不同的行为。在一些发行版中生成DT_RPATH,而在另外一些发行版中却同时生成DT_RPATH和DT_RUNPATH。

好的,这并不严重,但问题是什么呢?

简单地说:在你的应用程序中设置DT_RUNPATH(或者DT_RUNPATH和DT_RPATH)并不足以保证它链接到你所指定目录中的库。

一个导致问题的具体例子:

  • Qt Creator链接到它自带的QtGui
  • 它通过dlopen加载了系统提供的KDE插件,该插件(间接)依赖QtDBus
  • 如果Qt Creator的二进制程序设置了RPATH而没有RUNPATH:Qt Creator自带QtDBus被加载
  • 如果Qt Creator的二进制程序设置了RUNPATH:系统提供的QtDBus被加载且导致Qt Creator终止。

该错误将会类似这样“Cannot mix incompatible Qt library (version 473) with this library (version 474)”[不能将当前库(版本474)与不兼容的Qt库(版本473)混用]。因为即使版本间是二进制兼容的,你也不能混用它们。QtDBus可能会依赖QtCore中已经发生变化或者在4.7.4中新增的私有API。

对于所有的链接到自有QtGui库且运行在带有KDE的系统上的应用程序,都可能发生这种问题。但是该问题也并不局限于KDE:任何使用了先前未加载的Qt库的插件,都可能查找到错误的库。

为什么会这种情况?

实验以及对glibc源码(elf/dl-load.c中的_dl_map_object)阅读表明,库的搜索顺序如下:

除非正被加载的对象(object)拥有RUNPATH:
正被加载对象的RPATH,
然后是其加载者(loader)的RPATH(除非它有RUNPATH),...,
直到搜索链的结束,它要么是可执行程序,
要么是通过dlopen加载的对象
除非可执行程序拥有RUNPATH:
该可执行程序的RPATH
LD_LIBRARY_PATH
正被加载对象的RUNPATH
ld.so.cache
默认路径

该过程解释了这种行为:我们依赖于插件加载时检查可执行程序的RPATH。可执行程序的RUNPATH并不被用来查找间接依赖的库。

我们该如何做?

当你发布二进制(程序)时,要么使用RPATH且不使用RUNPATH,要么确保LD_LIBRARY_PATH在运行前被设置。当你在“ld”默认是–enable-new-dtags(因此-rpath会添加RUNPATH)的系统中构建Qt时,要明白一点:在启动使用该版本Qt构建的程序时,你可能必须要先设置LD_LIBRARY_PATH。

RPATH与RUNPATH的更多相关文章

  1. rpath 与runpath

  2. linux动态库加载RPATH, RUNPATH

    摘自http://gotowqj.iteye.com/blog/1926771 linux动态库加载RPATH, RUNPATH 链接动态库 如何程序在连接时使用了共享库,就必须在运行的时候能够找到共 ...

  3. 探讨CMake中关于RPATH的使用

    最近研究CMake,发现CMake对于RPATH的管理也非常人性化.官方说法是当动态库的编译也和执行档在同级目录下的时候,CMake会自动给执行档加入适当的RPATH.具体可以通过readelf -d ...

  4. linux动态库加载的秘密

    摘自http://gotowqj.iteye.com/blog/1926734 摘自http://www.360doc.com/content/14/0313/13/12747488_36024641 ...

  5. 高级C/C++编译技术之读书笔记(四)之定位库文件

    最近有幸阅读了<高级C/C++编译技术>深受启发,该书深入浅出地讲解了构建过程(编译.链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架 ...

  6. 通过一道简单的例题了解Linux内核PWN

    写在前面 这篇文章目的在于简单介绍内核PWN题,揭开内核的神秘面纱.背后的知识点包含Linux驱动和内核源码,学习路线非常陡峭.也就是说,会一道Linux内核PWN需要非常多的铺垫知识,如果要学习可以 ...

  7. MacOS平台下@rpath在动态链接库中的应用

    一.背景介绍 公司开发的一个底层库被用在了Mac平台的多个产品中.在开发这个底层库的初期,对于Mac OSX下的Install name 并没有过多的了解.对于XCode中的install name项 ...

  8. @rpath/libswiftCore.dylib问题

    dyld: Library not loaded: @rpath/libswiftCore.dylib  Referenced from: /private/var/containers/Bundle ...

  9. Objective-C @executable_path、@loader_path和@rpath

    工程配置中,有三个路径和库的加载息息相关: 1.@executable_path 可执行文件的路径,例如/Applications/WeChat.app/Contents/MacOS. 2.@load ...

随机推荐

  1. 三 ICE开发初级研究

    http://www.acejoy.com/bbs/viewthread.php?tid=2878&extra=page%3D1 ICE开发初级研究(一) 最近一段一直在忙于工作,事情比较多, ...

  2. UESTC_吴队长征婚 2015 UESTC Training for Search Algorithm & String<Problem E>

    E - 吴队长征婚 Time Limit: 10000/4000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submi ...

  3. Subsets 解答

    Question Given a set of distinct integers, nums, return all possible subsets. Note: Elements in a su ...

  4. LeeCode-Linked List Cycle

    Given a linked list, determine if it has a cycle in it. /** * Definition for singly-linked list. * s ...

  5. 从设计模式说起JAVA I/O流

    从设计模式说起JAVA I/O流 之前写过一篇I/O流的入门介绍,直到最近看了设计模式,顺带理下I/O流的设计思路. JAVA类库中的I/O类分成输入和输出两部分,通过继承,任何自InputStrea ...

  6. 【转】C/C++程序员应聘常见面试题深入剖析

    1.引言 本文的写作目的并不在于提供C/C++程序员求职面试指导,而旨在从技术上分析面试题的内涵.文中的大多数面试题来自各大论坛,部分试题解答也参考了网友的意见­. 许多面试题看似简单,却需要深厚的基 ...

  7. C++中的初始化列表中可以对那些变量或对象进行初始化

    构造函数与其函数体之间可以添加初始化列表,能对某些对象进行初始化.格式为 类名() : 变量1(参数1),变量2(参数2) { } 1.     父类的对象的构造必须在初始化列表中,如: 子类名(): ...

  8. Android多媒体开发-stagefright及AwesomePlayer相关知识梳理

    android的多媒体框架中, stagefright其实是AwesomePlayer的代理,就是个皮包公司. status_t StagefrightPlayer::setDataSource( c ...

  9. React-Native ListView加载图片淡入淡出效果的组件

    今天练习项目中需要给listview在加载图片时增加一个淡入淡出的效果,因此干脆就自己封装了一个组件: 'use strict' import React from 'react-native' va ...

  10. 将整数数组按就分成2个部分,数组坐标为奇数,右边为偶数(java实现)

    方法1: 若不考虑性能: 使用一个新的数组target 遍历原数组 发现奇数则复制到target中 然后偶数 最后显示 import java.util.Arrays; public class Sp ...