Makefile 基础
Makefile 是一个用于自动化构建和管理项目的工具,通常用于编译源代码、链接目标文件以及生成最终的可执行文件或库。它基于 Make 工具,通过定义规则和依赖关系来高效地管理构建过程。
.s
和 .o
文件是两种常见的中间文件,它们分别代表 汇编代码文件 和 目标文件
对于庞大的项目,Makefile对.o文件进行链接。
Makefile 的基本语法
命令必须以 Tab 开头,
(1)规则(Rule)结构
1 | target: prerequisites |
- target:生成的目标文件(如
main.o
)或伪目标(如clean
)。 - prerequisites:依赖文件(如
main.c
)。 - recipe:执行的命令(必须以 Tab 开头)。
示例
1 | hello: hello.c |
(2)变量(Variable)
1 | CC = gcc |
(3)伪目标(Phony Target)
用于定义非文件任务(如清理):
1 |
|
进阶特性
(1)自动变量(Automatic Variables)
变量 | 说明 |
---|---|
$@ |
当前目标(如 hello )。 |
$< |
第一个依赖文件(如 hello.c )。 |
$^ |
所有依赖文件。 |
$? |
比目标更新的依赖文件。 |
示例
1 | hello: hello.o utils.o |
(2)模式规则(Pattern Rules)
通用规则编译所有 .c
文件,使用%
符号:
1 | %.o: %.c |
(3)变量(Value)
变量的赋值方式
(1)递归展开 (=
)
延迟求值:变量在引用时才会展开(可能受后续赋值影响)。
示例:
1
2VAR1 = $(VAR2) # VAR1 的值会随 VAR2 的变化而改变
VAR2 = value
(2)直接展开 (:=
)
立即求值:变量在定义时展开(后续赋值不影响已定义的值)。
示例:
1
2
3
4
5
6
7
8VAR1 := $(VAR2) # VAR1 的值固定为定义时的 VAR2
VAR2 := value
a:=abc
b:=bcd
all:
@echo $(A) #若不想输出命令行,前面加入@
echo $(B)
(3)条件赋值 (?=
)
仅在变量未定义时赋值。
示例:
1
VAR ?= default_value # 如果 VAR 未定义,则赋值为 default_value
(4)追加赋值 (+=
)
向变量追加内容。
示例:
1
2CFLAGS = -Wall
CFLAGS += -O2 # CFLAGS 变为 "-Wall -O2"
(4)函数(Functions)
常用函数:
wildcard
:匹配文件模式。
- 展开当前目录下匹配
pattern
的文件名(支持*
、?
等通配符),取出存在的文件
1 | SRC = $(wildcard *.c) #*.c:通配符模式,表示所有以 .c 结尾的文件 |
patsubst
:替换文件名后缀。
1 | OBJ = $(patsubst %.c,%.o,$(SRC)) #从SRC列表中取出每一个值如果符合%.c*(pattern)就替换 |
(foreach var,list,text)
:循环遍历 list
,将每次迭代的值赋给 var
,并展开 text
。
1 | A = a, b, c |
(filter pattern...,text)
和 $(filter-out pattern...,text)
filter
:保留text
中匹配pattern
的单词。filter-out
:排除匹配pattern
的单词。
1 | C = a b c d/ |
当文件有许多.h文件的依赖时
1 | gcc -M c.o #打印出依赖 |
1 | objs = a.o b.o c.o |
其他
在使用make [目标]
编译时,会执行对应的目标下的命令,若无[目标]
则默认运行第一个目标下的命令。
1 | hello: hello.o utils.o |
如果项目目录中意外存在一个名为 clean
的文件(或文件夹),make
会认为 clean
是一个需要构建的 文件目标,而非伪目标。可以将clean
定义为假想目标。
1 |