Makefile 杂记¶
约 1115 个字 128 行代码 预计阅读时间 6 分钟
- GNU make 官方文档:GNU make
基础¶
makefile 规则¶
- makefile 的文件名默认为
Makefile或makefile,如果文件名不是这两者,那么需要使用make -f filename来指定文件名。 -
makefile 由一系列规则组成,每个规则由三部分组成:目标、依赖和命令。大体结构如下:
- 依赖可以是另一条规则的目标名,如果依赖是目标名,那么 make 会先查看这个依赖是否存在或是否需要更新,如果不存在或需要更新,那么会先执行这个依赖的规则。
-
命令必须以
Tab开头,不能用空格代替。
Example
假设我们已经有了 a.txt b.txt 和 c.txt 三个文件,makefile 内容如下:
- 当这个 makefile 被执行时,默认将第一条规则作为整个 makefile 的总目标,即生成
x.txt文件 x.txt依赖于m.txt,所以会先执行第二条规则来创建/更新m.txt文件
make 通过文件的创建和修改时间来判断是否应该更新一个目标文件。
还是上面那个文本文件的例子,
- 当我们修改
c.txt时,会使c.txt的时间戳比x.txt更晚- makefile 意识到
x.txt需要被重新生成,因此执行cat m.txt c.txt > x.txt来生成新的x.txt - 而由于
m.txt与c.txt无关,所以c.txt的修改不会影响m.txt
- makefile 意识到
- 当我们修改
a.txt时,a.txt的时间戳比m.txt更晚- makefile 首先查看
x.txt的依赖中是否需要更新 - 它发现
c.txt不需要更新,但m.txt的依赖a.txt已经被更新了,所以m.txt也需要被更新 - 因此 makefile 会先执行
cat a.txt b.txt > m.txt来更新m.txt,然后再执行cat m.txt c.txt > x.txt来更新x.txt
- makefile 首先查看
伪目标¶
伪目标(Phony Target)是一种特殊的目标,它不是一个文件,而是一个标签。伪目标的作用执行一些特殊的操作,例如清理工程、生成文档等。
当我们想要删除已经生成的文件时,可以使用伪目标。
通常来说,clean、install、uninstall 等都是约定俗成的伪目标名称,这时候也可以不使用 .PHONY 来声明伪目标(除非这个目录下真的有一个文件叫做 clean)。
其他¶
-
控制打印
@:在命令前加上@可以阻止 make 打印命令本身,只打印命令的输出。 -
忽略错误:在命令前加上
-可以忽略命令执行的错误。- 当我们执行的命令遇到错误时会让 makefile 停止执行,但有时候我们希望即使命令执行失败也继续执行后续命令,这时候可以使用
-来忽略错误。
- 当我们执行的命令遇到错误时会让 makefile 停止执行,但有时候我们希望即使命令执行失败也继续执行后续命令,这时候可以使用
变量¶
给变量赋值¶
-
=:递归赋值,在使用变量时才会递归地展开变量 -
:=:简单赋值,在赋值时就展开变量 -
+=:追加赋值,用于向已经定义的变量添加文本 -
?=:条件赋值,只有当变量未定义时才会赋值
使用变量¶
使用变量时用 ${} 或 $()。
自动变量¶
$@:表示规则中的目标文件名$<:表示规则中的第一个依赖文件名$^:表示规则中的所有依赖文件名$?:表示规则中所有比目标文件更新的依赖文件名
模式规则¶
这是一个通用的规则(模式匹配规则),% 表示匹配任意非空字符。这个规则的意思是:%.o 会匹配上所有以 .o 结尾的文件;%.c 中的 % 会被替换成目标 .o 文件名中的前缀。
函数¶
常用函数¶
-
$(subst from,to,text):将 text 中的 from 替换为 to -
$(patsubst pattern,replacement,text):将 text 中的符合 pattern 的部分替换为 replacement -
$(strip string):去掉 string 中的前后空格 -
$(findstring find,in):在 in 中查找 find,如果找到返回 find,否则返回空 -
$(filter pattern...,text):从 text 中过滤出符合 pattern 的部分 -
$(foreach var,list,text):遍历 list 中的每个元素,将元素赋值给变量 var,然后展开 text -
$(wildcard pattern):展开通配符 -
$(shell command):执行 shell 命令
其他函数¶
-
$(if condition,then-part[,else-part]):条件判断,如果第一个参数为非空字符串,则展开第二个参数,否则展开第三个参数 -
$(or condition1,condition2,...):逻辑或 -
$(and condition1,condition2,...):逻辑与
一个简单的 C 程序 makefile 通用模板