title: GNU Make手册-构建自动化指南
original_path: /田浩然上传的资料/电子书/Linux/make.pdf
file_size: 1.07 MB
total_pages: 188
processed_date: 2026-09-29
method: PDF文本提取
status: done
GNU Make 手册 - 构建自动化指南
GNU Make 是 Unix/Linux 系统上最常用的构建自动化工具,由 Richard Stallman 等人开发。
一、核心概念
1.1 什么是 Make
Make 是一个用于管理程序重新编译的工具。它根据 Makefile 中的规则,自动判断哪些文件需要重新编译,并执行相应的命令。
1.2 Makefile 基本结构
目标: 依赖条件
命令
示例:
all: main.o utils.o
gcc -o program main.o utils.o
main.o: main.c
gcc -c main.c
clean:
rm -f *.o program
1.3 基本规则要素
| 要素 | 说明 |
|---|
| 目标 | 要生成的文件(或伪目标) |
| 依赖 | 生成目标所需的文件 |
| 命令 | 执行的具体操作(必须以Tab开头) |
二、变量系统
2.1 变量赋值类型
| 运算符 | 说明 | 示例 |
|---|
= | 递归展开 | CC = gcc |
:= | 简单赋值 | CC := gcc |
?= | 条件赋值(未定义时) | CC ?= gcc |
+= | 追加 | CFLAGS += -Wall |
2.2 变量引用
CC = gcc
CFLAGS = -Wall -O2
program: main.o
$(CC) $(CFLAGS) -o program main.o
2.3 自动变量
| 变量 | 说明 |
|---|
$@ | 目标文件名 |
$< | 第一个依赖文件名 |
$^ | 所有依赖文件名(去重) |
$* | 目标文件名中去掉后缀 |
三、模式规则
3.1 基本语法
%.o: %.c
$(CC) -c $< -o $@
这表示:任何 .o 文件都由对应的 .c 文件生成。
3.2 静态模式规则
objects = foo.o bar.o
$(objects): %.o: %.c
$(CC) -c $< -o $@
四、条件与函数
4.1 条件指令
ifdef CC
CFLAGS += -std=c99
endif
ifeq ($(OS),Linux)
LDFLAGS += -lnsl
endif
4.2 常用函数
| 函数 | 说明 |
|---|
$(wildcard *.c) | 匹配文件 |
$(subst from,to,text) | 文本替换 |
$(patsubst %.c,%.o,$(SRC)) | 模式替换 |
$(dir $^) | 提取目录 |
$(notdir $^) | 提取文件名 |
五、Phony 目标
5.1 定义伪目标
.PHONY: clean all install
clean:
rm -f *.o program
install: program
cp program /usr/local/bin/
5.2 作用
六、隐式规则
6.1 内置规则
Make 预定义了常见的编译规则:
| 文件类型 | 自动规则 |
|---|
.c → .o | gcc -c |
.cc → .o | g++ -c |
.o → 可执行文件 | ld |
.s → .o | as |
6.2 禁用隐式规则
.c.o:
@echo "This rule is disabled"
七、高级特性
7.1 包含其他文件
include common.mk
include config.mk
7.2 VPATH 搜索路径
VPATH = src:include
# 或
vpath %.c src
vpath %.h include
7.3 递归调用 Make
subdirs = lib1 lib2 lib3
subdirs-target:
for d in $(subdirs); do $(MAKE) -C $$d; done
7.4 并行执行
make -j4 # 使用4个并行任务
make -j # 使用尽可能多的并行任务
八、最佳实践
8.1 变量命名
- 用户变量使用小写
- 环境变量和大写变量保持原样
- 避免覆盖 Make 内置变量
8.2 Makefile 组织
# 1. 配置文件(可被include)
include config.mk
# 2. 变量定义
CC = gcc
CFLAGS = -Wall -O2
SRC_DIR = src
OBJ_DIR = obj
# 3. 源文件列表
SRC = $(wildcard $(SRC_DIR)/*.c)
OBJ = $(patsubst %.c,$(OBJ_DIR)/%.o,$(SRC))
# 4. 规则
all: program
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
mkdir -p $(OBJ_DIR)
$(CC) $(CFLAGS) -c $< -o $@
program: $(OBJ)
$(CC) -o $@ $^
clean:
rm -rf $(OBJ_DIR) program
8.3 常用目标
.PHONY: all clean install test
all: program
test: program
./run_tests.sh
install: program
install -m 755 program /usr/local/bin/
九、调试技巧
9.1 打印 Makefile 解析过程
make -p > makefile.out
9.2 强制重新执行命令
make --always-make
# 或
make BINARY=dummy
9.3 详细输出
make --trace
make -d # 更详细的调试信息
十、与其他构建系统对比
| 特性 | Make | CMake | Meson |
|---|
| 学习曲线 | 中等 | 较陡 | 平缓 |
| 跨平台 | 一般 | 优秀 | 优秀 |
| 社区规模 | 最大 | 大 | 中等 |
| 适合项目 | 小型到中型 | 大型跨平台 | 现代项目 |
关键要点总结
- Makefile 是声明式的 - 描述”做什么”而非”怎么做”
- 变量延迟求值 -
= 在引用时求值,:~ 在定义时求值
- 自动变量简化规则 -
$@, $<, $^ 是常用工具
- 模式规则提高复用 -
%.o: %.c 模式通用性强
- Phony 目标防冲突 - 始终为伪目标添加
.PHONY
- 并行加速构建 -
-j 参数显著提升大型项目编译速度