【发布时间】:2021-12-08 05:43:55
【问题描述】:
我对共享库的次要依赖有疑问。 假设我们有以下依赖树:
libA.so
├─libB.so
└─libC.so
└─libD.so
也就是说,共享库 A 依赖于共享库 B 和 C,共享库 C 自身依赖于共享库 D。libC 的一个很好的例子是 GSL shared library,它依赖于 CBLAS。
为了制作一个自给自足且易于使用的包并避免安装的共享库的不同版本出现问题,我将库libB、libC 和libD 与libA 打包在一起,并按照说明例如,在Drepper的article,“如何编写共享库”(2011)中,我添加了链接标志-Wl,-rpath,\$ORIGIN --enable-new-dtags来设置libA.so的RUN_PATH,这样动态加载器就可以找到@的依赖项987654334@在对应的目录下,不需要设置LD_LIBRARY_PATH(有缺点)。
问题是在libA 中设置RUN_PATH 对辅助依赖项没有帮助,例如libD.so。
打开动态加载程序调试消息(通过设置LD_DEBUG)显示加载程序仅尝试在标准库位置找到libD.so,而不是在libA的位置(相反它用于查找libB 或libC)。
有没有办法解决这个问题?
确实,如果我有源代码或正确编译的静态库,我可以静态链接库 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