How to get make dependancies working when one rule builds several files
# This entire HTML file is a single makefile that shows how to do this.
#
# Here is how to set up dependancies for a build step that generates a bunch of
# files from one or more source files.
#
# Example:
# We start with these source files:
# x.c
# y.c
# src1
# src2
# src3
# We want to build obj
#
# obj depends on x,c y.c gen1 gen2 and gen3
#
# gen1 gen2 and gen3 are generated by the stamp: rule
# src1 arc2 and src3 are required to generate gen1 gen2 and gen3
#
# Solution:
#
# obj depends on what it needs - this is straightforward
# obj must also depend on stamp
#
# stamp is the rule that generates everything
# - stamp generates its own dep.d file with generated dependancies:
# - dep.d depends on all src files
# - each gen file depends on dep.d
# - stamp depends on all gen files
# - the dep.d file must be removed and generated with a different name
# (dep2.d) and copied as the 2nd to last step of the stamp rule
# - the last step of stamp must touch all the gen files and stamp to
# ensure they are newer than dep.d
#
# How it works:
#
# When dep.d does not exist:
# stamp must be built because dep.d does not exist
#
# When dep.d exists:
# changes to src force dep.d to build
# changes to dep.d (incl src) force gen to build
# changes to any gen (incl dep.d and src) force stamp to build
# So basically any change forces stamp to rebuild
#
#
# Note: if a generated program runs as part of stamp then consider that a
# src and also add it as a dependancy of stamp so it gets built initially.
obj: x.c y.c stamp gen1 gen2 gen3
@echo "Do obj"
grep s1 gen1 || exit 1
grep s1 gen2 || exit 1
grep s1 gen3 || exit 1
cat x.c y.c gen1 gen2 gen3 > $@
sleep 2
# You can optionally make dep.d depend on the Makefile if you want.
dep.d:
@echo "Do abc for $@"
\rm -f stamp
stamp: dep.d
@echo "Do stamp"
\rm -f dep.d
@echo "EXPENSIVE OPERATION - ONLY DO ONCE"
cat src1 src2 src3 | tee gen1 | tee gen2 > gen3
echo "dep.d: src1 src2 src3" > dep2.d
echo "gen1 gen2 gen3: dep.d" >> dep2.d
echo "stamp: gen1 gen2 gen3" >> dep2.d
mv dep2.d dep.d
sleep 2
touch gen1 gen2 gen3 stamp
clean:
\rm -f gen* stamp* obj dep.d
-include dep.d
ifeq (0,1)
# Tests: copy & paste to command line to test.
# Each test should only run the EXPENSIVE OPERATION exactly once.
# The 2nd make on each line should be up to date (nothing to do).
make clean ; make ; echo "===" ; make ; echo "============="
\rm -f stamp ; make ; echo "===" ; make ; echo "============="
\rm -f gen1 ; make ; echo "===" ; make ; echo "============="
\rm -f gen1 gen2 ; make ; echo "===" ; make ; echo "============="
\rm -f dep.d ; make ; echo "===" ; make ; echo "============="
\rm -f dep.d gen1 ; make ; echo "===" ; make ; echo "============="
\rm -f stamp gen1 ; make ; echo "===" ; make ; echo "============="
\rm -f stamp dep.d ; make ; echo "===" ; make ; echo "============="
\rm -f stamp dep.d gen3 ; make ; echo "===" ; make ; echo "============="
touch src1 ; make ; echo "===" ; make ; echo "============="
touch dep.d ; make ; echo "===" ; make ; echo "============="
echo "" > gen1 ; make ; echo "===" ; make ; echo "============="
touch src1 src2 ; \rm gen1 gen2 ; make ; echo "===" ; make ; echo "========"
touch gen1 ; make ; echo "===" ; make ; echo "============="
touch stamp ; make ; echo "===" ; make ; echo "============="
# The following do not require EXPENSIVE OPERATION at all.
touch x.c ; make ; echo "===" ; make ; echo "============="
#
endif