Skip to content

Latest commit

 

History

History
115 lines (77 loc) · 6.93 KB

编译器-gcc学习.md

File metadata and controls

115 lines (77 loc) · 6.93 KB

GCC学习

1 GCC简介

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百科


2 GCC命令

当调用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库

常用options

  • -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

windows相关

  • -Wl,--add-stdcall-alias Wl用于传递参数给连接器,--add-stdcall-alias表示具有stdcall后缀的符号将按原样导出,并且也将删除后缀。因为dll中导出的函数签名与VC生成的不一致。需要加上编译参数。

3 常见错误

  • undefined reference to 'xxxxx':这是链接错误,不是编译错误,也就是说如果只有这个错误,说明程序源码本身没有问题,是用编译器编译时参数用得不对,没有指定链接程序要用到得库,比如程序里用到了某个函数属于libm.so库,那么就要在编译参数里指定程序要链接数学库,方法是在编译命令行里加入-lm

引用