gcc编译器
gcc 编译器是 Linux 系统下最常用的 C/C++ 编译器,大部分 Linux 发行版中都会默认安装。
gcc的编译过程:
- 预处理:主要是加载头文件、进行宏替换、条件编译等
- 编译:在确定没有语法和词法错误后将其翻译成汇编代码
- 汇编:将编译过程中生成的汇编文件转换成二进制代码
- 链接:将目标文件、库文件等链接成可执行文件
gcc支持编译的后缀名
后缀名 | 对应语言 | 后缀名 | 对应语言 |
---|
.c | C原始程序 | .ii | 已经经过预处理的C++原始程序 | .C | C++原始程序 | .s | 汇编语言原始程序 | .cc | C++原始程序 | .S | 汇编语言原始程序 | .cxx | C++原始程序 | .h | 预处理文件(头文件) | .m | Object-C原始程序 | .o | 目标文件 | .i | 已经预处理过的C原始程序 | .a/.so | 编译后的库文件 |
gcc有非常多的编译选项,这里列举几个常用的
- -o 指定输出文件,默认:a.out
- -E 仅进行预处理,生成预处理代码(默认输出到屏幕,可通过-o输出到文件)
- -S 编译到汇编语言,生成汇编代码:*.s
- -c 将汇编语言翻译到目标代码(也可以直接编译c文件,gcc会根据文件后缀名进行判断),不进行链接,生成目标文件:*.o
- -g 编译时在可执行文件中插入调试信息,以便gdb进行调试
- -Wall 显示更多警告信息
- -O n 优化编译,提高可执行程序的运行速度,n可取值:1,2,3
- -lx 链接库,对应库文件为libx.so或libx.a,x为库名,与-l之间没有空格
- I dir 指定额外的头文件搜索位置dir
- L dir 指定额外的库文件搜索位置dir
- -static 不使用动态库,编译出的文件较大,但不需要再链接库
- -share 尽量使用动态库
gcc编译常用格式如下:
gcc C源文件 -o 目标文件
函数库
函数库是一组预先编译好的函数集合,以便重复使用。
静态库
在链接阶段,编译器将指定的静态库与程序代码结合生成可执行文件。
静态库的文件名一般是:*.a
创建静态库
首先将源码编译为目标文件(*.o),然后使用ar命令创建静态库。
ar是一个静态库管理命令。
ar [crv] 库名 文件列表
- c:创建归档
- r:把文件合并成一个静态库,如果静态库文件已经存在则更新。
- v:显示过程信息
使用静态库
- 直接调用,在gcc的源文件里一起列出
- 设置LIBRARY_PATH环境变量来指定库的路径,然后在gcc命令中通过参数-lx来指定库名
- 在gcc参数中指定库文件搜索路径,然后通过参数-lx来指定库名
动态库(共享库)
在编译时,并不将函数库的代码插入到可执行程序中,而是将库的引用插入,在执行期间动态的加载函数库。
创建动态库
在使用gcc生成目标文件时添加参数–fPIC(生成与位置无关的代码),因为动态库的变量地址是运行时确定的,而不是链接时确定的。
然后使用gcc -shared来创建动态库
gcc -shared -o lib*.so(库名) *.o(目标文件列表)
make工程管理
make是一个"自动编译管理器"
在模块化开发中,make来根据程序模块的修改情况重新编译链接目标代码,以保证目标代码总是由它的最新模块组成。
make命令将根据Makefile文件的内容来处理依赖关系,只编译需要更新的模块,方便大型项目的管理。
make的使用
由于现在的很多IDE集成了自动生成Makefile文件的功能,因此这里只作简单介绍。
语法
make [选项] [make工程文件]
选项
- -f makefile 指定规则文件,建议使用默认的Makefile
- -d 显示调试信息
- -n 显示命令,但不执行
- -s 执行命令但不显示任何信息
Makefile文件编写
Makefile的文件格式为: 目标文件列表:依赖文件列表 <TAB>命令列表
- 目标文件列表:make需要创建的文件
- 依赖文件列表:编译目标文件所需要的其他文件,make会先去处理依赖文件的编译
- 命令列表:make执行的动作,通常是编译命令
示例 下面的程序的功能是输入一个名字name,打印"hello,name"
sayhello.c文件内容
#include <stdio.h>
int main(){
printf("what's your name?\n");
char name[100];
scanf("%s", name);
myprint(name);
return 0;
}
myprint.c文件内容
#include <stdio.h>
void myprint(char name[]){
printf("hello,%s\n", name);
}
Makefile文件内容
sayhello:sayhello.c myprint.o
gcc sayhello.c myprint.o -o sayhello
myprint.o:myprint.c
gcc myprint.c -c -o myprint.o
下面是执行make命令的输出
gcc myprint.c -c -o myprint.o
gcc sayhello.c myprint.o -o sayhello
运行sayhello文件
>>>what's your name?
<<<jack
>>>hello,jack
修改myprint.c文件
#include <stdio.h>
void myprint(char name[]){
printf("nice to meet you,%s\n", name);
}
再次执行make命令,下面是输出内容,因为sayhello要重新链接目标文件,所以两条编译命令都执行了
gcc myprint.c -c -o myprint.o
gcc sayhello.c myprint.o -o sayhello
修改sayhello.c文件
#include <stdio.h>
int main(){
printf("tell me your name\n");
char name[100];
scanf("%s", name);
myprint(name);
return 0;
}
再次执行make命令,下面是输出内容,这次只执行了一条编译命令,因为myprint.o文件无需更新
gcc sayhello.c myprint.o -o sayhello
gdb调试工具
跟踪程序的运行,给出它的内部运行状态以协助开发者定位程序中的错误。
语法
gdb [选项] [可执行程序]
选项
- -q 安静模式,启动gdb时不输出版本和版权信息
- -n 不执行任何初始化文件中的命令,默认初始化文件为 .gdbinit
- -cd dir 将dir作为调试的工作目录,默认为当前目录
进入gdb后通过gdb提供的命令来进行调试
- file 装入待调试的程序
- kill 终止当前调试的程序
- list 列出源程序,默认只显示10行,按回车继续显示下10行
- next 执行一行程序但不进入函数
- step 执行一行程序但且进入函数
- run 执行当前程序
- watch 动态监视指定变量的值,当变量变化时立 即暂停执行
- print 打印表达式值
- break n 在第n行上设置断点
- quit 退出调试
|