Makefile Cheatsheet - Build Automation
Makefile 是 C/C++ 项目最常用的构建工具,也广泛用于自动化任务。按语法分类整理常用写法。
Back to SysOps变量与赋值 6
CC = gcc递归展开变量,引用时才展开(可能有副作用)
CC := gcc简单展开变量,定义时就展开(推荐)
CC ?= gcc条件赋值,变量未定义时才赋值
CFLAGS += -Wall追加值到变量末尾
export PATH := /opt/bin:$(PATH)导出变量到子进程环境
$(CC) 或 ${CC}引用变量,圆括号与花括号均可
自动变量 7
$@当前目标名
$<第一个依赖
$^所有依赖(去重)
$+所有依赖(含重复)
$*模式规则中 % 匹配的部分
$?比目标更新的依赖列表
$(@D) / $(@F)目标的目录名 / 文件名部分
规则与目标 5
target: deps\n\trecipe基本规则:目标、依赖和配方
.PHONY: clean install声明伪目标,避免与同名文件冲突
all: prog1 prog2默认目标(第一个非点开头的目标)
clean:\n\trm -f *.o $(TARGET)清理目标文件
install: target\n\tcp target /usr/local/bin安装目标到系统路径
模式规则 5
%.o: %.c\n\t$(CC) -c $< -o $@通配规则:所有 .o 由同名 .c 生成
%.o: %.c $(HDRS)为模式规则添加额外依赖(头文件)
$(OBJDIR)/%.o: $(SRCDIR)/%.c跨目录的模式规则
OBJS := $(SRCS:.c=.o)变量替换引用,批量改后缀
$(OBJS): obj/%.o: src/%.c静态模式规则,显式指定目标列表
内置函数 8
$(wildcard *.c)展开通配符,获取匹配的文件列表
$(patsubst %.c,%.o,$(SRCS))模式替换:把 .c 后缀换成 .o
$(filter %.c %.h,$(SRCS))过滤出匹配模式的单词
$(filter-out %.test,$(SRCS))反向过滤,排除匹配项
$(strip $(string))去除字符串首尾空格
$(shell date +%Y)执行 shell 命令并返回输出
$(subst from,to,text)文本替换(非模式,直接匹配)
$(foreach var,list,text)遍历列表生成文本
条件判断 5
ifeq ($(OS),Windows_NT)\n...\nendif相等判断
ifneq ($(CC),gcc)\n...\nendif不等判断
ifdef DEBUG\nCFLAGS += -g\nendif变量已定义则执行
ifndef RELEASE\n...\nelse\n...\nendif带 else 的条件分支
$(if $(DEBUG),-g,-O2)条件函数:成立返回第二参数,否则第三参数
实用示例 6
SRCS := $(wildcard src/*.c)\nOBJS := $(SRCS:.c=.o)自动收集源文件并生成目标列表
include config.mk包含其他 Makefile,适合拆分配置
.DEFAULT_GOAL := install显式设置默认目标
vpath %.c src:src2为指定后缀设置搜索目录
make -j4并行构建,4 个任务同时跑
make CFLAGS="-O2 -g"命令行覆盖变量(优先级最高)
💡 Tips
- Makefile 的配方行必须以 Tab 开头,不能用空格,这是最常见的错误。
- .PHONY 声明的目标不会检查同名文件是否存在,适合 clean、install 等操作。
- $@ 代表目标,$< 代表第一个依赖,$^ 代表所有依赖,这三个自动变量最常用。
- := 是立即展开,= 是延迟展开;复杂 Makefile 中推荐用 := 避免递归副作用。
- include other.mk 可以引入其他 Makefile,适合大型项目拆分配置。
- 命令行变量会覆盖 Makefile 中的赋值,用 override 关键字可防止被覆盖。