【问题标题】:Managing secondary dependencies of shared libraries管理共享库的二级依赖
【发布时间】:2021-12-08 05:43:55
【问题描述】:

我对共享库的次要依赖有疑问。 假设我们有以下依赖树:

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

也就是说,共享库 A 依赖于共享库 B 和 C,共享库 C 自身依赖于共享库 D。libC 的一个很好的例子是 GSL shared library,它依赖于 CBLAS。

为了制作一个自给自足且易于使用的包并避免安装的共享库的不同版本出现问题,我将库libBlibClibDlibA 打包在一起,并按照说明例如,在Drepper的article,“如何编写共享库”(2011)中,我添加了链接标志-Wl,-rpath,\$ORIGIN --enable-new-dtags来设置libA.soRUN_PATH,这样动态加载器就可以找到@的依赖项987654334@在对应的目录下,不需要设置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 搜索 transitive 依赖项;也就是说,RPATH 中的路径将被考虑用于动态加载的所有内容,甚至是依赖项的依赖项。

相比之下,ld 动态链接器RUNPATH 位置搜索传递依赖项(与RPATH 不同)。

另见:

【问题讨论】:

    标签: shared-libraries dependency-management dynamic-linking


    【解决方案1】:

    通过设置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 man page中解释:

           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.
    

    【讨论】:

    • 所以,你建议它重新编译 libC 的方式是正确的RUNPATH;对吗?
    • @AlQuemist 重新链接 libC,是的。
    • 问题是我可能没有拥有libC的源文件或正确编译的目标文件。在这种情况下,没有解决方案(除了静态链接);正确的? @Employed 俄罗斯人?
    • @AlQuemist 我已经更新了答案。
    • 太棒了!您能否也为您提到的几点添加一些参考资料?
    猜你喜欢
    • 2011-10-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 2015-11-23
    • 2012-04-05
    相关资源
    最近更新 更多