目录
3.3 汇编——gcc -c选项:只编译不链接,仅生成目标文件
3.4 链接——gcc file.o -o选项:指定输出文件
6.2.1、动态库查找不到解决方法一(不推荐——不允许使用)
一、前言
GCC是GNU工具链的集合,包含编译器、汇编器、链接器、解释器等。它是一个能够编译多种语言的编译器。最开始gcc是作为C语言的编译器(GNU C Compiler),现在除了c语言,还支持C++、java、Pascal等语言。gcc支持多种硬件平台。
1.1、库的种类
linux下的库有两种:静态库和共享库(动态库)。
二者的不同点在于代码被载入的时刻不同。
静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。
1.2、库存在的意义
库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。
现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
二、gcc的特点
- gcc是一个可移植的编译器,支持多种硬件平台。例如ARM、X86等等。
- gcc不仅是个baidu本地编译器,它还能跨平台交叉编译。所谓的本地编译器,是指编译出来的程序只能够在本地环境进行运行。而gcc编译出来的程序能够在其他平台进行运行。例如嵌入式程序可在x86上编译,然后在arm上运行。
- gcc有多种语言前端,用于解析不同的语言。
- gcc是按模块化设计的,可以加入新语言和新CPU架构的支持。
- gcc是自由软件。任何人都可以使用或更改这个软件。
三、gcc编译的四个过程
gcc在执行编译工作的时,分为以下四个过程:
1.预处理(pre-processing),生成.i的文件
2.编译(compiling):将预处理后的文件转换成汇编语言,生成.s文件
3.汇编(assembling)变为目标代码(机器代码),生成.o的文件
4.链接(linking)目标代码,生成可执行程序
盗用一张图~
3.1 预处理 ——gcc -E选项:生成预处理文件
gcc -E HelloWorld.c -o HelloWorld.i
在此阶段,gcc使用预编译器,对代码进行预编译,预编译后,gcc将拷贝头文件,宏替换文字的替换,条件编译等操作。可以查看helloWorld.i文件预编译后的文件内容,包含了大量的extern,一些结构、一些枚举等。
3.2 编译——gcc -S选项:生成汇编文件
gcc -S HelloWorld.i -o HelloWorld.s
gcc在编译阶段进行代码的规范性检查以及代码是否有语法错误,如果没有就生成.s汇编文件
3.3 汇编——gcc -c选项:只编译不链接,仅生成目标文件
gcc -c HelloWorld.s -o HelloWorld.o
将编译生成的汇编文件转换成二进制代码文件.o文件。
3.4 链接——gcc file.o -o选项:指定输出文件
gcc HelloWorld.o -o HelloWorld
预处理的时候虽然加载了stdio.h,但是这个头文件里面全都是一些声明,并没有具体的代码实现,例如调用了printf函数的时候,stdio.h里面没有实现代码,所以链接阶段主要的工作就是链接所需要的函数库。printf这个函数是在libc.so.6这个库里面,所以链接阶段gcc编译器会链接到这个库,所以就实现了这个函数的调用。
函数库又可以分为静态库和动态库,后续讲解
3.5 一步到位
gcc hello.c -o hello 直接编译链接成可执行目标文件
note:一步到位和链接都只有-o,其它过程除了-o,还有其它参数
3.5.1 多文件编译
一次性编译
gcc -Wall -g test1.c test2.c test3.c -o test
独立编译
gcc -Wall -g -c test1.c -o test1.o
gcc -Wall -g -c test2.c -o test2.o
gcc -Wall -g -c test3.c -o test3.o
gcc -Wall -g test1.o test2.o test3.o -o test
使用独立编译的好处:
当一个项目中包含大量源文件时,当一个文件改动后,使用独立编译可以只编译改动的文件,
不必编译所有文件,从而节省编译时间。
四、gcc编译选项
常用选项
- 语法:gcc [options] [filenames]
参数 | 作用 | 编译示例 | 示例说明 |
---|---|---|---|
-o | 指定输出可执行程序的名称,默认文件名为”a.out” | gcc test.c -o test | 编译单个源文件 test.c,指定输出可执行程序的名称为 test,支持同时编译多个源文件 |
-E | 仅作预处理,不进行编译、汇编和链接 | gcc -E test.c -o test.i | 仅预处理源文件,指定生成中间文件 *.i ,此阶段主要处理源文件中的 #ifdef、#include、#define 等预处理命令 |
-C | 在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的 | ||
-S | 只编译到汇编语言,不进行汇编和链接,生成汇编代码 | gcc -S test.c -o test.s | 仅编译到汇编语言,指定生成汇编源文件 *.s |
-c | 只编译、汇编到目标代码,不进行链接,生成目标文件(机器语言) | gcc -c test.s -o test.o | 根据汇编源文件 *.s ,指定生成目标文件 *.o ,最后根据生成的目标文件,可执行 gcc test.o -o test 命令生成可执行程序 |
-llib | 指定程序链接哪个静态库或者动态库 | ||
-I- | 就是取消前一个参数的功能,所以一般在-Idir之后使用 | ||
-m | 表示是数学库,也就是使用 math.h 头文件 | gcc test.c -o test -lm | 编译单个源文件 test.c,指定输出可执行程序名称为 test,并指定程序链接到数学库 |
-Idir | 在头文件的搜索路径列表中添加 dir 目录 | ||
-Ldir | 在库文件的搜索路径列表中添加 dir 目录 | ||
-O、-O2、-O3 | 将优化状态打开,该选项不能与”-g” 选项联合使用 | ||
-g | 在生成的可执行程序中包含标准调试信息 | 在目标文件长嵌入调试信息, |