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)?

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)

| improve this answer | |
  • 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.

| improve this answer | |
  • This works, but boy is it ugly to add it to every line that contains a pipeline. – Lorin Hochstein Jul 18 '11 at 18:05
  • 1
    @lorin: You could clean it up a little with a Make variable -- e.g. PF=set -o pipefail; after which you can do $(PF) false | true > foo. – Jander Jul 19 '11 at 1:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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