概念
1、静态库与动态库的区别
根据代码被载入的时间不同,linux下库分为两种:静态库和动态库(也叫共享库)。静态库,在编译时,已经被载入到可执行程序中,静态库成为可执行文件的一部分,因此可可执行程序文件比较大。
动态库,可执行程序在执行时,才被引用到内存,因此可执行程序文件小。当多个程序调用同个动态库时,内存中只有一个动态库实例。
2、库命名规范
静态库:以.a 为后缀,名字一般是libxxx.a,其中xxx 是库的名字。动态库:以.so为后缀,名字一般是libxxx.so.major.minor 其中xxx是库名,majar 是主版本号,minor是副版本号
3、通过ldd查看程序所依赖的共享库
如:查看vim所依赖的共享库:ldd /usr/bin/vim4、程序查找动态库的路径
/lib 和 /usr/lib 及 /etc/ld.so.conf配置的路径下。生成静态库
静态库是一堆object对象目标文件的集合,使用 ar 命令可将 .o 文件打包成 .a 静态库。
假设 g++ 已经生成 a.o, b.o, c.o, 使用下面命令可生成 libmylib.a
# ar rcs libmylib.a a.o b.o c.o
ar 命令类似 tar,起打包作用。
选项 r 将后面的文件列表添加到文件包,文件包不存在就创建,存在就替换。
选项 s 是专用于生成静态库,表示为静态库创建索引,这个索引被链接器使用。
生成动态库
动态库由 g++ 直接生成。
假设有 a.cpp, b.cpp 两个代码文件,通过下面的命令可生成 libmylib.so
# g++ a.cpp b.cpp -o libmylib.so -shared -fPIC
或着假设 g++ 已经生成 a.o, b.o, 通过下面的命令可生成 libmylib.so
# g++ a.o b.o -o libmylib.so -shared -fPIC
使用静态库
# g++ main.cpp libmylib.a -o output
使用动态库
# g++ main.cpp -L. -lmylib -o output
相关参数:
-L 指定搜索库的目录,如指定当前目录 gcc -L.
-l 指定要链接的库的名称,如链接libmylib.so动态库 gcc -lmylib
--static 组织在链接时使用静态库
--shared 生成动态库
其它
对静态库动态库使用方法一样,同一库如果同时存在动态库和静态库,优先链接动态库,除非用 --static 强制使用静态库。
ldconfig 是一个动态链接库管理命令,为了让动态链接库为系统所共享,还需运行动态链接库的管理命令–ldconfig
ldd 用来查看程序运行所需的共享库,常用来解决程序因缺少某个库文件而不能运行的一些问题。
代码举例
静态库
1. 首先是准备工作,把我们需要封装成库文件的函数的头文件与源文件写好
如下:
头文件 myAPI.h
int ADD(int a, int b);
int MINUS(int a, int b);
源文件 myAPI.cpp
#include "myAPI.h"
int ADD(int a, int b){
return a + b;
}
int MINUS(int a, int b){
return a - b;
}
2. 接下来准备一个测试用的主函数源文件
主函数文件 main.cpp
#include "myAPI.h"
#include <iostream>
int main(){
std::cout << "1 + 1 = " << ADD(1, 1) << std::endl;
std::cout << "1 - 1 = " << MINUS(1, 1) << std::endl;
return 0;
}
3. 先编译我们的 myAPI.cpp 文件生成 myAPI.o 目标文件
g++ -c myAPI.cpp
4. 生成静态库并使用
ar crv libmyAPI.a myAPI.o
5. 使用静态库编译可执行文件
g++ main.cpp libmyAPI.a -o output
6. 此时 源文件、头文件、o文件、静态库文件都不需要了,只保留和运行可执行程序即可
./output
动态库
1. 编译时通过 -shared 参数可以生成动态库(.so)文件
g++ -shared -fPIC -o libmyAPI.so myAPI.o
2. 生成的动态库在编译时需要声明,运行时需要被依赖
g++ main.cpp -L. -lmyAPI -o output
3. 运行可执行程序
./output
如有找不到的错误,则将 libmyAPI.so 移到 /usr/lib 目录下,ldconfig即可。