一、make 与 Makefile 的关系
在 Linux 开发里,项目一旦从几个文件扩展到几十个、上百个源文件,手动敲 gcc 命令就会变得很吃力:编译参数容易漏,依赖关系也不好维护。make 和 Makefile 正是为了解决这类问题而生的。
make是命令行工具,负责读取规则并决定哪些文件需要重新构建。Makefile是规则文件,make会按照它里面写好的依赖关系和执行命令去工作。
简单理解就是:make 负责执行,Makefile 负责描述'怎么做'。
二、Makefile 的基本写法
写 Makefile 时,最核心的是把'目标、依赖、方法'这三件事讲清楚。
- 目标:最终要生成什么,比如可执行文件
Hello。 - 依赖:目标由哪些文件生成,通常是
.c、.h文件。 - 方法:具体怎么生成目标,一般就是编译命令。
一个典型的规则长这样:
Hello: main.o func.o
gcc -o Hello main.o func.o
main.o: main.c
gcc -c main.c
func.o: func.c
gcc -c func.c
.PHONY: clean
clean:
rm -f *.o Hello
这里有几个地方很容易踩坑。
1. 命令前面必须是 Tab
Makefile 里目标下面的执行命令前面不是空格,而是 Tab。这一点非常关键,很多人第一次写都会卡在这里。
2. make 是按时间判断是否需要重建
make 不会每次都无脑重编译,它会比较文件的修改时间:如果依赖文件比目标文件更新,就说明目标需要重新生成。
这也是为什么你执行过一次 make 之后,再次执行时可能提示'没有需要更新的目标'。如果你改动了源文件,却没有触发重新编译,可以用 touch 刷新文件时间戳,或者直接修改源文件内容。
3. .PHONY 让伪目标更可靠
像 clean 这种目标,本质上不是一个真实文件。为了避免目录里刚好有个同名文件导致执行异常,通常会写成:
.PHONY: clean
这样 make clean 就会始终执行,不受同名文件影响。
4. 常用自动变量
Makefile 里有几个很实用的自动变量:
$@:目标文件名$^:所有依赖文件$<:第一个依赖文件
例如:
gcc -o


