理解gcc/g++的编译过程

gcc的编译流程分为了四个步骤,分别为(学过计算机的都知道,不细讲啦)预处理(Pre-Processing),编译(Compiling),汇编(Assembling)和链接(Linking)。

gcc的编译流程及状态流向可以归纳如下(网上转的图示,很生动)

gcc编译过程状态及选项图

gcc编译过程状态及选项图

从中得出几点:
(1) 通过控制gcc的选项,可以得出不同类型的中间文件;
(2) 编译流水为:源文件->汇编文件->目标文件(机器文件)->二进制文件。编译过程不能逆着来,也就是流水只能这样流。假如写了一个汇编文件,也可以流到二进制文件。
(3) gcc用到的处理程序分别是:cpp、ccl、as、ld,也就是说图中的gcc命令可由这些处理程序来进行编译的过程,其结果是一样的。这些命令的使用可参照网上的文章。

下面是一个简单的图示(转账的图片,来源不明)

gcc编译过程

gcc编译过程

不详细理解gcc的编译过程会导致两个问题:
(1) 对编译过程理解含糊,不能熟悉gcc/g++编译的参数和选项;
(2) Makefile不会写,或写不好。
很多人想一天就学好Makefile的熟悉,殊不知对gcc/g++的学习也是基础的一步。另外请看我的另一篇文章–《gcc/g++参数选项》。
先明确几点:
(1) gcc不是一个命令,而是一个工具集,即GNU Compiler Collection(应该没记错哈~);
(2) gcc的-o选项不只是用来重新指定最终的可执行文件名,而是可以指定编译过程中产生的中间文件名称。
接下来先熟悉本文涉及到gcc的几个参数:
-o 定义输出文件
-E 完成预处理/预编译停止
-c 只编译生成.o,不连接

下面就具体来查看一下gcc是如何完成四个步骤的。
首先,有以下hello.c源代码

#include
int main()
{
printf(“Hello World!\n”);
return 0;
}
(1)预处理阶段
在该阶段,编译器将上述代码中的stdio.h编译进来,并且用户可以使用gcc的选项”-E”进行查看,该选项的作用是让gcc在预处理结束后停止编译过程。
gcc -E hello.c -o hello.i
(2)编译阶段
接下来进行的是编译阶段,在这个阶段中,gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。用户可以使用”-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
gcc -S hello.i -o hello.s
(3)汇编阶段
汇编阶段是把编译阶段生成的”.s”文件转成目标文件,读者在此可使用选项”-c”就可看到汇编代码已转化为”.o”的二进制目标代码了。如下所示:
gcc -c hello.s -o hello.o
(4)链接阶段
在成功编译之后,就进入了链接阶段。在这里涉及库的概念,包括静态库和动态库,请网上查找相关资料熟悉。
完成了链接之后,gcc就可以生成可执行文件,如下所示。
gcc hello.o -o hello

(5)运行该可执行文件
./hello
Hello World!