介绍
GCC(GNU Compiler Collection
,GNU
编译器集合)是由GNU
开发的各种编程语言编译器的合集。
GNU
编译器套件包括C
、C++
、 Objective-C
、 Fortran
、Java
、Ada
和Go
语言编译器,也包括了这些语言的库(如libstdc++
、libgcj
等)。
GCC
最开始的时候是 GNU C Compiler
, 如你所知,只是一个C
编译器。 但是后来这个项目里边集成了更多其他不同语言的编译器,于是GCC
变成了 the GNU Compiler Collection
,表示一堆编译器的合集。
GCC
是GNU
编译器集合的意思, 对于用户能用的常用命令, 有gcc
和g++
。
无论是gcc
还是g++
, 他们的定位都是驱动程序(driver
)。
driver
负责调用编译器(狭义), 把源码编译到汇编代码。比如C
语言的编译器(狭义)是cc1
, 而C++
语言的编译器(狭义)是cc1plus
。(但一般使用gcc和g++来分别指代C编译器和C++编译器,大家注意分别)
driver
再调用as
,把汇编代码变成二进制代码。 最后调用ld
, 负责把二进制代码拼在一起。
现在你在编译代码时调用的gcc
命令,不是所谓的C
语言编译器,更确切的说它是一个驱动程序,可以根据代码的后缀名来判断调用C
编译器还是C++
编译器 。
比如你的代码后缀是.c
,他会调用C
编译器和linker
去链接C
的library
;
如果你的代码后缀是.cpp
, 他会调用C++
编译器和linker
去链接C++
的library
。
GCC这个项目中,真正负责编译 C 代码的程序叫做
cc1
,负责编译 C++ 代码的程序叫做cc1plus
。
玩转Linux:常用命令实例指南
编译过程
- 预处理,生成
.i
的文件
[预处理器cpp
Cpreprocesser
] - 将预处理后的文件转换成汇编代码,生成文件
.s
[编译器egcs
] - 将汇编代码变为目标代码(机器代码)生成
.o
的文件
[汇编器as
] - 连接目标代码, 生成可执行程序
.out
[链接器ld
]
在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。
linux中扩展名除了一些特殊的约定,一般情况下是无意义的。
而gcc
则通过后缀来区别输入文件的类别,下面介绍gcc
所遵循的部分约定规则:
.c
为后缀的文件,C语言源代码文件.a
为后缀的文件,是由目标文件构成的库文件;.C
,.cc
或.cxx
为后缀的文件,是C++源代码文件;.h
为后缀的文件,是程序所包含的头文件;.i
为后缀的文件,是已经预处理过的C源代码文件;.m
为后缀的文件,是Objective-C源代码文件;.o
为后缀的文件,是编译后的目标文件;.s
为后缀的文件,是汇编语言源代码文件;.S
为后缀的文件,是经过预编译的汇编语言源代码文件.out
为后缀的文件,是代码最终生成的可执行程序
一. 常用编译命令选项
假设源程序文件名为test.c
-
无选项编译链接
用法:gcc test.c
作用:将test.c
预处理、汇编、编译并链接形成可执行文件。
这里未指定输出文件,默认输出为a.out
。 -
选项
-o
用法:gcc test.c -o test
作用:将test.c
预处理、汇编、编译并链接形成可执行文件test。
-o
选项用来指定输出文件的文件名。
-
选项
-E
用法:gcc -E test.c -o test.i
作用:将test.c
预处理输出test.i
文件。 -
选项
-S
用法:gcc -S test.i -o test.s
作用:将预处理输出文件test.i
编译成test.s
文件。 -
选项
-c
用法:gcc -c test.s -o test.o
作用:将汇编输出文件test.s
汇编输出test.o
目标文件。单个程序(不需链接动态库和静态库)到此就可以运行了。 -
无选项链接
用法:gcc test.o -o test
作用:将目标文件test.o
链接动态库和静态库成最终可执行文件test
。 -
选项
-O
用法:gcc -O1 test.c -o test
作用:使用编译优化级别1编译程序。级别为1~3,级别越大优化效果越好,但编译时间越长。
二. 多源文件的编译方法
如果有多个源文件,基本上有两种编译方法:
假设有两个源文件为test.c
和testfun.c
-
多个文件一起编译
用法:gcc testfun.c test.c -o test
作用:将testfun.c
和test.c
分别编译后链接成test可执行文件。 -
分别编译各个源文件,之后对编译后输出的目标文件链接
用法:
gcc -c testfun.c //将testfun.c编译成testfun.o
gcc -c test.c //将test.c编译成test.o
gcc -o testfun.o test.o -o test //将testfun.o和test.o链接成test
以上两种方法相比较,第一中方法编译时需要所有文件重新编译,而第二种方法可以只重新编译修改的文件,未修改的文件不用重新编译。
运行程序 例如./a.out
就可以运行程序