前面一篇已经简单的介绍了如何利用gcc编译c源代码,这篇说一下gcc的具体编译过程
- 预处理
预处理的工作主要是处理#include语句等,然后生成*.i文件。如果不加参数“-o *.i”,则会将预处理的结果输出到标准输出。
gcc -E *.c -o *.i #使用gcc的E参数进行预处理
cpp *c - o *.i #使用cpp命令进行预处理
这两条命令预处理的结果一样,因为gcc使用-E参数实际上也是调用了cpp指令。
2.生成汇编代码
gcc -S *c -o *.s #将C代码汇编为汇编语言代码
gcc -S *.i -o *.s #将i文件汇编为汇编语言代码
3.编译
gcc -c *.c -o *.o
gcc -c *.s -o *o
as *.s -o *.o
cc -c *.c -o *.o
4.链接
gcc *.o -o *out
GCC高级技巧
1.指定头文件位置
一是在源码中指定头文件的绝对路径,简单直观但缺乏灵活性,二是在编译时使用“-I”参数来指定头文件的路径,实际工作中,一般选择第二种。
使用第二种方法将resolv.c编译为resolv.out的命令如下:
gcc resolv.c -I /home/myname/code/header -o resolv.out 如果找不到会按照代码所在目录或系统目录寻找头文件
gcc resolv.c -I /home/myname/code/header -I /home/myname/code/header2 -o resolv.out 多个路径
2.定义符号常量
在代码中会使用一些常量来控制程序的行为,如#define WIRELESS 211 等等一系列,怎么来检验定义了符号常量与为定义符号常量的区别,一般在编译时使用-D参数来指定符号常量,命令如下:gcc -D WIRELESS -I /home/myname/code/header resolv.c -o resolv.out
3.定义警告级别
最常用的警告选项是-Wall选项。其意思是warning all。使用如下命令显示特定警告信息来编译test.c,命令如下:
gcc -Wall test.c -o test
4.其他GCC选项
gcc [option] [filename]
- -c:只将源代码编译为以.o为后缀的目标文件,而不是直接将这些文件连接可执行文件。通常用于不包含主程序(man函数)的子程序代码。
- -o:filename: 指定输出文件名。如果不用这个选项,gcc会将文件输出到a.out,而不管输出文件的类型
- -g:产生调试信息。如果要使用gdb进行调式,则必须使用该选项。但是该选项所产生的调式符号,并不能被其他调式器识别。
- -O:在程序编译、连接过程中对代码进行优化。
- -O2:比-O更好的优化编译、连接。
- -L dir:在程序连接时,会首先在dir目录寻找类库文件,然后在系统预设路径中寻找类库。也可以使用多个-L参数指定多个类库存放的目录。
- -lname:在程序连接时加载名为libname.a的函数库。如-lmath 表示连接名为libmath.a的数学函数库。
- --sysboot=dir:让目录dir作为头文件和库文件的根目录
- -B dir:将目录dir添加到编译器的搜索路径中。
- -b:指定gcc编译的目标机器架构,如ARM、DEC、GNU/Linux、IA64、MIPS等,这也可以看出gcc的超级跨平台性。
- -V n1.n2:使用n1.n2指定版本的gcc进行编译
- -E:仅作预处理,不能进行编译等工作,生成i文件
- -S:将源码编译为汇编语言代码
- -x lang:将源代码依照特定语言进行编译,可以取得值包括但不限于C、C++、Objective-C、Objective-C++、Assembler、Ada、java等。在一系列的编译中,该选项会一直保持,知道另一个-x lang出现,指定另一种编译语言。如果是none,意味着让gcc一句文件的后缀来自动判断语言种类。