Linux 如何使用GCC/LD设置RPATH和运行路径?

Linux 如何使用GCC/LD设置RPATH和运行路径?,linux,gcc,shared-libraries,ld,dynamic-linking,Linux,Gcc,Shared Libraries,Ld,Dynamic Linking,我最近在升级系统后遇到了这个问题:使用GCC-Wl,-rpath=选项的工作方式与以前不同 我用它来设置一些共享库的搜索路径,这些库是在我的项目的子模块中构建的。当时我认为它比在系统范围内设置LD\u LIBRARY\u PATH要好(我不想每次打开电脑时都设置它)。一切都很顺利,这两种方法似乎是等价的 现在可以看出,-rpath的行为已经改变。它仍然适用于直接依赖的库,但不适用于那些通过-rpath=链接同一目录集中的其他库的库。导出LD\u LIBRARY\u路径仍像以前一样工作 我使用re

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

我用它来设置一些共享库的搜索路径,这些库是在我的项目的子模块中构建的。当时我认为它比在系统范围内设置
LD\u LIBRARY\u PATH
要好(我不想每次打开电脑时都设置它)。一切都很顺利,这两种方法似乎是等价的

现在可以看出,
-rpath
的行为已经改变。它仍然适用于直接依赖的库,但不适用于那些通过
-rpath=
链接同一目录集中的其他库的库。导出
LD\u LIBRARY\u路径
仍像以前一样工作

我使用
readelf
检查了编译的输出,发现有一点不同。在升级(Linux Mint 18.2和GCC 5.4)之前,动态部分有以下内容:

0x000000000000000f (RPATH)            Library rpath: [submod/lib]
升级(Linux Mint 19和GCC 7.3)后,行更改为:

0x000000000000001d (RUNPATH)            Library runpath: [submod/lib]
在本文中,有人建议将RPATH替换为RUNPATH(或者它至少服务于一个不同的用途,因为它具有较低的优先级),但它没有回答为什么会影响间接链接。库本身在
readelf
输出中既没有RPATH,也没有RUNPATH

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

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


编辑

这不是重复的——我的问题正好相反:我想要RPATH的行为。我找到了答案(感谢评论中的提示),我将在这里回答我的问题

有没有办法强迫旧的行为

对。您可以使用此选项
-Wl,--disable new dtags
告知新链接器使用旧行为,即RPATH

是否可以告诉旧版本的链接器生成新的输出(即运行路径而不是RPATH)

对。使用
-Wl,--enable new dtag
告诉旧链接器使用新行为,即运行路径

我用
readelf
验证了可执行文件,这两个选项似乎可以控制在ELF动态部分中编写的内容。我认为这个问题是由于新版本的默认设置发生了变化,尽管有趣的是,
ld
的手册页面会建议它仍然应该是相同的:

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

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

根据2013年1月Mike Frysinger的gentoo承诺:

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

由于运行路径和RPATH具有“未记录的行为差异”,因此未很好地接受此更改。。。 令人惊讶的是,这一变化现在应用于Debian stable

问题是使用运行路径会导致不可预知的问题。。。 但主要是起作用。来自维基百科:

ld动态链接器不会在DT_运行路径位置搜索 可传递依赖项,与DT_RPATH不同

可能的重复等。我相信新的做事方式是
-Wl,-rpath,
-Wl,--启用新的dtags
。它允许您使用
LD_LIBRARY_PATH
覆盖嵌入的路径,这也是Coreutil人员推荐的二进制文件。