36. 静态库和动态库¶
36.1. 编译静态库¶
下载以下文件到任意目录
make
生成的lib_mylib.a是静态链接库,生成的driver是静态链接的目标文件。
使用静态库的方法: 把lib_mylib.a和lib_mylib.h拷贝到任意主机,在源文件中include lib_mylib.h即可使用fun函数 如driver.c:
#include "lib_mylib.h"
void main()
{
fun();
}
编译命令
gcc -o driver driver.c -L. -l_mylib
-L. 代表lib_mylib.a在当前路径,-l_mylib达标在-L指定的目录下查找lib_mylib.a
36.2. 编译动态库¶
下载以下文件到任意目录
make
export LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
./app
生成的liblowcase.so是动态链接库。 生成的app是动态链接文件。使用ldd可以看到app有应用当前的路径。
[me@centos share_lib]$ ldd app
linux-vdso.so.1 => (0x0000ffff8ef60000)
liblowcase.so => /home/me/gsrc/share_lib/liblowcase.so (0x0000ffff8ef20000)
libc.so.6 => /lib64/libc.so.6 (0x0000ffff8ed70000)
/lib/ld-linux-aarch64.so.1 (0x0000ffff8ef70000)
使用动态链接库的方法,把liblowcase.so放到目录之后。编译指定路径和库。 设置环境变量,默认情况下,ld程序不回去搜索../code/路径,所以需要手动指定
gcc call_dynamic.c -L ../code/ -llowcase -o call
export LD_LIBRARY_PATH=../code/
./call
36.3. gcc 指定库文件和头文件¶
“-I”(大写i),“-L”(大写l),“-l”(小写l)的区别 我们用gcc编译程序时,可能会用到“-I”(大写i),“-L”(大写l),“-l”(小写l)等参数,下面做个记录:
例:
gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld
-I | /home/hello/include表示将/home/hello/include目录作为第一个寻找头文件的目录, 寻找的顺序是:/home/hello/include–>/usr/include–>/usr/local/include |
-L | /home/hello/lib表示将/home/hello/lib目录作为第一个寻找库文件的目录, 寻找的顺序是:/home/hello/lib–>/lib–>/usr/lib–>/usr/local/lib |
-lworld | 表示在上面的lib的路径中寻找libworld.so动态库文件 (如果gcc编译选项中加入了“-static”表示寻找libworld.a静态库文件) |
- LD_PRELOAD
- 用法LD_PRELOAD=/usr/local/zlib/lib/libz.so.1.2.7 ./lzbench -ezlib silesia.tar 在加载系统的libz之前先加载自定义的so
- LD_LIBRARY_PATH
- 添加程序执行时的搜索路径。 用法export LD_LIBRARY_PATH=/usr/local/zlib/lib/ 程序执行时从这里搜索动态库
gcc -l参数和-L参数
-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢? 就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。
36.4. 如何让gcc在生成动态链接库的时候静态链接glibc¶
$ gcc -fPIC -shared reload.c -o reload.so -nostdlib
$ ldd reload.so
statically linked