Reputation: 127408
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?
Upvotes: 50
Views: 65914
Reputation: 731
I'll add yet another answer here as I don't really like the current ones. The idea is to create dependency files at the same time as compilation goes and do not fail the first time when these do not exist. Have in mind this is for GNU Make, not POSIX make, and for GCC-compatible compilers, but this is what everyone assumed here it seems.
Let's say we want to build inside of the source tree and link into one executable:
SRCS = $(wildcard *.c)
OBJS = $(SRCS:%.c=%.o)
DEPS = $(OBJS:%.o=%.d)
executable: $(OBJS)
$(CC) $(OBJS) -o executable
-include $(DEPS)
%.o: %.c
$(CC) -c $*.c -MMD -MF $*.d -o $*.o
Now, the rule executable: $(OBJS)
will trigger the build process of object files, which is defined by pattern rule %.o: %.c
. Then -MMD -MF $*.d
will create dependency files during compilation. -include $(DEPS)
will include depfiles during next make invocation. It's crucial to use -
in -include
so it will silently fail during initial build (or when new .c file is added). This is not a problem because we only need depfiles during incremental builds. The first time we need to compile every object anyway so we don't care about their dependencies.
I use -MMD
as it omits dependencies on system headers. It's rarely the case where you need to depend on them, unless you're treating a regular headers as system header with something like -isystem
.
Rules from depfiles will NOT clash with the pattern rule %.o: %.c
. GNU Make will conciser rule dependencies from depfiles and then run the pattern rule anyway because hose rules in depfiles are empty.
You do NOT have to specify %.d
as dependency of another rule. These will be crated automatically when needed. This process is self-sustained.
Remember to use your CFLAGS
, CPPFLAGS
, CXXFLAGS
, LDFLAGS
, etc. I omitted them to keep the code snippet simple. You can also use make's $@
, $<
, $^
, etc. I also omitted those for the same reason.
Upvotes: 0
Reputation: 18940
I just add this to the makefile and it works nicely:
-include Makefile.deps
Makefile.deps:
$(CC) $(CFLAGS) -MM *.c > $@
Upvotes: 6
Reputation: 23929
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.
Upvotes: 60
Reputation: 5542
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.
Upvotes: 30
Reputation: 42142
The GNU C preprocessor cpp has an option, -MM, which produces a make-suitable set of dependencies based on inclusion patterns.
Upvotes: 7