管理共享库的次要依赖项



我对共享库的二级依赖有一个问题。假设我们有如下的依赖树:

libA.so
├─libB.so
└─libC.so
└─libD.so

也就是说,共享库a依赖于共享库B和C,而共享库C依赖于共享库d。libC的一个很好的例子是GSL共享库,它依赖于CBLAS。

做一个自给自足的易于使用的不同版本的安装包,避免问题共享库,我包库libBlibClibDlibA,解释,例如,在Drepper的文章,"如何写共享库"(2011),我添加链接标志-Wl,-rpath,$ORIGIN --enable-new-dtags设置RUN_PATHlibA.so,以便动态加载程序可以找到libA的依赖性在相应的目录,无需设置LD_LIBRARY_PATH(缺点)。

问题是在libA中设置RUN_PATH对次要依赖项(如libD.so)没有帮助。打开动态加载器调试消息(通过设置LD_DEBUG)显示加载器只尝试在标准库位置查找libD.so,而不是在libA的位置(与查找libBlibC相反)。

有办法克服这个问题吗?

实际上,如果我有源代码或正确编译的静态库,我可以静态地链接库C和D。但是有没有更好的办法呢?

解决方案

:
Employed Russian所述,解决方案是设置RPATH而不是RUNPATH。对于最新版本的GCC,应该使用以下链接标志:

-Wl,--disable-new-dtags,-rpath,$ORIGIN

RPATH查找传递依赖项;也就是说,RPATH中的路径将被考虑为动态加载的所有内容,甚至是依赖项的依赖项。

相比之下,ld动态链接器不搜索RUNPATH位置的传递依赖关系(不像RPATH)。

参见:

  • 维基百科:https://en.wikipedia.org/wiki/Rpath The_role_of_GNU_ld
  • 问题:如何在GCC/LD中设置RPATH和RUNPATH ?

通过设置DT_RUNPATH,您告诉加载器每个二进制文件都与其所有依赖项相链接。

但是对于libC.so来说不是真的——它(显然)没有自己的DT_RUNPATH

我可以静态链接库C和D,…但是有没有更好的办法呢?

是:链接libC.so与正确的DT_RUNPATH(如果libC.solibD.so在同一目录下,那么-Wl,-rpath,$ORIGIN也将适用于libC.so)。

更新:

问题是我可能没有libC的源文件或正确编译的目标文件

在这种情况下,你应该使用RPATH而不是RUNPATH。与后者不同,前者适用于对象本身以及该对象的所有依赖项。

换句话说,在这种情况下使用--enable-new-dtags是错误的——您需要的是相反的。

在这种情况下,没有解决方案(除了静态链接);正确吗?

另一个解决方案(除了使用RPATH)是在环境中设置LD_LIBRARY_PATH

更新2:

RPATHRUNPATH的差异

差异在ld.so手册页中解释:

If a shared object dependency does not contain a slash, then it
is searched for in the following order:
o  Using the directories specified in the DT_RPATH dynamic
section attribute of the binary if present and DT_RUNPATH
attribute does not exist.  Use of DT_RPATH is deprecated.
...
o  Using the directories specified in the DT_RUNPATH dynamic
section attribute of the binary if present.  Such directories
are searched only to find those objects required by DT_NEEDED
(direct dependencies) entries and do not apply to those
objects' children, which must themselves have their own
DT_RUNPATH entries.  This is unlike DT_RPATH, which is applied
to searches for all children in the dependency tree.

最新更新