summaryrefslogtreecommitdiffstats
path: root/doc/user/sideeffect.xml
diff options
context:
space:
mode:
Diffstat (limited to 'doc/user/sideeffect.xml')
-rw-r--r--doc/user/sideeffect.xml208
1 files changed, 137 insertions, 71 deletions
diff --git a/doc/user/sideeffect.xml b/doc/user/sideeffect.xml
index d03fbe2..2733769 100644
--- a/doc/user/sideeffect.xml
+++ b/doc/user/sideeffect.xml
@@ -2,7 +2,7 @@
<!DOCTYPE sconsdoc [
<!ENTITY % scons SYSTEM "../scons.mod">
%scons;
-
+
<!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
%builders-mod;
<!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
@@ -13,11 +13,11 @@
%variables-mod;
]>
-<chapter id="chap-sideeffect"
+<section id="sect-sideeffect"
xmlns="http://www.scons.org/dbxsd/v1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
-<title>Sideeffect files</title>
+<title>Declaring Additional Outputs: the &f-SideEffect; Function </title>
<!--
@@ -46,68 +46,142 @@
<para>
- If &SCons; is unaware that a build step produces an extra file,
- the &SideEffect; method can be used to identify it,
- so that the file can be used as a dependency in subsequent build steps.
- However, the primary use for the &SideEffect; method
- is to prevent two build steps from simultaneously modifying the same file.
+ Sometimes the way an action is defined causes effects on files
+ that &SCons; does not recognize as targets. The &f-link-SideEffect;
+ method can be used to informs &SCons; about such files.
+ This can be used just to flag a dependency for use in subsequent
+ build steps, although there is usually a better way to do that.
+ The primary use for the &SideEffect; method
+ is to prevent two build steps from simultaneously modifying
+ or accessing the same file in a way that could impact each other.
</para>
<para>
- TODO: currently doesn't work due to issue #2154:
- https://github.com/SCons/scons/issues/2154
+
+ In this example, the rule to build <filename>file1</filename>
+ will also put data into <filename>log</filename>, which is used
+ as a source for the command to generate <filename>file2</filename>,
+ but <filename>log</filename> is unknown to &SCons; on a clean
+ build: it neither exists, nor is it a target output by any builder.
+ The <filename>SConscript</filename> uses
+ &SideEffect; to inform &SCons; about the additional output file.
+
</para>
-
+
+ <scons_example name="sideeffect_simple">
+ <file name="SConstruct" printme="1">
+env = Environment()
+f2 = env.Command(
+ target='file2',
+ source='log',
+ action=Copy('$TARGET', '$SOURCE')
+)
+f1 = env.Command(
+ target='file1',
+ source=[],
+ action='echo >$TARGET data1; echo >log updated file1'
+)
+env.SideEffect('log', f1)
+ </file>
+ </scons_example>
+
<para>
- If more than one build step creates or manipulates the same file,
- it can cause unpleasant results if both build steps are run at the same time.
- The shared file is declared as a side-effect of building the primary targets
- and &SCons; will prevent the two build steps from running in parallel.
+ Without the &f-SideEffect;, this build would fail with a message
+ <computeroutput>Source `log' not found, needed by target `file2'</computeroutput>,
+ but now it can proceed:
</para>
+ <scons_output example="sideeffect_simple" suffix="1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
<para>
- In this example, the <filename>SConscript</filename> uses
- &SideEffect; to inform &SCons; about the additional output file.
+ However, it is better to actually identify
+ <filename>log</filename> as a target, since in this
+ case that's what it is:
</para>
- <scons_example name="sideeffect_simple">
+ <scons_example name="sideeffect_simple2">
<file name="SConstruct" printme="1">
env = Environment()
-f2 = env.Command('file2', 'log', Copy('$TARGET', '$SOURCE'))
-f1 = env.Command('file1', [],
- 'echo >$TARGET data1; echo >log updated file1')
-env.SideEffect('log', env.Command('file1', [],
- 'echo >$TARGET data1; echo >log updated file1'))
+f2 = env.Command(
+ target='file2',
+ source='log',
+ action=Copy('$TARGET', '$SOURCE')
+)
+f1 = env.Command(
+ target=['file1', 'log'],
+ source=[],
+ action='echo >$TARGET data1; echo >log updated file1'
+)
</file>
</scons_example>
+ <scons_output example="sideeffect_simple2" suffix="1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
<para>
- Even when run in parallel mode, &SCons; will run the two steps in order:
+ In general, &SideEffect; is not intended for the case when
+ a command produces extra target files (that is, files which
+ will be used as sources to other build steps). For example, the
+ the Microsoft Visual C/C++ compiler is capable of performing
+ incremental linking, for which it uses a status file - such that
+ linking <filename>foo.exe</filename> also produces
+ a <filename>foo.ilk</filename>, or uses it if it was already present,
+ if the <option>/INCREMENTAL</option> option was supplied.
+ Specifying <filename>foo.ilk</filename> as a
+ side-effect of <filename>foo.exe</filename>
+ is <emphasis>not</emphasis> a recommended use of &SideEffect;
+ since <filename>foo.ilk</filename> is used by the link.
+ &SCons; handles side-effect files
+ slightly differently in its analysis of the dependency graph.
+ When a command produces multiple output files,
+ they should be specified as multiple targets of
+ the call to the relevant builder function.
+ The &SideEffect; function itself should really only be used
+ when it's important to ensure that commands are not executed in parallel,
+ such as when a "peripheral" file (such as a log file)
+ may actually be updated by more than one command invocation.
</para>
- <scons_output example="sideeffect_simple" suffix="1">
- <scons_output_command>scons -Q --jobs=2</scons_output_command>
- </scons_output>
+ <para>
+
+ Unfortunately, the tool which sets up the &b-Program; builder
+ for the MSVC compiler chain does not come prebuilt
+ with an understanding of the details of the <filename>.ilk</filename>
+ example - that the target list would need to change
+ in the presence of that specific option flag. Unlike the trivial
+ example above where we could simply tell the &Command; builder
+ there were two targets of the action, modifying the
+ chain of events for a builder like &b-Program;,
+ though not inherently complex, is definitely an
+ advanced &SCons; topic. It's okay to use &SideEffect; here
+ to get started, as long as it comes with an understanding
+ that it's "not quite right". Perhaps leave a comment in
+ the file as a reminder, if it does turn out to cause problems later.
+
+ </para>
<para>
- Sometimes a program the you need to call
- to build a target file
- will also update another file,
- such as a log file describing what the program
+ So if the main use is to prevent parallelism problems,
+ here is an example to illustrate.
+ Say a program that you need to call to build a target file
+ will also update a log file describing what the program
does while building the target.
- For example, we the folowing configuration
+ The following configuration
would have &SCons; invoke a hypothetical
script named <application>build</application>
(in the local directory)
- with command-line arguments that write
+ with command-line arguments telling it to write
log information to a common
<filename>logfile.txt</filename> file:
@@ -115,10 +189,16 @@ env.SideEffect('log', env.Command('file1', [],
<screen>
env = Environment()
-env.Command('file1.out', 'file.in',
- './build --log logfile.txt $SOURCE $TARGET')
-env.Command('file2.out', 'file.in',
- './build --log logfile.txt $SOURCE $TARGET')
+env.Command(
+ target='file1.out',
+ source='file1.in',
+ action='./build --log logfile.txt $SOURCE $TARGET'
+)
+env.Command(
+ target='file2.out',
+ source='file2.in',
+ action='./build --log logfile.txt $SOURCE $TARGET'
+)
</screen>
<para>
@@ -156,10 +236,16 @@ env.Command('file2.out', 'file.in',
<scons_example name="sideeffect_shared">
<file name="SConstruct" printme="1">
env = Environment()
-f1 = env.Command('file1.out', 'file1.in',
- './build --log logfile.txt $SOURCE $TARGET')
-f2 = env.Command('file2.out', 'file2.in',
- './build --log logfile.txt $SOURCE $TARGET')
+f1 = env.Command(
+ target='file1.out',
+ source='file1.in',
+ action='./build --log logfile.txt $SOURCE $TARGET'
+)
+f2 = env.Command(
+ target='file2.out',
+ source='file2.in',
+ action='./build --log logfile.txt $SOURCE $TARGET'
+)
env.SideEffect('logfile.txt', f1 + f2)
</file>
<file name="file1.in">file1.in</file>
@@ -177,7 +263,7 @@ cat
This makes sure the the two
<application>./build</application> steps are run sequentially,
- even withthe <filename>--jobs=2</filename> in the command line:
+ even with the <filename>--jobs=2</filename> in the command line:
</para>
@@ -189,20 +275,23 @@ cat
The &SideEffect; function can be called multiple
times for the same side-effect file.
- Additionally, the name used as a &SideEffect; does not
- even need to actually exist as a file on disk.
+ In fact, the name used as a &SideEffect; does not
+ even need to actually exist as a file on disk -
&SCons; will still make sure
that the relevant targets
- will be executed sequentially, not in parallel:
+ will be executed sequentially, not in parallel.
+ The side effect is actually a pseudo-target, and &SCons;
+ mainly cares whether nodes are listed as depending on it,
+ not about its contents.
</para>
<scons_example name="sideeffect_parallel">
<file name="SConstruct" printme="1">
env = Environment()
-f1 = env.Command('file1.out', [], 'echo >$TARGET data1')
+f1 = env.Command('file1.out', [], action='echo >$TARGET data1')
env.SideEffect('not_really_updated', f1)
-f2 = env.Command('file2.out', [], 'echo >$TARGET data2')
+f2 = env.Command('file2.out', [], action='echo >$TARGET data2')
env.SideEffect('not_really_updated', f2)
</file>
</scons_example>
@@ -211,28 +300,5 @@ env.SideEffect('not_really_updated', f2)
<scons_output_command>scons -Q --jobs=2</scons_output_command>
</scons_output>
- <para>
-
- Note that it might be tempting to
- use &SideEffect; for additional target files
- that a command produces.
- For example, versions the Microsoft Visual C/C++ compiler
- produce a <filename>foo.ilk</filename>
- alongside compiling <filename>foo.obj</filename> file.
- Specifying <filename>foo.ilk</filename> as a
- side-effect of <filename>foo.obj</filename>
- is <emphasis>not</emphasis> a recommended use of &SideEffect;,
- because &SCons; handle side-effect files
- slightly differently in its analysis of the dependency graph.
- When a command produces multiple output files,
- they should be specified as multiple targets of
- the call to the relevant builder function,
- and the &SideEffect; function itself should really only be used
- when it's important to ensure that commands are not executed in parallel,
- such as when a "peripheral" file (such as a log file)
- may actually updated by more than one command invocation.
-
- </para>
+ </section>
- </chapter>
-