1

I have a minimal Makefile with just this one pattern rule:

%: %.m4
    m4 $< > $@

Then, with GNU Make:

touch foo.in.m4 ; make foo.in executes as expected: m4 foo.in.m4 > foo.in

but for foo.sh.m4 (note double suffix), touch foo.sh.m4; make foo.sh tells me: *** No rule to make target 'foo.sh'.

Similar problem with several target suffixes other than .sh (namely: .f, .c, .o, .tex, .dvi). And yet many other suffixes do work (e.g. xml, doc, mp3, pdf, png, txt). The test is:

 for suff in pdf sh f c o xml doc docx tex dvi mp3 png odt txt in none yxn; do
      touch foo.$suff.m4
      make foo.$suff
 done

make -r causes things to work as expected so I guess it has something to do with the default suffix list. However, if that's the case, shouldn't adding a rule

.SUFFIXES: 

...have the same effect? I tried it, and things improved, but it still failed with .c and .tex, i.e. make bar.c and make bar.tex still fail with a "no rule" error even when bar.c.in and bar.tex.in are present.

Whether make -r or the empty .SUFFIXES rule, I thought the suffix list has to do with suffix rules, not pattern rules. Can someone explain what's going on here? Thx.

1 Answer 1

4

Match-anything pattern rules (%: ...) are special for performance reasons. If they were not make would have to consider these rules for every target or prerequisite, and this would be slow. To understand all the details you can read the manual. The behavior of a match-anything pattern rule depends on the existence of implicit rules for the considered target. In your case the difference between targets foo.sh and foo.in is that, for the former, make has implicit rules, while there are no implicit rules for the latter.

You can try to make your rule terminal (double colon):

%:: %.m4
    m4 $< > $@

such that, when trying to build foo.bar, make ignores this rule unless foo.bar.m4 exists, and if it does, the terminal match-anything rule applies, even if implicit rules also apply.

You could also keep your rule as it is (non-terminal) but disable implicit rules completely with make -r foo.sh (except if other parts of your Makefile make use of implicit rules, of course).

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks - and thanks for the pointer to the right place in the manual. I didn't realize that "match-anything" pattern rules were a "thing." I went with the terminal rule (double colon) as you suggested and it worked great. Thanks again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.