Match-Anything Pattern Rules - makefile

I am using GNU Make 3.81 version.
From the following example, I expect match anything pattern(%:) has to be print. Instead of that te%: has executed.
Can some one explain, why target '%:' did not run?
Is this not match all file name?
Makefile:
all: test
echo $#
%:
echo 1: $#
te%:
echo 2: $#
Output:
echo 2: test
2: test
echo all
all

There are special rules for how make treats match-anything pattern rules; see the documentation. You are creating a "non-terminal match-anything rule" here, and the rule for that is this:
A non-terminal match-anything rule cannot apply to a file name that indicates a specific type of data. A file name indicates a specific type of data if some non-match-anything implicit rule target matches it.
In your case you have a non-match-anything implicit rule target (te%) which matches the file name (test) and so a non-terminal match-anything rule (%:) cannot match it.

Related

Multiple stems (%) in a Makefile prerequisite

I'm trying to use the following Makefile to create the target foo.a with foo.foo.b as a prerequisite, using the stem character (%) as shown.
%.a: %.%.b
touch $#
However running touch foo.foo.b; make foo.a doesn't work with No rule to make target. The debug output below shows that the stem % is only expanded once. How to get the desired behavior of replacing all % in the prerequisite?
Considering target file 'sdf.a'.
File 'sdf.a' does not exist.
Looking for an implicit rule for 'sdf.a'.
Trying implicit prerequisite 'sdf.%.b'.
Looking for a rule with intermediate file 'sdf.%.b'.
Avoiding implicit rule recursion.
Trying pattern rule with stem 'sdf.%.b'.
Trying implicit prerequisite 'sdf.%.b,v'.
(..)
No implicit rule found for 'sdf.a'.
Finished prerequisites of target file 'sdf.a'.
Must remake target 'sdf.a'.
make: *** No rule to make target 'sdf.a'. Stop.
Side note: this seems like a trivial question but for some reason I can't find the answer, maybe I'm using the wrong search terms or overlooking something simple, sorry if that is the case.
The stem is only replaced once. If you wish to have stem contents inserted more than once, you would need to use secondary expansion, i.e.:
$ cat Makefile
.SECONDEXPANSION:
%.a: $$*.$$*.b
echo Making $# from $<
Output:
$ touch foo.foo.b
$ make -s foo.a
Making foo.a from foo.foo.b

GNU make - implicit rule is not used, but static pattern rule is

Consider the following makefile (and any hi.c):
.PHONY: analyze-%
hi: hi.c
gcc -o $# $<
%.json: %
touch $# # actually created by analysis-tool
analyze-%: %.json # why does this not work?
As my comment in the makefile points out, the implicit rule does not work:
$ make analyze-hi
make: *** No rule to make target 'analyze-hi'. Stop.
It only works after transforming it into a static pattern rule:
...
analyze-hi: analyze-%: %.json
Why is this the case? Shouldn't make be able to figure this out on its own, without me having to explicitly write the full target name? There is no ambiguity or anything (as far as I'm aware).
Pattern rules must have recipes. If they don't have a recipe then they're not creating a pattern rule, they're canceling one.
See https://www.gnu.org/software/make/manual/html_node/Canceling-Rules.html
A static pattern rule, contrary to what's implied by its name, is not actually creating an implicit rule (pattern or suffix rule). It's creating explicit rules, just based on a pattern. Explicit rules don't have to have recipes.

Make not using Match Anything rule for prerequisite

So, I have a Makefile with 2 pattern rules, one of them is a terminal Match-Anything; the target is about.html (for example):
vpath %.md $(SOURCE_DIR)
HEADER := assets/navbar.part
%.html : %.md $(HEADER)
pandoc [...] $< -o $#
%::
cp $(SOURCE_DIR)/$# $#
If I execute make assets/navbar.part, and then make about.html (for example), everything works fine (navbar.part uses the match anything, and about.html uses the first rule). But if I try to make about.html without having navbar.part present, make does:
Find the prerequisite about.md
?? Gives up on fulfilling $(HEADER)
Tries to use the match anything rule to generate about.html
I was expecting that make would:
Find the prerequisite about.md
Make the prerequisite $(HEADER) using the match-anything rule
With all the prerequisites fulfilled, finally execute the first rule
From reading the debug trace, it seems like Make never really tries to fulfill the $(HEADER) prerequisite:
Considering target file 'about.html'.
File 'about.html' does not exist.
Looking for an implicit rule for 'about.html'.
Trying pattern rule with stem 'about'.
Trying implicit prerequisite 'about.md'.
Found prerequisite 'about.md' as VPATH '../website/about.md'
Trying rule prerequisite 'assets/navbar.part'.
Trying pattern rule with stem 'about.html'.
Found an implicit rule for 'about.html'.
Considering target file 'about.md'.
Finished prerequisites of target file 'about.md'.
No need to remake target 'about.md'; using VPATH name '../website/about.md'.
Finished prerequisites of target file 'about.html'.
Must remake target 'about.html'.
cp -f ../website/about.html about.html
Any ideas?
After digging the manual, I found section 10.8 that states:
For each pattern rule in the list:
Find the stem s, which is the nonempty part of t or n matched by the ‘%’ in the target pattern.
Compute the prerequisite names by substituting s for ‘%’; if the target pattern does not contain a slash, append d to the front of each prerequisite name.
Test whether all the prerequisites exist or ought to exist. (If a file name is mentioned in the makefile as a target or as an explicit prerequisite, then we say it ought to exist.)
Because the $(HEADER) does not meet the definition of ought to exist:
No file exists when the rule is tried
No rule with that explicit target exists
it fails; however, it suceeds if we try to make specifically $(HEADER), and then try to make about.html it suceeds, because by then $(HEADER) is an existing file.

Makefile Pattern Rule is found but recipe does not run

I have a makefile that has the following pattern rule to create an implicit rule:
%.cpp:
$(warning foo)
When I check the output of make -d I see that this implicit rule is being found and matching a file. I verify that when I remove the pattern rule, the output of make -d no longer shows a match. However, even when the implicit rule is found, the warning doesn't show up. The recipe isn't running, even though the implicit rule matches.
What gives?
That recipe tells make how to create a %.cpp file (and gives it no prerequisites).
When are you expecting it to be run?
It will not run for any existing *.cpp files as the lack of prerequisites means that make considers the files up to date.
Try running make totally-doesnt-exist.cpp and you should see the warning.

make implicit rules don't work without command

I have a simple Makefile like this:
%.t1: %.t2
%.t2:
echo "t2"
When I type
make x.t2
it works fine. But when I type
make x.t1
I get
make: *** No rule to make target 'x.t1'. Stop.
If I modify the %.t1 target to say
%.t1: %.t2
echo
Then it works. Why doesn't it work without a command? I'm using GNU make 4.0 on Fedora 23.
A pattern rule with no recipe does not add a rule, it cancels implicit rules. See http://www.gnu.org/software/make/manual/make.html#Canceling-Rules:
You can cancel a built-in implicit rule by defining a pattern rule with the same target and prerequisites, but no recipe. For example, the following would cancel the rule that runs the assembler:
%.o : %.s
A semi-colon can be added to tell make that it has an empty recipe:
%.t1: %.t2 ;
%.t2:
echo t2
Which yields:
$ make x.t1
t2

Resources