基本概念

Makefile最重要的三个概念是目标、依赖和命令,所有的目标都是通过命令来生成,而执行命令的顺序则是由依赖关系确定。基本语法如下所示。

target: dependency
        command

另外一个比较重要的是可以在Makefile中定义变量,定义的方式就是直接用等号赋值,引用变量则要用$(varname)来表示。

基本语法

符号与规则

基本符号

@
如果在命令开头,表示编译时不显示当前命令,这样可以减少不必要的输出
-
如果在命令开头,表示忽略该行的错误
$@
表示规则中的目标
$*
目标主文件名,即去除后缀
$^
表示规则中的所有依赖
$+
所有依赖,未对重复项清理
$<
表示规则中的第一个依赖
$?
时间戳在目标之后的所有依赖
.PHONY: all
all: dep1 dep2 dep3
        @echo "\$$@ = $@"
        @echo "$$^ = $^"
        @echo "$$< = $<"
dep1 dep2 dep3:

要输出$符号就需要用两个,注意$@在Bash shell中有特殊含义,所以必须要转义。

.PHONY
设定假目标,防止发现和目标相同的文件时不去编译
CURDIR
自动设置为当前目录
MAKE
处理Makefile的命令。
MAKECMDGOALS
Makefile构建的目标名。
MAKE_VERSION
版本号
MAKEFILE_LIST
程序make读入的Makefile文件名列表
.VARIABLES
程序make读入的变量列表

精简规则

如下写法表示目标文件的生成规则,避免手动输入大量重复规则。

%.o: %.c
        $(CC) -c $^ -o $@

更局部的一种写法是如下这样,这样可以更好的指定规则作用的范围:

$(OBJECTS): %.o: %.c
        $(CC) -c $^ -o $@

条件判断

条件判断包括ifdefifndefifeqifneq几个,使用必须记住以endif结束。中间可以插入else分支。

变量赋值

基本变量赋值

=
递归赋值,调用时展开。
:=
简单赋值,赋值时展开。
?=
条件赋值,调用时展开,如果已经定义就保持不变。
x = one
y = $(x) two
x = three

a := one
b := $(a) two
a := three

all:
        @echo "x = $(y), a = $(b)"
x = three two, a = one two

除了这里提到的变量定义方法,还有另外两种变量定义方式,一种是通过命令行传递,这种方法会覆盖Makefile中的定义,另外一种方式是通过shell来导出变量,即使用export定义。

高级变量赋值

如下这段代码实现批量后缀替换。

src = a.c b.c c.c
header = $(src:.c=.h)
all:
        @echo "header: $(header)"
header: a.h b.h c.h
overide
用于强制避免变量被覆盖。

函数

字符串处理

strip text
删除首尾空白字符,并合并多个连续空格
first list
取第一个单词
findstring str,text
查询文本中的字符串,没找到返回空
sort list
对列表中单词排序
subst from,to,text
替换文本
patsubst regex,to,text
按规则替换文本
word n,text
取第n个单词
wordlist b,e,text
取索引在[b,e)范围内的单词
words text
统计单词数
filter regex list
从列表中获取匹配的项
filter-out regex list
返回列表中不匹配的项

路径处理

abspath path
将路径名转换为绝对路径名
realpath path
获取真实路径
dir list
获取从列表路径中解析目录名
notdir list
取路径中非目录部分
suffix list
取后缀
basename list
取文件名去除后缀部分
addprefix pre,list
增加前缀
addsuffix suf,list
增加后缀
join list1,list2
将两组单词对应拼接
wildcard regex
获取当前目录中满足规则的文件/目录列表

其他操作

eval text
相当于将文本/变量展开作为Makefile的一部分执行
if cond,then-do[,else-do]
条件执行
foreach var,list,cmd
将列表元素依次赋值给变量并执行命令
call func[,vars]
调用函数
shell cmd
执行命令
origin var
返回变量来源,可以用来测试变量是否定义
value var
不对变量展开,直接返回
warning text
打印警告信息
error text
打印错误信息,会退出执行