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