11

我有一个 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)放在系统库之后。有任何想法吗?

4

4 回答 4

13

您可以将以下内容添加到您的 .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

于 2014-12-10T04:12:25.097 回答
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;'
于 2014-12-09T21:33:32.240 回答
0

我对正在发生的事情进行了一些猜测,但这是基于了解 ld 的一些奇怪行为。

检查是否存在LD_LIBRARY_PATH将在处理 RUNPATH 变量之前生效的变量。由于 和 的存在,RPATH规则生效,所以如果它被设置然后取消它。RUNPATHLD_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,在我看来,这听起来像是你已经发生了环境覆盖。

于 2014-12-09T17:52:39.510 回答
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.pro文件中的行。

于 2017-01-13T08:46:46.057 回答