I have a project that has a makefile with broken dependencies. Is there any best known way to generate a list of dependencies for the project that I can use in the makefile, other than examining each source file by hand or with a hand written perl script?
5 Answers
GNU make's documentation provides a good solution.
Absolutely. g++ -MM <your file>
will generate a GMake compatible list of dependencies. I use something like this:
# Add .d to Make's recognized suffixes.
SUFFIXES += .d
#We don't need to clean up when we're making these targets
NODEPS:=clean tags svn
#Find all the C++ files in the src/ directory
SOURCES:=$(shell find src/ -name "*.cpp")
#These are the dependency files, which make will clean up after it creates them
DEPFILES:=$(patsubst %.cpp,%.d,$(SOURCES))
#Don't create dependencies when we're cleaning, for instance
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
#Chances are, these files don't exist. GMake will create them and
#clean up automatically afterwards
-include $(DEPFILES)
endif
#This is the rule for creating the dependency files
src/%.d: src/%.cpp
$(CXX) $(CXXFLAGS) -MM -MT '$(patsubst src/%.cpp,obj/%.o,$<)' $< -MF $@
#This rule does the compilation
obj/%.o: src/%.cpp src/%.d src/%.h
@$(MKDIR) $(dir $@)
$(CXX) $(CXXFLAGS) -o $@ -c $<
Note: $(CXX)
/gcc
command must be preceded with a hard tab
What this will do is automatically generate the dependencies for each file that has changed, and compile them according to whatever rule you have in place. This allows me to just dump new files into the src/
directory, and have them compiled automatically, dependencies and all.

- 65
- 7

- 23,367
- 6
- 55
- 61
-
1Don't fall into this trap if you have more than 100 files, because it's too slow the first time. In this case, you should use something that is invoked once, not once for each file. Makedepend might have this option. At work, we use a custom perl script. – Steve Hanov Mar 08 '09 at 12:57
-
Thanks, I'll keep that in mind. My current project has about a dozen files, so it doesn't have big overhead. Besides, the initial build takes more than 20 minutes, so I always run that, go get some coffee, and run incremental builds after that. – Nathan Fellman Apr 27 '09 at 11:21
-
1Thanks, this really helped me. You can write `$(patsubst src/%,obj/%,$(patsubst %.cpp,%.o,$<))` a bit simpler as `$(patsubst src/%.cpp,obj/%.o,$<)`. Also, wouldn't it make more sense to use the option `-MF $@` option instead of redirecting the output with `> $@`? The g++ man page warns you that there could be some unwanted debug output on stdout, but you don't get that with `-MF $@`. – Maarten Apr 19 '12 at 20:26
-
@Maarten Good points! I've incorporated your changes into the answer. If you see anything else that might be helpful, feel free to make the edits yourself. Thanks! – Stefan Mai Apr 19 '12 at 20:56
-
In order to avoid @SteveHanov objection, if the dependencies aren't up to date you'll have to recompile the file and if you have to recompile the file, the dependencies may not be up to date. So I just generate the .d unconditionally when I compile and have no special rule to remake them. – AProgrammer Nov 24 '12 at 21:09
-
Compilation of a 'test.o' fails when there isn't a 'test.h'. I think you should change `obj/%.o: src/%.cpp src/%.d src/%.h` into `obj/%.o: src/%.cpp src/%.d` ? – Carlo Wood Nov 13 '16 at 12:51
-
I believe (haven't verified) your Makefile will not rebuild dependency files when only .h file was modified. (no idea for simple robust fix, all my ideas feel too hackish right now, so I will stop here just pointing out this may still fail) – Ped7g Nov 28 '20 at 23:01
-
What if sources are not only suffixed by ".cpp", but also by ".cu". Does this solution still work? – Ziqi Fan May 27 '22 at 14:54
Having now read this portion in particular I think there is a much easier solution out there, as long as you have a reasonably up to date version of gcc/g++. If you just add -MMD
to your CFLAGS
, define a variable OBJS
representing all your object files, and then do:
-include $(OBJS:%.o=%.d)
then that should get you both an efficient and simple automatic dependency build system.

- 122,701
- 101
- 260
- 319

- 5,372
- 1
- 34
- 18
The GNU C preprocessor cpp has an option, -MM, which produces a make-suitable set of dependencies based on inclusion patterns.

- 41,404
- 5
- 117
- 189
I just add this to the makefile and it works nicely:
-include Makefile.deps
Makefile.deps:
$(CC) $(CFLAGS) -MM *.c > $@
-
I know this answer is old, but that should be `*.c`, not `*.[ch]` - no need to drag in every `*.h` into the compiler - as they should all be included by some `.c` file(s) if they are used at all [and if they are not, dependencies don't matter]. – Mats Petersson Jul 18 '15 at 00:56
-
Does this have any benefit over per-source dependencies? It seems like you'd be doubling the number of preprocessor passes over all files, for no real benefit. – underscore_d Sep 19 '15 at 23:11
-
Is there a way to reuse the output to generate a Makefile recipe or something similar? – PoVa Nov 28 '17 at 07:40