Elegant way to remove target file if a Make rule fails
Asked Answered
T

1

7

I have a rule in my Makefile that roughly looks like this:

target_file: src_file
        some_tool src_file > target_file

(Of course, in reality I'm using $@ and $<, but for this question I prefer a more explicit style.)

The problem is that target_file is always created by the shell with a fresh timestamp, even if some_tool fails. In that case, an empty target_file exists, and even if I fix the underlying issue, it won't be rebuilt until I manually remove target_file or touch src_file.

Also, some_tool only writes to standard output, so I can't work around this through a cleaner approach such as some_tool ... -o target_file.

My current approach is to remove

target_file: src_file
        some_tool src_file > target_file || rm -f target_file

However, this has the disadvantage that Make won't notice if some_tool fails, because in that case rm takes over and returns exitcode 0 (succeess).

Another approach may be:

target_file: src_file
        some_tool src_file > target_file.tmp
        mv target_file.tmp target_file

But that kind of code is tedious and on failure leaves an annoying file target_file.tmp behind.

Is there a more elegant way to solve this problem?

Toh answered 8/10, 2016 at 7:59 Comment(0)
C
13

You could use the special target .DELETE_ON_ERROR:

If .DELETE_ON_ERROR is mentioned as a target anywhere in the makefile, then make will delete the target of a rule if it has changed and its recipe exits with a nonzero exit status, just as it does when it receives a signal.

All it takes is one line:

.DELETE_ON_ERROR:

And all rules that fail will have their target removed.

Coextend answered 8/10, 2016 at 10:39 Comment(1)
Thanks! This should be the default behavior in make.Hurricane

© 2022 - 2024 — McMap. All rights reserved.