GNU编译器套装(英语:GNU Compiler Collection,缩写为GCC),指一套编程语言编译器,以GPL及LGPL许可证所发行的自由软件,也是GNU项目的关键部分,也是GNU工具链的主要组成部分之一。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。1985年由理查德·马修·斯托曼开始发展,现在由自由软件基金会负责维护工作。
原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC在发布后很快地得到扩展,变得可处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java、Ada,Go与其他语言。
许多操作系统,包括许多类Unix系统,如Linux及BSD家族都采用GCC作为标准编译器。苹果电脑预装的Mac OS X操作系统也采用这个编译器。
GCC原本用C开发,后来因为LLVM、Clang的崛起,它更快地将开发语言转换为C++。许多C的爱好者在对C++一知半解的情况下主观认定C++的性能一定会输给C,但是Taylor给出了不同的意见,并表明C++不但性能不输给C,而且能设计出更好,更容易维护的程序(GCC's move to C++)。——WIKI百科
当调用GCC时,通常会进行预处理,编译,汇编和链接。,“options”可以在中间阶段停止这个过程。例如,-c
选项表示不运行链接器。然后输出由汇编器输出的目标文件组成。选项被传递到一个或多个处理阶段,一些options控制预处理器,而其他的则控制编译器本身。还有其他选项控制汇编器和链接器。大多数可以与GCC一起使用的命令行选项对C程序很有用;但有些选项只对另一种语言有用。
运行GCC的通常方法是在交叉编译时运行名为gcc
的可执行文件或者machine-gcc
,或者运行特定版本的GCC的machine-gcc
版本。
GCC程序接受选项和文件名作为操作数。许多选项有多个字母的名字;因此多个单字母选项可能不会分组:-dv
与-d -v
是不同的。
可以混合选项和其他参数。大多数情况下,参数使用的顺序无关紧要。当使用相同种类的多个选项时,顺序很重要,例如,如果多次指定-L
,则按指定的顺序搜索目录。另外,-l
选项的位置也很重要。很多选项都以-f
或-W
开头,例如,-fmove-loop-invariants,-Wformat
等等。这些大多数都有正面和负面的形式; -ffoo
的否定形式是-fno-foo
。
gcc的语法为gcc(选项)(参数)
,选项包括的类型非常多,比如:控制输出类型、警告压制类型、编译优化类型等等。
gcc test.c #编译出一个名为a.out或a.exe的可执行程序
gcc test.c -o test #将test.c预处理、汇编、编译并链接形成可执行文件test。-o选项用来指定输出文件的文件名。
//windows上编译
gcc -c HelloC.c -I "H:\dev_tools\java8\include" -I "H:\dev_tools\java8\include\win32" #用于编译c代码生成.o库
gcc -Wl,--add-stdcall-alias -shared -o HelloC.dll HelloC.o #用于把.o库转换成windows平台的dll库
gcc -Wl,--add-stdcall-alias -I "H:\dev_tools\java8\include" -I "H:\dev_tools\java8\include\win32" -shared -o helloC.dll HelloC.c #直接生成windows平台的.dll库
-
-Wl
:告诉编译器将后面的参数传递给链接器。 -
-o
:指定生成的输出文件。 -
-E
:仅执行编译预处理
gcc -E test.c -o test.i #将test.c预处理输出test.i文件
-S
:将C代码转换为汇编代码
gcc -S test.i #将预处理输出文件test.i汇编成test.s文件
-
-wall
:显示警告信息 -
-c
:仅执行编译操作,不进行连接操作
gcc -c test.s #将汇编输出文件test.s编译输出test.o文件
gcc test.o -o test #无选项链接,将编译输出文件test.o链接成最终可执行文件test
-
-l
和-L
参数:用来指定程序要链接的库-l
参数紧接着就是库名,加入库名是libA.so
,那么命令就是-lA
-l
和-L
的区别是,如果需要连接的第三方库在/lib、/usr/lib、/usr/local/lib
下,那么只需要使用-l
命令,如果不在这三个目录,就需要使用-L
命令来指定全路径,比如L/aaa/bbb/ccc -lA
。 -
-include
和-I
参数:用来指定包含的头文件-include
用来包含头文件,但一般情况下包含头文件都在源码里用#include
引入了,所以-include
参数很少用。-I
参数是用来指定头文件目录,/usr/include
目录一般是不用指定的,gcc可以找到,但是如果头文件不在/usr/include
里就要用-I
参数指定了,比如头文件放在/myinclude
目录里,那编译命令行就要加上-I/myinclude
参数,参数可以用相对路径,比如头文件在当前目录,可以用-I.
来指定。 -
-O
参数:程序优化参数
gcc test.c -O2 #使用编译优化级别2编译程序。级别为1~3,级别越大优化效果越好,但编译时间越长
-shared
参数,用于编译动态链接库
`gcc -shared test.c -o libtest.so` #将test.c 编译成动态链接库
-fPIC
:属于“Options for Code Generation Conventions”类选项-fPIC
作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
- 1 多个文件一起编译:
gcc testA.c testB.c -o test`
- 2 分开编译后再连接:
gcc -c testA.c #将testA.c编译成testA.o
gcc -c testB.c #将testB.c编译成testB.o
gcc -o testA.o testB.o -o test #将testA.o和testB.o链接成test
-Wl,--add-stdcall-alias
Wl用于传递参数给连接器,--add-stdcall-alias表示具有stdcall后缀的符号将按原样导出,并且也将删除后缀。因为dll
中导出的函数签名与VC生成的不一致。需要加上编译参数。
undefined reference to 'xxxxx'
:这是链接错误,不是编译错误,也就是说如果只有这个错误,说明程序源码本身没有问题,是用编译器编译时参数用得不对,没有指定链接程序要用到得库,比如程序里用到了某个函数属于libm.so
库,那么就要在编译参数里指定程序要链接数学库,方法是在编译命令行里加入-lm
- gcc 文档
- Option-Summary,所有的gcc命令可以在这里找到
- Options specific to i386 PE targets