Linux编译器 – gcc / g++
通常我们所写的C/C++程序, 是一种高级语言程序, 这些程序是cpu无法直接识别的, 需要编译器将我们所写的代码解释成为机器指令之后, 才能执行
首先了解一下编译的过程:
1.预处理
预处理主要包括展开头文件, 宏替换, 条件编译, 去注释等
例如现在有一个源文件hello.c, 在终端下输入命令:
gcc –E hello.c –o hello.i
选项 “-E” 的作用是让 gcc 在预处理结束后停止编译过程
选项 “-o” 是指目标文件, “.i” 文件为已经经过预处理的C原始程序
2.编译
编译的目的是检查有无语法错误, 没有问题然后生成汇编代码
gcc –S hello.i –o hello.s
同样, 选项 “-S” 的作用是在生成汇编代码后, 停止编译
3.汇编
将汇编代码转化为二进制机器指令
gcc –c hello.s –o hello.o
4.链接
把多个目标文件链接起来, 生成可执行文件
gcc hello.o –o hello
链接方式的分类:
动态链接: 链接时并没有将具体函数的实现代码写入到可执行程序中, 所以以后运行这个程序的时候, 需要将函数库也加载到内存中, 但是在内存中多个程序可以使用同一个库(节省资源)
静态链接: 在链接库函数文件生成可执行程序的时候, 直接将库文件中的代码加入到可执行程序中, 因此生成的文件会比较大, 但是运行的时候不需要依赖库的存在
gcc中默认的链接方式是动态链接
Linux调试器 – gdb
调试器的作用是调试程序运行过程, 查看程序出问题的位置
程序的发布方式有两种, debug版本和release版本
Linux下gcc/g++出来的可执行程序, 默认是release版本, 然而调试程序的前提是要生成一个debug版程序
要使用gdb调试, 必须在源代码生成可执行程序的时候, 加上 -g 选项
开始调试命令:
run 程序直接开始运行
start 开始逐步调试
调试的流程控制命令:
list 查看指定文件指定行附近的代码
list filename(文件名):line(行号)
step 下一步,若当前调试位置是一个函数,则会进入函数
next 下一步,若当前调试位置是一个函数,则会直接运行完这一行的函数
until 直接运行到指定文件的指定行
until filename(文件名):line(行号)
continue 从当前位置继续运行
断点相关命令:
break 打断点
break filename(文件名):line(行号) break function_name(函数名)
info break 查看断点信息
delete 删除断点
watch 变量监控,当变量内容发生变化则停下来
watch variable_name(变量名)
其他指令命令:
backtrace 查看程序运行信息中的函数调用栈
可以快速定位程序崩溃位置,因为程序崩溃后,栈顶函数就是出问题的函数
quit: 退出调试 print 打印变量内容
项目自动化构建工具 – make/Makefile
make: Makefile解释器, 逐行解释执行项目构建规则, 完成项目的构建
从当前所在目录找到makefile文件, 在makefile中找到第一个目标对象后, 执行命令, 完毕之后退出;
但是若发现依赖对象也需要生成, 则会在makefile中找寻依赖对象的生成规则, 生成依赖对象之后, 然后再生成目标对象
Makefile: 是一个普通的文本文件, 在这个文件中可以编写整个项目的编译流程规则
makefile带来的好处就是——“自动化编译”, 只要写好规则, 用一个make命令, 整个工程完全自动编
译, 极大的提高了软件开发的效率
Makefile的编写格式:
目标对象:依赖对象
<tap> 编译命令
例如:
hello:hello.o
gcc hello.o -o hello
hello.o:hello.s
gcc -c hello.s -o hello.o
hello.s:hello.i
gcc -S hello.i -o hello.s
hello.i:hello.c
gcc -E hello.c -o hello.i
预定义变量:
$^: 全部的依赖对象
$<: 第一个依赖对象
$@: 目标对象
比如生成可执行文件main,需要依赖文件main.o和hello.o
下面就可以这么写了:
main:main.o hello.o
gcc $^ -o $@
%.o:%.c
gcc -c $< -o $@
%是一个通配符,当上面找main.o的生成规则的时候,%就通配的是main
通过这种方式,就不用一个个去写每个.o文件的生成规则了
.PHONY关键字
.PHONY:clean
clean:
rm -f hello.i hello.s hello.o hello
如果把.PHONY : clean 这句删除的话, 当make clean时就会出现:
make: “clean”是最新的。
因此无法达到删除的目的, 我们可以使用 .PHONY 来声明伪对象, 不管对象是否最新, 每次都重新生成, 一般用来改善性能和避免冲突