假设我们有一个库libutils.so:
ldd libutils.so
...
libdependency.so
...
让我们进一步假设我们需要构建一个应用程序:
g++ appliation.cpp -lutils -o application
可以在上面的命令中省略-ldependency还是必须写:
g++ appliation.cpp -lutils -ldependency -o application
答案 0 :(得分:1)
我们可以在上面的命令中省略-ldependency
如果您控制libutils.so
本身的链接,可以。插图:
main.c
extern void foo(void);
int main(void)
{
foo();
return 0;
}
foo.c
extern void bar(void);
void foo(void)
{
bar();
}
bar.c
#include <stdio.h>
void bar(void)
{
puts(__func__);
}
我们将制作一个依赖于libfoo.so
的程序,该程序依赖于libbar.so
。
制作目标文件:
$ gcc -Wall -c -fPIC foo.c bar.c
gcc -Wall -c main.c
现在以“简洁”的方式链接libbar.so
:
$ gcc -shared -o libbar.so bar.o
下一个链接libfoo.so
如下:
$ gcc -shared -o libfoo.so foo.o -L. -lbar -Wl,-rpath=$(pwd)
-rpath linker option
的作用是:
-rpath = dir
将目录添加到运行时库搜索路径。在将ELF可执行文件与共享库链接时使用。 所有-rpath参数都被串联并传递到运行时链接程序,该链接程序使用它们在运行时定位共享对象。 在查找链接中显式包含的共享库所需的共享库时,也使用-rpath选项。 请参阅-rpath-link选项的描述。如果在链接ELF可执行文件时未使用-rpath, 如果定义了环境变量LD_RUN_PATH,将使用它的内容。
结果是:
$ objdump -x -j .dynamic libfoo.so | egrep '(RUNPATH|NEEDED)'
NEEDED libbar.so
RUNPATH /home/imk/develop/so/scrap
libfoo.so
的{{1}}部分中有一个NEEDED
条目,内容为
该库对.dynamic
具有运行时依赖性。同样,它有
那里的一个libbar.so
条目说可以在RUNPATH
中搜索运行时依赖项
这只是我进行链接的/home/imk/develop/so/scrap
:不一定要那样做,只要确实如此
链接器或加载器来查找pwd
时所在的目录。
当libbar.so
与其他链接在一起时,链接器可以读取此信息,
并由加载程序在运行时执行。所以最后我可以像这样链接libbar.so
:
prog
我不需要提及$ gcc -o prog main.o -L. -lfoo -Wl,-rpath=$(pwd)
,因为-lbar
本身为链接器提供了
libfoo.so
依赖于libfoo.so
的信息以及在何处查找。
由于我在libbar.so
的链接中也通过了-rpath=$(pwd)
,因此我们看到
将提供此信息
prog
到运行时加载器:$ objdump -x -j .dynamic prog | egrep '(RUNPATH|NEEDED)'
NEEDED libfoo.so
NEEDED libc.so.6
RUNPATH /home/imk/develop/so/scrap
需要prog
,可以寻找它
在libfoo.so
中。当加载程序找到/home/imk/develop/so/scrap
并加载它时,它将
从中发现:
libfoo.so
并依次查找并加载 NEEDED libbar.so
RUNPATH /home/imk/develop/so/scrap
,这将使其能够解析所有
施工中所指的符号。因此,libbar.so
可以立即运行:
prog
我没有没有在$ ./prog
bar
的链接中通过-rpath=$(pwd)
。但是,如果我没有:
prog
加载程序不知道在哪里找到$ gcc -o prog main.o -L. -lfoo
$ ./prog
./prog: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
。参见:
libfoo.so
然后我不得不求助于:
$ ldd prog
linux-vdso.so.1 (0x00007ffffcc35000)
libfoo.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4d1aff9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4d1b5ec000)
稍后
在ldd libutils.so的输出中是否存在libdependency.so是否足以在链接期间省略-ldependencny仍然有点不清楚
您需要问至少一个和最多两个关于$ export LD_LIBRARY_PATH=.
$ ldd prog
linux-vdso.so.1 (0x00007fff964dc000)
libfoo.so => ./libfoo.so (0x00007fc2a7f35000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc2a7b44000)
libbar.so => ./libbar.so (0x00007fc2a7942000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc2a8339000)
$ ./prog
bar
输出的问题:-
ldd utils.so
的输出是否全部报告ldd libutils.so
的名称? ?如果对 1 否,则libdependency.so
不包含有关其对libdutils.so
的依赖性的信息
并且您必须在任何进一步的链接中指定libdependency.so
。
如果对 1 为是,对 2 为否(即-lutils -ldependency
报告ldd libutils.so
),则libdependency.so => not found
具有
libutils.so
条目的NEEDED
条目,但不是一个libdependency.so
条目,链接器或
加载程序可以将该名称解析为任何实际文件。再次在这种情况下,如果链接RUNPATH
,则必须链接-lutils -ldependency
,以便链接器然后搜索可解析-lutils
的文件。至少,执行链接时,只要-ldependency
still 报告ldd libutils.so
,您就必须这样做。继续阅读...
如果对 1 是,对 2 是是,那么您可以在进一步的链接中放置libdependency.so => not found
,前提是
在您运行的相同环境中运行 -ldependency
需要进行警告,因为如果ldd libutils.so
解决了ldd libutils.so
,那么您所知道的一切
是libdependency.so
能够使用加载程序的搜索算法解析ldd
:-
libdependency.so
环境变量(在活动外壳中)列出目录
找到LD_LIBRARY_PATH
的地方,或者libdependency.so
提供了一个libutils.so
,其中找到了RUNPATH
,或者libdependency.so
中列出的目录之一(或其递归libdependency.so
扩展名)中找到/etc/ld.so.conf
,或者include
和libdependency.so
中找到/lib
如果/usr/lib
可以通过以下四种方式之一解析ldd
,则链接程序将能够
以相同的方式进行操作,只要在执行链接时该方法仍然成功。
现在回到我的示例和我的链接:
libdependency.so
此后,感谢$ gcc -shared -o libfoo.so foo.o -L. -lbar -Wl,-rpath=$(pwd)
。我可以像这样链接-rpath=$(pwd)
:
prog
而没有提及$ gcc -o prog main.o -L. -lfoo
,则它成功。现在,我链接-lbar
而不是 without
libfoo.so
:
-rpath
之后:
$ gcc -shared -o libfoo.so foo.o -L. -lbar
不再有$ objdump -x -j .dynamic libfoo.so | egrep '(RUNPATH|NEEDED)'
NEEDED libbar.so
,因此:
RUNPATH
因为加载程序也无法以任何其他方式解析$ ldd libfoo.so
linux-vdso.so.1 (0x00007ffda05e6000)
libbar.so => not found
。
现在,如果没有libbar.so
,我将无法链接prog
:
-lbar
但如果我这样做:
$ gcc -o prog main.o -L. -lfoo
/usr/bin/ld: warning: libbar.so, needed by ./libfoo.so, not found (try using -rpath or -rpath-link)
./libfoo.so: undefined reference to `bar'
然后:
$ export LD_LIBRARY_PATH=$(pwd)
$ ldd libfoo.so
linux-vdso.so.1 (0x00007ffe56d1e000)
libbar.so => /home/imk/develop/so/scrap/libbar.so (0x00007fd2456e8000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd2452f7000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd245aec000)
的依存关系libfoo.so
由加载程序使用libbar.so
并在
链接器也是如此:
LD_LIBRARY_PATH
如果我再次清除$ gcc -o prog main.o -L. -lfoo; echo Done
Done
:
LD_LIBRARY_PATH
回到失败。