在Make中优先考虑模式规则

时间:2017-05-01 19:10:55

标签: sorting makefile

我(大致)这个Makefile:

.PHONY: all
.SUFFIXES:

OUT = /www/web

all: $(OUT)/index.html

# rule 1
%.html: %.in
    build_html $< $@

# rule 2
$(OUT)/%: %
    cp $< $@

这个Makefile有一个问题,因为有两种不同的方法来构建$(OUT)/index.html

  1. 构建./index.html(规则1),然后将其复制到$(OUT)(规则2)。
  2. ./index.in复制到$(OUT)(规则2),然后构建$(OUT)/index.html(规则1)。
  3. 我希望make 总是更喜欢选项1.如何指出这两种模式规则之间存在首选顺序?

    (我可以想到一些hacky方法来完成这个特定情况,但我想要一个尽可能通用的解决方案 - 例如,将规则2的模式更改为$(OUT)/%.html: %.html将修复问题,但失去了普遍性,因为如果我想以后以同样的方式处理其他类型的文件,我需要重复自己。)

2 个答案:

答案 0 :(得分:1)

GNU Makefile手册中的quote

  

多个模式规则可能符合这些标准。在这种情况下,make将选择具有最短词干的规则(即,最具体匹配的模式)。如果多个模式规则具有最短的词干,则make将选择在makefile中找到的第一个。

因此,您可以尝试创建规则,以确保较短的词干优先。或者,您可以使用static pattern rules来限制复制内容的范围,如下所示:

%.html: %.in
      build_html $@ $<

$(expected_out) : (OBJS)/% : %
      cp $@ $<

然后根据您的需要预填充$(expected_out)。最后,您可以添加:

$(OUT)/index.html : index.html

在makefile中的某个地方,因为make更喜欢构建对象的“最短路径”,在这种情况下,这只是一个模式规则。

答案 1 :(得分:1)

虽然@ John的答案最适合我的用例(我确切知道$(OUT)中的文件属于哪个),但还有另一种解决方案:将所需的中间文件标记为“珍贵”。

.PRECIOUS: index.html

这也将指示Make不要删除index.html,否则它会为你做。

这要归功于Make's algorithm for choosing implicit rules。制定依赖存在或应该存在的规则,如果文件具有明确规则或者是另一规则的依赖关系,则应该存在“应该存在”的文件。即使它是.SECONDARY.INTERMEDIATE.PRECIOUS等特殊目标的依赖项,这也适用。有关详情,请参阅manual section on "Chains of Implicit Rules"