I know the following makefile will have the pre-processor automatically generate dependencies (in .d files) and include them in the makefile (because my course notes say so), so that they do not have to be automatically maintained. The -MMD
flag is what's responsible for this. What I don't get is: At what point are the .d files generated? There isn't even any command where ${CXXFLAGS}
is used. Presumably, commands like ${CXX} ${CXXFLAGS} -c x.C -o x.o
will be automatically deduced by make for each of the object files, but if these are the commands that generate the .d files, wouldn't we have already passed the point where knowing the dependencies of x.o, y.o and z.o could've been relevant, if we only know them by executing the commands that generate these .o files? (Say there are .h files that the makefile would ignore if left to deduce the rules on its own or something.)
CXX = g++ # compiler
CXXFLAGS = -g -Wall -MMD # compiler flags
OBJECTS = x.o y.o z.o # object files forming executable
DEPENDS = ${OBJECTS:.o=.d} # substitutes ".o" with ".d"
EXEC = a.out # executable name
${EXEC} : ${OBJECTS} # link step
${CXX} ${OBJECTS} -o ${EXEC}
-include ${DEPENDS} # copies files x.d, y.d, z.d (if they exist)
$@ is the name of the target being generated, and $< the first prerequisite (usually a source file). You can find a list of all these special variables in the GNU Make manual.
The special rule . PHONY is used to specify that the target is not a file. Common uses are clean and all . This way it won't conflict if you have files named clean or all .
A dependency is a file that is used as input to create the target. A target often depends on several files. A command is an action that make carries out. A rule may have more than one command, each on its own line.
The -f flag in make is defined as follows, make -f makefile Specifies a different makefile . The argument makefile is a pathname of a description file, which is also referred to as the makefile. A pathname of '-' shall denote the standard input.
Presumably, commands like
${CXX} ${CXXFLAGS} -c x.C -o x.o
will be automatically deduced by make for each of the object files, but if these are the commands that generate the .d files, wouldn't we have already passed the point where knowing the dependencies of x.o, y.o and z.o could've been relevant, if we only know them by executing the commands that generate these .o files?
You're correct here. The dependencies aren't present the first time the Makefile is run.
But this doesn't matter - the dependency information is only needed when .o files are already present, and you've changed a .h file. The first time you run Make, all .o files will need to be built anyway, and the .d files are generated at the same time.
After that, the .d files will give dependency information. If a header is changed, the dependency information will tell Make which .o files need rebuilding. If a source file is changed, the .o will always need to be rebuilt, and updated dependency information will be generated at the same time.
If you ever wonder what's being done by the makefile behind your back, use the -p flag, and redirect the output to a file because it's a ton of stuff.
make -p foo > bar
will dump out all the variable values and rules for a make foo
, then looking in bar
will show you what commands are run for the implicit rules. In your case it would have shown you that the .cpp.o
or %.o: %.cpp
(strangely they're both there) rule will call $(COMPILE.cpp)
which resolves to $(COMPILE.cc)
which resolves to $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
. Which has the interesting property that you can add things to either CXXFLAGS or CPPFLAGS to get them into your .cpp.o compiles, but not CFLAGS, which is only used by the .c.o
rules, which makes a little sense because you probably want your C files and C++ files dealt with differently (CC and CXX are usually set to different compilers, too).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With