makefile中的工作目标依存于一组必要条件,这些条件一般也都是文件。当你要求更新某个工作目标时,如果必要条件中存在时间戳在工作目标的时间戳之后的文件,make就会执行相应规则里的命令脚本。因为某个规则的工作目标可以是另一个规则的必要条件,所以这样的工作目标和必要条件将会形成依存图(dependency graph)。建立及处理依存图,并据此更新特定的工作目标,就是make所要做的事。
规则对make而言十分重要,make允许你使用各种类型的规则。
0. 绪论
具体规则(explicit rule),用来指定需要更新的目标:如果必要条件中存在时间戳在此工作目标的时间戳之后的文件,make就会对它进行更新的动作。
模式规则(pattern rule),使用的是通配符而非明确的文件名称,这让make得以对与模式相符的工作目标应用该规则,进行必要的更新动作。
隐含规则(implicit rule),可以是模式规则,也可以是内置于make的后缀规则(suffix rule)
1. 具体规则
具体规则(explicit rule),用来指定需要更新的目标:如果必要条件中存在时间戳在此工作目标的时间戳之后的文件,make就会对它进行更新的动作。
通配符
通配符,也称为文件名模式匹配(globbing)。make的通配符如同Bourne shell的~、*、?、[...]和1。
- ~ 代表当前用户的主目录
- *.* 会被扩展为文件名中包含点号的所有文件号
- ? 代表任何一个单一字符
- [...] 代表一个字符集
- 1 取得字符集的补集
值得注意的是,当模式出现在工作目标或必要条件中时,是由make进行通配符的扩展。然而,当模式出现在命令中时,是由subshell进行扩展的动作。区分这两种情况有时会变得很重要,因为make会在读取makefile的时候立即扩展通配符,但是shell只会在执行命令的时候扩展通配符。当有许多复杂的文件操作需要进行时,这两种文件扩展动作将会有很大的差别。
假想工作目标
任何不代表文件的工作目标就叫作假想工作目标(phony target)。
通常,make总是会执行假想工作目标,因为对应于该规则命令并不会创建以该工作目标为名称的文件。
在.PHONY这个工作目标中声明假想工作目标,例如
.PHONY: clean
clean:
rm -rf *.o
这样,即使目录中存在名为clean的文件,make还是会执行对应于clean的命令。
以“假想工作目标”作为“实际文件”的一个“必要条件”似乎不太有意义,因为假想工作目标总是尚未更新,这会使得该实际文件被重新建立。实际应用中,一般以“假想工作目标”作为“假想工作目标”的必要条件。
2. 变量
一般来说,必须用$()或${}将变量名称括住,这样make才会认得。有一个例外:变量名称若是单一字符则不需要为它加上圆括号。
下面是make中定义的一些自动变量
自动变量 | 含义 |
---|---|
$@ | 工作目标的文件名 |
$% | 档案文件成员(archive member)结构中的文件名元素。 |
$< | 第一个必要条件的文件名 |
$? | 时间戳在工作目标(的时间戳)之后的所有必要条件,并以空格隔开这些必要条件 |
$^ | 所有必要条件的文件名,并以空格隔开这些文件名。这份列表已删掉重复的文件名,因为对大多数的应用而言,比如编译、复制等,并不会用到重复的文件名 |
$+ | 如同$^,代表所有必要条件的文件名,并以空格隔开这些文件名。不过,$+包含重复的文件名。 |
$* | 工作目标的主文件名。一个文件名称是由两部分组成:主文件名(stem)和扩展名(suffix) |
3. 以VPATH和vpath来查找文件
除非你告诉make,否则它只会在当前目录中找寻工作目标以及必要条件。
VPATH变量的内容是一份目录列表,可供make搜索其所需的文件。例如,VPATH src1 src2
这份目录列表可用来搜索工作目标以及必要条件,但不包括脚本中所提及的文件。这份目录列表的分隔符在Unix上可以是空格或冒号。
虽然VPATH变量可以解决大部分搜索问题,但也有限制。make将会为它所需要的的任何文件搜索VPATH列表中的目录,如果在多个目录中出现同名的文件,则make只会摄取第一个被找到的文件,这有时可能会造成问题。
此时可以使用vpath指令。语法如下所示:
vpath pattern directory-list
例如
vpath %.l %.c src
vpath %.h include
4. 模式规则
许多程序在读取文件时都会依照惯例。例如,所有C编译器都会假设,文件若是以.c为扩展名,其所包含的就是C源代码,把文件名从.c替换成.o就可以得到目标文件的文件名。
这种惯例让make可以通过文件名模式的匹配来简化规则的建立,以及提供内置规则来处理它们。
模式
模式规则中的百分比字符(%)大体上等效于Unix shell中的星号(*),它可以代表任意多个字符。百分比字符可以放在模式中的任何地方,不过只能出现一次。百分比字符的正确用法如下所示:
%,v
s%.o
wrapper_%
在文件名中,百分比以外的字符会按照字面进行匹配。一个模式可以包含一个前缀(prefix)或一个后缀(suffix),或者这两个同时存在。模式规则工作目标必须以前缀开头并且以后缀结尾(如果它们存在的话)。
5. 隐含规则
6. 特殊工作目标
7. 特殊工作目标
8. 自动产生依存关系
9. 管理程序库
- ... ↩
评论