[Scons-users] SCons misses a dependency which results in incorrect output.
Tal Dayan
tal at zapta.com
Thu Jul 17 01:37:15 EDT 2025
Yes, this work. Here is the log: https://pastebin.com/4GW5wWqQ
I wonder, will it also work deleting file2 from the database instead of
deleting the file itself? This may be less intrusive in case the
erroneous file may help diagnosing the issue.
Thanks for your help.
On Wed, Jul 16, 2025 at 9:13 PM Bill Deegan <bill at baddogconsulting.com>
wrote:
> 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
>>
> _______________________________________________
> 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/718b765d/attachment-0001.htm>
More information about the Scons-users
mailing list