具有共享相同配方的多个规则的Makefile

43

我想知道是否可能编写一个Makefile,其中有几个规则,每个规则定义自己的先决条件并执行相同的配方而不重复。

例如:

TARGETS= file1 file2 file3

all: $(TARGETS)

file1: dep1 dep2
file2: dep2 dep3 dep4
file3: dep2 dep1
    cat $^ > $@

谢谢!

2个回答

65
是的,它被明显地书写了出来。
TARGETS= file1 file2 file3

all: $(TARGETS)

file1: dep1 dep2
file2: dep2 dep3 dep4
file3: dep2 dep1

$(TARGETS):
    cat $^ > $@

更新

仅为澄清。

通用的make规则看起来像这样:

targets... : prerequisites...
    recipe
    ...

规则的任何部分都可以省略。没有配方,一个人可以在makefile的任何地方填充先决条件列表,一个目标可以出现在多个规则语句的左侧。

例如,以下内容等同于上面的示例(假定Makefile已经正确设计,使得先决条件的顺序不重要):

file1 file3       : dep1
file1 file2 file3 : dep2
file2             : dep3 dep4

与列出先决条件不同,每个目标最多只能有一个明确的配方。在配方中,您可以使用自动变量来获取目标名称、先决条件列表等信息。

更新. 2

正如@Calmarius在评论中提到的,这不适用于模式规则,比如%.txt: %.foo。 目标中的多个模式意味着该规则一次性生成所有这些目标。

 

此模式规则有两个目标:

%.tab.c %.tab.h: %.y
    bison -d $<
这告诉make工具,配方bison -d x.y会生成x.tab.cx.tab.h两个文件。 如果文件foo依赖于parse.tab.oscan.o,而文件scan.o又依赖于文件parse.tab.h,那么当修改parse.y时,配方bison -d parse.y只会被执行一次,并且parse.tab.oscan.o的前提条件都会得到满足。 虽然可以在模式规则中定义多个前提条件(即其目标包含一个%词根),但需要注意,否则它将成为一个常规规则。

@superruzafa,请看更新的答案,我尝试解释一下规则可能是什么样子。 - Eldar Abusalimov
7
如果你有模式规则,比如%.txt: %.foo,那么这将不起作用。如果你将一些txt文件添加到TARGETS变量中,$^将扩展为空。我猜make认为$(TARGETS): 更具体,因此不会应用通用规则。显然,对于模式规则,你无法避免重复的配方。 - Calmarius

0
我找到了一种相对模块化的方法来使用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

只要确保在定义命令时不使用:=,要么就要知道自己在做什么!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接