I understand that an "explicit" pattern rule will take precedence on its implicit counterpart when its prerequisites can be made.
all: src/foo.o
src/%.o: makefile my_haeder.h src/%.c
echo Do something with those source files
If there is a typo for "my_header.h", the implicit rule for %.o will take precedence. Not only my recipe will not be executed, but touching the prerequisites will not trigger the rule. Actually it is the second point which is of interest for me.
The make documentation offers a verification using static pattern rules:
SET_OF_FILES=src/foo.o
all: src/foo.o
$(SET_OF_FILES): src/%.o: makefile my_haeder.h src/%.c
echo Do something with those source files
This results in:
gmake: *** No rule to make target `src/my_haeder.h', needed by `src/foo.o'. Stop.
Though a larger rule, that solution is nice, as long as I don't have to add a rule for which the stem could overlap:
SET_OF_FILES=src/foo.o src/subsrc/bar.o
all: src/foo.o
$(SET_OF_FILES): src/%.o: makefile my_header.h src/%.c
echo Do something with those source files
$(SET_OF_FILES): src/subsrc/%.o: makefile my_header.h src/subsrc/%.c
echo Do something with those other source files
Which results in:
makefile:8: target `src/foo.o' doesn't match the target pattern
makefile:9: warning: overriding commands for target `src/foo.o'
makefile:6: warning: ignoring old commands for target `src/foo.o'
makefile:9: warning: overriding commands for target `src/subsrc/bar.o'
makefile:6: warning: ignoring old commands for target `src/subsrc/bar.o'
The first message is here because I didn't bother $(filter)ing SET_OF_FILES. I don't know how to solve the next warnings, which for any reviewer would mean "something's wrong".
Is there another (more elegant) way to verify that the prerequisites are actually feasible, in order to avoid dropping the explicit pattern rule?
(using GNU Make 3.79.1 win32)
Add a separate rule to check for your prerequisites
all: prereqs src/foo.o
prereqs: Makefile my_header.h
src/%.o: src/%.c Makefile my_header.h
echo Do something with those source files
src/subsrc/%.o: src/subsrc/%.c Makefile my_header.h
echo Do something with those other source files
which will give you:
make
make: *** No rule to make target 'my_header.h', needed by 'prereqs'. Stop
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
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.
I'd like to know what's wrong with my makefile where I'm using inferred rules:
nvcc=/usr/local/cuda-6.5/bin/nvcc
opts="-O3 -arch=sm_35 -rdc=true -lcudadevrt -Xcompiler -fopenmp -lpng"
base: ignore dynamic predict
%: ./../source/%.cu
$(nvcc) $> $(opts) -o $#
The error I get:
make: *** No rule to make target `ignore.exe', needed by `base'. Stop.
Of course there's no such a rule, but shouldn't make assume that ignore is hidden in %?
First, your error message doesn't match your makefile (nowhere in your makefile is the target ignore.exe mentioned). This makes me cautious that there maybe other relevant differences between what you're running and what you've shown us.
In any event, a rule like %: ./../source/%.cu will match a target if and only if there's a prerequisite that matches the pattern as well. So if your target is ignore.exe and the target pattern is % that means that the % in the prerequisite will expand to ignore.exe as well. So make will look for a prerequisite ./../source/ignore.exe.cu. If that file exists (or can be made itself) then make will try to build the target. If it doesn't exist and can't be created, then make will ignore that rule and keep looking for more rules that might match the target and where the prerequisite exists or can be built.
If none are found, then you get the error you see (No rule to make target)
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).
http://www.cprogramming.com/tutorial/makefiles_continued.html explains implicit targets:
There are some actions that are nearly ubiquitous: for instance, you might have a collection of .c files that you may wish to execute the same command for. Ideally, the name of the file would be the target; using the implicit target ".c" you can specify a command to execute for any target that corresponds to the name of a .c file (minus the .c extension).
However, when I try it, the implicit target is simply ignored. My test makefile is as follows:
Default: Foo.bar
echo "In default."
.bar:
echo "In .bar."
make: *** No rule to make target `Foo.bar', needed by `Default'. Stop.
What am I missing?
Try:
default: foo.bar
echo "In default."
%.bar:
echo "In .bar."
You may be asking about old-style suffix rules - for example this rule:
.c.o:
cc -c $<
tells make how to build a .o file from a .c source. The form with the '%' is known as a pattern rules and is more "modern". I suggest you read the GNU Make manual, which is very informative about such stuff, and easy to read.