调试第一步:使用 make -n(干运行)查看执行计划
说实话,我见过太多人一遇到 Makefile 报错就慌了。
直接 make 一把梭,然后盯着满屏的错误日志发呆。
其实没必要。你想想看,Makefile 本质上就是个「任务调度器」。它怎么执行、先执行谁、依赖什么文件——这些信息,完全可以在真正运行之前就摸清楚。
怎么摸?用 make -n。
什么是干运行?
make -n 也叫 dry run。说白了就是「只打印,不执行」。
它会把你 Makefile 里所有要执行的命令,一条一条列出来。但不会真的去编译、链接、拷贝文件。就像看剧本,不演出来。
我个人习惯,每次修改 Makefile 之后,第一件事就是跑一遍 make -n。确认执行计划没问题了,再真正去构建。
一个简单的例子
假设你有这样一个 Makefile:
# Makefile
all: hello
hello: main.o utils.o
gcc -o hello main.o utils.o
main.o: main.c
gcc -c main.c
utils.o: utils.c
gcc -c utils.c
clean:
rm -f *.o hello
执行 make -n,你会看到:
$ make -n
gcc -c main.c
gcc -c utils.c
gcc -o hello main.o utils.o
看到了吗?它把三条命令都列出来了。但此时你的目录里,没有任何 .o 文件和 hello 可执行文件。
这就是干运行——只看,不动手。
什么时候用 make -n?
我总结了几种典型场景:
- 刚写完 Makefile:检查依赖关系对不对,目标顺序对不对
- 修改了变量或规则:比如改了
CFLAGS,看看实际编译命令是否生效 - 怀疑有循环依赖:干运行能帮你发现死循环的苗头
- 想了解别人的构建流程:拿到一个陌生项目,先
make -n看看它要干什么
make -p 使用效果更佳。-p 打印所有变量和规则,-n 打印执行计划。两者结合,基本能把 Makefile 的底裤都看穿。
避坑指南:干运行 ≠ 完全安全
嗯,这里要注意。虽然 make -n 不会执行编译命令,但它会执行 Makefile 中的 递归调用。
什么意思?如果你的 Makefile 里有 $(MAKE) -C subdir 这种写法,make -n 会进入子目录继续干运行。这本身没问题。但如果你在子 Makefile 里写了 $(shell ...) 函数——那它真的会执行 shell 命令。
我曾经在一个项目里吃过这个亏。有个同事在 Makefile 里用 $(shell rm -rf /tmp/build) 清理临时文件。我跑 make -n 想看看流程,结果那个 rm 真的被执行了。还好删的是 /tmp 下的目录,要是路径写错了……你懂的。
$(shell ...) 和 $(eval ...) 在 Makefile 解析阶段就会执行,不受 -n 控制。干运行前,最好检查一下有没有这类「副作用」代码。
进阶用法:只查看特定目标的执行计划
有时候你不想看全部,只想看某个目标。比如只想看 clean 会做什么:
$ make -n clean
rm -f *.o hello
这招在调试复杂 Makefile 时特别有用。我经常用它来验证某个规则是否被正确触发。
结合 --debug 选项
光看命令还不够?那就加上 --debug:
$ make -n --debug=v
Reading makefiles...
Updating goal targets....
File 'all' does not exist.
File 'hello' does not exist.
File 'main.o' does not exist.
Must remake target 'main.o'.
gcc -c main.c
File 'utils.o' does not exist.
Must remake target 'utils.o'.
gcc -c utils.c
Must remake target 'hello'.
gcc -o hello main.o utils.o
你看,它把决策过程都打印出来了。哪个文件不存在、为什么需要重新编译、依赖链是怎样的——一目了然。
make -n --debug=v 2>&1 | tee build.log。既看执行计划,又看决策逻辑,还能保存日志。一举三得。
知识体系:干运行的核心逻辑
为了让你更直观地理解,我画了一张流程图:
总结一下
make -n 是我用得最频繁的调试命令,没有之一。
它简单、安全、信息量大。你不需要记住复杂的调试技巧,只需要记住一条:在真正执行之前,先看看它打算干什么。
这就像开车前先看一眼导航。虽然你认识路,但看一眼总没坏处,对吧?
make -n,再 make。养成习惯,能省掉你 80% 的调试时间。
可可精品资料库