编译原理¶
编译过程和静态库¶
编译过程
情景:假设你有两个文件,一个是hello.c,一个是fun.c,hello.c里面调用了fun.c的代码,具体如下:
//hello.c文件
#include <stdio.h>
int fun(int a,int b);
int main(){
int sum=0;
printf("hello world.\n");
sum=fun(2,3);
return sum;
}
//fun.c文件
int fun(int a,int b){
return a+b;
}
接下来让我们看看原始的编译过程是什么。
首先,最快捷的一步编译方式采用如下指令,可以联合编译两个文件,并输出一个可执行文件:
gcc hello.c fun.c -o hello.out
上述gcc指令实际上可以被分解为如下几个过程:
1. 预处理:如头文件展开、宏替换、条件编译、注释清除,产生.i文件。下面的指令基本等级,不同在于是输出到.i文件还是输出到命令行。
cpp hello.c
gcc -E hello.c
gcc -E hello.c -o hello.i
2. 编译:将源代码转为汇编代码,产生.s文件。gcc -S
实际上也包含了预处理的过程,等价于预处理+编译。
gcc -S hello.c
3. 汇编:将汇编代码转为目标代码,生成.o文件,表示可重定位目标文件。
as hello.s -o hello.o //汇编
gcc -c hello.c -o hello.o //预处理+编译+汇编
file hello.o //查看文件类型
objdump -d hello.o //反汇编代码段
4. 链接:生成可执行目标文件(略微不同于目标文件),后缀为.out。ld命令详细可以参考:ld链接
ld hello.o fun.o xxxx //后面跟的参数很多,具体见链接
gcc hello.c fun.c -o hello.out //gcc一步到位,包含了预处理+编译+汇编+链接
5. 运行与加载:运行二进制代码。
./hello.out
echo $?
静态库
使用ar可以将多个目标文件放到同一个静态链接库中,方便后续调用。Linux中静态链接库通常以.a结尾。
1. 生成 fun.c 的目标文件 fun.o
gcc -c fun.c
2. 创建并添加 fun.o 到库文件 my-lib1.a
ar -r my-lib1.a fun.o
说明:ar 选项
1)命令
⚫ -r //在库中插入模块(替换),replace
⚫ -t //显示库中的文件,list
⚫ -d //删除库中的文件,delete
⚫ -x //提取库中的文件,extract
2)通用修饰符
⚫ -s //添加索引
⚫ -c //不显示提示警告
总结
1. ar:归档,生成库,扩展名为.a。
2. tar:归档。原用于磁盘备份,与 ar 的主要区别是:可归档目录结构
3. objdump:反汇编
4. file:查看文件的类型