概念
库文件是一组预先编译好的函数、类或数据的集合,以文件的形式存在,用于被其他程序调用,通俗点讲就是把一堆写好的函数,变量,代码全部编译打包成一个二进制文件,不给别人看源码,只给别人用
作用
1.提高开发效率:避免重复编写相同功能的代码,减少开发时间
2.便于代码维护:集中管理功能模块,修改和升级库时,只需更新库文件,无需修改使用库的程序
3.保护代码隐私:可以将核心代码封装在库中,只提供接口供外部使用,隐藏实现细节
在Linux下库分为两种形式:静态库和动态库
静态库
定义
在程序编译链接阶段,把代码完整的复制到最终的可执行文件中,成为可执行文件的一部分,编译完成后,静态库跟可执行文件绑定,运行时无需额外依赖
特点
1.可执行文件独立运行,不依赖外部库文件
2.静态库会让可执行文件体积较大,但是效率比较高
3.如果静态库更新,需要重新编译链接程序,所以有点麻烦
文件格式(每个平台不同):
windows平台下为.lib,Linux平台下为.a,Mac平台下为.a
静态库制作步骤
1.准备源文件
2.编译生成目标文件.o
gcc -c test.c -o test.o-c:只编译,不链接
3.用ar工具打包成静态库.a
ar crs libmylib.a test.o参数说明:
r:插入模块到库中c:创建库s:生成索引
静态库命名规范:libxxx.a
4.编译主程序并链接静态库生成可执行文件
gcc test.o -lmylib -L. -o test参数说明:
- -l:指定要链接的库名
- -L.:在当前目录找库,.代表当前目录
动态库
定义
动态库也叫共享库,是在程序运行时才被加载到内存中,可以被多个可执行文件使用,提供函数数据等资源
特点
1.可执行文件运行时,需依赖系统中存在的动态库
2.可执行文件体积小,有效节省磁盘和内存空间
3.更新灵活,只要接口不变,无需重新编译依赖他的可执行文件
动态库文件格式:windows平台下为.dll;Linux平台下为.so;Mac平台下为.dylib
动态库制作步骤
1.准备源文件
2.生成位置无关代码:使用编译器编译源文件时,添加相关选项(如GCC的-fPIC选项)生成位置无关代码(PIC)的目标文件
gcc -c -fPIC test.c -o test.o-fPIC:生成位置无关代码,动态库必须加
3.链接生成动态库.so
gcc -shared test.o -o libmylib.so-share:生成动态库
4.编译时通过-L指定路径,-l指定库名生成可执行文件
gcc test.c -lmylib -L. -o test动态库的使用
如果完成以上步骤后直接运行会报错,提示找不到动态库,因为动态库不像静态库直接与执行文件绑定,需要给可执行文件指条明路去找动态库,所以需要配置环境变量,有以下三种方法:
1.临时配置环境变量
export LD_LIBRARY_PATH=. ./main2.把.so放到系统库目录
sudo cp libmylib.so /usr/lib/3.配置/etc/ld.so.conf刷新缓存(不推荐,比较麻烦,要编辑文件,容易出错)
静态库VS动态库核心区别
| 对比项 | 静态库 .a | 动态库 .so |
|---|---|---|
| 后缀 | .a | .so |
| 链接时机 | 编译链接时打包进程序 | 运行时加载库 |
| 代码拷贝 | 复制一份到可执行文件 | 不复制,共享调用 |
| 程序体积 | 大 | 小 |
| 运行依赖 | 不依赖外部库,可独立运行 | 必须有对应 .so 否则跑不起来 |
| 升级更新 | 升级库要重新编译程序 | 直接替换 .so 即可,不用重新编译 |
| 内存占用 | 每个程序独占一份代码 | 内存中只存一份,多程序共享 |
| 制作参数 | ar rcs | gcc -fPIC -shared |
| 适用场景 | 小型程序、嵌入式、不想依赖外部文件 | 大型项目、系统库、频繁更新 |
总结
- 静态库:打包进程序,独立运行,体积大
- 动态库:运行加载,共享省内存,体积小
库文件相关问题
为什么动态库必须加 -fPIC?
动态库要加载到内存任意地址,必须生成位置无关代码,不加会报错重定位。
静态库和动态库优先用哪个?
- Linux 默认优先链接动态库
- 想强制用静态库:
gcc main.c -o main -static -L. -lmylib头文件和库的关系
- 头文件
.h:告诉编译器函数声明 - 库
.a/.so:提供函数实现编译缺一不可。
ar 命令作用
用来打包静态库,把多个 .o 合并成一个 .a
静态库能不能多个程序共享?
不能。每个程序编译时都拷贝一份代码,内存多份冗余。
动态库好处
- 可执行程序体积小
- 内存共享,节省内存
- 库升级不用重新编译项目
静态库好处
- 部署简单,不用带库文件
- 嵌入式常用,环境依赖少
- 运行不担心库路径问题