What approach do C++ programmers on Unix platform use to create and manage Makefiles?
I was using hand made Makefiles for my projects but they don't handle header file changes and other dependencies. I googled around and found a good solution here.
But I ran into a problem here in the sed command -
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
The problem is with the 3rd expression "-e 's/ *\$$//'. It doesn't work. Its supposed to remove trailing backslashes. I understand that there has to be double dollar there since this is part of a Makefile. Can someone tell me what wrong here?
Here's the complete Makefile -
CC=g++
CFLAGS=-g -Wall
LIBS=-lpthread
OBJS=file1.o file2.o
TARGET=testProg
$(TARGET) : $(OBJS)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
%.o : %.cpp
$(CC) -MMD -c -o $@ $< $(CFLAGS)
@cp $*.d $*.P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
rm -f $*.d
-include $(OBJS:%.o=%.P)
clean :
rm -f $(TARGET) $(OBJS)
all : $(TARGET)
Apart from the solution to this problem, I would also like some tips/pointers to my 1st question.
gcc/g++ can generate dependencies for you with the
-M
family of options. The following works by specifying how to generate.depends
files given a source file. By doing-include $(DEPS)
$(DEPS) is recognized as a target and will be built/rebuilt when the source files change.I use BSD make (pmake?) which does lot of work for me (my lang is C, but I think no difference here). This is my common 'local.prog.mk', I never change it:
Note 'bsd.prog.mk' inclusion -- this handles all, build, depend, clean targets. Project-specific
BSDmakefile
s are simple:I just make depend every time I insert/remove any #include directives.
I top tip that I have found useful when building dependency files is to include the dependency file as a target in the generated rule:
Thus
make
will regenerate the dependencies if the source or any of the headers change. Including phony targets for the headers (GCC-MP
) should then allow stable builds when headers are removed - the absense of required header remains a compilation error, not a make dependency error.Assuming that dependency files are generated into the same directory as the object files, the following should work for GCC on Unix:
(from memory)
In Mozilla's build system, we use GCC's -MD switch to generate the dependency files: http://mxr.mozilla.org/mozilla-central/source/configure.in#7134 and then we use a script called mddepend.pl to check for removed header files, such that removing a header simply causes a rebuild, not an error: http://mxr.mozilla.org/mozilla-central/source/config/rules.mk#2066 http://mxr.mozilla.org/mozilla-central/source/build/unix/mddepend.pl
That script generates an .all.pp file containing all the dependencies, with extra
foo.o: FORCE
dependencies stuck in for missing header files. We then simply -include the .all.pp file in rules.mk right below there.The makedepend utility is installed on many systems and can be quite useful for generating dependency information.
Here is an example Makefile that uses the
include
directive (plus a little Perl magic) to incorporate the output from makedepend:If both
foo.cc
andmain.cc
depend onfoo.h
, then the contents ofMakefile.depend
would be:The end result is that the dependency information from
makedepend
is injected into the Makefile as a series of rules. It's similar to the approach of using a.d
file for each.cc
file, but keeps the dependency information in one file instead of scattered all over the place.You can use qmake to generate Makefiles for a project even if that project is not using Qt.