Correct errors in the use of multiple targets, which could break parallel make.
Nicholas Clark [Thu, 7 Jan 2010 15:17:15 +0000 (15:17 +0000)]
Where a single script (or program) generates multiple files, the Makefile rule
was written with those multiple files as targets on the same line. This would
be correct if that syntax meant "these $n things are built by these commands".

However it doesn't - it means "to build any of these targets, run these
commands", and hence to run them once for each of the targets. This can result
in race conditions with parallel makes, with files being trampled on and
strange failure modes.

Hence the correct style is to give one of the targets on the rule, and rules
that make all the other targets that are generated depend on that target.

Makefile.SH

index 97df05a..0fba695 100644 (file)
@@ -607,7 +607,9 @@ perlmini\$(OBJ_EXT): perlmini.c
 
 globals\$(OBJ_EXT): uudmap.h bitcount.h
 
-uudmap.h bitcount.h: generate_uudmap\$(HOST_EXE_EXT)
+uudmap.h: bitcount.h
+
+bitcount.h: generate_uudmap\$(HOST_EXE_EXT)
        \$(RUN) ./generate_uudmap\$(HOST_EXE_EXT) uudmap.h bitcount.h
 
 generate_uudmap\$(HOST_EXE_EXT): generate_uudmap\$(OBJ_EXT)
@@ -970,7 +972,9 @@ $spitshell >>$Makefile <<'!NO!SUBS!'
 .PHONY: preplibrary
 preplibrary: $(MINIPERL_EXE) $(CONFIGPM) lib/re.pm $(PREPLIBRARY_LIBPERL)
 
-$(CONFIGPM_FROM_CONFIG_SH) $(CONFIGPOD): config.sh $(MINIPERL_EXE) configpm Porting/Glossary lib/Config_git.pl
+$(CONFIGPM_FROM_CONFIG_SH): $(CONFIGPOD)
+
+$(CONFIGPOD): config.sh $(MINIPERL_EXE) configpm Porting/Glossary lib/Config_git.pl
        $(MINIPERL) configpm
 
 lib/ExtUtils/Miniperl.pm: miniperlmain.c $(MINIPERL_EXE) minimod.pl $(CONFIGPM)
@@ -1001,7 +1005,9 @@ uni.data: $(MINIPERL_EXE) $(CONFIGPM) lib/unicore/mktables $(nonxs_ext)
 pod/perltoc.pod: $(perltoc_pod_prereqs)  $(PERL_EXE) $(ext) pod/buildtoc
        $(RUN_PERL) -f -Ilib pod/buildtoc --build-toc -q
 
-pod/perlapi.pod pod/perlintern.pod: $(MINIPERL_EXE) autodoc.pl embed.fnc
+pod/perlapi.pod: pod/perlintern.pod
+
+pod/perlintern.pod: $(MINIPERL_EXE) autodoc.pl embed.fnc
        $(MINIPERL) autodoc.pl
 
 pod/perlmodlib.pod: $(MINIPERL_EXE) pod/perlmodlib.PL MANIFEST