I'm using gmake and gcc -MM
to track header dependencies, following the manual. The mechanism relies on a makefile include
directive to import the computed dependencies.
Because the .d
files are included by the makefile, they must exist for any target to be made, including clean
. So before clean
can do the right thing, the dependencies must be generated, and if one fails to build then clean
just made more mess.
Besides clean
, it wants to make all the dependencies before building any target.
Furthermore, if any file is changed to include a nonexistent file, then the dependency resolution breaks and nothing at all will build.
If a header is deleted, then the existing dependency files contain still name it as a target, and nothing will build until the offending dependency files are removed… which can't be done with clean
.
Replacing the substitution pattern of the include
with a wildcard to include all preexisting dependency files solves some of the issues, but it still can't clean out a broken dependency, and stale dependency files are never removed. Is there a better solution? Is the manual's example really intended for real use?
Just don't provide a rule for generating .d
files. A good explanation of why it is not so good (including your case too) is available in "Advanced Auto-Dependency Generation" of Paul Smith - a maintainer of GNU Make.
In a nutshell, the following pattern works fine for me for all cases:
CPPFLAGS += -MMD -MP
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
-include $(OBJS:.o=.d)
See also my previous related answers:
The solution is to use Conditional Syntax:
ifneq ($(MAKECMDGOALS), clean)
-include $(notdir $(SOURCES:.cpp=.d))
endif
This makes the clean target do not invoke the *.d
targets, since when you run make clean
the *.d
files will not be included in the Makefile.
Reference: https://www.gnu.org/software/make/manual/html_node/Goals.html
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