跳转至

编译原理

编译过程和静态库


编译过程

情景:假设你有两个文件,一个是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:查看文件的类型