https://lists.gnu.org/archive/html/bug-bash/2011-10/msg00036.html the current yacc rules allow multiple runs to generate the same files. usually this doesn't come up as the generated files are shipped in the tarball, but when you modify parse.y (applying a patch or developing or whatever), you can hit this problem. simple way of showing this: make -j y.tab.{c,h} a correct system would not show the yacc parser running twice :) simple patch is to have the .h file depend on the .c file, and have the .h file itself issue a dummy rule (to avoid make thinking things changed). --- a/Makefile.in +++ b/Makefile.in @@ -579,16 +579,17 @@ # old rules GRAM_H = parser-built -y.tab.o: y.tab.c ${GRAM_H} command.h ${BASHINCDIR}/stdc.h input.h +y.tab.o: y.tab.h y.tab.c ${GRAM_H} command.h ${BASHINCDIR}/stdc.h input.h ${GRAM_H}: y.tab.h @-if test -f y.tab.h ; then \ cmp -s $@ y.tab.h 2>/dev/null || cp -p y.tab.h $@; \ fi -y.tab.c y.tab.h: parse.y +y.tab.c: parse.y # -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi $(YACC) -d $(srcdir)/parse.y touch parser-built # -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; else cp -p y.tab.h ${GRAM_H}; fi +y.tab.h: y.tab.c ; @true # experimental new rules - work with GNU make but not BSD (or OSF) make #y.tab.o: y.tab.c y.tab.h https://lists.gnu.org/archive/html/bug-bash/2011-10/msg00037.html the current code generates a bunch of local libraries in subdirs and then links bash against that. those subdirs sometimes need version.h. so they have a rule to change back up to the parent dir and build version.h (which is fine). the trouble is that the top level objects and the subdirs are allowed to build in parallel, so it's possible for multiple children to see that version.h is not available and that it needs to be created, so they all do. there is even more trouble is that version.h depends on all the top level sources, some of which are compiled (like syntax.c). so these parallel children all kick off a job to generate syntax.c which in turn requires the mksyntax helper executable. obviously multiple processes rm-ing, compiling, and linking the same files quickly falls apart. so tweak the subdirs to all depend on the .build target which in turn depends on all of these top level files being generated. now the subdirs won't try and recursively enter the top level. (noticed by David James) --- a/Makefile.in +++ b/Makefile.in @@ -597,6 +598,11 @@ # $(YACC) -d $(srcdir)/parse.y # -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; fi +# Subdirs will often times want version.h, so they'll change back up to +# the top level and try to create it. This causes parallel build issues +# so just force top level sanity before we descend. +$(LIBDEP): .build + $(READLINE_LIBRARY): config.h $(READLINE_SOURCE) @echo making $@ in ${RL_LIBDIR} @( { test "${RL_LIBDIR}" = "${libdir}" && exit 0; } || \ http://lists.gnu.org/archive/html/bug-bash/2011-10/msg00107.html the top level Makefile will recurse into the defdir for multiple targets (libbuiltins.a, common.o, bashgetopt.o, builtext.h), and since these do not have any declared interdependencies, parallel makes will recurse into the subdir and build the respective targets. nothing depends on common.o or bashgetopt.o, so those targets don't get used normally. this leaves libbuiltins.a and builtext.h. at a glance, this shouldn't be a big deal, but when we look closer, there's a subtle failure lurking. most of the objects in the defdir need to be generated which means they need to build+link the local mkbuiltins helper. the builtext.h header also needs to be generated by the mkbuiltins helper. so when the top level launches a child for libbuiltins.a and a child for builtext.h, we can hit a race condition where the two try to generate mkbuiltins, and the build randomly fails. so update libbuiltins.a to depend on builtext.h. this should be fairly simple since it's only a single target. --- a/Makefile.in +++ b/Makefile.in @@ -674,7 +674,7 @@ $(RM) $@ ./mksyntax$(EXEEXT) -o $@ -$(BUILTINS_LIBRARY): $(BUILTIN_DEFS) $(BUILTIN_C_SRC) config.h ${BASHINCDIR}/memalloc.h version.h +$(BUILTINS_LIBRARY): $(BUILTIN_DEFS) $(BUILTIN_C_SRC) config.h ${BASHINCDIR}/memalloc.h ${DEFDIR}/builtext.h version.h @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libbuiltins.a ) || exit 1 # these require special rules to circumvent make builtin rules