我在构建可执行文件时在命令行上链接共享库。在该可执行文件上运行ldd
不会显示链接的共享库。
查看了链接器的某些输出之后,我什至尝试添加-Wl,--no-as-needed
选项,但这也没有帮助。
foo.c:
#include <stdio.h>
void foo () {
printf ("Hello world\n");
}
main.c:
#include <stdio.h>
int main () {
printf ("In main \n");
foo ();
}
这是我用来编译和链接的命令:
$ gcc -Wl,--no-as-needed main.c -o main -L./ -lfoo
/bin/ld: cannot find -lfoo
collect2: error: ld returned 1 exit status
$ gcc -c foo.c -shared -Wl,-soname,libfoo.so -o libfoo.so
$ ls -l libfoo.so
-rw-r--r-- 1 apple eng 1488 Jun 4 04:44 libfoo.so
$ gcc -Wl,--no-as-needed main.c -o main -L./ -lfoo
$ ldd main
linux-vdso.so.1 => (0x00007fffbdd6c000)
libc.so.6 => /lib64/libc.so.6 (0x00007f6367e23000)
/lib64/ld-linux-x86-64.so.2 (0x00005556e268a000)
libfoo.so
不在上方显示。
$ objdump -x main | grep NEEDED
NEEDED libc.so.6
为什么libfoo.so
不能显示为NEEDED
?
答案 0 :(得分:1)
此命令不会不生成共享库:
gcc -c foo.c -shared -Wl,-soname,libfoo.so -o libfoo.so
它会生成一个目标文件libfoo.so
,该文件以后会与您的代码进行静态链接。证明:删除lib
文件,该程序仍将运行。
解决方案:
分别编译目标文件,然后将其转换为共享库。您必须通过设置LD_LIBRARY_PATH
来告诉加载程序在哪里搜索共享库:
gcc -c foo.c
gcc foo.o -shared -o libfoo.so
gcc main.c -o main -L./ -lfoo
export LD_LIBRARY_PATH=`pwd`
ldd ./main
# linux-vdso.so.1 (0x00007ffe0f7cb000)
# libfoo.so => /home/---/tmp/libfoo.so (0x00007f9bab6ec000)
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9bab2fb000)
# /lib64/ld-linux-x86-64.so.2 (0x00007f9babaf0000)
答案 1 :(得分:1)
使用gcc选项-c
告诉它仅从foo.c
创建对象,因此,从此gcc命令获得的唯一产品是目标文件。其后缀为.so
的事实仅是因为您使用-o
选项强加了它。如果在没有-o
的情况下运行此命令,则会看到输出仅为foo.o
-目标文件。
如果您从gcc命令中省略了-c
,则会得到您想要的共享对象。
在输出文件上运行file
会显示出差异(请注意,我没有使用-o
设置输出名称,而没有让gcc使用其默认名称):
使用-c
:
> gcc -c foo.c -shared
> file foo.o
foo.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
没有-c
:
> gcc foo.c -shared
> file a.out
a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=a63581bfc45f845c501ffb6635, not stripped
^^^
|||