GCC是 "GNU Compiler Collection" 的简称,属于 GNU 的一员。
GCC 的步骤可以拆解如下:
--main.c--
#include <stdio.h>
int main()
{
printf("The is a test.\n");
return 0;
}
--main.c--
| 预处理器
| cpp
| 命令:gcc -E main.c > main.i
| 备注:假设源文件需要使用到非系统头文件且它们不在源文件所在目录时,通过-I 参数指定
↓ 作用:展开源文件中的所有宏指令(#define/#include)
--main.i--
| 编译器
| cc
| 命令:gcc -S -O2 main.c
| 备注:-On n∈{0,1,2,3} 数值越大,优化等级越高
↓ 作用:从c代码翻译成为汇编
--main.s--
| 汇编器
| as
↓ 作用:只包含符号信息,没有任何c语言和汇编语言方面的踪迹
--main.o--
| 链接器
| ld
| 备注:可以用来生成映射文件
↓ 作用:链接各种.o文件,生成可执行程序
--main.exe--
其中的as、ld都属于binutils工具集的一部分。
1、直接从 main.c -> main.exe
$ gcc main.c -o main.exe
2、获取系统头文件路径
$ gcc -v main.c
3、生成映射文件
$ gcc -Wl,-Map=main.map main.c -o main.exe
4、通过选项定义宏 -D
假设源文件更改为:
--main.c--#include <stdio.h>
#define min(X,Y) ((X)<(Y) ? (X) : (Y))
int main()
{
printf("The min is %d.\n", min(AA,BB));
return 0;
}
则可以通过 -D 命令动态指定宏:
$ gcc -DAA=3 -DBB=4 main.c -o main.exe
这在测试条件编译,或者 u-boot 中指定基地址时很有用
5、查看依赖关系。
通过以下命令可以查看文件的依赖关系:
$ gcc -M main.c
这样的命令会将系统头文件也包含进来(有的是直接包含,有的间接包含),如果不想包含系统头文件,可以使用如下命令:
$ gcc -MM main.c6、生成静态库
现假设有 foo.c 文件如下:
--foo.c--#include <stdio.h>
void foo()
{
printf("this is foo().\n");
}
可以使用如下两条命令将其生成静态库:
$ gcc -c foo.c
$ ar crs libfoo.a foo.o
7、指定静态链接库
当一个可执行程序的生成需要使用其他库时,需要在链接时加以指定,这就要用到 gcc 的 -L 和 -l 选项。-L 用来指定查找库文件的目录,-l 指定需要链接的库名。现假设有 main.c 文件如下,它所调用的 foo 函数来自 6 中的静态库。
--main.c--extern void foo();
int main()
{
foo();
return 0;
}
可以使用如下命令:
$ gcc -o main.exe -L. main.c -lfoo
关于这条命令做几点说明:
① -L. 不可省略,表示库文件在当前工作目录
② main.c 和 -lfoo 不可交换,因为 main.c 依赖于 foo,gcc 规定被依赖者在后
③ -l 指定库名时可以去掉前缀 "lib" 和后缀 ".a"
④ 如果同时存在 foo.c 和 mian.c,则可以直接通过命令 gcc main.c foo.c -o main.exe 生成
⑤ 当目录中同时存在静态库和动态库时,编译会自动指定为动态库, -Wl,-Bstatic 可以指定静态库,对应的, -Wl,-Bdynamic 指定动态库
8、其它的一些命令
-Wall 让所有编译警告都显示出来: gcc -Wall main.c -o main.exe
-Wall -Werror 将编译警告转换成错误: gcc -Wall -Werror main.c -o main.exe
-save-temps 输出所有的中间文件: gcc -save-temps main.c -o main.exe
@filename 通过文件指定编译选项,然后通过@指定文件从而间接指定编译选项
比如; 文件"opt_file" 内容的内容为 "-Wall -o main.exe" (没有引号)gcc main.c @opt_file 就等效于 gcc main.c -Wall -o main.exe