计算机系统篇之链接(1):gcc/g++的编译流程
Author:stormQ
Saturday, 21. December 2019 09:48AM
gcc/g++,实质上是一个编译驱动器(Compile Driver),对它的调用意味着调用一系列的程序——预处理器、编译器、汇编器和链接器,从而将源代码转化成可执行目标文件。具体流程可以分为如下四个步骤:
1)预处理
首先调用 C 预处理器(名称为cpp
的可执行目标文件,通常位于/usr/bin/
目录下)将每个源文件(比如:以.c 或 .cc 或. cpp
结尾的文件)扩展源代码——即插入所有用#include
命令指定的文件,并扩展所有用#define
声明指定的宏。对一个源文件进行预处理的输出结果是一个以.i
结尾的中间文件,即编码为 ASCII 码的源代码中间文件。
由源文件生成预处理文件的命令:
# 一个源文件(以.c/.cc/.cpp结尾的文件)对应一个预处理后的源文件(以.i结尾的文件)
$ cpp -std=c++11 main.cpp -o main.i
$ cpp -std=c++11 shm_manager_sim.cpp -o shm_manager_sim.i
$ cpp -std=c++11 subscription_sim.cpp -o subscription_sim.i
$ cpp -std=c++11 topic_manager_sim.cpp -o topic_manager_sim.i
或
$ g++ -E main.cpp -o main.i
$ g++ -E shm_manager_sim.cpp -o shm_manager_sim.i
$ g++ -E subscription_sim.cpp -o subscription_sim.i
$ g++ -E topic_manager_sim.cpp -o topic_manager_sim.i
注意:
-
main.cpp 中包含了
<thread>
头文件(在 C++11 标准中涵盖)。所以,直接调用预处理器cpp
时需要添加-std=c++11
选项,而采用g++ -E
的方式不需要添加该选项。 -
如果源文件与其包含的用户头文件不在同一个目录中,需要添加
-I
选项指定搜索路径,从而成功地生成.i
文件。示例:1)用户头文件都处于同一个目录时,对应的命令:g++ -E main.cpp -o main.i -I <directory>
;2)用户头文件处于不同目录时,对应的命令:g++ -E main.cpp -o main.i -I <directory 1> -I <directory 2> -I <directory n>
。 -
在某些 gcc/g++ 版本中,预处理器被集成到编译驱动器中,而不是作为独立的程序存在。
2)编译
其次,调用编译器(名称为cc1
——用于编译C程序的可执行目标文件或cc1plus
——用于编译C++程序的可执行目标文件,在本人的机器上两者位于/usr/lib/gcc/x86_64-linux-gnu/6
目录下)将扩展后的源代码(以.i
结尾的文件)编译成汇编代码(以.s
结尾的文件,即编码为 ASCII 码的汇编语言文件)。
由预处理文件生成汇编语言文件的命令:
# 一个预处理后的源文件(以.i结尾的文件)对应一个汇编代码文件(以.s结尾的文件)
# /usr/lib/gcc/x86_64-linux-gnu/6/cc1plus -o main.s main.cpp <other arguments>
$ /usr/lib/gcc/x86_64-linux-gnu/6/cc1plus -o main.s main.cpp -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE -quiet -dumpbase -mtune=generic -march=x86-64 -auxbase-strip -version -fstack-protector-strong -Wformat -Wformat-security
或
$ g++ -S main.i -o main.s
$ g++ -S shm_manager_sim.i -o shm_manager_sim.s
$ g++ -S subscription_sim.i -o subscription_sim.s
$ g++ -S topic_manager_sim.i -o topic_manager_sim.s
注意:
-
cc1plus
命令中<other arguments>
部分如何确定?详见下文。 -
如果需要添加调试信息,只能在执行本步骤时加
-g
选项。其他时期:步骤1)、步骤3)、步骤4)时加-g
选项都没有任何作用。添加-g
所生成的汇编代码文件中可以看到与调试相关的 sections,如:.debug_aranges
、.debug_info
、.deb