`-rpath-link` 和 `-L` 有什么区别? [英] What's the difference between `-rpath-link` and `-L`?

查看:31
本文介绍了`-rpath-link` 和 `-L` 有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 的 man 听起来有点像 -rpath-link 用于递归包含的 sos.

The man for bfd ld makes it sort of sound like -rpath-link is used for recursively included sos.

ld.lld 甚至没有将其列为参数.

ld.lld doesn't even list it as an argument.

有人可以帮我澄清一下这种情况吗?

Could somebody clarify this situation for me?

推荐答案

这里有一个demo,对于GNU ld-L的区别-rpath-link -为了更好地衡量,-rpath-link-rpath 之间的区别.

Here is a demo, for GNU ld, of the difference between -L and -rpath-link - and for good measure, the difference between -rpath-link and -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();
}

ma​​in.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,它依赖于前两个;

Make a third shared library, libfoobar.so that depends on the first two;

$ 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.

Oops. The linker doesn't know where to look to resolve -lfoo or -lbar.

-L 选项可以解决这个问题.

The -L option fixes that.

$ gcc -shared -o libfoobar.so foobar.o -L. -lfoo -lbar

-Ldir 选项告诉链接器 dir 是要访问的目录之一搜索能够解析它给出的 -lname 选项的库.它搜索-L 目录首先,按命令行顺序;然后它搜索它的配置的默认目录,按照它们的配置顺序.

The -Ldir option tells the linker that dir is one of the directories to search for libraries that resolve the -lname options it is given. It searches the -L directories first, in their commandline order; then it searches its configured default directories, in their configured order.

现在制作一个依赖于libfoobar.so的程序:

Now make a program that depends on 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 请求的动态依赖但不能满足他们.让我们拒绝它的建议 - 尝试使用 -rpath 或 -rpath-link -看看我们可以用 -L-l 做什么:

Oops again. The linker detects the dynamic dependencies requested by libfoobar.so but can't satisfy them. Let's resist its advice - try using -rpath or -rpath-link - for a bit and see what we can do with -L and -l:

$ gcc -o prog main.o -L. -lfoobar -lfoo -lbar

到目前为止一切顺利.但是:

So far so good. But:

$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory

在运行时,加载器找不到libfoobar.so.

at runtime, the loader can't find libfoobar.so.

那么链接器的建议呢?使用-rpath-link,我们可以做到:

What about the linker's advice then? With -rpath-link, we can do:

$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath-link=$(pwd)

并且该链接也成功了.($(pwd) 表示Print Working Directory"并且只是复制"当前路径.)

and that linkage also succeeds. ($(pwd) means "Print Working Directory" and just "copies" the current path.)

-rpath-link=dir 选项告诉链接器,当它遇到一个输入文件时,请求动态依赖 - 比如 libfoobar.so - 它应该搜索目录 dir 到解决它们.所以我们不需要-lfoo -lbar 来指定那些依赖甚至需要知道它们是什么.它们是已经写在libfoobar.so 的动态部分:-

The -rpath-link=dir option tells the linker that when it encounters an input file that requests dynamic dependencies - like libfoobar.so - it should search directory dir to resolve them. So we don't need to specify those dependencies with -lfoo -lbar and don't even need to know what they are. What they are is information already written in the dynamic section of 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]
 ...
 ...

我们只需要知道可以找到它们的目录,无论它们是什么.

We just need to know a directory where they can be found, whatever they are.

但这会给我们一个可运行的prog吗?

But does that give us a runnable 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 选项的链接的依赖关系.

No. Same as story as before. That's because -rpath-link=dir gives the linker the information that the loader would need to resolve some of the dynamic dependencies of prog at runtime - assuming it remained true at runtime - but it doesn't write that information into the dynamic section of prog. It just lets the linkage succeed, without our needing to spell out all the recursive dynamic dependencies of the linkage with -l options.

在运行时,libfoo.solibbar.so - 实际上是 libfoobar.so -很可能不在它们现在所在的位置 - $(pwd) - 但加载器可能能够找到它们通过其他方式:通过 ldconfig 缓存或设置LD_LIBRARY_PATH 环境变量,例如:

At runtime, libfoo.so, libbar.so - and indeed libfoobar.so - might well not be where they are now - $(pwd) - but the loader might be able to locate them by other means: through the ldconfig cache or a setting of the LD_LIBRARY_PATH environment variable, e.g:

$ export LD_LIBRARY_PATH=.; ./prog
foo
bar

rpath=dir 为链接器提供与 rpath-link=dir 相同的信息and 指示链接器将该信息烘焙到输出文件.让我们试试吧:

rpath=dir provides the linker with the same information as rpath-link=dir and instructs the linker to bake that information into the dynamic section of the output file. Let's try that:

$ export LD_LIBRARY_PATH=
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath=$(pwd)
$ ./prog
foo
bar

一切都好.因为现在, prog 包含 $(pwd) 是运行时搜索的信息如我们所见,它所依赖的共享库的路径:

All good. Because now, prog contains the information that $(pwd) is a runtime search path for shared libraries that it depends on, as we can see:

$ 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.

That search path will be tried after the directories listed in LD_LIBRARY_PATH, if any are set, and before the system defaults - the ldconfig-ed directories, plus /lib and /usr/lib.

这篇关于`-rpath-link` 和 `-L` 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆