Why this rule cannot override the default implicit rule ?
When make is invoked like: make myapp (suppose myapp.c is there). The make runs the default command to build and link the program instead the commands defined in this implicit rule:
#... omitted code
LCUS=$(LIBS)/libcus.a
#... omitted code
% : %.o $(LCUS)
echo !!! Custom build !!!
$(MY_CMD) $< -o $# $(LCUS)
Taken from the GNU online make manual:
You can override a built-in implicit rule (or one you have defined
yourself) by defining a new pattern rule with the same target and
prerequisites, but different commands.
So I would assume it is because the prerequisites are not the same as the implicit rule.
Also take from the make manual:
Linking a single object file n is made automatically from n.o by
running the linker (usually called ld) via the C compiler. The
precise command used is $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS).
This rule does the right thing for a simple program with only one
source file. It will also do the right thing if there are multiple
object files (presumably coming from various other source files), one
of which has a name matching that of the executable file. Thus,
x: y.o z.o
when x.c, y.c and z.c all exist will execute:
cc -c x.c -o x.o
cc -c y.c -o y.o
cc -c z.c -o z.o
cc x.o y.o z.o -o x
rm -f x.o
rm -f y.o
rm -f z.o
So basically make understands implicit rules for program files that are generated from .o files but when you throw in your static library it doesn't understand. A simple way to test would be to remove $(LCUS) from your dependencies (as a temporary measure) to see if it then uses your rule instead of the built in one. If it does then you know that is your problem. If simply adding myapp in replace of % is a problem because you want the rule to build multiple targets you can try the following:
$(APPS): % : %.o $(LCUS)
where $(APPS) is a variable containing all the applications you wish to build. This will allow one rule to build multiple targets. You could also skip the use of the variable altogether and place a space separated list. This is an example of a static pattern rule, more information can be found here. The difference between static pattern and implicit rules can be found here.
Your rule isn't the same as the built-in implicit rule so it doesn't cancel it.
Additionally, make always prefers a rule that doesn't require intermediate files to be built to one that does. If you pre-create the .a file make might use your rule instead (but it might not even still).
If you cancel the built-in rule and leave your rule in place it should work correctly I believe.
Related
I'm quite new to makefiles, and I'm wondering what exactly is the role of the library in this format:
app: app.o mylibrary.a
$(LD) -o $# $(LDFLAGS) app.o mylibrary.a
What I usually see would be something like this:
app: app.o
$(LD) -o app $(LDFLAGS) $^ mylibrary.a
My understanding for this format is that the executable will be made from the app.o file, which has a dependency on mylibrary.a.
I can't quite understand the difference/meaning of the first version though.
Where the $# is the target is substituted, in the first case that would be app.
Although they aren't defined in the question, the $(LD) and $(CFLAGS) are usually defined as the c-compiler and the flags to use in the compiler.
E.g. something like CFLAGS = -g -Wall -std=c99 -lstdc++ would be a defined line at the top of the Makefile.
I'd usually write these as the first two parts of the command to run for the target.
The $^ indicates to substitute everything that is listed as a dependency of the target. In the first row the dependencies are app.o mylibrary.a whereas in the second it is only app.o. These ($^, $#)are usually used to simplify the writing of make rules.
The choice of whether to use the wildcards-as these are called-is really your own choice. I usually use them because they make it easier to write and maintain.
So to answer your question the main difference is where you explicitly need to place the name of the file.
Additional note on dependencies
The files in the line where there are dependencies of the target listed are used by make to determine which targets need to be rerun. Make does a topological sort of the dependencies and if something changes-based on last touched time of file-the make command will rerun the target if it is within the path of the make target that is being called.
I have this makefile which I don't understand.
build_sources:=$(wildcard *.cpp)
depends:=$(build_sources:.cpp=.d)
build_targets:=$(build_sources:.cpp=)
.PHONY: all
all: $(build_targets)
.PHONY: clean
clean:
rm -f $(build_targets) *.{a,o,d}
#build the list of header file dependencies automatically
%.d: %.cpp
#echo building include dependencies for $(*F)
#$(CXX) -MM $(CPPFLAGS) $< | { sed 's#\($*\)\.o[ :]*#\1.o $# : #g' ; echo "%.h:;" ; } > $#
-include $(depends)
I understand that the executables created are build_target. So if I have Foo.cpp and Bar.cpp, the executables created would be Foo and Bar.
But how does it do that? I only see 1 rule, and it is %.d: %.cpp. So it's saying the Foo.d file depends on Foo.cpp. But what about the rule to actually compile Foo?
This makefile works, so it's not actually missing anything. But how come I don't see the rule? Is there some implicit rule?
EDIT - i did make debug, and saw the following
No need to remake target `foo.d'.
Considering target file `foo'.
File `foo' does not exist.
Looking for an implicit rule for `foo'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.o'.
Found an implicit rule for `foo'. ## WHAT EXACTLY IS THIS?
Considering target file `foo.o'.
File `foo.o' does not exist.
Looking for an implicit rule for `foo.o'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.c'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.cc'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.C'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.cpp'.
Found an implicit rule for `foo.o'.
Pruning file `foo.cpp'.
Pruning file `foo.cpp'.
Finished prerequisites of target file `foo.o'.
Must remake target `foo.o'.
g++ -I../../include -Wall -std=c++11 -O3 -Wsign-compare -Wno-strict-aliasing -s -c -o foo.o foo.cpp
That's great. This must be the rule that's getting called. But where is this rule from? How do I know what default rules exist?
What you probably miss to understand this Makefile is the concept of pattern rule and automatic variables.
This part finds .cpp files:
build_sources:=$(wildcard *.cpp)
And this part creates targets with the same name (using the variable build_sources defined above) except the extension is replaced by .d:
depends:=$(build_sources:.cpp=.d)
The same kind of construction defines the build targets (same file name with extension removed):
build_targets:=$(build_sources:.cpp=)
Then the default target is defined to require build_targets, i.e the executable corresponding to the .cpp`
all: $(build_targets)
This rule defines how to build a .d from a .cpp:
#build the list of header file dependencies automatically
%.d: %.cpp
#echo building include dependencies for $(*F)
#$(CXX) -MM $(CPPFLAGS) $< | { sed 's#\($*\)\.o[ :]*#\1.o $# : #g' ; echo "%.h:;" ; } > $#
gcc -MM produce rules to know on which headers a .c or .cpp file depend. Typically if test.cpp includes test1.h and test2.h the output will be:
test.o: test.cpp test1.h test2.h
The .d will contain dependencies of each cpp file and will create a ruleto build a .o file and an executable from each cpp. $# is the target of the rule (the .d file) and will contain, unless I'm mistaken, a rule looking like this (written by the sed expression):
filename.o filename.d : filename.cpp <list of headers>
%.h:;
The first rule give dependencies of the .o files. It has no recipe which means it simply adds dependencies to any existing rule. An implicit rule will be used to build them.
The second one is here in case you suppress a header. In this case, make will use this rule that says that there's simply nothing to do (it has an empty recipe).
Then all the .d files are included as part of the makefile:
-include $(depends)
Finally, the implicit rule to link a single .o file kicks in:
Linking a single object file
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
Edit: To build objects in a subdirectory obj you would have to modify each filename:
depends:=$(foreach file,$(build_sources:.cpp=.d),"obj/$(file)")
To build binaries in a separate subdirectory bin you would need to do the same for build_targets:
build_targets:=$(foreach file,$(build_sources:.cpp=), "bin/$(file)")
Then you need to write the rule to build it because the default rule wont work anymore (the .o is not in the same directory). What you want is to add a rule like this:
bin/foo: obj/foo.o
$(CC) $(LDFLAGS) obj/foo.o $(LOADLIBES) $(LDLIBS) -o bin/foo
which can be done with the right modification of the long shell command:
#$(CXX) -MM $(CPPFLAGS) $< | { sed 's#\($*\)\.o[ :]*#\1.o $# : #g' ; echo "%.h:;" ; obj=`echo $< | sed 's/.cpp/.o/'` ; bin=`echo $< | sed 's/.cpp//'` ; echo "$bin: $obj" ; echo -e "\t\$(CC) \$(LDFLAGS) $obj \$(LOADLIBES) \$(LDLIBS) -o $bin" ; } > $#
Your make package includes a large number of default rules, which this Makefile depends on. Try running your make with -d (debug info). I believe that will show you everything that is in play.
Many rules are built in to Make. If you are using GNU Make, you can get it to print its built-in rules like this:
make -f /dev/null -p
You can make it ignore the built-in rules with -r; if you do this with your Makefile, you'll find that it complains that it doesn't know how to make your targets.
The makefile is't complete in itself. It automatically creates the files .d which are snippets included into that makefile at the end. These files are created with the %.d-rule.
So have a look at those generated .d files to see rules for each individual object file. The rule generation script is written with sed and kind of hard to read, but in fact very simple. At first, the compiler is invoked on the .cpp file with the -MM flag, which will output something like
foo.o: foo.cpp foo.h bar.h
if foo.cpp includes its own header file foo.h as well as bar.h, for example (directly or indirectly).
The sed regex replacement command now simply adds the name of the file, in which the generated rules are about to be written (the .d file) right after the .o in the above rule, so it is also marked as depending on the sources, just like the object file. That's important when the includes in one of the sources is changed later. The sed command also adds a rule for all header files to do nothing.
foo.o foo.d: foo.cpp foo.h bar.h
%.h:;
The resulting object files .o are then linked using one of the implicit rules:
Linking a single object file
n is made automatically from n.o by
running the linker (usually called ld) via the C compiler. The precise
recipe used is $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS).
[...]
I seem to be having an issue getting my makefile to build my C++ file correctly. My makefile code is below; the file I am trying to compile is named "avl.cc" (which is working and compiles properly).
CC=g++
CFLAGS=-g -O2
PROGS=avl
all: $(PROGS)
$#:
$(CC) $(CFLAGS) $# $#.cc
.PHONY: clean
clean:
rm $(PROGS)
However, when I enter the command make or make all, I get
c++ avl.cc -o avl
And the debugging symbols I want from the -g flag don't come up. A similar makefile (only changing the PROGS variable) worked for a similar project, so I am not sure what I'm doing wrong. Does anyone have any tips? Thanks!
From Makefile documentation about automatic variables:
It’s very important that you recognize the limited scope in which
automatic variable values are available: they only have values within
the recipe. In particular, you cannot use them anywhere within the
target list of a rule; they have no value there and will expand to the
empty string.
This means you cannot use $# as a rule, which means the default c++ compilation rule of Makefile is used, and since you did not use the correct variable names for c++ compilation, they are also ignored.
You can replace CC by CXX and CFLAGS by CXXFLAGS to work with c++.
You don't have a target for 'avl', so make uses a default rule.
Try changing the makefile to this:
CC=g++
CFLAGS=-g -O2
PROGS=avl
all: $(PROGS)
$(PROGS):
$(CC) $(CFLAGS) -o $# $#.cc
.PHONY: clean
clean:
rm $(PROGS)
I had the exact same question but a much different source of the problem. There were typos or misnamed files in my makefile. Make found no rules for such files but tried to compile targets with the c++ compiler. This made the process seem like it was ignoring my rules and imposing its own, switching compilers since I needed g++. Finally I tried using the -r option, and then the resulting different error messages allowed me to figure out what was really wrong. Below is the entry from the make man page for option -r.
-r, --no-builtin-rules
Eliminate use of the built-in implicit rules. Also clear out the default
list of suffixes for suffix rules.
I have a makefile in my src directory.
The makefile should build the data structures, which are in DataStructures/, and then iterate over all cpp files in calculations/ and create a corresponding .so file in ../bin/calculations
I tried the following syntax:
DAST = DataStructures/
COMPS = computations/
BIN = ../bin/
OBJECTS = ${DAST}Atom.o ${DAST}Molecule.o
COMPILE = g++ -Wall -g -c -std=c++0x -I/usr/local/include/openbabel-2.0 LINK = g++ -Wall -g -std=c++0x ${OBJECTS} -lopenbabel -I/usr/local/include/openbabel-2.0
all: ${BIN}main ${DAST}Molecule.o ${DAST}Atom.o ${BIN}${COMPS}%.so
${BIN}main: ${OBJECTS} main.cpp
${LINK} main.cpp -o ${BIN}main
${DAST}Molecule.o: ${DAST}Molecule.h ${DAST}Molecule.cpp
${COMPILE} ${DAST}Molecule.cpp -o ${DAST}Molecule.o
${DAST}Atom.o: ${DAST}Atom.h ${DAST}Atom.cpp
${COMPILE} ${DAST}Atom.cpp -o ${DAST}Atom.o
${BIN}${COMPS}%.o: ${COMPS}%.cpp
gcc -Wall -fPIC -c -lopenbabel $< -I/usr/local/include/openbabel-2.0 -std=c++0x
${BIN}${COMPS}%.so: ${COMPS}%.o
gcc -shared -Wl,-soname,libcsmtest.so.1 -o libcsmtest.so $#
clean:
rm -rf ${OBJECTS}
.PHONY: all clean
But it obviously doesn't work, as I get the following output:
shai#ubuntu:~/csm/csm2/src$ make all
make: *** No rule to make target `../bin/computations/%.so', needed by 'all'. Stop.
thanks
You need to specify in the all: target, the prerequisites explicitly.
In Makefile parlance, % is a wildcard that can be used in automatic rules. However, the all: target is a simple target with no such wildcard, thus ${BIN}${COMPS}%.so is wrong in that context.
Please note that when I say 'wildcard' in this context, this wildcard matches the target against the prerequisites, not against the filesystem like * do in glob expressions.
Also, while your hart is in the right place, as a matter of style, your Makefile can be better:
Intermediary objects, should not be prerequisites of the all target, but only the final targets you wish to ship.
There is a mix of automatic and simple rules to specify the creation of objects.
Typically one doesn't write an automatic rule for %.so, because a library is often constructed from more than one object.
The dependencies between an object and header files is a complex issue. In short you need to specify that the resulting object depends on the *.cpp (or .c) as well as all the headers included (directly and indirectly) by the *.cpp file.
By convention, that is well supported by GNU make, instead of using ${COMPILE} as you do, one should use $(CXX) for your C++ compiler, and $(CXXFLAGS) for the standard flags you wish to pass to that compiler.
You need something like
SOBJECTS = ...
all: ${BIN}main ${SOBJECTS}
...
You need a way to gather all the *.so names in the variable SOBJECTS. You can do this manually, or use some of make's internal functions to scan the source directory.
Also notice that I removed the two *.o files as dependencies from the all target. They are not final goals of the build (I assume), so you don't need to mention them there.
Besides this there are other stylistic points which I would do differently, but at the moment they are not causing immediate problems, so I won't digress, but I advise you to have a look at some tutorials to see how things are done generally.
For starters, look at Paul's Rules of Makefiles, and How Not to Use VPATH.
I know I am doing it wrong, but I can't figure out how to organize this makefile. I define my util source files, and use some functions to define the .o files from them here:
UTIL_SRC = utils/src/foo.cpp utils/src/bar.cpp utils/src/baz.cpp
UTIL_OBJS = $(patsubst utils/src/%.cpp,utils/obj/%.o,$(UTIL_SRC))
This is the target that I use these files for:
lib : lib/libutils.a
lib/libutils.a : $(UTIL_OBJS)
rm -f lib/libutils.a
ar -c -q lib/libutils.a $(UTIL_OBJS)
Then, when I get to the rule to compile these babies, I would love to just have one command that would iterate through each UTIL_OBJS file and each UTIL_SRC file. Instead I have resorted to this monstrosity, which defeats the purpose of storing them in variables.
$(UTIL_OBJS) : $(UTIL_SRC)
g++ $(UTIL_FLAGS) utils/src/foo.cpp -o utils/obj/foo.o
g++ $(UTIL_FLAGS) utils/src/bar.cpp -o utils/obj/bar.o
g++ $(UTIL_FLAGS) utils/src/baz.cpp -o utils/obj/baz.o
Can I condense this down to one line? How? Thanks, great ones!
It's usually easier to work with implicit rules. There are a lot of predefined ones, where you'll only need to specify variables.
CXX=g++
CXXFLAGS=$(UTIL_FLAGS)
Then you need to define an executable, like this
myutil: $(UTIL_OBJS)
Since you're not storing your objects in the same directory, you'll need to specify a new implicit rule as well though (otherwise, we'd be done now).
utils/obj/%.o: utils/obj/%.cpp
% is a pattern-match, it'll match the same text on both left and right side, so this rule will make foo.o out of foo.cpp.
Try if that'll work without the command (it might have grabbed that from another rule, I'm not sure), otherwise let it say:
utils/obj/%.o: utils/obj/%.cpp
$(CXX) $(CXXFLAGS) -o $# $^
$# is the target of the rule (e.g. foo.o), and $^ is all files on the right hand side.
I'm writing this off the top of my head, without the possibility to test it, so please let me know how it turned out.. :)
To make it even more elegant, you can include a dependency file
include .depend
If you're running GNU make, it'll try to make the .depend file if it can't find it (with old school make, you need to create it yourself first, it can be just a dummy though, if you'd like to manage it through the makefile)
.depend: $(UTIL_SRC)
$(CXX) -MM -o $# $^
The dependency file will contain lines for each .cpp file, telling make what header files it needs, which will allow make to recompile the necessary files when you change something. This doesn't help with your original question though, just thought it might come in handy.
EDIT:
As a response to your edit. You could probably drop the commands for creating the .a-file as well, that too is already available as an implicit rule. Not sure exactly how it works though, haven't used it much. I do know that there are a bunch of quirks in make for dealing with .a(rchive?)-files.
I think you could use this:
$(UTIL_OBJS) : $(UTIL_SRC)
g++ $(UTIL_FLAGS) $(# : .o = .cpp) -o $#
again, I'm not quite sure... especialy about the $(# : .cpp = .o) part