% not matching zero or more characters in rule? - makefile

According to the manual on Defining and Redefining Pattern Rules (and if I am reading it correctly):
‘%’ character matching any sequence of zero or more characters...
But the following is not matching both bench.cpp and bench2.cpp:
bench%.o : bench%.cpp
$(CXX) $(CXXFLAGS) -DCRYPTOPP_DATA_DIR='"$(PREFIX)/share/cryptopp"' -c $<
%.o : %.cpp
$(CXX) $(CXXFLAGS) -c $<
Here's what I see when running make:
$ rm bench*.o
$ make static dynamic cryptest.exe PREFIX=/usr/local
make: Nothing to be done for `static'.
make: Nothing to be done for `dynamic'.
g++ -DNDEBUG -g -O2 -fPIC -march=native -pipe -c bench.cpp
g++ -DNDEBUG -g -O2 -fPIC -march=native -pipe -DCRYPTOPP_DATA_DIR='"/usr/local/share/cryptopp"' -c bench2.cpp
Above, both bench.cpp and bench2.cpp should have -DCRYPTOPP_DATA_DIR='"/usr/local/share/cryptopp"'. I also tried using the asterisk (*) with no joy.
How do I craft a rule that matches both bench.cpp and bench2.cpp?

According to the link you provided
A pattern rule contains the character ‘%’ (exactly one of them) in the
target; otherwise, it looks exactly like an ordinary rule. The target
is a pattern for matching file names; the ‘%’ matches any nonempty
substring, while other characters match only themselves.
So % doesn't match empty strings.
‘%’ character matching any sequence of zero or more characters...
refers to the definition of vpath which is totally different.
I'm afraid you'll have to use bench1 instead of bench. Alternatively you can use macro to defines 2 rules but write it only once.

Well, I happened to stumble across the proper section of the documentation on this.
According to 4.4 Using Wildcard Characters in File Names, I should probably use an asterisk in this case.
And according to Stallman and the GNUMake manual, % is not a wildcard for specifying file names:
A single file name can specify many files using wildcard characters.
The wildcard characters in make are ‘*’, ‘?’ and ‘[…]’ ...

Related

Makefile Static Pattern Rule

A part of my Makefile:
CFLAGS = -I ../headers -Wall
EXECUTABLES = testPattern testPatterns
$(EXECUTABLES): %Pattern: %.c pattern.o
g++ $(CFLAGS) $#.c pattern.o -o $#
I didn't include the object compilation because it's irrelevant.
The problem I have with this code is that the pattern matches only the first executable because it ends with 'Pattern', the second executable has an additional 's' at the end which kills the script. Is there any way I can make it work without changing the name of the second executable?
Thanks
There's no point in using a static pattern rule here, since the pattern doesn't appear in the prerequisites list. However, I assume you also wanted to include the .c file as a prerequisite here.
Why do you include the Pattern in the pattern match?
You can just write:
CFLAGS = -I ../headers -Wall
EXECUTABLES = testPattern testPatterns
$(EXECUTABLES): % : %.c pattern.o
g++ $(CFLAGS) $^ -o $#
ETA
It appears a better example that would show the real issues you face would be something like this:
EXECUTABLES = someThing somePattern morePatterns
where you want a static pattern rule that matches the two binaries containing Pattern but not the others.
As I said in my comment below, you cannot do this with a single pattern which means you can't do it in the target part of a static pattern rule.
However, you could do it like this:
$(foreach E,$(EXECUTABLES),$(if $(findstring Pattern,$E),$E)): % : %.c pattern.o
g++ $(CFLAGS) $^ -o $#
This basically loops through each entry in EXECUTABLES and tests to see if it contains the string Pattern, and if so expands to that string else expands to nothing.

What does "$(#:%.o=%.d)" mean in a makefile?

I see below command options for GCC in a makefile:
... -MMD -MP -MF "$(#:%.o=%.d)" -MT "$(#:%.o=%.d)" -o "$#" "$<"
How to interpret it?
I searched through the makefile document, but no luck so far.
(This is not just about Automatic Variables)
$(:=) performs a string replacement.
$# is the name of the file being generated (the target).
So $(#:%.o=%.d) is the name of the file, with the .o extension changed to .d.
This command line generates one .d dependency file for each .o file.
(Thanks to #Quentin's clue. I just found it!)
It is called Substitution Reference
Some quote:
A substitution reference substitutes the value of a variable with
alterations that you specify. It has the form ‘$(var:a=b)’ (or
‘${var:a=b}’) and its meaning is to take the value of the variable
var, replace every a at the end of a word with b in that value, and
substitute the resulting string.
When we say “at the end of a word”, we mean that a must appear either
followed by whitespace or at the end of the value in order to be
replaced; other occurrences of a in the value are unaltered. For
example:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
sets ‘bar’ to ‘a.c b.c c.c’. See Setting Variables.
A substitution reference is actually an abbreviation for use of the
patsubst expansion function (see Functions for String Substitution and
Analysis). We provide substitution references as well as patsubst for
compatibility with other implementations of make.
So, the full interpretation of the following command:
... -MMD -MP -MF "$(#:%.o=%.d)" -MT "$(#:%.o=%.d)" -o "$#" "$<"
is:
Use gcc to compile the 1st prerequisite file ($<) and generate the
output file named after the current rule target's name (%#). And by
the way, generate a makefile named as *.d containing a rule to describe the dependency of current rule target. And change the name of rule target in the
generated *.d makefile from *.o to *.d.

Makefile implicit rule matching - prefix length not affecting match

In my gnu-make-3.81 Makefile, I wish to define two implicit rules, such that the more specific first one takes precedence over the more general second one:
src/%_bar.o : src/%_bar.c
$(CC) -Wall -Wno-unused-but-set-variable -c $^ -o $#
src/%.o : src/%.c
$(CC) -Wall -c $^ -o $#
The issue I have is that foo_bar.c represents autogenerated code that triggers a warning with -Wall that I'd prefer to suppress, so the first rule is meant to catch this special case.
According to make's manual:
It is possible that more than one pattern rule will meet these criteria. In that case, make will choose the rule with the shortest stem (that is, the pattern that matches most specifically).
I thought that for a filename of src/foo_bar.o, the first rule would generate the stem foo, and the second would generate foo_bar. The former is the shortest so I'd expect it to apply. However this doesn't seem to be the case, the second rule is selected by make and executed. Running make -d doesn't even show an attempt to match with the stem foo - only foo_bar is considered.
If I make the following change, by making the second rule's stem deliberately longer by shortening the prefix from src/ to sr, the second rule is still selected:
src/%_bar.o : src/%_bar.c
$(CC) -Wall -Wno-unused-but-set-variable -c $^ -o $#
sr%.o : sr%.c
$(CC) -Wall -c $^ -o $#
I can't reconcile this with the make documentation.
In addition, if I remove the src/ prefix entirely, the second rule is selected:
src/%_bar.o : src/%_bar.c
$(CC) -Wall -Wno-unused-but-set-variable -c $^ -o $#
%.o : %.c
$(CC) -Wall -c $^ -o $#
Although this solves my problem, it's actually not suitable because it overrides/interacts with another implicit rule on the current directory that I need to keep:
%.o : %.c
# do something else
My question is why does make behave this way in this case, and is this consistent with the documentation? If so, is there a better way to specify a more specialised implicit rule?
First, be aware that the "shortest stem" method of pattern matching was introduced in GNU make 3.82. If you're using GNU make 3.81 then your version of make uses the old method which was "first match". It's always best to read the documentation that comes with your distribution, if possible, rather than the web documentation because the web documentation is for the latest version of GNU make. GNU make 3.81 was released in April 2006... that's pretty old.
However, the example you provided actually DOES work the way you wanted it to:
src/%_bar.o : src/%_bar.c ; #echo shorter: $*
src/%.o : src/%.c ; #echo longer: $*
all: src/foo_bar.o
$ make-3.81
shorter: foo
$ make-3.82
shorter: foo
I suspect that when you asked your question here you didn't use the same code you're using in your real environment. In that environment you must have the shorter pattern after the longer pattern, like this:
src/%.o : src/%.c ; #echo longer: $*
src/%_bar.o : src/%_bar.c ; #echo shorter: $*
all: src/foo_bar.o
$ make-3.81
longer: foo_bar
$ make-3.82
shorter: foo
When asking questions it's very important to be sure that the simplified examples in the question accurately reflect the real situation.

getting the target name in a function in prerequisites list [makefile]

I'm trying to create a makefile where the target is used to search for dependencies in .d
Thanks to the answers here and here I have discovered that .SECONDEXPANSION: does the job. However I'm running into an issue nesting functions which is seemingly bizarre. The offending rule looks like this:
.SECONDEXPANSION:
$(APPS): %: $$(patsubst %.c,%.o,$$(wildcard $$#.d/*.c)) $$(INC_OBJS)
$(CC) $(CFLAGS) $^ -o $#
instead of:
gcc -Wall -std=c99 unittest.d/unittest.o common/cards.o -o unittest
which is what I want, I get:
gcc -Wall -std=c99 unittest.d/unittest.c common/cards.o -o unittest
which for some reason doesn't have the .o substituted for the .c. So it appears I'm almost there, I just need to get the substitution working. All help appreciated and if you think this is a poor way to organize a makefile, critizism on that front welcome.
The problem is that you're trying to use % as two different wildcards at once, the static pattern stem and the patsubst wildcard. So Make makes the stem replacement and gets this:
$(patsubst unittest.c,unittest.o,$(wildcard $#.d/*.c))
and then patsubst does nothing, because it finds no "unittest.c" to replace. (Note that the "unittest.c" in "unittest.d/unittest.c" doesn't match, because without a wildcard, patsubst looks for a perfect match.)
There's no need for this to be a static pattern rule (you never use that functionality), so you can just eliminate that part and the rest should work:
.SECONDEXPANSION:
$(APPS): $$(patsubst %.c,%.o,$$(wildcard $$#.d/*.c)) $$(INC_OBJS)
$(CC) $(CFLAGS) $^ -o $#

GNU make not recognizing %

I'm trying to make a makefile for compiling various examples that are within a subfolder. The makefile consisting of just:
S_1_2.exe : Twister.cpp Parsing.cpp ./Surfaces/S_1_2.cpp
g++ -o $#.exe $^ -I . -W -Wall
Works fine when run with the command "make S_1_2.exe". However:
%S_1_2.exe : Twister.cpp Parsing.cpp ./Surfaces/S_1_2.cpp
g++ -o $#.exe $^ -I . -W -Wall
fails, even when run with the command make S_1_2.exe, with the error "make: * No rule to make target 'S_1_2.exe'. Stop."
Shouldn't %S_1_2.exe do pattern matching and so match S_1_2.exe? In which case why is it not matching this rule?
I am using GNU Make 3.81
The percentage symbol matches a non-empty string. So you should use %_1_2.exe or better yet - %.exe. I don't know if there is any other symbol that matches empty strings too.
The % is for matching a part of the target against the same part in one or more dependencies.
You can't omit it from all dependencies.

Resources