环境及工具:ubuntu20.04、gcc(版本9.3.0)、AR(版本2.34)
- 静态链接库存在的意义就在于统一存放编译后的文件.o文件,以方便调用和管理.
- 静态链接库简单来说就是封装好的函数的归档文件.其后缀.a,全称为archive(归档).
linux中的目标文件分为三种
- 共享目标文件 (动态链接库,扩展名.so的文件,意为shared object)
- 可执行目标文件 (ELF格式的,编译并链接的最终产物.)
- 可重定位目标文件 (一般扩展名为.o,二进制代码已经生成,但还未进行重定位.)
tip: 从c源文件到可执行文件,中间经历了预处理->编译->汇编->链接
既然要说静态链接库,就要首先明白什么是链接,举个例子:
//a.c 默认只编译和汇编生成a.o
#include <stdio.h>
int sum(short,short);
int main(void){
int result=sum(1,2);
printf("1+2=%d\n",result);
return 0;
}
//b.c 默认只编译和汇编生成b.o
int sum(short one,short two){
return one+two;
}
gcc是以单个文件为单位进行编译(通常将编译和汇编合并,统称为编译)的,a.c文件使用了b.c文件中定义的函数sum,但在a.c文件中并没有sum函数的具体实现,所以在所有文件都编译完成之后,需要一个过程,将a,b文件中的相互调用解析到具体的符号上.这就是链接要做的事情.
只编译但未链接的生成的目标文件就是 可重定位目标文件.
gcc -c a.c #只编译不链接,生成a.o
gcc -c b.c #只编译不链接,生成b.o
a单独生成可执行文件的时,会找不到引用sum gcc a.o ❌
b也无法生成可执行文件,因为它没有入口函数main gcc b.o ❌
所以,在编译后链接前的a.o文件后面 必须加上有sum实现的可重定位目标文件,即 b.o文件.
gcc a.o b.o ✅
可以想见,如果将实现好的函数,全部编译为对应的.o文件,下次其他程序使用的时候,只需要链接上去即可,也就是在gcc的命令后面添加上函数对应的.o的文件名,可是当.o文件过于多的时候就不方便输入和管理了,于是就将多个.o文件归档在一起,创建为.a文件,既方便了管理,又方便了引用.
eg: ar rcs myfunc.a b.o x.o xx.o xxx.o #在当前目录下生成myfunc.a的归档文件.
下次使用直接gcc a.c myfunc.a
end.