前言
对于.c格式的C文件,可以采用gcc或g++编译,对于.cc、.cpp格式的C++文件,应该采用g++进行编译。常用的选项:
-c 表示编译源文件
-o 表示输出目标文件
-g 表示在目标文件中产生调试信息,用于gdb调试
-D<宏定义> 编译时将宏定义传入进去
-Wall 打开所有类型的警告
一、gcc/g++编译过程
进行编译时,需要使用一系列的工具,称为工具链。包括:预处理器、编译、汇编器、连接器。
编译过程包括以下几个阶段:
- 预处理:预处理器将对源文件中的宏进行展开
- 编译:gcc将C文件编译成汇编文件
- 汇编:as将汇编文件编译成机器码
- 链接:将目标文件和外部符号进行链接,得到一个可执行的二进制文件
gcc所支持的后缀名:
后缀名 | 所对应的语言 |
---|---|
.c | C原始程序 |
.C / .cc / .cxx | C++原始程序 |
.m | Objective -C原始程序 |
.i | 已经过预处理的C原始程序 |
.ii | 已经过预处理的C++原始程序 |
.s / .S | 汇编语言原始程序 |
.h | 预处理文件(头文件) |
.o | 目标文件 |
.a / .so | 编译后的库文件 |
gcc常用选项:
选项 | 含义 |
---|---|
-c | 只编译不链接,生成目标文件".o" |
-S | 只编译不汇编,生成汇编代码 |
-E | 只进行预编译,不做其他处理 |
-g | 在可执行程序中包含标准调试信息 |
-o file | 指定将file文件作为输出文件 |
-v | 打印出编译器内部编译各过程的命令行信息和编译器版本 |
-I dir | 在头文件的搜索路径列表中添加dir目录 |
预处理阶段:对包含的头文件(#include)和宏定义(#define、#ifdef等)进行处理。
编译阶段:检查代码规范性、语法错误等,在检查无误后把代码翻译成汇编语言。
链接阶段:将.s文件及库文件整合起来链接为可执行程序。
二、静态库和动态库
gcc库选项:
选项 | 含义 |
---|---|
-static | 进行静态编译,即链接静态库,禁止使用动态库 |
-shared | 可以生成动态库文件;进行动态编译,尽可能地链接动态库,只有没有动态库时才会链接同名的静态库 |
-L dir | 在库文件的搜索路径列表中添加dir目录 |
-lname | 链接称为libname.a(静态库)或libname.so(动态库)的库文件。若两个库文件都存在,则根据编译方式(-static或-shared)进行链接 |
-fPIC(或-fpic) | 生成使用相对地址的位置无关的目标代码,通常使用gcc的-static选项从该PIC目标文件生成动态链接文件 |
函数库分为静态库和动态库。
静态库是目标文件.a的归档文件(格式为libname.a);若编译程序时链接静态库,则链接器将会搜索静态库并直接复制到该程序的可执行二进制文件中;
动态库(格式为libname.so)在编译时不会被链接到目标代码中,而是在程序运行时才被载入。
创建静态库:
$gcc -c add.c //编译add.c源文件生成add.o目标文件
$ar crsv libadd.a add.o //对目标文件*.o进行归档,生成lib*.a(lib必须写)
$gcc -o main main.c -L./ -ladd -I./ //-L后"."表示当前路径
//-ladd表示链接库文件libadd.a/.so
//-I./表示包含在当前目录中的头文件
$./main
创建动态库:
$gcc -fPIC -Wall -c add.c
$gcc -shared -o libadd.so add.o
$gcc-o main main.c -L./ -ladd
在运行main之前,需要注册动态库路径,有三种方法:修改/etc/ld.so.conf、修改LD_LIBRARY_PATH环境变量、将库文件复制到/lib或/usr/lib下(系统默认搜索路径);通常采用第三种。
如果不复制,生成.so之后还有两种方法:$gcc -o main main.c -L. -Wl, -rpath, ${PWD} -ladd
最后执行:gcc -o main main.c -ldl
静态库与动态库的比较:
- 动态库只在执行时才被链接使用,不是直接编译为可执行文件,并且一个动态库可以被多个程序使用,故称为共享库。
- 静态库将会整合到程序中,在程序执行时不用加载静态库。因此,静态库会使你的程序臃肿且难以升级,但比较容易部署。而动态库会使你的程序轻便、易于升级,但难以部署。
三、gcc警告和优化选项
1.gcc警告
gcc警告的选项:
选项 | 含义 |
---|---|
-ansi | 支持符合ANSI标准的C程序 |
-pedantic | 允许发出ANSI C标准所列的全部警告信息 |
-pedantic -error | 允许发出ANSI C标准所列的全部错误信息 |
-w | 关闭所有警告 |
-Wall | 允许发出gcc提供的所有有用的报警信息 |
-werror | 把所有的告警信息转为错误信息,并在告警发生时终止编译过程 |
2.gcc优化选项
gcc对代码进行优化通过选项"-On"来控制优化级别(n为整数)。
不同的优化级别:
- "-O1"级别优化主要进行线程跳转和延迟退栈两种优化;
- “-O2"级别优化除完成”-O1"级别优化之外,还进行一些额外的调整工作,如处理其指令调度等。
调试时不建议优化,发行时考虑进行优化,通常用"-O2"。