项目自动化构建工具-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 进行授权