一、GCC的基本介绍
GCC(GNU Compiler Collection,GNU编译器套装),是一套由GNU开发的编程语言编译器。它是一套以GPL及LGPL许可证所发行的自由软件,也是GNU计划的关键部分,亦是自由的类Unix及苹果电脑 Mac OS X 操作系统的标准编译器。
GCC原名为GNU C语言编译器,因为它原本只能处理C语言。GCC很快地扩展,变得可以处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java,以及Ada与其他语言。Linux系统下的GCC(GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。
GCC是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%。GCC编译器能将C、C++语言源程序和目标程序编译、连接成可执行文件,如果没有给出可执行文件的名字,GCC将生成一个名为a.out的文件。在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。而GCC则通过后缀来区别输入文件的类别。一般情况下gcc认为预处理后的文件(.i)是C文件,并且设定c形式的连接;g++认为预处理后的文件(.i)是c++文件,并且设定c++形式的连接。
GCC所遵循的部分约定规则:
.c为后缀的文件,C语言源文件; .
a为后缀的文件,是由目标文件构成的档案库文件;
.C,.cc或.cxx为后缀的文件,是C++源代码文件;
.h为后缀的文件,是程序所包含的头文件;
.i为后缀的文件,是已经预处理过的C源代码文件;
.ii为后缀的文件,是已经预处理过的C++源代码文件;
.m为后缀的文件,是Objective-C源代码文件;
.o为后缀的文件,是编译后的目标文件;
.s为后缀的文件,是汇编语言源代码文件;
.S为后缀的文件,是经过预编译的汇编语言源代码文件。
在gcc的使用过程中,一般除非使用-c,-S,或-E选项(或者因为其他的错误阻止了完整编译的过程),否则连接总是最后的步骤。在连接阶段中,所有对应于的源程序的.o文件,-l库文件,无法识别的文件名(包括指定的.o目标文件和.a库文件)按照命令行中的顺序传递给连接器。
二、GCC的执行过程
GCC是C语言的编译器,但使用GCC由C语言源代码文件生成可执行文件的过程不仅仅是编译的过程,而是要经历四个相互关联的步骤∶预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编(Assembly)和连接(Linking)。命令gcc首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析。接着调用cc1进行编译,这个阶段根据输入文件生成以.o为后缀的目标文件。汇编过程是针对汇编语言的步骤,调用as进行工作。一般来讲,.S为后缀的汇编语言源代码文件和汇编、.s为后缀的汇编语言文件经过预编译和汇编之后都生成以.o为后缀的目标文件。当所有的目标文件都生成之后,gcc就调用ld来完成最后的关键性工作,这个阶段就是连接。在连接阶段,所有的目标文件被安排在可执行程序中的恰当的位置,同时该程序所调用到的库函数也从各自所在的档案库中连到合适的地方。
三、GCC的常见编译选项
GCC的编译选项中包括总体选项、语言选项、预处理器选项、汇编器选项等等。
-c 编译或者汇编源文件,但是不作连接。编译器输出对应于源文件的目标文件。缺省情况下,GCC通过―.o‖替换源文件名后缀..c‘,..i ‘,..s ‘等等,产生目标文件名。可以使用-o 选项选择其他名字。GCC忽略-c选项后面任何无法识别的输入文件(他们一般不需要编译或汇编)。
-S 编译后即停止,不进行汇编。对于每个输入的非汇编语言文件,输出文件是汇编语言文件。在缺省情况下,GCC通过用..o‘替换源文件名后缀..c‘,..i ‘等等,产生目标文件名。可以使用-o选项选择其他名字。GCC忽略任何不需要编译的输入文件。
-E 预处理后即刻停止,不进行编译。预处理之后的代码送往标准输出。GCC忽略任何不需要预处理的输入文件。
-o file 指定输出文件为file.该选项不在乎GCC产生什么输出,无论是可执行文件,目标文件,汇编文件还是预处理后的c代码。一般只能指定一个输入文件,当编译多个输入文件时,使用.-o‘选项没有意义,除非输出一个可执行文件。如果没有使用.-o‘选项,默认输出结果是:可执行文件为.a.out‘, .source.suffix‘的目标文件是.source.o‘,汇编文件是.source.s‘,而预处理后的c 源代码送往标准输出。
-v 显示执行编译阶段的命令。同时显示编译器驱动程序,预处理器,编译器的版本号。
-pipe 在编译过程的不通阶段间使用管道而非临时文件进行通信。这个选项在某些系统上无法工作,因为那些系统的汇编器不能从管道读取数据。
-ansi支持符合ANSI标准的c程序。这样就会关闭GNU C中某些不兼容ANSI C的特性,例如asm,inline和typeof关键字,以及诸如unix和vax这些表明当前系统类型的预定义宏。同时开启不受欢迎和极少使用的ANSI trigraph特性,以及禁止‗$‘成为标识符的一部分。如果是使用了‗-ansi‘选项,下面的这些可选的关键字,__asm__,__extension__,__inline__和__typeof__仍然有效。当用在ANSI C程序当中的时候,可以把他们放在头文件中。使用‗-ansi‘选项不会自动拒绝编译非ANSI程序,除非增加‗-pedantic‘选项作为‗-ansi‘选项的补充。使用‗-ansi‘选项的时候,预处理器会预定义一个__STRICT_ANSI__宏。有些头文件关注此宏,以避免声明某些函数,或者避免定义某些宏,这些函数和宏不被ANSI标准调用;这样就不会干扰在其他地方使用这些名字的程序了。
-fno-asm 不把asm,inline或typeof当作关键字,因此这些词可以用做标识符。用__asm__,__inline__和__typeof__能够替代他们。.-ansi‘隐含声明了.-fno-asm‘。 -include file 在处理常规输入文件之前,首先处理文件file,其结果是,文件file的内容先得到编译。命令行上任何.-D‘和.-U‘选项永远在.-include file‘之前处理,无论他们在命令行上的顺序如何。.-include‘和.-imacros‘选项按书写顺序处理。 -imacros file 在处理常规输入文件之前,首先处理文件file,但是忽略输出结果。由于丢弃了文件file的输出内容,
.-imacros file‘选项的唯一效果是使文件file中的宏定义生效,可以用于其他输入文件。在处理.-imacros file‘选项之前,预处理器首先处理.-D‘和.-U‘选项,并不在乎他们在命令行上的顺序。然而.-include‘和.-imacros‘选项按书写顺序处理。
三、GCC常见的优化选项
gcc默认提供了5级优化选项的集合:
-O0:无优化(默认) -O和-O1:使用能减少目标文件大小以及执行时间并且不会使编译时间明显增加的优化。在编译大型程序的时候会显著增加编译时内存的使用。
-O2:包含-O1的优化并增加了不需要在目标文件大小和执行速度上进行折衷的优化。编译器不执行循环展开以及函数内联。此选项将增加编译时间和目标文件的执行性能。
-Os:专门优化目标文件大小,执行所遇的不增加目标文件大小的-O2优化选项。并且执行专门减小目标文件大小的优化选项。
-O3:打开所有-O2的优化选项并且增加-finline-functions,-funswitch-loops,-fpredictive -commoning,-fgcse-after-reload and –ftree-vectorize优化选项。
四、GCC常见的编译命令示例
对于在使用GCC编译的时候,常见的使用编译的参数如下,以hello.c文件为例:
gcc –o hello hello.c : 将hello.c文件编译成hello的可执行文件 gcc –c hello.c : 将hello.c文件生成hello.o文件 gcc -E hello.c : 只是激活预处理,不生成文档,需要把它重定向到另外一个文档里 gcc –S hello.c : 将hello.c文件生成hello.s文件的汇编代码 gcc –pipe –o hello hello.c : 使用管道代替编译中临时文档 gcc hello.c –include /root/hello.h :包含某个代码,简单来说,就是以某个文档,需要另外一个文档的时候,就能够用它设定,功能就相当于在代码中使用#include |
1、在Ubuntu文件夹下新建一个hello.c文件,并添加如下内容:
#include int main(void) { printf("Hello World\n"); return 0; } |
$ gcc -o test hello.c |
3、运行test
# ./test Hello World |