makefile pattern rules without recipes - makefile

I'm observing an interesting behavior of make and I wonder if there is a reasonable explanation to it besides a bug in gmake.
Let's say we have the following in makefile:
%-animal:
echo "$* is an animal"
%-fox: %-fox-animal
%-wolf: %-wolf-animal
The difference between the last two targets is that "%-wolf" does not have any recipe, and "%-fox" has an empty recipe (i.e. just a line with a tab at the beginning).
When we try to execute the rules, here's what happens:
[root#cv19 tmp]# make freddy-animal
echo "freddy is an animal"
freddy is an animal
[root#cv19 tmp]# make freddy-wolf
make: *** No rule to make target `freddy-wolf'. Stop.
[root#cv19 tmp]# make freddy-fox
echo "freddy-fox is an animal"
freddy-fox is an animal
i.e.the pattern rule that has a recipe (although an empty one) works, the one that doesn't does not. Am I missing something in the way it's supposed to work?

Pattern rules with no recipes at all are documented as meaning something quite different from those providing a recipe, even an empty one. Instead they cancel any pre-existing implicit rule:
You can cancel a built-in implicit rule by defining a pattern rule with the same target and prerequisites, but no recipe.
Thus your "%-wolf" pattern actually serves to cancel any existing implicit rule for %-wolf-animal -> %-wolf. And there wasn't one anyway.

Related

No rule to make (phony) target

I am trying to create a pattern rule for a phony target foo-test which should build an actual file foo-test1:
%-test: %-test1
%-test1:
touch $#
When I call make --just-print foo-test I get No rule to make target: foo-test.
Yet I would expect make to see that foo-test depends on foo-test1 and apply the second rule to make foo-test1. How can achieve this behaviour? (I have tried declaring %-test and %-test1 as .PHONY; it doesn't help).
This:
%-test: %-test1
does not define a pattern rule. It deletes a pattern rule. See https://www.gnu.org/software/make/manual/html_node/Canceling-Rules.html
You have to give it a recipe if you want to make a pattern rule. Something like this is sufficient:
%-test: %-test1 ;

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.

Implict rule cancellation in Makefile

I have come across the following line in U-boot Makefile ( https://github.com/siemens/u-boot/blob/master/Makefile#L128 ) with comment "Cancel implicit rules on top Makefile".
Can you help me to understand the following line, how/what will happen while executing the following line by make utility.
$(CURDIR)/Makefile Makefile: ;
See How Makefiles Are Remade:
If you know that one or more of your makefiles cannot be remade and you want to keep make from performing an implicit rule search on them, perhaps for efficiency reasons, you can use any normal method of preventing implicit rule look-up to do so. For example, you can write an explicit rule with the makefile as the target, and an empty recipe.
And that is exactly what $(CURDIR)/Makefile Makefile: ; rule does - it has an empty recipe.

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.

Rule with wildcard to depend on other rules [duplicate]

I'm observing an interesting behavior of make and I wonder if there is a reasonable explanation to it besides a bug in gmake.
Let's say we have the following in makefile:
%-animal:
echo "$* is an animal"
%-fox: %-fox-animal
%-wolf: %-wolf-animal
The difference between the last two targets is that "%-wolf" does not have any recipe, and "%-fox" has an empty recipe (i.e. just a line with a tab at the beginning).
When we try to execute the rules, here's what happens:
[root#cv19 tmp]# make freddy-animal
echo "freddy is an animal"
freddy is an animal
[root#cv19 tmp]# make freddy-wolf
make: *** No rule to make target `freddy-wolf'. Stop.
[root#cv19 tmp]# make freddy-fox
echo "freddy-fox is an animal"
freddy-fox is an animal
i.e.the pattern rule that has a recipe (although an empty one) works, the one that doesn't does not. Am I missing something in the way it's supposed to work?
Pattern rules with no recipes at all are documented as meaning something quite different from those providing a recipe, even an empty one. Instead they cancel any pre-existing implicit rule:
You can cancel a built-in implicit rule by defining a pattern rule with the same target and prerequisites, but no recipe.
Thus your "%-wolf" pattern actually serves to cancel any existing implicit rule for %-wolf-animal -> %-wolf. And there wasn't one anyway.

Resources