文章目录
准备: test.c
在正式开始之前,若是想要通过一个代码(.c文件)来熟悉gcc的编译流程,可以在你的测试目录下使用如下代码:
// 文件名:test.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main(int argc, char *argv[])
5 {
6 int arg;
7 for(arg = 0; arg < argc; arg++){
8 if(argv[arg][0] == ‘-’)
9 printf("option:%s\n",argv[arg]+1);
10 else
11 printf("argument %d:%s\n",arg,argv[arg]);
12 }
13 exit(0);
14 }
1. 编译过程
在使用gcc编译程序时,编译过程可以简要划分为4个阶段:
- 预处理
- 汇编
- 编译
- 链接
1.1 预处理(Pre-Processing)
这个阶段主要处理源文件中的#indef、#include和#define预处理命令;
这里主要是把一些include的头文件和一些宏定义,放到源文件中。
- 输入的是C语言的源文件
- 输出 :生成一个中间/预加载文件 *.i(以 .i 结尾的文件)
- 这个阶段对应的gcc命令如下:
#gcc –E(预处理) test.c(源文件) -o test.i(将结果生成的文件)
- 说明:它通过对源文件test.c使用E选项来生成中间文件test.i
1.2 汇编(Assembling)
-
输入:中间文件*.i
-
输出:编译后生成汇编编语言文件*.s
-
这个阶段对应的gcc命令如下:
#gcc -S(汇编) test.i -o test.s(汇编编语言文件)
-
说明:它通过对源文件test.c使用S选项来生成汇编文件test.s
1.3 编译(Compiling)
- 输入文件:汇编文件*.s
- 输出文件:二进制机器代码*.o
- 这个阶段对应的gcc命令如下:
#gcc -c(编译) test.s -o test.o
* gcc -c
在功能上,预处理、编译、汇编是3个不同的阶段
但gcc在实际操作时可以把这3个步骤合并为一个步骤来执行,即使用 -c选项:
- 输入文件:源码*.c文件
- 输出文件:二进制机器代码*.o
- 这个阶段对应的gcc命令如下:
# gcc –c test.c -o test.o
// -o指定了output_filename
或 :
#gcc -c test.c
//省略-o output_filename
//默认输出为test.o
//与源文件同名,后缀为.o
1.4 链接(Linking)
- 输入文件:二进制机器码*.o文件
- 输出文件:与其它的机器代码和库文件汇集成一个可执行的二进制代码文件(无后缀)
- 这个阶段对应的gcc命令如下:
#gcc (没有选项符号) test.o example.o -o test
可用选项:
-L 指定库路径
-l (小写的L)指定库名称
-I (大写的i)指定头文件所在路径
-i 指定头文件名称
选项详解:
选项 | 用法 | 解释 |
---|---|---|
-l(大写的i) | -Idirname(没有间隔) | 将名为dirname的目录加入到程序头文件目录列表中,它是在预处理阶段使用的选项,I是指Include |
-L | -Ldirname | 将名为dirname的目录加入到程序的库文件搜索目录列表中,它是在链接过程中使用的参数, L是指Link |
-l (小写的L) | -lname | 指示编译器,在链接时,装载名为libname.a的函数库,该函数库位于系统预定义的目录或者由-L选项指定的目录下 |
· 例:-lm 表示链接名为libm.a的数学函数库
2. 简化过程 —— gcc
- 上述过程可以简化为:
#gcc test.c (源文件) -o test(可执行文件)
注意:与链接的语句差别主要在指令中输入文件的后缀
注:
1.库是头文件的实现!
2.在编译过程中可以被装载/拷贝的库为静态库(.a后缀)
· 更多关于静态库/动态库的知识请参考这篇博客:详解Linux下静态库/动态库(含代码示例)
3. gcc常用选项总结
常用选项:
选项 | 功能 |
---|---|
-c | 只编译,不链接成可执行文件,编译器只是由输入的.c等为后缀的源代码文件生成.o为后缀的标文件,通常用于编译不包含主程序的子程序文件 |
-o | output_filename 确定输出文件的名称为output_filename,同时这个名称不能和源文件名。如果不给出这个选项,gcc就默认将输出的可执行文件命名为a.out |
-g | 产生调试器gdb所必须的符号信息,要对源代码进行调试,就必须在编译程序时加入这个选项 |
-O | 对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、链接过程中进行优化处理,这样产生的可执行文件的执行效率较高,但是,编译、链接的速度就相应地要慢一些。 |
-O2 | 比-O更好的优化编译、链接 |
-Wall | 输出所有警告信息 |
-w | 关闭所有警告信息 |
-Idirname(没有间隔,大写 i ) | 将名为dirname的目录加入到程序头文件目录列表中,它是在预处理阶段使用的选项,I是指Include |
-Ldirname | 将名为dirname的目录加入到程序的库文件搜索目录列表中,它是在链接过程中使用的参数。 |
· L是指Link | |
-lname(小写的L) | 指示编译器,在链接时,装载名为libname.a的函数库,该函数库位于系统预定义的目录或者由-L选项指定的目录下 |
- gcc使用例子:
(1)gcc -Wall src.c –o dest -lpthread
/*输出所有警告信息地编译src.c生成dest可执行文件
/*并在链接时装入libpthread.a的函数库
—————————————————————————
(2)gcc -Wall -o sniffex sniffex.c -lpcap
/*输出所有警告信息地编译sniffex.c生成sniffex可执行文件
/*并在链接时装入libpcap.a的函数库