12.9 The Make Macro SHELL

Many make implementations use the $(SHELL) macro to spawn shell processes and execute Make rules. This is a builtin macro with a default value upplied by make; the default can be overridden by a makefile or by a command-line argument, though not by the environment.

Other make implementations use other ways to spawn shell processes, and the POSIX standard for make says that portable makefiles should neither define nor use the $(SHELL) macro.

Despite this prohibition, in practice it does not hurt to define and then possibly use SHELL in your makefiles and in some cases it can help your builds use a better shell to spawn shell processes. So it’s a good idea to define SHELL in your makefiles. If you use Autoconf, you can use its standard output variable SHELL as follows:

SHELL = @SHELL@

If you use Automake, this is done for you.

Do not force SHELL = /bin/sh because that is not correct everywhere. Remember, /bin/sh is not POSIX compliant on some systems, such as Solaris 10. Additionally, DJGPP lacks /bin/sh, and when its GNU make port sees such a setting it enters a special emulation mode where features like pipes and redirections are emulated on top of DOS’s command.com. Unfortunately this emulation is incomplete; for instance it does not handle command substitutions. Using @SHELL@ means that your makefile will benefit from the same improved shell, such as bash or ksh, that was discovered during configure, so that you aren’t fighting two different sets of shell bugs between the two contexts.

Do not rely on whether make’s SHELL settings are exported to subprocesses, as implementations differ:

$ cat Makefile
all:
        @printf '%s\n' '$(SHELL)'
        @printenv SHELL
$ env SHELL=/bin/sh make -e SHELL=/bin/ksh  # BSD make, AIX make
/bin/ksh
/bin/ksh
$ env SHELL=/bin/sh make -e SHELL=/bin/ksh  # GNU make
/bin/ksh
sh