I like to use the g++ -MM
feature to auto-build my dependencies. The way I do this is as follows:
include $(ALLOBJ:%.o=%.d)
%.d: %.cxx
@echo making dependencies for $<
@g++ -MM $(CXXFLAGS) $< -o $@
@sed -i 's,$*\.o,& $@ ,g' $@
Basically I can give this rule ALLOBJ
, and it will:
- convert every
.o
name to a.d
name, andinclude
it, - when it can't find a
.d
, it will create it from the.cxx
file- the final line of the
%.d: %.cxx
rule will add the name of the.d
file to the file itself, so that the dependency will be updated automatically.
- the final line of the
The issue arises when I remove a header: the .d
file still expects to find it, and make will get upset when it's not there. One solution is to replace include
with -include
, and to build the dependencies within the compile rule. Unfortunately this requires a dependency generation line for each compile rule, and will also ignore all other include
errors (which seems risky). Is there some other simple way to auto-build dependencies which avoids this issue?
Reading the g++ manual a bit more, and thanks to @jackKelly and @Beta's responses above, I found the following solution:
To summarize the flags:
-MM
: build dependencies (rather than compiling)-MP
: build 'dummy' targets for all headers. This prevents make from complaining when headers are deleted and thus can't be found.-MT
: specify the targets for the rule. This allows us to tell make the.d
file depends on the headers without resorting to the ugly sed rule.I don't believe my solution is any more correct than @Beta's solution. I tend to use multiple compile rules for C++ files in the same makefile, so having a single dependency rule for all of them is slightly cleaner (in my case) than generating the dependencies in each compile rule.
To restate my answer to the other question, I do it this way:
EDIT:
It... It produces the dependency file, but more cleanly and without the
sed
command:So now I have to modify the
%.o
rule in my own makefiles. From now on there'll be a little bit of @JackKelly in everything I compile, mocking me. Oh, this is a black day.