我有一个Linux Qt程序。我希望在可执行文件目录中优先使用(动态)Qt库(如果存在),否则使用系统的Qt库。 RPATH救援。
我将此行添加到 qmake 的.pro文件中:
QMAKE_LFLAGS += '-Wl,-rpath,\'\$$ORIGIN\''
用 readelf 查看生成的可执行文件,我看到了:
0x000000000000000f (RPATH) Library rpath: [$ORIGIN:/usr/local/Trolltech/Qt-5.2.0/lib]
0x000000000000001d (RUNPATH) Library runpath: [$ORIGIN:/usr/local/Trolltech/Qt-5.2.0/lib]
似乎没错,但是 ldd 显示它使用系统版本:
libQt5Core.so.5 => /usr/local/Trolltech/Qt-5.2.0/lib/libQt5Core.so.5 (0x00007f2d2fe09000)
如果我手动编辑qmake的生成的Makefile来交换两个rpath的顺序,那么$ ORIGIN出现在/ usr / local / ...之后,我得到正确的行为:
0x000000000000000f (RPATH) Library rpath: [/usr/local/Trolltech/Qt-5.2.0/lib:$ORIGIN]
0x000000000000001d (RUNPATH) Library runpath: [/usr/local/Trolltech/Qt-5.2.0/lib:$ORIGIN]
libQt5Core.so.5 => ./libQt5Core.so.5 (0x00007fb92aba9000)
我的问题在于 qmake 如何构建最终的LFLAGS变量。我无法弄清楚如何在系统库之后添加($ ORIGIN)。有什么想法吗?
答案 0 :(得分:12)
您可以将以下内容添加到.pro文件中,以强制动态链接器在运行时在Linux中查找与Qt应用程序相同的目录:
unix:{
# suppress the default RPATH if you wish
QMAKE_LFLAGS_RPATH=
# add your own with quoting gyrations to make sure $ORIGIN gets to the command line unexpanded
QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\'"
}
如果要查看可执行路径的子目录,可以使用:
QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN/libs\'"
请注意,您的应用程序目录中应该具有完全相同名称的.so文件。例如,您应该将libQt5Core.so.5.2.0
复制到名称为libQt5Core.so.5
的应用程序目录中。现在ldd显示了应用程序的目录。
您还可以在应用程序目录中使用libQt5Core.so.5.2.0
及其名称为libQt5Core.so.5
的链接。
答案 1 :(得分:1)
就我的研究而言,你只能在QMake的列表开头添加RPATH。
但是,如果您使用的是Linux并且可以安装chrpath
,那么您可以解决这个问题。
在.pro文件末尾添加此块
# Add spacing since chrpath cannot expand RPATH length
QMAKE_RPATHDIR = \
/XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY1\
/XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY2\
/XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY3\
/XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY4
QMAKE_POST_LINK += 'chrpath -r \'/my/qt/installation:\$$ORIGIN\' $$OUT_PWD/mybinaryname;'
答案 2 :(得分:0)
我对发生的事情进行了一些猜测,但这是基于了解ld的一些奇怪行为。
检查是否存在将在处理RUNPATH变量之前生效的LD_LIBRARY_PATH
变量。由于RPATH
和RUNPATH
都存在,LD_LIBRARY_PATH
规则生效,因此如果已设置,则取消设置。
其次,我永远不会期待看到:
libQt5Core.so.5 => ./libQt5Core.so.5 (0x00007fb92aba9000)
在ldd
的输出中,我总会看到$ORIGIN
扩展到二进制文件的目录(也许你缩短了它?),所以我原以为:
libQt5Core.so.5 => /path/to/bin/./libQt5Core.so.5 (0x00007fb92aba9000)
这意味着LD_LIBRARY_PATH
展开.:/usr/local/Trolltech/Qt-5.2.0/lib
听起来像是{{1}},这听起来像是你发生了环境覆盖。
答案 3 :(得分:0)
qmake会始终将QMAKE_RPATHDIR
附加在QT_INSTALL_LIBS
文件中内部定义的$(QT_DIR)/mkspecs/features/qt.prf
:
170: relative_qt_rpath:!isEmpty(QMAKE_REL_RPATH_BASE):contains(INSTALLS, target):\
173: QMAKE_RPATHDIR += $$relative_path($$[QT_INSTALL_LIBS], $$qtRelativeRPathBase())
175: QMAKE_RPATHDIR += $$[QT_INSTALL_LIBS/dev]
179:!isEmpty(QMAKE_LFLAGS_RPATHLINK):!contains(QT_CONFIG, static) {
189: QMAKE_RPATHLINKDIR *= $$unique(rpaths)
为避免您的应用程序使用系统路径中的QT
库,请注释掉上面的行QMAKE_RPATHDIR
并添加QMAKE_RPATHDIR=$ORIGIN
到{ {1}}文件。