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

Bill Deegan bill at baddogconsulting.com
Wed Jul 16 20:01:43 EDT 2025


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
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://pairlist4.pair.net/pipermail/scons-users/attachments/20250716/366c3c3b/attachment-0001.htm>


More information about the Scons-users mailing list