我想知道是否可以编写一个包含多个规则的 Makefile,每个规则都定义自己的先决条件,并以相同的配方执行所有这些规则,而无需重复配方。示例:
TARGETS= file1 file2 file3
all: $(TARGETS)
file1: dep1 dep2
file2: dep2 dep3 dep4
file3: dep2 dep1
cat $^ > $@
谢谢!
是的,写得相当明显:
TARGETS= file1 file2 file3
all: $(TARGETS)
file1: dep1 dep2
file2: dep2 dep3 dep4
file3: dep2 dep1
$(TARGETS):
cat $^ > $@
只是为了澄清。
通用制定规则看起来像这样:
targets... : prerequisites...
recipe
...
规则的任何部分都可以省略。如果没有配方,人们可以在 makefile 中的任何位置填充先决条件列表,目标可以出现在多个规则语句的左侧。
例如,以下内容与上面的示例等效(假设 Makefile 设计正确,因此先决条件的顺序并不重要):
file1 file3 : dep1
file1 file2 file3 : dep2
file2 : dep3 dep4
与列出先决条件不同,每个目标最多可以有一个显式配方。在配方中,您可以使用自动变量来获取目标名称、先决条件列表等。
正如@Calmarius 在评论中提到的那样,这不适用于模式规则,例如
%.txt: %.foo
。
目标中的多个模式意味着该规则立即产生所有这些目标。
此模式规则有两个目标:
%.tab.c %.tab.h: %.y bison -d $<
这告诉make,配方
将同时制作bison -d x.y
和x.tab.c
。 如果文件 foo 依赖于 文件x.tab.h
和parse.tab.o
以及文件 scan.o 取决于 文件scan.o
,当parse.tab.h
更改时,配方parse.y
只会执行一次,并且两者的先决条件bison -d parse.y
和parse.tab.o
会很满意。scan.o
尽管可以在模式规则中定义多个先决条件(也就是说,只要其目标包含
%
词干,否则它将是常规规则)。
我发现了一种 GNU make 4.0 的模块化方法:
如果你像这样小心地定义你的命令
CMD_DBG=@echo "Making $@ from $<"
即使在这样的模式规则中,您也可以使用这些命令:
%.xml: %.out
$(CMD_DBG)
我什至在这里使用了一些病态的案例:
%.prtg: %.test
$(CMD_DBG)
@if cp -p "$<" "$@"; then \
$(CMD_LINT_PRTG); \
else \
$(CMD_BAD_TGT); \
fi
只要确保在定义命令时不使用
:=
,或知道你在做什么!