Tips and Tricks From the Automatic Dependency Generation Masters

Mr. Make

to remove the need for GNU Make to restart, by merging the rule that makes the .d file into the rule that makes the .o.   Since the .d file is updated if and only if the .o file needs to be updated (both are updated when any of the sources for the .o change) it's possible to have the makedepend occur at the same time as the compilation:

.PHONY: all
all: foo.o bar.o baz.o

SRCS = foo.c bar.c baz.c

%.o : %.c
@makedepend -f - $< | sed 's,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\n\1 : \2,g' > $*.d
@$(COMPILE.c) -o $@ $<

-include $(SRCS:.c=.d)

This rule makes use of another GNU Make variable: $*. $* is the part of the pattern %.c which matches the %; if this rule is building foo.o from foo.c then $* is just foo.  $* is used to create the name of the .d file that makedepend writes to.

This final version does not use GNU Make's 'Makefile remaking' system.  There are no rules for making .d files (they are made as a side effect of making the .o) and hence GNU Make doesn't have to restart.  This provides the best combination of accuracy and speed possible.   

In general it's bad idea to have a rule that makes multiple files because it's impossible for GNU Make to find the rule that makes a file if it's created as a side effect of something else.  In this case that behavior is desired: we want to hide the creation of .d files from GNU Make so that it doesn't try to make them and then have to restart.

(A similar idea was proposed by Tom Tromey (without the $(wildcard) trick) and more information about building dependency files can be found on the GNU Make maintainer Paul Smith's web site at; another good resource for any GNU Make developer---once you've purchased the FSF's GNU Make manual---is Robert Mecklenburg's Managing Projects with GNU Make from O'Reilly)

Doing away with makedepend
Finally, it's possible to omit makedepend altogether if you are using the GNU gcc compiler.  It has a -MD option that does the work of makedepend at the same time as the compilation:

.PHONY: all
all: foo.o bar.o baz.o

SRCS = foo.c bar.c baz.c

%.o : %.c
@$(COMPILE.c) -MD -o $@ $<
@sed -i 's,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\n\1 : \2,g' $*.d

-include $(SRCS:.c=.d)

For example, the compilation step for foo.o will create foo.d from foo.c and then sed is run on the foo.d to add the extra line for foo.d containing the $(wildcard).

About the author

John Graham-Cumming's picture John Graham-Cumming

John Graham-Cumming is Co-Founder at Electric Cloud, Inc . Prior to joining Electric Cloud, John was a Venture Consultant with Accel Partners, VP of Internet Technology at Interwoven, Inc. (IWOV), VP of Engineering at Scriptics Corporation (acquired by Interwoven), and Chief Architect at Optimal Networks, Inc. John holds BA and MA degrees in Mathematics and Computation and a Doctorate in Computer Security from Oxford University. John is the creator of the highly acclaimed open source POPFile project. He also holds two patents in network analysis and has others pending.

AgileConnection is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, is the place to go for what is happening in software development and delivery.  Join the conversation now!

Upcoming Events

Sep 22
Sep 24
Oct 12
Nov 09