bashmakefile

How to ensure Make fails fast?


This is my Makefile:

.SHELLFLAGS: -e -o pipefail -c
.ONESHELL:

all:
    echo 1
    echo--- 2
    echo 3

I run make and I see this:

$ make
echo 1
echo--- 2
echo 3
1
/bin/sh: line 1: echo---: command not found
3

I don't want to see echo 3 executed, since the line before it failed. This is how I can fix this (notice the set -e added), but I want a better solution (maybe Make provides one):

.SHELLFLAGS: -e -o pipefail -c
.ONESHELL:

all:
    set -e
    echo 1
    echo--- 2
    echo 3

Solution

  • The problem with your makefile is that .SHELLFLAGS is a variable, but you set it as a target. You wrote:

    .SHELLFLAGS: -e -o pipefail -c
    

    which creates a target named .SHELLFLAGS (which means nothing to GNU Make) with prerequisites -e, -o, pipefail, and -c. Instead, you want:

    .SHELLFLAGS := -e -o pipefail -c
    

    However, these are bash-specific flags so you should also be sure to add:

    SHELL := /bin/bash
    

    otherwise your makefile will fail on systems where /bin/sh is not bash.

    ETA Oh sorry, I misinterpreted when you said you didn't want to see echo 3 I thought you meant you didn't want it to be printed out.

    Old answer below:

    You cannot prevent this, if you enable .ONESHELL. That option tells make to send the entire recipe (all lines) to a single shell invocation. Of course, make cannot know which lines of the recipe will fail before it invokes that shell, so it will always print the entire recipe.

    If you want each line to be printed right before it's run and lines that are not run (due to error) to not be printed, you can't enable .ONESHELL.