One example: * fbset-2.1.tar.gz RMD160 SHA1 SHA256 size ;-) ... [ ok ] * checking ebuild checksums ;-) ... [ ok ] * checking miscfile checksums ;-) ... [ ok ] >>> Unpacking source... >>> Unpacking fbset-2.1.tar.gz to /var/tmp/portage/sys-apps/fbset-2.1/work >>> Source unpacked in /var/tmp/portage/sys-apps/fbset-2.1/work >>> Compiling source in /var/tmp/portage/sys-apps/fbset-2.1/work/fbset-2.1 ... make -j3 i686-pc-linux-gnu-gcc -Wall -Os -march=pentium3 -mtune=core2 -mfpmath=sse -fomit-frame-pointer -pipe -I. -Os -march=pentium3 -mtune=core2 -mfpmath=sse -fomit-frame-pointer -pipe -c -o fbset.o fbset.c bison -d modes.y flex modes.l bison -d modes.y i686-pc-linux-gnu-gcc -Wall -Os -march=pentium3 -mtune=core2 -mfpmath=sse -fomit-frame-pointer -pipe -I. -Os -march=pentium3 -mtune=core2 -mfpmath=sse -fomit-frame-pointer -pipe -c -o modes.tab.o modes.tab.c modes.tab.c:162:2: error: invalid preprocessing directive #l modes.y:33:13: warning: ‘ClearVideoMode’ defined but not used make: *** [modes.tab.o] Error 1 make: *** Waiting for unfinished jobs.... emake failed In modes.tab.c, line 162 contains: #line 163 "modes.tab.c" So it's clear that gcc was reading the file while the second bison invocation didn't complete writing to it. Question is, why is bison invoked twice? Dependencies in Makefile seem correct. From reading GNU make manual, however (Rules -> Multiple Targets), it seems that something like target1 target2: dep cmd is actually equivalent to target1: dep cmd target2: dep cmd So there are two paths for bison invocation: modes.y -> modes.tab.c -> modes.tab.o -> fbset modes.y -> modes.tab.h -> lex.yy.o -> fbset In parallel build, bison can be invoked twice, separately for modes.tab.h and for modes.tab.c. I guess that the easiest solution for such a small package is enforcing -j1.
It took 10 iterations, but yes, this is confirmed. :)
Seems that multi-target *pattern* rules are still safe for parallel make: http://www.gnu.org/software/make/manual/make.html#Pattern-Intro Explains why similar bugs are not encountered that often.
This seems easy to fix, no? Just filter out make -j*.
No. That's not a fix, it's a workaround.
FWIW http://goo.gl/PYRMk gives you an idea how this works and how it can be fixed (although that particular use of timestamps is overkill in this situation.
Fixed, properly. Interestingly the extra failure was _added_ by Gentoo as the one before was actually much easier to spot (instead of a race condition you had a make failure for missing targets). The correct fix is to add a dependency from the .h file to the .c one, as the two are generated together.
(In reply to comment #6) > The correct fix is to add a dependency from the .h file to the .c one, as > the two are generated together. That's not a correct fix, since bison is called twice (albeit without a race). The correct fix is to make a pattern rule: %.tab.h %.tab.c: %.y $(BISON) $<
No your's wrong, mine's correct. Your's exactly like the one you had before; the multi-target pattern rules are parallel safe _between the rules themselves_, but they still cause multiple calls — you, like Mr Bones who "fixed" it before, are misreading the way make works with multiple output. Given I have heavily-multicore machines, and years of experience with make, I think I can safely say I know what I'm doing.
My mistake, I assumed that the previous multi-target rule was also left in place (wrote this before the change was in CVS). A multi-target pattern rule is still better, though.
Your multi-target pattern rule is also _broken_, just the way it was before. %.tab.h %.tab.c: %.y $(BISON) $< still means %.tab.h %.y $(BISON) $< %.tab.h: %.y $(BISON) $< which causes bison to be called twice (with a race condition). Again, you didn't understand Makefile syntax, I know it's hard, but trust me I've been fixing this kind of stuff for the past few years.
(In reply to comment #10) > Your multi-target pattern rule is also _broken_, just the way it was before. > > [...] > > which causes bison to be called twice (with a race condition). Again, you > didn't understand Makefile syntax, I know it's hard, but trust me I've been > fixing this kind of stuff for the past few years. To be honest, your attempts at condescendence are annoying. I assure you that I know GNU Make better than you -- although I will not provide proof, since this username is a pseudonym, so feel free to think otherwise. In any case, please refer to the link posted in comment #2: "Pattern rules may have more than one target. Unlike normal rules, this does not act as many different rules with the same prerequisites and recipe. If a pattern rule has multiple targets, make knows that the rule's recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets. When searching for a pattern rule to match a target, the target patterns of a rule other than the one that matches the target in need of a rule are incidental: make worries only about giving a recipe and prerequisites to the file presently in question. However, when this file's recipe is run, the other targets are marked as having been updated themselves." This is easily verified by replacing the multi-target rule with a pattern rule provided above, and observing the lack of a race condition after repeated invocations of make -j<num>. With that said, I appreciate your work, but please don't automatically assume that your expertise level is better than anyone else's just because you are familiar with a given subject.