Reputation: 47658
I have couple of cpp and hpp files in directory ./src
. I compile all cpp files in one binary file, say ./bin/run
. I want to re-compile only if I need i.e it or one of its header was changed.
I, probably, can create Makefile where file will be recompiled if and only if it was changed, but it's quite uncomfortable because big part of my code is in the headers. (It's not going to be changed, because the product is header itself and cpp files are tests).
I want to store temporary .o
files in ./build
I know about g++ -MM
function but I'm not sure how to use it.
I'll glad to see solutions that use not necessary make
but any other system possible if they are easy enough.
UPD I'll try to clarify, what's the problem is:
New cpp's maybe created, includes may be added or gone, etc. I don't want to edit my makefile each time.
Upvotes: 0
Views: 687
Reputation: 8380
You mention g++ -MM
, which can do what you're trying to do:
include $(ALLOBJ:%.o=%.d)
%.d: %.cxx
@echo making dependencies for $<
@g++ -MM -MP $(CXXFLAGS) $< -o $@
@sed -i 's,$*\.o,& $@ ,g' $@
Basically this defines a rule that creates .d
files from .cxx
files. The .d
files are, in turn, required by the include
statement, which requires one for each .o
file in ALLOBJ
.
The last line in the dependency rule is the 'sed magic' that makes the dependency files regenerate themselves. If you think regular expressions are hacks at best, and evil more often than not, you can use the -MT
flag.
Upvotes: 1
Reputation: 99172
To solve the problem I mentioned (-include
is not a good solution), I use something like this:
build/%.o: %.cpp
@$(CC) -MD -c -Wall -o $@ $<
@cp build/$*.d build/$*.P
@sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < build/$*.P >> build/$*.d
@rm build/$*.P
-include build/*.d
No `%.d rule is needed.
EDIT:
@JackKelly has [*cough*, *choke*] shown me a better way to get effectively the same dependency file:
build/%.o: %.cpp
@$(CC) -MD -c -Wall -o $@ $<
@$(CC) -MM -MP -Wall -o $*.d $<
-include build/*.d
Ye, you can have multiple rules for the same target, as long as only one of them has commands; the prerequisites accumulate. The idea is to get a file like this:
file.o: file.cpp headerfile.h
headerfile.h:
The second line (headerfile.h:
) is a rule for headerfile.h
that has no prerequisites or commands. It does nothing, but it's a rule, so if headerfile.h
is missing, Make is satisfied.
Upvotes: 2
Reputation: 28300
The outline of a solution is as follows:
foo.dep
for foo.c
, bar.dep
for bar.c
etc)gcc -MM
to create the dependency filesmake
to do this automatically, use foo.c
as a prerequisite for foo.dep
and foo.o
; this requires some minor sed
magic on the output of gcc -MM
The last step is written as follows:
-include $(dependency_files)
This is very tricky but possible; see the GNU make manual for more information.
Upvotes: 1
Reputation: 9642
You can do this with Make, you just need to specify the headers in your rule's sensitivity list. For example
myfile.o: myfile.cpp
gcc -c myfile.o myfile.cpp ${LDFLAGS} # This is optional. make can infer this line.
Turns into
myfile.o: myfile.cpp myfile.h
gcc -c myfile.o myfile.cpp ${LDFLAGS} # Again, optional.
Now, whenever myfile.h
changes, myfile.cpp
will be rebuild. More headers can be chained in a similar way.
Upvotes: 0