Below is a snippet from Caffe's Makefile.
TEST_BIN_DIR = build/test
$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CXX_BUILD_DIR)/%.o $(GTEST_OBJ) | $(DYNAMIC_NAME) $(TEST_BIN_DIR)
# echo LD $<
$(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) \
-o $# $(LINKFLAGS) $(LDFLAGS) -l$(LIBRARY_NAME) -Wl,-rpath,$(ORIGIN)/../lib
What's the meaning of the colon (:) in the TEST_CXX_BINS's prerequisite? Is it defining another rule in the prerequisite?
It's not the standard implicit rule or pattern rule. I've searched the web and GNU Make manual, find nothing for reference.
It's a static pattern rule. The first part (left to first colon) is a list of targets. The second part defines a pattern to match against each target. The % stem that matches can then be used (or not) in the third part (right to the second colon) that lists the prerequisites. In your example TEST_CXX_BINS is supposed to be a list of targets. If one of these targets is, let's say, $(TEST_BIN_DIR)/foo.testbin (build/test/foo.testbin), then the following rule will be used for it:
$(TEST_BIN_DIR)/foo.testbin: $(TEST_CXX_BUILD_DIR)/foo.o $(GTEST_OBJ) | $(DYNAMIC_NAME) $(TEST_BIN_DIR)
# echo LD $<
$(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) \
-o $# $(LINKFLAGS) $(LDFLAGS) -l$(LIBRARY_NAME) -Wl,-rpath,$(ORIGIN)/../lib
Note that the pre-requisites after the | are ordered pre-requisites: they must exist and are created if they don't, but if they do, make will not check whether they are more recent or not than the target.
Note also that the stem that matched can also be referred to in the recipe, thanks to the $* automatic variable.
Related
Having this simple makefile:
VPATH = include
CC := gcc
CFLAGS := -I include -Wall -pedantic
%: %.o include.o
$(CC) -o $# $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
When I trigger it with the name of a program (the same name as is source with .c extension), I would expect to trigger the first rule (since I provided just a name without extension) and the the second one, because for the first rule, there is %.o prerequisite, which is exactly the second rule.
Having these file in pwd:
client.c include makefile server6.c server.c
Now If I make make server:
It does
gcc -I include -Wall -pedantic server.c -o server
In other words, The second rule is not triggered. there is no step with makeing object files, even though the object file is in the first rule as prerequisite. So how is that possible? The make is simply ignoring the prerequisite and trying to make just with the first rule. How to fix that?
That's because make has a built-in rule for %: %.c and make will always choose a pattern rule that can directly create the target over a pattern rule that requires another pattern rule:
Note however, that a rule whose prerequisites actually exist or are mentioned always takes priority over a rule with prerequisites that must be made by chaining other implicit rules.
You can run make -r to remove all the built-in rules, or else remove it yourself by adding:
% : %.c
to your makefile.
You can see all built-in rules by running make -p -f/dev/null
Googling doesn't help much in understand how the % variable is being used in the Makefile snippet below.
_OBJ = a.o b.o c.o
OBJ = $(patsubst %,$(OBJDIR)/%,$(_OBJ))
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(INC)
$(CC) -c -o $# $< $(CFLAGS)
Can anybody please help me out? Does it mean that if there are five .c files present under $(SRCDIR), that many *.o rules are being populated behind the scene?
That is an "implicit rule". The % makes the word $(OBJDIR)/%.o a pattern. It tells make that if it's trying to build a target and the name of the target matches that pattern (where the % can substitute for one or more characters--any characters), AND that a file that matches the pattern $(SRCDIR)/%.c (where the % here has the same value as in the target) either already exists or can be built, then make can use this recipe to build that target.
So, if make wants to build a file foo/bar.o and the variable OBJDIR has the value foo, then this pattern foo/%.o will match that file with the % matching bar (this is called the stem in the GNU make documentation).
Then if SRCDIR has the value blah and make can find (or create) a file named blah/bar.c, then this implicit rule can be used to build the target foo/bar.o by running this recipe ($(CC) -c -o $# $< $(CFLAGS)).
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.
I was reading gnu make section 10.5.4 "How patterns match" and it does not sound like I can do what I want.
I want to setup a directory structure where my source code is in one directory, and there are sub-directories to hold object files.
One sub-directory for each build configuration.
So I might have these files
a.c
debug/a.o # compiled with -g
release/a.o # compiled with -O
So I would like to make rules like this
debug/%.o : %.c
gcc -c -g %.c -o $#
release/%.o : %.c
gcc -c -O %.c -o $#
But section 10.5.4 tells me a match on "debug/a.o" will make the stem be "debug/a" so gnu make
will look for the source file at "debug/a.c" which is not what I want.
Is there a way to get GNU make to help me ?
Your makefile will work as written.
From that section of the manual:
When the target pattern does not contain a slash (and it usually does
not), directory names in the file names are removed from the file name
before it is compared with the target prefix and suffix. After the
comparison of the file name to the target pattern, the directory
names, along with the slash that ends them, are added on to the
prerequisite file names generated from the pattern rule's prerequisite
patterns... [bold added]
Your target patterns do contain slashes.
Try it if you don't believe me.
EDIT:
Correction: in the commands you should use $< rather than %.c.
CC=gcc
DEBUGFLAGS=-g
RELEASEFLAGS=-O
debug/%.o : %.c
$(CC) $(DEBUGFLAGS) -c $< -o $#
release/%.o : %.c
$(CC) $(RELEASEFLAGS) -c $< -o $#
consider the following fragment of my makefile:
gui_backend: $(BUILDDIR)/gui_backend
$(BUILDDIR)/gui_backend: $(BUILDDIR)/gui_backend.o $(BUILDDIR)/config.pb.o
$(CXX) $(LDFLAGS) -o $# $^
$(BUILDDIR)/%.o: $(SRCDIR)/%.cc $(SRCDIR)/%.h | $(BUILDDIR)
$(CXX) $(CXXFLAGS) -c -o $# $<
$(SRCDIR)/%.pb.cc: $(PROTODIR)/%.proto
$(PROTOC) $(PROTOOPTIONS) --cpp_out=$(SRCDIR) $<
now if I call to make gui_backend, I get
make: *** No rule to make target `build/config.pb.o', needed by `build/gui_backend'.
Why doesn't make pick up on the $(BUILDDIR)/%.o pattern here? If I state things explicitly by adding the rule
$(BUILDDIR)/config.pb.o: $(SRCDIR)/config.pb.cc $(SRCDIR)/config.pb.h | $(BUILDDIR)
$(CXX) $(CXXFLAGS) -c -o $# $<
it seems to work. However, I would like to keep the makefile as concise as possible.
Running make with -d gives me the following (complete output here):
Considering target file `build/config.pb.o'.
File `build/config.pb.o' does not exist.
Looking for an implicit rule for `build/config.pb.o'.
Trying pattern rule with stem `config.pb'.
Trying implicit prerequisite `src/config.pb.cc'.
Trying pattern rule with stem `config.pb'.
Trying implicit prerequisite `build/config.pb.c'.
Trying pattern rule with stem `config.pb'.
Trying implicit prerequisite `build/config.pb.cc'.
Trying pattern rule with stem `config.pb'.
[...]
Trying implicit prerequisite `build/SCCS/s.config.pb.o'.
Trying pattern rule with stem `config.pb'.
Trying implicit prerequisite `src/config.pb.cc'.
Looking for a rule with intermediate file `src/config.pb.cc'.
Avoiding implicit rule recursion.
Trying pattern rule with stem `config'.
Trying implicit prerequisite `src/proto/config.proto'.
[...]
I'm running GNU Make 3.81, btw.
Also, I just noticed that if I run make src/config.pb.cc and then make build/config.pb.o manually, it works.
Why doesn't this work?
Your example looks correct to me. The only difference between the pattern rule and the explicit rule I see is that the explicit rule doesn't have the order-only prerequisite. What version of GNU make are you running? Are you sure it supports order-only prerequisites? If it doesn't then the pattern rule will not match as it's trying to find a way to build a target like | and can't.
Whenever you hit issues like this the simplest thing to do is run make -d. The output is voluminous but it is also very enlightening: find the section where it's trying to build config.pb.o and see what patterns it's trying and why it decides to give up on that one.
I am also building proto files, I am using these Makefile targets:
%.pb.cpp: %.proto
protoc --cpp_out=. $<
mv $(#:cpp=cc) $#
%.pb.h: %.pb.cpp ;
build/%.o: %.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) $(NON_PROFILE_CXXFLAGS) -MD -MF $(#:%.o=%.d) -MT $# -c $< -o $#
I can execute
rm -rf build/lsm.pb.o lsm.pb.h lsm.pb.cpp
make build/lsm.pb.o
And it correctly finds the dependencies. For me, I was unable to get this to work until I added the semicolon to the end of the first rule. For some reason, Make does not like empty recipes for pattern rules.
Six year old question at this point, but hopefully this answer can help others like me who end up here.