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.solibbar.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.solibbar.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/

10-11 18:19