六、多目標(biāo)
Makefile的規(guī)則中的目標(biāo)可以不止一個(gè),其支持多目標(biāo),有可能我們的多個(gè)目標(biāo)同時(shí)依賴于一個(gè)文件,并且其生成的命令大體類似。于是我們就能把其合并起來。當(dāng)然,多個(gè)目標(biāo)的生成規(guī)則的執(zhí)行命令是同一個(gè),這可能會(huì)可我們帶來麻煩,不過好在我們的可以使用一個(gè)自動(dòng)化變量“$@”(關(guān)于自動(dòng)化變量,將在后面講述),這個(gè)變量表示著目前規(guī)則中所有的目標(biāo)的集合,這樣說可能很抽象,還是看一個(gè)例子吧。
bigoutput littleoutput : text.g
generate text.g -$(subst output,,$@) >; $@
上述規(guī)則等價(jià)于:
bigoutput : text.g
generate text.g -big >; bigoutput
littleoutput : text.g
generate text.g -little >; littleoutput
其中,-$(subst output,,$@)中的“$”表示執(zhí)行一個(gè)Makefile的函數(shù),函數(shù)名為subst,后面的為參數(shù)。關(guān)于函數(shù),將在后面講述。這里的這個(gè)函數(shù)是截取字符串的意思,“$@”表示目標(biāo)的集合,就像一個(gè)數(shù)組,“$@”依次取出目標(biāo),并執(zhí)于命令。
七、靜態(tài)模式
靜態(tài)模式可以更加容易地定義多目標(biāo)的規(guī)則,可以讓我們的規(guī)則變得更加的有彈性和靈活。我們還是先來看一下語(yǔ)法:
<targets ...>;: <target-pattern>;: <prereq-patterns ...>;
<commands>;
...
targets定義了一系列的目標(biāo)文件,可以有通配符。是目標(biāo)的一個(gè)集合。
target-parrtern是指明了targets的模式,也就是的目標(biāo)集模式。
prereq-parrterns是目標(biāo)的依賴模式,它對(duì)target-parrtern形成的模式再進(jìn)行一次依賴目標(biāo)的定義。
這樣描述這三個(gè)東西,可能還是沒有說清楚,還是舉個(gè)例子來說明一下吧。如果我們的<target-parrtern>;定義成“%.o”,意思是我們的<target>;集合中都是以“.o”結(jié)尾的,而如果我們的<prereq-parrterns>;定義成“%.c”,意思是對(duì)<target-parrtern>;所形成的目標(biāo)集進(jìn)行二次定義,其計(jì)算方法是,取<target-parrtern>;模式中的“%”(也就是去掉了[.o]這個(gè)結(jié)尾),并為其加上[.c]這個(gè)結(jié)尾,形成的新集合。
所以,我們的“目標(biāo)模式”或是“依賴模式”中都應(yīng)該有“%”這個(gè)字符,如果你的文件名中有“%”那么你可以使用反斜杠“\”進(jìn)行轉(zhuǎn)義,來標(biāo)明真實(shí)的“%”字符。
看一個(gè)例子:
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
上面的例子中,指明了我們的目標(biāo)從$object中獲取,“%.o”表明要所有以“.o”結(jié)尾的目標(biāo),也就是“foo.o bar.o”,也就是變量$object集合的模式,而依賴模式“%.c”則取模式“%.o”的“%”,也就是“foo bar”,并為其加下“.c”的后綴,于是,我們的依賴目標(biāo)就是“foo.c bar.c”。而命令中的“$<”和“$@”則是自動(dòng)化變量,“$<”表示所有的依賴目標(biāo)集(也就是“foo.c bar.c”),“$@”表示目標(biāo)集(也就是“foo.o bar.o”)。于是,上面的規(guī)則展開后等價(jià)于下面的規(guī)則:
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”有幾百個(gè),那種我們只要用這種很簡(jiǎn)單的“靜態(tài)模式規(guī)則”就可以寫完一堆規(guī)則,實(shí)在是太有效率了。“靜態(tài)模式規(guī)則”的用法很靈活,如果用得好,那會(huì)一個(gè)很強(qiáng)大的功能。再看一個(gè)例子:
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))表示調(diào)用Makefile的filter函數(shù),過濾“$filter”集,只要其中模式為“%.o”的內(nèi)容。其的它內(nèi)容,我就不用多說了吧。這個(gè)例字展示了Makefile中更大的彈性。