[Scons-users] SCons misses a dependency which results in incorrect output.

Bill Deegan bill at baddogconsulting.com
Thu Jul 17 00:13:04 EDT 2025


If you patch your SCons sources like this, it should remove any failed
actions targets.
(This is just a quick hack, working on a proper fix with option to control
it)

diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py
index 98f1f345a..f0152a383 100644
--- a/SCons/Script/Main.py
+++ b/SCons/Script/Main.py
@@ -317,6 +317,10 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask):
             node = [node]
         nodename = ', '.join(map(str, node))

+        for n in node:
+            print(f"removing {n}")
+            n.remove()
+
         errfmt = "scons: *** [%s] %s\n"
         sys.stderr.write(errfmt % (nodename, buildError))




On Wed, Jul 16, 2025 at 5:15 PM Tal Dayan <tal at zapta.com> wrote:

> Our system is based on Python plugin classes that provide scons Builders
> so I wonder if we can just define our own subclass of Builder that
> automatically adds the deletion on errors functionality.
>
>
> https://github.com/FPGAwars/apio/blob/008b090e92246414353776ef5df4c0dd3e274fab/apio/scons/plugin_ice40.py#L62C16-L62C23
>
> On Wed, Jul 16, 2025 at 5:02 PM Bill Deegan <bill at baddogconsulting.com>
> wrote:
>
>> Tai,
>>
>> If you have a program you're running as the action in a command which is
>> erroring out but writing the file, you can work around this issue for the
>> time being by wrapping that program with a script which checks the exit
>> value of your program, and removing the target files if it exits with an
>> error status.
>>
>> That should be sufficient to get you going again.
>>
>> -Bill
>>
>> On Wed, Jul 16, 2025 at 3:18 PM Bill Deegan <bill at baddogconsulting.com>
>> wrote:
>>
>>> Did you read my explanation and how to fix it in your environment
>>> assuming command.sh is similar to what's really happening in your build?
>>>
>>>
>>> On Wed, Jul 16, 2025 at 3:16 PM Bill Deegan <bill at baddogconsulting.com>
>>> wrote:
>>>
>>>> It's an enhancement request.
>>>>
>>>> The bug is in your command.sh script.
>>>> I'll change the description and text.
>>>>
>>>>
>>>>
>>>> On Wed, Jul 16, 2025 at 12:56 PM Tal Dayan <tal at zapta.com> wrote:
>>>>
>>>>> Hi Bill, I will file an issue.
>>>>>
>>>>> I don't think it's safe for SCons to assume that once a program writes
>>>>> an output file it can't crash.
>>>>>
>>>>> On Wed, Jul 16, 2025 at 12:45 PM Bill Deegan <
>>>>> bill at baddogconsulting.com> wrote:
>>>>>
>>>>>> Arguably your command.sh is incorrectly written.
>>>>>>
>>>>>>  It copies the file and then checks it's contents and exits with
>>>>>> error status if there improper.
>>>>>>
>>>>>> So a quick fix would be to check the input before copying the file.
>>>>>>
>>>>>> From the URL you posted in other email here's the 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
>>>>>>
>>>>>> Change it to this:
>>>>>> #!/bin/bash
>>>>>> # Usage: ./command input > output
>>>>>>
>>>>>> # 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
>>>>>>
>>>>>> # Copy source to destination
>>>>>> cp "$1" "$2"
>>>>>>
>>>>>> exit 0
>>>>>>
>>>>>> Results:
>>>>>>
>>>>>> % ./run.sh
>>>>>>
>>>>>> ----- Iteration 1: file1 = 'good' -----
>>>>>>
>>>>>> scons: Reading SConscript files ...
>>>>>> scons: done reading SConscript files.
>>>>>> scons: Building targets ...
>>>>>> scons: building `file2' because it doesn't exist
>>>>>> ./command.sh file1 file2
>>>>>> +-file2
>>>>>>   +-file1
>>>>>> scons: done building targets.
>>>>>>
>>>>>> File1
>>>>>> MD5 (file1) = d7f986677d9f563bd1794b09d82206a3
>>>>>>      1 good
>>>>>>
>>>>>> File2
>>>>>> MD5 (file2) = d7f986677d9f563bd1794b09d82206a3
>>>>>>      1 good
>>>>>>
>>>>>> DBlite:
>>>>>> === .:
>>>>>> file1: d7f986677d9f563bd1794b09d82206a3 1752694898 5
>>>>>> file2: d7f986677d9f563bd1794b09d82206a3 1752694898 5
>>>>>>         file1: d7f986677d9f563bd1794b09d82206a3 1752694898 5
>>>>>>         2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE
>>>>>> $TARGET]
>>>>>>
>>>>>> ----- Iteration 2: file1 = 'bad' -----
>>>>>>
>>>>>> scons: Reading SConscript files ...
>>>>>> scons: done reading SConscript files.
>>>>>> scons: Building targets ...
>>>>>> scons: rebuilding `file2' because `file1' changed
>>>>>> ./command.sh file1 file2
>>>>>> scons: *** [file2] Error 1
>>>>>> +-file2
>>>>>>   +-file1
>>>>>> scons: building terminated because of errors.
>>>>>>
>>>>>> File1
>>>>>> MD5 (file1) = df207dc9143c6fabf60b69b9c3035103
>>>>>>      1 bad
>>>>>>
>>>>>> File2
>>>>>> md5: file2: No such file or directory
>>>>>> cat: file2: No such file or directory
>>>>>>
>>>>>> DBlite:
>>>>>> === .:
>>>>>> file1: df207dc9143c6fabf60b69b9c3035103 1752694898 4
>>>>>> file2: d7f986677d9f563bd1794b09d82206a3 1752694898 5
>>>>>>         file1: d7f986677d9f563bd1794b09d82206a3 1752694898 5
>>>>>>         2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE
>>>>>> $TARGET]
>>>>>>
>>>>>> ----- Iteration 3: file1 = 'good' -----
>>>>>>
>>>>>> scons: Reading SConscript files ...
>>>>>> scons: done reading SConscript files.
>>>>>> scons: Building targets ...
>>>>>> scons: building `file2' because it doesn't exist
>>>>>> ./command.sh file1 file2
>>>>>> +-file2
>>>>>>   +-file1
>>>>>> scons: done building targets.
>>>>>>
>>>>>> File1
>>>>>> MD5 (file1) = d7f986677d9f563bd1794b09d82206a3
>>>>>>      1 good
>>>>>>
>>>>>> File2
>>>>>> MD5 (file2) = d7f986677d9f563bd1794b09d82206a3
>>>>>>      1 good
>>>>>>
>>>>>> DBlite:
>>>>>> === .:
>>>>>> file1: d7f986677d9f563bd1794b09d82206a3 1752694899 5
>>>>>> file2: d7f986677d9f563bd1794b09d82206a3 1752694899 5
>>>>>>         file1: d7f986677d9f563bd1794b09d82206a3 1752694899 5
>>>>>>         2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE
>>>>>> $TARGET]
>>>>>>
>>>>>> There's not presently logic in SCons to delete target files if the
>>>>>> associated action yields an error.
>>>>>>
>>>>>> I think what you want is equivalent to makes .DELETE_ON_FAILURE,
>>>>>> there's actually a SO question on this:
>>>>>>
>>>>>> https://stackoverflow.com/questions/29546276/scons-delete-target-on-failure-of-any-action
>>>>>>
>>>>>> Please go ahead and file an enhancement request to add equivalent
>>>>>> to DELETE_ON_FAILURE, please include your reproducer scripts.
>>>>>>
>>>>>> -Bill
>>>>>>
>>>>>> On Wed, Jul 16, 2025 at 10:44 AM Tal Dayan <tal at zapta.com> wrote:
>>>>>>
>>>>>>> Looking at the end state of scons after invocation #3, the actual
>>>>>>> md5 of file2 doesn't match its md5 in the dblite.
>>>>>>>
>>>>>>> https://i.imgur.com/NGco3yQ.png
>>>>>>>
>>>>>>> On Wed, Jul 16, 2025 at 10:33 AM Tal Dayan <tal at zapta.com> wrote:
>>>>>>>
>>>>>>>> Hi Keith, I updated the example files here
>>>>>>>> https://github.com/FPGAwars/apio/issues/676
>>>>>>>>
>>>>>>>> They now include the md5 of the files and a dump of
>>>>>>>> .sconsign.dblite
>>>>>>>>
>>>>>>>> On Wed, Jul 16, 2025 at 10:08 AM Keith Prussing <
>>>>>>>> kprussing74 at gmail.com> wrote:
>>>>>>>>
>>>>>>>>> I suspect it's because `file1` has the same hash in the
>>>>>>>>> .sconsign.dblite as the last "good" build (i.e. the first one).
>>>>>>>>> Thus
>>>>>>>>> you get the line "scons: `file2' is up to date." on the third run.
>>>>>>>>> However, I am not an expert in the specifics of SCons' hashing
>>>>>>>>> methods.
>>>>>>>>>
>>>>>>>>> On Wed, Jul 16, 2025 at 12:38 PM Tal Dayan <tal at zapta.com> wrote:
>>>>>>>>> >
>>>>>>>>> > Hi all,
>>>>>>>>> >
>>>>>>>>> > We encountered this problem with the nextpnr tool and created
>>>>>>>>> here a small and independent example that demonstrates it.
>>>>>>>>> >
>>>>>>>>> > In the example below, a shell script 'command.sh' reads the
>>>>>>>>> source file 'file1' and writes it to the target file 'file2'. However, if
>>>>>>>>> the
>>>>>>>>> > source file starts with 'bad' it exits with an error code,
>>>>>>>>> *after* creating the target file.
>>>>>>>>> >
>>>>>>>>> > The script `run.sh', runs scons three times with these values of
>>>>>>>>> the source file file1 'good', 'bad', and 'good'.  The expectation is that
>>>>>>>>> after the third scons run, file2 should contain the value 'good' but it
>>>>>>>>> contains the value 'bad'.
>>>>>>>>> >
>>>>>>>>> > Do we miss anything or is it simply a bug?
>>>>>>>>> >
>>>>>>>>> > 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)
>>>>>>>>> >
>>>>>>>>> > ----------------------------------------------
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > command.sh:
>>>>>>>>> >
>>>>>>>>> > ----------------------------------------------
>>>>>>>>> >
>>>>>>>>> > #!/bin/bash
>>>>>>>>> >
>>>>>>>>> > # Usage: ./command input > output
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > # Read from the first argument and copy to stdout
>>>>>>>>> >
>>>>>>>>> > cat "$1"
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > # If the input file starts 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
>>>>>>>>> >
>>>>>>>>> > ----------------------------------------------
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > run.sh
>>>>>>>>> >
>>>>>>>>> > ----------------------------------------------
>>>>>>>>> >
>>>>>>>>> > #!/bin/bash
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > # Clean up.
>>>>>>>>> >
>>>>>>>>> > rm -f .sconsign.dblite
>>>>>>>>> >
>>>>>>>>> > rm -f file[12]
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > echo
>>>>>>>>> >
>>>>>>>>> > echo "---- Iteration 1: file1 = 'good'"
>>>>>>>>> >
>>>>>>>>> > echo "good" > file1
>>>>>>>>> >
>>>>>>>>> > scons
>>>>>>>>> >
>>>>>>>>> > echo
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > echo "File1"
>>>>>>>>> >
>>>>>>>>> > cat -n file1
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > echo "File2"
>>>>>>>>> >
>>>>>>>>> > cat -n file2
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > echo
>>>>>>>>> >
>>>>>>>>> > echo "---- Iteration 2: file1 = 'bad'"
>>>>>>>>> >
>>>>>>>>> > echo "bad" > file1
>>>>>>>>> >
>>>>>>>>> > cat -n file1
>>>>>>>>> >
>>>>>>>>> > scons
>>>>>>>>> >
>>>>>>>>> > echo
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > echo "File1"
>>>>>>>>> >
>>>>>>>>> > cat -n file1
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > echo "File2"
>>>>>>>>> >
>>>>>>>>> > cat -n file2
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > echo
>>>>>>>>> >
>>>>>>>>> > echo "---- Iteration 3: file1 = 'good'"
>>>>>>>>> >
>>>>>>>>> > echo "good" > file1
>>>>>>>>> >
>>>>>>>>> > cat -n file1
>>>>>>>>> >
>>>>>>>>> > scons
>>>>>>>>> >
>>>>>>>>> > echo
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > echo "File1"
>>>>>>>>> >
>>>>>>>>> > cat -n file1
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > echo "File2"
>>>>>>>>> >
>>>>>>>>> > cat -n file2
>>>>>>>>> >
>>>>>>>>> > ----------------------------------------------
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > Run 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
>>>>>>>>> >
>>>>>>>>> >      1 good
>>>>>>>>> >
>>>>>>>>> > File2
>>>>>>>>> >
>>>>>>>>> >      1 good
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > ---- Iteration 2: file1 = 'bad'
>>>>>>>>> >
>>>>>>>>> >      1 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
>>>>>>>>> >
>>>>>>>>> >      1 bad
>>>>>>>>> >
>>>>>>>>> > File2
>>>>>>>>> >
>>>>>>>>> >      1 bad
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > ---- Iteration 1: file1 = 'good'
>>>>>>>>> >
>>>>>>>>> >      1 good
>>>>>>>>> >
>>>>>>>>> > scons: Reading SConscript files ...
>>>>>>>>> >
>>>>>>>>> > scons: done reading SConscript files.
>>>>>>>>> >
>>>>>>>>> > scons: Building targets ...
>>>>>>>>> >
>>>>>>>>> > scons: `file2' is up to date.
>>>>>>>>> >
>>>>>>>>> > scons: done building targets.
>>>>>>>>> >
>>>>>>>>> >
>>>>>>>>> > File1
>>>>>>>>> >
>>>>>>>>> >      1 good
>>>>>>>>> >
>>>>>>>>> > File2
>>>>>>>>> >
>>>>>>>>> >      1 bad
>>>>>>>>> >
>>>>>>>>> > ----------------------------------------------
>>>>>>>>> >
>>>>>>>>> > _______________________________________________
>>>>>>>>> > Scons-users mailing list
>>>>>>>>> > Scons-users at scons.org
>>>>>>>>> > https://pairlist4.pair.net/mailman/listinfo/scons-users
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Keith Prussing
>>>>>>>>> _______________________________________________
>>>>>>>>> Scons-users mailing list
>>>>>>>>> Scons-users at scons.org
>>>>>>>>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>> Scons-users mailing list
>>>>>>> Scons-users at scons.org
>>>>>>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>>>>>>
>>>>>> _______________________________________________
>>>>>> Scons-users mailing list
>>>>>> Scons-users at scons.org
>>>>>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>>>>>
>>>>> _______________________________________________
>>>>> Scons-users mailing list
>>>>> Scons-users at scons.org
>>>>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>>>>
>>>> _______________________________________________
>> Scons-users mailing list
>> Scons-users at scons.org
>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>
> _______________________________________________
> Scons-users mailing list
> Scons-users at scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://pairlist4.pair.net/pipermail/scons-users/attachments/20250716/114579bf/attachment-0001.htm>


More information about the Scons-users mailing list