Makefile
makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile文件就像一个shell脚本一样,也可以执行操作系统的命令。
自动化编译,只要一个make命令,整个工程完全自动编译。
规则
一个makefile文件中可以有一个或者多个规则
目标 ... : 依赖 ...
命令(shell命令)
...
目标:最终要生成的文件(伪目标除外)
依赖:生成目标所需要的文件或是目标
命令:通过执行命令对依赖操作生成目标(命令前必须Tab缩进)
Makefile中的其它规则一般都是为第一条规则服务的
命令在执行之前,需要先检查规则中的依赖是否存在
检查更新,在执行规则中的命令时,会比较目标和依赖文件的时间
如果依赖的时间比目标的时间晚,需要重新生成目标
如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行。
变量
自定义变量
变量名=变量值 var=hello $(var)
预定义变量
AR:归档维护程序的名称,默认值为ar app:main.c a.c b.c
CC:C编译器的名称,默认值为cc gcc -c main.c a.c b.c
CXX:C++编译器的名称,默认值为g++
$@:目标的完整名称 #自动变量只能在规则的命令中使用
$<:第一个依赖文件的名称 app:main.c a.c b.c
$^:所有的依赖文件 $(CC) -c $^ -o $@
获取变量的值
$(变量名)
模式匹配
%.o:%.c
-%:通配符,匹配一个字符串
-两个%匹配的是同一个字符串
%.o:%.c
gcc -c $< -o $@
函数
$(wildcard PATTERN...)
功能:获取指定目录下指定类型的文件列表
参数:PATTERN指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔
返回:得到的若干个文件的文件列表,文件名之间使用空格间隔
示例:
$(wildcard *.c ./sub/*.c)
返回值格式:a.c b.c c.c d.c e.c f.c
$(patsubst <pattern>,<replacement>,<text>)
功能:查找<text>中的单词(单词以"空格"、"Tab"或"回车""换行"分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换
<pattern>可以包括通配符'%',表示任意长度的字串。如果<replacement>中也包含'%',那么,<replacement>中的这个'%'将是<pattern>中的那个%所代表的字串。
返回:函数返回被替换过后的字符串
示例:
$(patsubst %.c, %.o, x.c bar.c)
返回值格式:x.o bar.o
示例
三个文件 保存函数的声明(.h文件),函数的实现(.c文件),主函数文件
编写makefile
processOn:main.c mytest.c
gcc main.c mytest.c -o processOn
.PHONY:clean
clean:
rm -f processOn
用上变量里的特殊符号的话就变成了
processOn:main.c mytest.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f processOn
生成一个可执行文件processOn,它依赖于main.c和mytest.c,第二行是它的依赖方法。此时我们使用make命令,则目录下会自动生成一个可执行文件processOn.
而工程也是需要被清理的。像clean这种没有被第一个目标文件直接或者间接关联,那么它后面的命令就不会被执行,所以我们可以显式要make执行,即make clean,以此来一次性清除所有生成的目标文件,以便于重新编译。
.PHONY是一个关键字,被该关键字修饰的对象是一个伪目标,该目标总是被执行,不是拿时间来作为新旧文件的对比。所以一般将clean设置成伪目标。
GDB调试
GDB是由GNU软件系统社区提供的调试工具,同GCC配套组成一套完整的开发环境,
GDB功能
-
启动程序,可以按照自定义的要求随心所欲的运行程序
-
可让被调试的程序在所指定的调置的断点处停住(断点可以是条件表达式)
-
当程序被停住时,可以检查此时程序中所发生的事
-
可以改变程序,将一个BUG产生的影响修正从而测试其他BUG
准备工作
在为调试而编译时,我们会()关掉编译器的优化选项('-o'),并打开调试选项('-g')。另外,'-Wall'在尽量不影响程序行为的情况下选项打开所有warning,也可以发现许多问题,避免一些不必要的BUG
gcc -g -Wall program.c -o program
'-g'选项的作用是在可执行文件中加入源代码的信息,比如可执行文件中第几条机器指令对应源代码的第几行,但并不是把整个源文件嵌入到可执行文件中,所以在调试时必须保证gdb能找到源文件。
GBD命令
启动和退出
gdb 可执行程序
quit
给程序设置参数/获取设置参数
set args 10 20
show args
GDB 使用帮助
help
查看当前文件代码
list/l (从默认位置显示)
list/l 行号 (从指定的行显示)
list/l 函数名 (从指定的函数显示)
查看非当前文件代码
list/l 文件名:行号
list/l 文件名:函数名
设置显示的行数
show list/listsize
set list/listsize 行数
示例
# test.c一个示例源文件
gcc test.c -o test -g
# 生成一个test
# 打开gdb
gdb test
# 进入到gdb里面
# 传入一些参数
set args 10 20
# 获取传入的参数
show args
# 退出gdb
quit
list # 查看代码文件,注意只有前面加-g才可以
GDB断点操作
设置断点
b/break 行号
b/break 函数名
b/break 文件名:行号
b/break 文件名:函数
查看断点
i/info b/break
删除断点
d/del/delete 断点编号
设置断点无效
dis/disable 断点编号
设置断点生效
ena/enable 断点编号
设置条件断点
b/break 10 if i==5
示例
# 第九行打断点
break 9
# 查看断点信息
info break
GDB调试命令
运行GDB程序
start(程序停在第一行)
run(遇到断点才停)
继续运行,到下一个断点停
c/continue
向下执行一行代码(不会进入函数体)
n/next
变量操作
p/print 变量名(打印变量值)
ptype 变量名(打印变量类型)
向下单步调试(遇到函数进入函数体)
s/step
finish (跳出函数体)
自动变量操作
display num (自动打印指定变量的值)
i/info display
undisplay 编号
其他操作
set var 变量名=变量值
until (跳出循环)