Skip to content

Add option to delete targets for failed actions simliar to make's DELETE_ON_ERROR #4747

@zapta

Description

@zapta

Describe the bug
When a command fails after writing its output file, SCons doesn't delete the target file.
Add feature like make's DELETE_ON_ERROR to allow optional deletion of targets of actions which error out.
See also StackOverFlow question

Required information

  • Link to SCons Users thread discussing your issue.

https://pairlist4.pair.net/pipermail/scons-users/2025-July/009515.html

  • Version of SCons
    4.8.1

  • Version of Python
    3.13.1

  • Which python distribution if applicable (python.org, cygwin, anaconda, macports, brew,etc)

python.org (I think)

  • How you installed SCons

pip install scons

  • What Platform are you on? (Linux/Windows and which version)

macOS 15.5 Apple Silicon

  • How to reproduce your issue?

Extract the three files below SConstruct, command.sh and run.sh, make command.sh and run.sh executable and run run.sh.

The command command.sh copies file1 to file2. If file1 starts with 'bad' it exits with an error code to simulate a crash after the output file was written. SCons is executed three times with file1 having the content "good", "bad", and "good" respectively. At the end of the third scons runs we expect file2 to have "good" but it contains "bad".

  1. File SConstruct:
# SCons environment
env = Environment()

# Copy file1 → file2 using command.sh
# Inject an error if file1 starts with 'bad"
file2 = env.Command(
    target='file2',
    source='file1',
    action='./command.sh $SOURCE $TARGET'
)

# Make 'file2' the default target
Default(file2)
  1. File command.sh:
#!/bin/bash
# Usage: ./command input > output

# Copy source to destination
cp "$1" "$2"

# If the input file stats with 'bad' inject an error AFTER creating the output file.

first_line=$(head -n 1 "$1")

if [[ "$first_line" == bad* ]]; then
  exit 1
fi

exit 0
  1. File run.sh:
#!/bin/bash

# Clean up.
rm -f .sconsign.dblite
rm -f file[12]

values=('good' 'bad' 'good')

i=0
for val in "${values[@]}"; do
  ((i++))
  echo
  echo "----- Iteration $i: file1 = '$val' -----"

  echo
  echo "$val" > file1
  scons

  echo
  echo "File1"
  md5 file1
  cat -n file1

  echo
  echo "File2"
  md5 file2
  cat -n file2

  echo
  echo "DBlite:"
  sconsign  .sconsign.dblite
done

exit 
  1. Output log
$ ./run.sh 

----- Iteration 1: file1 = 'good' -----

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
./command.sh file1 file2
scons: done building targets.

File1
MD5 (file1) = d7f986677d9f563bd1794b09d82206a3
     1	good

File2
MD5 (file2) = d7f986677d9f563bd1794b09d82206a3
     1	good

DBlite:
=== .:
file1: d7f986677d9f563bd1794b09d82206a3 1752702994 5
file2: d7f986677d9f563bd1794b09d82206a3 1752702995 5
        file1: d7f986677d9f563bd1794b09d82206a3 1752702994 5
        2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE $TARGET]

----- Iteration 2: file1 = 'bad' -----

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
./command.sh file1 file2
scons: *** [file2] Error 1
scons: building terminated because of errors.

File1
MD5 (file1) = df207dc9143c6fabf60b69b9c3035103
     1	bad

File2
MD5 (file2) = df207dc9143c6fabf60b69b9c3035103
     1	bad

DBlite:
=== .:
file1: df207dc9143c6fabf60b69b9c3035103 1752702995 4
file2: d7f986677d9f563bd1794b09d82206a3 1752702995 5
        file1: d7f986677d9f563bd1794b09d82206a3 1752702994 5
        2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE $TARGET]

----- Iteration 3: file1 = 'good' -----

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `file2' is up to date.
scons: done building targets.

File1
MD5 (file1) = d7f986677d9f563bd1794b09d82206a3
     1	good

File2
MD5 (file2) = df207dc9143c6fabf60b69b9c3035103
     1	bad

DBlite:
=== .:
file1: d7f986677d9f563bd1794b09d82206a3 1752702995 5
file2: d7f986677d9f563bd1794b09d82206a3 1752702995 4
        file1: d7f986677d9f563bd1794b09d82206a3 1752702995 5
        2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE $TARGET]
/projects/apio-dev/repo/experimental/scons_bug$ 
  • How you invoke scons (The command line you're using "scons --flags some_arguments")

Running scons three times via run.sh.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions