Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SCons delete $TARGET on failure of any Action

Tags:

scons

Is there a way to emulate Make's .DELETE_ON_FAILURE behavior? If I have a builder that executes a series of Actions to produce a target, I would expect them to operate atomically. If an earlier Action produces an (incomplete) file, and a later action fails to modify it, I would like the target file to be deleted, instead of remaining in its incomplete state.

Consider this SConstruct file:

def example(target, source, env):
    raise Exception('failure')
    # more processing that never happens...

action_list = [
    Copy('$TARGET', '$SOURCE'),
    Chmod('$TARGET', 0755),
    example,
]

Command(
    action = action_list,
    target = 'foo.out',
    source = 'foo.in',
)

If the example action fails, foo.out still exists, because the first two actions were successful. However, it is incomplete.

Interestingly, running scons again causes is to again retry to build foo.out, even though it exists in the filesystem.

like image 797
Jonathon Reinhart Avatar asked Oct 31 '25 20:10

Jonathon Reinhart


1 Answers

Yes, what you are looking for is GetBuildFailures.

Expanding on your example to include this feature...

import atexit
import os

def delete_on_failure():
    from SCons.Script import GetBuildFailures
    for bf in GetBuildFailures():
        if os.path.isfile(bf.node.abspath):
            print 'Removing %s' % bf.node.path
            os.remove(bf.node.abspath)
atexit.register(delete_on_failure)

def example(target, source, env):
    raise Exception('failure')
    # more processing that never happens...

action_list = [
    Copy('$TARGET', '$SOURCE'),
    Chmod('$TARGET', 0755),
    example,
]

Command(
    action = action_list,
    target = 'foo.out',
    source = 'foo.in',
)

Which when run produces the following...

>> scons --version
SCons by Steven Knight et al.:
    script: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
    engine: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
    engine path: ['/usr/lib/scons/SCons']
Copyright (c) 2001 - 2014 The SCons Foundation

>> tree 
.
├── foo.in
└── SConstruct

0 directories, 2 files

>> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
Copy("foo.out", "foo.in")
Chmod("foo.out", 0755)
example(["foo.out"], ["foo.in"])
scons: *** [foo.out] Exception : failure
Traceback (most recent call last):
  File "/usr/lib/scons/SCons/Action.py", line 1065, in execute
    result = self.execfunction(target=target, source=rsources, env=env)
  File "/path/to/SConstruct", line 13, in example
    raise Exception('failure')
Exception: failure
scons: building terminated because of errors.
Removing foo.out

>> tree
.
├── foo.in
└── SConstruct

0 directories, 2 files
like image 147
Kenneth E. Bellock Avatar answered Nov 04 '25 06:11

Kenneth E. Bellock



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!