diff options
Diffstat (limited to 'doc/user/sideeffect.in')
-rw-r--r-- | doc/user/sideeffect.in | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/doc/user/sideeffect.in b/doc/user/sideeffect.in new file mode 100644 index 0000000..cbeefae --- /dev/null +++ b/doc/user/sideeffect.in @@ -0,0 +1,216 @@ +<!-- + + __COPYRIGHT__ + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <!-- + + <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. + + </para> + + TODO: currently doesn't work due to issue #2154: + http://scons.tigris.org/issues/show_bug.cgi?id=2154 + + <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. + + </para> + + <para> + + In this example, the <filename>SConscript</filename> uses + &SideEffect; to inform &SCons; about the additional output file. + + </para> + + <scons_example name="SideEffectSimple"> + <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')) + </file> + </scons_example> + + <para> + + Even when run in parallel mode, &SCons; will run the two steps in order: + + </para> + + <scons_output example="SideEffectSimple"> + <scons_output_command>scons -Q --jobs=2</scons_output_command> + </scons_output> + + --> + + <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 + does while building the target. + For example, we the folowing configuration + would have &SCons; invoke a hypothetical + script named <application>build</application> + (in the local directory) + with command-line arguments that write + log information to a common + <filename>logfile.txt</filename> file: + + </para> + + <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') + <screen> + + <para> + + This can cause problems when running + the build in parallel if + &SCons; decides to update both targets + by running both program invocations at the same time. + The multiple program invocations + may interfere with each other + writing to the common log file, + leading at best to intermixed output in the log file, + and at worst to an actual failed build + (on a system like Windows, for example, + where only one process at a time can open the log file for writing). + + </para> + + <para> + + We can make sure that &SCons; does not + run these <application>build</application> + commands at the same time + by using the &SideEffect; function + to specify that updating + the <filename>logfile.txt</filename> file + is a side effect of building the specified + <filename>file1</filename> + and + <filename>file2</filename> + target files: + + </para> + + <scons_example name="SideEffectShared"> + <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') + env.SideEffect('logfile.txt', f1 + f2) + </file> + <file name="file1.in">file1.in</file> + <file name="file2.in">file2.in</file> + <file name="build" chmod="0755"> + cat + </file> + </scons_example> + + <para> + + </para> + + <para> + + This makes sure the the two + <application>./build</application> steps are run sequentially, + even withthe <filename>--jobs=2</filename> in the command line: + + </para> + + <scons_output example="SideEffectShared"> + <scons_output_command>scons -Q --jobs=2</scons_output_command> + </scons_output> + + <para> + + 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. + &SCons; will still make sure + that the relevant targets + will be executed sequentially, not in parallel: + + </para> + + <scons_example name="SideEffectParallel"> + <file name="SConstruct" printme="1"> + env = Environment() + f1 = env.Command('file1.out', [], 'echo >$TARGET data1') + env.SideEffect('not_really_updated', f1) + f2 = env.Command('file2.out', [], 'echo >$TARGET data2') + env.SideEffect('not_really_updated', f2) + </file> + </scons_example> + + <scons_output example="SideEffectParallel"> + <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> |