Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU make: clean target depends on includes

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?

like image 486
Potatoswatter Avatar asked Oct 12 '12 10:10

Potatoswatter


2 Answers

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:

  • GNU Make. Why this complex syntax to generate dependencies?
  • Makefile improvements, dependency generation not functioning
like image 70
Eldar Abusalimov Avatar answered Sep 22 '22 16:09

Eldar Abusalimov


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

like image 22
Jorgeluis Avatar answered Sep 20 '22 16:09

Jorgeluis