Makefile基础
Makefile基础
make解决的是“按依赖关系增量执行命令”的问题。
写 Makefile 的价值,不只是编译 C/C++,更是把项目里的重复构建动作标准化。
1. Makefile 到底在做什么
一句话:声明目标、依赖和命令,让 make 决定何时执行。
基本规则:
1 | target: prerequisites |
关键点:
commands前必须是 Tab,不是空格。- 当依赖比目标“更新”或目标不存在时,命令会执行。
make默认执行文件中的第一个目标。
2. 一个最小示例
1 | app: main.o util.o |
执行:
1 | make # 构建 app |
3. 变量:避免重复
1 | CC := gcc |
常见变量写法:
=递归展开(延迟求值)。:=立即展开(推荐大部分场景用它,行为更可控)。
4. 自动变量:Makefile 的高频语法
在规则命令里最常用 3 个:
$@:当前目标名。$<:第一个依赖(常用于单源文件编译)。$^:全部依赖(去重后)。
示例:
1 | %.o: %.c |
5. 模式规则:批量处理同类文件
1 | SRCS := main.c util.c log.c |
这种写法可扩展性强,新增源文件通常只改 SRCS。
6. 伪目标:不是文件的“动作”
clean、run、test 通常不是实际文件,应该声明成伪目标:
1 |
否则目录里若碰巧出现同名文件,目标可能不会执行。
7. 自动生成头文件依赖(实战很重要)
如果只写 %.o: %.c,头文件变化可能不会触发重编译。
推荐让编译器自动生成依赖文件:
1 | CC := gcc |
这是我最建议保留的基础配置之一。
8. 一个更像项目的模板
目录示例:
1 | project/ |
对应 Makefile:
1 | CC := gcc |
9. 常见坑
- 命令前用了空格而不是 Tab。
- 没有
.PHONY,导致clean不执行。 - 忘了头文件依赖,改了
.h却不重编译。 - 在同一个规则里混用太多 shell 逻辑,维护困难。
10. 我的看法
Makefile 的门槛不在语法,而在“依赖建模”:
- 把目标拆清楚(编译、链接、测试、打包)。
- 让每个目标只做一件事。
- 先可读,再追求花哨技巧。
基础写稳后,你会发现 Makefile 不只是“老工具”,而是工程自动化里非常耐用的一层。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 因受!
评论