使用 -static
编译出现以下警告
libcurl.a(netrc.c.o): In function `Curl_parsenetrc':
netrc.c:(.text.Curl_parsenetrc+0x23e): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
libplayer.a(stream_wfd.c.o): In function `wfd_stream_open':
stream_wfd.c:(.text.wfd_stream_open+0x5fe): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
glibc uses libnss to support a number of different providers for address resolution services. Unfortunately, you cannot statically link libnss, as exactly what providers it loads depends on the local system’s configuration.
相关功能不能正常工作,需要使用 动态编译
解决此问题或者更换编译工具链为 uclibc
、 musl-gcc
动态
动态库后缀为 .so
,是 Shared Object
的缩写,程序运行时的动态链接,多个进程可以链接同一个共享库。动态库在程序编译时并不会被连接到目标代码中,程序运行时被载入,因此在程序运行时还需要动态库存在。
编译生成动态库
gcc -fPIC -shared -o libmax.so max.c
-fPIC
为编译器选项,是Position Independent Code
的缩写,表示要生成位置无关的代码,这是动态库需要的特性-shared
为链接器选项,告诉 gcc 生成动态库而不是可执行文件
使用动态连接库
gcc test.c -L. -lmax
- 生成可执行文件
a.out
-L.
表示搜索要链接的库文件时包含当前路径-lmax
表示要链接libmax.so
,如果同一目录下同时存在同名的动态库和静态库,比如libmax.so
和libmax.a
都在当前路径下,则gcc
会优先链接动态库
运行
$ ./a.out
./a.out: error while loading shared libraries: libmax.so: cannot open shared object file: No such file or directory
找不到 libmax.so
,原来 Linux
是通过 /etc/ld.so.cache
文件搜寻要链接的动态库的。而 /etc/ld.so.cache
是 ldconfig
程序读取 /etc/ld.so.conf
文件生成的。( /etc/ld.so.conf
中并不必包含 /lib
和 /usr/lib
, ldconfig
程序会自动搜索这两个目录)
如果我们把 libmax.so
所在的路径添加到 /etc/ld.so.conf
中,再以 root
权限运行 ldconfig
程序,更新 /etc/ld.so.cache
, a.out
运行时,就可以找到 libmax.so
。
还有另一种简单的方法,就是为 a.out
指定 LD_LIBRARY_PATH
LD_LIBRARY_PATH=. ./a.out
LD_LIBRARY_PATH
是寻找链接的动态库路径
对于
elf 格式的可执行程序
,是由ld-linux.so*
来完成的,它先后搜索elf 文件
的DT_RPATH
段,环境变量LD_LIBRARY_PATH
,/etc/ld.so.cache
文件列表,/lib/
,/usr/lib
目录,找到库文件后将其载入内存
静态
静态库后缀为 .a
,静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
LDFLAGS += -static
工具
ldd
使用 ldd
查看可执行程序依赖那些动态库或着动态库依赖于那些动态库
$ ldd /lib/libxtables.so.10
linux-vdso.so.1 => (0x00007ffdf51f5000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fb9cda56000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb9cd676000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb9cde67000)
nm
使用 nm
工具,查看静态库和动态库中有那些函数名
$ nm /lib/libxtables.so.10
nm
列出的符号有很多, 常见的有三种:
T 类
:是在库中定义的函数,用 T 表示,这是最常见的U 类
:是在库中被调用,但并没有在库中定义(表明需要其他库支持),用 U 表示W 类
:是所谓的弱态
符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用 W 表示
ar
使用 ar
工具,可以生成静态库,同时可以查看静态库中包含那些 .o
文件,即有那些源文件构成
$ ar -t libpng.a
pngerror.c.o
pngmem.c.o
pngrio.c.o
pngrutil.c.o
pngtrans.c.o
png.c.o
pngget.c.o
pngread.c.o
pngpread.c.o
pngrtran.c.o
pngset.c.o
如何查看动态库和静态库是 32 位,还是 64 位下的库
file .so
objdump -x .a
混合链接
当 ld
使用了选项 -static
时会导致所有的库使用静态链接,因此当使用混合链接是一定不能使用 -static
,只能通过 -Wl,-Bstatic -llibname
或 -Wl,-Bdynamic -llibname
来指定链接方式
LIBRARY_PATH
环境变量:指定程序静态链接库文件搜索路径LD_LIBRARY_PATH
环境变量:指定程序动态链接库文件搜索路径