GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL 语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而 GCC 也不再单只是 GNU C 语 言编译器的意思了,而是变成了 GNU Compiler Collection 也即是 GNU 编译器家族的意思了。另 一方面,说到 GCC 对于操作系统平台及硬件平台支持,概括起来就是一句话:无所不在。
一般来说编译一步到位的指令为
gcc test.c -o test
我们可以拆解成:预处理、编译为汇编代码、汇编、连接等,一步步来编译源程序。
1、预处理命令为:
gcc -E test.c -o test.i 或 gcc -E test.c
命令含义:
将源文件 hello.c 文件预处理生成 hello.i
GCC 的选项-E 使 GCC 在进行完预处理后即停止
预处理过程:
(1)将所有的#define 删除,并且展开所有的宏定义,并且处理所有的条件预编 译指令,比如#if #ifdef #elif #else #endif 等。
(2) 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
(3) 删除所有注释“//”和“/* */”。
(4) 添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
(5) 保留所有的#pragma 编译器指令,后续编译过程需要使用它们
查看一下.i文件
打开 test.i 文件一看,就明白了。后 面那条指令,是直接在命令行窗口中输出预处理后的代码.
2、编译为汇编代码
gcc -S test.i -o test.s
命令含义:
将预处理生成的 hello.i 文件编译生成汇编程序 hello.s
gcc 的-S 选项,表示在程序编译期间,在生成汇编代码后,停止,-o 输出汇编代码文件。
处理内容:
编译过程就是对预处理完的文件进行一系列的词法分析,语法分析,语义分析及 优化后生成相应的汇编代码。
3、汇编
gcc -c test.s -o test.o
命令含义:
将编译生成的 hello.s 文件汇编生成目标文件 hello.o
GCC 的选项-c 使 GCC 在执行完汇编后停止,生成目标文件
处理内容:
汇编过程调用对汇编代码进行处理,生成处理器能识别的指令,保存在后缀为.o 的目标文件中。
需要注意的是目标文件已经是最终程序的某一部 分了,只是在链接之前还不能执行。
4、链接
链接又分为静态链接与动态链接:
详见:
Linux GCC 编译过程分析及常用检错的编译选项
gcc test.o -o test
生成可执行文件后,可以使用 Binutils 的 size 命令查看文件大小和使用 Binutils 的 ldd 命令查看链接的动态库。
size hello
ldd hello
通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用 GCC 能够很好地管理 这些编译单元.
我们可以使用下面这行命令一步到位:
gcc test1.c test2.c -o test
如果同时处理的文件不止一个,GCC 仍然会按照预处理、编译和链接的过程依次进行。如果深究起 来,上面这条命令大致相当于依次执行如下三条命令:
gcc -c test1.c -o test1.o gcc -c test2.c -o test2.o gcc test1.o test2.o -o test
示例:
gcc -pedantic illcode.c -o illcode
-pedantic 选项能够帮助程序员发现一些不符合 ANSI/ISO C 标准的代码,但不是全部,事实上只有 ANSI/ISO C 语言标准中要求进行编译器诊断的 那些情况,才有可能被 GCC 发现并提出警告。
示例:
gcc -Wall illcode.c -o illcode
使用它也能够使 GCC 产生尽可能多的警告信息
示例:
gcc -Werror test.c -o test
在编译程序时带上-Werror 选项,那 么 GCC 会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改。
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
一个典型的ELF文件包含以下几个段:
说明:
.text:已编译程序的指令代码段。
.rodata:ro 代表 read only,即只读数据(譬如常数 const)。
.data:已初始化的 C 程序全局变量和静态局部变量。
.bss:未初始化的 C 程序全局变量和静态局部变量。
.debug:调试符号表,调试器用此段的信息帮助调试
可以使用 readelf -S 查看其各个 section 的信息:
$ readelf -S 目标文件
由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包 含的指令和数据,需要使用反汇编的方法。 使用 objdump -D 对其进行反汇编。
$ objdump -D 目标文件
以上就是今天总结的内容,本文仅仅简单分析了GCC的编译与使用,还有一些检错选项来帮助我们查看警告,还介绍了ELF文件的格式等。