linux系统编程——Makefile、GDB调试

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功能

  1. 启动程序,可以按照自定义的要求随心所欲的运行程序

  2. 可让被调试的程序在所指定的调置的断点处停住(断点可以是条件表达式)

  3. 当程序被停住时,可以检查此时程序中所发生的事

  4. 可以改变程序,将一个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 (跳出循环)
相关推荐
网络工程小王12 分钟前
【LCEL 链式调用详解】调用篇-2
java·服务器·前端·数据库·人工智能
搬砖的小码农_Sky39 分钟前
Linux操作系统:Ubuntu和Debian的区别
linux·ubuntu·debian
江湖有缘43 分钟前
基于Ubuntu系统Docker部署Note Mark:从安装到配置全流程
linux·ubuntu·docker
xhbh6661 小时前
路由端口转发常见应用场景有哪些?有什么?
服务器·ip·端口转发·ip地址·流量转发·建站
前端之虎陈随易1 小时前
2年没用Nodejs了,Bun很香
linux·前端·javascript·vue.js·typescript
宁小法1 小时前
Linux批量删除文件
linux·服务器·批量·删除文件
AC赳赳老秦2 小时前
财务报销自动化:用 OpenClaw 自动识别发票信息、填写报销单、校验报销规则,减少手工操作
运维·网络·eclipse·github·visual studio·deepseek·openclaw
05候补工程师2 小时前
深度解构 ROS 2:如何手动调通 Nav2 A* 路径规划引擎
linux·人工智能·经验分享·算法·机器人
zhangfeng11332 小时前
适合 5人以内小团队的Git 工作流 + Code Review + 自动化部署方案 FastAdmin +linunx服务器宝塔系统 外包项目 —
服务器·git·自动化·php·代码复审
北冥湖畔的燕雀3 小时前
Linux线程编程核心指南
linux·服务器·网络