Stop make on a Failing Pipeline with pipefail in a Recipe
Make a failing stage in a recipe pipeline stop make by setting SHELL to bash and .SHELLFLAGS to -o pipefail -c. Without it, only the last command's status counts.
A recipe pipes a command into another one, and a failure in the first goes unnoticed.
cat > plain.mk <<'EOF'
show:
@false | cat
@echo "recipe finished"
EOF
cat > strict.mk <<'EOF'
SHELL := /bin/bash
.SHELLFLAGS := -o pipefail -c
show:
@false | cat
@echo "recipe finished"
EOF
make -f plain.mk
make -f strict.mk
echo "exit status: $?"recipe finished
make: *** [strict.mk:4: show] Error 1
exit status: 2A pipeline returns the status of its last command, so false | cat succeeds and make printed recipe finished. With SHELL := /bin/bash and .SHELLFLAGS := -o pipefail -c, make starts bash with pipefail, the pipeline reports the first failure, and the second run ended with Error 1 and make's own exit status 2. See Choosing the Shell in the make manual.
.SHELLFLAGS needs GNU Make 3.82 or later and applies to every recipe in the file. Setting SHELL to bash makes the Makefile need bash, where /bin/sh was enough, and BSD make reads these variables differently. Add -e too, as in -e -o pipefail -c, to stop at the first failing line of a multi-command recipe. This was run with GNU Make 4.3.