gold
的人指出:
-L DIR, --library-path DIR
Add directory to search path
--rpath-link DIR
Add DIR to link time shared library search path
bfd
ld
的人听起来像-rpath-link
用于递归包含的sos。ld.lld
甚至没有将其列为参数。有人可以为我澄清这种情况吗?
最佳答案
这是一个针对GNU ld
的演示,它演示-L
和-rpath-link
之间的区别-
从长远来看,-rpath-link
和-rpath
之间的区别。
foo.c
#include <stdio.h>
void foo(void)
{
puts(__func__);
}
bar.c
#include <stdio.h>
void bar(void)
{
puts(__func__);
}
foobar.c
extern void foo(void);
extern void bar(void);
void foobar(void)
{
foo();
bar();
}
main.c
extern void foobar(void);
int main(void)
{
foobar();
return 0;
}
创建两个共享库
libfoo.so
和libbar.so
:$ gcc -c -Wall -fPIC foo.c bar.c
$ gcc -shared -o libfoo.so foo.o
$ gcc -shared -o libbar.so bar.o
创建第三个共享库
libfoobar.so
,它取决于前两个;$ gcc -c -Wall -fPIC foobar.c
$ gcc -shared -o libfoobar.so foobar.o -lfoo -lbar
/usr/bin/ld: cannot find -lfoo
/usr/bin/ld: cannot find -lbar
collect2: error: ld returned 1 exit status
哎呀。链接器不知道在哪里解析
-lfoo
或-lbar
。-L
选项可解决此问题。$ gcc -shared -o libfoobar.so foobar.o -L. -lfoo -lbar
-Ldir
选项告诉链接器dir
是要访问的目录之一搜索可解决给定的
-lname
选项的库。搜索首先按命令行顺序排列
-L
目录;然后搜索配置的默认目录,按其配置顺序。
现在制作一个依赖于
libfoobar.so
的程序:$ gcc -c -Wall main.c
$ gcc -o prog main.o -L. -lfoobar
/usr/bin/ld: warning: libfoo.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libbar.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
./libfoobar.so: undefined reference to `bar'
./libfoobar.so: undefined reference to `foo'
collect2: error: ld returned 1 exit status
再次糟糕。链接器检测
libfoobar.so
请求的动态依赖项但不能满足他们。让我们拒绝它的建议-
try using -rpath or -rpath-link
-看看我们可以使用
-L
和-l
做什么:$ gcc -o prog main.o -L. -lfoobar -lfoo -lbar
到现在为止还挺好。但:
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
在运行时,加载程序找不到
libfoobar.so
。那链接器的建议呢?使用
-rpath-link
,我们可以做到:$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath-link=$(pwd)
这种联系也成功了。
-rpath-link=dir
选项告诉链接器,当它遇到输入文件时,请求动态依赖项-像
libfoobar.so
-它应该搜索目录dir
到解决它们。因此,我们不需要使用
-lfoo -lbar
指定那些依赖项,也不需要甚至需要知道它们是什么。它们是已经写在
libfoobar.so
的动态部分:-$ readelf -d libfoobar.so
Dynamic section at offset 0xdf8 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoo.so]
0x0000000000000001 (NEEDED) Shared library: [libbar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
...
...
我们只需要知道一个目录,无论它们在哪里都可以找到它们。
但这是否给我们提供了可运行的
prog
?$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
不,和以前一样。那是因为
-rpath-link=dir
为链接器提供了信息加载程序需要解决
prog
的一些动态依赖关系在运行时-假设它在运行时仍然是正确的-但是不会将信息写入
prog
的动态部分。它仅使链接成功,而无需我们阐明所有递归动态
带有
-l
选项的链接的依赖性。在运行时,
libfoo.so
,libbar.so
-甚至是libfoobar.so
-可能不是它们现在所在的位置-
$(pwd)
-但加载程序可能能够找到它们通过其他方式:通过
ldconfig
缓存或设置LD_LIBRARY_PATH
环境变量的值,例如:$ export LD_LIBRARY_PATH=.; ./prog
foo
bar
rpath=dir
为链接器提供与rpath-link=dir
相同的信息并指示链接器将该信息烘焙到
输出文件。让我们尝试一下:
$ export LD_LIBRARY_PATH=
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath=$(pwd)
$ ./prog
foo
bar
都好。因为现在,
prog
包含以下信息:$(pwd)
是运行时搜索我们可以看到它所依赖的共享库的路径:
$ readelf -d prog
Dynamic section at offset 0xe08 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoobar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/imk/develop/so/scrap]
... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
将在
LD_LIBRARY_PATH
中列出的目录(如果已设置)之后,并且在系统默认设置之前-ldconfig
-ed目录以及/lib
和/usr/lib
,尝试该搜索路径。关于linker - `-rpath-link`和 `-L`有什么区别?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49138195/