ld:在共享库中使用-rpath,$ ORIGIN(递归)
|
我只是在此处使用ld \的
-rpath
选项和$ORIGIN
做了一个基本示例(有关工作版本,请参见第二个响应)。我正在尝试创建一个示例,其中main.run
链接到foo.so
,然后依次链接到bar.so
,都使用rpath
和$ORIGIN
。
运行时文件结构为:
项目/
lib /
目录/
子/
栏
foo.so
跑/
main.run(无法构建)
我正在使用以下命令构建foo.so:
g++ -c -o obj/foo.o src/foo.cpp -fPIC
g++ -shared -o lib/dir/foo.so obj/foo.o -Wl,-soname,foo.so -Wl,-rpath,\'$ORIGIN/sub\' -Llib/dir/sub -l:bar.so
哪个很好。 ldd lib/dir/foo.so
甚至可以找到bar.so
。
但是,当我尝试将main.run
链接到foo.so
时,foo.so
找不到bar.so。
我正在使用以下命令构建main.so:
g++ -c -o obj/main.o src/main.cpp
g++ -o run/main.run obj/main.o -Wl,-rpath,\'$ORIGIN/../lib/dir\' -Llib/dir -l:foo.so
如果使用的是其他版本的foo.so
,而该版本没有递归链接,则效果很好。 (在下面的项目中的make.sh中取消注释行以进行测试)。
但是,使用普通的foo.so
在构建main.run
时出现此错误:
/ usr / bin / ld:警告:找不到lib / dir / foo.so所需的bar.so(尝试使用-rpath或-rpath-link)
所以我的问题是:
foo.so中的$ORIGIN
解析为project/lib/dir
(where3是)或project/run
(where2ѭ(链接它的可执行文件))?
ldd似乎表明它是project/lib/dir
,这似乎是最好的方法(尽管我尝试同时假设两者)。
我如何使它们链接(同时保持可重定位性)-最好不使用-rpath-link
。
您可以在此处下载项目。这就是我所能做到的。 4个简短的资源和一个脚本。
提取后,只需在project/
之内运行./make.sh
。
注意:我使用的是-l:
。除了将库命名为foo.so
(而不是ѭ28)以及用-l:foo.so
(而不是ѭ30)来命名外,这没有什么改变。
没有找到相关结果
已邀请:
6 个回复
薄响
的实际目录。 它似乎也在-rpath-link路径中搜索名称\“ lib / dir / sub / bar.so \”,而不仅仅是\“ bar.so \”。我不知道为什么。 无论如何,这是对我有用的main.run链接:
与您的相同,但插入了
。 [附录] 好吧,我想我知道发生了什么事。首先,静态链接器(GNU ld)根本不遵守其链接所针对的库中的$ ORIGIN。 其次,当您使用
与
时的行为有很大不同。 在
上运行
。在您的构建中,它显示对\“ lib / dir / sub / bar.so \”的依赖。这就是为什么将rpath-link设置为\“。\”会修复main.run的构建;它使静态链接器在\“。\”中搜索找到的\“ lib / dir / sub / bar.so \”。 如果将bar.so重命名为libbar.so,并链接foo.so以使用
而不是
,则相同的readelf显示foo.so现在依赖于\“ libbar.so \”(不包含路径组件)。有了foo.so,您可以使用
来使main.run链接正常工作,就像您知道静态链接器根本不遵守$ ORIGIN一样,这是您所期望的。 顺便说一下,我在GNU ld手册的任何地方都没有看到
语法。出于好奇,您是怎么想出来的? 假设它是受支持的功能,则看起来有点像个错误(-l:bar.so创建了对lib / dir / sub / bar.so的依赖,而不仅仅是bar.so)。您可以通过将main.run的rpath-link设置为\'。\'来解决此错误,也可以按通常的方式(libxxx.so)重命名内容。
澜悍景哭苟
。 因此,第二个问题的答案应该是使用以下命令链接
:
际恃啸称桅
在运行
之前。效果很好,并且找到了第一级依赖项。处理此类宏扩展问题时,请小心单引号和双引号。 其次,如果您在二进制文件或库上运行“ 49”,则可以看到它实际包含的RPATH标头。当我运行
时,它显示了此信息。
RPATH$ {ORIGIN} /../ lib:$ {ORIGIN} /../ usr / lib` 我建议您检查二进制文件以查看RPATH标头中的实际内容。不幸的是,我认为这不会解决您的问题。这是我在运行
时看到的内容:
如您所见,第一级依赖关系由ѭ5正确处理,但是第二级依赖关系(即libpython的依赖关系)恢复为系统库。是的,libpython在其二进制文件中具有完全相同的RPATH标头。我在搜寻
时发现了您的问题,以尝试解决制作发行独立软件包的问题。 以后添加
标头仅更改搜索库的第一条路径。如果未在此处找到它们,则加载程序会继续在正常位置搜索。
仅列出通过搜索找到的库的实际路径。当我将这些库复制到
目录时,一切正常。基本上,没有一种整洁的方法来找到所有依赖项并复制它们,只有
和对该输出的一些解析。
量华
。例如:
不会在使用
指定的路径或从子依赖项的RPATH检索的路径内扩展
。在上面的示例中,
取决于
;在链接
时,
会尝试使用libmylib2.so中嵌入的文字/未扩展字符串
查找
。
在运行时会显示,但
在运行时不会显示。 它还不会使用用with73指定的路径来找到子依赖库librar(y | ies)。
瞥同忙接
的附加
,因为
根本不理解
。 至于你的问题。
仅在运行时有效,并且每个图书馆。因此,不同的共享库具有不同的“ 1”。 恐怕最好的方法是添加
,这不会影响您的可移植性,因为它们是相对的,并且不会出现在最终的可执行文件中,正如我在
版本中所展示的那样。 另外,这是我对整个链接内容的理解。希望对您有所帮助。
版萍层分
。依赖项中的rpath将添加到搜索中。 即
找到
,然后读取
中的RPATH,从而找到
这是我的堆栈溢出问题: Binutils次要依赖关系变更 这是我对各种发行版(在Docker容器内部)的调查,以测试各种binutils版本 https://github.com/Mizux/SecondaryDependency 注意:看看travis-CI日志...