初识动静态库
静态库(.a)
程序在编译链接的时候把库的代码链接到可执行文件中。编译出的程序运行时不再需要静态库
生成和使用静态库
这里使用gcc
编译获得.o
链接文件,再用gnu
归档工具中的ar
指令配合-rc
选项(replace and create)封装库文件,最后借助makefile
简化文件目录的封装操作
使用第三方库时,还可以使用ar -tv
查看库中的目录列表
- t:列出静态库中的文件
- v:verbose 详细信息
使用静态库:
gcc
编译时使用第三方静态库必须包含以下选项:
-I
指定头文件目录-L
指定库路径-l
指定库名(不加空格),库名要把文件名
前面去掉lib
,后面去掉.a
才是真正的库名
否则编译器不知道头文件在哪,或者不知道链接哪个库
库搜索路径
库的搜索会按照一定的顺序
- 从左到右搜索-L指定的目录。
- 由环境变量指定的目录 (
LIBRARY_PATH
) - 由系统指定的目录
/usr/lib
/usr/local/lib
样例
测试程序(共5
个文件)
1 | /////////////add.h///////////////// |
然后我们编写makefile
文件
1 | lib = libmymath.a |
lib
作为makefile
中的变量,储存了库名
,默认的make
指令用于打包库文件,其依赖的add.o
和sub.o
会自动调用后两句编译产生。
make output
指令自动准备好目录并拷贝头文件和静态库
然后编译产生可执行程序
1 | gcc main.c -o mycmd -I ./lib/include -L ./lib/mymathlib -lmymath |
注意,使用第三方库时-I
,-L
和-l
缺一不可
但如果安装了第三方库时,即将库文件/库文件的软链接
拷贝至/lib64/
,将头文件/头文件的软链接
拷贝至/usr/inlude/
,使gcc
能够自动搜索到路径,则编译时只需用-l
指定库名
即可
动态库(.so)
动态库的作用是使程序在运行时才去链接动态库的代码,多个程序共享使用库的代码,从而使编译出的可执行文件更小,节省磁盘空间。使用动态库时,动态库也要加载到内存中
使用动态库底层的过程
- 使用动态库编译可执行程序:一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
- 动态链接: 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制(加载)到内存中,这个过程称为
动态链接
(dynamic linking) - 运行时调用动态库:调用来自动态库的函数时,实现函数功能的机器码将由动态库提供
生成和使用动态库
这里使用gcc
加-fPIC
(产生位置无关码position independent code)和-c
编译获得.o
链接文件,再用gcc
指令配合封装库文件,最后借助makefile
简化文件目录的封装操作
使用动态库:
gcc
编译时使用第三方静态库必须包含以下选项:
-I
指定头文件目录-L
指定库路径-l
指定库名(不加空格),库名要把文件名
前面去掉lib
,后面去掉.a
才是真正的库名
否则编译器不知道头文件在哪,或者不知道链接哪个库
特别的,当动静态库同时存在时,gcc
默认优先使用动态库,除非加-static
参数
但是,仅仅编译出可执行文件还不够,因为可执行文件还找不到动态库,所以我们还得告诉系统中的加载器
,我们的动态库在哪,所以我们要把动态库安装到/lib64/
,拷贝文件或建立软连接都可以(需要sudo
或root
权限)
亦或者修改环境变量LD_LIBRARY_PATH
示例
文件代码同上,这里展示makefile
文件
1 | lib = mymathlib.a |
库搜索路径
库的搜索会按照一定的顺序
- 从左到右搜索-L指定的目录。
- 由环境变量指定的目录 (
LIBRARY_PATH
) - 由系统指定的目录
/usr/lib
/usr/local/lib
小结
库文件命名规则libxxx.a
/libxxx.so
库文件名称->库名:去掉前缀lib
,去掉后缀.so
/.a
使用动态库的可执行程序需要安装动态库
或修改环境变量LD_LIBRARY_PATH