3

The .DELETE_ON_ERROR target will tell make to delete a target if a rule fails. But this doesn't work for pipelines, because the exit status value $? holds the value of the last program in the pipeline. As an example, the following makefile will not delete the newly created file foo.

.DELETE_ON_ERROR:
foo:
    false | true > foo

Is there a way to get make to consider the rule as having failed if any of the programs in the pipeline fail (i.e., if there's a non-zero value in any of the elements of the $PIPESTATUS array)?

2 Answers2

4

If you're using bash, you can also set the pipefail option globally. I have this once at the start of my makefiles and it catches errors even in the middle of a pipe:

# Make sure any errors in the middle of a pipe cause the build to fail
SHELL=/bin/bash -e -o pipefail

(Changed from /bin/sh to /bin/bash based on MadScientist's comment)

techno
  • 106
  • Good point, MadScientist. I'll update my response to reflect your comment. (And discuss with my teammates internally.) – techno Jul 23 '12 at 16:50
2

If you're sure your makefile will have bash as its shell, you could try setting the pipefail option:

SHELL=bash
.DELETE_ON_ERROR:
foo:
    set -o pipefail; false | true > foo

Since each line of a rule runs in a separate shell instance, you'll have to add set -o pipefail to each line you want to apply this to.

If you want it to work on any POSIX sh (and not just bash), the answer is much more involved.

Jander
  • 16,682