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 ;
Related
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
I have a main Makefile that calls Makefiles placed in subfolders. For testing purposes I would like to add Match-Anything rule at the end of main Makefile.
This rule would be:
%:
make -e -C subdir $#
Are there any contrarguments for such a rule?
I think you meant "con", as in "pro or con", not "cont". "Con" is short for the Latin "contra".
For your question, the downside of adding a new "match anything" rule is that any file that doesn't exist, will try to be created using this rule. For example suppose you run include foo.mk and foo.mk doesn't exist... make will attempt to build foo.mk by running your rule. Basically it can be confusing. It's possible there could be some performance impact; if you run make -d and examine it you should see if your match-anything rule is being used at all during a normal build. I'm not sure if there are any other serious downsides.
By the way you should always only use the make variable $(MAKE) when invoking a sub-make in a recipe; never use the raw make 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
I have the following rule in my makefile:
$(TESTDIR)/%.test.out:$(TESTDIR)/%.test $(TESTDIR)/%.in
$< < $(patsubst %.out, %.in, $#) 2>&1 > $#
I expect that, when I invoke make
make testing/Candidate.test.out
(where TESTDIR=testing in the makefile), make should respond with
testing/Candidate.test < Candidate.test.in 2>&1 >Candidate.test.out
Instead, make responds with
cp testing/Candidate.test testing/Candidate.test.out
and make -d yields:
Considering target file 'testing/Candidate.test.out'.
File 'testing/Candidate.test.out' does not exist.
Looking for an implicit rule for 'testing/Candidate.test.out'.
Trying pattern rule with stem 'Candidate'.
Trying implicit prerequisite 'testing/Candidate.test'.
Trying implicit prerequisite 'testing/Candidate.in'.
Trying pattern rule with stem 'Candidate.test'.
Trying implicit prerequisite 'testing/Candidate.test'.
Found an implicit rule for 'testing/Candidate.test.out'.
Building with make -r:
make -r testing/Candidate.test.out
make: *** No rule to make target 'testing/Candidate.test.out'. Stop.
indicates that make is decidedly not recognizing my rule, but I can't see why not. Clearly make believes $(TESTDIR)=testing, based on the cp output. Clearly it also recognizes testing/Candidate.test.out as a valid target, because it attempts to build it (whereas it fails for testing/blah.test.out).
Is there something obvious I'm missing here?
One of the targets in the rule (%.in) is incorrect (should be %.test.in).
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.