Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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

share|improve this question
    
Related: Get exit code of process that's piped to another –  Gilles Jul 15 '11 at 10:43
add comment

2 Answers 2

up vote 2 down vote accepted

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)

share|improve this answer
    
Please do not do this. It will fail on any system where /bin/sh != bash, which are quite a few systems (all Ubuntu and Debian versions of Linux, and almost every non-Linux system). If you want bash behavior, you should always request bash specifically: /bin/bash -e -o pipefail –  MadScientist Jul 21 '12 at 16:29
    
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
add comment

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.

share|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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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