从头学习编译过程

来源:互联网 发布:华军软件下载中心 编辑:程序博客网 时间:2024/06/04 18:55

     之前经常接触Makefile  ,但近日跟随 韦东山老师学习时,总觉的自己了解的不透彻,所以决定再复习一遍。

经典的样例代码:

#include <stdio.h>
void main(void){
        printf("hello  world!!!!!\n");
        return;
}

以上内容保存为hello.c ,linux 环境下cd 到当前目录,

输入:gcc -o hello hello.c 

发现已经生成可执行文件hello  ,输入 ./hello , 终端打印:hello  world!!!!! 


问题1:-o  代表意义?

回答问题1: 允许用户指定输出文件名

所以gcc -o hello hello.c   指令 表示:告诉编译工具 ,编译生成可执行目标文件,并且目标文件的名称为hello。

这句指令的背后,编译工具实际上做了编译过程的必需4大步骤:

分别是预处理(Preprocess),编译(Compilation),汇编(Assembly)和链接(Linking)。


一、预处理

预处理过程主要读取c源程序,对伪指令和特殊符号进行处理。包括宏,条件编译,包含的头文件,以及一些特殊符号。基本上是一个replace的过程。

预处理过程主要处理规则如下:

1、将所有的#define删除,并且展开所有的宏定义;

2、处理所有条件编译指令,如#if,#ifdef等;

3、处理#include预编译指令,将被包含的文件插入到该预编译指令的位置。该过程递归进行,及被包含的文件可能还包含其他文件。

4、删除所有的注释//和 /**/;

5、添加行号和文件标识,如#2 “hello.c” 2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号信息;

6、保留所有的#pragma编译器指令,因为编译器须要使用它们;


二、编译

编译过程通过词法和语法分析,确认所有指令符合语法规则(否则报编译错),之后翻译成对应的中间码,在linux中被称为RTL(Register Transfer Language),通常是平台无关的,这个过程也被称为编译前端。编译后端对RTL树进行裁减,优化,得到在目标机上可执行的汇编代码。gcc采用as作为其汇编器,所以汇编码是AT&T格式的,而不是Intel格式,所以在用gcc编译嵌入式汇编时,也要采用AT&T格式。


三、汇编

汇编器是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。


四、链接

链接器ld将各个目标文件组装在一起,解决符号依赖,库依赖关系,并生成可执行文件。链接需要用到链接脚本,用来指定链接地址,链接顺序是链接命令来指定的。


回过头 看编译命令: gcc -o hello hello.c  ,试试 不使用 -o 指定输出文件名来编译:

直接:gcc hello.c

发现自动生成目标可执行文件 a.out  ,输入:./a.out , 终端打印:Hello World!   

搞明白了-o ,再来看-c

输入:gcc -c hello.c  ,结果 生成一个不能执行的 hello.o 文件

再输入:gcc hello.o  ,然后生成 可执行文件 a.out

那么-c 的作用是:编译产生对象文件(*.obj)而不链接成可执行文件,当编译几个独立的模块,而待以后由链接程序把它们链接在一起时,就可以使用这个选项,简单说就是编译而不连接


为了更好的显示细节,我改下代码:

#include <stdio.h>
extern a_fun(void);
void main(void){
        printf("hello  world!!!!!\n");
        a_fun();
        return;
}

保存为hello.c



#include <stdio.h>
void a_fun(void){


        printf("this is a function !!!\n");
        return;

}

最简单编译命令:gcc -o hello hello.c a.c

./hello    打印:
hello  world!!!!!
this is a function !!!


使用Makefile ,分步操作:

编写 Makefile 


hello : hello.o a.o
        gcc -o hello hello.o a.o

hello.o : hello.c
        gcc -o hello.o -c hello.c

a.o     : a.c
        gcc -o a.o -c a.c

保存,make,显示编译过程
gcc -o hello.o -c hello.c
gcc -o a.o -c a.c
gcc -o hello hello.o a.o
生成目标可执行文件:hello


参考网络文章:

http://blog.csdn.net/eastmoon502136/article/details/8162626



0 0
原创粉丝点击