使用 -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 linkingglibc 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 .soobjdump -x .a
混合链接
当 ld 使用了选项 -static 时会导致所有的库使用静态链接,因此当使用混合链接是一定不能使用 -static,只能通过 -Wl,-Bstatic -llibname 或 -Wl,-Bdynamic -llibname 来指定链接方式
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径