如何使用GCC / LD设置RPATH和RUNPATH?

Mac*_*hta 6 linux gcc shared-libraries dynamic-linking ld

我最近在系统升级后遇到了这个问题:使用GCC -Wl,-rpath=选项的工作方式与以前不同。

我用它来设置一些在我的项目子模块中构建的共享库的搜索路径。当时我认为它比在LD_LIBRARY_PATH系统范围内进行设置要好(我不想每次打开计算机时都进行设置)。一切正常,这两种方法似乎是等效的。

现在,它的行为-rpath已经改变。它仍然适用于直接依赖的库,但不适用于通过链接来自同一目录集的其他库的库-rpath=。导出LD_LIBRARY_PATH仍然可以像以前一样进行。

我使用来检查了编译的输出,readelf并且有所不同。升级之前(Linux Mint 18.2和GCC 5.4),“ 动态”部分具有以下内容:

0x000000000000000f (RPATH)            Library rpath: [submod/lib]
Run Code Online (Sandbox Code Playgroud)

升级后(带有GCC 7.3的Linux Mint 19),该行更改为:

0x000000000000001d (RUNPATH)            Library runpath: [submod/lib]
Run Code Online (Sandbox Code Playgroud)

使用RPATH而不是RUNPATH吗?建议将RPATH替换为RUNPATH(或者说,它至少具有不同的用途,因为它的优先级较低),但是它没有给出答案为什么会影响间接链接。库本身在readelf输出中既没有RPATH也没有RUNPATH 。

所以我的问题是:为什么链接程序突然开始以-rpath=不同的方式解释选项,并且有办法强制执行旧的行为?(或者做一些不同的事情,将产生相同的结果。)

另一个问题是:是否可以告诉链接器的旧版本产生新的输出(即RUNPATH而不是RPATH)?


编辑

这不是如何设置二进制文件的RunPath的副本-我的问题恰恰相反:我想要RPATH的行为。我知道了(感谢评论中的技巧),我将在这里回答我的问题。

小智 14

GNU Binutils 项目(包含 GNU 链接器 (ld))并不是这种行为变化的根源,而是 Debian (2016) 1和 Gentoo (2013!) 2

根据 Mike Frysinger 在 2013 年 1 月的 gentoo 提交:

““新”dtags 选项已经存在 14 年多了,因此对于 Linux 和 GNU 目标,默认启用它们。”

此更改并未得到很好的接受3 , 4 , 5,因为 RUNPATH 和 RPATH 具有“未记录的行为差异”...令人惊讶的是,此更改现在已应用于 Debian 稳定版。

问题是使用 RUNPATH 会导致不可预测的问题......但主要是可以工作。来自维基百科:

与 DT_RPATH 不同,ld 动态链接器不会在 DT_RUNPATH 位置中搜索 传递依赖项


Mac*_*hta 6

有办法强制旧行为吗?

是。您可以使用此选项-Wl,--disable-new-dtags来告诉链接程序使用行为,即RPATH。

是否可以告诉链接器的旧版本产生新的输出(即RUNPATH而不是RPATH)?

是。使用-Wl,--enable-new-dtags告诉链接器使用新的行为,即RUNPATH。

我使用验证了可执行文件,readelf并且这两个选项似乎可以控制ELF动态部分中的内容。我认为问题是由新版本默认值的更改引起的,尽管有趣的是,的手册页ld会建议仍然保持相同:

--enable-new-dtags
--disable-new-dtags
此链接器可以在ELF中创建新的动态标签。但是较旧的ELF系统可能无法理解它们。如果指定--enable-new-dtags,则将根据需要创建新的动态标签,而旧的动态标签将被省略。如果指定--disable-new-dtags,则不会创建新的动态标签。默认情况下,不创建新的动态标签。请注意,这些选项仅适用于ELF系统。