Re: SCons misses a dependency which results in incorrect output.

Tal Dayan <[email protected]> Wed, 16 Jul 2025 12:56:20 -0700
Newsgroups gmane.comp.programming.tools.scons.user
Message-ID <CAM+zu_6i3W8MXyD_sV7rh=qsAo5C5yw2eGxHP8f3eNAt-k8PgQ@mail.gmail.com>
--===============1304207759890990031==
Content-Type: multipart/alternative; boundary="0000000000005819a0063a114ae7"

--0000000000005819a0063a114ae7
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

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=E2=80=AFPM Bill Deegan <bill@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=3D$(head -n 1 "$1")
>
> if [[ "$first_line" =3D=3D 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=3D$(head -n 1 "$1")
>
> if [[ "$first_line" =3D=3D bad* ]]; then
>   exit 1
> fi
>
> # Copy source to destination
> cp "$1" "$2"
>
> exit 0
>
> Results:
>
> % ./run.sh
>
> ----- Iteration 1: file1 =3D '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) =3D d7f986677d9f563bd1794b09d82206a3
>      1 good
>
> File2
> MD5 (file2) =3D d7f986677d9f563bd1794b09d82206a3
>      1 good
>
> DBlite:
> =3D=3D=3D .:
> file1: d7f986677d9f563bd1794b09d82206a3 1752694898 5
> file2: d7f986677d9f563bd1794b09d82206a3 1752694898 5
>         file1: d7f986677d9f563bd1794b09d82206a3 1752694898 5
>         2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE $TARGET]
>
> ----- Iteration 2: file1 =3D '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) =3D df207dc9143c6fabf60b69b9c3035103
>      1 bad
>
> File2
> md5: file2: No such file or directory
> cat: file2: No such file or directory
>
> DBlite:
> =3D=3D=3D .:
> file1: df207dc9143c6fabf60b69b9c3035103 1752694898 4
> file2: d7f986677d9f563bd1794b09d82206a3 1752694898 5
>         file1: d7f986677d9f563bd1794b09d82206a3 1752694898 5
>         2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE $TARGET]
>
> ----- Iteration 3: file1 =3D '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) =3D d7f986677d9f563bd1794b09d82206a3
>      1 good
>
> File2
> MD5 (file2) =3D d7f986677d9f563bd1794b09d82206a3
>      1 good
>
> DBlite:
> =3D=3D=3D .:
> 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-failu=
re-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=E2=80=AFAM Tal Dayan <[email protected]> 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=E2=80=AFAM Tal Dayan <[email protected]> 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=E2=80=AFAM Keith Prussing <kprussing74@gm=
ail.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=E2=80=AFPM Tal Dayan <[email protected]> wro=
te:
>>>> >
>>>> > 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 cont=
ains
>>>> the value 'bad'.
>>>> >
>>>> > Do we miss anything or is it simply a bug?
>>>> >
>>>> > SConstruct:
>>>> >
>>>> > ----------------------------------------------
>>>> >
>>>> > # SCons environment
>>>> >
>>>> > env =3D Environment()
>>>> >
>>>> >
>>>> > # Copy file1 =E2=86=92 file2 using command.sh
>>>> >
>>>> > # Inject an error if file1 starts with 'bad"
>>>> >
>>>> > file2 =3D env.Command(
>>>> >
>>>> >     target=3D'file2',
>>>> >
>>>> >     source=3D'file1',
>>>> >
>>>> >     action=3D'./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 creatin=
g
>>>> the output file.
>>>> >
>>>> >
>>>> > first_line=3D$(head -n 1 "$1")
>>>> >
>>>> >
>>>> > if [[ "$first_line" =3D=3D 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 =3D 'good'"
>>>> >
>>>> > echo "good" > file1
>>>> >
>>>> > scons
>>>> >
>>>> > echo
>>>> >
>>>> >
>>>> > echo "File1"
>>>> >
>>>> > cat -n file1
>>>> >
>>>> >
>>>> > echo "File2"
>>>> >
>>>> > cat -n file2
>>>> >
>>>> >
>>>> >
>>>> > echo
>>>> >
>>>> > echo "---- Iteration 2: file1 =3D 'bad'"
>>>> >
>>>> > echo "bad" > file1
>>>> >
>>>> > cat -n file1
>>>> >
>>>> > scons
>>>> >
>>>> > echo
>>>> >
>>>> >
>>>> > echo "File1"
>>>> >
>>>> > cat -n file1
>>>> >
>>>> >
>>>> > echo "File2"
>>>> >
>>>> > cat -n file2
>>>> >
>>>> >
>>>> > echo
>>>> >
>>>> > echo "---- Iteration 3: file1 =3D '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 =3D '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 =3D '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 =3D '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
>>>> > [email protected]
>>>> > https://pairlist4.pair.net/mailman/listinfo/scons-users
>>>>
>>>>
>>>>
>>>> --
>>>> Keith Prussing
>>>> _______________________________________________
>>>> Scons-users mailing list
>>>> [email protected]
>>>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>>>
>>> _______________________________________________
>> Scons-users mailing list
>> [email protected]
>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>
> _______________________________________________
> Scons-users mailing list
> [email protected]
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>

--0000000000005819a0063a114ae7
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hi Bill, I will file an issue.<div><br></div><div>I don&#3=
9;t think it&#39;s safe for SCons to assume that once a program writes an o=
utput file it can&#39;t crash.=C2=A0</div></div><br><div class=3D"gmail_quo=
te gmail_quote_container"><div dir=3D"ltr" class=3D"gmail_attr">On Wed, Jul=
 16, 2025 at 12:45=E2=80=AFPM Bill Deegan &lt;<a href=3D"mailto:bill@baddog=
consulting.com">[email protected]</a>&gt; wrote:<br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px =
solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>Arguably you=
r command.sh is incorrectly written.</div><div><br></div><div>=C2=A0It copi=
es the file and then checks it&#39;s contents and exits with error status i=
f there improper.</div><div><br></div><div>So a quick fix would be to check=
 the input before copying the file.</div><div><br></div><div>From the URL y=
ou posted in other email here&#39;s the command.sh</div><div><span style=3D=
"font-family:monospace">#!/bin/bash<br># Usage: ./command input &gt; output=
<br><br># Copy source to destination<br>cp &quot;$1&quot; &quot;$2&quot;<br=
><br># If the input file stats with &#39;bad&#39; inject an error AFTER cre=
ating the output file.<br><br>first_line=3D$(head -n 1 &quot;$1&quot;)<br><=
br>if [[ &quot;$first_line&quot; =3D=3D bad* ]]; then<br>=C2=A0 exit 1<br>f=
i<br><br>exit 0</span></div><div><span style=3D"font-family:monospace"><br>=
</span></div><div><span style=3D"font-family:monospace">Change it to this:<=
/span></div><div><span style=3D"font-family:monospace">#!/bin/bash<br># Usa=
ge: ./command input &gt; output<br><br># If the input file stats with &#39;=
bad&#39; inject an error AFTER creating the output file.<br><br>first_line=
=3D$(head -n 1 &quot;$1&quot;)<br><br>if [[ &quot;$first_line&quot; =3D=3D =
bad* ]]; then<br>=C2=A0 exit 1<br>fi<br><br># Copy source to destination<br=
>cp &quot;$1&quot; &quot;$2&quot;<br><br>exit 0</span><br><br></div><div>Re=
sults:</div><div><br></div><div><span style=3D"font-family:monospace">% ./r=
un.sh<br><br>----- Iteration 1: file1 =3D &#39;good&#39; -----<br><br>scons=
: Reading SConscript files ...<br>scons: done reading SConscript files.<br>=
scons: Building targets ...<br>scons: building `file2&#39; because it doesn=
&#39;t exist<br>./command.sh file1 file2<br>+-file2<br>=C2=A0 +-file1<br>sc=
ons: done building targets.<br><br>File1<br>MD5 (file1) =3D d7f986677d9f563=
bd1794b09d82206a3<br>=C2=A0 =C2=A0 =C2=A01	good<br><br>File2<br>MD5 (file2)=
 =3D d7f986677d9f563bd1794b09d82206a3<br>=C2=A0 =C2=A0 =C2=A01	good<br><br>=
DBlite:<br>=3D=3D=3D .:<br>file1: d7f986677d9f563bd1794b09d82206a3 17526948=
98 5<br>file2: d7f986677d9f563bd1794b09d82206a3 1752694898 5<br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 file1: d7f986677d9f563bd1794b09d82206a3 1752694898 5<br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 2dbc2dce125a753309a27b7d5157aaaa [./command.sh =
$SOURCE $TARGET]<br><br>----- Iteration 2: file1 =3D &#39;bad&#39; -----<br=
><br>scons: Reading SConscript files ...<br>scons: done reading SConscript =
files.<br>scons: Building targets ...<br>scons: rebuilding `file2&#39; beca=
use `file1&#39; changed<br>./command.sh file1 file2<br>scons: *** [file2] E=
rror 1<br>+-file2<br>=C2=A0 +-file1<br>scons: building terminated because o=
f errors.<br><br>File1<br>MD5 (file1) =3D df207dc9143c6fabf60b69b9c3035103<=
br>=C2=A0 =C2=A0 =C2=A01	bad<br><br>File2<br>md5: file2: No such file or di=
rectory<br>cat: file2: No such file or directory<br><br>DBlite:<br>=3D=3D=
=3D .:<br>file1: df207dc9143c6fabf60b69b9c3035103 1752694898 4<br>file2: d7=
f986677d9f563bd1794b09d82206a3 1752694898 5<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
file1: d7f986677d9f563bd1794b09d82206a3 1752694898 5<br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE $TARGET]<=
br><br>----- Iteration 3: file1 =3D &#39;good&#39; -----<br><br>scons: Read=
ing SConscript files ...<br>scons: done reading SConscript files.<br>scons:=
 Building targets ...<br>scons: building `file2&#39; because it doesn&#39;t=
 exist<br>./command.sh file1 file2<br>+-file2<br>=C2=A0 +-file1<br>scons: d=
one building targets.<br><br>File1<br>MD5 (file1) =3D d7f986677d9f563bd1794=
b09d82206a3<br>=C2=A0 =C2=A0 =C2=A01	good<br><br>File2<br>MD5 (file2) =3D d=
7f986677d9f563bd1794b09d82206a3<br>=C2=A0 =C2=A0 =C2=A01	good<br><br>DBlite=
:<br>=3D=3D=3D .:<br>file1: d7f986677d9f563bd1794b09d82206a3 1752694899 5<b=
r>file2: d7f986677d9f563bd1794b09d82206a3 1752694899 5<br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 file1: d7f986677d9f563bd1794b09d82206a3 1752694899 5<br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 2dbc2dce125a753309a27b7d5157aaaa [./command.sh $SOURCE=
 $TARGET]</span></div><div><br></div><div>There&#39;s not presently logic i=
n SCons to delete target files if the associated action yields an error.</d=
iv><div><br></div><div>I think what you want is equivalent to makes .DELETE=
_ON_FAILURE, there&#39;s actually a SO question on this:</div><div><a href=
=3D"https://stackoverflow.com/questions/29546276/scons-delete-target-on-fai=
lure-of-any-action" target=3D"_blank">https://stackoverflow.com/questions/2=
9546276/scons-delete-target-on-failure-of-any-action</a></div><div><br></di=
v><div>Please go ahead and file an enhancement request to add equivalent to=
=C2=A0DELETE_ON_FAILURE, please include your reproducer scripts.</div><div>=
<br></div><div>-Bill</div></div><br><div class=3D"gmail_quote"><div dir=3D"=
ltr" class=3D"gmail_attr">On Wed, Jul 16, 2025 at 10:44=E2=80=AFAM Tal Daya=
n &lt;<a href=3D"mailto:[email protected]" target=3D"_blank">[email protected]</a>&=
gt; wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0=
px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div =
dir=3D"ltr">Looking at the end state of scons after invocation #3, the actu=
al md5 of file2 doesn&#39;t match its md5 in the dblite.<div><br></div><div=
><a href=3D"https://i.imgur.com/NGco3yQ.png" target=3D"_blank">https://i.im=
gur.com/NGco3yQ.png</a></div></div><br><div class=3D"gmail_quote"><div dir=
=3D"ltr" class=3D"gmail_attr">On Wed, Jul 16, 2025 at 10:33=E2=80=AFAM Tal =
Dayan &lt;<a href=3D"mailto:[email protected]" target=3D"_blank">[email protected]<=
/a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><=
div dir=3D"ltr">Hi Keith, I updated the example files here=C2=A0<a href=3D"=
https://github.com/FPGAwars/apio/issues/676" target=3D"_blank">https://gith=
ub.com/FPGAwars/apio/issues/676</a><div><br></div><div>They now include the=
 md5 of the files and a dump of=C2=A0<span style=3D"font-variant-ligatures:=
no-common-ligatures;color:rgb(0,0,0);font-family:Menlo;font-size:12px">.sco=
nsign.dblite</span></div>





</div><br><div class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">=
On Wed, Jul 16, 2025 at 10:08=E2=80=AFAM Keith Prussing &lt;<a href=3D"mail=
to:[email protected]" target=3D"_blank">[email protected]</a>&gt; w=
rote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I suspect =
it&#39;s because `file1` has the same hash in the<br>
.sconsign.dblite as the last &quot;good&quot; build (i.e. the first one). T=
hus<br>
you get the line &quot;scons: `file2&#39; is up to date.&quot; on the third=
 run.<br>
However, I am not an expert in the specifics of SCons&#39; hashing<br>
methods.<br>
<br>
On Wed, Jul 16, 2025 at 12:38=E2=80=AFPM Tal Dayan &lt;<a href=3D"mailto:ta=
[email protected]" target=3D"_blank">[email protected]</a>&gt; wrote:<br>
&gt;<br>
&gt; Hi all,<br>
&gt;<br>
&gt; We encountered this problem with the nextpnr tool and created here a s=
mall and independent example that demonstrates it.<br>
&gt;<br>
&gt; In the example below, a shell script &#39;command.sh&#39; reads the so=
urce file &#39;file1&#39; and writes it to the target file &#39;file2&#39;.=
 However, if the<br>
&gt; source file starts with &#39;bad&#39; it exits with an error code, *af=
ter* creating the target file.<br>
&gt;<br>
&gt; The script `run.sh&#39;, runs scons three times with these values of t=
he source file file1 &#39;good&#39;, &#39;bad&#39;, and &#39;good&#39;.=C2=
=A0 The expectation is that after the third scons run, file2 should contain=
 the value &#39;good&#39; but it contains the value &#39;bad&#39;.<br>
&gt;<br>
&gt; Do we miss anything or is it simply a bug?<br>
&gt;<br>
&gt; SConstruct:<br>
&gt;<br>
&gt; ----------------------------------------------<br>
&gt;<br>
&gt; # SCons environment<br>
&gt;<br>
&gt; env =3D Environment()<br>
&gt;<br>
&gt;<br>
&gt; # Copy file1 =E2=86=92 file2 using command.sh<br>
&gt;<br>
&gt; # Inject an error if file1 starts with &#39;bad&quot;<br>
&gt;<br>
&gt; file2 =3D env.Command(<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0target=3D&#39;file2&#39;,<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0source=3D&#39;file1&#39;,<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0action=3D&#39;./command.sh $SOURCE &gt; $TARGET&#39=
;<br>
&gt;<br>
&gt; )<br>
&gt;<br>
&gt;<br>
&gt; # Make &#39;file2&#39; the default target<br>
&gt;<br>
&gt; Default(file2)<br>
&gt;<br>
&gt; ----------------------------------------------<br>
&gt;<br>
&gt;<br>
&gt; command.sh:<br>
&gt;<br>
&gt; ----------------------------------------------<br>
&gt;<br>
&gt; #!/bin/bash<br>
&gt;<br>
&gt; # Usage: ./command input &gt; output<br>
&gt;<br>
&gt;<br>
&gt; # Read from the first argument and copy to stdout<br>
&gt;<br>
&gt; cat &quot;$1&quot;<br>
&gt;<br>
&gt;<br>
&gt; # If the input file starts with &#39;bad&#39;, inject an error AFTER c=
reating the output file.<br>
&gt;<br>
&gt;<br>
&gt; first_line=3D$(head -n 1 &quot;$1&quot;)<br>
&gt;<br>
&gt;<br>
&gt; if [[ &quot;$first_line&quot; =3D=3D bad* ]]; then<br>
&gt;<br>
&gt;=C2=A0 =C2=A0exit 1<br>
&gt;<br>
&gt; fi<br>
&gt;<br>
&gt;<br>
&gt; exit 0<br>
&gt;<br>
&gt; ----------------------------------------------<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; run.sh<br>
&gt;<br>
&gt; ----------------------------------------------<br>
&gt;<br>
&gt; #!/bin/bash<br>
&gt;<br>
&gt;<br>
&gt; # Clean up.<br>
&gt;<br>
&gt; rm -f .sconsign.dblite<br>
&gt;<br>
&gt; rm -f file[12]<br>
&gt;<br>
&gt;<br>
&gt; echo<br>
&gt;<br>
&gt; echo &quot;---- Iteration 1: file1 =3D &#39;good&#39;&quot;<br>
&gt;<br>
&gt; echo &quot;good&quot; &gt; file1<br>
&gt;<br>
&gt; scons<br>
&gt;<br>
&gt; echo<br>
&gt;<br>
&gt;<br>
&gt; echo &quot;File1&quot;<br>
&gt;<br>
&gt; cat -n file1<br>
&gt;<br>
&gt;<br>
&gt; echo &quot;File2&quot;<br>
&gt;<br>
&gt; cat -n file2<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; echo<br>
&gt;<br>
&gt; echo &quot;---- Iteration 2: file1 =3D &#39;bad&#39;&quot;<br>
&gt;<br>
&gt; echo &quot;bad&quot; &gt; file1<br>
&gt;<br>
&gt; cat -n file1<br>
&gt;<br>
&gt; scons<br>
&gt;<br>
&gt; echo<br>
&gt;<br>
&gt;<br>
&gt; echo &quot;File1&quot;<br>
&gt;<br>
&gt; cat -n file1<br>
&gt;<br>
&gt;<br>
&gt; echo &quot;File2&quot;<br>
&gt;<br>
&gt; cat -n file2<br>
&gt;<br>
&gt;<br>
&gt; echo<br>
&gt;<br>
&gt; echo &quot;---- Iteration 3: file1 =3D &#39;good&#39;&quot;<br>
&gt;<br>
&gt; echo &quot;good&quot; &gt; file1<br>
&gt;<br>
&gt; cat -n file1<br>
&gt;<br>
&gt; scons<br>
&gt;<br>
&gt; echo<br>
&gt;<br>
&gt;<br>
&gt; echo &quot;File1&quot;<br>
&gt;<br>
&gt; cat -n file1<br>
&gt;<br>
&gt;<br>
&gt; echo &quot;File2&quot;<br>
&gt;<br>
&gt; cat -n file2<br>
&gt;<br>
&gt; ----------------------------------------------<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; Run log:<br>
&gt;<br>
&gt; ----------------------------------------------<br>
&gt;<br>
&gt; $ ./run.sh<br>
&gt;<br>
&gt;<br>
&gt; ---- Iteration 1: file1 =3D &#39;good&#39;<br>
&gt;<br>
&gt; scons: Reading SConscript files ...<br>
&gt;<br>
&gt; scons: done reading SConscript files.<br>
&gt;<br>
&gt; scons: Building targets ...<br>
&gt;<br>
&gt; ./command.sh file1 &gt; file2<br>
&gt;<br>
&gt; scons: done building targets.<br>
&gt;<br>
&gt;<br>
&gt; File1<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 1 good<br>
&gt;<br>
&gt; File2<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 1 good<br>
&gt;<br>
&gt;<br>
&gt; ---- Iteration 2: file1 =3D &#39;bad&#39;<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 1 bad<br>
&gt;<br>
&gt; scons: Reading SConscript files ...<br>
&gt;<br>
&gt; scons: done reading SConscript files.<br>
&gt;<br>
&gt; scons: Building targets ...<br>
&gt;<br>
&gt; ./command.sh file1 &gt; file2<br>
&gt;<br>
&gt; scons: *** [file2] Error 1<br>
&gt;<br>
&gt; scons: building terminated because of errors.<br>
&gt;<br>
&gt;<br>
&gt; File1<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 1 bad<br>
&gt;<br>
&gt; File2<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 1 bad<br>
&gt;<br>
&gt;<br>
&gt; ---- Iteration 1: file1 =3D &#39;good&#39;<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 1 good<br>
&gt;<br>
&gt; scons: Reading SConscript files ...<br>
&gt;<br>
&gt; scons: done reading SConscript files.<br>
&gt;<br>
&gt; scons: Building targets ...<br>
&gt;<br>
&gt; scons: `file2&#39; is up to date.<br>
&gt;<br>
&gt; scons: done building targets.<br>
&gt;<br>
&gt;<br>
&gt; File1<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 1 good<br>
&gt;<br>
&gt; File2<br>
&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 1 bad<br>
&gt;<br>
&gt; ----------------------------------------------<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; Scons-users mailing list<br>
&gt; <a href=3D"mailto:[email protected]" target=3D"_blank">Scons-users=
@scons.org</a><br>
&gt; <a href=3D"https://pairlist4.pair.net/mailman/listinfo/scons-users" re=
l=3D"noreferrer" target=3D"_blank">https://pairlist4.pair.net/mailman/listi=
nfo/scons-users</a><br>
<br>
<br>
<br>
-- <br>
Keith Prussing<br>
_______________________________________________<br>
Scons-users mailing list<br>
<a href=3D"mailto:[email protected]" target=3D"_blank">Scons-users@scon=
s.org</a><br>
<a href=3D"https://pairlist4.pair.net/mailman/listinfo/scons-users" rel=3D"=
noreferrer" target=3D"_blank">https://pairlist4.pair.net/mailman/listinfo/s=
cons-users</a><br>
</blockquote></div>
</blockquote></div>
_______________________________________________<br>
Scons-users mailing list<br>
<a href=3D"mailto:[email protected]" target=3D"_blank">Scons-users@scon=
s.org</a><br>
<a href=3D"https://pairlist4.pair.net/mailman/listinfo/scons-users" rel=3D"=
noreferrer" target=3D"_blank">https://pairlist4.pair.net/mailman/listinfo/s=
cons-users</a><br>
</blockquote></div>
_______________________________________________<br>
Scons-users mailing list<br>
<a href=3D"mailto:[email protected]" target=3D"_blank">Scons-users@scon=
s.org</a><br>
<a href=3D"https://pairlist4.pair.net/mailman/listinfo/scons-users" rel=3D"=
noreferrer" target=3D"_blank">https://pairlist4.pair.net/mailman/listinfo/s=
cons-users</a><br>
</blockquote></div>

--0000000000005819a0063a114ae7--

--===============1304207759890990031==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Scons-users mailing list
[email protected]
https://pairlist4.pair.net/mailman/listinfo/scons-users

--===============1304207759890990031==--