静态模式
静态模式可以更加容易地定义多目标的规则,可以让我们的规则变得更加的有弹性和灵活。我们还是先来看一下语法:
- <targets ...> : <target-pattern> : <prereq-patterns ...>
- <commands>
- ...
targets定义了一系列的目标文件,可以有通配符。是目标的一个集合。
target-parrtern是指明了targets的模式,也就是的目标集模式。
prereq-parrterns是目标的依赖模式,它对target-parrtern形成的模式再进行一次依赖目标的定义。
这样描述这三个东西,可能还是没有说清楚,还是举个例子来说明一下吧。如果我们的<target-parrtern>定义成 %.o
,意思是我们的<target>;集合中都是以 .o
结尾的,而如果我们的<prereq-parrterns>定义成 %.c
,意思是对<target-parrtern>所形成的目标集进行二次定义,其计算方法是,取<target-parrtern>模式中的 %
(也就是去掉了 .o
这个结尾),并为其加上 .c
这个结尾,形成的新集合。
所以,我们的“目标模式”或是“依赖模式”中都应该有 %
这个字符,如果你的文件名中有 %
那么你可以使用反斜杠 \
进行转义,来标明真实的 %
字符。
看一个例子:
- objects = foo.o bar.o
- all: $(objects)
- $(objects): %.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
上面的例子中,指明了我们的目标从$object中获取, %.o
表明要所有以 .o
结尾的目标,也就是 foo.o bar.o
,也就是变量 $object
集合的模式,而依赖模式 %.c
则取模式%.o
的 %
,也就是 foo bar
,并为其加下 .c
的后缀,于是,我们的依赖目标就是 foo.c bar.c
。而命令中的 $<
和 $@
则是自动化变量, $<
表示第一个依赖文件,$@
表示目标集(也就是“foo.o bar.o”)。于是,上面的规则展开后等价于下面的规则:
- foo.o : foo.c
- $(CC) -c $(CFLAGS) foo.c -o foo.o
- bar.o : bar.c
- $(CC) -c $(CFLAGS) bar.c -o bar.o
试想,如果我们的 %.o
有几百个,那么我们只要用这种很简单的“静态模式规则”就可以写完一堆规则,实在是太有效率了。“静态模式规则”的用法很灵活,如果用得好,那会是一个很强大的功能。再看一个例子:
- files = foo.elc bar.o lose.o
- $(filter %.o,$(files)): %.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
- $(filter %.elc,$(files)): %.elc: %.el
- emacs -f batch-byte-compile $<
$(filter %.o,$(files))表示调用Makefile的filter函数,过滤“$files”集,只要其中模式为“%.o”的内容。其它的内容,我就不用多说了吧。这个例子展示了Makefile中更大的弹性。