Linux开发三件套:make、git、gdb 入门指南

一、make和makefile

1. 什么是 make 和 Makefile?

  • make:一个命令工具,用于解释 Makefile 中的指令。

  • Makefile:一个文件,定义了项目的编译规则、依赖关系和命令。

2. 基本使用示例

bash 复制代码
myproc: myproc.c
    gcc -o myproc myproc.c

.PHONY: clean
clean:
    rm -f myproc
  • myproc 是目标文件,依赖于 myproc.c

  • gcc -o myproc myproc.c 是生成目标的命令

  • clean 用于清理项目,.PHONY 表示它不生成文件,总是执行

3. make 的工作流程

  1. 在当前目录下查找 Makefile 或 makefile

  2. 找到第一个目标文件(如 myproc)

  3. 检查目标文件是否存在或其依赖是否更新

  4. 递归查找依赖链,直到所有依赖都被处理

  5. 执行相应命令生成最终目标

如果某个依赖文件不存在,make 会报错并退出。

4. .PHONY 的作用

  • 被 .PHONY 修饰的目标,总是被执行,不受文件时间戳影响。

  • 典型应用:clean、test 等辅助操作。

bash 复制代码
.PHONY: clean
clean:
    rm -f *.o *.i *.s myproc

5. Makefile 的推导过程(多文件编译)

bash 复制代码
myproc: myproc.o
    gcc myproc.o -o myproc
myproc.o: myproc.s
    gcc -c myproc.s -o myproc.o
myproc.s: myproc.i
    gcc -S myproc.i -o myproc.s
myproc.i: myproc.c
    gcc -E myproc.c -o myproc.i

这就是一个完整的从 .c 到可执行文件的推导链:

.c → .i → .s → .o → 可执行文件

6. Makefile 高级语法扩展

bash 复制代码
BIN = proc.exe         # 定义变量:最终生成的可执行文件名
CC = gcc               # 定义变量:指定编译器为 gcc
SRC = $(wildcard *.c)  # 使用 wildcard 函数:获取当前目录下所有 .c 文件,保存到 SRC 变量
OBJ = $(SRC:.c=.o)     # 模式替换:将 SRC 中所有 .c 后缀替换为 .o,生成目标文件列表
LFLAGS = -o            # 定义变量:链接阶段的编译选项(-o 指定输出文件名)
FLAGS = -c             # 定义变量:编译阶段的选项(-c 表示只编译不链接)
RM = rm -f             # 定义变量:删除命令,-f 表示强制删除不提示

$(BIN): $(OBJ)         # 规则:proc.exe 依赖于所有 .o 文件
    @$(CC) $(LFLAGS) $@ $^     # 执行链接:gcc -o proc.exe 所有.o文件
    @echo "Linking ... $^ to $@"   # 输出链接信息,@ 表示不显示命令本身

%.o: %.c               # 静态模式规则:所有 .o 文件依赖于同名的 .c 文件
    @$(CC) $(FLAGS) $<         # 执行编译:gcc -c 对应的.c文件
    @echo "Compiling ... $< to $@"   # 输出编译信息

.PHONY: clean          # 声明伪目标:clean 不是一个真实文件
clean:                 # 清理规则
    $(RM) $(OBJ) $(BIN)         # 删除所有 .o 文件和可执行文件

.PHONY: test           # 声明伪目标:test 也不是真实文件
test:                  # 测试规则
    @echo $(SRC)       # 打印所有 .c 源文件
    @echo $(OBJ)       # 打印所有 .o 目标文件
语法 说明 示例
= 定义变量 BIN = proc.exe
$(变量名) 引用变量 $(CC)
$(wildcard 模式) 查找匹配的文件 $(wildcard *.c) → 返回所有.c文件
$(变量:.旧后缀=.新后缀) 后缀替换 $(SRC:.c=.o) → 将.c换成.o
% 通配符,匹配任意字符串 %.o: %.c → 所有.o依赖同名.c
$@ 自动变量:目标文件名 在规则中代表目标
$^ 自动变量:所有依赖文件 在规则中代表所有依赖
$< 自动变量:第一个依赖文件 在规则中代表第一个依赖
@ 命令前缀:静默执行 @echo → 不显示echo命令本身
.PHONY 声明伪目标 防止与同名文件冲突

二、git提交的流程

bash 复制代码
# 1. 初始化仓库或克隆现有项目
git init
# 或
git clone <仓库地址>

# 2. 编辑文件后,查看变更
git status

# 3. 将文件添加到暂存区(准备提交)
git add <文件名>   # 添加单个文件
git add .         # 添加所有变更

# 4. 提交到本地仓库,并附上说明
git commit -m "修改了某个功能"

# 5. 推送到远程仓库(如GitHub、GitLab)
git push origin main

# 6. 拉取他人最新提交
git pull origin main

三、gbd/cgbd使用

1. 调试版本的编译

默认 gcc 编译出的程序是 release 模式 ,不支持调试。必须加上 -g 选项生成 debug 版本:

bash 复制代码
# 不支持调试(默认)
gcc mycmd.c -o mycmd

# 支持调试(debug 模式)
gcc mycmd.c -o mycmd -g

使用 file mycmd 查看是否包含 debug_info。

2. GDB 常用命令速查表

命令 作用 示例
l / list 显示源代码 l main
b / break 设置断点 b 10 或 b main
info b / info breakpoints 查看所有断点信息 info b
d / delete 删除所有断点 delete
d 断点编号 删除指定编号的断点 delete 2
disable 禁用所有断点 disable
disable 断点编号 禁用指定编号的断点 disable 1
enable 启用所有断点 enable
enable 断点编号 启用指定编号的断点 enable 1
r / run 开始执行程序 run
n / next 单步执行(不进入函数) next
s / step 单步执行(进入函数) step
c / continue 继续执行到下一断点 continue
p / print 打印变量或表达式 p result
set var 修改变量值 set var flag=1
watch 监视变量变化 watch result
finish 执行到当前函数返回 finish
until 执行到指定行 until 14
info locals 查看当前局部变量 info locals
bt / backtrace 查看函数调用栈 backtrace
quit 退出 GDB quit

3. 高级调试技巧(加餐)

1. 使用 cgdb 提升体验
bash 复制代码
# Ubuntu
sudo apt install cgdb

# CentOS
sudo yum install cgdb

cgdb 兼顾 GDB 的命令行能力 + 代码窗口,调试更直观。

2. watch:监视变量变化
bash 复制代码
watch result

当 result 被修改时,GDB 会自动暂停并提示旧值/新值,非常适合定位"不该变却变了"的变量。

3. set var:动态修改变量,快速验证问题
bash 复制代码
p flag   # 查看当前值
set var flag=1
4. 条件断点

条件断点允许我们只在某个条件满足时才触发断点,非常适合调试循环体或频繁调用的函数。

1. 添加条件断点

语法格式:

bash 复制代码
break 行号 if 条件表达式
break 函数名 if 条件表达式

实战示例:

假设我们想在 Sum 函数的第 9 行(循环体内部)设置断点,并且只有当 i == 30 时才暂停:

bash 复制代码
(gdb) b 9 if i == 30
Breakpoint 2 at 0x555555555156: file mycmd.c, line 9.

2. 查看条件断点

使用 info b 可以看到条件断点的特殊标记:

bash 复制代码
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555551c3 in main at mycmd.c:20
        breakpoint already hit 1 time
2       breakpoint     keep y   0x0000555555555156 in Sum at mycmd.c:9
        stop only if i == 30          # ← 条件断点的标识

可以看到,断点 2 后面多了 stop only if i == 30,表示这是一个条件断点。

3. 条件断点的执行效果

当程序运行时,GDB 会自动检查条件:

  • 条件为 false(如 i=1,2,3...29)→ 断点不触发,程序继续执行

  • 条件为 true(如 i=30)→ 断点触发,程序暂停

这样我们就不需要手动按几百次 n 来追踪循环,直接精准定位到 i == 30 的时刻。

4. 其他条件断点操作

bash 复制代码
# 为现有断点添加条件
condition 2 i == 50

# 修改已有断点的条件
condition 2 i == 100

# 删除断点的条件(变为普通断点)
condition 2

# 设置条件断点的另一种写法
break mycmd.c:9 if i == 30
相关推荐
echome8881 小时前
Linux 定时任务:crontab 写法与常见失效原因
linux·运维·网络·定时任务·crontab
从琳开始9891 小时前
从Socket到TCP回显服务器:Java网络编程完整指南
java·服务器·网络·tcp/ip·java-ee
云-缩影2 小时前
做微信小程序,自建服务器还是用云托管:技术选型对比
服务器·微信小程序·小程序
分布式存储与RustFS2 小时前
可观测性数据落进对象存储:Proscia 案例拆解与 ClickHouse 自托管配置
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
Sw1zzle2 小时前
Go入门(零):Linux Ubuntu 22.04 安装 Go
linux·ubuntu·golang
device_Any2 小时前
接口文档写着三个字段,接口返回了五个
android·java·linux
土星云SaturnCloud2 小时前
基于边缘计算与AI视觉的智慧街面治理方案:架构设计与场景落地
服务器·人工智能·ai·边缘计算
无足鸟ICT2 小时前
【RHCA+】dstat命令(监控系统资源)
linux·服务器
方便面不加香菜2 小时前
Docker Image-- 镜像命令详解与使用示例
运维·docker·容器