Back to Blog home

RPATH与RUNPATH

Published on 星期二 十一月 01, 2011 by Debao Zhang in C++ qt-labs-chinese | Comments

原文链接: ckamm RPATH 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。

Subscribe to Our Blog

Stay up to date with the latest marketing, sales and service tips and news.

?
Aleksey
0 points
86 months ago

Yes, fixing bugs in QtWidgets and QtCreator would be good! Also good to improve Widgets or provide good samples to support modern complex UIs like other frameworks have:
- filtered columns in tree/table views
- complex headers with widgets
- split columns,
- more customizations in existing widgets, in Designer
- etc, etc

?
Katica Borčić
0 points
86 months ago

Thanks, Aleksey! Yes, we are definitely planning to put more focus on Widgets and continue adding value to Qt Creator. The current aim with Widgets is to tackle the existing bug reports and suggestions in Jira before we augment the feature list, and we are thankful to the community for a tremendous help!

?
Jason
0 points
86 months ago

It would be really cool if...
Someone could figure out how to abstract the behavior and logic from Widgets/Controls from the UI, so that everything QML didn't have to be a re-implementation of Widgets. QML's easy C++ integration means that we should be able to code a CheckBox Behavior C++ class, and have both a GL-based QML UI and a QPainter based class use that same Behavior class*. Currently you can embed one in the other, but the behavior/GUI exists as a combined unit.

*Not to be be confused with QML Behavior elements.

?
jason
0 points
86 months ago

When are we going to get a TreeView in QML?

?
Atchadam228
0 points
85 months ago

Qt was the base of my succes as c++ programmer...Qt motivates me every time...I'm glad when using Qt...even if mates are trying to find out weaks about Qt...I strongly expecting for Qt to improve them and they are keeping doing it...It would be nice if Qt make something for us to facilitate Printing and reporting...and some plugins to access databases from QtCreator....and to design some charts UI. I have a lot to ask but very tankful for what I already have...

?
Jason
0 points
85 months ago

We need QML to become a web standard.