When .ONESHELL is not used Makefile executes each shell commands in a separate shell. What is the benefit of this? Why doesn't makefile uses the same shell?

One reason is that a failure in one of the recipe commands would not be detected by GNU make. Only the final exit status of the shell would be given to make. One would have to additionally set .SHELLFLAGS to -e to get the shell to terminate early upon errors (this is required for multi-command shell invocations even without .ONESHELL if they need to fail at the first error).

This is all well and good for when SHELL is a POSIX shell. A Makefile can also set SHELL to e.g. /usr/bin/perl or some other command interpreter. It may then be appropriate, or not, to use .ONESHELL.

Making .ONESHELL the default behaviour in make would potentially break older Makefiles.

Even though this is not a question relating to the POSIX standard or the compliance to that standard by GNU make, the Rationale of the POSIX specification for make has this to say about the issue at hand:

The default in some advanced versions of make is to group all the command lines for a target and execute them using a single shell invocation; the System V method is to pass each line individually to a separate shell. The single-shell method has the advantages in performance and the lack of a requirement for many continued lines. However, converting to this newer method has caused portability problems with many historical makefiles, so the behavior with the POSIX makefile is specified to be the same as that of System V. It is suggested that the special target .ONESHELL be used as an implementation extension to achieve the single-shell grouping for a target or group of targets.

GNU make is POSIX compliant in this respect as it implements the System V behaviour and provides a .ONESHELL target for enabling the alternative behaviour, if wanted. ... which is another reason for GNU make to keep the current behaviour.

  • GNU make is not POSIX compliant: It does not set the -e flag for the shell and it implements a parser bug that causes whitespace to be handled incorrectly. – schily Oct 17 at 10:23
  • 2
    @schily I specifically used the words "in this respect". By this I meant that GNU make follows the POSIX standard in that it executes each recipe line in its own shell by default, and allows for the user to change this behaviour as suggested by the Rationale. – Kusalananda Oct 17 at 10:26

.ONESHELL is a GNU vendor specific extension that is not portable and not part of the POSIX standard.

The reason why this is not in the POSIX standard is most likely that there is only one implementation so far that supports it.

The reason why this is not the default of the standard is easier to explain:

POSIX tries to standardize existing behavior and POSIX does not like to make existing original UNIX implementations being in conflict with the standard - except when a specific behavior can be seen as a clear design bug.

The original make implementation from Stuart Feldman in 1977 called each line from the action list in a separate shell using sh -ce cmdline and this has become the master for all later make implementations.

But even the GNU implementation (seen separately) is not without problems when .ONESHELLis in effect. The reason is that GNU make does not set the -e flag of the shell when invoking commands. This causes a multi line shell script caused by .ONESHELL not to be terminated when an error occurs.

Beyond that, I see few benefit for .ONESHELL:

  • Multi line shell scripts may be used inside make by a backslash newline sequence in the make files.

  • The performance argument does not apply to modern make implementations since modern implementations try to avoid to call the shell in case that the command line does not contain shell specific meta characters.

  • My smake implementation even implements inline support for the echo command in case that it is the first command in a line is echo followed by only one semicolon and a simple other command. This avoids the need to call the shell for more than 90% of all cases.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.