autoconf: Parallel Make

1 
1 12.10 Parallel Make
1 ===================
1 
1 Support for parallel execution in `make' implementation varies.
1 Generally, using GNU make is your best bet.
1 
1    When NetBSD or FreeBSD `make' are run in parallel mode, they will
1 reuse the same shell for multiple commands within one recipe.  This can
1 have various unexpected consequences.  For example, changes of
1 directories or variables persist between recipes, so that:
1 
1      all:
1              @var=value; cd /; pwd; echo $$var; echo $$$$
1              @pwd; echo $$var; echo $$$$
1 
1 may output the following with `make -j1', at least on NetBSD up to 5.1
1 and FreeBSD up to 8.2:
1 
1      /
1      value
1      32235
1      /
1      value
1      32235
1 
1 while without `-j1', or with `-B', the output looks less surprising:
1 
1      /
1      value
1      32238
1      /tmp
1 
1      32239
1 
1 Another consequence is that, if one command in a recipe uses `exit 0'
1 to indicate a successful exit, the shell will be gone and the remaining
1 commands of this recipe will not be executed.
1 
1    The BSD `make' implementations, when run in parallel mode, will also
1 pass the `Makefile' recipes to the shell through its standard input,
1 thus making it unusable from the recipes:
1 
1      $ cat Makefile
1      read:
1              @read line; echo LINE: $$line
1      $ echo foo | make read
1      LINE: foo
1      $ echo foo | make -j1 read # NetBSD 5.1 and FreeBSD 8.2
1      LINE:
1 
1 Moreover, when FreeBSD `make' (up at least to 8.2) is run in parallel
1 mode, it implements the `@' and `-' "recipe modifiers" by dynamically
1 modifying the active shell flags.  This behavior has the effects of
1 potentially clobbering the exit status of recipes silenced with the `@'
1 modifier if they also unset the `errexit' shell flag, and of mangling
1 the output in unexpected ways:
1 
1      $ cat Makefile
1      a:
1              @echo $$-; set +e; false
1      b:
1              -echo $$-; false; echo set -
1      $ make a; echo status: $?
1      ehBc
1      *** Error code 1
1      status: 1
1      $ make -j1 a; echo status: $?
1      ehB
1      status: 0
1      $ make b
1      echo $-; echo set -
1      hBc
1      set -
1      $ make -j1 b
1      echo $-; echo hvB
1 
1 You can avoid all these issues by using the `-B' option to enable
1 compatibility semantics.  However, that will effectively also disable
1 all parallelism as that will cause prerequisites to be updated in the
1 order they are listed in a rule.
1 
1    Some make implementations (among them, FreeBSD `make', NetBSD
1 `make', and Solaris `dmake'), when invoked with a `-jN' option, connect
1 the standard output and standard error of all their child processes to
1 pipes or temporary regular files.  This can lead to subtly different
1 semantics in the behavior of the spawned processes.  For example, even
1 if the `make' standard output is connected to a tty, the recipe command
1 will not be:
1 
1      $ cat Makefile
1      all:
1              @test -t 1 && echo "Is a tty" || echo "Is not a tty"
1      $ make -j 2 # FreeBSD 8.2 make
1      Is not a tty
1      $ make -j 2 # NetBSD 5.1 make
1      --- all ---
1      Is not a tty
1      $ dmake -j 2 # Solaris 10 dmake
1      HOSTNAME --> 1 job
1      HOSTNAME --> Job output
1      Is not a tty
1 
1 On the other hand:
1 
1      $ make -j 2 # GNU make, Heirloom make
1      Is a tty
1 
1 The above examples also show additional status output produced in
1 parallel mode for targets being updated by Solaris `dmake' and NetBSD
1 `make' (but _not_ by FreeBSD `make').
1 
1    Furthermore, parallel runs of those `make' implementations will
1 route standard error from commands that they spawn into their own
1 standard output, and may remove leading whitespace from output lines.
1