pattern rules with multiple targets producing intermediate files
Hello, while something has changed from 4.3 to 4.4 in the dealing with intermediate files, the example Makefile below still doesn't work as expected. There are two pairs of *.[ch] files generated, each by their respective rule. Each of the *.o files to be compiled from the *.c ones has a dependency recorded on both *.h files. If (up-to-date or outdated) instances of all four generated files are there, all is fine. If both *.c files are missing, all is fine as well. However, if only one *.c file is missing and the other is up-to-date, compilation of the other *.c file will (provided at least -j2 was passed) be invoked in parallel to the re-generation of the other *.[ch] pair, not taking into consideration that one of the *.h files is in the process of being re-generated (together with its sibling *.c file). The difference in behavior of 4.4 compared to 4.3 is that this is now symmetric. In 4.3 only the C file corresponding to the first prereq of "all" was permanently affected by the bad behavior (according to my experiments); a re-run of make would succeed (because the intermediate file was not treated as such and hence was not deleted). Of course I'm not going to exclude that there's something that's done wrongly in that (heavily stripped down) example - apologies in advance if so, yet then I'd still appreciate if it could be pointed out what needs doing differently. Jan .PHONY: all all:tst_b.o tst_a.o Makefile:: ; tst_b.o tst_a.o: tst_a.h tst_b.h #.SECONDARY: tst_a.c tst_b.c %.o: %.c @echo 'C: *=$* @=$@ <=$<' @for i in $^; do test -f "$$i" || echo "Missing: $$i"; done @for i in $^; do test -s "$$i" || echo "Empty: $$i"; done %.c %.h: %.a @echo 'A: *=$* @=$@ <=$<' rm -f $*.[ch] touch $*.c $*.h sleep 1 echo "$*.c ($<)" >$*.c sleep 1 echo "$*.h ($<)" >$*.h %.c %.h: %.b @echo 'B: *=$* @=$@ <=$<' rm -f $*.[ch] touch $*.c $*.h sleep 1 echo "$*.c ($<)" >$*.c sleep 1 echo "$*.h ($<)" >$*.h
Generating missing depfiles by an automake based makefile
Good morning. Here is a rule from an automake generated makefile. $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ This rule restores a missing depfile file by creating a file with one line '# dummy'. (Next version of automake will create an empty one). There must have been a reason for generating such a depfile. However, this depfile fails dependency tracking. Once a depfile was removed and recreated in this shape, it will no longer perform its function. Below is a sample bash session with gnu make which demonstrates how a dummy shuffle.Po makefile fails to have shuffle.o rebuilt when shuffle.h changes. $ make -j3 CFLAGS='-Wall -Wextra -ggdb -m64 -O0 -DMAKE_MAINTAINER_MODE=1' ./config.status --header=src/mkconfig.h Making all in lib make[1]: Entering directory '/home/dgoncharov/src/gmake/make/l64/lib' make all-recursive config.status: creating src/mkconfig.h config.status: src/mkconfig.h is unchanged make[2]: Entering directory '/home/dgoncharov/src/gmake/make/l64/lib' make[3]: Entering directory '/home/dgoncharov/src/gmake/make/l64/lib' make[3]: Nothing to be done for 'all-am'. make[3]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/lib' make[2]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/lib' make[1]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/lib' Making all in po make[1]: Entering directory '/home/dgoncharov/src/gmake/make/l64/po' make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/po' Making all in doc make[1]: Entering directory '/home/dgoncharov/src/gmake/make/l64/doc' make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/doc' make[1]: Entering directory '/home/dgoncharov/src/gmake/make/l64' make[1]: Leaving directory '/home/dgoncharov/src/gmake/make/l64' $ ls -l src/shuffle.o -rw-r--r-- 1 dgoncharov wireshark 13K Feb 7 21:16 src/shuffle.o $ head src/.deps/shuffle.Po src/shuffle.o: ../src/shuffle.c /usr/include/stdc-predef.h \ ../src/makeint.h src/config.h ../src/../src/mkcustom.h lib/alloca.h \ /usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include/stddef.h \ ../src/gnumake.h /usr/include/sys/types.h /usr/include/features.h \ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \ /usr/include/bits/long-double.h /usr/include/gnu/stubs.h \ /usr/include/gnu/stubs-64.h /usr/include/bits/types.h \ /usr/include/bits/timesize.h /usr/include/bits/typesizes.h \ /usr/include/bits/time64.h /usr/include/bits/types/clock_t.h \ /usr/include/bits/types/clockid_t.h /usr/include/bits/types/time_t.h \ $ grep shuffle.h src/.deps/*.Po src/.deps/file.Po: ../src/variable.h ../src/debug.h ../src/shuffle.h src/.deps/file.Po:../src/shuffle.h: src/.deps/implicit.Po: ../src/output.h ../src/commands.h ../src/shuffle.h /usr/include/assert.h src/.deps/implicit.Po:../src/shuffle.h: src/.deps/job.Po: ../src/variable.h ../src/os.h ../src/dep.h ../src/shuffle.h \ src/.deps/job.Po:../src/shuffle.h: src/.deps/main.Po: ../src/shuffle.h /usr/include/assert.h /usr/include/fcntl.h \ src/.deps/main.Po:../src/shuffle.h: src/.deps/shuffle.Po: /usr/include/glob.h ../src/shuffle.h ../src/filedef.h ../src/hash.h \ src/.deps/shuffle.Po:../src/shuffle.h: $ rm src/.deps/shuffle.Po $ make -j3 CFLAGS='-Wall -Wextra -ggdb -m64 -O0 -DMAKE_MAINTAINER_MODE=1' ./config.status --header=src/mkconfig.h Making all in lib make[1]: Entering directory '/home/dgoncharov/src/gmake/make/l64/lib' make all-recursive make[2]: Entering directory '/home/dgoncharov/src/gmake/make/l64/lib' config.status: creating src/mkconfig.h config.status: src/mkconfig.h is unchanged make[3]: Entering directory '/home/dgoncharov/src/gmake/make/l64/lib' make[3]: Nothing to be done for 'all-am'. make[3]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/lib' make[2]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/lib' make[1]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/lib' Making all in po make[1]: Entering directory '/home/dgoncharov/src/gmake/make/l64/po' make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/po' Making all in doc make[1]: Entering directory '/home/dgoncharov/src/gmake/make/l64/doc' make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/home/dgoncharov/src/gmake/make/l64/doc' make[1]: Entering directory '/home/dgoncharov/src/gmake/make/l64' make[1]: Leaving directory '/home/dgoncharov/src/gmake/make/l64' $ head src/.deps/shuffle.Po # dummy $ touch ../src/shuffle.h $ make -j3 CFLAGS='-Wall -Wextra -ggdb -m64 -O0 -DMAKE_MAINTAINER_MODE=1' ./config.status --header=src/mkconfig.h Making all in lib make[1]: Entering directory '/home/dgoncharov/src/gmake/make/l64/lib' make all-recursive config.status: creating src/mkconfig.h config.status: src/mkconfig.h is unchanged make[2]: Entering directory '/home/dgoncharov/src/gmake/make/l64/lib' make[3]: Entering directory '/home/dgoncharov/src/gmake/make/l6