GCC用法学习笔记
一、GCC简介
GCC是GNU编程套件(GNU Compiler Collection)的简称,可编译C、C++、Objective C、Pascal、Ada等语言。可以说是Linux开发的标准编译环境,也是入门Linux开发的第一课。
二、C\C++编译过程
与大多数编译型语言一样,Linux下C\C++同样需要经过预处理、编译、链接三个典型阶段。
举例有如下C源文件hello.c
// output hello string program source file
#include <stdio.h>
Int main(int argc, char* argv[])
{
printf(“hello!\n”);
return 0;
}
执行命令: gcc hello.c –ohello 会在当前目录下生成名为hello的可执行文件。-o是接触到的第一个gcc参数,代表output(输出文件名)的意思。
上述gcc命令会自动完成预处理、编译和链接三个过程,如果想具体手工控制每个编译的中间过程,可按照如下操作:
Ø 预处理阶段
将源程序进行预处理操作。主要包括将#include的头文件包代码包含进来、处理#define定义的宏替换、过滤#if #ifndef #endif等条件编译。
执行命令:gcc –E hello.c –o hello.pre
通过查看生成的hello.pre文件即可预处理后的源代码详情。
Ø 编译阶段
编译阶段非常简单,就是将每个单独的源文件(.c)生成对应的编译后文件(.o)。
执行命令:gcc –c hello.c –o hello.o
Ø 链接阶段
.o是一种二进制的临时文件,若干个.o文件可以链接成一个可执行文件。
执行命令:gcc hello.o –o hello
三、文件后缀名规则
GCC是通过文件的后缀名来识别各种不同类型的文件(虽然linux的世界大多不采用后缀名的方式),大致规则如下:
扩展名 | 类型 |
.c | C语言源代码 |
.C .cc .cpp | C++语言源代码 |
.i | 预处理后的C源代码 |
.ii | 预处理后的C++源代码 |
.S .s | 汇编语言源代码 |
.o | 编译后的目标代码 |
.a .so | 编译后的库代码 |
四、常用命令行选项
选项 | 含义 |
-o | 指定当前阶段输出文件名,在链接阶段如果不指定,则默认为a.out |
-c | 只编译不链接 |
-D KEY=VALUE | 定义预处理的宏,名称为KEY,值为-- |
-I /user/include | 指定编译阶段包含头文件的路径 |
-L /user/lib | 指定编译阶段包含库的路径 |
-lpthread | 链接名libpthread的库 |
-g | 在可执行程序中包含标准调试信息,会增大可执行程序的体积 |
-ggdb | 在可执行程序中包含只有gdb才可以识别的调试信息 |
-O? | 编译过程对代码进行优化,?代表1~3的数字,不过不填就默认为1,数字越大优化的效果越好。 |
-w | 关闭所有警告,不建议使用 |
-W*** | 打开对应的编译警告,***有很多的取值,all代表显示所有类型的警告,unused警告所有没有使用的变量。 |
-werror | 将所有警告转换成错误,主要用于强迫编码着解决所有警告避免产生隐含问题。 |
-static | 生成静态链接库,即后缀名为.a的文件,相当于windows下的lib文件。 |
-shared | 生成动态链接库,即后缀名为.so的文件,相当于windows下的dll文件。 |
-p | 在可执行程序中生成性能分析标准定位信息,通过prof程序查看。 |
-pg | 在可执行程序中生成性能分析标准定位信息,通过gprof程序查看。通过科学的性能分析定位瓶颈才是优化程序的王道! |
还有很多其他选项,我个人觉得已经过时或者非极端场合不需要使用,所以没有一一列出,如需使用,可找谷老师帮忙。
【后话】如果工程量稍大,有几十个模块、上百个源文件,肯定不能采用手写编译命令的方式,需要用到linux下自动化编译的又一利器makefile了!