Prioritizing pattern rules in Make

时光总嘲笑我的痴心妄想 提交于 2020-05-29 05:06:06

问题


I have (roughly) this Makefile:

.PHONY: all
.SUFFIXES:

OUT = /www/web

all: $(OUT)/index.html

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

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

This Makefile has a problem, since there are two different ways to build $(OUT)/index.html:

  1. build ./index.html (rule 1), then copy it to $(OUT) (rule 2).
  2. copy ./index.in to $(OUT) (rule 2), then build $(OUT)/index.html (rule 1).

I want make to always prefer option 1. How can I indicate that there is a preferred order between these two pattern rules?

(I can think of a few hacky ways to accomplish it for this particular case, but I want a solution that is as general as possible---for instance, changing the pattern of rule 2 to $(OUT)/%.html: %.html will fix the problem, but loses generality since I need to repeat myself if I want to handle other kinds of files in the same way later.)


回答1:


A quote from the GNU Makefile Manual:

It is possible that more than one pattern rule will meet these criteria. In that case, make will choose the rule with the shortest stem (that is, the pattern that matches most specifically). If more than one pattern rule has the shortest stem, make will choose the first one found in the makefile.

So, you can try to create rules which ensure shorter stems to take priority. Alternatively, you could use static pattern rules to limit the scope of what gets copied where, as so:

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

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

and then prepopulate $(expected_out) with what you want in there. Finally, you can add:

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

somewhere in your makefile, as make prefers the 'shortest path' to building an object, which would only be one pattern rule in this case.




回答2:


While @John's answer best fits my use-case (I know exactly what files belong in $(OUT)), there is also an alternative solution: mark the desired intermediate file as "precious".

.PRECIOUS: index.html

This will also instruct Make not to delete index.html, which it would otherwise do for you.

This works thanks to Make's algorithm for choosing implicit rules. Make favors rules whose dependencies exist or ought to exist, and a file "ought to exist" if it has an explicit rule or is a dependency of another rule. This applies even if it is a dependency of a special target like .SECONDARY, .INTERMEDIATE, or .PRECIOUS. For more info, also see the manual section on "Chains of Implicit Rules".



来源:https://stackoverflow.com/questions/43724971/prioritizing-pattern-rules-in-make

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!