`-rpath-link` 和 `-L` 有什么区别? [英] What's the difference between `-rpath-link` and `-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();
}
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
,它依赖于前两个;
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.so
、libbar.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屋!