gcc 编译过程

gcc 编译过程
hello.c hello(a.out)文件, 必须历经 hello.ihello.shello.o,最后才获得 hello(
a.out)文件,分别对应着预处理、编译、汇编和连接 4 个步骤,整个过程如图 10.5 所示。
编辑器

4 步大体的工做内容以下:
1) 预处理, C 编译器对各类预处理命令进行处理,包括头文件包含、宏定义的扩
展、条件编译的选择等;
2) 编译,将预处理获得的源代码文件,进行“翻译转换”,产生出机器语言的目标
程序,获得机器语言的汇编文件;
3) 汇编,将汇编代码翻译成了机器码,可是还不能够运行;
4) 连接,处理可重定位文件,把各类符号引用和符号定义转换成为可执行文件中
的合适信息,一般是虚拟地址。
函数

下面根据 hello.c 这个示例,跟踪一下其中的细节。
1)预处理
gcc 命令加上-E 参数,能够获得预处理文件。输入下列命令:
vmuser@Linux-host:hello$ gcc -E hello.c –o hello.i
将会产生 hello.i 文件,这就是 hello.c 通过预处理后的文件。实际操做结果见图 10.6

spa

10.6 预编译获得 hello.i 文件
一个本来连同空行才 8 行的代码,通过预处理,获得了一个 800 多行的预处理文件,文
件开的内容如图 10.7 所示。
翻译

10.7 hello.i 文件开头
hello.i 文件末尾处的内容如图 10.8 所示。
blog


10.8 hello.i 文件末尾
其他部份内容请用 Vi 打开后进行查看。能够看到, hello.c 通过预处理后获得的 hello.i
文件,除了本来的几行代码以外,还包含了不少额外的变量、函数等等,这些都是预处理器
处理的结果。
2)编译
gcc 编译参数加上-S,能够将 hello.i 编译成 hello.s 文件。命令以下:
vmuser@Linux-host:hello$ gcc -S hello.i

md5

实际操做和结果如图 10.9 所示。

编译器

10.9 编译获得 hello.s 文件
hello.s 是一个汇编文件,可用 Vi 编辑器打开查看,如图 10.10 所示。
编译


10.10 hello.s 文件内容
能够看到,该文件内容都是汇编语句。这里不对汇编进行解释。
3)汇编
获得了汇编文件后,经过 gcc 就能够获得机器码了。在终端输入下列命令,能够获得
hello.o 文件。
vmuser@Linux-host:hello$ gcc -c hello.s
实际操做和结果如图 10.11 所示。
class


10.11 汇编获得 hello.o 文件
4)连接
尽管已经获得了机器码,但这个文件却仍是不能够运行的,必需要通过连接才能运行。
在终端输入下列命令,将会获得可执行文件 a.out
vmuser@Linux-host:hello$ gcc hello.o
操做和结果如图 10.12 所示。
变量


10.12 连接获得 a.out 文件
a.out gcc 默认输出文件名称,能够经过-o 参数指定新的文件名。例如加上“-o hello
参数,将会生成 hello 文件,这个文件和 a.out 其实是同样的,用 md5sum 命令计算文件校
验值,二者彻底同样,如图 10.13 所示。


10.13 a.out hello 文件
连接可分为动态连接和静态连接:
动态连接使用动态连接库进行连接,生成的程序在执行的时候须要加载所需的动态
库才能运行。动态连接生成的程序小巧,可是必须依赖动态库,不然没法执行。
Linux 下的动态连接库实际是共享目标文件(shared object),通常是.so 文件,
做用相似于 Windows 下的.dll 文件。
静态连接使用静态库进行连接,生成的程序包含程序运行所须要的所有库,能够直
接运行,不过体积较大。
Linux 下静态库是汇编产生的.o 文件的集合,通常以.a 文件形式出现。
gcc 默认是动态连接,加上-static 参数则采用静态连接。再来看 hello.c 示例,在连接的
时候加上-static 参数:
vmuser@Linux-host:hello$ gcc hello.o -static -o hello_static
操做命令和结果如图 10.14 所示,能够看到,动态连接生成的文件大小是 7155 字节,
而静态连接生成的文件却有 616096 字节,体积明显大了不少。


10.14 静态连接和动态连接结果对比

相关文章
相关标签/搜索