- 生成静态库的指令 ar
- 示例
- 一个完整的生成 a 文件的例子
- 编写源码
- 生成 o 文件
- 打包
- 使用静态库
- 客户端测试代码
- 编译链接成最终的可执行文件
生成静态库的指令 ar
- 常用选项
选 项 | 说 明 |
d | 从归档文件中删除文件 |
m[ab] | 在归档文件中移动文件 |
p | 打印在归档文件中找到的文件 |
q[f] | 将文件快速追加到归档文件中 |
r[ab][f][u] | 替换归档文件中已有的文件或加入新文件 |
s | 作为 ranlib 工作 |
t | 显示归档文件的内容 |
x[o] | 从归档文件中分解文件 |
示例
- 打包命令
$ ar -r libbase.a add.o sub.o
该命令的作用实际上就是把 add.o 和 sub.o 这两个文件打成一个包 libbase.a,可以通过下面的命令查看这个包里的内容。
- 查看包中的内容
$ ar -t libbase.a
执行后显示
add.o
sub.o
- 解压包
$ ar -x libbase.a // 解压所有文件
$ ar -x libbase.a -o add.o // 只解压 add.o文件
你完全可以把 ar 理解成 windows 下的压缩软件,虽然不是很准确,但是便于理解。这样一看,ar只是把生成的 .o 文件打成了一个包,方便使用而已。
一个完整的生成 .a 文件的例子
编写源码
// 文件名:add.c
int add(int a, int b) {
return
// 文件名:sub.c
int sub(int a, int b) {
return
生成 .o 文件
$ gcc -c -static add.c -o add.o
$ gcc -c -static sub.c -o sub.o
注意上面的 static 选项,该选项只是告诉编译器,如果操作系统支持动态链接,该选项将阻止其生成动态链接库。man 手册中是这样描述的:
On systems that support dynamic linking, this prevents linking with the shared libraries. On other systems, this option has no effect.
因为 add.c 和 sub.c 并未使用到任何系统调用和库函数,所以这里加 static 和不加 static 都没什么区别。一般来说,加 static 生成的文件会非常巨大。
打包
$ ar -r libbase.a add.o
$ ar -r libbase.a sub.o
当然,上面的两条命令可以合并成一条
$ ar -r libbase.a add.o sub.o
至于包名(静态库名字),最好以 lib 开头,如果你不喜欢也没关系,你起个阿猫阿狗也拦不住你。上面的命令完成后,会生成一个 libbase.a 的包。执行下面的命令,可以看到包里所有的 .o 文件。
$ ar -t libbase.a
使用静态库
理解了 libbase.a 只是 .o 的集合后,使用它就不难了。
客户端测试代码
// 文件名:main.c
#include <stdio.h>
int add(int a, int b); // 使用函数当然要先声明啦。
int sub(int a, int b);
int main() {
printf("3 + 1 = %d\n", add(3, 1));
printf("3 - 1 = %d\n", sub(3, 1));
return 0;
}
编译链接成最终的可执行文件
- 生成 .o 文件
$ gcc -c main.c -o main.o
- 链接成最终文件
$ gcc main.o libbase.a -o app
或者
$ gcc main.o -o app -L. -lbase
需要注意的是,上面的命令你是不能写成下面这样的,否则会报错。
$ gcc libbase.a main.o -o app // error
最终生成 了可执行程序 app,运行结果如下:
-Ldir 选项的含义是在 dir 这个目录中查找要链接的库文件
-lname 是指链接库名为 libname.a 的文件(不要和我说 libname.so,这个还没学到)。