项目自动化构建工具-make/Makefile
项目自动化构建工具-make/Makefile
概述
make:一个常见的自动化构建工具,用于根据依赖关系自动编译、链接及执行其他任务。Makefile:make所读取和执行的脚本文件,定义了目标、依赖及命令。
作用:通过声明式规则管理源文件、目标文件及其依赖关系,避免手动重复编译,提高效率。
make和makefile的关系
make是可执行程序,运行时会在当前目录寻找名为Makefile、makefile或GNUmakefile的文件。Makefile中定义了:- 目标(target)
- 依赖(dependencies)
- 构建命令(recipes)
执行 make 时:
- 若不指定目标,默认执行第一个目标。
- 若指定目标,如
make clean,则执行对应规则。
隐式规则
如果当前目录下没有makefile,例如以下的文件结构:
1
2
3
4
.
└── main.c
0 directories, 1 file
这时候如果输入命令
1
make main
即使没有makefile文件,make也会按照默认规则去尝试自动构建文件
尝试隐式规则:GNU make 有一套内建规则,例如:
如果目标是 main,并且有一个
main.c文件,那就自动用cc -o main main.c编译。
make自动认为你想用下面的规则构建目标:
1
2
main: main.c
$(CC) $(CFLAGS) -o main main.c
Makefile基本结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 变量定义
CC = gcc
CFLAGS = -Wall -O2
# 默认目标
all: app
# 目标与依赖
app: main.o utils.o
$(CC) $(CFLAGS) -o $@ $^
# 单个文件编译
%.o: %.c
$(CC) $(CFLAGS) -c $<
# 清理
.PHONY: clean
clean:
rm -f *.o app
缩进使用
tab制表符缩进,如果用空格缩进会报错
GNU
make是按照 UNIX 传统设计的,它用 Tab 来明确表示“命令行”。如果你用了空格,它会认为这是其他语法,比如变量或目标定义,不符合格式就会报错。
- 变量:用来简化命令,如
$(CC)、$(CFLAGS)。 - 自动化变量:
$@:目标文件名$<:第一个依赖文件$^:所有依赖文件列表
- 模式规则(Pattern rule):
%.o: %.c适用于所有.c->.o的编译。 - 伪目标(.PHONY):声明
clean不对应实际文件,防止同名文件冲突。伪目标总是被执行。 make通过检测目标和依赖的Modify时间,来判断是否执行指令,.PHONY则不需要对比时间
.PHONY声明的目标,总是会执行,否则会对比文件的时间状态
例如
1
2
3
4
5
6
main: main.c
gcc main.c -o main
.PHONY: clean
clean:
rm -f main
1
2
3
4
5
6
7
8
9
10
11
TARGETS := ex1 ex2
all: $(TARGETS)
%: %.c
gcc -o $@ $<
clean:
rm -f $(TARGETS)
.PHONY: all clean
makefile原理
- 建立依赖关系,谁依赖:于谁,比如说
main依赖main.c - 新起一行,必须以tab开头,如
gcc main.c -o main
常用命令
| 命令 | 含义 |
|---|---|
| make | 执行默认目标(通常是第一个) |
| make all | 执行 all 目标 |
| make clean | 执行清理操作 |
| make -n | 模拟运行,不实际执行命令 |
| make -B | 强制重建所有目标 |
| make -j[N] | 并行执行,多核加速(N 为线程数,省略时使用所有可用核心) |
高级特性
条件判断:1 2 3
ifeq ($(DEBUG),1) CFLAGS += -g endif
- 函数:如
$(shell ...)、$(wildcard ...)。 包含其他 Makefile:
1
include common.mk
- 文件依赖自动生成:配合
gcc -MMD生成.d文件。
本文由作者按照 CC BY 4.0 进行授权