Makefile 学习笔记
1. 什么是 Makefile?
- Makefile 是一个自动化构建工具(如 gcc/g++ 编译 C/C++ 项目)用的脚本文件。
- 它定义了如何编译和链接程序,自动化重复的构建流程。
- 配合
make
命令使用。
2. Makefile 的基本结构
目标: 依赖
[TAB] 命令
- 目标:最终要生成的文件(如可执行文件、.o 文件等)。
- 依赖:生成目标所需的文件或目标。
- 命令:生成目标所需执行的 shell 命令(前面必须是 TAB)。
示例
main.o: main.c
gcc -c main.c
3. 常用变量
- 变量定义:
变量名 = 值
- 使用变量:
$(变量名)
CC = gcc
CFLAGS = -g -Wall
main.o: main.c
$(CC) $(CFLAGS) -c main.c
4. 伪目标(PHONY)
- 用于定义非文件目标,如
clean
。 - 避免与同名文件冲突。
.PHONY: clean
clean:
rm -f *.o main
5. 自动化变量
$@
:目标名$<
:第一个依赖$^
:所有依赖
main.o: main.c
$(CC) -c $< -o $@
6. 通配符与自动推导
%.o: %.c
:所有 .c 文件自动编译为 .o 文件
%.o: %.c
$(CC) -c $< -o $@
7. 一个完整的示例
假设有 main.c、foo.c、bar.c:
CC = gcc
CFLAGS = -g -Wall
OBJS = main.o foo.o bar.o
main: $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
.PHONY: clean
clean:
rm -f *.o main
8. 常见用法
- 多文件编译:自动化管理依赖,减少手动编译。
- 分模块管理:大型项目可用子 Makefile。
- 自动清理:
make clean
一键清理中间文件。 - 条件编译:通过变量切换 Debug/Release。
9. 常用命令
make
:默认执行第一个目标make 目标名
:只执行指定目标make clean
:清理编译生成的文件
10. 常见问题
- 命令前必须是 TAB,不是空格!
- 变量引用要加
$()
。 - 依赖关系要写全,避免漏编译。
11. 子 Makefile 用法
在大型项目中,常用子 Makefile(子目录 Makefile)进行分模块管理。每个模块/子目录有自己的 Makefile,主目录的 Makefile 通过调用子目录的 Makefile 实现整体编译和管理,让项目结构更清晰、维护更方便。
1. 目录结构示例
project/
├── main.c
├── Makefile # 主 Makefile
├── module1/
│ ├── foo.c
│ └── Makefile # module1 的子 Makefile
└── module2/
├── bar.c
└── Makefile # module2 的子 Makefile
2. 主 Makefile 示例
.PHONY: all clean
all:
$(MAKE) -C module1
$(MAKE) -C module2
gcc main.c module1/foo.o module2/bar.o -o main
clean:
$(MAKE) -C module1 clean
$(MAKE) -C module2 clean
rm -f main
$(MAKE) -C 目录
表示进入指定目录执行该目录下的 Makefile。all
目标会先编译子目录,再编译主程序。clean
目标会递归清理所有子目录和主目录的生成文件。
3. 子目录 Makefile 示例(如 module1/Makefile)
foo.o: foo.c
gcc -c foo.c -o foo.o
.PHONY: clean
clean:
rm -f foo.o
module2/Makefile 类似。
4. 建议
- 每个模块/子目录维护自己的 Makefile,便于独立开发和调试。
- 主 Makefile 统一调度,方便一键编译和清理整个项目。
- 推荐用
$(MAKE) -C
,而不是直接cd
,这样更安全、兼容性更好。