Sim*_*mon 29 linux linker shared rpath
我只是做了使用ld的一个基本的例子-rpath选项与$ORIGIN 这里(见一个工作版本第二反应).我试图创造一个例子main.run链接foo.so,进而链接bar.so,全部采用rpath和$ORIGIN.
运行时文件结构是:
- 项目/
- LIB /
- DIR /
- 子/
- bar.so
- 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
Run Code Online (Sandbox Code Playgroud)
哪个建好了.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
Run Code Online (Sandbox Code Playgroud)
如果foo.so使用不递归链接的另一个版本,这可以正常工作.(取消注释make.sh中的行,在下面的项目中进行测试).
但是,使用正常foo.so我在构建时遇到此错误main.run:
/ usr/bin/ld:警告:bar.so,lib/dir/foo.so需要,找不到(尝试使用-rpath或-rpath-link)
所以我的问题是:
$ORIGIN内foo.so解析project/lib/dir(这里foo.so是)或project/run(其中main.run(可执行文件链接吧))?project/lib/dir,这似乎是最好的方式(虽然我尝试假设两者).-rpath-link.您可以在此处下载该项目.它就像我能做到的一样简单.4个简短的来源和一个脚本.
提取后,只需./make.sh从内部运行project/.
注意:我正在使用-l:.这不应该改变任何东西,除了库被命名为foo.so而不是libfoo.so和lunk -l:foo.so而不是-lfoo.
好吧,我有一些工作.但我真的不明白为什么它有效.这对我来说就像是一个错误.
我跑strace -f -o /var/tmp/strace.out -- g++ ...了main.run编译.静态链接器实际上是尝试打开其文字名称看起来像"$ ORIGIN/lib/dir/sub/bar.so"的文件,其中包括20-30个其他内容.(换句话说,它正在寻找一个名为的实际目录$ORIGIN.认真.)
它似乎也在-rpath-link路径中搜索名称"lib/dir/sub/bar.so",而不仅仅是"bar.so".我不知道为什么.
无论如何,这是为我工作的main.run的链接:
g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../lib/dir' -Wl,-rpath-link,. -Llib/dir -l:foo.so
Run Code Online (Sandbox Code Playgroud)
它与您的相同,但-Wl,-rpath-link,.插入.
[附录]
好吧,我想我知道发生了什么.首先,静态链接器(GNU ld)根本不会在它链接的库中使用$ ORIGIN.
其次,使用-lbarvs. 时的行为-l:bar.so是非常不同的.
运行readelf -a上foo.so.在您的构建中,它显示依赖于"lib/dir/sub/bar.so".这就是将rpath-link设置为"."的原因.修复main.run的构建; 它会导致静态链接器搜索"." 对于它找到的"lib/dir/sub/bar.so".
如果你将bar.so重命名为libbar.so,并链接foo.so -lbar而不是使用-l:bar.so,则相同的readelf显示foo.so现在依赖于"libbar.so"(没有路径组件).使用那个foo.so,你可以使用main.run链接工作-Wl,-rpath-link,lib/dir/sub,正如你所知,如果你知道静态链接器根本不遵守$ ORIGIN.
顺便说一下,我没有看到-l:bar.soGNU ld手册中任何地方记录的语法.出于好奇,你是怎么想出来的?
假设它是一个受支持的功能,这看起来有点像一个bug(-l:bar.so创建一个依赖于lib/dir/sub/bar.so而不仅仅是bar.so).您可以通过将rpath-link设置为'.'来处理此错误.对于main.run,或者你可以用通常的方式重命名东西(libxxx.so).
小智 6
$ ORIGIN和rpath
ld.so理解rpath规范(DT_RPATH或DT_RUNPATH)中的字符串$ ORIGIN(或等效$ {ORIGIN}),表示包含应用程序可执行文件的目录.因此,位于somedir/app中的应用程序可以使用gcc -Wl,-rpath,'$ ORIGIN /../ lib'进行编译,以便在somedir/lib中找到关联的共享库,无论somedir位于目录中的哪个位置层次结构.这有助于创建不需要安装到特殊目录中的"交钥匙"应用程序,但可以将其解压缩到任何目录中,并仍然可以找到自己的共享库.
因此,在回答您的第一个问题时,只有一个值$ORIGIN:project/run.
因此,第二个问题的答案应该是使用以下命令链接foo.so:
g++ -shared -o lib/dir/foo.so obj/foo.o -Wl,-soname,foo.so -Wl,-rpath,'$ORIGIN/../lib/dir/sub' -Llib/dir/sub -l:bar.so
Run Code Online (Sandbox Code Playgroud)
首先,$ sign扩展存在问题,可能会导致问题.我正在从源代码构建Python,我这样做:
export LDFLAGS='-Wl,-rpath,\$${ORIGIN}/../lib -Wl,-rpath,\$${ORIGIN}/../usr/lib -Wl,--enable-new-dtags'
Run Code Online (Sandbox Code Playgroud)
在跑步之前make.这很好,它找到了第一级依赖项.处理此类宏扩展问题时,请注意单引号和双引号.
其次,如果您运行objdump -x二进制文件或库,您可以看到它实际包含的RPATH标头.当我跑的objdump -x path/to/python |grep RPATH时候告诉我这个.RPATH ${ORIGIN}/../lib:${ORIGIN}/../usr/lib`
I suggest that you check your binaries to see what is actually in the RPATH header. Unfortunately, I don't think that this will solve your problem. This is what I see when I run ldd path/to/python:
libpython2.7.so.1.0 => /data1/python27/bin/../lib/libpython2.7.so.1.0 (0x00002ad369d4f000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00002ad36a12f000)
libdl.so.2 => /lib/libdl.so.2 (0x00002ad36a34d000)
libutil.so.1 => /lib/libutil.so.1 (0x00002ad36a551000)
libm.so.6 => /lib/libm.so.6 (0x00002ad36a754000)
libc.so.6 => /lib/libc.so.6 (0x00002ad36a9d8000)
/lib64/ld-linux-x86-64.so.2 (0x00002ad369b2d000)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,第一级依赖项是由rpath第二级依赖项正确处理的,但是第二级依赖项(即libpython的依赖项)还原为系统库.是的,libpython在其二进制文件中具有完全相同的RPATH头.我在google搜索时发现了你的问题rpath recursive,试图解决我制作发行版独立包的问题.
后来添加
的rpath头只更改搜索库的第一个路径.如果在那里找不到它们,则加载器继续在正常位置搜索.ldd仅列出作为搜索结果找到的库的实际路径.当我将这些库复制到rpath目录中时,一切正常.基本上没有找到所有依赖项并复制它们的简洁方法,只是ldd -v path/to/python对该输出进行一些解析.
| 归档时间: |
|
| 查看次数: |
29823 次 |
| 最近记录: |