一、GCC是什么?
gcc可以编译C、C++、JAVA...等多种语言,且gcc是一个交叉平台编译器,可以再cpu平台上为多种不同体系的硬件平台开发软件
二、编译过程
- 将C语言源程序预处理,生成.i文件。
- 预处理后的.i文件编译成为汇编语言,生成.s文件。
- 将汇编语言文件经过汇编,生成目标文件.o文件。
- 将各个模块的.o文件链接起来生成一个可执行程序文件。
三、gcc所遵守部分约定
文件后缀名 | 文件类型约定 |
---|---|
.c | c语言源代码文件 |
.a | 由目标文件构成的档案库文件 |
.C, .cc, .cxx | C++源代码文件 |
.h | 程序所包含的头文件 |
.i | 经预处理过的c源代码文件 |
.ii | 经预处理过的C++源代码文件 |
.m | Objective-C源代码文件 |
.o | 编译后的目标文件 |
.s | 汇编语言源代码文件 |
.S | 经过预编译的汇编语言源代码文件 |
四、常用编译命令
选项 | 含义描述 |
---|---|
-o filename | 指定输出文件的文件名 如果filename没有指定,缺省文件名是a.out |
-c | 编译、汇编指定的源文件,但是不进行链接,生成目标文件 “.o” |
-S | 源文件编译为汇编语言,但是并不汇编该程序,汇编成.s文件。 |
-E | 预处理指定的源文件,不进行编译。将C语言源文件进行预处理,但是并不编译该程序。 |
-g | 生成调试信息,该程序可以被调试器调试 |
-v | 打印编译器内部编译各过程的的命令行信息和编译器的版本号 |
-I dir | 在头文件的搜索路径列表中添加dir目录 |
-L dir | 在库文件的搜索路径列表中添加dir目录 |
-static | 连接静态库 |
-library | 连接名为library的库文件 |
-Dmacro | 定义指定的宏,使它能够通过源码中的#ifdef进行检验 |
-O 、-O2、-O3 | 将优化状态打开,该选项不能与-g选项联合使用 |
-Wall | 在发生警告信息时取消编译操作,即警告看做错误 |
-Werror | 在发生警告信息时取消编译操作,即警告看做错误 |
-w | 禁止所有的报警 |
-pedantic | 严格要求符合ANSI标准 |
五、编译命令详解
1. 无选项
用法:#gcc test.c
作用:将test.c预处理、汇编、编译并链接形成可执行文件。
这里未指定输出文件,默认输出为a.out。
2. 选项 -o
用法:#gcc test.c -o test
作用:将test.c预处理、汇编、编译并链接形成可执行文件test。
-o选项用来指定输出文件的文件名。
3. 选项 –E 预处理指定的源文件,不进行编译。将C语言源文件进行预处理,但是并不编译该程序。对于一般的预处理问题,可以使用这个选项进行查看,例如,宏的展开问题、文件的包含问题等。
用法:#gcc -E test.c -o test.i
作用:将test.c预处理输出test.i文件。
4. 选项 –S 将C语言源文件编译为汇编语言,但是并不汇编该程序。
用法:#gcc -S test.i
作用:将预处理输出文件test.i汇编成test.s文件。
5. 选项 –c 编译、汇编指定的源文件,但是不进行链接
用法:#gcc -c test.s
作用:将汇编输出文件test.s编译输出test.o文件。
6. 选项 -o
用法:#gcc test.o -o test
作用:将编译输出文件test.o链接成最终可执行文件test。
7. 选项-O
用法:#gcc -O1 test.c -o test
作用:使用编译优化级别1编译程序。级别为1~3,级别越大优化效果越好,但编译时间越长。
8. 选项-I directory
用法:指定 include 包含文件的搜索目录
9 选项-g 生成调试信息,该程序可以被调试器调试
10. 选项 –L directory 指定库文件目录
多源文件的编译方法
如果有多个源文件,基本上有两种编译方法:
[假设有两个源文件为test.c和testfun.c]
1. 多个文件一起编译
用法:#gcc testfun.c test.c -o test
作用:将testfun.c和test.c分别编译后链接成test可执行文件。
2. 分别编译各个源文件,之后对编译后输出的目标文件链接。
用法:
#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
以上两种方法相比较,第一中方法编译时需要所有文件重新编译,而第二种方法可以只重新编译修改的文件,未修改的文件不用重新编译。
3. 库文件连接
开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助许多函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(so、或lib、dll)的集合。。虽然Linux下的大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下;Windows所使用的库文件主要放在Visual Stido的目录下的include和lib,以及系统文件夹下。但也有的时候,我们要用的库不再这些目录下,所以GCC在编译时必须用自己的办法来查找所需要的头文件和库文件。
例如我们的程序test.c是在linux上使用c连接mysql,这个时候我们需要去mysql官网下载MySQL Connectors的C库,下载下来解压之后,有一个include文件夹,里面包含mysql connectors的头文件,还有一个lib文件夹,里面包含二进制so文件libmysqlclient.so
其中inclulde文件夹的路径是/usr/dev/mysql/include,lib文件夹是/usr/dev/mysql/lib
3.1编译成可执行文件
首先我们要进行编译test.c为目标文件,这个时候需要执行
gcc –c –I /usr/dev/mysql/include test.c –o test.o
3.2链接
最后我们把所有目标文件链接成可执行文件:
gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test
Linux下的库文件分为两大类分别是动态链接库(通常以.so结尾)和静态链接库(通常以.a结尾),二者的区别仅在于程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。
3.3强制链接时使用静态链接库
默认情况下, GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库,如果需要的话可以在编译时加上-static选项,强制使用静态链接库。
在/usr/dev/mysql/lib目录下有链接时所需要的库文件libmysqlclient.so和libmysqlclient.a,为了让GCC在链接时只用到静态链接库,可以使用下面的命令:
gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test
静态库链接时搜索路径顺序:
1. ld会去找GCC命令中的参数-L
2. 再找gcc的环境变量LIBRARY_PATH
3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的
动态链接时、执行时搜索路径顺序:
1. 编译目标代码时指定的动态库搜索路径
2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
4. 默认的动态库搜索路径/lib
5. 默认的动态库搜索路径/usr/lib
有关环境变量:
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径