这反映了 make 的一项常见任务,但可以通过两种不同的方式发生。
文件链
有时构建会经历一个序列的文件类型,但并不总是希望重新生成每个文件,而是在中途停止。举个例子,当从 lex 和 yacc 构建一些东西时,我们可能会得到一些模糊的东西:
%.l -> %.y -> %.c -> %.o -> ....
或者从 LaTex 构建输出文件时:
%.tex -> %.dvi -> %.ps -> %.pdf (maybe)
我们只是放了必要的Pattern Rules 来显示依赖关系:
%.y: %.c
bison -y $<
mv y.tab.c $@
%.c: %.o
$(CC) $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
# This rule is actually built into make
现在我们可以随时制作中间文件:
$ make mycompiler.c
并且 make 只会从源 mycompiler.y 重新构建文件 mycompiler.c 构建所需的任何早期 *.l 文件,但不会构建 mycompiler.o 或 mycompiler.exe。它只是制作您要求的文件。
请注意,这只是一个 GNU make 配方。还有一个Traditional Suffix rule 用于其他类似的制作系统。应该是这样写的:
.y.c:
bison -y $<
mv y.tab.c $@
... etc...
如果您想构建 all *.vd,下一个问题是您如何指定它。您可以像这样传递 *.vd 文件的名称(如果它们存在):
make *.vd
或在 make 文件中有一个 phony 目标,将它们包含在依赖项列表中:
VD_FILES= 1.vd 2.vd ... etc ...
.PHONY: VD
VD: $(VD_FILES)
文件选择
在您的示例中,您有一个选择,而不是一个序列。您可以从源文件中创建一个或两个目标文件。 make 中有一个语法,它是double colon rule。不幸的是,使用了double colons in patterns means something different,所以我们必须使用双冒号规则和虚假目标来表达我们想要的构建。我们还必须注意规则的顺序,因为较早的规则优先于后面的规则。在您的示例中,这可以通过以下方式实现*:
CC_FILES := $(wildcard *.cc)
O_FILES := $(patsubst %.cc,%.o,$(CC_FILES))
VD_FILES := $(patsubst %.cc,%.vd,$(CC_FILES))
.PHONY: all VD
all: $(VD_FILES) $(O_FILES)
VD: $(VD_FILES)
# rule to make only %.vd, relatively fast
$(VD_FILES):: $(CC_FILES)
# different set of shell commands
touch $@
# rule to make %.o that makes %.vd as side-effect; relatively expensive
%.vd %.o:: %.cc
# shell commands
touch $*.o $*.vd
我们现在可以调用 make 来构建所有 *.vd 文件:
make VD
或者只是一两个单独的:
make 1.vd 2.vd
但如果我们要求一个 *.o 文件,它将同时构建:
make 1.o
但是,由于我们首先在依赖项列表中列出了 VD 文件,因此它将在 *.o 文件之前检查所有 VD 文件,这意味着每次都会采用最佳构建。这意味着您现在有选择;您可以手动请求构建任何文件、仅请求 VD 文件或高效更新所有内容(默认)。
*这已经过测试,并且是一个工作的makefile BTW