Suppose the source files are foo.cpp
and bar.cpp
, and the headers are foo.h
and bar.h
, such that foo.cpp
includes foo.h
and bar.h
, and bar.cpp
includes bar.h
.
You can have a simple makefile that does not involve dependency files at all:
project: $(OBJECTS)
...
%.o: %.cpp
...
Now if you modify foo.cpp
, Make will rebuild foo.o
(and project
). If you modify bar.cpp
, Make will rebuild bar.o
(and project
). If you modify a header, Make will do nothing, because Make doesn't know that the objects depend in any way upon the headers.
You can put in a rule for dependency files:
project: $(OBJECTS)
...
%.o: %.cpp
...
%.d:
...
-include *.d
Now Make will build and use the dependency files-- if you remember to tell it to. If you do that, Make will know that when you modify foo.h
it must rebuild foo.o
, and when you modify bar.h
it must rebuild foo.o
and bar.o
.
Remembering to rebuild dependency files is a pain. It would be better to let Make do it. When must foo.d
be rebuilt? Well, when foo.cpp
is modified, certainly:
project: $(OBJECTS)
...
%.o: %.cpp
...
%.d: %.cpp
...
-include *.d
But foo.d
must also be rebuilt when any of the other prerequisites of foo.o
(i.e. foo.h
or bar.h
) has been modified. I haven't spelled out the commands in the rules (and I can't make much sense of the command in your %.d
rule), but a simple rule will build a foo.d
that looks like this:
foo.o: foo.cpp foo.h bar.h
It is possible to write a command that will produce a foo.d
that looks like this:
foo.o: foo.cpp foo.h bar.h
foo.d: foo.cpp foo.h bar.h
There are more sophisticated methods, but this is enough for today.
As to why many example makefiles share a certain sub-optimal feature, it's because people copy each others' makefiles without rigorously examining or understanding every feature.