Skip to content
shellhacks.dev
Command Line

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.

1 min read
Summarize in AI

A recipe pipes a command into another one, and a failure in the first goes unnoticed.

Shell
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: $?"
Text
recipe finished
make: *** [strict.mk:4: show] Error 1
exit status: 2

A 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.

Share

More snippets

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.