SHELL
Posix-compliant make internally uses the $(SHELL)
macro to spawn shell processes and execute Make rules. This
is a builtin macro supplied by make, but it can be modified
by a makefile or by a command-line argument.
Not all make implementations define this SHELL
macro.
Tru64
make is an example; this implementation always uses
/bin/sh
. So it's a good idea to always define SHELL
in
your makefiles. If you use Autoconf, do
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 many
systems, such as FreeBSD 4, NetBSD 3, AIX 3, Solaris 10, or Tru64.
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.
Posix-compliant make should never acquire the value of
$(SHELL) from the environment, even when make -e
is used
(otherwise, think about what would happen to your rules if
SHELL=/bin/tcsh
).
However not all make implementations have this exception.
For instance it's not surprising that Tru64 make doesn't
protect SHELL
, since it doesn't use it.
$ cat Makefile SHELL = /bin/sh FOO = foo all: @echo $(SHELL) @echo $(FOO) $ env SHELL=/bin/tcsh FOO=bar make -e # Tru64 Make /bin/tcsh bar $ env SHELL=/bin/tcsh FOO=bar gmake -e # GNU make /bin/sh bar
Conversely, make is not supposed to export any changes to the
macro SHELL
to child processes. Again, many implementations
break this rule:
$ cat Makefile all: @echo $(SHELL) @printenv SHELL $ env SHELL=sh make -e SHELL=/bin/ksh # BSD Make, GNU make 3.80 /bin/ksh /bin/ksh $ env SHELL=sh gmake -e SHELL=/bin/ksh # GNU make 3.81 /bin/ksh sh