diff options
Diffstat (limited to 'doc')
82 files changed, 3241 insertions, 24918 deletions
diff --git a/doc/user/actions.in b/doc/user/actions.in deleted file mode 100644 index d2a3dad..0000000 --- a/doc/user/actions.in +++ /dev/null @@ -1,404 +0,0 @@ -<!-- - - __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. - ---> - -<!-- - -=head1 Build actions - -Cons supports several types of B<build actions> that can be performed -to construct one or more target files. Usually, a build action is -a construction command, that is, a command-line string that invokes -an external command. Cons can also execute Perl code embedded in a -command-line string, and even supports an experimental ability to build -a target file by executing a Perl code reference directly. - -A build action is usually specified as the value of a construction -variable: - - $env = new cons( - CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>', - LINKCOM => '[perl] &link_executable("%>", "%<")', - ARCOM => sub { my($env, $target, @sources) = @_; - # code to create an archive - } - ); - -A build action may be associated directly with one or more target files -via the C<Command> method; see below. - -=head2 Construction commands - -A construction command goes through expansion of construction variables -and C<%-> pseudo-variables, as described above, to create the actual -command line that Cons will execute to generate the target file or -files. - -After substitution occurs, strings of white space are converted into -single blanks, and leading and trailing white space is eliminated. It -is therefore currently not possible to introduce variable length white -space in strings passed into a command. - -If a multi-line command string is provided, the commands are executed -sequentially. If any of the commands fails, then none of the rest are -executed, and the target is not marked as updated, i.e. a new signature is -not stored for the target. - -Normally, if all the commands succeed, and return a zero status (or whatever -platform-specific indication of success is required), then a new signature -is stored for the target. If a command erroneously reports success even -after a failure, then Cons will assume that the target file created by that -command is accurate and up-to-date. - -The first word of each command string, after expansion, is assumed to be an -executable command looked up on the C<PATH> environment variable (which is, -in turn, specified by the C<ENV> construction variable). If this command is -found on the path, then the target will depend upon it: the command will -therefore be automatically built, as necessary. It's possible to write -multi-part commands to some shells, separated by semi-colons. Only the first -command word will be depended upon, however, so if you write your command -strings this way, you must either explicitly set up a dependency (with the -C<Depends> method), or be sure that the command you are using is a system -command which is expected to be available. If it isn't available, you will, -of course, get an error. - -Cons normally prints a command before executing it. This behavior is -suppressed if the first character of the command is C<@>. Note that -you may need to separate the C<@> from the command name or escape it to -prevent C<@cmd> from looking like an array to Perl quote operators that -perform interpolation: - - # The first command line is incorrect, - # because "@cp" looks like an array - # to the Perl qq// function. - # Use the second form instead. - Command $env 'foo', 'foo.in', qq( - @cp %< tempfile - @ cp tempfile %> - ); - -If there are shell meta characters anywhere in the expanded command line, -such as C<E<lt>>, C<E<gt>>, quotes, or semi-colon, then the command -will actually be executed by invoking a shell. This means that a command -such as: - - cd foo - -alone will typically fail, since there is no command C<cd> on the path. But -the command string: - - cd $<:d; tar cf $>:f $<:f - -when expanded will still contain the shell meta character semi-colon, and a -shell will be invoked to interpret the command. Since C<cd> is interpreted -by this sub-shell, the command will execute as expected. - -=head2 Perl expressions - -If any command (even one within a multi-line command) begins with -C<[perl]>, the remainder of that command line will be evaluated by the -running Perl instead of being forked by the shell. If an error occurs -in parsing the Perl code, or if the Perl expression returns 0 or undef, -the command will be considered to have failed. For example, here is a -simple command which creates a file C<foo> directly from Perl: - - $env = new cons(); - Command $env 'foo', - qq([perl] open(FOO,'>foo');print FOO "hi\\n"; close(FOO); 1); - -Note that when the command is executed, you are in the same package as -when the F<Construct> or F<Conscript> file was read, so you can call -Perl functions you've defined in the same F<Construct> or F<Conscript> -file in which the C<Command> appears: - - $env = new cons(); - sub create_file { - my $file = shift; - open(FILE, ">$file"); - print FILE "hi\n"; - close(FILE); - return 1; - } - Command $env 'foo', "[perl] &create_file('%>')"; - -The Perl string will be used to generate the signature for the derived -file, so if you change the string, the file will be rebuilt. The contents -of any subroutines you call, however, are not part of the signature, -so if you modify a called subroutine such as C<create_file> above, -the target will I<not> be rebuilt. Caveat user. - -=head2 Perl code references [EXPERIMENTAL] - -Cons supports the ability to create a derived file by directly executing -a Perl code reference. This feature is considered EXPERIMENTAL and -subject to change in the future. - -A code reference may either be a named subroutine referenced by the -usual C<\&> syntax: - - sub build_output { - my($env, $target, @sources) = @_; - print "build_output building $target\n"; - open(OUT, ">$target"); - foreach $src (@sources) { - if (! open(IN, "<$src")) { - print STDERR "cannot open '$src': $!\n"; - return undef; - } - print OUT, <IN>; - } - close(OUT); - return 1; - } - Command $env 'output', \&build_output; - -or the code reference may be an anonymous subroutine: - - Command $env 'output', sub { - my($env, $target, @sources) = @_; - print "building $target\n"; - open(FILE, ">$target"); - print FILE "hello\n"; - close(FILE); - return 1; - }; - -To build the target file, the referenced subroutine is passed, in order: -the construction environment used to generate the target; the path -name of the target itself; and the path names of all the source files -necessary to build the target file. - -The code reference is expected to generate the target file, of course, -but may manipulate the source and target files in any way it chooses. -The code reference must return a false value (C<undef> or C<0>) if -the build of the file failed. Any true value indicates a successful -build of the target. - -Building target files using code references is considered EXPERIMENTAL -due to the following current limitations: - -=over 4 - -Cons does I<not> print anything to indicate the code reference is being -called to build the file. The only way to give the user any indication -is to have the code reference explicitly print some sort of "building" -message, as in the above examples. - -Cons does not generate any signatures for code references, so if the -code in the reference changes, the target will I<not> be rebuilt. - -Cons has no public method to allow a code reference to extract -construction variables. This would be good to allow generalization of -code references based on the current construction environment, but would -also complicate the problem of generating meaningful signatures for code -references. - -=back - -Support for building targets via code references has been released in -this version to encourage experimentation and the seeking of possible -solutions to the above limitations. - ---> - - <para> - - &SCons; supports several types of &build_actions; - that can be performed to build one or more target files. - Usually, a &build_action; is a command-line string - that invokes an external command. - A build action can also be an external command - specified as a list of arguments, - or even a Python function. - - </para> - - <para> - - Build action objects are created by the &Action; function. - This function is, in fact, what &SCons; uses - to interpret the &action; - keyword argument when you call the &Builder; function. - So the following line that creates a simple Builder: - - </para> - - <sconstruct> - b = Builder(action = 'build < $SOURCE > $TARGET') - </sconstruct> - - <para> - - Is equivalent to: - - </para> - - <sconstruct> - b = Builder(action = Action('build < $SOURCE > $TARGET')) - </sconstruct> - - <para> - - The advantage of using the &Action; function directly - is that it can take a number of additional options - to modify the action's behavior in many useful ways. - - </para> - - <section> - <title>Command Strings as Actions</title> - - <section> - <title>Suppressing Command-Line Printing</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Ignoring Exit Status</title> - - <para> - - XXX - - </para> - - </section> - - </section> - - <section> - <title>Argument Lists as Actions</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Python Functions as Actions</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Modifying How an Action is Printed</title> - - <section> - <title>XXX: the &strfunction; keyword argument</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>XXX: the &cmdstr; keyword argument</title> - - <para> - - XXX - - </para> - - </section> - - </section> - - <section> - <title>Making an Action Depend on Variable Contents: the &varlist; keyword argument</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>chdir=1</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Batch Building of Multiple Targets from Separate Sources: the &batch_key; keyword argument</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Manipulating the Exit Status of an Action: the &exitstatfunc; keyword argument</title> - - <para> - - XXX - - </para> - - </section> - - <!-- - - ??? - - <section> - <title>presub=</title> - - <para> - - XXX - - </para> - - </section> - - --> diff --git a/doc/user/actions.xml b/doc/user/actions.xml index ea76eb9..d2a3dad 100644 --- a/doc/user/actions.xml +++ b/doc/user/actions.xml @@ -244,9 +244,9 @@ solutions to the above limitations. </para> - <programlisting> + <sconstruct> b = Builder(action = 'build < $SOURCE > $TARGET') - </programlisting> + </sconstruct> <para> @@ -254,9 +254,9 @@ solutions to the above limitations. </para> - <programlisting> + <sconstruct> b = Builder(action = Action('build < $SOURCE > $TARGET')) - </programlisting> + </sconstruct> <para> diff --git a/doc/user/add-method.in b/doc/user/add-method.in deleted file mode 100644 index 2deb07a..0000000 --- a/doc/user/add-method.in +++ /dev/null @@ -1,127 +0,0 @@ -<!-- - - __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> - - The &AddMethod; function is used to add a method - to an environment. It's typically used to add a "pseudo-builder," - a function that looks like a &Builder; but - wraps up calls to multiple other &Builder;s - or otherwise processes its arguments - before calling one or more &Builder;s. - In the following example, - we want to install the program into the standard - <filename>/usr/bin</filename> directory hierarchy, - but also copy it into a local <filename>install/bin</filename> - directory from which a package might be built: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - def install_in_bin_dirs(env, source): - """Install source in both bin dirs""" - i1 = env.Install("$BIN", source) - i2 = env.Install("$LOCALBIN", source) - return [i1[0], i2[0]] # Return a list, like a normal builder - env = Environment(BIN='__ROOT__/usr/bin', LOCALBIN='#install/bin') - env.AddMethod(install_in_bin_dirs, "InstallInBinDirs") - env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - This produces the following: - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q /</scons_output_command> - </scons_output> - - <para> - - As mentioned, a pseudo-builder also provides more flexibility - in parsing arguments than you can get with a &Builder;. - The next example shows a pseudo-builder with a - named argument that modifies the filename, and a separate argument - for the resource file (rather than having the builder figure it out - by file extension). This example also demonstrates using the global - &AddMethod; function to add a method to the global Environment class, - so it will be used in all subsequently created environments. - - </para> - - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - def BuildTestProg(env, testfile, resourcefile, testdir="tests"): - """Build the test program; - prepends "test_" to src and target, - and puts target into testdir.""" - srcfile = "test_%s.c" % testfile - target = "%s/test_%s" % (testdir, testfile) - if env['PLATFORM'] == 'win32': - resfile = env.RES(resourcefile) - p = env.Program(target, [srcfile, resfile]) - else: - p = env.Program(target, srcfile) - return p - AddMethod(Environment, BuildTestProg) - - env = Environment() - env.BuildTestProg('stuff', resourcefile='res.rc') - </file> - <file name="test_stuff.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="res.rc"> - res.rc - </file> - </scons_example> - - <para> - This produces the following on Linux: - </para> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - And the following on Windows: - </para> - - <scons_output example="ex2" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - Using &AddMethod; is better than just adding an instance method - to a &consenv; because it gets called as a proper method, - and because &AddMethod; provides for copying the method - to any clones of the &consenv; instance. - </para> diff --git a/doc/user/add-method.xml b/doc/user/add-method.xml index 3aac7a8..2deb07a 100644 --- a/doc/user/add-method.xml +++ b/doc/user/add-method.xml @@ -39,28 +39,29 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> def install_in_bin_dirs(env, source): """Install source in both bin dirs""" i1 = env.Install("$BIN", source) i2 = env.Install("$LOCALBIN", source) return [i1[0], i2[0]] # Return a list, like a normal builder - env = Environment(BIN='/usr/bin', LOCALBIN='#install/bin') + env = Environment(BIN='__ROOT__/usr/bin', LOCALBIN='#install/bin') env.AddMethod(install_in_bin_dirs, "InstallInBinDirs") env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> This produces the following: </para> - <screen> - % <userinput>scons -Q /</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - Install file: "hello" as "/usr/bin/hello" - Install file: "hello" as "install/bin/hello" - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q /</scons_output_command> + </scons_output> <para> @@ -75,7 +76,8 @@ </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> def BuildTestProg(env, testfile, resourcefile, testdir="tests"): """Build the test program; prepends "test_" to src and target, @@ -92,29 +94,30 @@ env = Environment() env.BuildTestProg('stuff', resourcefile='res.rc') - </programlisting> + </file> + <file name="test_stuff.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="res.rc"> + res.rc + </file> + </scons_example> <para> This produces the following on Linux: </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o test_stuff.o -c test_stuff.c - cc -o tests/test_stuff test_stuff.o - </screen> + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> And the following on Windows: </para> - <screen> - C:\><userinput>scons -Q</userinput> - rc /fores.res res.rc - cl /Fotest_stuff.obj /c test_stuff.c /nologo - link /nologo /OUT:tests\test_stuff.exe test_stuff.obj res.res - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="ex2" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> Using &AddMethod; is better than just adding an instance method diff --git a/doc/user/alias.in b/doc/user/alias.in deleted file mode 100644 index 686c004..0000000 --- a/doc/user/alias.in +++ /dev/null @@ -1,102 +0,0 @@ -<!-- - - __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> - - We've already seen how you can use the &Alias; - function to create a target named <literal>install</literal>: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - env = Environment() - hello = env.Program('hello.c') - env.Install('__ROOT__/usr/bin', hello) - env.Alias('install', '__ROOT__/usr/bin') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - You can then use this alias on the command line - to tell &SCons; more naturally that you want to install files: - - </para> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons -Q install</scons_output_command> - </scons_output> - - <para> - - Like other &Builder; methods, though, - the &Alias; method returns an object - representing the alias being built. - You can then use this object as input to anothother &Builder;. - This is especially useful if you use such an object - as input to another call to the &Alias; &Builder;, - allowing you to create a hierarchy - of nested aliases: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - env = Environment() - p = env.Program('foo.c') - l = env.Library('bar.c') - env.Install('__ROOT__/usr/bin', p) - env.Install('__ROOT__/usr/lib', l) - ib = env.Alias('install-bin', '__ROOT__/usr/bin') - il = env.Alias('install-lib', '__ROOT__/usr/lib') - env.Alias('install', [ib, il]) - </file> - <file name="foo.c"> - int main() { printf("foo.c\n"); } - </file> - <file name="bar.c"> - void bar() { printf("bar.c\n"); } - </file> - </scons_example> - - <para> - - This example defines separate <literal>install</literal>, - <literal>install-bin</literal>, - and <literal>install-lib</literal> aliases, - allowing you finer control over what gets installed: - - </para> - - <scons_output example="ex2" os="posix"> - <scons_output_command>scons -Q install-bin</scons_output_command> - <scons_output_command>scons -Q install-lib</scons_output_command> - <scons_output_command>scons -Q -c __ROOT__/</scons_output_command> - <scons_output_command>scons -Q install</scons_output_command> - </scons_output> diff --git a/doc/user/alias.xml b/doc/user/alias.xml index f285d70..686c004 100644 --- a/doc/user/alias.xml +++ b/doc/user/alias.xml @@ -30,12 +30,17 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> env = Environment() hello = env.Program('hello.c') - env.Install('/usr/bin', hello) - env.Alias('install', '/usr/bin') - </programlisting> + env.Install('__ROOT__/usr/bin', hello) + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -44,12 +49,9 @@ </para> - <screen> - % <userinput>scons -Q install</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - Install file: "hello" as "/usr/bin/hello" - </screen> + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> <para> @@ -64,16 +66,24 @@ </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> env = Environment() p = env.Program('foo.c') l = env.Library('bar.c') - env.Install('/usr/bin', p) - env.Install('/usr/lib', l) - ib = env.Alias('install-bin', '/usr/bin') - il = env.Alias('install-lib', '/usr/lib') + env.Install('__ROOT__/usr/bin', p) + env.Install('__ROOT__/usr/lib', l) + ib = env.Alias('install-bin', '__ROOT__/usr/bin') + il = env.Alias('install-lib', '__ROOT__/usr/lib') env.Alias('install', [ib, il]) - </programlisting> + </file> + <file name="foo.c"> + int main() { printf("foo.c\n"); } + </file> + <file name="bar.c"> + void bar() { printf("bar.c\n"); } + </file> + </scons_example> <para> @@ -84,29 +94,9 @@ </para> - <screen> - % <userinput>scons -Q install-bin</userinput> - cc -o foo.o -c foo.c - cc -o foo foo.o - Install file: "foo" as "/usr/bin/foo" - % <userinput>scons -Q install-lib</userinput> - cc -o bar.o -c bar.c - ar rc libbar.a bar.o - ranlib libbar.a - Install file: "libbar.a" as "/usr/lib/libbar.a" - % <userinput>scons -Q -c /</userinput> - Removed foo.o - Removed foo - Removed /usr/bin/foo - Removed bar.o - Removed libbar.a - Removed /usr/lib/libbar.a - % <userinput>scons -Q install</userinput> - cc -o foo.o -c foo.c - cc -o foo foo.o - Install file: "foo" as "/usr/bin/foo" - cc -o bar.o -c bar.c - ar rc libbar.a bar.o - ranlib libbar.a - Install file: "libbar.a" as "/usr/lib/libbar.a" - </screen> + <scons_output example="ex2" os="posix"> + <scons_output_command>scons -Q install-bin</scons_output_command> + <scons_output_command>scons -Q install-lib</scons_output_command> + <scons_output_command>scons -Q -c __ROOT__/</scons_output_command> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> diff --git a/doc/user/ant.in b/doc/user/ant.in deleted file mode 100644 index 0df1027..0000000 --- a/doc/user/ant.in +++ /dev/null @@ -1,52 +0,0 @@ -<!-- - - __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> - - XXX - - </para> - - <section> - <title>Differences Between &Ant; and &SCons;</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Advantages of &SCons; Over &Ant;</title> - - <para> - - XXX - - </para> - - </section> diff --git a/doc/user/build-install.in b/doc/user/build-install.in deleted file mode 100644 index 821d2be..0000000 --- a/doc/user/build-install.in +++ /dev/null @@ -1,709 +0,0 @@ -<!-- - - __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> - - This chapter will take you through the basic steps - of installing &SCons; on your system, - and building &SCons; if you don't have a - pre-built package available - (or simply prefer the flexibility of building it yourself). - Before that, however, this chapter will also describe the basic steps - involved in installing Python on your system, - in case that is necessary. - Fortunately, both &SCons; and Python - are very easy to install on almost any system, - and Python already comes installed on many systems. - - </para> - - <!-- - - <para> - - Lastly, this chapter also contains a section that - provides a brief overview of the Python programming language, - which is the language used to implement &SCons;, - and which forms the basis of the &SCons; configuration files. - Becoming familiar with some Python concepts will make it easier - to understand many of the examples in this User's Guide. - Nevertheless, it <emphasis>is</emphasis> possible - to configure simple &SCons; builds without knowing Python, - so you can skip this section if you - want to dive in and pick up things - by example- -or, of course, if you are - already familiar with Python. - - </para> - - --> - - <section> - <title>Installing Python</title> - - <para> - - Because &SCons; is written in Python, - you must obviously have Python installed on your system - to use &SCons;. - Before you try to install Python, - you should check to see if Python is already - available on your system by typing - <userinput>python -V</userinput> - (capital 'V') - or - <userinput>python --version</userinput> - at your system's command-line prompt. - - </para> - - <screen> - $ <userinput>python -V</userinput> - Python 2.5.1 - </screen> - - <para> - - And on a Windows system with Python installed: - - </para> - - <screen> - C:\><userinput>python -V</userinput> - Python 2.5.1 - </screen> - - <para> - - If Python is not installed on your system, - you will see an error message - stating something like "command not found" - (on UNIX or Linux) - or "'python' is not recognized - as an internal or external command, operable progam or batch file" - (on Windows). - In that case, you need to install Python - before you can install &SCons;. - - </para> - - <para> - - The standard location for information - about downloading and installing Python is - <ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>. - See that page for information about - how to download and install Python on your system. - - </para> - - <para> - - &SCons; will work with any 2.x version of Python from 2.4 on; - 3.0 and later are not yet supported. - If you need to install Python and have a choice, - we recommend using the most recent 2.x Python version available. - Newer Pythons have significant improvements - that help speed up the performance of &SCons;. - - </para> - - </section> - - <section> - <title>Installing &SCons; From Pre-Built Packages</title> - - <para> - - &SCons; comes pre-packaged for installation on a number of systems, - including Linux and Windows systems. - You do not need to read this entire section, - you should need to read only the section - appropriate to the type of system you're running on. - - </para> - - <section> - <title>Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems</title> - - <para> - - &SCons; comes in RPM (Red Hat Package Manager) format, - pre-built and ready to install on Red Hat Linux, - Fedora, - or any other Linux distribution that uses RPM. - Your distribution may - already have an &SCons; RPM built specifically for it; - many do, including SUSE, Mandrake and Fedora. - You can check for the availability of an &SCons; RPM - on your distribution's download servers, - or by consulting an RPM search site like - <ulink url="http://www.rpmfind.net/">http://www.rpmfind.net/</ulink> or - <ulink url="http://rpm.pbone.net/">http://rpm.pbone.net/</ulink>. - - </para> - - <para> - - If your distribution supports installation via - <application>yum</application>, - you should be able to install &SCons; by running: - - </para> - - <screen> - # <userinput>yum install scons</userinput> - </screen> - - <para> - - If your Linux distribution does not already have - a specific &SCons; RPM file, - you can download and install from the - generic RPM provided by the &SCons; project. - This will install the - SCons script(s) in <filename>/usr/bin</filename>, - and the SCons library modules in - <filename>/usr/lib/scons</filename>. - - </para> - - <para> - - To install from the command line, simply download the - appropriate <filename>.rpm</filename> file, - and then run: - - </para> - - <screen> - # <userinput>rpm -Uvh scons-__VERSION__-1.noarch.rpm</userinput> - </screen> - - <para> - - Or, you can use a graphical RPM package manager. - See your package manager application's documention - for specific instructions about - how to use it to install a downloaded RPM. - - </para> - - </section> - - <section> - <title>Installing &SCons; on Debian Linux Systems</title> - - <para> - - Debian Linux systems use a different package management - format that also makes it very easy to install &SCons;. - - </para> - - <para> - - If your system is connected to the Internet, - you can install the latest official Debian package - by running: - - </para> - - <screen> - # <userinput>apt-get install scons</userinput> - </screen> - - <!-- - - <para> - - Alternatively, - you can download the Debian package built - by the &SCons; project - and install it manually by running: - - </para> - - <screen> - # <userinput>db-XXX scons-*.deb</userinput> - </screen> - - --> - - </section> - - <section> - <title>Installing &SCons; on Windows Systems</title> - - <para> - - &SCons; provides a Windows installer - that makes installation extremely easy. - Download the <filename>scons-__VERSION__.win32.exe</filename> - file from the &SCons; download page at - <ulink url="http://www.scons.org/download.php">http://www.scons.org/download.php</ulink>. - Then all you need to do is execute the file - (usually by clicking on its icon in Windows Explorer). - These will take you through a small - sequence of windows that will install - &SCons; on your system. - - <!-- - Things are a little more complicated - if you are using the Cygwin version of Python. - This is because Cygwin - tries to make a Windows system look more - POSIX-like (or UNIX-like or Linux-like, if you prefer) - by having the Cygwin utilities, - including Cygwin Python, - interpret file name arguments on the command line - using the forward-slash (<filename>/</filename>) - as the directory separator, - instead of the normal Windows behavior of the - backslash (<filename>\</filename>) as the directory separator. - --> - - </para> - - <!-- - - <section> - <title>Installing &SCons; on Windows Systems Without Cygwin Python</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Installing &SCons; on Windows Systems With Cygwin Python</title> - - <para> - - XXX - - </para> - - </section> - - --> - - <!-- - - XXX - don't have the kinks worked out on how to - get these to display properly in all formats, - so comment them out for now. - - <screenshot> - <mediaobject> - <imageobject> - <imagedata fileref="SCons-win32-install-1.jpg" format="jpg" align="center"> - </imageobject> - </mediaobject> - </screenshot> - - <screenshot> - <mediaobject> - <imageobject> - <imagedata fileref="SCons-win32-install-2.jpg" format="jpg" align="center"> - </imageobject> - </mediaobject> - </screenshot> - - <screenshot> - <mediaobject> - <imageobject> - <imagedata fileref="SCons-win32-install-3.jpg" format="jpg" align="center"> - </imageobject> - </mediaobject> - </screenshot> - - <screenshot> - <mediaobject> - <imageobject> - <imagedata fileref="SCons-win32-install-4.jpg" format="jpg" align="center"> - </imageobject> - </mediaobject> - </screenshot> - - --> - - </section> - - </section> - - <section> - <title>Building and Installing &SCons; on Any System</title> - - <para> - - If a pre-built &SCons; package is not available for your system, - then you can still easily build and install &SCons; using the native - Python <filename>distutils</filename> package. - - </para> - - <para> - - The first step is to download either the - <filename>scons-__VERSION__.tar.gz</filename> - or <filename>scons-__VERSION__.zip</filename>, - which are available from the SCons download page at - <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>. - - </para> - - <para> - - Unpack the archive you downloaded, - using a utility like <application>tar</application> - on Linux or UNIX, - or <application>WinZip</application> on Windows. - This will create a directory called - <filename>scons-__VERSION__</filename>, - usually in your local directory. - Then change your working directory to that directory - and install &SCons; by executing the following commands: - - </para> - - <screen> - # <userinput>cd scons-__VERSION__</userinput> - # <userinput>python setup.py install</userinput> - </screen> - - <para> - - This will build &SCons;, - install the &scons; script - in the python which is used to run the setup.py's scripts directory - (<filename>/usr/local/bin</filename> or - <filename>C:\Python25\Scripts</filename>), - and will install the &SCons; build engine - in the corresponding library directory for the python used - (<filename>/usr/local/lib/scons</filename> or - <filename>C:\Python25\scons</filename>). - Because these are system directories, - you may need root (on Linux or UNIX) or Administrator (on Windows) - privileges to install &SCons; like this. - - </para> - - <!-- - - <section> - <title>Building and Installing &SCons; in the Standard Python Library Directories</title> - - <para> - - XXX - - </para> - - </section> - - --> - - <section> - <title>Building and Installing Multiple Versions of &SCons; Side-by-Side</title> - - <para> - - The &SCons; <filename>setup.py</filename> script - has some extensions that support - easy installation of multiple versions of &SCons; - in side-by-side locations. - This makes it easier to download and - experiment with different versions of &SCons; - before moving your official build process to a new version, - for example. - - </para> - - <para> - - To install &SCons; in a version-specific location, - add the <option>--version-lib</option> option - when you call <filename>setup.py</filename>: - - </para> - - <screen> - # <userinput>python setup.py install --version-lib</userinput> - </screen> - - <para> - - This will install the &SCons; build engine - in the - <filename>/usr/lib/scons-__VERSION__</filename> - or - <filename>C:\Python25\scons-__VERSION__</filename> - directory, for example. - - </para> - - <para> - - If you use the <option>--version-lib</option> option - the first time you install &SCons;, - you do not need to specify it each time you install - a new version. - The &SCons; <filename>setup.py</filename> script - will detect the version-specific directory name(s) - and assume you want to install all versions - in version-specific directories. - You can override that assumption in the future - by explicitly specifying the <option>--standalone-lib</option> option. - - </para> - - </section> - - <section> - <title>Installing &SCons; in Other Locations</title> - - <para> - - You can install &SCons; in locations other than - the default by specifying the <option>--prefix=</option> option: - - </para> - - <screen> - # <userinput>python setup.py install --prefix=/opt/scons</userinput> - </screen> - - <para> - - This would - install the <application>scons</application> script in - <filename>/opt/scons/bin</filename> - and the build engine in - <filename>/opt/scons/lib/scons</filename>, - - </para> - - <para> - - Note that you can specify both the <option>--prefix=</option> - and the <option>--version-lib</option> options - at the same type, - in which case <filename>setup.py</filename> - will install the build engine - in a version-specific directory - relative to the specified prefix. - Adding <option>--version-lib</option> to the - above example would install the build engine in - <filename>/opt/scons/lib/scons-__VERSION__</filename>. - - </para> - - </section> - - <section> - <title>Building and Installing &SCons; Without Administrative Privileges</title> - - <para> - - If you don't have the right privileges to install &SCons; - in a system location, - simply use the <literal>--prefix=</literal> option - to install it in a location of your choosing. - For example, - to install &SCons; in appropriate locations - relative to the user's <literal>$HOME</literal> directory, - the &scons; script in - <filename>$HOME/bin</filename> - and the build engine in - <filename>$HOME/lib/scons</filename>, - simply type: - - </para> - - <screen> - $ <userinput>python setup.py install --prefix=$HOME</userinput> - </screen> - - <para> - - You may, of course, specify any other location you prefer, - and may use the <option>--version-lib</option> option - if you would like to install version-specific directories - relative to the specified prefix. - - </para> - - <para> - - This can also be used to experiment with a newer - version of &SCons; than the one installed - in your system locations. - Of course, the location in which you install the - newer version of the &scons; script - (<filename>$HOME/bin</filename> in the above example) - must be configured in your &PATH; variable - before the directory containing - the system-installed version - of the &scons; script. - - </para> - - </section> - - </section> - - <!-- - - <section> - <title>Python Basics</title> - - <para> - - This section will provide a brief overview of - the Python programming language. - Skip this section if you are already familiar with Python - (or you're really intent on diving into &SCons; - and just picking up things as you go). - - </para> - - <para> - - Python has a lot of good - documentation freely available on-line - to help you get started. - The standard tutorial is available at XXX. - - - </para> - - <para> - - Python is very easy to pick up. - - </para> - - <para> - - Python variables must be assigned to before they can be referenced. - - </para> - - <para> - - Assignment is like most programming languages: - - x = 1 + 2 - z = 3 * x - - </para> - - <para> - - Function calls look like most language function calls: - - a = f(g) - - </para> - - <para> - - Define functions like so: - - def func(arg1, arg2): - return arg1 * arg 2 - - The number of parameters - - </para> - - <para> - - Strings can be enclosed in single quotes or double quotes, - backslashes are used to escape characters, - triple-quote syntax lets you include quotes and newlines, - raw strings begin with 'r'. - - </para> - - <para> - - Lists are enclosed in square brackets, - list items are separated by commas. - List references use square brackets and integer index values, - slice notation lets you select, delete or replace a range. - - </para> - - <para> - - Dictionaries (hashes) are enclosed in curly brackets, - : separates keys from values, - , separates items. - Dictionary values are referenced using square brackets. - - </para> - - <para> - - Access class attributes (including methods) using a '.'. - - </para> - - <para> - - if: statements look like - - elif: statements look like - - else: statements look like - - </para> - - <para> - - for: statements look like - - while: statements look like - - break statements look like - - continue statements look like - - </para> - - <para> - - pass - - </para> - - </section> - - --> diff --git a/doc/user/builders-built-in.in b/doc/user/builders-built-in.in deleted file mode 100644 index 3b5b981..0000000 --- a/doc/user/builders-built-in.in +++ /dev/null @@ -1,950 +0,0 @@ -<!-- - - __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> - - &SCons; provides the ability to build a lot of different - types of files right "out of the box." - So far, we've been using &SCons;' ability to build - programs, objects and libraries to - illustrate much of the underlying functionality of &SCons; - This section will describe all of the different - types of files that you can build with &SCons;, - and the built-in &Builder; objects used to build them. - By default, all of the &Builder; objects in this section - can be built either with or without an explicit - construction environment. - - </para> - - <section> - <title>Programs: the &Program; Builder</title> - - <para> - - As we've seen, the &b-link-Program; Builder - is used to build an executable program. - The &source; argument is one or more - source-code files or object files, - and the ⌖ argument is the - name of the executable program name to be created. - For example: - - </para> - - <programlisting> - Program('prog', 'file1.o') - </programlisting> - - <para> - - Will create the &prog; - executable on a POSIX system, - the &prog_exe; executable on a Windows system. - - </para> - - <para> - - The target file's prefix and suffix may be omitted, - and the values from the - &cv-link-PROGPREFIX; - and - &cv-link-PROGSUFFIX; - construction variables - will be appended appropriately. - For example: - - </para> - - <programlisting> - env = Environment(PROGPREFIX='my', PROGSUFFIX='.xxx') - env.Program('prog', ['file1.o', 'file2.o']) - </programlisting> - - <para> - - Will create a program named - <filename>myprog.xxx</filename> - regardless of the system on which it is run. - - </para> - - <para> - - If you omit the ⌖, - the base of the first input - file name specified - becomes the base of the target - program created. - For example: - - </para> - - <programlisting> - Program(['hello.c', 'goodbye.c']) - </programlisting> - - <para> - - Will create the &hello; - executable on a POSIX system, - the &hello_exe; executable on a Windows system. - - </para> - - <para> - - Two construction variables control what libraries - will be linked with the resulting program. - The &cv-link-LIBS; variable is a list of the names of - libraries that will be linked into any programs, - and the &cv-link-LIBPATH; variables is a list of - directories that will be searched for - the specified libraries. - &SCons; will construct the right command-line - options for the running system. - For example: - - </para> - - <scons_example name="libs"> - <file name="SConstruct" printme="1"> - env = Environment(LIBS = ['foo1', 'foo2'], - LIBPATH = ['/usr/dir1', 'dir2']) - env.Program(['hello.c', 'goodbye.c']) - </file> - <file name="hello.c"> - int hello() { printf("Hello, world!\n"); } - </file> - <file name="goodbye.c"> - int goodbye() { printf("Goodbye, world!\n"); } - </file> - </scons_example> - - <para> - - Will execute as follows on a POSIX system: - - </para> - - <scons_output example="libs" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - And execute as follows on a Windows system: - - </para> - - <scons_output example="libs" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - The &cv-LIBS; construction variable - is turned into command line options - by appending the &cv-link-LIBLINKPREFIX; and &cv-link-LIBLINKSUFFIX; - construction variables to the beginning and end, - respectively, of each specified library. - - </para> - - <para> - - The &cv-LIBPATH; construction variable - is turned into command line options - by appending the &cv-link-LIBDIRPREFIX; and &cv-link-LIBDIRSUFFIX; - construction variables to the beginning and end, - respectively, of each specified library. - - </para> - - <para> - - Other relevant construction variables - include those used by the &b-link-Object; - builders to affect how the - source files specified as input to the &t-Program; - builders are turned into object files; - see the next section. - - </para> - - <para> - - The command line used to control how a program is linked - is specified by the &cv-link-LINKCOM; construction variable. - By default, it uses the - &cv-link-LINK; construction variable - and the &cv-link-LINKFLAGS; construction variable. - - </para> - - </section> - - <section> - <title>Object-File Builders</title> - - <para> - - &SCons; provides separate Builder objects - to create static and shared object files. - The distinction becomes especially important when - archiving object files into different types of libraries. - - </para> - - <section> - <title>The &StaticObject; Builder</title> - - <para> - - The &b-link-StaticObject; Builder - is used to build an object file - suitable for static linking into a program, - or for inclusion in a static library. - The &source; argument is a single source-code file, - and the ⌖ argument is the - name of the static object file to be created. - For example: - - </para> - - <programlisting> - StaticObject('file', 'file.c') - </programlisting> - - <para> - - Will create the &file_o; - object file on a POSIX system, - the &file_obj; executable on a Windows system. - - </para> - - <para> - - The target file's prefix and suffix may be omitted, - and the values from the - &cv-link-OBJPREFIX; - and - &cv-link-OBJSUFFIX; - construction variables - will be appended appropriately. - For example: - - </para> - - <programlisting> - env = Environment(OBJPREFIX='my', OBJSUFFIX='.xxx') - env.StaticObject('file', 'file.c') - </programlisting> - - <para> - - Will create an object file named - <filename>myfile.xxx</filename> - regardless of the system on which it is run. - - </para> - - <para> - - If you omit the ⌖, - the base of the first input - file name specified - beomces the base of the name - of the static object file to be created. - For example: - - </para> - - <programlisting> - StaticObject('file.c') - </programlisting> - - <para> - - Will create the &file_o; - executable on a POSIX system, - the &file_obj; executable on a Windows system. - - </para> - - </section> - - <section> - <title>The &SharedObject; Builder</title> - - <para> - - The &b-link-SharedObject; Builder - is used to build an object file - suitable for shared linking into a program, - or for inclusion in a shared library. - The &source; argument is a single source-code file, - and the ⌖ argument is the - name of the shared object file to be created. - For example: - - </para> - - <programlisting> - SharedObject('file', 'file.c') - </programlisting> - - <para> - - Will create the &file_o; - object file on a POSIX system, - the &file_obj; executable on a Windows system. - - </para> - - <para> - - The target file's prefix and suffix may be omitted, - and the values from the - &cv-link-SHOBJPREFIX; - and - &cv-link-SHOBJSUFFIX; - construction variables - will be appended appropriately. - For example: - - </para> - - <programlisting> - env = Environment(SHOBJPREFIX='my', SHOBJSUFFIX='.xxx') - env.SharedObject('file', 'file.c') - </programlisting> - - <para> - - Will create an object file named - <filename>myfile.xxx</filename> - regardless of the system on which it is run. - - </para> - - <para> - - If you omit the ⌖, - the base of the first input - file name specified - becomes the base of the name - of the shared object file to be created. - For example: - - </para> - - <programlisting> - SharedObject('file.c') - </programlisting> - - <para> - - Will create the &file_o; - executable on a POSIX system, - the &file_obj; executable on a Windows system. - - </para> - - </section> - - <section> - <title>The &Object; Builder</title> - - <para> - - The &b-link-Object; Builder is a synonym for &b-link-StaticObject; - and is completely equivalent. - - </para> - - </section> - - </section> - - <section> - <title>Library Builders</title> - - <para> - - &SCons; provides separate Builder objects - to create static and shared libraries. - - </para> - - <section> - <title>The &StaticLibrary; Builder</title> - - <para> - - The &b-link-StaticLibrary; Builder - is used to create a library - suitable for static linking into a program. - The &source; argument is one or more - source-code files or object files, - and the ⌖ argument is the - name of the static library to be created. - For example: - - </para> - - <programlisting> - StaticLibrary('foo', ['file1.c', 'file2.c']) - </programlisting> - - <para> - - The target file's prefix and suffix may be omitted, - and the values from the - &cv-link-LIBPREFIX; - and - &cv-link-LIBSUFFIX; - construction variables - will be appended appropriately. - For example: - - </para> - - <programlisting> - env = Environment(LIBPREFIX='my', LIBSUFFIX='.xxx') - env.StaticLibrary('lib', ['file1.o', 'file2.o']) - </programlisting> - - <para> - - Will create an object file named - <filename>mylib.xxx</filename> - regardless of the system on which it is run. - - </para> - - <programlisting> - StaticLibrary('foo', ['file1.c', 'file2.c']) - </programlisting> - - <para> - - If you omit the ⌖, - the base of the first input - file name specified - becomes the base of the name of the static object file to be created. - For example: - - </para> - - <programlisting> - StaticLibrary(['file.c', 'another.c']) - </programlisting> - - <para> - - Will create the &libfile_a; - library on a POSIX system, - the &file_lib; library on a Windows system. - - </para> - - </section> - - <section> - <title>The &SharedLibrary; Builder</title> - - <para> - - The &b-link-SharedLibrary; Builder - is used to create a shared library - suitable for linking with a program. - The &source; argument is one or more - source-code files or object files, - and the ⌖ argument is the - name of the shared library to be created. - For example: - - </para> - - <programlisting> - SharedLibrary('foo', ['file1.c', 'file2.c']) - </programlisting> - - <para> - - The target file's prefix and suffix may be omitted, - and the values from the - &cv-link-SHLIBPREFIX; - and - &cv-link-SHLIBSUFFIX; - construction variables - will be appended appropriately. - For example: - - </para> - - <programlisting> - env = Environment(SHLIBPREFIX='my', SHLIBSUFFIX='.xxx') - env.SharedLibrary('shared', ['file1.o', 'file2.o']) - </programlisting> - - <para> - - Will create an object file named - <filename>myshared.xxx</filename> - regardless of the system on which it is run. - - </para> - - <programlisting> - SharedLibrary('foo', ['file1.c', 'file2.c']) - </programlisting> - - <para> - - If you omit the ⌖, - the base of the first input - file name specified - becomes the base of the name of the shared library to be created. - For example: - - </para> - - <programlisting> - SharedLibrary(['file.c', 'another.c']) - </programlisting> - - <para> - - Will create the &libfile_so; - library on a POSIX system, - the &file_dll; library on a Windows system. - - </para> - - </section> - - <section> - <title>The &Library; Builder</title> - - <para> - - The &b-link-Library; Builder is a synonym for &b-link-StaticLibrary; - and is completely equivalent. - - </para> - - </section> - - </section> - - <section> - <title>Pre-Compiled Headers: the &PCH; Builder</title> - - <para> - - XXX PCH() - - </para> - - </section> - - <section> - <title>Microsoft Visual C++ Resource Files: the &RES; Builder</title> - - <para> - - XXX RES() - - </para> - - </section> - - <section> - <title>Source Files</title> - - <para> - - By default - &SCons; supports two Builder objects - that know how to build source files - from other input files. - These are typically invoked "internally" - to turn files that need preprocessing into other source files. - - </para> - - <section> - <title>The &CFile; Builder</title> - - <para> - - XXX CFile() - - </para> - - <programlisting> - XXX CFile() programlisting - </programlisting> - - <screen> - XXX CFile() screen - </screen> - - </section> - - <section> - <title>The &CXXFile; Builder</title> - - <para> - - XXX CXXFILE() - - </para> - - <programlisting> - XXX CXXFILE() programlisting - </programlisting> - - <screen> - XXX CXXFILE() screen - </screen> - - </section> - - </section> - - <section> - <title>Documents</title> - - <para> - - &SCons; provides a number of Builder objects - for creating different types of documents. - - </para> - - <section> - <title>The &DVI; Builder</title> - - <para> - - XXX DVI() para - - </para> - - <programlisting> - XXX DVI() programlisting - </programlisting> - - <screen> - XXX DVI() screen - </screen> - - </section> - - <section> - <title>The &PDF; Builder</title> - - <para> - - XXX PDF() para - - </para> - - </section> - - <section> - <title>The &PostScript; Builder</title> - - <para> - - XXX PostScript() para - - </para> - - <programlisting> - XXX PostScript() programlisting - </programlisting> - - <screen> - XXX PostScript() screen - </screen> - - </section> - - </section> - - <section> - <title>Archives</title> - - <para> - - &SCons; provides Builder objects - for creating two different types of archive files. - - </para> - - <section> - <title>The &Tar; Builder</title> - - <para> - - The &b-link-Tar; Builder object uses the &tar; - utility to create archives of files - and/or directory trees: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Tar('out1.tar', ['file1', 'file2']) - env.Tar('out2', 'directory') - </file> - <file name="file1"> - file1 - </file> - <file name="file2"> - file2 - </file> - <file name="directory/file3"> - directory/file3 - </file> - </scons_example> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons -Q .</scons_output_command> - </scons_output> - - <para> - - One common requirement when creating a &tar; archive - is to create a compressed archive using the - <option>-z</option> option. - This is easily handled by specifying - the value of the &cv-link-TARFLAGS; variable - when you create the construction environment. - Note, however, that the <option>-c</option> used to - to instruct &tar; to create the archive - is part of the default value of &cv-TARFLAGS;, - so you need to set it both options: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - env = Environment(TARFLAGS = '-c -z') - env.Tar('out.tar.gz', 'directory') - </file> - <file name="directory/file"> - directory/file - </file> - </scons_example> - - <scons_output example="ex2" os="posix"> - <scons_output_command>scons -Q .</scons_output_command> - </scons_output> - - <para> - - you may also wish to set the value of the - &cv-link-TARSUFFIX; construction variable - to your desired suffix for compress &tar; archives, - so that &SCons; can append it to the target file name - without your having to specify it explicitly: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct" printme="1"> - env = Environment(TARFLAGS = '-c -z', - TARSUFFIX = '.tgz') - env.Tar('out', 'directory') - </file> - <file name="directory/file"> - directory/file - </file> - </scons_example> - - <scons_output example="ex3" os="posix"> - <scons_output_command>scons -Q .</scons_output_command> - </scons_output> - - </section> - - <section> - <title>The &Zip; Builder</title> - - <para> - - The &b-link-Zip; Builder object creates archives of files - and/or directory trees in the ZIP file format. - Python versions 1.6 or later - contain an internal &zipfile; module - that &SCons; will use. - In this case, given the following - &SConstruct; file: - - </para> - - <scons_example name="ex4"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Zip('out', ['file1', 'file2']) - </file> - <file name="file1"> - file1 - </file> - <file name="file2"> - file2 - </file> - </scons_example> - - <para> - - Your output will reflect the fact - that an internal Python function - is being used to create the output ZIP archive: - - </para> - - <scons_output example="ex4" os="posix"> - <scons_output_command>scons -Q .</scons_output_command> - </scons_output> - - </section> - - </section> - - <section> - <title>Java</title> - - <para> - - &SCons; provides Builder objects - for creating various types of Java output files. - - </para> - - <section> - <title>Building Class Files: the &Java; Builder</title> - - <para> - - The &b-link-Java; builder takes one or more input - <filename>.java</filename> files - and turns them into one or more - <filename>.class</filename> files - Unlike most builders, however, - the &Java; builder takes - target and source <emphasis>directories</emphasis>, - not files, as input. - - </para> - - <programlisting> - env = Environment() - env.Java(target = 'classes', source = 'src') - </programlisting> - - <para> - - The &Java; builder will then - search the specified source directory - tree for all <filename>.java</filename> files, - and pass any out-of-date - - </para> - - <screen> - XXX Java() screen - </screen> - - </section> - - <section> - <title>The &Jar; Builder</title> - - <para> - - XXX The &Jar; builder object - - </para> - - <programlisting> - env = Environment() - env.Java(target = 'classes', source = 'src') - env.Jar(target = '', source = 'classes') - </programlisting> - - <screen> - XXX Jar() screen - </screen> - - </section> - - <section> - <title>Building C header and stub files: the &JavaH; Builder</title> - - <para> - - XXX JavaH() para - - </para> - - <programlisting> - XXX JavaH() programlisting - </programlisting> - - <screen> - XXX JavaH() screen - </screen> - - </section> - - <section> - <title>Building RMI stub and skeleton class files: the &RMIC; Builder</title> - - <para> - - XXX RMIC() para - - </para> - - <programlisting> - XXX RMIC() programlisting - </programlisting> - - <screen> - XXX RMIC() screen - </screen> - - </section> - - </section> diff --git a/doc/user/builders-built-in.xml b/doc/user/builders-built-in.xml index 1356022..3b5b981 100644 --- a/doc/user/builders-built-in.xml +++ b/doc/user/builders-built-in.xml @@ -130,11 +130,19 @@ </para> - <programlisting> + <scons_example name="libs"> + <file name="SConstruct" printme="1"> env = Environment(LIBS = ['foo1', 'foo2'], LIBPATH = ['/usr/dir1', 'dir2']) env.Program(['hello.c', 'goodbye.c']) - </programlisting> + </file> + <file name="hello.c"> + int hello() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int goodbye() { printf("Goodbye, world!\n"); } + </file> + </scons_example> <para> @@ -142,12 +150,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o goodbye.o -c goodbye.c - cc -o hello.o -c hello.c - cc -o hello hello.o goodbye.o -L/usr/dir1 -Ldir2 -lfoo1 -lfoo2 - </screen> + <scons_output example="libs" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -155,13 +160,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - cl /Fogoodbye.obj /c goodbye.c /nologo - cl /Fohello.obj /c hello.c /nologo - link /nologo /OUT:hello.exe /LIBPATH:\usr\dir1 /LIBPATH:dir2 foo1.lib foo2.lib hello.obj goodbye.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="libs" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -720,17 +721,26 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> env = Environment() env.Tar('out1.tar', ['file1', 'file2']) env.Tar('out2', 'directory') - </programlisting> + </file> + <file name="file1"> + file1 + </file> + <file name="file2"> + file2 + </file> + <file name="directory/file3"> + directory/file3 + </file> + </scons_example> - <screen> - % <userinput>scons -Q .</userinput> - tar -c -f out1.tar file1 file2 - tar -c -f out2.tar directory - </screen> + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> <para> @@ -747,15 +757,19 @@ </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> env = Environment(TARFLAGS = '-c -z') env.Tar('out.tar.gz', 'directory') - </programlisting> + </file> + <file name="directory/file"> + directory/file + </file> + </scons_example> - <screen> - % <userinput>scons -Q .</userinput> - tar -c -z -f out.tar.gz directory - </screen> + <scons_output example="ex2" os="posix"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> <para> @@ -767,16 +781,20 @@ </para> - <programlisting> + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> env = Environment(TARFLAGS = '-c -z', TARSUFFIX = '.tgz') env.Tar('out', 'directory') - </programlisting> + </file> + <file name="directory/file"> + directory/file + </file> + </scons_example> - <screen> - % <userinput>scons -Q .</userinput> - tar -c -z -f out.tgz directory - </screen> + <scons_output example="ex3" os="posix"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> </section> @@ -795,10 +813,18 @@ </para> - <programlisting> + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> env = Environment() env.Zip('out', ['file1', 'file2']) - </programlisting> + </file> + <file name="file1"> + file1 + </file> + <file name="file2"> + file2 + </file> + </scons_example> <para> @@ -808,10 +834,9 @@ </para> - <screen> - % <userinput>scons -Q .</userinput> - zip(["out.zip"], ["file1", "file2"]) - </screen> + <scons_output example="ex4" os="posix"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> </section> diff --git a/doc/user/builders-commands.in b/doc/user/builders-commands.in deleted file mode 100644 index d0aae61..0000000 --- a/doc/user/builders-commands.in +++ /dev/null @@ -1,156 +0,0 @@ -<!-- - - __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. - ---> - - <!-- - - =head2 The C<Command> method - - - The C<Command> method is called as follows: - - Command $env <target>, <inputs>, <build action>; - - The target is made dependent upon the list of input files specified, and the - inputs must be built successfully or Cons will not attempt to build the - target. - - To specify a command with multiple targets, you can specify a reference to a - list of targets. In Perl, a list reference can be created by enclosing a - list in square brackets. Hence the following command: - - Command $env ['foo.h', 'foo.c'], 'foo.template', q( - gen %1 - ); - - could be used in a case where the command C<gen> creates two files, both - F<foo.h> and F<foo.c>. - - --> - - <para> - - Creating a &Builder; and attaching it to a &consenv; - allows for a lot of flexibility when you - want to re-use actions - to build multiple files of the same type. - This can, however, be cumbersome - if you only need to execute one specific command - to build a single file (or group of files). - For these situations, &SCons; supports a - &Command; &Builder; that arranges - for a specific action to be executed - to build a specific file or files. - This looks a lot like the other builders - (like &b-link-Program;, &b-link-Object;, etc.), - but takes as an additional argument - the command to be executed to build the file: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET") - </file> - <file name="foo.in"> - foo.in - </file> - </scons_example> - - <para> - - When executed, - &SCons; runs the specified command, - substituting &cv-link-SOURCE; and &cv-link-TARGET; - as expected: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - This is often more convenient than - creating a &Builder; object - and adding it to the &cv-link-BUILDERS; variable - of a &consenv; - - </para> - - <para> - - Note that the action you specify to the - &Command; &Builder; can be any legal &SCons; &Action;, - such as a Python function: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - env = Environment() - def build(target, source, env): - # Whatever it takes to build - return None - env.Command('foo.out', 'foo.in', build) - </file> - <file name="foo.in"> - foo.in - </file> - </scons_example> - - <para> - - Which executes as follows: - - </para> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note that &cv-link-SOURCE; and &cv-link-TARGET; are expanded - in the source and target as well as of SCons 1.1, - so you can write: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct" printme="1"> - env.Command('${SOURCE.basename}.out', 'foo.in', build) - </file> - </scons_example> - - - <para> - - which does the same thing as the previous example, but allows you - to avoid repeating yourself. - - </para> - diff --git a/doc/user/builders-commands.xml b/doc/user/builders-commands.xml index fcb2a96..d0aae61 100644 --- a/doc/user/builders-commands.xml +++ b/doc/user/builders-commands.xml @@ -69,10 +69,15 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> env = Environment() - env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET") - </programlisting> + env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET") + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> <para> @@ -83,10 +88,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - sed 's/x/y/' < foo.in > foo.out - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -105,13 +109,18 @@ </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> env = Environment() def build(target, source, env): # Whatever it takes to build return None env.Command('foo.out', 'foo.in', build) - </programlisting> + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> <para> @@ -119,10 +128,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - build(["foo.out"], ["foo.in"]) - </screen> + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -132,9 +140,11 @@ </para> - <programlisting> + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> env.Command('${SOURCE.basename}.out', 'foo.in', build) - </programlisting> + </file> + </scons_example> <para> diff --git a/doc/user/builders-writing.in b/doc/user/builders-writing.in deleted file mode 100644 index 749a8ba..0000000 --- a/doc/user/builders-writing.in +++ /dev/null @@ -1,1108 +0,0 @@ -<!-- - - __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. - ---> - -<!-- - -=head2 Adding new methods - -For slightly more demanding changes, you may wish to add new methods to the -C<cons> package. Here's an example of a very simple extension, -C<InstallScript>, which installs a tcl script in a requested location, but -edits the script first to reflect a platform-dependent path that needs to be -installed in the script: - - # cons::InstallScript - Create a platform dependent version of a shell - # script by replacing string ``#!your-path-here'' with platform specific - # path $BIN_DIR. - - sub cons::InstallScript { - my ($env, $dst, $src) = @_; - Command $env $dst, $src, qq( - sed s+your-path-here+$BIN_DIR+ %< > %> - chmod oug+x %> - ); - } - -Notice that this method is defined directly in the C<cons> package (by -prefixing the name with C<cons::>). A change made in this manner will be -globally visible to all environments, and could be called as in the -following example: - - InstallScript $env "$BIN/foo", "foo.tcl"; - -For a small improvement in generality, the C<BINDIR> variable could be -passed in as an argument or taken from the construction environment-,-as -C<%BINDIR>. - - -=head2 Overriding methods - -Instead of adding the method to the C<cons> name space, you could define a -new package which inherits existing methods from the C<cons> package and -overrides or adds others. This can be done using Perl's inheritance -mechanisms. - -The following example defines a new package C<cons::switch> which -overrides the standard C<Library> method. The overridden method builds -linked library modules, rather than library archives. A new -constructor is provided. Environments created with this constructor -will have the new library method; others won't. - - package cons::switch; - BEGIN {@ISA = 'cons'} - - sub new { - shift; - bless new cons(@_); - } - - sub Library { - my($env) = shift; - my($lib) = shift; - my(@objs) = Objects $env @_; - Command $env $lib, @objs, q( - %LD -r %LDFLAGS %< -o %> - ); - } - -This functionality could be invoked as in the following example: - - $env = new cons::switch(@overrides); - ... - Library $env 'lib.o', 'foo.c', 'bar.c'; - ---> - - <para> - - Although &SCons; provides many useful methods - for building common software products - (programs, libraries, documents, etc.), - you frequently want to be - able to build some other type of file - not supported directly by &SCons;. - Fortunately, &SCons; makes it very easy - to define your own &Builder; objects - for any custom file types you want to build. - (In fact, the &SCons; interfaces for creating - &Builder; objects are flexible enough and easy enough to use - that all of the the &SCons; built-in &Builder; objects - are created using the mechanisms described in this section.) - - </para> - - <section> - <title>Writing Builders That Execute External Commands</title> - - <para> - - The simplest &Builder; to create is - one that executes an external command. - For example, if we want to build - an output file by running the contents - of the input file through a command named - <literal>foobuild</literal>, - creating that &Builder; might look like: - - </para> - - <programlisting> - bld = Builder(action = 'foobuild < $SOURCE > $TARGET') - </programlisting> - - <para> - - All the above line does is create a free-standing - &Builder; object. - The next section will show us how to actually use it. - - </para> - - </section> - - <section> - <title>Attaching a Builder to a &ConsEnv;</title> - - <para> - - A &Builder; object isn't useful - until it's attached to a &consenv; - so that we can call it to arrange - for files to be built. - This is done through the &cv-link-BUILDERS; - &consvar; in an environment. - The &cv-BUILDERS; variable is a Python dictionary - that maps the names by which you want to call - various &Builder; objects to the objects themselves. - For example, if we want to call the - &Builder; we just defined by the name - <function>Foo</function>, - our &SConstruct; file might look like: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct"> - bld = Builder(action = 'foobuild < $SOURCE > $TARGET') - env = Environment(BUILDERS = {'Foo' : bld}) - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - env.Foo('file.foo', 'file.input') - </file> - <file name="file.input"> - file.input - </file> - <file name="foobuild" chmod="0755"> - cat - </file> - </scons_example> - - <sconstruct> - bld = Builder(action = 'foobuild < $SOURCE > $TARGET') - env = Environment(BUILDERS = {'Foo' : bld}) - </sconstruct> - - <para> - - With the &Builder; attached to our &consenv; - with the name <function>Foo</function>, - we can now actually call it like so: - - </para> - - <programlisting> - env.Foo('file.foo', 'file.input') - </programlisting> - - <para> - - Then when we run &SCons; it looks like: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note, however, that the default &cv-BUILDERS; - variable in a &consenv; - comes with a default set of &Builder; objects - already defined: - &b-link-Program;, &b-link-Library;, etc. - And when we explicitly set the &cv-BUILDERS; variable - when we create the &consenv;, - the default &Builder;s are no longer part of - the environment: - - </para> - - <!-- - The ToolSurrogate stuff that's used to capture output initializes - SCons.Defaults.ConstructionEnvironment with its own list of TOOLS. - In this next example, we want to show the user that when they - set the BUILDERS explicitly, the call to env.Program() generates - an AttributeError. This won't happen with all of the default - ToolSurrogates in the default construction environment. To make the - AttributeError show up, we have to overwite the default construction - environment's TOOLS variable so Program() builder doesn't show up. - - We do this by executing a slightly different SConstruct file than the - one we print in the guide, with two extra statements at the front - that overwrite the TOOLS variable as described. Note that we have - to jam those statements on to the first line to keep the line number - in the generated error consistent with what the user will see in the - User's Guide. - --> - <scons_example name="ex2"> - <file name="SConstruct"> - import SCons.Defaults; SCons.Defaults.ConstructionEnvironment['TOOLS'] = {}; bld = Builder(action = 'foobuild < $SOURCE > $TARGET') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file.foo', 'file.input') - env.Program('hello.c') - </file> - <file name="SConstruct.printme" printme="1"> - bld = Builder(action = 'foobuild < $SOURCE > $TARGET') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file.foo', 'file.input') - env.Program('hello.c') - </file> - <file name="file.input"> - file.input - </file> - <file name="hello.c"> - hello.c - </file> - </scons_example> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - To be able to use both our own defined &Builder; objects - and the default &Builder; objects in the same &consenv;, - you can either add to the &cv-BUILDERS; variable - using the &Append; function: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct"> - env = Environment() - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - bld = Builder(action = 'foobuild < $SOURCE > $TARGET') - env.Append(BUILDERS = {'Foo' : bld}) - env.Foo('file.foo', 'file.input') - env.Program('hello.c') - </file> - <file name="file.input"> - file.input - </file> - <file name="hello.c"> - hello.c - </file> - <file name="foobuild" chmod="0755"> - cat - </file> - </scons_example> - - <sconstruct> - env = Environment() - bld = Builder(action = 'foobuild < $SOURCE > $TARGET') - env.Append(BUILDERS = {'Foo' : bld}) - env.Foo('file.foo', 'file.input') - env.Program('hello.c') - </sconstruct> - - <para> - - Or you can explicitly set the appropriately-named - key in the &cv-BUILDERS; dictionary: - - </para> - - <sconstruct> - env = Environment() - bld = Builder(action = 'foobuild < $SOURCE > $TARGET') - env['BUILDERS']['Foo'] = bld - env.Foo('file.foo', 'file.input') - env.Program('hello.c') - </sconstruct> - - <para> - - Either way, the same &consenv; - can then use both the newly-defined - <function>Foo</function> &Builder; - and the default &b-link-Program; &Builder;: - - </para> - - <scons_output example="ex3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Letting &SCons; Handle The File Suffixes</title> - - <para> - - By supplying additional information - when you create a &Builder;, - you can let &SCons; add appropriate file - suffixes to the target and/or the source file. - For example, rather than having to specify - explicitly that you want the <literal>Foo</literal> - &Builder; to build the <literal>file.foo</literal> - target file from the <literal>file.input</literal> source file, - you can give the <literal>.foo</literal> - and <literal>.input</literal> suffixes to the &Builder;, - making for more compact and readable calls to - the <literal>Foo</literal> &Builder;: - - </para> - - <scons_example name="ex4"> - <file name="SConstruct"> - bld = Builder(action = 'foobuild < $SOURCE > $TARGET', - suffix = '.foo', - src_suffix = '.input') - env = Environment(BUILDERS = {'Foo' : bld}) - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - env.Foo('file1') - env.Foo('file2') - </file> - <file name="file1.input"> - file1.input - </file> - <file name="file2.input"> - file2.input - </file> - <file name="foobuild" chmod="0755"> - cat - </file> - </scons_example> - - <sconstruct> - bld = Builder(action = 'foobuild < $SOURCE > $TARGET', - suffix = '.foo', - src_suffix = '.input') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file1') - env.Foo('file2') - </sconstruct> - - <scons_output example="ex4"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - You can also supply a <literal>prefix</literal> keyword argument - if it's appropriate to have &SCons; append a prefix - to the beginning of target file names. - - </para> - - </section> - - <section> - <title>Builders That Execute Python Functions</title> - - <para> - - In &SCons;, you don't have to call an external command - to build a file. - You can, instead, define a Python function - that a &Builder; object can invoke - to build your target file (or files). - Such a &buildfunc; definition looks like: - - </para> - - <programlisting> - def build_function(target, source, env): - # Code to build "target" from "source" - return None - </programlisting> - - <para> - - The arguments of a &buildfunc; are: - - </para> - - <variablelist> - - <varlistentry> - <term>target</term> - - <listitem> - <para> - - A list of Node objects representing - the target or targets to be - built by this builder function. - The file names of these target(s) - may be extracted using the Python &str; function. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>source</term> - - <listitem> - <para> - - A list of Node objects representing - the sources to be - used by this builder function to build the targets. - The file names of these source(s) - may be extracted using the Python &str; function. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>env</term> - - <listitem> - <para> - - The &consenv; used for building the target(s). - The builder function may use any of the - environment's construction variables - in any way to affect how it builds the targets. - - </para> - </listitem> - </varlistentry> - - </variablelist> - - <para> - - The builder function must - return a <literal>0</literal> or <literal>None</literal> value - if the target(s) are built successfully. - The builder function - may raise an exception - or return any non-zero value - to indicate that the build is unsuccessful, - - </para> - - <para> - - Once you've defined the Python function - that will build your target file, - defining a &Builder; object for it is as - simple as specifying the name of the function, - instead of an external command, - as the &Builder;'s - <literal>action</literal> - argument: - - </para> - - <scons_example name="ex5"> - <file name="SConstruct" printme="1"> - def build_function(target, source, env): - # Code to build "target" from "source" - return None - bld = Builder(action = build_function, - suffix = '.foo', - src_suffix = '.input') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file') - </file> - <file name="file.input"> - file.input - </file> - </scons_example> - - <para> - - And notice that the output changes slightly, - reflecting the fact that a Python function, - not an external command, - is now called to build the target file: - - </para> - - <scons_output example="ex5"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Builders That Create Actions Using a &Generator;</title> - - <para> - - &SCons; Builder objects can create an action "on the fly" - by using a function called a &generator;. - This provides a great deal of flexibility to - construct just the right list of commands - to build your target. - A &generator; looks like: - - </para> - - <programlisting> - def generate_actions(source, target, env, for_signature): - return 'foobuild < %s > %s' % (target[0], source[0]) - </programlisting> - - <para> - - The arguments of a &generator; are: - - </para> - - <variablelist> - - <varlistentry> - <term>source</term> - - <listitem> - <para> - - A list of Node objects representing - the sources to be built - by the command or other action - generated by this function. - The file names of these source(s) - may be extracted using the Python &str; function. - - </para> - </listitem> - - </varlistentry> - - <varlistentry> - <term>target</term> - - <listitem> - <para> - - A list of Node objects representing - the target or targets to be built - by the command or other action - generated by this function. - The file names of these target(s) - may be extracted using the Python &str; function. - - </para> - </listitem> - - </varlistentry> - - <varlistentry> - <term>env</term> - - <listitem> - <para> - - The &consenv; used for building the target(s). - The generator may use any of the - environment's construction variables - in any way to determine what command - or other action to return. - - </para> - </listitem> - - </varlistentry> - - <varlistentry> - <term>for_signature</term> - - <listitem> - <para> - - A flag that specifies whether the - generator is being called to contribute to a build signature, - as opposed to actually executing the command. - - <!-- XXX NEED MORE HERE, describe generators use in signatures --> - - </para> - </listitem> - - </varlistentry> - - </variablelist> - - <para> - - The &generator; must return a - command string or other action that will be used to - build the specified target(s) from the specified source(s). - - </para> - - <para> - - Once you've defined a &generator;, - you create a &Builder; to use it - by specifying the generator keyword argument - instead of <literal>action</literal>. - - </para> - - <scons_example name="ex6"> - <file name="SConstruct"> - def generate_actions(source, target, env, for_signature): - return 'foobuild < %s > %s' % (source[0], target[0]) - bld = Builder(generator = generate_actions, - suffix = '.foo', - src_suffix = '.input') - env = Environment(BUILDERS = {'Foo' : bld}) - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - env.Foo('file') - </file> - <file name="file.input"> - file.input - </file> - <file name="foobuild" chmod="0755"> - cat - </file> - </scons_example> - - <sconstruct> - def generate_actions(source, target, env, for_signature): - return 'foobuild < %s > %s' % (source[0], target[0]) - bld = Builder(generator = generate_actions, - suffix = '.foo', - src_suffix = '.input') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file') - </sconstruct> - - <scons_output example="ex6"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note that it's illegal to specify both an - <literal>action</literal> - and a - <literal>generator</literal> - for a &Builder;. - - </para> - - </section> - - <section> - <title>Builders That Modify the Target or Source Lists Using an &Emitter;</title> - - <para> - - &SCons; supports the ability for a Builder to modify the - lists of target(s) from the specified source(s). - You do this by defining an &emitter; function - that takes as its arguments - the list of the targets passed to the builder, - the list of the sources passed to the builder, - and the construction environment. - The emitter function should return the modified - lists of targets that should be built - and sources from which the targets will be built. - - </para> - - <para> - - For example, suppose you want to define a Builder - that always calls a <filename>foobuild</filename> program, - and you want to automatically add - a new target file named - <filename>new_target</filename> - and a new source file named - <filename>new_source</filename> - whenever it's called. - The &SConstruct; file might look like this: - - </para> - - <scons_example name="ex7"> - <file name="SConstruct"> - def modify_targets(target, source, env): - target.append('new_target') - source.append('new_source') - return target, source - bld = Builder(action = 'foobuild $TARGETS - $SOURCES', - suffix = '.foo', - src_suffix = '.input', - emitter = modify_targets) - env = Environment(BUILDERS = {'Foo' : bld}) - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - env.Foo('file') - </file> - <file name="file.input"> - file.input - </file> - <file name="new_source"> - new_source - </file> - <file name="foobuild" chmod="0755"> - cat - </file> - </scons_example> - - <sconstruct> - def modify_targets(target, source, env): - target.append('new_target') - source.append('new_source') - return target, source - bld = Builder(action = 'foobuild $TARGETS - $SOURCES', - suffix = '.foo', - src_suffix = '.input', - emitter = modify_targets) - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file') - </sconstruct> - - <para> - - And would yield the following output: - - </para> - - <scons_output example="ex7"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - One very flexible thing that you can do is - use a construction variable to specify - different emitter functions for different - construction variable. - To do this, specify a string - containing a construction variable - expansion as the emitter when you call - the &Builder; function, - and set that construction variable to - the desired emitter function - in different construction environments: - - </para> - - <scons_example name="MY_EMITTER"> - - <file name="SConstruct" printme="1"> - bld = Builder(action = 'my_command $SOURCES > $TARGET', - suffix = '.foo', - src_suffix = '.input', - emitter = '$MY_EMITTER') - def modify1(target, source, env): - return target, source + ['modify1.in'] - def modify2(target, source, env): - return target, source + ['modify2.in'] - env1 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify1) - env2 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify2) - env1.Foo('file1') - env2.Foo('file2') - import os - env1['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() - env2['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() - </file> - <file name="file1.input"> - file1.input - </file> - <file name="file2.input"> - file2.input - </file> - <file name="modify1.in"> - modify1.input - </file> - <file name="modify2.in"> - modify2.input - </file> - <file name="my_command" chmod="0755"> - cat - </file> - - </scons_example> - - <sconstruct> - bld = Builder(action = 'my_command $SOURCES > $TARGET', - suffix = '.foo', - src_suffix = '.input', - emitter = '$MY_EMITTER') - def modify1(target, source, env): - return target, source + ['modify1.in'] - def modify2(target, source, env): - return target, source + ['modify2.in'] - env1 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify1) - env2 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify2) - env1.Foo('file1') - env2.Foo('file2') - </sconstruct> - - <para> - - In this example, the <filename>modify1.in</filename> - and <filename>modify2.in</filename> files - get added to the source lists - of the different commands: - - </para> - - <scons_output example="MY_EMITTER"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <!-- - - <section> - <title>target_factor=, source_factory=</title> - - </section> - - <section> - <title>target_scanner=, source_scanner=</title> - - </section> - - <section> - <title>multi=</title> - - </section> - - <section> - <title>single_source=</title> - - </section> - - <section> - <title>src_builder=</title> - - </section> - - <section> - <title>ensure_suffix=</title> - - </section> - - --> - - <section> - <title>Where To Put Your Custom Builders and Tools</title> - - <para> - - The <filename>site_scons</filename> directories give you a place to - put Python modules and packages that you can import into your &SConscript; files - (<filename>site_scons</filename>), - add-on tools that can integrate into &SCons; - (<filename>site_scons/site_tools</filename>), - and a <filename>site_scons/site_init.py</filename> file that - gets read before any &SConstruct; or &SConscript; file, - allowing you to change &SCons;'s default behavior. - - </para> - - <para> - - Each system type (Windows, Mac, Linux, etc.) searches a canonical - set of directories for site_scons; see the man page for details. - The top-level SConstruct's site_scons dir is always searched last, - and its dir is placed first in the tool path so it overrides all - others. - - </para> - - <para> - - If you get a tool from somewhere (the &SCons; wiki or a third party, - for instance) and you'd like to use it in your project, a - <filename>site_scons</filename> dir is the simplest place to put it. - Tools come in two flavors; either a Python function that operates on - an &Environment; or a Python module or package containing two functions, - <function>exists()</function> and <function>generate()</function>. - - </para> - - <para> - - A single-function Tool can just be included in your - <filename>site_scons/site_init.py</filename> file where it will be - parsed and made available for use. For instance, you could have a - <filename>site_scons/site_init.py</filename> file like this: - - </para> - - <scons_example name="site1"> - <file name="site_scons/site_init.py" printme="1"> - def TOOL_ADD_HEADER(env): - """A Tool to add a header from $HEADER to the source file""" - add_header = Builder(action=['echo "$HEADER" > $TARGET', - 'cat $SOURCE >> $TARGET']) - env.Append(BUILDERS = {'AddHeader' : add_header}) - env['HEADER'] = '' # set default value - </file> - <file name="SConstruct"> - env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====") - env.AddHeader('tgt', 'src') - </file> - <file name="src"> - hi there - </file> - </scons_example> - - <para> - - and a &SConstruct; like this: - - </para> - - <sconstruct> - # Use TOOL_ADD_HEADER from site_scons/site_init.py - env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====") - env.AddHeader('tgt', 'src') - </sconstruct> - - <para> - - The <function>TOOL_ADD_HEADER</function> tool method will be - called to add the <function>AddHeader</function> tool to the - environment. - - </para> - - <!-- - <scons_output example="site1" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - --> - - <para> - A more full-fledged tool with - <function>exists()</function> and <function>generate()</function> - methods can be installed either as a module in the file - <filename>site_scons/site_tools/toolname.py</filename> or as a - package in the - directory <filename>site_scons/site_tools/toolname</filename>. In - the case of using a package, the <function>exists()</function> - and <function>generate()</function> are in the - file <filename>site_scons/site_tools/toolname/__init__.py</filename>. - (In all the above case <filename>toolname</filename> is replaced - by the name of the tool.) - Since <filename>site_scons/site_tools</filename> is automatically - added to the head of the tool search path, any tool found there - will be available to all environments. Furthermore, a tool found - there will override a built-in tool of the same name, so if you - need to change the behavior of a built-in - tool, <filename>site_scons</filename> gives you the hook you need. - </para> - - <para> - Many people have a library of utility Python functions they'd like - to include in &SConscript;s; just put that module in - <filename>site_scons/my_utils.py</filename> or any valid Python module name of your - choice. For instance you can do something like this in - <filename>site_scons/my_utils.py</filename> to add - <function>build_id</function> and <function>MakeWorkDir</function> - functions: - </para> - - <scons_example name="site2"> - <file name="site_scons/my_utils.py" printme="1"> - from SCons.Script import * # for Execute and Mkdir - def build_id(): - """Return a build ID (stub version)""" - return "100" - def MakeWorkDir(workdir): - """Create the specified dir immediately""" - Execute(Mkdir(workdir)) - </file> - <file name="SConscript"> - import my_utils - MakeWorkDir('/tmp/work') - print "build_id=" + my_utils.build_id() - </file> - </scons_example> - - <para> - - And then in your &SConscript; or any sub-&SConscript; anywhere in - your build, you can import <filename>my_utils</filename> and use it: - - </para> - - <sconstruct> - import my_utils - print "build_id=" + my_utils.build_id() - my_utils.MakeWorkDir('/tmp/work') - </sconstruct> - - <para> - Note that although you can put this library in - <filename>site_scons/site_init.py</filename>, - it is no better there than <filename>site_scons/my_utils.py</filename> - since you still have to import that module into your &SConscript;. - Also note that in order to refer to objects in the SCons namespace - such as &Environment; or &Mkdir; or &Execute; in any file other - than a &SConstruct; or &SConscript; you always need to do - </para> - <sconstruct> - from SCons.Script import * - </sconstruct> - - <para> - This is true in modules in <filename>site_scons</filename> such as - <filename>site_scons/site_init.py</filename> as well. - </para> - - <para> - - You can use any of the user- or machine-wide site dirs such as - <filename>~/.scons/site_scons</filename> instead of - <filename>./site_scons</filename>, or use the - <literal>--site-dir</literal> option to point to your own dir. - <filename>site_init.py</filename> and - <filename>site_tools</filename> will be located under that dir. - To avoid using a <filename>site_scons</filename> dir at all, - even if it exists, use the <literal>--no-site-dir</literal> - option. - - </para> - - </section> - - - <!-- - - <section> - <title>Builders That Use Other Builders</title> - - <para> - - XXX para - - </para> - - <scons_example name="ex8"> - <file name="SConstruct" printme="1"> - env = Environment() - #env.SourceCode('.', env.BitKeeper('my_command')) - env.Program('hello.c') - </file> - <file name="hello.c"> - hello.c - </file> - </scons_example> - - <scons_output example="ex8"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - --> diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml index f42a61f..749a8ba 100644 --- a/doc/user/builders-writing.xml +++ b/doc/user/builders-writing.xml @@ -129,7 +129,7 @@ This functionality could be invoked as in the following example: </para> <programlisting> - bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') </programlisting> <para> @@ -163,12 +163,26 @@ This functionality could be invoked as in the following example: </para> - + <scons_example name="ex1"> + <file name="SConstruct"> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env = Environment(BUILDERS = {'Foo' : bld}) + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + env.Foo('file.foo', 'file.input') + </file> + <file name="file.input"> + file.input + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> - <programlisting> + <sconstruct> bld = Builder(action = 'foobuild < $SOURCE > $TARGET') env = Environment(BUILDERS = {'Foo' : bld}) - </programlisting> + </sconstruct> <para> @@ -188,10 +202,9 @@ This functionality could be invoked as in the following example: </para> - <screen> - % <userinput>scons -Q</userinput> - foobuild < file.input > file.foo - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -224,19 +237,30 @@ This functionality could be invoked as in the following example: in the generated error consistent with what the user will see in the User's Guide. --> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct"> + import SCons.Defaults; SCons.Defaults.ConstructionEnvironment['TOOLS'] = {}; bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </file> + <file name="SConstruct.printme" printme="1"> bld = Builder(action = 'foobuild < $SOURCE > $TARGET') env = Environment(BUILDERS = {'Foo' : bld}) env.Foo('file.foo', 'file.input') env.Program('hello.c') - </programlisting> + </file> + <file name="file.input"> + file.input + </file> + <file name="hello.c"> + hello.c + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - AttributeError: 'SConsEnvironment' object has no attribute 'Program': - File "/home/my/project/SConstruct", line 4: - env.Program('hello.c') - </screen> + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -247,15 +271,34 @@ This functionality could be invoked as in the following example: </para> - + <scons_example name="ex3"> + <file name="SConstruct"> + env = Environment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + bld = Builder(action = 'foobuild < $SOURCE > $TARGET') + env.Append(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + </file> + <file name="file.input"> + file.input + </file> + <file name="hello.c"> + hello.c + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> - <programlisting> + <sconstruct> env = Environment() bld = Builder(action = 'foobuild < $SOURCE > $TARGET') env.Append(BUILDERS = {'Foo' : bld}) env.Foo('file.foo', 'file.input') env.Program('hello.c') - </programlisting> + </sconstruct> <para> @@ -264,13 +307,13 @@ This functionality could be invoked as in the following example: </para> - <programlisting> + <sconstruct> env = Environment() bld = Builder(action = 'foobuild < $SOURCE > $TARGET') env['BUILDERS']['Foo'] = bld env.Foo('file.foo', 'file.input') env.Program('hello.c') - </programlisting> + </sconstruct> <para> @@ -281,12 +324,9 @@ This functionality could be invoked as in the following example: </para> - <screen> - % <userinput>scons -Q</userinput> - foobuild < file.input > file.foo - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="ex3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -310,22 +350,40 @@ This functionality could be invoked as in the following example: </para> - + <scons_example name="ex4"> + <file name="SConstruct"> + bld = Builder(action = 'foobuild < $SOURCE > $TARGET', + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + env.Foo('file1') + env.Foo('file2') + </file> + <file name="file1.input"> + file1.input + </file> + <file name="file2.input"> + file2.input + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> - <programlisting> + <sconstruct> bld = Builder(action = 'foobuild < $SOURCE > $TARGET', suffix = '.foo', src_suffix = '.input') env = Environment(BUILDERS = {'Foo' : bld}) env.Foo('file1') env.Foo('file2') - </programlisting> + </sconstruct> - <screen> - % <userinput>scons -Q</userinput> - foobuild < file1.input > file1.foo - foobuild < file2.input > file2.foo - </screen> + <scons_output example="ex4"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -439,7 +497,8 @@ This functionality could be invoked as in the following example: </para> - <programlisting> + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> def build_function(target, source, env): # Code to build "target" from "source" return None @@ -448,7 +507,11 @@ This functionality could be invoked as in the following example: src_suffix = '.input') env = Environment(BUILDERS = {'Foo' : bld}) env.Foo('file') - </programlisting> + </file> + <file name="file.input"> + file.input + </file> + </scons_example> <para> @@ -459,10 +522,9 @@ This functionality could be invoked as in the following example: </para> - <screen> - % <userinput>scons -Q</userinput> - build_function(["file.foo"], ["file.input"]) - </screen> + <scons_output example="ex5"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -482,7 +544,7 @@ This functionality could be invoked as in the following example: <programlisting> def generate_actions(source, target, env, for_signature): - return 'foobuild < %s > %s' % (target[0], source[0]) + return 'foobuild < %s > %s' % (target[0], source[0]) </programlisting> <para> @@ -582,9 +644,27 @@ This functionality could be invoked as in the following example: </para> - + <scons_example name="ex6"> + <file name="SConstruct"> + def generate_actions(source, target, env, for_signature): + return 'foobuild < %s > %s' % (source[0], target[0]) + bld = Builder(generator = generate_actions, + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + env.Foo('file') + </file> + <file name="file.input"> + file.input + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> - <programlisting> + <sconstruct> def generate_actions(source, target, env, for_signature): return 'foobuild < %s > %s' % (source[0], target[0]) bld = Builder(generator = generate_actions, @@ -592,12 +672,11 @@ This functionality could be invoked as in the following example: src_suffix = '.input') env = Environment(BUILDERS = {'Foo' : bld}) env.Foo('file') - </programlisting> + </sconstruct> - <screen> - % <userinput>scons -Q</userinput> - foobuild < file.input > file.foo - </screen> + <scons_output example="ex6"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -643,9 +722,33 @@ This functionality could be invoked as in the following example: </para> - + <scons_example name="ex7"> + <file name="SConstruct"> + def modify_targets(target, source, env): + target.append('new_target') + source.append('new_source') + return target, source + bld = Builder(action = 'foobuild $TARGETS - $SOURCES', + suffix = '.foo', + src_suffix = '.input', + emitter = modify_targets) + env = Environment(BUILDERS = {'Foo' : bld}) + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + env.Foo('file') + </file> + <file name="file.input"> + file.input + </file> + <file name="new_source"> + new_source + </file> + <file name="foobuild" chmod="0755"> + cat + </file> + </scons_example> - <programlisting> + <sconstruct> def modify_targets(target, source, env): target.append('new_target') source.append('new_source') @@ -656,7 +759,7 @@ This functionality could be invoked as in the following example: emitter = modify_targets) env = Environment(BUILDERS = {'Foo' : bld}) env.Foo('file') - </programlisting> + </sconstruct> <para> @@ -664,10 +767,9 @@ This functionality could be invoked as in the following example: </para> - <screen> - % <userinput>scons -Q</userinput> - foobuild file.foo new_target - file.input new_source - </screen> + <scons_output example="ex7"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -685,7 +787,9 @@ This functionality could be invoked as in the following example: </para> - <programlisting> + <scons_example name="MY_EMITTER"> + + <file name="SConstruct" printme="1"> bld = Builder(action = 'my_command $SOURCES > $TARGET', suffix = '.foo', src_suffix = '.input', @@ -703,10 +807,26 @@ This functionality could be invoked as in the following example: import os env1['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() env2['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() + </file> + <file name="file1.input"> + file1.input + </file> + <file name="file2.input"> + file2.input + </file> + <file name="modify1.in"> + modify1.input + </file> + <file name="modify2.in"> + modify2.input + </file> + <file name="my_command" chmod="0755"> + cat + </file> - </programlisting> + </scons_example> - <programlisting> + <sconstruct> bld = Builder(action = 'my_command $SOURCES > $TARGET', suffix = '.foo', src_suffix = '.input', @@ -721,7 +841,7 @@ This functionality could be invoked as in the following example: MY_EMITTER = modify2) env1.Foo('file1') env2.Foo('file2') - </programlisting> + </sconstruct> <para> @@ -732,11 +852,9 @@ This functionality could be invoked as in the following example: </para> - <screen> - % <userinput>scons -Q</userinput> - my_command file1.input modify1.in > file1.foo - my_command file2.input modify2.in > file2.foo - </screen> + <scons_output example="MY_EMITTER"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -820,14 +938,23 @@ This functionality could be invoked as in the following example: </para> - <programlisting> + <scons_example name="site1"> + <file name="site_scons/site_init.py" printme="1"> def TOOL_ADD_HEADER(env): """A Tool to add a header from $HEADER to the source file""" add_header = Builder(action=['echo "$HEADER" > $TARGET', 'cat $SOURCE >> $TARGET']) env.Append(BUILDERS = {'AddHeader' : add_header}) env['HEADER'] = '' # set default value - </programlisting> + </file> + <file name="SConstruct"> + env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====") + env.AddHeader('tgt', 'src') + </file> + <file name="src"> + hi there + </file> + </scons_example> <para> @@ -835,11 +962,11 @@ This functionality could be invoked as in the following example: </para> - <programlisting> + <sconstruct> # Use TOOL_ADD_HEADER from site_scons/site_init.py env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====") env.AddHeader('tgt', 'src') - </programlisting> + </sconstruct> <para> @@ -885,7 +1012,8 @@ This functionality could be invoked as in the following example: functions: </para> - <programlisting> + <scons_example name="site2"> + <file name="site_scons/my_utils.py" printme="1"> from SCons.Script import * # for Execute and Mkdir def build_id(): """Return a build ID (stub version)""" @@ -893,7 +1021,13 @@ This functionality could be invoked as in the following example: def MakeWorkDir(workdir): """Create the specified dir immediately""" Execute(Mkdir(workdir)) - </programlisting> + </file> + <file name="SConscript"> + import my_utils + MakeWorkDir('/tmp/work') + print "build_id=" + my_utils.build_id() + </file> + </scons_example> <para> @@ -902,11 +1036,11 @@ This functionality could be invoked as in the following example: </para> - <programlisting> + <sconstruct> import my_utils print "build_id=" + my_utils.build_id() my_utils.MakeWorkDir('/tmp/work') - </programlisting> + </sconstruct> <para> Note that although you can put this library in @@ -917,9 +1051,9 @@ This functionality could be invoked as in the following example: such as &Environment; or &Mkdir; or &Execute; in any file other than a &SConstruct; or &SConscript; you always need to do </para> - <programlisting> + <sconstruct> from SCons.Script import * - </programlisting> + </sconstruct> <para> This is true in modules in <filename>site_scons</filename> such as diff --git a/doc/user/builders.in b/doc/user/builders.in deleted file mode 100644 index f3989ef..0000000 --- a/doc/user/builders.in +++ /dev/null @@ -1,57 +0,0 @@ -<!-- - - __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. - ---> - -<!-- -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" -"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> - -<refentry id="Command"> - -<refmeta> -<refentrytitle>Command</refentrytitle> -</refmeta> - -<methodsynopsis> - <methodname>env.Command</methodname> - <methodparam>foo</methodparam> - <methodparam>bar</methodparam> -</methodsynopsis> - -</refentry> ---> - -<para> - -This appendix contains descriptions of all of the -Builders that are <emphasis>potentially</emphasis> -available "out of the box" in this version of SCons. - -</para> - -<variablelist> - -&builders-gen; - -</variablelist> diff --git a/doc/user/caching.in b/doc/user/caching.in deleted file mode 100644 index cb8521b..0000000 --- a/doc/user/caching.in +++ /dev/null @@ -1,502 +0,0 @@ -<!-- - - __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> - - On multi-developer software projects, - you can sometimes speed up every developer's builds a lot by - allowing them to share the derived files that they build. - &SCons; makes this easy, as well as reliable. - - </para> - - <section> - <title>Specifying the Shared Cache Directory</title> - - <para> - - To enable sharing of derived files, - use the &CacheDir; function - in any &SConscript; file: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct"> - env = Environment() - env.Program('hello.c') - CacheDir('cache') - </file> - <file name="hello.c"> - hello.c - </file> - <directory name="cache"> - </directory> - <file name="not_used" printme="1"> - CacheDir('/usr/local/build_cache') - </file> - </scons_example> - - <para> - - Note that the directory you specify must already exist - and be readable and writable by all developers - who will be sharing derived files. - It should also be in some central location - that all builds will be able to access. - In environments where developers are using separate systems - (like individual workstations) for builds, - this directory would typically be - on a shared or NFS-mounted file system. - - </para> - - <para> - - Here's what happens: - When a build has a &CacheDir; specified, - every time a file is built, - it is stored in the shared cache directory - along with its MD5 build signature. - <footnote> - <para> - Actually, the MD5 signature is used as the name of the file - in the shared cache directory in which the contents are stored. - </para> - </footnote> - On subsequent builds, - before an action is invoked to build a file, - &SCons; will check the shared cache directory - to see if a file with the exact same build - signature already exists. - If so, the derived file will not be built locally, - but will be copied into the local build directory - from the shared cache directory, - like so: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q -c</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note that the &CacheDir; feature still calculates - MD5 build sigantures for the shared cache file names - even if you configure &SCons; to use timestamps - to decide if files are up to date. - (See the <xref linkend="chap-depends"></xref> - chapter for information about the &Decider; function.) - Consequently, using &CacheDir; may reduce or eliminate any - potential performance improvements - from using timestamps for up-to-date decisions. - - </para> - - </section> - - <section> - <title>Keeping Build Output Consistent</title> - - <para> - - One potential drawback to using a shared cache - is that the output printed by &SCons; - can be inconsistent from invocation to invocation, - because any given file may be rebuilt one time - and retrieved from the shared cache the next time. - This can make analyzing build output more difficult, - especially for automated scripts that - expect consistent output each time. - - </para> - - <para> - - If, however, you use the <literal>--cache-show</literal> option, - &SCons; will print the command line that it - <emphasis>would</emphasis> have executed - to build the file, - even when it is retrieving the file from the shared cache. - This makes the build output consistent - every time the build is run: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q -c</scons_output_command> - <scons_output_command>scons -Q --cache-show</scons_output_command> - </scons_output> - - <para> - - The trade-off, of course, is that you no longer - know whether or not &SCons; - has retrieved a derived file from cache - or has rebuilt it locally. - - </para> - - </section> - - <section> - <title>Not Using the Shared Cache for Specific Files</title> - - <para> - - You may want to disable caching for certain - specific files in your configuration. - For example, if you only want to put - executable files in a central cache, - but not the intermediate object files, - you can use the &NoCache; - function to specify that the - object files should not be cached: - - </para> - - <scons_example name="ex-NoCache"> - <file name="SConstruct" printme="1"> - env = Environment() - obj = env.Object('hello.c') - env.Program('hello.c') - CacheDir('cache') - NoCache('hello.o') - </file> - <file name="hello.c"> - hello.c - </file> - <directory name="cache"> - </directory> - </scons_example> - - <para> - - Then when you run &scons; after cleaning - the built targets, - it will recompile the object file locally - (since it doesn't exist in the shared cache directory), - but still realize that the shared cache directory - contains an up-to-date executable program - that can be retrieved instead of re-linking: - - </para> - - <!-- - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q -c</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - --> - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q -c</userinput> - Removed hello.o - Removed hello - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - Retrieved `hello' from cache - </screen> - - </section> - - <section> - <title>Disabling the Shared Cache</title> - - <para> - - Retrieving an already-built file - from the shared cache - is usually a significant time-savings - over rebuilding the file, - but how much of a savings - (or even whether it saves time at all) - can depend a great deal on your - system or network configuration. - For example, retrieving cached files - from a busy server over a busy network - might end up being slower than - rebuilding the files locally. - - </para> - - <para> - - In these cases, you can specify - the <literal>--cache-disable</literal> - command-line option to tell &SCons; - to not retrieve already-built files from the - shared cache directory: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q -c</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q -c</scons_output_command> - <scons_output_command>scons -Q --cache-disable</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Populating a Shared Cache With Already-Built Files</title> - - <para> - - Sometimes, you may have one or more derived files - already built in your local build tree - that you wish to make available to other people doing builds. - For example, you may find it more effective to perform - integration builds with the cache disabled - (per the previous section) - and only populate the shared cache directory - with the built files after the integration build - has completed successfully. - This way, the cache will only get filled up - with derived files that are part of a complete, successful build - not with files that might be later overwritten - while you debug integration problems. - - </para> - - <para> - - In this case, you can use the - the <literal>--cache-force</literal> option - to tell &SCons; to put all derived files in the cache, - even if the files already exist in your local tree - from having been built by a previous invocation: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q --cache-disable</scons_output_command> - <scons_output_command>scons -Q -c</scons_output_command> - <scons_output_command>scons -Q --cache-disable</scons_output_command> - <scons_output_command>scons -Q --cache-force</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Notice how the above sample run - demonstrates that the <literal>--cache-disable</literal> - option avoids putting the built - <filename>hello.o</filename> - and - <filename>hello</filename> files in the cache, - but after using the <literal>--cache-force</literal> option, - the files have been put in the cache - for the next invocation to retrieve. - - </para> - - </section> - - <section> - <title>Minimizing Cache Contention: the <literal>--random</literal> Option</title> - - <para> - - If you allow multiple builds to update the - shared cache directory simultaneously, - two builds that occur at the same time - can sometimes start "racing" - with one another to build the same files - in the same order. - If, for example, - you are linking multiple files into an executable program: - - </para> - - <scons_example name="ex-random"> - <file name="SConstruct" printme="1"> - Program('prog', - ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) - </file> - <file name="f1.c">f1.c</file> - <file name="f2.c">f2.c</file> - <file name="f3.c">f3.c</file> - <file name="f4.c">f4.c</file> - <file name="f5.c">f5.c</file> - <file name="f6.c">f6.c</file> - </scons_example> - - <para> - - &SCons; will normally build the input object files - on which the program depends in their normal, sorted order: - - </para> - - <scons_output example="ex-random"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - But if two such builds take place simultaneously, - they may each look in the cache at nearly the same - time and both decide that <filename>f1.o</filename> - must be rebuilt and pushed into the shared cache directory, - then both decide that <filename>f2.o</filename> - must be rebuilt (and pushed into the shared cache directory), - then both decide that <filename>f3.o</filename> - must be rebuilt... - This won't cause any actual build problems--both - builds will succeed, - generate correct output files, - and populate the cache--but - it does represent wasted effort. - - </para> - - <para> - - To alleviate such contention for the cache, - you can use the <literal>--random</literal> command-line option - to tell &SCons; to build dependencies - in a random order: - - </para> - - <!-- - - The following <screen> output was generated by this: - - <scons_output example="ex-random"> - <scons_output_command>scons -Q - -random</scons_output_command> - </scons_output> - - We captured it directly here to guarantee a "random" order, - guarding against the potential for - -random to happen - to return things in the original sorted order. - - --> - - <screen> - % <userinput>scons -Q --random</userinput> - cc -o f3.o -c f3.c - cc -o f1.o -c f1.c - cc -o f5.o -c f5.c - cc -o f2.o -c f2.c - cc -o f4.o -c f4.c - cc -o prog f1.o f2.o f3.o f4.o f5.o - </screen> - - <para> - - Multiple builds using the <literal>--random</literal> option - will usually build their dependencies in different, - random orders, - which minimizes the chances for a lot of - contention for same-named files - in the shared cache directory. - Multiple simultaneous builds might still race to try to build - the same target file on occasion, - but long sequences of inefficient contention - should be rare. - - </para> - - <para> - - Note, of course, - the <literal>--random</literal> option - will cause the output that &SCons; prints - to be inconsistent from invocation to invocation, - which may be an issue when - trying to compare output from different build runs. - - </para> - - <para> - - If you want to make sure dependencies will be built - in a random order without having to specify - the <literal>--random</literal> on very command line, - you can use the &SetOption; function to - set the <literal>random</literal> option - within any &SConscript; file: - - </para> - - <scons_example name="ex-random"> - <file name="SConstruct" printme="1"> - SetOption('random', 1) - Program('prog', - ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) - </file> - <file name="f1.c">f1.c</file> - <file name="f2.c">f2.c</file> - <file name="f3.c">f3.c</file> - <file name="f4.c">f4.c</file> - <file name="f5.c">f5.c</file> - <file name="f6.c">f6.c</file> - </scons_example> - - </section> - - <!-- - - <section> - <title>Troubleshooting Shared Caching: the &cache-debug; Option</title> - - <para> - - XXX describe the - - cache-debug option - XXX maybe point to the troubleshooting appendix? - - </para> - - </section> - - --> - - <!-- - - <section> - - <para> - - XXX describe CacheDir management: monitoring, deleting, etc. - - </para> - - </section> - - --> diff --git a/doc/user/caching.xml b/doc/user/caching.xml index 2348d32..cb8521b 100644 --- a/doc/user/caching.xml +++ b/doc/user/caching.xml @@ -43,9 +43,21 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct"> + env = Environment() + env.Program('hello.c') + CacheDir('cache') + </file> + <file name="hello.c"> + hello.c + </file> + <directory name="cache"> + </directory> + <file name="not_used" printme="1"> CacheDir('/usr/local/build_cache') - </programlisting> + </file> + </scons_example> <para> @@ -86,17 +98,11 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q -c</userinput> - Removed hello.o - Removed hello - % <userinput>scons -Q</userinput> - Retrieved `hello.o' from cache - Retrieved `hello' from cache - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -142,17 +148,11 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q -c</userinput> - Removed hello.o - Removed hello - % <userinput>scons -Q --cache-show</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q --cache-show</scons_output_command> + </scons_output> <para> @@ -181,13 +181,20 @@ </para> - <programlisting> + <scons_example name="ex-NoCache"> + <file name="SConstruct" printme="1"> env = Environment() obj = env.Object('hello.c') env.Program('hello.c') CacheDir('cache') NoCache('hello.o') - </programlisting> + </file> + <file name="hello.c"> + hello.c + </file> + <directory name="cache"> + </directory> + </scons_example> <para> @@ -255,23 +262,13 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q -c</userinput> - Removed hello.o - Removed hello - % <userinput>scons -Q</userinput> - Retrieved `hello.o' from cache - Retrieved `hello' from cache - % <userinput>scons -Q -c</userinput> - Removed hello.o - Removed hello - % <userinput>scons -Q --cache-disable</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q --cache-disable</scons_output_command> + </scons_output> </section> @@ -306,21 +303,13 @@ </para> - <screen> - % <userinput>scons -Q --cache-disable</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q -c</userinput> - Removed hello.o - Removed hello - % <userinput>scons -Q --cache-disable</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q --cache-force</userinput> - scons: `.' is up to date. - % <userinput>scons -Q</userinput> - scons: `.' is up to date. - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q --cache-disable</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + <scons_output_command>scons -Q --cache-disable</scons_output_command> + <scons_output_command>scons -Q --cache-force</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -354,10 +343,18 @@ </para> - <programlisting> + <scons_example name="ex-random"> + <file name="SConstruct" printme="1"> Program('prog', ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) - </programlisting> + </file> + <file name="f1.c">f1.c</file> + <file name="f2.c">f2.c</file> + <file name="f3.c">f3.c</file> + <file name="f4.c">f4.c</file> + <file name="f5.c">f5.c</file> + <file name="f6.c">f6.c</file> + </scons_example> <para> @@ -366,15 +363,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o f1.o -c f1.c - cc -o f2.o -c f2.c - cc -o f3.o -c f3.c - cc -o f4.o -c f4.c - cc -o f5.o -c f5.c - cc -o prog f1.o f2.o f3.o f4.o f5.o - </screen> + <scons_output example="ex-random"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -464,14 +455,19 @@ </para> - <programlisting> - Program('prog', - ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) - + <scons_example name="ex-random"> + <file name="SConstruct" printme="1"> SetOption('random', 1) Program('prog', ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c']) - </programlisting> + </file> + <file name="f1.c">f1.c</file> + <file name="f2.c">f2.c</file> + <file name="f3.c">f3.c</file> + <file name="f4.c">f4.c</file> + <file name="f5.c">f5.c</file> + <file name="f6.c">f6.c</file> + </scons_example> </section> diff --git a/doc/user/command-line.in b/doc/user/command-line.in deleted file mode 100644 index 33f88ec..0000000 --- a/doc/user/command-line.in +++ /dev/null @@ -1,2345 +0,0 @@ -<!-- - - __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> - - &SCons; provides a number of ways - for the writer of the &SConscript; files - to give the users who will run &SCons; - a great deal of control over the build execution. - The arguments that the user can specify on - the command line are broken down into three types: - - </para> - - <variablelist> - - <varlistentry> - <term>Options</term> - - <listitem> - <para> - - Command-line options always begin with - one or two <literal>-</literal> (hyphen) characters. - &SCons; provides ways for you to examine - and set options values from within your &SConscript; files, - as well as the ability to define your own - custom options. - See <xref linkend="sect-command-line-options"></xref>, below. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Variables</term> - - <listitem> - <para> - - Any command-line argument containing an <literal>=</literal> - (equal sign) is considered a variable setting with the form - <varname>variable</varname>=<varname>value</varname>. - &SCons; provides direct access to - all of the command-line variable settings, - the ability to apply command-line variable settings - to construction environments, - and functions for configuring - specific types of variables - (Boolean values, path names, etc.) - with automatic validation of the user's specified values. - See <xref linkend="sect-command-line-variables"></xref>, below. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Targets</term> - - <listitem> - <para> - - Any command-line argument that is not an option - or a variable setting - (does not begin with a hyphen - and does not contain an equal sign) - is considered a target that the user - (presumably) wants &SCons; to build. - A list of Node objects representing - the target or targets to build. - &SCons; provides access to the list of specified targets, - as well as ways to set the default list of targets - from within the &SConscript; files. - See <xref linkend="sect-command-line-targets"></xref>, below. - - </para> - </listitem> - </varlistentry> - - </variablelist> - - <section id="sect-command-line-options"> - <title>Command-Line Options</title> - - <para> - - &SCons; has many <emphasis>command-line options</emphasis> - that control its behavior. - A &SCons; <emphasis>command-line option</emphasis> - always begins with one or two <literal>-</literal> (hyphen) - characters. - - </para> - - <section> - <title>Not Having to Specify Command-Line Options Each Time: the &SCONSFLAGS; Environment Variable</title> - - <para> - - Users may find themselves supplying - the same command-line options every time - they run &SCons;. - For example, you might find it saves time - to specify a value of <literal>-j 2</literal> - to have &SCons; run up to two build commands in parallel. - To avoid having to type <literal>-j 2</literal> by hand - every time, - you can set the external environment variable - &SCONSFLAGS; to a string containing - command-line options that you want &SCons; to use. - - </para> - - <para> - - If, for example, - you're using a POSIX shell that's - compatible with the Bourne shell, - and you always want &SCons; to use the - <literal>-Q</literal> option, - you can set the &SCONSFLAGS; - environment as follows: - - </para> - - <scons_example name="SCONSFLAGS"> - <file name="SConstruct"> - def b(target, source, env): - pass - def s(target, source, env): - return " ... [build output] ..." - a = Action(b, strfunction = s) - env = Environment(BUILDERS = {'A' : Builder(action=a)}) - env.A('foo.out', 'foo.in') - </file> - <file name="foo.in"> - foo.in - </file> - </scons_example> - - <scons_output example="SCONSFLAGS"> - <scons_output_command>scons</scons_output_command> - <scons_output_command>export SCONSFLAGS="-Q"</scons_output_command> - <scons_output_command environment="SCONSFLAGS=-Q">scons</scons_output_command> - </scons_output> - - <para> - - Users of &csh;-style shells on POSIX systems - can set the &SCONSFLAGS; environment as follows: - - </para> - - <screen> - $ <userinput>setenv SCONSFLAGS "-Q"</userinput> - </screen> - - <para> - - Windows users may typically want to set the - &SCONSFLAGS; in the appropriate tab of the - <literal>System Properties</literal> window. - - </para> - - </section> - - <section> - <title>Getting Values Set by Command-Line Options: the &GetOption; Function</title> - - <para> - - &SCons; provides the &GetOption; function - to get the values set by the various command-line options. - One common use of this is to check whether or not - the <literal>-h</literal> or <literal>--help</literal> option - has been specified. - Normally, &SCons; does not print its help text - until after it has read all of the &SConscript; files, - because it's possible that help text has been added - by some subsidiary &SConscript; file deep in the - source tree hierarchy. - Of course, reading all of the &SConscript; files - takes extra time. - - </para> - - <para> - - If you know that your configuration does not define - any additional help text in subsidiary &SConscript; files, - you can speed up the command-line help available to users - by using the &GetOption; function to load the - subsidiary &SConscript; files only if the - the user has <emphasis>not</emphasis> specified - the <literal>-h</literal> or <literal>--help</literal> option, - like so: - - </para> - - <sconstruct> - if not GetOption('help'): - SConscript('src/SConscript', export='env') - </sconstruct> - - <para> - - In general, the string that you pass to the - &GetOption; function to fetch the value of a command-line - option setting is the same as the "most common" long option name - (beginning with two hyphen characters), - although there are some exceptions. - The list of &SCons; command-line options - and the &GetOption; strings for fetching them, - are available in the - <xref linkend="sect-command-line-option-strings"></xref> section, - below. - - </para> - - </section> - - <section> - <title>Setting Values of Command-Line Options: the &SetOption; Function</title> - - <para> - - You can also set the values of &SCons; - command-line options from within the &SConscript; files - by using the &SetOption; function. - The strings that you use to set the values of &SCons; - command-line options are available in the - <xref linkend="sect-command-line-option-strings"></xref> section, - below. - - </para> - - <para> - - One use of the &SetOption; function is to - specify a value for the <literal>-j</literal> - or <literal>--jobs</literal> option, - so that users get the improved performance - of a parallel build without having to specify the option by hand. - A complicating factor is that a good value - for the <literal>-j</literal> option is - somewhat system-dependent. - One rough guideline is that the more processors - your system has, - the higher you want to set the - <literal>-j</literal> value, - in order to take advantage of the number of CPUs. - - </para> - - <para> - - For example, suppose the administrators - of your development systems - have standardized on setting a - <varname>NUM_CPU</varname> environment variable - to the number of processors on each system. - A little bit of Python code - to access the environment variable - and the &SetOption; function - provide the right level of flexibility: - - </para> - - <scons_example name="SetOption"> - <file name="SConstruct" printme="1"> - import os - num_cpu = int(os.environ.get('NUM_CPU', 2)) - SetOption('num_jobs', num_cpu) - print "running with -j", GetOption('num_jobs') - </file> - <file name="foo.in"> - foo.in - </file> - </scons_example> - - <para> - - The above snippet of code - sets the value of the <literal>--jobs</literal> option - to the value specified in the - <varname>$NUM_CPU</varname> environment variable. - (This is one of the exception cases - where the string is spelled differently from - the from command-line option. - The string for fetching or setting the <literal>--jobs</literal> - value is <literal>num_jobs</literal> - for historical reasons.) - The code in this example prints the <literal>num_jobs</literal> - value for illustrative purposes. - It uses a default value of <literal>2</literal> - to provide some minimal parallelism even on - single-processor systems: - - </para> - - <scons_output example="SetOption"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - But if the <varname>$NUM_CPU</varname> - environment variable is set, - then we use that for the default number of jobs: - - </para> - - <scons_output example="SetOption"> - <scons_output_command>export NUM_CPU="4"</scons_output_command> - <scons_output_command environment="NUM_CPU=4">scons -Q</scons_output_command> - </scons_output> - - <para> - - But any explicit - <literal>-j</literal> or <literal>--jobs</literal> - value the user specifies an the command line is used first, - regardless of whether or not - the <varname>$NUM_CPU</varname> environment - variable is set: - - </para> - - <scons_output example="SetOption"> - <scons_output_command>scons -Q -j 7</scons_output_command> - <scons_output_command>export NUM_CPU="4"</scons_output_command> - <scons_output_command environment="NUM_CPU=4">scons -Q -j 3</scons_output_command> - </scons_output> - - </section> - - <section id="sect-command-line-option-strings"> - <title>Strings for Getting or Setting Values of &SCons; Command-Line Options</title> - - <para> - - The strings that you can pass to the &GetOption; - and &SetOption; functions usually correspond to the - first long-form option name - (beginning with two hyphen characters: <literal>--</literal>), - after replacing any remaining hyphen characters - with underscores. - - </para> - - <para> - - The full list of strings and the variables they - correspond to is as follows: - - </para> - - <informaltable> - <tgroup cols="2" align="left"> - - <thead> - - <row> - <entry>String for &GetOption; and &SetOption;</entry> - <entry>Command-Line Option(s)</entry> - </row> - - </thead> - - <tbody> - - <row> - <entry><literal>cache_debug</literal></entry> - <entry><option>--cache-debug</option></entry> - </row> - - <row> - <entry><literal>cache_disable</literal></entry> - <entry><option>--cache-disable</option></entry> - </row> - - <row> - <entry><literal>cache_force</literal></entry> - <entry><option>--cache-force</option></entry> - </row> - - <row> - <entry><literal>cache_show</literal></entry> - <entry><option>--cache-show</option></entry> - </row> - - <row> - <entry><literal>clean</literal></entry> - <entry><option>-c</option>, - <option>--clean</option>, - <option>--remove</option></entry> - </row> - - <row> - <entry><literal>config</literal></entry> - <entry><option>--config</option></entry> - </row> - - <row> - <entry><literal>directory</literal></entry> - <entry><option>-C</option>, - <option>--directory</option></entry> - </row> - - <row> - <entry><literal>diskcheck</literal></entry> - <entry><option>--diskcheck</option></entry> - </row> - - <row> - <entry><literal>duplicate</literal></entry> - <entry><option>--duplicate</option></entry> - </row> - - <row> - <entry><literal>file</literal></entry> - <entry><option>-f</option>, - <option>--file</option>, - <option>--makefile </option>, - <option>--sconstruct</option></entry> - </row> - - <row> - <entry><literal>help</literal></entry> - <entry><option>-h</option>, - <option>--help</option></entry> - </row> - - <row> - <entry><literal>ignore_errors</literal></entry> - <entry><option>--ignore-errors</option></entry> - </row> - - <row> - <entry><literal>implicit_cache</literal></entry> - <entry><option>--implicit-cache</option></entry> - </row> - - <row> - <entry><literal>implicit_deps_changed</literal></entry> - <entry><option>--implicit-deps-changed</option></entry> - </row> - - <row> - <entry><literal>implicit_deps_unchanged</literal></entry> - <entry><option>--implicit-deps-unchanged</option></entry> - </row> - - <row> - <entry><literal>interactive</literal></entry> - <entry><option>--interact</option>, - <option>--interactive</option></entry> - </row> - - <row> - <entry><literal>keep_going</literal></entry> - <entry><option>-k</option>, - <option>--keep-going</option></entry> - </row> - - <row> - <entry><literal>max_drift</literal></entry> - <entry><option>--max-drift</option></entry> - </row> - - <row> - <entry><literal>no_exec</literal></entry> - <entry><option>-n</option>, - <option>--no-exec</option>, - <option>--just-print</option>, - <option>--dry-run</option>, - <option>--recon</option></entry> - </row> - - <row> - <entry><literal>no_site_dir</literal></entry> - <entry><option>--no-site-dir</option></entry> - </row> - - <row> - <entry><literal>num_jobs</literal></entry> - <entry><option>-j</option>, - <option>--jobs</option></entry> - </row> - - <row> - <entry><literal>profile_file</literal></entry> - <entry><option>--profile</option></entry> - </row> - - <row> - <entry><literal>question</literal></entry> - <entry><option>-q</option>, - <option>--question</option></entry> - </row> - - <row> - <entry><literal>random</literal></entry> - <entry><option>--random</option></entry> - </row> - - <row> - <entry><literal>repository</literal></entry> - <entry><option>-Y</option>, - <option>--repository</option>, - <option>--srcdir</option></entry> - </row> - - <row> - <entry><literal>silent</literal></entry> - <entry><option>-s</option>, - <option>--silent</option>, - <option>--quiet</option></entry> - </row> - - <row> - <entry><literal>site_dir</literal></entry> - <entry><option>--site-dir</option></entry> - </row> - - <row> - <entry><literal>stack_size</literal></entry> - <entry><option>--stack-size</option></entry> - </row> - - <row> - <entry><literal>taskmastertrace_file</literal></entry> - <entry><option>--taskmastertrace</option></entry> - </row> - - <row> - <entry><literal>warn</literal></entry> - <entry><option>--warn</option> <option>--warning</option></entry> - </row> - - </tbody> - - </tgroup> - </informaltable> - - </section> - - <section> - <title>Adding Custom Command-Line Options: the &AddOption; Function</title> - - <para> - - &SCons; also allows you to define your own - command-line options with the &AddOption; function. - The &AddOption; function takes the same arguments - as the <function>optparse.add_option</function> function - from the standard Python library. - <footnote> - <para> - The &AddOption; function is, - in fact, implemented using a subclass - of the <classname>optparse.OptionParser</classname>. - </para> - </footnote> - Once you have added a custom command-line option - with the &AddOption; function, - the value of the option (if any) is immediately available - using the standard &GetOption; function. - (The value can also be set using &SetOption;, - although that's not very useful in practice - because a default value can be specified in - directly in the &AddOption; call.) - - </para> - - <para> - - One useful example of using this functionality - is to provide a <option>--prefix</option> for users: - - </para> - - <scons_example name="AddOption"> - <file name="SConstruct" printme="1"> - AddOption('--prefix', - dest='prefix', - type='string', - nargs=1, - action='store', - metavar='DIR', - help='installation prefix') - - env = Environment(PREFIX = GetOption('prefix')) - - installed_foo = env.Install('$PREFIX/usr/bin', 'foo.in') - Default(installed_foo) - </file> - <file name="foo.in"> - foo.in - </file> - </scons_example> - - <para> - - The above code uses the &GetOption; function - to set the <varname>$PREFIX</varname> - construction variable to any - value that the user specifies with a command-line - option of <literal>--prefix</literal>. - Because <varname>$PREFIX</varname> - will expand to a null string if it's not initialized, - running &SCons; without the - option of <literal>--prefix</literal> - will install the file in the - <filename>/usr/bin/</filename> directory: - - </para> - - <scons_output example="AddOption"> - <scons_output_command>scons -Q -n</scons_output_command> - </scons_output> - - <para> - - But specifying <literal>--prefix=/tmp/install</literal> - on the command line causes the file to be installed in the - <filename>/tmp/install/usr/bin/</filename> directory: - - </para> - - <scons_output example="AddOption"> - <scons_output_command>scons -Q -n --prefix=/tmp/install</scons_output_command> - </scons_output> - - </section> - - </section> - - <section id="sect-command-line-variables"> - <title>Command-Line <varname>variable</varname>=<varname>value</varname> Build Variables</title> - - <para> - - You may want to control various aspects - of your build by allowing the user - to specify <varname>variable</varname>=<varname>value</varname> - values on the command line. - For example, suppose you - want users to be able to - build a debug version of a program - by running &SCons; as follows: - - </para> - - <screen> - % <userinput>scons -Q debug=1</userinput> - </screen> - - <para> - - &SCons; provides an &ARGUMENTS; dictionary - that stores all of the - <varname>variable</varname>=<varname>value</varname> - assignments from the command line. - This allows you to modify - aspects of your build in response - to specifications on the command line. - (Note that unless you want to require - that users <emphasis>always</emphasis> - specify a variable, - you probably want to use - the Python - <literal>ARGUMENTS.get()</literal> function, - which allows you to specify a default value - to be used if there is no specification - on the command line.) - - </para> - - <para> - - The following code sets the &cv-link-CCFLAGS; construction - variable in response to the <varname>debug</varname> - flag being set in the &ARGUMENTS; dictionary: - - </para> - - <scons_example name="ARGUMENTS"> - <file name="SConstruct" printme="1"> - env = Environment() - debug = ARGUMENTS.get('debug', 0) - if int(debug): - env.Append(CCFLAGS = '-g') - env.Program('prog.c') - </file> - <file name="prog.c"> - prog.c - </file> - </scons_example> - - <para> - - This results in the <varname>-g</varname> - compiler option being used when - <literal>debug=1</literal> - is used on the command line: - - </para> - - <scons_output example="ARGUMENTS"> - <scons_output_command>scons -Q debug=0</scons_output_command> - <scons_output_command>scons -Q debug=0</scons_output_command> - <scons_output_command>scons -Q debug=1</scons_output_command> - <scons_output_command>scons -Q debug=1</scons_output_command> - </scons_output> - - <para> - - Notice that &SCons; keeps track of - the last values used to build the object files, - and as a result correctly rebuilds - the object and executable files - only when the value of the <literal>debug</literal> - argument has changed. - - </para> - - <para> - - The &ARGUMENTS; dictionary has two minor drawbacks. - First, because it is a dictionary, - it can only store one value for each specified keyword, - and thus only "remembers" the last setting - for each keyword on the command line. - This makes the &ARGUMENTS; dictionary - inappropriate if users should be able to - specify multiple values - on the command line for a given keyword. - Second, it does not preserve - the order in which the variable settings - were specified, - which is a problem if - you want the configuration to - behave differently in response - to the order in which the build - variable settings were specified on the command line. - - </para> - - <para> - - To accomodate these requirements, - &SCons; provides an &ARGLIST; variable - that gives you direct access to - <varname>variable</varname>=<varname>value</varname> - settings on the command line, - in the exact order they were specified, - and without removing any duplicate settings. - Each element in the &ARGLIST; variable - is itself a two-element list - containing the keyword and the value - of the setting, - and you must loop through, - or otherwise select from, - the elements of &ARGLIST; to - process the specific settings you want - in whatever way is appropriate for your configuration. - For example, - the following code to let the user - add to the &CPPDEFINES; construction variable - by specifying multiple - <varname>define=</varname> - settings on the command line: - - </para> - - <scons_example name="ARGLIST"> - <file name="SConstruct" printme="1"> - cppdefines = [] - for key, value in ARGLIST: - if key == 'define': - cppdefines.append(value) - env = Environment(CPPDEFINES = cppdefines) - env.Object('prog.c') - </file> - <file name="prog.c"> - prog.c - </file> - </scons_example> - - <para> - - Yields the following output: - - </para> - - <scons_output example="ARGLIST"> - <scons_output_command>scons -Q define=FOO</scons_output_command> - <scons_output_command>scons -Q define=FOO define=BAR</scons_output_command> - </scons_output> - - <para> - - Note that the &ARGLIST; and &ARGUMENTS; - variables do not interfere with each other, - but merely provide slightly different views - into how the user specified - <varname>variable</varname>=<varname>value</varname> - settings on the command line. - You can use both variables in the same - &SCons; configuration. - In general, the &ARGUMENTS; dictionary - is more convenient to use, - (since you can just fetch variable - settings through a dictionary access), - and the &ARGLIST; list - is more flexible - (since you can examine the - specific order in which - the user's command-line variabe settings). - - </para> - - <section> - <title>Controlling Command-Line Build Variables</title> - - <para> - - Being able to use a command-line build variable like - <literal>debug=1</literal> is handy, - but it can be a chore to write specific Python code - to recognize each such variable, - check for errors and provide appropriate messages, - and apply the values to a construction variable. - To help with this, - &SCons; supports a class to - define such build variables easily, - and a mechanism to apply the - build variables to a construction environment. - This allows you to control how the build variables affect - construction environments. - - </para> - - <para> - - For example, suppose that you want users to set - a &RELEASE; construction variable on the - command line whenever the time comes to build - a program for release, - and that the value of this variable - should be added to the command line - with the appropriate <literal>-D</literal> option - (or other command line option) - to pass the value to the C compiler. - Here's how you might do that by setting - the appropriate value in a dictionary for the - &cv-link-CPPDEFINES; construction variable: - - </para> - - <scons_example name="Variables1"> - <file name="SConstruct" printme="1"> - vars = Variables(None, ARGUMENTS) - vars.Add('RELEASE', 'Set to 1 to build for release', 0) - env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) - env.Program(['foo.c', 'bar.c']) - </file> - <file name="foo.c"> - foo.c - </file> - <file name="bar.c"> - bar.c - </file> - </scons_example> - - <para> - - This &SConstruct; file first creates a &Variables; object - which uses the values from the command-line options dictionary &ARGUMENTS; - (the <literal>vars = Variables(None, ARGUMENTS)</literal> call). - It then uses the object's &Add; - method to indicate that the &RELEASE; - variable can be set on the command line, - and that its default value will be <literal>0</literal> - (the third argument to the &Add; method). - The second argument is a line of help text; - we'll learn how to use it in the next section. - - </para> - - <para> - - We then pass the created &Variables; - object as a &variables; keyword argument - to the &Environment; call - used to create the construction environment. - This then allows a user to set the - &RELEASE; build variable on the command line - and have the variable show up in - the command line used to build each object from - a C source file: - - </para> - - <scons_output example="Variables1"> - <scons_output_command>scons -Q RELEASE=1</scons_output_command> - </scons_output> - - <para> - - NOTE: Before &SCons; release 0.98.1, these build variables - were known as "command-line build options." - The class was actually named the &Options; class, - and in the sections below, - the various functions were named - &BoolOption;, &EnumOption;, &ListOption;, - &PathOption;, &PackageOption; and &AddOptions;. - These older names still work, - and you may encounter them in older - &SConscript; files, - but they have been officially deprecated - as of &SCons; version 2.0. - - </para> - - </section> - - <section> - <title>Providing Help for Command-Line Build Variables</title> - - <para> - - To make command-line build variables most useful, - you ideally want to provide - some help text that will describe - the available variables - when the user runs <literal>scons -h</literal>. - You could write this text by hand, - but &SCons; provides an easier way. - &Variables; objects support a - &GenerateHelpText; method - that will, as its name suggests, - generate text that describes - the various variables that - have been added to it. - You then pass the output from this method to - the &Help; function: - - </para> - - <scons_example name="Variables_Help"> - <file name="SConstruct" printme="1"> - vars = Variables(None, ARGUMENTS) - vars.Add('RELEASE', 'Set to 1 to build for release', 0) - env = Environment(variables = vars) - Help(vars.GenerateHelpText(env)) - </file> - </scons_example> - - <para> - - &SCons; will now display some useful text - when the <literal>-h</literal> option is used: - - </para> - - <scons_output example="Variables_Help"> - <scons_output_command>scons -Q -h</scons_output_command> - </scons_output> - - <para> - - Notice that the help output shows the default value, - and the current actual value of the build variable. - - </para> - - </section> - - <section> - <title>Reading Build Variables From a File</title> - - <para> - - Giving the user a way to specify the - value of a build variable on the command line - is useful, - but can still be tedious - if users must specify the variable - every time they run &SCons;. - We can let users provide customized build variable settings - in a local file by providing a - file name when we create the - &Variables; object: - - </para> - - <scons_example name="Variables_custom_py_1"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add('RELEASE', 'Set to 1 to build for release', 0) - env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) - env.Program(['foo.c', 'bar.c']) - Help(vars.GenerateHelpText(env)) - </file> - <file name="foo.c"> - foo.c - </file> - <file name="bar.c"> - bar.c - </file> - <file name="custom.py"> - RELEASE = 1 - </file> - </scons_example> - - <para> - - This then allows the user to control the &RELEASE; - variable by setting it in the &custom_py; file: - - </para> - - <scons_example_file example="Variables_custom_py_1" name="custom.py"></scons_example_file> - - <para> - - Note that this file is actually executed - like a Python script. - Now when we run &SCons;: - - </para> - - <scons_output example="Variables_custom_py_1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - And if we change the contents of &custom_py; to: - - </para> - - <scons_example name="Variables_custom_py_2"> - <file name="SConstruct"> - vars = Variables('custom.py') - vars.Add('RELEASE', 'Set to 1 to build for release', 0) - env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) - env.Program(['foo.c', 'bar.c']) - Help(vars.GenerateHelpText(env)) - </file> - <file name="foo.c"> - foo.c - </file> - <file name="bar.c"> - bar.c - </file> - <file name="custom.py" printme="1"> - RELEASE = 0 - </file> - </scons_example> - - <para> - - The object files are rebuilt appropriately - with the new variable: - - </para> - - <scons_output example="Variables_custom_py_2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Finally, you can combine both methods with: - - </para> - - <screen> - vars = Variables('custom.py', ARGUMENTS) - </screen> - - <para> - - where values in the option file &custom_py; get overwritten - by the ones specified on the command line. - - </para> - - </section> - - <section> - <title>Pre-Defined Build Variable Functions</title> - - <para> - - &SCons; provides a number of functions - that provide ready-made behaviors - for various types of command-line build variables. - - </para> - - <section> - <title>True/False Values: the &BoolVariable; Build Variable Function</title> - - <para> - - It's often handy to be able to specify a - variable that controls a simple Boolean variable - with a &true; or &false; value. - It would be even more handy to accomodate - users who have different preferences for how to represent - &true; or &false; values. - The &BoolVariable; function - makes it easy to accomodate these - common representations of - &true; or &false;. - - </para> - - <para> - - The &BoolVariable; function takes three arguments: - the name of the build variable, - the default value of the build variable, - and the help string for the variable. - It then returns appropriate information for - passing to the &Add; method of a &Variables; object, like so: - - </para> - - <scons_example name="BoolVariable"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(BoolVariable('RELEASE', 'Set to build for release', 0)) - env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - <para> - - With this build variable, - the &RELEASE; variable can now be enabled by - setting it to the value <literal>yes</literal> - or <literal>t</literal>: - - </para> - - <scons_output example="BoolVariable"> - <scons_output_command>scons -Q RELEASE=yes foo.o</scons_output_command> - </scons_output> - - <scons_output example="BoolVariable"> - <scons_output_command>scons -Q RELEASE=t foo.o</scons_output_command> - </scons_output> - - <para> - - Other values that equate to &true; include - <literal>y</literal>, - <literal>1</literal>, - <literal>on</literal> - and - <literal>all</literal>. - - </para> - - <para> - - Conversely, &RELEASE; may now be given a &false; - value by setting it to - <literal>no</literal> - or - <literal>f</literal>: - - </para> - - <scons_output example="BoolVariable"> - <scons_output_command>scons -Q RELEASE=no foo.o</scons_output_command> - </scons_output> - - <scons_output example="BoolVariable"> - <scons_output_command>scons -Q RELEASE=f foo.o</scons_output_command> - </scons_output> - - <para> - - Other values that equate to &false; include - <literal>n</literal>, - <literal>0</literal>, - <literal>off</literal> - and - <literal>none</literal>. - - </para> - - <para> - - Lastly, if a user tries to specify - any other value, - &SCons; supplies an appropriate error message: - - </para> - - <scons_output example="BoolVariable"> - <scons_output_command>scons -Q RELEASE=bad_value foo.o</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Single Value From a List: the &EnumVariable; Build Variable Function</title> - - <para> - - Suppose that we want a user to be able to - set a &COLOR; variable - that selects a background color to be - displayed by an application, - but that we want to restrict the - choices to a specific set of allowed colors. - This can be set up quite easily - using the &EnumVariable;, - which takes a list of &allowed_values; - in addition to the variable name, - default value, - and help text arguments: - - </para> - - <scons_example name="EnumVariable"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(EnumVariable('COLOR', 'Set background color', 'red', - allowed_values=('red', 'green', 'blue'))) - env = Environment(variables = vars, - CPPDEFINES={'COLOR' : '"${COLOR}"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - <para> - - The user can now explicity set the &COLOR; build variable - to any of the specified allowed values: - - </para> - - <scons_output example="EnumVariable"> - <scons_output_command>scons -Q COLOR=red foo.o</scons_output_command> - <scons_output_command>scons -Q COLOR=blue foo.o</scons_output_command> - <scons_output_command>scons -Q COLOR=green foo.o</scons_output_command> - </scons_output> - - <para> - - But, almost more importantly, - an attempt to set &COLOR; - to a value that's not in the list - generates an error message: - - </para> - - <scons_output example="EnumVariable"> - <scons_output_command>scons -Q COLOR=magenta foo.o</scons_output_command> - </scons_output> - - <para> - - The &EnumVariable; function also supports a way - to map alternate names to allowed values. - Suppose, for example, - that we want to allow the user - to use the word <literal>navy</literal> as a synonym for - <literal>blue</literal>. - We do this by adding a ↦ dictionary - that will map its key values - to the desired legal value: - - </para> - - <scons_example name="EnumVariable_map"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(EnumVariable('COLOR', 'Set background color', 'red', - allowed_values=('red', 'green', 'blue'), - map={'navy':'blue'})) - env = Environment(variables = vars, - CPPDEFINES={'COLOR' : '"${COLOR}"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - <para> - - As desired, the user can then use - <literal>navy</literal> on the command line, - and &SCons; will translate it into <literal>blue</literal> - when it comes time to use the &COLOR; - variable to build a target: - - </para> - - <scons_output example="EnumVariable_map"> - <scons_output_command>scons -Q COLOR=navy foo.o</scons_output_command> - </scons_output> - - <para> - - By default, when using the &EnumVariable; function, - arguments that differ - from the legal values - only in case - are treated as illegal values: - - </para> - - <scons_output example="EnumVariable"> - <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command> - <scons_output_command>scons -Q COLOR=BLUE foo.o</scons_output_command> - <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command> - </scons_output> - - <para> - - The &EnumVariable; function can take an additional - &ignorecase; keyword argument that, - when set to <literal>1</literal>, - tells &SCons; to allow case differences - when the values are specified: - - </para> - - <scons_example name="EnumVariable_ic1"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(EnumVariable('COLOR', 'Set background color', 'red', - allowed_values=('red', 'green', 'blue'), - map={'navy':'blue'}, - ignorecase=1)) - env = Environment(variables = vars, - CPPDEFINES={'COLOR' : '"${COLOR}"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - <para> - - Which yields the output: - - </para> - - <scons_output example="EnumVariable_ic1"> - <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command> - <scons_output_command>scons -Q COLOR=BLUE foo.o</scons_output_command> - <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command> - <scons_output_command>scons -Q COLOR=green foo.o</scons_output_command> - </scons_output> - - <para> - - Notice that an &ignorecase; value of <literal>1</literal> - preserves the case-spelling that the user supplied. - If you want &SCons; to translate the names - into lower-case, - regardless of the case used by the user, - specify an &ignorecase; value of <literal>2</literal>: - - </para> - - <scons_example name="EnumVariable_ic2"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(EnumVariable('COLOR', 'Set background color', 'red', - allowed_values=('red', 'green', 'blue'), - map={'navy':'blue'}, - ignorecase=2)) - env = Environment(variables = vars, - CPPDEFINES={'COLOR' : '"${COLOR}"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - <para> - - Now &SCons; will use values of - <literal>red</literal>, - <literal>green</literal> or - <literal>blue</literal> - regardless of how the user spells - those values on the command line: - - </para> - - <scons_output example="EnumVariable_ic2"> - <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command> - <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command> - <scons_output_command>scons -Q COLOR=GREEN foo.o</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Multiple Values From a List: the &ListVariable; Build Variable Function</title> - - <para> - - Another way in which you might want to allow users - to control a build variable is to - specify a list of one or more legal values. - &SCons; supports this through the &ListVariable; function. - If, for example, we want a user to be able to set a - &COLORS; variable to one or more of the legal list of values: - - </para> - - <scons_example name="ListVariable"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(ListVariable('COLORS', 'List of colors', 0, - ['red', 'green', 'blue'])) - env = Environment(variables = vars, - CPPDEFINES={'COLORS' : '"${COLORS}"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - <para> - - A user can now specify a comma-separated list - of legal values, - which will get translated into a space-separated - list for passing to the any build commands: - - </para> - - <scons_output example="ListVariable"> - <scons_output_command>scons -Q COLORS=red,blue foo.o</scons_output_command> - <scons_output_command>scons -Q COLORS=blue,green,red foo.o</scons_output_command> - </scons_output> - - <para> - - In addition, the &ListVariable; function - allows the user to specify explicit keywords of - &all; or &none; - to select all of the legal values, - or none of them, respectively: - - </para> - - <scons_output example="ListVariable"> - <scons_output_command>scons -Q COLORS=all foo.o</scons_output_command> - <scons_output_command>scons -Q COLORS=none foo.o</scons_output_command> - </scons_output> - - <para> - - And, of course, an illegal value - still generates an error message: - - </para> - - <scons_output example="ListVariable"> - <scons_output_command>scons -Q COLORS=magenta foo.o</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Path Names: the &PathVariable; Build Variable Function</title> - - <para> - - &SCons; supports a &PathVariable; function - to make it easy to create a build variable - to control an expected path name. - If, for example, you need to - define a variable in the preprocessor - that controls the location of a - configuration file: - - </para> - - <scons_example name="PathVariable"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(PathVariable('CONFIG', - 'Path to configuration file', - '__ROOT__/etc/my_config')) - env = Environment(variables = vars, - CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - <file name="__ROOT__/etc/my_config"> - /opt/location - </file> - <file name="__ROOT__/usr/local/etc/other_config"> - /opt/location - </file> - </scons_example> - - <para> - - This then allows the user to - override the &CONFIG; build variable - on the command line as necessary: - - </para> - - <scons_output example="PathVariable"> - <scons_output_command>scons -Q foo.o</scons_output_command> - <scons_output_command>scons -Q CONFIG=__ROOT__/usr/local/etc/other_config foo.o</scons_output_command> - </scons_output> - - <para> - - By default, &PathVariable; checks to make sure - that the specified path exists and generates an error if it - doesn't: - - </para> - - <scons_output example="PathVariable"> - <scons_output_command>scons -Q CONFIG=__ROOT__/does/not/exist foo.o</scons_output_command> - </scons_output> - - <para> - - &PathVariable; provides a number of methods - that you can use to change this behavior. - If you want to ensure that any specified paths are, - in fact, files and not directories, - use the &PathVariable_PathIsFile; method: - - </para> - - <scons_example name="PathIsFile"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(PathVariable('CONFIG', - 'Path to configuration file', - '__ROOT__/etc/my_config', - PathVariable.PathIsFile)) - env = Environment(variables = vars, - CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - <file name="__ROOT__/etc/my_config"> - /opt/location - </file> - </scons_example> - - <para> - - Conversely, to ensure that any specified paths are - directories and not files, - use the &PathVariable_PathIsDir; method: - - </para> - - <scons_example name="PathIsDir"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(PathVariable('DBDIR', - 'Path to database directory', - '__ROOT__/var/my_dbdir', - PathVariable.PathIsDir)) - env = Environment(variables = vars, - CPPDEFINES={'DBDIR' : '"$DBDIR"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - <file name="__ROOT__/var/my_dbdir"> - /opt/location - </file> - </scons_example> - - <para> - - If you want to make sure that any specified paths - are directories, - and you would like the directory created - if it doesn't already exist, - use the &PathVariable_PathIsDirCreate; method: - - </para> - - <scons_example name="PathIsDirCreate"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(PathVariable('DBDIR', - 'Path to database directory', - '__ROOT__/var/my_dbdir', - PathVariable.PathIsDirCreate)) - env = Environment(variables = vars, - CPPDEFINES={'DBDIR' : '"$DBDIR"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - <file name="__ROOT__/var/my_dbdir"> - /opt/location - </file> - </scons_example> - - <para> - - Lastly, if you don't care whether the path exists, - is a file, or a directory, - use the &PathVariable_PathAccept; method - to accept any path that the user supplies: - - </para> - - <scons_example name="PathAccept"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(PathVariable('OUTPUT', - 'Path to output file or directory', - None, - PathVariable.PathAccept)) - env = Environment(variables = vars, - CPPDEFINES={'OUTPUT' : '"$OUTPUT"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - </section> - - <section> - <title>Enabled/Disabled Path Names: the &PackageVariable; Build Variable Function</title> - - <para> - - Sometimes you want to give users - even more control over a path name variable, - allowing them to explicitly enable or - disable the path name - by using <literal>yes</literal> or <literal>no</literal> keywords, - in addition to allow them - to supply an explicit path name. - &SCons; supports the &PackageVariable; - function to support this: - - </para> - - <scons_example name="PackageVariable"> - <file name="SConstruct" printme="1"> - vars = Variables('custom.py') - vars.Add(PackageVariable('PACKAGE', - 'Location package', - '__ROOT__/opt/location')) - env = Environment(variables = vars, - CPPDEFINES={'PACKAGE' : '"$PACKAGE"'}) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - <file name="__ROOT__/opt/location"> - /opt/location - </file> - <file name="__ROOT__/usr/local/location"> - /opt/location - </file> - </scons_example> - - <para> - - When the &SConscript; file uses the &PackageVariable; funciton, - user can now still use the default - or supply an overriding path name, - but can now explicitly set the - specified variable to a value - that indicates the package should be enabled - (in which case the default should be used) - or disabled: - - </para> - - <scons_output example="PackageVariable"> - <scons_output_command>scons -Q foo.o</scons_output_command> - <scons_output_command>scons -Q PACKAGE=__ROOT__/usr/local/location foo.o</scons_output_command> - <scons_output_command>scons -Q PACKAGE=yes foo.o</scons_output_command> - <scons_output_command>scons -Q PACKAGE=no foo.o</scons_output_command> - </scons_output> - - </section> - - </section> - - <section> - <title>Adding Multiple Command-Line Build Variables at Once</title> - - <para> - - Lastly, &SCons; provides a way to add - multiple build variables to a &Variables; object at once. - Instead of having to call the &Add; method - multiple times, - you can call the &AddVariables; - method with a list of build variables - to be added to the object. - Each build variable is specified - as either a tuple of arguments, - just like you'd pass to the &Add; method itself, - or as a call to one of the pre-defined - functions for pre-packaged command-line build variables. - in any order: - - </para> - - <scons_example name="AddVariables_1"> - <file name="SConstruct" printme="1"> - vars = Variables() - vars.AddVariables( - ('RELEASE', 'Set to 1 to build for release', 0), - ('CONFIG', 'Configuration file', '/etc/my_config'), - BoolVariable('warnings', 'compilation with -Wall and similiar', 1), - EnumVariable('debug', 'debug output and symbols', 'no', - allowed_values=('yes', 'no', 'full'), - map={}, ignorecase=0), # case sensitive - ListVariable('shared', - 'libraries to build as shared libraries', - 'all', - names = list_of_libs), - PackageVariable('x11', - 'use X11 installed here (yes = search some places)', - 'yes'), - PathVariable('qtdir', 'where the root of Qt is installed', qtdir), - ) - </file> - </scons_example> - - <para> - </para> - - </section> - - <section> - <title>Handling Unknown Command-Line Build Variables: the &UnknownVariables; Function</title> - - <para> - - Users may, of course, - occasionally misspell variable names in their command-line settings. - &SCons; does not generate an error or warning - for any unknown variables the users specifies on the command line. - (This is in no small part because you may be - processing the arguments directly using the &ARGUMENTS; dictionary, - and therefore &SCons; can't know in the general case - whether a given "misspelled" variable is - really unknown and a potential problem, - or something that your &SConscript; file - will handle directly with some Python code.) - - </para> - - <para> - - If, however, you're using a &Variables; object to - define a specific set of command-line build variables - that you expect users to be able to set, - you may want to provide an error - message or warning of your own - if the user supplies a variable setting - that is <emphasis>not</emphasis> among - the defined list of variable names known to the &Variables; object. - You can do this by calling the &UnknownVariables; - method of the &Variables; object: - - </para> - - <scons_example name="UnknownVariables"> - <file name="SConstruct" printme="1"> - vars = Variables(None) - vars.Add('RELEASE', 'Set to 1 to build for release', 0) - env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) - unknown = vars.UnknownVariables() - if unknown: - print "Unknown variables:", unknown.keys() - Exit(1) - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - <para> - - The &UnknownVariables; method returns a dictionary - containing the keywords and values - of any variables the user specified on the command line - that are <emphasis>not</emphasis> - among the variables known to the &Variables; object - (from having been specified using - the &Variables; object's&Add; method). - In the examble above, - we check for whether the dictionary - returned by the &UnknownVariables; is non-empty, - and if so print the Python list - containing the names of the unknwown variables - and then call the &Exit; function - to terminate &SCons;: - - </para> - - <scons_output example="UnknownVariables"> - <scons_output_command>scons -Q NOT_KNOWN=foo</scons_output_command> - </scons_output> - - <para> - - Of course, you can process the items in the - dictionary returned by the &UnknownVariables; function - in any way appropriate to your build configuration, - including just printing a warning message - but not exiting, - logging an error somewhere, - etc. - - </para> - - <para> - - Note that you must delay the call of &UnknownVariables; - until after you have applied the &Variables; object - to a construction environment - with the <literal>variables=</literal> - keyword argument of an &Environment; call. - - </para> - - </section> - - </section> - - <section id="sect-command-line-targets"> - <title>Command-Line Targets</title> - - <section> - <title>Fetching Command-Line Targets: the &COMMAND_LINE_TARGETS; Variable</title> - - <para> - - &SCons; supports a &COMMAND_LINE_TARGETS; variable - that lets you fetch the list of targets that the - user specified on the command line. - You can use the targets to manipulate the - build in any way you wish. - As a simple example, - suppose that you want to print a reminder - to the user whenever a specific program is built. - You can do this by checking for the - target in the &COMMAND_LINE_TARGETS; list: - - </para> - - <scons_example name="COMMAND_LINE_TARGETS"> - <file name="SConstruct" printme="1"> - if 'bar' in COMMAND_LINE_TARGETS: - print "Don't forget to copy `bar' to the archive!" - Default(Program('foo.c')) - Program('bar.c') - </file> - <file name="foo.c"> - foo.c - </file> - <file name="bar.c"> - foo.c - </file> - </scons_example> - - <para> - - Then, running &SCons; with the default target - works as it always does, - but explicity specifying the &bar; target - on the command line generates the warning message: - - </para> - - <scons_output example="COMMAND_LINE_TARGETS"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q bar</scons_output_command> - </scons_output> - - <para> - - Another practical use for the &COMMAND_LINE_TARGETS; variable - might be to speed up a build - by only reading certain subsidiary &SConscript; - files if a specific target is requested. - - </para> - - </section> - - <section> - <title>Controlling the Default Targets: the &Default; Function</title> - - <para> - - One of the most basic things you can control - is which targets &SCons; will build by default--that is, - when there are no targets specified on the command line. - As mentioned previously, - &SCons; will normally build every target - in or below the current directory - by default--that is, when you don't - explicitly specify one or more targets - on the command line. - Sometimes, however, you may want - to specify explicitly that only - certain programs, or programs in certain directories, - should be built by default. - You do this with the &Default; function: - - </para> - - <scons_example name="Default1"> - <file name="SConstruct" printme="1"> - env = Environment() - hello = env.Program('hello.c') - env.Program('goodbye.c') - Default(hello) - </file> - <file name="hello.c"> - hello.c - </file> - <file name="goodbye.c"> - goodbye.c - </file> - </scons_example> - - <para> - - This &SConstruct; file knows how to build two programs, - &hello; and &goodbye;, - but only builds the - &hello; program by default: - - </para> - - <scons_output example="Default1"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q goodbye</scons_output_command> - </scons_output> - - <para> - - Note that, even when you use the &Default; - function in your &SConstruct; file, - you can still explicitly specify the current directory - (<literal>.</literal>) on the command line - to tell &SCons; to build - everything in (or below) the current directory: - - </para> - - <scons_output example="Default1"> - <scons_output_command>scons -Q .</scons_output_command> - </scons_output> - - <para> - - You can also call the &Default; - function more than once, - in which case each call - adds to the list of targets to be built by default: - - </para> - - <scons_example name="Default2"> - <file name="SConstruct" printme="1"> - env = Environment() - prog1 = env.Program('prog1.c') - Default(prog1) - prog2 = env.Program('prog2.c') - prog3 = env.Program('prog3.c') - Default(prog3) - </file> - <file name="prog1.c"> - prog1.c - </file> - <file name="prog2.c"> - prog2.c - </file> - <file name="prog3.c"> - prog3.c - </file> - </scons_example> - - <para> - - Or you can specify more than one target - in a single call to the &Default; function: - - </para> - - <programlisting> - env = Environment() - prog1 = env.Program('prog1.c') - prog2 = env.Program('prog2.c') - prog3 = env.Program('prog3.c') - Default(prog1, prog3) - </programlisting> - - <para> - - Either of these last two examples - will build only the - <application>prog1</application> - and - <application>prog3</application> - programs by default: - - </para> - - <scons_output example="Default2"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q .</scons_output_command> - </scons_output> - - <para> - - You can list a directory as - an argument to &Default;: - - </para> - - <scons_example name="Default3"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Program(['prog1/main.c', 'prog1/foo.c']) - env.Program(['prog2/main.c', 'prog2/bar.c']) - Default('prog1') - </file> - <directory name="prog1"></directory> - <directory name="prog2"></directory> - <file name="prog1/main.c"> - int main() { printf("prog1/main.c\n"); } - </file> - <file name="prog1/foo.c"> - int foo() { printf("prog1/foo.c\n"); } - </file> - <file name="prog2/main.c"> - int main() { printf("prog2/main.c\n"); } - </file> - <file name="prog2/bar.c"> - int bar() { printf("prog2/bar.c\n"); } - </file> - </scons_example> - - <para> - - In which case only the target(s) in that - directory will be built by default: - - </para> - - <scons_output example="Default3"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q .</scons_output_command> - </scons_output> - - <para> - - Lastly, if for some reason you don't want - any targets built by default, - you can use the Python <literal>None</literal> - variable: - - </para> - - <scons_example name="Default4"> - <file name="SConstruct" printme="1"> - env = Environment() - prog1 = env.Program('prog1.c') - prog2 = env.Program('prog2.c') - Default(None) - </file> - <file name="prog1.c"> - prog1.c - </file> - <file name="prog2.c"> - prog2.c - </file> - </scons_example> - - <para> - - Which would produce build output like: - - </para> - - <scons_output example="Default4"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q .</scons_output_command> - </scons_output> - - <section> - <title>Fetching the List of Default Targets: the &DEFAULT_TARGETS; Variable</title> - - <para> - - &SCons; supports a &DEFAULT_TARGETS; variable - that lets you get at the current list of default targets. - The &DEFAULT_TARGETS; variable has - two important differences from the &COMMAND_LINE_TARGETS; variable. - First, the &DEFAULT_TARGETS; variable is a list of - internal &SCons; nodes, - so you need to convert the list elements to strings - if you want to print them or look for a specific target name. - Fortunately, you can do this easily - by using the Python <function>map</function> function - to run the list through <function>str</function>: - - </para> - - <scons_example name="DEFAULT_TARGETS_1"> - <file name="SConstruct" printme="1"> - prog1 = Program('prog1.c') - Default(prog1) - print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS) - </file> - <file name="prog1.c"> - prog1.c - </file> - </scons_example> - - <para> - - (Keep in mind that all of the manipulation of the - &DEFAULT_TARGETS; list takes place during the - first phase when &SCons; is reading up the &SConscript; files, - which is obvious if - we leave off the <literal>-Q</literal> flag when we run &SCons;:) - - </para> - - <scons_output example="DEFAULT_TARGETS_1"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - Second, - the contents of the &DEFAULT_TARGETS; list change - in response to calls to the &Default; function, - as you can see from the following &SConstruct; file: - - </para> - - <scons_example name="DEFAULT_TARGETS_2"> - <file name="SConstruct" printme="1"> - prog1 = Program('prog1.c') - Default(prog1) - print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) - prog2 = Program('prog2.c') - Default(prog2) - print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) - </file> - <file name="prog1.c"> - prog1.c - </file> - <file name="prog2.c"> - prog2.c - </file> - </scons_example> - - <para> - - Which yields the output: - - </para> - - <scons_output example="DEFAULT_TARGETS_2"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - In practice, this simply means that you - need to pay attention to the order in - which you call the &Default; function - and refer to the &DEFAULT_TARGETS; list, - to make sure that you don't examine the - list before you've added the default targets - you expect to find in it. - - </para> - - </section> - - </section> - - <section> - <title>Fetching the List of Build Targets, Regardless of Origin: the &BUILD_TARGETS; Variable</title> - - <para> - - We've already been introduced to the - &COMMAND_LINE_TARGETS; variable, - which contains a list of targets specified on the command line, - and the &DEFAULT_TARGETS; variable, - which contains a list of targets specified - via calls to the &Default; method or function. - Sometimes, however, - you want a list of whatever targets - &SCons; will try to build, - regardless of whether the targets came from the - command line or a &Default; call. - You could code this up by hand, as follows: - - </para> - - <sconstruct> - if COMMAND_LINE_TARGETS: - targets = COMMAND_LINE_TARGETS - else: - targets = DEFAULT_TARGETS - </sconstruct> - - <para> - - &SCons;, however, provides a convenient - &BUILD_TARGETS; variable - that eliminates the need for this by-hand manipulation. - Essentially, the &BUILD_TARGETS; variable - contains a list of the command-line targets, - if any were specified, - and if no command-line targets were specified, - it contains a list of the targets specified - via the &Default; method or function. - - </para> - - <para> - - Because &BUILD_TARGETS; may contain a list of &SCons; nodes, - you must convert the list elements to strings - if you want to print them or look for a specific target name, - just like the &DEFAULT_TARGETS; list: - - </para> - - <scons_example name="BUILD_TARGETS_1"> - <file name="SConstruct" printme="1"> - prog1 = Program('prog1.c') - Program('prog2.c') - Default(prog1) - print "BUILD_TARGETS is", map(str, BUILD_TARGETS) - </file> - <file name="prog1.c"> - prog1.c - </file> - <file name="prog2.c"> - prog2.c - </file> - </scons_example> - - <para> - - Notice how the value of &BUILD_TARGETS; - changes depending on whether a target is - specified on the command line: - - </para> - - <scons_output example="BUILD_TARGETS_1"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q prog2</scons_output_command> - <scons_output_command>scons -Q -c .</scons_output_command> - </scons_output> - - </section> - - </section> diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml index 1006c6b..33f88ec 100644 --- a/doc/user/command-line.xml +++ b/doc/user/command-line.xml @@ -146,19 +146,26 @@ </para> - - - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - ... [build output] ... - scons: done building targets. - % <userinput>export SCONSFLAGS="-Q"</userinput> - % <userinput>scons</userinput> - ... [build output] ... - </screen> + <scons_example name="SCONSFLAGS"> + <file name="SConstruct"> + def b(target, source, env): + pass + def s(target, source, env): + return " ... [build output] ..." + a = Action(b, strfunction = s) + env = Environment(BUILDERS = {'A' : Builder(action=a)}) + env.A('foo.out', 'foo.in') + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> + + <scons_output example="SCONSFLAGS"> + <scons_output_command>scons</scons_output_command> + <scons_output_command>export SCONSFLAGS="-Q"</scons_output_command> + <scons_output_command environment="SCONSFLAGS=-Q">scons</scons_output_command> + </scons_output> <para> @@ -214,10 +221,10 @@ </para> - <programlisting> + <sconstruct> if not GetOption('help'): SConscript('src/SConscript', export='env') - </programlisting> + </sconstruct> <para> @@ -283,12 +290,17 @@ </para> - <programlisting> + <scons_example name="SetOption"> + <file name="SConstruct" printme="1"> import os num_cpu = int(os.environ.get('NUM_CPU', 2)) SetOption('num_jobs', num_cpu) print "running with -j", GetOption('num_jobs') - </programlisting> + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> <para> @@ -310,11 +322,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - running with -j 2 - scons: `.' is up to date. - </screen> + <scons_output example="SetOption"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -324,12 +334,10 @@ </para> - <screen> - % <userinput>export NUM_CPU="4"</userinput> - % <userinput>scons -Q</userinput> - running with -j 4 - scons: `.' is up to date. - </screen> + <scons_output example="SetOption"> + <scons_output_command>export NUM_CPU="4"</scons_output_command> + <scons_output_command environment="NUM_CPU=4">scons -Q</scons_output_command> + </scons_output> <para> @@ -342,15 +350,11 @@ </para> - <screen> - % <userinput>scons -Q -j 7</userinput> - running with -j 7 - scons: `.' is up to date. - % <userinput>export NUM_CPU="4"</userinput> - % <userinput>scons -Q -j 3</userinput> - running with -j 3 - scons: `.' is up to date. - </screen> + <scons_output example="SetOption"> + <scons_output_command>scons -Q -j 7</scons_output_command> + <scons_output_command>export NUM_CPU="4"</scons_output_command> + <scons_output_command environment="NUM_CPU=4">scons -Q -j 3</scons_output_command> + </scons_output> </section> @@ -600,7 +604,8 @@ </para> - <programlisting> + <scons_example name="AddOption"> + <file name="SConstruct" printme="1"> AddOption('--prefix', dest='prefix', type='string', @@ -613,7 +618,11 @@ installed_foo = env.Install('$PREFIX/usr/bin', 'foo.in') Default(installed_foo) - </programlisting> + </file> + <file name="foo.in"> + foo.in + </file> + </scons_example> <para> @@ -631,10 +640,9 @@ </para> - <screen> - % <userinput>scons -Q -n</userinput> - Install file: "foo.in" as "/usr/bin/foo.in" - </screen> + <scons_output example="AddOption"> + <scons_output_command>scons -Q -n</scons_output_command> + </scons_output> <para> @@ -644,10 +652,9 @@ </para> - <screen> - % <userinput>scons -Q -n --prefix=/tmp/install</userinput> - Install file: "foo.in" as "/tmp/install/usr/bin/foo.in" - </screen> + <scons_output example="AddOption"> + <scons_output_command>scons -Q -n --prefix=/tmp/install</scons_output_command> + </scons_output> </section> @@ -702,13 +709,18 @@ </para> - <programlisting> + <scons_example name="ARGUMENTS"> + <file name="SConstruct" printme="1"> env = Environment() debug = ARGUMENTS.get('debug', 0) if int(debug): env.Append(CCFLAGS = '-g') env.Program('prog.c') - </programlisting> + </file> + <file name="prog.c"> + prog.c + </file> + </scons_example> <para> @@ -719,18 +731,12 @@ </para> - <screen> - % <userinput>scons -Q debug=0</userinput> - cc -o prog.o -c prog.c - cc -o prog prog.o - % <userinput>scons -Q debug=0</userinput> - scons: `.' is up to date. - % <userinput>scons -Q debug=1</userinput> - cc -o prog.o -c -g prog.c - cc -o prog prog.o - % <userinput>scons -Q debug=1</userinput> - scons: `.' is up to date. - </screen> + <scons_output example="ARGUMENTS"> + <scons_output_command>scons -Q debug=0</scons_output_command> + <scons_output_command>scons -Q debug=0</scons_output_command> + <scons_output_command>scons -Q debug=1</scons_output_command> + <scons_output_command>scons -Q debug=1</scons_output_command> + </scons_output> <para> @@ -792,14 +798,19 @@ </para> - <programlisting> + <scons_example name="ARGLIST"> + <file name="SConstruct" printme="1"> cppdefines = [] for key, value in ARGLIST: if key == 'define': cppdefines.append(value) env = Environment(CPPDEFINES = cppdefines) env.Object('prog.c') - </programlisting> + </file> + <file name="prog.c"> + prog.c + </file> + </scons_example> <para> @@ -807,12 +818,10 @@ </para> - <screen> - % <userinput>scons -Q define=FOO</userinput> - cc -o prog.o -c -DFOO prog.c - % <userinput>scons -Q define=FOO define=BAR</userinput> - cc -o prog.o -c -DFOO -DBAR prog.c - </screen> + <scons_output example="ARGLIST"> + <scons_output_command>scons -Q define=FOO</scons_output_command> + <scons_output_command>scons -Q define=FOO define=BAR</scons_output_command> + </scons_output> <para> @@ -874,13 +883,21 @@ </para> - <programlisting> + <scons_example name="Variables1"> + <file name="SConstruct" printme="1"> vars = Variables(None, ARGUMENTS) vars.Add('RELEASE', 'Set to 1 to build for release', 0) env = Environment(variables = vars, CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) env.Program(['foo.c', 'bar.c']) - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + <file name="bar.c"> + bar.c + </file> + </scons_example> <para> @@ -911,12 +928,9 @@ </para> - <screen> - % <userinput>scons -Q RELEASE=1</userinput> - cc -o bar.o -c -DRELEASE_BUILD=1 bar.c - cc -o foo.o -c -DRELEASE_BUILD=1 foo.c - cc -o foo foo.o bar.o - </screen> + <scons_output example="Variables1"> + <scons_output_command>scons -Q RELEASE=1</scons_output_command> + </scons_output> <para> @@ -960,12 +974,14 @@ </para> - <programlisting> + <scons_example name="Variables_Help"> + <file name="SConstruct" printme="1"> vars = Variables(None, ARGUMENTS) vars.Add('RELEASE', 'Set to 1 to build for release', 0) env = Environment(variables = vars) Help(vars.GenerateHelpText(env)) - </programlisting> + </file> + </scons_example> <para> @@ -974,15 +990,9 @@ </para> - <screen> - % <userinput>scons -Q -h</userinput> - - RELEASE: Set to 1 to build for release - default: 0 - actual: 0 - - Use scons -H for help about command-line options. - </screen> + <scons_output example="Variables_Help"> + <scons_output_command>scons -Q -h</scons_output_command> + </scons_output> <para> @@ -1011,14 +1021,25 @@ </para> - <programlisting> + <scons_example name="Variables_custom_py_1"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add('RELEASE', 'Set to 1 to build for release', 0) env = Environment(variables = vars, CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) env.Program(['foo.c', 'bar.c']) Help(vars.GenerateHelpText(env)) - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + <file name="bar.c"> + bar.c + </file> + <file name="custom.py"> + RELEASE = 1 + </file> + </scons_example> <para> @@ -1027,9 +1048,7 @@ </para> - <programlisting> - RELEASE = 1 - </programlisting> + <scons_example_file example="Variables_custom_py_1" name="custom.py"></scons_example_file> <para> @@ -1039,12 +1058,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o bar.o -c -DRELEASE_BUILD=1 bar.c - cc -o foo.o -c -DRELEASE_BUILD=1 foo.c - cc -o foo foo.o bar.o - </screen> + <scons_output example="Variables_custom_py_1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1052,9 +1068,25 @@ </para> - <programlisting> + <scons_example name="Variables_custom_py_2"> + <file name="SConstruct"> + vars = Variables('custom.py') + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + Help(vars.GenerateHelpText(env)) + </file> + <file name="foo.c"> + foo.c + </file> + <file name="bar.c"> + bar.c + </file> + <file name="custom.py" printme="1"> RELEASE = 0 - </programlisting> + </file> + </scons_example> <para> @@ -1063,12 +1095,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o bar.o -c -DRELEASE_BUILD=0 bar.c - cc -o foo.o -c -DRELEASE_BUILD=0 foo.c - cc -o foo foo.o bar.o - </screen> + <scons_output example="Variables_custom_py_2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1129,13 +1158,18 @@ </para> - <programlisting> + <scons_example name="BoolVariable"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(BoolVariable('RELEASE', 'Set to build for release', 0)) env = Environment(variables = vars, CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> <para> @@ -1146,15 +1180,13 @@ </para> - <screen> - % <userinput>scons -Q RELEASE=yes foo.o</userinput> - cc -o foo.o -c -DRELEASE_BUILD=True foo.c - </screen> + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=yes foo.o</scons_output_command> + </scons_output> - <screen> - % <userinput>scons -Q RELEASE=t foo.o</userinput> - cc -o foo.o -c -DRELEASE_BUILD=True foo.c - </screen> + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=t foo.o</scons_output_command> + </scons_output> <para> @@ -1177,15 +1209,13 @@ </para> - <screen> - % <userinput>scons -Q RELEASE=no foo.o</userinput> - cc -o foo.o -c -DRELEASE_BUILD=False foo.c - </screen> + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=no foo.o</scons_output_command> + </scons_output> - <screen> - % <userinput>scons -Q RELEASE=f foo.o</userinput> - cc -o foo.o -c -DRELEASE_BUILD=False foo.c - </screen> + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=f foo.o</scons_output_command> + </scons_output> <para> @@ -1206,13 +1236,9 @@ </para> - <screen> - % <userinput>scons -Q RELEASE=bad_value foo.o</userinput> - - scons: *** Error converting option: RELEASE - Invalid value for boolean option: bad_value - File "/home/my/project/SConstruct", line 4, in <module> - </screen> + <scons_output example="BoolVariable"> + <scons_output_command>scons -Q RELEASE=bad_value foo.o</scons_output_command> + </scons_output> </section> @@ -1236,14 +1262,19 @@ </para> - <programlisting> + <scons_example name="EnumVariable"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(EnumVariable('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'))) env = Environment(variables = vars, CPPDEFINES={'COLOR' : '"${COLOR}"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> <para> @@ -1252,14 +1283,11 @@ </para> - <screen> - % <userinput>scons -Q COLOR=red foo.o</userinput> - cc -o foo.o -c -DCOLOR="red" foo.c - % <userinput>scons -Q COLOR=blue foo.o</userinput> - cc -o foo.o -c -DCOLOR="blue" foo.c - % <userinput>scons -Q COLOR=green foo.o</userinput> - cc -o foo.o -c -DCOLOR="green" foo.c - </screen> + <scons_output example="EnumVariable"> + <scons_output_command>scons -Q COLOR=red foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=blue foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=green foo.o</scons_output_command> + </scons_output> <para> @@ -1270,12 +1298,9 @@ </para> - <screen> - % <userinput>scons -Q COLOR=magenta foo.o</userinput> - - scons: *** Invalid value for option COLOR: magenta. Valid values are: ('red', 'green', 'blue') - File "/home/my/project/SConstruct", line 5, in <module> - </screen> + <scons_output example="EnumVariable"> + <scons_output_command>scons -Q COLOR=magenta foo.o</scons_output_command> + </scons_output> <para> @@ -1291,7 +1316,8 @@ </para> - <programlisting> + <scons_example name="EnumVariable_map"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(EnumVariable('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'), @@ -1299,7 +1325,11 @@ env = Environment(variables = vars, CPPDEFINES={'COLOR' : '"${COLOR}"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> <para> @@ -1311,10 +1341,9 @@ </para> - <screen> - % <userinput>scons -Q COLOR=navy foo.o</userinput> - cc -o foo.o -c -DCOLOR="blue" foo.c - </screen> + <scons_output example="EnumVariable_map"> + <scons_output_command>scons -Q COLOR=navy foo.o</scons_output_command> + </scons_output> <para> @@ -1326,20 +1355,11 @@ </para> - <screen> - % <userinput>scons -Q COLOR=Red foo.o</userinput> - - scons: *** Invalid value for option COLOR: Red. Valid values are: ('red', 'green', 'blue') - File "/home/my/project/SConstruct", line 5, in <module> - % <userinput>scons -Q COLOR=BLUE foo.o</userinput> - - scons: *** Invalid value for option COLOR: BLUE. Valid values are: ('red', 'green', 'blue') - File "/home/my/project/SConstruct", line 5, in <module> - % <userinput>scons -Q COLOR=nAvY foo.o</userinput> - - scons: *** Invalid value for option COLOR: nAvY. Valid values are: ('red', 'green', 'blue') - File "/home/my/project/SConstruct", line 5, in <module> - </screen> + <scons_output example="EnumVariable"> + <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=BLUE foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command> + </scons_output> <para> @@ -1351,7 +1371,8 @@ </para> - <programlisting> + <scons_example name="EnumVariable_ic1"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(EnumVariable('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'), @@ -1360,7 +1381,11 @@ env = Environment(variables = vars, CPPDEFINES={'COLOR' : '"${COLOR}"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> <para> @@ -1368,16 +1393,12 @@ </para> - <screen> - % <userinput>scons -Q COLOR=Red foo.o</userinput> - cc -o foo.o -c -DCOLOR="Red" foo.c - % <userinput>scons -Q COLOR=BLUE foo.o</userinput> - cc -o foo.o -c -DCOLOR="BLUE" foo.c - % <userinput>scons -Q COLOR=nAvY foo.o</userinput> - cc -o foo.o -c -DCOLOR="blue" foo.c - % <userinput>scons -Q COLOR=green foo.o</userinput> - cc -o foo.o -c -DCOLOR="green" foo.c - </screen> + <scons_output example="EnumVariable_ic1"> + <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=BLUE foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=green foo.o</scons_output_command> + </scons_output> <para> @@ -1390,7 +1411,8 @@ </para> - <programlisting> + <scons_example name="EnumVariable_ic2"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(EnumVariable('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'), @@ -1399,7 +1421,11 @@ env = Environment(variables = vars, CPPDEFINES={'COLOR' : '"${COLOR}"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> <para> @@ -1412,14 +1438,11 @@ </para> - <screen> - % <userinput>scons -Q COLOR=Red foo.o</userinput> - cc -o foo.o -c -DCOLOR="red" foo.c - % <userinput>scons -Q COLOR=nAvY foo.o</userinput> - cc -o foo.o -c -DCOLOR="blue" foo.c - % <userinput>scons -Q COLOR=GREEN foo.o</userinput> - cc -o foo.o -c -DCOLOR="green" foo.c - </screen> + <scons_output example="EnumVariable_ic2"> + <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command> + <scons_output_command>scons -Q COLOR=GREEN foo.o</scons_output_command> + </scons_output> </section> @@ -1437,14 +1460,19 @@ </para> - <programlisting> + <scons_example name="ListVariable"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(ListVariable('COLORS', 'List of colors', 0, ['red', 'green', 'blue'])) env = Environment(variables = vars, CPPDEFINES={'COLORS' : '"${COLORS}"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> <para> @@ -1455,12 +1483,10 @@ </para> - <screen> - % <userinput>scons -Q COLORS=red,blue foo.o</userinput> - cc -o foo.o -c -DCOLORS="red blue" foo.c - % <userinput>scons -Q COLORS=blue,green,red foo.o</userinput> - cc -o foo.o -c -DCOLORS="blue green red" foo.c - </screen> + <scons_output example="ListVariable"> + <scons_output_command>scons -Q COLORS=red,blue foo.o</scons_output_command> + <scons_output_command>scons -Q COLORS=blue,green,red foo.o</scons_output_command> + </scons_output> <para> @@ -1472,12 +1498,10 @@ </para> - <screen> - % <userinput>scons -Q COLORS=all foo.o</userinput> - cc -o foo.o -c -DCOLORS="red green blue" foo.c - % <userinput>scons -Q COLORS=none foo.o</userinput> - cc -o foo.o -c -DCOLORS="" foo.c - </screen> + <scons_output example="ListVariable"> + <scons_output_command>scons -Q COLORS=all foo.o</scons_output_command> + <scons_output_command>scons -Q COLORS=none foo.o</scons_output_command> + </scons_output> <para> @@ -1486,13 +1510,9 @@ </para> - <screen> - % <userinput>scons -Q COLORS=magenta foo.o</userinput> - - scons: *** Error converting option: COLORS - Invalid value(s) for option: magenta - File "/home/my/project/SConstruct", line 5, in <module> - </screen> + <scons_output example="ListVariable"> + <scons_output_command>scons -Q COLORS=magenta foo.o</scons_output_command> + </scons_output> </section> @@ -1511,15 +1531,26 @@ </para> - <programlisting> + <scons_example name="PathVariable"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(PathVariable('CONFIG', 'Path to configuration file', - '/etc/my_config')) + '__ROOT__/etc/my_config')) env = Environment(variables = vars, CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/etc/my_config"> + /opt/location + </file> + <file name="__ROOT__/usr/local/etc/other_config"> + /opt/location + </file> + </scons_example> <para> @@ -1529,12 +1560,10 @@ </para> - <screen> - % <userinput>scons -Q foo.o</userinput> - cc -o foo.o -c -DCONFIG_FILE="/etc/my_config" foo.c - % <userinput>scons -Q CONFIG=/usr/local/etc/other_config foo.o</userinput> - scons: `foo.o' is up to date. - </screen> + <scons_output example="PathVariable"> + <scons_output_command>scons -Q foo.o</scons_output_command> + <scons_output_command>scons -Q CONFIG=__ROOT__/usr/local/etc/other_config foo.o</scons_output_command> + </scons_output> <para> @@ -1544,12 +1573,9 @@ </para> - <screen> - % <userinput>scons -Q CONFIG=/does/not/exist foo.o</userinput> - - scons: *** Path for option CONFIG does not exist: /does/not/exist - File "/home/my/project/SConstruct", line 6, in <module> - </screen> + <scons_output example="PathVariable"> + <scons_output_command>scons -Q CONFIG=__ROOT__/does/not/exist foo.o</scons_output_command> + </scons_output> <para> @@ -1561,16 +1587,24 @@ </para> - <programlisting> + <scons_example name="PathIsFile"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(PathVariable('CONFIG', 'Path to configuration file', - '/etc/my_config', + '__ROOT__/etc/my_config', PathVariable.PathIsFile)) env = Environment(variables = vars, CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/etc/my_config"> + /opt/location + </file> + </scons_example> <para> @@ -1580,16 +1614,24 @@ </para> - <programlisting> + <scons_example name="PathIsDir"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(PathVariable('DBDIR', 'Path to database directory', - '/var/my_dbdir', + '__ROOT__/var/my_dbdir', PathVariable.PathIsDir)) env = Environment(variables = vars, CPPDEFINES={'DBDIR' : '"$DBDIR"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/var/my_dbdir"> + /opt/location + </file> + </scons_example> <para> @@ -1601,16 +1643,24 @@ </para> - <programlisting> + <scons_example name="PathIsDirCreate"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(PathVariable('DBDIR', 'Path to database directory', - '/var/my_dbdir', + '__ROOT__/var/my_dbdir', PathVariable.PathIsDirCreate)) env = Environment(variables = vars, CPPDEFINES={'DBDIR' : '"$DBDIR"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/var/my_dbdir"> + /opt/location + </file> + </scons_example> <para> @@ -1621,7 +1671,8 @@ </para> - <programlisting> + <scons_example name="PathAccept"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(PathVariable('OUTPUT', 'Path to output file or directory', @@ -1630,7 +1681,11 @@ env = Environment(variables = vars, CPPDEFINES={'OUTPUT' : '"$OUTPUT"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> </section> @@ -1651,15 +1706,26 @@ </para> - <programlisting> + <scons_example name="PackageVariable"> + <file name="SConstruct" printme="1"> vars = Variables('custom.py') vars.Add(PackageVariable('PACKAGE', 'Location package', - '/opt/location')) + '__ROOT__/opt/location')) env = Environment(variables = vars, CPPDEFINES={'PACKAGE' : '"$PACKAGE"'}) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + <file name="__ROOT__/opt/location"> + /opt/location + </file> + <file name="__ROOT__/usr/local/location"> + /opt/location + </file> + </scons_example> <para> @@ -1674,16 +1740,12 @@ </para> - <screen> - % <userinput>scons -Q foo.o</userinput> - cc -o foo.o -c -DPACKAGE="/opt/location" foo.c - % <userinput>scons -Q PACKAGE=/usr/local/location foo.o</userinput> - cc -o foo.o -c -DPACKAGE="/usr/local/location" foo.c - % <userinput>scons -Q PACKAGE=yes foo.o</userinput> - cc -o foo.o -c -DPACKAGE="True" foo.c - % <userinput>scons -Q PACKAGE=no foo.o</userinput> - cc -o foo.o -c -DPACKAGE="False" foo.c - </screen> + <scons_output example="PackageVariable"> + <scons_output_command>scons -Q foo.o</scons_output_command> + <scons_output_command>scons -Q PACKAGE=__ROOT__/usr/local/location foo.o</scons_output_command> + <scons_output_command>scons -Q PACKAGE=yes foo.o</scons_output_command> + <scons_output_command>scons -Q PACKAGE=no foo.o</scons_output_command> + </scons_output> </section> @@ -1710,7 +1772,8 @@ </para> - <programlisting> + <scons_example name="AddVariables_1"> + <file name="SConstruct" printme="1"> vars = Variables() vars.AddVariables( ('RELEASE', 'Set to 1 to build for release', 0), @@ -1728,7 +1791,8 @@ 'yes'), PathVariable('qtdir', 'where the root of Qt is installed', qtdir), ) - </programlisting> + </file> + </scons_example> <para> </para> @@ -1769,7 +1833,8 @@ </para> - <programlisting> + <scons_example name="UnknownVariables"> + <file name="SConstruct" printme="1"> vars = Variables(None) vars.Add('RELEASE', 'Set to 1 to build for release', 0) env = Environment(variables = vars, @@ -1779,7 +1844,11 @@ print "Unknown variables:", unknown.keys() Exit(1) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> <para> @@ -1800,10 +1869,9 @@ </para> - <screen> - % <userinput>scons -Q NOT_KNOWN=foo</userinput> - Unknown variables: ['NOT_KNOWN'] - </screen> + <scons_output example="UnknownVariables"> + <scons_output_command>scons -Q NOT_KNOWN=foo</scons_output_command> + </scons_output> <para> @@ -1852,12 +1920,20 @@ </para> - <programlisting> + <scons_example name="COMMAND_LINE_TARGETS"> + <file name="SConstruct" printme="1"> if 'bar' in COMMAND_LINE_TARGETS: print "Don't forget to copy `bar' to the archive!" Default(Program('foo.c')) Program('bar.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + <file name="bar.c"> + foo.c + </file> + </scons_example> <para> @@ -1868,15 +1944,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o foo.o -c foo.c - cc -o foo foo.o - % <userinput>scons -Q bar</userinput> - Don't forget to copy `bar' to the archive! - cc -o bar.o -c bar.c - cc -o bar bar.o - </screen> + <scons_output example="COMMAND_LINE_TARGETS"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q bar</scons_output_command> + </scons_output> <para> @@ -1911,12 +1982,20 @@ </para> - <programlisting> + <scons_example name="Default1"> + <file name="SConstruct" printme="1"> env = Environment() hello = env.Program('hello.c') env.Program('goodbye.c') Default(hello) - </programlisting> + </file> + <file name="hello.c"> + hello.c + </file> + <file name="goodbye.c"> + goodbye.c + </file> + </scons_example> <para> @@ -1927,16 +2006,11 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q</userinput> - scons: `hello' is up to date. - % <userinput>scons -Q goodbye</userinput> - cc -o goodbye.o -c goodbye.c - cc -o goodbye goodbye.o - </screen> + <scons_output example="Default1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q goodbye</scons_output_command> + </scons_output> <para> @@ -1949,13 +2023,9 @@ </para> - <screen> - % <userinput>scons -Q .</userinput> - cc -o goodbye.o -c goodbye.c - cc -o goodbye goodbye.o - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="Default1"> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> <para> @@ -1966,14 +2036,25 @@ </para> - <programlisting> + <scons_example name="Default2"> + <file name="SConstruct" printme="1"> env = Environment() prog1 = env.Program('prog1.c') Default(prog1) prog2 = env.Program('prog2.c') prog3 = env.Program('prog3.c') Default(prog3) - </programlisting> + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + <file name="prog3.c"> + prog3.c + </file> + </scons_example> <para> @@ -2001,16 +2082,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o prog1.o -c prog1.c - cc -o prog1 prog1.o - cc -o prog3.o -c prog3.c - cc -o prog3 prog3.o - % <userinput>scons -Q .</userinput> - cc -o prog2.o -c prog2.c - cc -o prog2 prog2.o - </screen> + <scons_output example="Default2"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> <para> @@ -2019,12 +2094,28 @@ </para> - <programlisting> + <scons_example name="Default3"> + <file name="SConstruct" printme="1"> env = Environment() env.Program(['prog1/main.c', 'prog1/foo.c']) env.Program(['prog2/main.c', 'prog2/bar.c']) Default('prog1') - </programlisting> + </file> + <directory name="prog1"></directory> + <directory name="prog2"></directory> + <file name="prog1/main.c"> + int main() { printf("prog1/main.c\n"); } + </file> + <file name="prog1/foo.c"> + int foo() { printf("prog1/foo.c\n"); } + </file> + <file name="prog2/main.c"> + int main() { printf("prog2/main.c\n"); } + </file> + <file name="prog2/bar.c"> + int bar() { printf("prog2/bar.c\n"); } + </file> + </scons_example> <para> @@ -2033,18 +2124,11 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o prog1/foo.o -c prog1/foo.c - cc -o prog1/main.o -c prog1/main.c - cc -o prog1/main prog1/main.o prog1/foo.o - % <userinput>scons -Q</userinput> - scons: `prog1' is up to date. - % <userinput>scons -Q .</userinput> - cc -o prog2/bar.o -c prog2/bar.c - cc -o prog2/main.o -c prog2/main.c - cc -o prog2/main prog2/main.o prog2/bar.o - </screen> + <scons_output example="Default3"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> <para> @@ -2055,12 +2139,20 @@ </para> - <programlisting> + <scons_example name="Default4"> + <file name="SConstruct" printme="1"> env = Environment() prog1 = env.Program('prog1.c') prog2 = env.Program('prog2.c') Default(None) - </programlisting> + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> <para> @@ -2068,15 +2160,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - scons: *** No targets specified and no Default() targets found. Stop. - % <userinput>scons -Q .</userinput> - cc -o prog1.o -c prog1.c - cc -o prog1 prog1.o - cc -o prog2.o -c prog2.c - cc -o prog2 prog2.o - </screen> + <scons_output example="Default4"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q .</scons_output_command> + </scons_output> <section> <title>Fetching the List of Default Targets: the &DEFAULT_TARGETS; Variable</title> @@ -2097,11 +2184,16 @@ </para> - <programlisting> + <scons_example name="DEFAULT_TARGETS_1"> + <file name="SConstruct" printme="1"> prog1 = Program('prog1.c') Default(prog1) print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS) - </programlisting> + </file> + <file name="prog1.c"> + prog1.c + </file> + </scons_example> <para> @@ -2113,16 +2205,9 @@ </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - DEFAULT_TARGETS is ['prog1'] - scons: done reading SConscript files. - scons: Building targets ... - cc -o prog1.o -c prog1.c - cc -o prog1 prog1.o - scons: done building targets. - </screen> + <scons_output example="DEFAULT_TARGETS_1"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -2133,14 +2218,22 @@ </para> - <programlisting> + <scons_example name="DEFAULT_TARGETS_2"> + <file name="SConstruct" printme="1"> prog1 = Program('prog1.c') Default(prog1) print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) prog2 = Program('prog2.c') Default(prog2) print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) - </programlisting> + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> <para> @@ -2148,19 +2241,9 @@ </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - DEFAULT_TARGETS is now ['prog1'] - DEFAULT_TARGETS is now ['prog1', 'prog2'] - scons: done reading SConscript files. - scons: Building targets ... - cc -o prog1.o -c prog1.c - cc -o prog1 prog1.o - cc -o prog2.o -c prog2.c - cc -o prog2 prog2.o - scons: done building targets. - </screen> + <scons_output example="DEFAULT_TARGETS_2"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -2198,12 +2281,12 @@ </para> - <programlisting> + <sconstruct> if COMMAND_LINE_TARGETS: targets = COMMAND_LINE_TARGETS else: targets = DEFAULT_TARGETS - </programlisting> + </sconstruct> <para> @@ -2228,12 +2311,20 @@ </para> - <programlisting> + <scons_example name="BUILD_TARGETS_1"> + <file name="SConstruct" printme="1"> prog1 = Program('prog1.c') Program('prog2.c') Default(prog1) print "BUILD_TARGETS is", map(str, BUILD_TARGETS) - </programlisting> + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> <para> @@ -2243,22 +2334,11 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - BUILD_TARGETS is ['prog1'] - cc -o prog1.o -c prog1.c - cc -o prog1 prog1.o - % <userinput>scons -Q prog2</userinput> - BUILD_TARGETS is ['prog2'] - cc -o prog2.o -c prog2.c - cc -o prog2 prog2.o - % <userinput>scons -Q -c .</userinput> - BUILD_TARGETS is ['.'] - Removed prog1.o - Removed prog1 - Removed prog2.o - Removed prog2 - </screen> + <scons_output example="BUILD_TARGETS_1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q prog2</scons_output_command> + <scons_output_command>scons -Q -c .</scons_output_command> + </scons_output> </section> diff --git a/doc/user/copyright.in b/doc/user/copyright.in deleted file mode 100644 index 76e3e50..0000000 --- a/doc/user/copyright.in +++ /dev/null @@ -1,32 +0,0 @@ -<!-- - - __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. - ---> - -<blockquote> - <para> - - SCons User's Guide Copyright (c) 2004, 2005, 2006, 2007 Steven Knight - - </para> -</blockquote> diff --git a/doc/user/depends.in b/doc/user/depends.in deleted file mode 100644 index f601312..0000000 --- a/doc/user/depends.in +++ /dev/null @@ -1,1872 +0,0 @@ -<!-- - - __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> - - So far we've seen how &SCons; handles one-time builds. - But one of the main functions of a build tool like &SCons; - is to rebuild only what is necessary - when source files change--or, put another way, - &SCons; should <emphasis>not</emphasis> - waste time rebuilding things that don't need to be rebuilt. - You can see this at work simply by re-invoking &SCons; - after building our simple &hello; example: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct"> - Program('hello.c') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - The second time it is executed, - &SCons; realizes that the &hello; program - is up-to-date with respect to the current &hello_c; source file, - and avoids rebuilding it. - You can see this more clearly by naming - the &hello; program explicitly on the command line: - - </para> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - Note that &SCons; reports <literal>"...is up to date"</literal> - only for target files named explicitly on the command line, - to avoid cluttering the output. - - </para> - - <section> - <title>Deciding When an Input File Has Changed: the &Decider; Function</title> - - <para> - - Another aspect of avoiding unnecessary rebuilds - is the fundamental build tool behavior - of <emphasis>rebuilding</emphasis> - things when an input file changes, - so that the built software is up to date. - By default, - &SCons; keeps track of this through an - MD5 &signature;, or checksum, of the contents of each file, - although you can easily configure - &SCons; to use the - modification times (or time stamps) - instead. - You can even specify your own Python function - for deciding if an input file has changed. - - </para> - - <section> - <title>Using MD5 Signatures to Decide if a File Has Changed</title> - - <para> - - By default, - &SCons; keeps track of whether a file has changed - based on an MD5 checksum of the file's contents, - not the file's modification time. - This means that you may be surprised by the - default &SCons; behavior if you are used to the - &Make; convention of forcing - a rebuild by updating the file's modification time - (using the &touch; command, for example): - - </para> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>touch hello.c</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - Even though the file's modification time has changed, - &SCons; realizes that the contents of the - &hello_c; file have <emphasis>not</emphasis> changed, - and therefore that the &hello; program - need not be rebuilt. - This avoids unnecessary rebuilds when, - for example, someone rewrites the - contents of a file without making a change. - But if the contents of the file really do change, - then &SCons; detects the change - and rebuilds the program as required: - - </para> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - Note that you can, if you wish, - specify this default behavior - (MD5 signatures) explicitly - using the &Decider; function as follows: - - </para> - - <sconstruct> - Program('hello.c') - Decider('MD5') - </sconstruct> - - <para> - - You can also use the string <literal>'content'</literal> - as a synonym for <literal>'MD5'</literal> - when calling the &Decider; function. - - </para> - - <section> - <title>Ramifications of Using MD5 Signatures</title> - - <para> - - Using MD5 signatures to decide if an input file has changed - has one surprising benefit: - if a source file has been changed - in such a way that the contents of the - rebuilt target file(s) - will be exactly the same as the last time - the file was built, - then any "downstream" target files - that depend on the rebuilt-but-not-changed target - file actually need not be rebuilt. - - </para> - - <para> - - So if, for example, - a user were to only change a comment in a &hello_c; file, - then the rebuilt &hello_o; file - would be exactly the same as the one previously built - (assuming the compiler doesn't put any build-specific - information in the object file). - &SCons; would then realize that it would not - need to rebuild the &hello; program as follows: - - </para> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - In essence, &SCons; - "short-circuits" any dependent builds - when it realizes that a target file - has been rebuilt to exactly the same file as the last build. - This does take some extra processing time - to read the contents of the target (&hello_o;) file, - but often saves time when the rebuild that was avoided - would have been time-consuming and expensive. - - </para> - - </section> - - </section> - - <section> - <title>Using Time Stamps to Decide If a File Has Changed</title> - - <para> - - If you prefer, you can - configure &SCons; to use the modification time - of a file, not the file contents, - when deciding if a target needs to be rebuilt. - &SCons; gives you two ways to use time stamps - to decide if an input file has changed - since the last time a target has been built. - - </para> - - <para> - - The most familiar way to use time stamps - is the way &Make; does: - that is, have &SCons; decide - that a target must be rebuilt - if a source file's modification time is - <emphasis>newer</emphasis> - than the target file. - To do this, call the &Decider; - function as follows: - - </para> - - <scons_example name="newer"> - <file name="SConstruct" printme="1"> - Object('hello.c') - Decider('timestamp-newer') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - This makes &SCons; act like &Make; - when a file's modification time is updated - (using the &touch; command, for example): - - </para> - - <scons_output example="newer" os="posix"> - <scons_output_command>scons -Q hello.o</scons_output_command> - <scons_output_command>touch hello.c</scons_output_command> - <scons_output_command>scons -Q hello.o</scons_output_command> - </scons_output> - - <para> - - And, in fact, because this behavior is the same - as the behavior of &Make;, - you can also use the string <literal>'make'</literal> - as a synonym for <literal>'timestamp-newer'</literal> - when calling the &Decider; function: - - </para> - - <sconstruct> - Object('hello.c') - Decider('make') - </sconstruct> - - <para> - - One drawback to using times stamps exactly like &Make; - is that if an input file's modification time suddenly - becomes <emphasis>older</emphasis> than a target file, - the target file will not be rebuilt. - This can happen if an old copy of a source file is restored - from a backup archive, for example. - The contents of the restored file will likely be different - than they were the last time a dependent target was built, - but the target won't be rebuilt - because the modification time of the source file - is not newer than the target. - - </para> - - <para> - - Because &SCons; actually stores information - about the source files' time stamps whenever a target is built, - it can handle this situation by checking for - an exact match of the source file time stamp, - instead of just whether or not the source file - is newer than the target file. - To do this, specify the argument - <literal>'timestamp-match'</literal> - when calling the &Decider; function: - - </para> - - <scons_example name="match"> - <file name="SConstruct" printme="1"> - Object('hello.c') - Decider('timestamp-match') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - When configured this way, - &SCons; will rebuild a target whenever - a source file's modification time has changed. - So if we use the <literal>touch -t</literal> - option to change the modification time of - &hello_c; to an old date (January 1, 1989), - &SCons; will still rebuild the target file: - - </para> - - <scons_output example="match" os="posix"> - <scons_output_command>scons -Q hello.o</scons_output_command> - <scons_output_command>touch -t 198901010000 hello.c</scons_output_command> - <scons_output_command>scons -Q hello.o</scons_output_command> - </scons_output> - - <para> - - In general, the only reason to prefer - <literal>timestamp-newer</literal> - instead of - <literal>timestamp-match</literal>, - would be if you have some specific reason - to require this &Make;-like behavior of - not rebuilding a target when an otherwise-modified - source file is older. - - </para> - - </section> - - <section> - <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title> - - <para> - - As a performance enhancement, - &SCons; provides a way to use - MD5 checksums of file contents - but to read those contents - only when the file's timestamp has changed. - To do this, call the &Decider; - function with <literal>'MD5-timestamp'</literal> - argument as follows: - - </para> - - <scons_example name="MD5-timestamp"> - <file name="SConstruct" printme="1"> - Program('hello.c') - Decider('MD5-timestamp') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - So configured, &SCons; will still behave like - it does when using <literal>Decider('MD5')</literal>: - - </para> - - <!-- - - We want to generate the output as follows, - but our "surrogate" system for generating the - output seems to get this wrong. - Just in-line the output for now. - - <scons_output example="MD5-timestamp" os="posix"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>touch hello.c</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - --> - - <screen> - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>touch hello.c</userinput> - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - % <userinput>edit hello.c</userinput> - [CHANGE THE CONTENTS OF hello.c] - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> - - <para> - - However, the second call to &SCons; in the above output, - when the build is up-to-date, - will have been performed by simply looking at the - modification time of the &hello_c; file, - not by opening it and performing - an MD5 checksum calcuation on its contents. - This can significantly speed up many up-to-date builds. - - </para> - - <para> - - The only drawback to using - <literal>Decider('MD5-timestamp')</literal> - is that &SCons; will <emphasis>not</emphasis> - rebuild a target file if a source file was modified - within one second of the last time &SCons; built the file. - While most developers are programming, - this isn't a problem in practice, - since it's unlikely that someone will have built - and then thought quickly enough to make a substantive - change to a source file within one second. - Certain build scripts or - continuous integration tools may, however, - rely on the ability to apply changes to files - automatically and then rebuild as quickly as possible, - in which case use of - <literal>Decider('MD5-timestamp')</literal> - may not be appropriate. - - </para> - - </section> - - <section> - <title>Writing Your Own Custom &Decider; Function</title> - - <para> - - The different string values that we've passed to - the &Decider; function are essentially used by &SCons; - to pick one of several specific internal functions - that implement various ways of deciding if a dependency - (usually a source file) - has changed since a target file has been built. - As it turns out, - you can also supply your own function - to decide if a dependency has changed. - - </para> - - <para> - - For example, suppose we have an input file - that contains a lot of data, - in some specific regular format, - that is used to rebuild a lot of different target files, - but each target file really only depends on - one particular section of the input file. - We'd like to have each target file depend on - only its section of the input file. - However, since the input file may contain a lot of data, - we want to open the input file only if its timestamp has changed. - This could be done with a custom - &Decider; function that might look something like this: - - </para> - - <scons_example name="function"> - <file name="SConstruct" printme="1"> - Program('hello.c') - def decide_if_changed(dependency, target, prev_ni): - if self.get_timestamp() != prev_ni.timestamp: - dep = str(dependency) - tgt = str(target) - if specific_part_of_file_has_changed(dep, tgt): - return True - return False - Decider(decide_if_changed) - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Note that in the function definition, - the <varname>dependency</varname> - (input file) is the first argument, - and then the ⌖. - Both of these are passed to the functions as - SCons &Node; objects, - which we convert to strings using the Python - <function>str()</function>. - - </para> - - <para> - - The third argument, <varname>prev_ni</varname>, - is an object that holds the - signature or timestamp information - that was recorded about the dependency - the last time the target was built. - A <varname>prev_ni</varname> object can hold - different information, - depending on the type of thing that the - <varname>dependency</varname> argument represents. - For normal files, - the <varname>prev_ni</varname> object - has the following attributes: - - </para> - - <variablelist> - - <varlistentry> - <term>.csig</term> - - <listitem> - <para> - The <emphasis>content signature</emphasis>, - or MD5 checksum, of the contents of the - <varname>dependency</varname> - file the list time the ⌖ was built. - </para> - </listitem> - - </varlistentry> - - <varlistentry> - <term>.size</term> - - <listitem> - <para> - The size in bytes of the <varname>dependency</varname> - file the list time the target was built. - </para> - </listitem> - - </varlistentry> - - <varlistentry> - <term>.timestamp</term> - - <listitem> - <para> - The modification time of the <varname>dependency</varname> - file the list time the ⌖ was built. - </para> - </listitem> - - </varlistentry> - - </variablelist> - - <para> - - Note that ignoring some of the arguments - in your custom &Decider; function - is a perfectly normal thing to do, - if they don't impact the way you want to - decide if the dependency file has changed. - - </para> - - <para> - - Another thing to look out for is the fact that the three - attributes above may not be present at the time of the first run. - Without any prior build, no targets have been created and no - <filename>.sconsign</filename> DB file exists yet. - So, you should always check whether the - <varname>prev_ni</varname> attribute in question is available. - - </para> - - <para> - - We finally present a small example for a - <varname>csig</varname>-based decider function. Note how the - signature information for the <varname>dependency</varname> file - has to get initialized via <function>get_csig</function> - during each function call (this is mandatory!). - - </para> - - <sconstruct> - env = Environment() - - def config_file_decider(dependency, target, prev_ni): - import os.path - - # We always have to init the .csig value... - dep_csig = dependency.get_csig() - # .csig may not exist, because no target was built yet... - if 'csig' not in dir(prev_ni): - return True - # Target file may not exist yet - if not os.path.exists(str(target.abspath)): - return True - if dep_csig != prev_ni.csig: - # Some change on source file => update installed one - return True - return False - - def update_file(): - f = open("test.txt","a") - f.write("some line\n") - f.close() - - update_file() - - # Activate our own decider function - env.Decider(config_file_decider) - - env.Install("install","test.txt") - </sconstruct> - - </section> - - <section> - <title>Mixing Different Ways of Deciding If a File Has Changed</title> - - <para> - - The previous examples have all demonstrated calling - the global &Decider; function - to configure all dependency decisions that &SCons; makes. - Sometimes, however, you want to be able to configure - different decision-making for different targets. - When that's necessary, you can use the - <function>env.Decider</function> - method to affect only the configuration - decisions for targets built with a - specific construction environment. - - </para> - - <para> - - For example, if we arbitrarily want to build - one program using MD5 checkums - and another using file modification times - from the same source - we might configure it this way: - - </para> - - <scons_example name="mixing"> - <file name="SConstruct" printme="1"> - env1 = Environment(CPPPATH = ['.']) - env2 = env1.Clone() - env2.Decider('timestamp-match') - env1.Program('prog-MD5', 'program1.c') - env2.Program('prog-timestamp', 'program2.c') - </file> - <file name="program1.c"> - #include "inc.h" - int main() { printf("Hello, world!\n"); } - </file> - <file name="program2.c"> - #include "inc.h" - int main() { printf("Hello, world!\n"); } - </file> - <file name="inc.h"> - #define INC 1 - </file> - </scons_example> - - <para> - - If both of the programs include the same - <filename>inc.h</filename> file, - then updating the modification time of - <filename>inc.h</filename> - (using the &touch; command) - will cause only <filename>prog-timestamp</filename> - to be rebuilt: - - </para> - - <scons_output example="mixing" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>touch inc.h</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - </section> - - <section> - <title>Older Functions for Deciding When an Input File Has Changed</title> - - <para> - - &SCons; still supports two functions that used to be the - primary methods for configuring the - decision about whether or not an input file has changed. - These functions have been officially deprecated - as &SCons; version 2.0, - and their use is discouraged, - mainly because they rely on a somewhat - confusing distinction between how - source files and target files are handled. - These functions are documented here mainly in case you - encounter them in older &SConscript; files. - - </para> - - <section> - <title>The &SourceSignatures; Function</title> - - <para> - - The &SourceSignatures; function is fairly straightforward, - and supports two different argument values - to configure whether source file changes should be decided - using MD5 signatures: - - </para> - - <sconstruct> - Program('hello.c') - SourceSignatures('MD5') - </sconstruct> - - <para> - - Or using time stamps: - - </para> - - <sconstruct> - Program('hello.c') - SourceSignatures('timestamp') - </sconstruct> - - <para> - - These are roughly equivalent to specifying - <function>Decider('MD5')</function> - or - <function>Decider('timestamp-match')</function>, - respectively, - although it only affects how SCons makes - decisions about dependencies on - <emphasis>source</emphasis> files--that is, - files that are not built from any other files. - - </para> - - </section> - - <section> - <title>The &TargetSignatures; Function</title> - - <para> - - The &TargetSignatures; function - specifies how &SCons; decides - when a target file has changed - <emphasis>when it is used as a - dependency of (input to) another target</emphasis>--that is, - the &TargetSignatures; function configures - how the signatures of "intermediate" target files - are used when deciding if a "downstream" target file - must be rebuilt. - <footnote><para> - This easily-overlooked distinction between - how &SCons; decides if the target itself must be rebuilt - and how the target is then used to decide if a different - target must be rebuilt is one of the confusing - things that has led to the &TargetSignatures; - and &SourceSignatures; functions being - replaced by the simpler &Decider; function. - </para></footnote> - - </para> - - <para> - - The &TargetSignatures; function supports the same - <literal>'MD5'</literal> and <literal>'timestamp'</literal> - argument values that are supported by the &SourceSignatures;, - with the same meanings, but applied to target files. - That is, in the example: - - </para> - - <sconstruct> - Program('hello.c') - TargetSignatures('MD5') - </sconstruct> - - <para> - - The MD5 checksum of the &hello_o; target file - will be used to decide if it has changed since the last - time the "downstream" &hello; target file was built. - And in the example: - - </para> - - <sconstruct> - Program('hello.c') - TargetSignatures('timestamp') - </sconstruct> - - <para> - - The modification time of the &hello_o; target file - will be used to decide if it has changed since the last - time the "downstream" &hello; target file was built. - - </para> - - <para> - - The &TargetSignatures; function supports - two additional argument values: - <literal>'source'</literal> and <literal>'build'</literal>. - The <literal>'source'</literal> argument - specifies that decisions involving - whether target files have changed - since a previous build - should use the same behavior - for the decisions configured for source files - (using the &SourceSignatures; function). - So in the example: - - </para> - - <sconstruct> - Program('hello.c') - TargetSignatures('source') - SourceSignatures('timestamp') - </sconstruct> - - <para> - - All files, both targets and sources, - will use modification times - when deciding if an input file - has changed since the last - time a target was built. - - </para> - - <para> - - Lastly, the <literal>'build'</literal> argument - specifies that &SCons; should examine - the build status of a target file - and always rebuild a "downstream" target - if the target file was itself rebuilt, - without re-examining the contents or timestamp - of the newly-built target file. - If the target file was not rebuilt during - this &scons; invocation, - then the target file will be examined - the same way as configured by - the &SourceSignature; call - to decide if it has changed. - - </para> - - <para> - - This mimics the behavior of - <literal>build signatures</literal> - in earlier versions of &SCons;. - A &buildsignature; re-combined - signatures of all the input files - that went into making the target file, - so that the target file itself - did not need to have its contents read - to compute an MD5 signature. - This can improve performance for some configurations, - but is generally not as effective as using - <literal>Decider('MD5-timestamp')</literal>. - - </para> - - </section> - - </section> - - <section> - <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title> - - <para> - - Now suppose that our "Hello, World!" program - actually has an <literal>#include</literal> line - to include the &hello_h; file in the compilation: - - </para> - - <scons_example name="include"> - <file name="SConstruct"> - Program('hello.c', CPPPATH = '.') - </file> - <file name="hello.c" printme="1"> - #include <hello.h> - int - main() - { - printf("Hello, %s!\n", string); - } - </file> - <file name="hello.h"> - #define string "world" - </file> - </scons_example> - - <para> - - And, for completeness, the &hello_h; file looks like this: - - </para> - - <scons_example_file example="include" name="hello.h"> - </scons_example_file> - - <para> - - In this case, we want &SCons; to recognize that, - if the contents of the &hello_h; file change, - the &hello; program must be recompiled. - To do this, we need to modify the - &SConstruct; file like so: - - </para> - - <scons_example_file example="include" name="SConstruct"> - </scons_example_file> - - <para> - - The &cv-link-CPPPATH; value - tells &SCons; to look in the current directory - (<literal>'.'</literal>) - for any files included by C source files - (<filename>.c</filename> or <filename>.h</filename> files). - With this assignment in the &SConstruct; file: - - </para> - - <scons_output example="include" os="posix"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - First, notice that &SCons; - added the <literal>-I.</literal> argument - from the &cv-CPPPATH; variable - so that the compilation would find the - &hello_h; file in the local directory. - - </para> - - <para> - - Second, realize that &SCons; knows that the &hello; - program must be rebuilt - because it scans the contents of - the &hello_c; file - for the <literal>#include</literal> lines that indicate - another file is being included in the compilation. - &SCons; records these as - <emphasis>implicit dependencies</emphasis> - of the target file, - Consequently, - when the &hello_h; file changes, - &SCons; realizes that the &hello_c; file includes it, - and rebuilds the resulting &hello; program - that depends on both the &hello_c; and &hello_h; files. - - </para> - - <para> - - Like the &cv-link-LIBPATH; variable, - the &cv-CPPPATH; variable - may be a list of directories, - or a string separated by - the system-specific path separation character - (':' on POSIX/Linux, ';' on Windows). - Either way, &SCons; creates the - right command-line options - so that the following example: - - </para> - - <scons_example name="ex5"> - <file name="SConstruct" printme="1"> - Program('hello.c', CPPPATH = ['include', '/home/project/inc']) - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Will look like this on POSIX or Linux: - - </para> - - <scons_output example="ex5" os="posix"> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - And like this on Windows: - - </para> - - <scons_output example="ex5" os="win32"> - <scons_output_command>scons -Q hello.exe</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Caching Implicit Dependencies</title> - - <para> - - Scanning each file for <literal>#include</literal> lines - does take some extra processing time. - When you're doing a full build of a large system, - the scanning time is usually a very small percentage - of the overall time spent on the build. - You're most likely to notice the scanning time, - however, when you <emphasis>rebuild</emphasis> - all or part of a large system: - &SCons; will likely take some extra time to "think about" - what must be built before it issues the - first build command - (or decides that everything is up to date - and nothing must be rebuilt). - - <!-- - Isn't this expensive? The answer is, it depends. If you do a full build of a - large system, the scanning time is insignificant. If you do a rebuild of a - large system, then Cons will spend a fair amount of time thinking about it - before it decides that nothing has to be done (although not necessarily more - time than make!). The good news is that Cons makes it very easy to - intelligently subset your build, when you are working on localized changes. - --> - - </para> - - <para> - - In practice, having &SCons; scan files saves time - relative to the amount of potential time - lost to tracking down subtle problems - introduced by incorrect dependencies. - Nevertheless, the "waiting time" - while &SCons; scans files can annoy - individual developers waiting for their builds to finish. - Consequently, &SCons; lets you cache - the implicit dependencies - that its scanners find, - for use by later builds. - You can do this by specifying the - &implicit-cache; option on the command line: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q --implicit-cache hello</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - If you don't want to specify &implicit-cache; - on the command line each time, - you can make it the default behavior for your build - by setting the &implicit_cache; option - in an &SConscript; file: - - </para> - - <sconstruct> - SetOption('implicit_cache', 1) - </sconstruct> - - <para> - - &SCons; does not cache implicit dependencies like this by default - because the &implicit-cache; causes &SCons; to simply use the implicit - dependencies stored during the last run, without any checking - for whether or not those dependencies are still correct. - Specifically, this means &implicit-cache; instructs &SCons; - to <emphasis>not</emphasis> rebuild "correctly" in the - following cases: - - - </para> - - <itemizedlist> - - <listitem> - <para> - - When &implicit-cache; is used, &SCons; will ignore any changes that - may have been made to search paths - (like &cv-CPPPATH; or &cv-LIBPATH;,). - This can lead to &SCons; not rebuilding a file if a change to - &cv-CPPPATH; would normally cause a different, same-named file from - a different directory to be used. - - </para> - </listitem> - - <listitem> - <para> - - When &implicit-cache; is used, &SCons; will not detect if a - same-named file has been added to a directory that is earlier in - the search path than the directory in which the file was found - last time. - - </para> - </listitem> - - </itemizedlist> - - <section> - <title>The &implicit-deps-changed; Option</title> - - <para> - - When using cached implicit dependencies, - sometimes you want to "start fresh" - and have &SCons; re-scan the files - for which it previously cached the dependencies. - For example, - if you have recently installed a new version of - external code that you use for compilation, - the external header files will have changed - and the previously-cached implicit dependencies - will be out of date. - You can update them by - running &SCons; with the &implicit-deps-changed; option: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q --implicit-deps-changed hello</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - In this case, &SCons; will re-scan all of the implicit dependencies - and cache updated copies of the information. - - </para> - - </section> - - <section> - <title>The &implicit-deps-unchanged; Option</title> - - <para> - - By default when caching dependencies, - &SCons; notices when a file has been modified - and re-scans the file for any updated - implicit dependency information. - Sometimes, however, you may want - to force &SCons; to use the cached implicit dependencies, - even if the source files changed. - This can speed up a build for example, - when you have changed your source files - but know that you haven't changed - any <literal>#include</literal> lines. - In this case, - you can use the &implicit-deps-unchanged; option: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q --implicit-deps-unchanged hello</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - In this case, - &SCons; will assume that the cached implicit - dependencies are correct and - will not bother to re-scan changed files. - For typical builds after small, - incremental changes to source files, - the savings may not be very big, - but sometimes every bit of - improved performance counts. - - </para> - - </section> - - <!-- - - <section> - <title>XXX max drift</title> - - XXX SetOption('max_drift') - - </section> - - --> - - </section> - - <section> - <title>Explicit Dependencies: the &Depends; Function</title> - - <para> - - Sometimes a file depends on another file - that is not detected by an &SCons; scanner. - For this situation, - &SCons; allows you to specific explicitly that one file - depends on another file, - and must be rebuilt whenever that file changes. - This is specified using the &Depends; method: - - </para> - - <programlisting> - hello = Program('hello.c') - Depends(hello, 'other_file') - </programlisting> - - <!-- XXX mention that you can use arrays for target and source? --> - - <screen> - % <userinput>scons -Q hello</userinput> - cc -c hello.c -o hello.o - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - % <userinput>edit other_file</userinput> - [CHANGE THE CONTENTS OF other_file] - % <userinput>scons -Q hello</userinput> - cc -c hello.c -o hello.o - cc -o hello hello.o - </screen> - - <para> - - Note that the dependency - (the second argument to &Depends;) - may also be a list of Node objects - (for example, as returned by a call to a Builder): - - </para> - - <programlisting> - hello = Program('hello.c') - goodbye = Program('goodbye.c') - Depends(hello, goodbye) - </programlisting> - - <para> - - in which case the dependency or dependencies - will be built before the target(s): - - </para> - - <screen> - % <userinput>scons -Q hello</userinput> - cc -c goodbye.c -o goodbye.o - cc -o goodbye goodbye.o - cc -c hello.c -o hello.o - cc -o hello hello.o - </screen> - - </section> - - <section> - <title>Dependencies From External Files: the &ParseDepends; - Function</title> - - <para> - - &SCons; has built-in scanners for a number of languages. Sometimes - these scanners fail to extract certain implicit dependencies due - to limitations of the scanner implementation. - - </para> - - <para> - - The following example illustrates a case where the built-in C - scanner is unable to extract the implicit dependency on a header - file. - - </para> - - <scons_example name="macroinc"> - <file name="hello.c" printme="1"> - #define FOO_HEADER <foo.h> - #include FOO_HEADER - - int main() { - return FOO; - } - </file> - <file name="SConstruct"> - Program('hello', 'hello.c', CPPPATH='.') - </file> - <file name="foo.h"> - #define FOO 42 - </file> - </scons_example> - - <scons_output example="macroinc" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command output=" [CHANGE CONTENTS OF foo.h]" - >edit foo.h</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Apparently, the scanner does not know about the header dependency. - Being not a full-fledged C preprocessor, the scanner does not - expand the macro. - - </para> - - <para> - - In these cases, you may also use the compiler to extract the - implicit dependencies. &ParseDepends; can parse the contents of - the compiler output in the style of &Make;, and explicitly - establish all of the listed dependencies. - - </para> - - <para> - - The following example uses &ParseDepends; to process a compiler - generated dependency file which is generated as a side effect - during compilation of the object file: - - </para> - - <!-- XXX The ParseDepends example below fakes proper working by a - priori specification of the dependency file. The produced hello.d - file is not found (or used) for unknown reasons. --> - - <scons_example name="parsedep"> - <file name="hello.c"> - #define FOO_HEADER <foo.h> - #include FOO_HEADER - - int main() { - return FOO; - } - </file> - <file name="SConstruct" printme="1"> - obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.') - SideEffect('hello.d', obj) - ParseDepends('hello.d') - Program('hello', obj) - </file> - <file name="foo.h"> - #define FOO 42 - </file> - <file name="hello.d"> - hello.o: hello.c foo.h - </file> - </scons_example> - - <scons_output example="parsedep" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command output=" [CHANGE CONTENTS OF foo.h]" - >edit foo.h</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Parsing dependencies from a compiler-generated - <filename>.d</filename> file has a chicken-and-egg problem, that - causes unnecessary rebuilds: - - </para> - - <scons_example name="parsedeprebuild"> - <file name="hello.c"> - #define FOO_HEADER <foo.h> - #include FOO_HEADER - - int main() { - return FOO; - } - </file> - <file name="SConstruct"> - obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.') - SideEffect('hello.d', obj) - ParseDepends('hello.d') - Program('hello', obj) - </file> - <file name="foo.h"> - #define FOO 42 - </file> - </scons_example> - - <!-- - <scons_output example="parsedeprebuild" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - --> - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c -MD -MF hello.d -I. hello.c - cc -o hello hello.o - % <userinput>scons -Q --debug=explain</userinput> - scons: rebuilding `hello.o' because `foo.h' is a new dependency - cc -o hello.o -c -MD -MF hello.d -I. hello.c - % <userinput>scons -Q</userinput> - scons: `.' is up to date. - </screen> - - <para> - - In the first pass, the dependency file is generated while the - object file is compiled. At that time, &SCons; does not know about - the dependency on <filename>foo.h</filename>. In the second pass, - the object file is regenerated because <filename>foo.h</filename> - is detected as a new dependency. - - </para> - - <para> - - &ParseDepends; immediately reads the specified file at invocation - time and just returns if the file does not exist. A dependency - file generated during the build process is not automatically - parsed again. Hence, the compiler-extracted dependencies are not - stored in the signature database during the same build pass. This - limitation of &ParseDepends; leads to unnecessary recompilations. - Therefore, &ParseDepends; should only be used if scanners are not - available for the employed language or not powerful enough for the - specific task. - - </para> - - </section> - - <section> - <title>Ignoring Dependencies: the &Ignore; Function</title> - - <para> - - Sometimes it makes sense - to not rebuild a program, - even if a dependency file changes. - In this case, - you would tell &SCons; specifically - to ignore a dependency as follows: - - </para> - - <scons_example name="ignore"> - <file name="SConstruct" printme="1"> - hello_obj=Object('hello.c') - hello = Program(hello_obj) - Ignore(hello_obj, 'hello.h') - </file> - <file name="hello.c"> - #include "hello.h" - int main() { printf("Hello, %s!\n", string); } - </file> - <file name="hello.h"> - #define string "world" - </file> - </scons_example> - - <!-- XXX mention that you can use lists for target and source? --> - - <!-- - <scons_output example="ignore"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX - </scons_output> - --> - - <screen> - % <userinput>scons -Q hello</userinput> - cc -c -o hello.o hello.c - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - % <userinput>edit hello.h</userinput> - [CHANGE THE CONTENTS OF hello.h] - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - </screen> - - <para> - - Now, the above example is a little contrived, - because it's hard to imagine a real-world situation - where you wouldn't want to rebuild &hello; - if the &hello_h; file changed. - A more realistic example - might be if the &hello; - program is being built in a - directory that is shared between multiple systems - that have different copies of the - &stdio_h; include file. - In that case, - &SCons; would notice the differences between - the different systems' copies of &stdio_h; - and would rebuild &hello; - each time you change systems. - You could avoid these rebuilds as follows: - - </para> - - <programlisting> - hello = Program('hello.c', CPPPATH=['/usr/include']) - Ignore(hello, '/usr/include/stdio.h') - </programlisting> - - <para> - &Ignore; can also be used to prevent a generated file from being built - by default. This is due to the fact that directories depend on - their contents. So to ignore a generated file from the default build, - you specify that the directory should ignore the generated file. - Note that the file will still be built if the user specifically - requests the target on scons command line, or if the file is - a dependency of another file which is requested and/or is built - by default. - </para> - - <scons_example name="ignore_explicit"> - <file name="SConstruct" printme="1"> - hello_obj=Object('hello.c') - hello = Program(hello_obj) - Ignore('.',[hello,hello_obj]) - </file> - <file name="hello.c"> - #include "stdio.h" - int main() { printf("Hello!\n"); } - </file> - </scons_example> - - <scons_output example="ignore_explicit" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - </section> - - <section> - <title>Order-Only Dependencies: the &Requires; Function</title> - - <para> - - Occasionally, - it may be useful to specify that a certain - file or directory must, if necessary, - be built or created before some other target is built, - but that changes to that file or directory - do <emphasis>not</emphasis> - require that the target itself be rebuilt. - Such a relationship is called an - <emphasis>order-only dependency</emphasis> - because it only affects the order in which - things must be built--the dependency before the target--but - it is not a strict dependency relationship - because the target should not - change in response to changes in the dependent file. - - </para> - - <para> - - For example, suppose that you want to create a file - every time you run a build - that identifies the time the build was performed, - the version number, etc., - and which is included in every program that you build. - The version file's contents will change every build. - If you specify a normal dependency relationship, - then every program that depends on - that file would be rebuilt every time you ran &SCons;. - For example, we could use some Python code in - a &SConstruct; file to create a new <filename>version.c</filename> file - with a string containing the current date every time - we run &SCons;, - and then link a program with the resulting object file - by listing <filename>version.c</filename> in the sources: - - </para> - - <scons_example name="no-Requires"> - <file name="SConstruct" printme="1"> - import time - - version_c_text = """ - char *date = "%s"; - """ % time.ctime(time.time()) - open('version.c', 'w').write(version_c_text) - - hello = Program(['hello.c', 'version.c']) - </file> - <file name="hello.c"> - extern char *date; - int main() { printf("Hello, %s! I was built: %s\n", date); } - </file> - </scons_example> - - <para> - - If we list <filename>version.c</filename> as an actual source file, - though, then the <filename>version.o</filename> file - will get rebuilt every time we run &SCons; - (because the &SConstruct; file itself changes - the contents of <filename>version.c</filename>) - and the <filename>hello</filename> executable - will get re-linked every time - (because the <filename>version.o</filename> file changes): - - </para> - - <scons_output example="no-Requires"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>sleep 1</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>sleep 1</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - <para> - - (Note that for the above example to work, - we &sleep; for one second in between each run, - so that the &SConstruct; file will create a - <filename>version.c</filename> file with a time string - that's one second later than the previous run.) - - </para> - - <para> - - One solution is to use the &Requires; function - to specify that the <filename>version.o</filename> - must be rebuilt before it is used by the link step, - but that changes to <filename>version.o</filename> - should not actually cause the <filename>hello</filename> - executable to be re-linked: - - </para> - - <scons_example name="Requires"> - <file name="SConstruct" printme="1"> - import time - - version_c_text = """ - char *date = "%s"; - """ % time.ctime(time.time()) - open('version.c', 'w').write(version_c_text) - - version_obj = Object('version.c') - - hello = Program('hello.c', - LINKFLAGS = str(version_obj[0])) - - Requires(hello, version_obj) - </file> - <file name="hello.c"> - extern char *date; - int main() { printf("Hello, %s! I was built: %s\n", date); } - </file> - </scons_example> - - <para> - - Notice that because we can no longer list <filename>version.c</filename> - as one of the sources for the <filename>hello</filename> program, - we have to find some other way to get it into the link command line. - For this example, we're cheating a bit and stuffing the - object file name (extracted from <literal>version_obj</literal> - list returned by the &b-Object; call) - into the &cv-link-LINKFLAGS; variable, - because &cv-LINKFLAGS; is already included - in the &cv-link-LINKCOM; command line. - - </para> - - <para> - - With these changes, - we get the desired behavior of only - re-linking the <filename>hello</filename> executable - when the <filename>hello.c</filename> has changed, - even though the <filename>version.o</filename> is rebuilt - (because the &SConstruct; file still changes the - <filename>version.c</filename> contents directly each run): - - </para> - - <scons_output example="Requires"> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>sleep 1</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>sleep 1</scons_output_command> - <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - <scons_output_command>sleep 1</scons_output_command> - <scons_output_command>scons -Q hello</scons_output_command> - </scons_output> - - </section> - - <section> - <title>The &AlwaysBuild; Function</title> - - <para> - - How &SCons; handles dependencies can also be affected - by the &AlwaysBuild; method. - When a file is passed to the &AlwaysBuild; method, - like so: - - </para> - - <scons_example name="AlwaysBuild"> - <file name="SConstruct" printme="1"> - hello = Program('hello.c') - AlwaysBuild(hello) - </file> - <file name="hello.c"> - int main() { printf("Hello, %s!\n", string); } - </file> - </scons_example> - - <para> - - Then the specified target file (&hello; in our example) - will always be considered out-of-date and - rebuilt whenever that target file is evaluated - while walking the dependency graph: - - </para> - - <scons_output example="AlwaysBuild"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - The &AlwaysBuild; function has a somewhat misleading name, - because it does not actually mean the target file will - be rebuilt every single time &SCons; is invoked. - Instead, it means that the target will, in fact, - be rebuilt whenever the target file is encountered - while evaluating the targets specified on - the command line (and their dependencies). - So specifying some other target on the command line, - a target that does <emphasis>not</emphasis> - itself depend on the &AlwaysBuild; target, - will still be rebuilt only if it's out-of-date - with respect to its dependencies: - - </para> - - <scons_output example="AlwaysBuild"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q hello.o</scons_output_command> - </scons_output> - - <!-- - - XXX AlwaysBuild() and Alias Nodes - - XXX AlwaysBuild() and Dir Nodes - - XXX AlwaysBuild() with no sources - - --> - - </section> - - <!-- - - <section> - <title>The &Salt; Method</title> - - <para> - - XXX Salt() (are we going to implement this ?) - - original Cons classic POD documentation: - -=head2 The C<Salt> method - -The C<Salt> method adds a constant value to the signature calculation -for every derived file. It is invoked as follows: - - Salt $string; - -Changing the Salt value will force a complete rebuild of every derived -file. This can be used to force rebuilds in certain desired -circumstances. For example, - - Salt `uname -s`; - -Would force a complete rebuild of every derived file whenever the -operating system on which the build is performed (as reported by C<uname --s>) changes. - - </para> - - </section> - - --> diff --git a/doc/user/depends.xml b/doc/user/depends.xml index df2a911..f601312 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -36,15 +36,19 @@ </para> - - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q</userinput> - scons: `.' is up to date. - </screen> + <scons_example name="ex1"> + <file name="SConstruct"> + Program('hello.c') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -57,13 +61,10 @@ </para> - <screen> - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - </screen> + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -112,14 +113,11 @@ </para> - <screen> - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>touch hello.c</userinput> - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - </screen> + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>touch hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -137,16 +135,11 @@ </para> - <screen> - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>edit hello.c</userinput> - [CHANGE THE CONTENTS OF hello.c] - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -157,10 +150,10 @@ </para> - <programlisting> + <sconstruct> Program('hello.c') Decider('MD5') - </programlisting> + </sconstruct> <para> @@ -201,16 +194,11 @@ </para> - <screen> - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>edit hello.c</userinput> - [CHANGE A COMMENT IN hello.c] - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - scons: `hello' is up to date. - </screen> + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -258,10 +246,15 @@ </para> - <programlisting> + <scons_example name="newer"> + <file name="SConstruct" printme="1"> Object('hello.c') Decider('timestamp-newer') - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -271,13 +264,11 @@ </para> - <screen> - % <userinput>scons -Q hello.o</userinput> - cc -o hello.o -c hello.c - % <userinput>touch hello.c</userinput> - % <userinput>scons -Q hello.o</userinput> - cc -o hello.o -c hello.c - </screen> + <scons_output example="newer" os="posix"> + <scons_output_command>scons -Q hello.o</scons_output_command> + <scons_output_command>touch hello.c</scons_output_command> + <scons_output_command>scons -Q hello.o</scons_output_command> + </scons_output> <para> @@ -289,10 +280,10 @@ </para> - <programlisting> + <sconstruct> Object('hello.c') Decider('make') - </programlisting> + </sconstruct> <para> @@ -324,10 +315,15 @@ </para> - <programlisting> + <scons_example name="match"> + <file name="SConstruct" printme="1"> Object('hello.c') Decider('timestamp-match') - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -341,13 +337,11 @@ </para> - <screen> - % <userinput>scons -Q hello.o</userinput> - cc -o hello.o -c hello.c - % <userinput>touch -t 198901010000 hello.c</userinput> - % <userinput>scons -Q hello.o</userinput> - cc -o hello.o -c hello.c - </screen> + <scons_output example="match" os="posix"> + <scons_output_command>scons -Q hello.o</scons_output_command> + <scons_output_command>touch -t 198901010000 hello.c</scons_output_command> + <scons_output_command>scons -Q hello.o</scons_output_command> + </scons_output> <para> @@ -380,10 +374,15 @@ </para> - <programlisting> + <scons_example name="MD5-timestamp"> + <file name="SConstruct" printme="1"> Program('hello.c') Decider('MD5-timestamp') - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -493,7 +492,8 @@ </para> - <programlisting> + <scons_example name="function"> + <file name="SConstruct" printme="1"> Program('hello.c') def decide_if_changed(dependency, target, prev_ni): if self.get_timestamp() != prev_ni.timestamp: @@ -503,7 +503,11 @@ return True return False Decider(decide_if_changed) - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -608,7 +612,7 @@ </para> - <programlisting> + <sconstruct> env = Environment() def config_file_decider(dependency, target, prev_ni): @@ -623,7 +627,7 @@ if not os.path.exists(str(target.abspath)): return True if dep_csig != prev_ni.csig: - # Some change on source file => update installed one + # Some change on source file => update installed one return True return False @@ -638,7 +642,7 @@ env.Decider(config_file_decider) env.Install("install","test.txt") - </programlisting> + </sconstruct> </section> @@ -670,13 +674,26 @@ </para> - <programlisting> + <scons_example name="mixing"> + <file name="SConstruct" printme="1"> env1 = Environment(CPPPATH = ['.']) env2 = env1.Clone() env2.Decider('timestamp-match') env1.Program('prog-MD5', 'program1.c') env2.Program('prog-timestamp', 'program2.c') - </programlisting> + </file> + <file name="program1.c"> + #include "inc.h" + int main() { printf("Hello, world!\n"); } + </file> + <file name="program2.c"> + #include "inc.h" + int main() { printf("Hello, world!\n"); } + </file> + <file name="inc.h"> + #define INC 1 + </file> + </scons_example> <para> @@ -690,17 +707,11 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o program1.o -c -I. program1.c - cc -o prog-MD5 program1.o - cc -o program2.o -c -I. program2.c - cc -o prog-timestamp program2.o - % <userinput>touch inc.h</userinput> - % <userinput>scons -Q</userinput> - cc -o program2.o -c -I. program2.c - cc -o prog-timestamp program2.o - </screen> + <scons_output example="mixing" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>touch inc.h</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -737,10 +748,10 @@ </para> - <programlisting> + <sconstruct> Program('hello.c') SourceSignatures('MD5') - </programlisting> + </sconstruct> <para> @@ -748,10 +759,10 @@ </para> - <programlisting> + <sconstruct> Program('hello.c') SourceSignatures('timestamp') - </programlisting> + </sconstruct> <para> @@ -805,10 +816,10 @@ </para> - <programlisting> + <sconstruct> Program('hello.c') TargetSignatures('MD5') - </programlisting> + </sconstruct> <para> @@ -819,10 +830,10 @@ </para> - <programlisting> + <sconstruct> Program('hello.c') TargetSignatures('timestamp') - </programlisting> + </sconstruct> <para> @@ -848,11 +859,11 @@ </para> - <programlisting> + <sconstruct> Program('hello.c') TargetSignatures('source') SourceSignatures('timestamp') - </programlisting> + </sconstruct> <para> @@ -914,14 +925,22 @@ </para> - <programlisting> + <scons_example name="include"> + <file name="SConstruct"> + Program('hello.c', CPPPATH = '.') + </file> + <file name="hello.c" printme="1"> #include <hello.h> int main() { printf("Hello, %s!\n", string); } - </programlisting> + </file> + <file name="hello.h"> + #define string "world" + </file> + </scons_example> <para> @@ -929,10 +948,8 @@ </para> - - <programlisting> - #define string "world" - </programlisting> + <scons_example_file example="include" name="hello.h"> + </scons_example_file> <para> @@ -944,10 +961,8 @@ </para> - - <programlisting> - Program('hello.c', CPPPATH = '.') - </programlisting> + <scons_example_file example="include" name="SConstruct"> + </scons_example_file> <para> @@ -960,18 +975,12 @@ </para> - <screen> - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c -I. hello.c - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - % <userinput>edit hello.h</userinput> - [CHANGE THE CONTENTS OF hello.h] - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c -I. hello.c - cc -o hello hello.o - </screen> + <scons_output example="include" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -1016,9 +1025,14 @@ </para> - <programlisting> + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> Program('hello.c', CPPPATH = ['include', '/home/project/inc']) - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -1026,11 +1040,9 @@ </para> - <screen> - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c -Iinclude -I/home/project/inc hello.c - cc -o hello hello.o - </screen> + <scons_output example="ex5" os="posix"> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -1038,12 +1050,9 @@ </para> - <screen> - C:\><userinput>scons -Q hello.exe</userinput> - cl /Fohello.obj /c hello.c /nologo /Iinclude /I\home\project\inc - link /nologo /OUT:hello.exe hello.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="ex5" os="win32"> + <scons_output_command>scons -Q hello.exe</scons_output_command> + </scons_output> </section> @@ -1095,13 +1104,10 @@ </para> - <screen> - % <userinput>scons -Q --implicit-cache hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q --implicit-cache hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -1113,9 +1119,9 @@ </para> - <programlisting> + <sconstruct> SetOption('implicit_cache', 1) - </programlisting> + </sconstruct> <para> @@ -1178,13 +1184,10 @@ </para> - <screen> - % <userinput>scons -Q --implicit-deps-changed hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q --implicit-deps-changed hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -1216,13 +1219,10 @@ </para> - <screen> - % <userinput>scons -Q --implicit-deps-unchanged hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q --implicit-deps-unchanged hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -1340,24 +1340,29 @@ </para> - <programlisting> + <scons_example name="macroinc"> + <file name="hello.c" printme="1"> #define FOO_HEADER <foo.h> #include FOO_HEADER int main() { return FOO; } - </programlisting> - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c -I. hello.c - cc -o hello hello.o - % <userinput>edit foo.h</userinput> - [CHANGE CONTENTS OF foo.h] - % <userinput>scons -Q</userinput> - scons: `.' is up to date. - </screen> + </file> + <file name="SConstruct"> + Program('hello', 'hello.c', CPPPATH='.') + </file> + <file name="foo.h"> + #define FOO 42 + </file> + </scons_example> + + <scons_output example="macroinc" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE CONTENTS OF foo.h]" + >edit foo.h</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1388,22 +1393,35 @@ priori specification of the dependency file. The produced hello.d file is not found (or used) for unknown reasons. --> - <programlisting> + <scons_example name="parsedep"> + <file name="hello.c"> + #define FOO_HEADER <foo.h> + #include FOO_HEADER + + int main() { + return FOO; + } + </file> + <file name="SConstruct" printme="1"> obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.') SideEffect('hello.d', obj) ParseDepends('hello.d') Program('hello', obj) - </programlisting> - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c -MD -MF hello.d -I. hello.c - cc -o hello hello.o - % <userinput>edit foo.h</userinput> - [CHANGE CONTENTS OF foo.h] - % <userinput>scons -Q</userinput> - cc -o hello.o -c -MD -MF hello.d -I. hello.c - </screen> + </file> + <file name="foo.h"> + #define FOO 42 + </file> + <file name="hello.d"> + hello.o: hello.c foo.h + </file> + </scons_example> + + <scons_output example="parsedep" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE CONTENTS OF foo.h]" + >edit foo.h</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1413,7 +1431,25 @@ </para> - + <scons_example name="parsedeprebuild"> + <file name="hello.c"> + #define FOO_HEADER <foo.h> + #include FOO_HEADER + + int main() { + return FOO; + } + </file> + <file name="SConstruct"> + obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.') + SideEffect('hello.d', obj) + ParseDepends('hello.d') + Program('hello', obj) + </file> + <file name="foo.h"> + #define FOO 42 + </file> + </scons_example> <!-- <scons_output example="parsedeprebuild" os="posix"> @@ -1474,11 +1510,20 @@ </para> - <programlisting> + <scons_example name="ignore"> + <file name="SConstruct" printme="1"> hello_obj=Object('hello.c') hello = Program(hello_obj) Ignore(hello_obj, 'hello.h') - </programlisting> + </file> + <file name="hello.c"> + #include "hello.h" + int main() { printf("Hello, %s!\n", string); } + </file> + <file name="hello.h"> + #define string "world" + </file> + </scons_example> <!-- XXX mention that you can use lists for target and source? --> @@ -1541,21 +1586,23 @@ by default. </para> - <programlisting> + <scons_example name="ignore_explicit"> + <file name="SConstruct" printme="1"> hello_obj=Object('hello.c') hello = Program(hello_obj) Ignore('.',[hello,hello_obj]) - </programlisting> - - <screen> - % <userinput>scons -Q</userinput> - scons: `.' is up to date. - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q hello</userinput> - scons: `hello' is up to date. - </screen> + </file> + <file name="hello.c"> + #include "stdio.h" + int main() { printf("Hello!\n"); } + </file> + </scons_example> + + <scons_output example="ignore_explicit" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> </section> <section> @@ -1600,7 +1647,8 @@ </para> - <programlisting> + <scons_example name="no-Requires"> + <file name="SConstruct" printme="1"> import time version_c_text = """ @@ -1609,7 +1657,12 @@ open('version.c', 'w').write(version_c_text) hello = Program(['hello.c', 'version.c']) - </programlisting> + </file> + <file name="hello.c"> + extern char *date; + int main() { printf("Hello, %s! I was built: %s\n", date); } + </file> + </scons_example> <para> @@ -1624,20 +1677,13 @@ </para> - <screen> - % <userinput>scons -Q hello</userinput> - cc -o hello.o -c hello.c - cc -o version.o -c version.c - cc -o hello hello.o version.o - % <userinput>sleep 1</userinput> - % <userinput>scons -Q hello</userinput> - cc -o version.o -c version.c - cc -o hello hello.o version.o - % <userinput>sleep 1</userinput> - % <userinput>scons -Q hello</userinput> - cc -o version.o -c version.c - cc -o hello hello.o version.o - </screen> + <scons_output example="no-Requires"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>sleep 1</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>sleep 1</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> <para> @@ -1660,7 +1706,8 @@ </para> - <programlisting> + <scons_example name="Requires"> + <file name="SConstruct" printme="1"> import time version_c_text = """ @@ -1674,7 +1721,12 @@ LINKFLAGS = str(version_obj[0])) Requires(hello, version_obj) - </programlisting> + </file> + <file name="hello.c"> + extern char *date; + int main() { printf("Hello, %s! I was built: %s\n", date); } + </file> + </scons_example> <para> @@ -1702,27 +1754,16 @@ </para> - <screen> - % <userinput>scons -Q hello</userinput> - cc -o version.o -c version.c - cc -o hello.o -c hello.c - cc -o hello version.o hello.o - % <userinput>sleep 1</userinput> - % <userinput>scons -Q hello</userinput> - cc -o version.o -c version.c - scons: `hello' is up to date. - % <userinput>sleep 1</userinput> - % <userinput>edit hello.c</userinput> - [CHANGE THE CONTENTS OF hello.c] - % <userinput>scons -Q hello</userinput> - cc -o version.o -c version.c - cc -o hello.o -c hello.c - cc -o hello version.o hello.o - % <userinput>sleep 1</userinput> - % <userinput>scons -Q hello</userinput> - cc -o version.o -c version.c - scons: `hello' is up to date. - </screen> + <scons_output example="Requires"> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>sleep 1</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>sleep 1</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + <scons_output_command>sleep 1</scons_output_command> + <scons_output_command>scons -Q hello</scons_output_command> + </scons_output> </section> @@ -1738,10 +1779,15 @@ </para> - <programlisting> + <scons_example name="AlwaysBuild"> + <file name="SConstruct" printme="1"> hello = Program('hello.c') AlwaysBuild(hello) - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, %s!\n", string); } + </file> + </scons_example> <para> @@ -1752,13 +1798,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q</userinput> - cc -o hello hello.o - </screen> + <scons_output example="AlwaysBuild"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1777,13 +1820,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q hello.o</userinput> - scons: `hello.o' is up to date. - </screen> + <scons_output example="AlwaysBuild"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q hello.o</scons_output_command> + </scons_output> <!-- diff --git a/doc/user/environments.in b/doc/user/environments.in deleted file mode 100644 index 9f39347..0000000 --- a/doc/user/environments.in +++ /dev/null @@ -1,1752 +0,0 @@ -<!-- - - __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. - ---> - -<!-- - -=head1 More on construction environments - -As previously mentioned, a B<construction environment> is an object that -has a set of keyword/value pairs and a set of methods, and which is used -to tell Cons how target files should be built. This section describes -how Cons uses and expands construction environment values to control its -build behavior. - -=head2 Construction variable expansion - -Construction variables from a construction environment are expanded -by preceding the keyword with a C<%> (percent sign): - - Construction variables: - XYZZY => 'abracadabra', - - The string: "The magic word is: %XYZZY!" - expands to: "The magic word is: abracadabra!" - -A construction variable name may be surrounded by C<{> and C<}> (curly -braces), which are stripped as part of the expansion. This can -sometimes be necessary to separate a variable expansion from trailing -alphanumeric characters: - - Construction variables: - OPT => 'value1', - OPTION => 'value2', - - The string: "%OPT %{OPT}ION %OPTION %{OPTION}" - expands to: "value1 value1ION value2 value2" - -Construction variable expansion is recursive, that is, a string -containing C<%->expansions after substitution will be re-expanded until -no further substitutions can be made: - - Construction variables: - STRING => 'The result is: %FOO', - FOO => '%BAR', - BAR => 'final value', - - The string: "The string says: %STRING" - expands to: "The string says: The result is: final value" - -If a construction variable is not defined in an environment, then the -null string is substituted: - - Construction variables: - FOO => 'value1', - BAR => 'value2', - - The string: "%FOO <%NO_VARIABLE> %BAR" - expands to: "value1 <> value2" - -A doubled C<%%> will be replaced by a single C<%>: - - The string: "Here is a percent sign: %%" - expands to: "Here is a percent sign: %" - -=head2 Default construction variables - -When you specify no arguments when creating a new construction -environment: - - $env = new cons(); - -Cons creates a reference to a new, default construction -environment. This contains a number of construction variables and some -methods. At the present writing, the default construction variables on a -UNIX system are: - - CC => 'cc', - CFLAGS => '', - CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>', - CXX => '%CC', - CXXFLAGS => '%CFLAGS', - CXXCOM => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>', - INCDIRPREFIX => '-I', - INCDIRSUFFIX => '', - LINK => '%CXX', - LINKCOM => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS', - LINKMODULECOM => '%LD -r -o %> %<', - LIBDIRPREFIX => '-L', - LIBDIRSUFFIX => '', - AR => 'ar', - ARFLAGS => 'r', - ARCOM => ['%AR %ARFLAGS %> %<', '%RANLIB %>'], - RANLIB => 'ranlib', - AS => 'as', - ASFLAGS => '', - ASCOM => '%AS %ASFLAGS %< -o %>', - LD => 'ld', - LDFLAGS => '', - PREFLIB => 'lib', - SUFLIB => '.a', - SUFLIBS => '.so:.a', - SUFOBJ => '.o', - SIGNATURE => [ '*' => 'build' ], - ENV => { 'PATH' => '/bin:/usr/bin' }, - - -And on a Windows system (Windows NT), the default construction variables -are (unless the default rule style is set using the B<DefaultRules> -method): - - CC => 'cl', - CFLAGS => '/nologo', - CCCOM => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>', - CXXCOM => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>', - INCDIRPREFIX => '/I', - INCDIRSUFFIX => '', - LINK => 'link', - LINKCOM => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS', - LINKMODULECOM => '%LD /r /o %> %<', - LIBDIRPREFIX => '/LIBPATH:', - LIBDIRSUFFIX => '', - AR => 'lib', - ARFLAGS => '/nologo ', - ARCOM => "%AR %ARFLAGS /out:%> %<", - RANLIB => '', - LD => 'link', - LDFLAGS => '/nologo ', - PREFLIB => '', - SUFEXE => '.exe', - SUFLIB => '.lib', - SUFLIBS => '.dll:.lib', - SUFOBJ => '.obj', - SIGNATURE => [ '*' => 'build' ], - -These variables are used by the various methods associated with the -environment. In particular, any method that ultimately invokes an external -command will substitute these variables into the final command, as -appropriate. For example, the C<Objects> method takes a number of source -files and arranges to derive, if necessary, the corresponding object -files: - - Objects $env 'foo.c', 'bar.c'; - -This will arrange to produce, if necessary, F<foo.o> and F<bar.o>. The -command invoked is simply C<%CCCOM>, which expands, through substitution, -to the appropriate external command required to build each object. The -substitution rules will be discussed in detail in the next section. - -The construction variables are also used for other purposes. For example, -C<CPPPATH> is used to specify a colon-separated path of include -directories. These are intended to be passed to the C preprocessor and are -also used by the C-file scanning machinery to determine the dependencies -involved in a C Compilation. - -Variables beginning with underscore are created by various methods, -and should normally be considered ``internal'' variables. For example, -when a method is called which calls for the creation of an object from -a C source, the variable C<_IFLAGS> is created: this corresponds to the -C<-I> switches required by the C compiler to represent the directories -specified by C<CPPPATH>. - -Note that, for any particular environment, the value of a variable is set -once, and then never reset (to change a variable, you must create a new -environment. Methods are provided for copying existing environments for this -purpose). Some internal variables, such as C<_IFLAGS> are created on demand, -but once set, they remain fixed for the life of the environment. - -The C<CFLAGS>, C<LDFLAGS>, and C<ARFLAGS> variables all supply a place -for passing options to the compiler, loader, and archiver, respectively. - -The C<INCDIRPREFIX> and C<INCDIRSUFFIX> variables specify option -strings to be appended to the beginning and end, respectively, of each -include directory so that the compiler knows where to find F<.h> files. -Similarly, the C<LIBDIRPREFIX> and C<LIBDIRSUFFIX> variables specify the -option string to be appended to the beginning of and end, respectively, -of each directory that the linker should search for libraries. - -Another variable, C<ENV>, is used to determine the system environment during -the execution of an external command. By default, the only environment -variable that is set is C<PATH>, which is the execution path for a UNIX -command. For the utmost reproducibility, you should really arrange to set -your own execution path, in your top-level F<Construct> file (or perhaps by -importing an appropriate construction package with the Perl C<use> -command). The default variables are intended to get you off the ground. - -=head2 Expanding variables in construction commands - -Within a construction command, construction variables will be expanded -according to the rules described above. In addition to normal variable -expansion from the construction environment, construction commands also -expand the following pseudo-variables to insert the specific input and -output files in the command line that will be executed: - -=over 10 - -=item %> - -The target file name. In a multi-target command, this expands to the -first target mentioned.) - -=item %0 - -Same as C<%E<gt>>. - -=item %1, %2, ..., %9 - -These refer to the first through ninth input file, respectively. - -=item %E<lt> - -The full set of input file names. If any of these have been used -anywhere else in the current command line (via C<%1>, C<%2>, etc.), then -those will be deleted from the list provided by C<%E<lt>>. Consider the -following command found in a F<Conscript> file in the F<test> directory: - - Command $env 'tgt', qw(foo bar baz), qq( - echo %< -i %1 > %> - echo %< -i %2 >> %> - echo %< -i %3 >> %> - ); - -If F<tgt> needed to be updated, then this would result in the execution of -the following commands, assuming that no remapping has been established for -the F<test> directory: - - echo test/bar test/baz -i test/foo > test/tgt - echo test/foo test/baz -i test/bar >> test/tgt - echo test/foo test/bar -i test/baz >> test/tgt - -=back - -Any of the above pseudo-variables may be followed immediately by one of -the following suffixes to select a portion of the expanded path name: - - :a the absolute path to the file name - :b the directory plus the file name stripped of any suffix - :d the directory - :f the file name - :s the file name suffix - :F the file name stripped of any suffix - :S the absolute path path to a Linked source file - -Continuing with the above example, C<%E<lt>:f> would expand to C<foo bar baz>, -and C<%E<gt>:d> would expand to C<test>. - -There are additional C<%> elements which affect the command line(s): - -=over 10 - -=item %[ %] - -It is possible to programmatically rewrite part of the command by -enclosing part of it between C<%[> and C<%]>. This will call the -construction variable named as the first word enclosed in the brackets -as a Perl code reference; the results of this call will be used to -replace the contents of the brackets in the command line. For example, -given an existing input file named F<tgt.in>: - - @keywords = qw(foo bar baz); - $env = new cons(X_COMMA => sub { join(",", @_) }); - Command $env 'tgt', 'tgt.in', qq( - echo '# Keywords: %[X_COMMA @keywords %]' > %> - cat %< >> %> - ); - -This will execute: - - echo '# Keywords: foo,bar,baz' > tgt - cat tgt.in >> tgt - -=item %( %) - -Cons includes the text of the command line in the MD5 signature for a -build, so that targets get rebuilt if you change the command line (to -add or remove an option, for example). Command-line text in between -C<%(> and C<%)>, however, will be ignored for MD5 signature calculation. - -Internally, Cons uses C<%(> and C<%)> around include and library -directory options (C<-I> and C<-L> on UNIX systems, C</I> and -C</LIBPATH> on Windows NT) to avoid rebuilds just because the directory -list changes. Rebuilds occur only if the changed directory list causes -any included I<files> to change, and a changed include file is detected -by the MD5 signature calculation on the actual file contents. - -=back - -XXX DESCRIBE THE Literal() FUNCTION, TOO XXX - -=head2 Expanding construction variables in file names - -Cons expands construction variables in the source and target file names -passed to the various construction methods according to the expansion -rules described above: - - $env = new cons( - DESTDIR => 'programs', - SRCDIR => 'src', - ); - Program $env '%DESTDIR/hello', '%SRCDIR/hello.c'; - -This allows for flexible configuration, through the construction -environment, of directory names, suffixes, etc. - ---> - - <para> - - An <literal>environment</literal> - is a collection of values that - can affect how a program executes. - &SCons; distinguishes between three - different types of environments - that can affect the behavior of &SCons; itself - (subject to the configuration in the &SConscript; files), - as well as the compilers and other tools it executes: - - </para> - - <variablelist> - - <varlistentry> - <term>External Environment</term> - - <listitem> - <para> - - The <literal>external environment</literal> - is the set of variables in the user's environment - at the time the user runs &SCons;. - These variables are available within the &SConscript; files - through the Python <literal>os.environ</literal> dictionary. - See <xref linkend="sect-external-environments"></xref>, below. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>&ConsEnv;</term> - - <listitem> - <para> - - A &consenv; - is a distinct object creating within - a &SConscript; file and - and which contains values that - affect how &SCons; decides - what action to use to build a target, - and even to define which targets - should be built from which sources. - One of the most powerful features of &SCons; - is the ability to create multiple &consenvs;, - including the ability to clone a new, customized - &consenv; from an existing &consenv;. - See <xref linkend="sect-construction-environments"></xref>, below. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Execution Environment</term> - - <listitem> - <para> - - An <literal>execution environment</literal> - is the values that &SCons; sets - when executing an external - command (such as a compiler or linker) - to build one or more targets. - Note that this is not the same as - the <literal>external environment</literal> - (see above). - See <xref linkend="sect-execution-environments"></xref>, below. - - </para> - </listitem> - </varlistentry> - - </variablelist> - - <para> - - Unlike &Make;, &SCons; does not automatically - copy or import values between different environments - (with the exception of explicit clones of &consenvs;, - which inherit values from their parent). - This is a deliberate design choice - to make sure that builds are, - by default, repeatable regardless of - the values in the user's external environment. - This avoids a whole class of problems with builds - where a developer's local build works - because a custom variable setting - causes a different compiler or build option to be used, - but the checked-in change breaks the official build - because it uses different environment variable settings. - - </para> - - <para> - - Note that the &SConscript; writer can - easily arrange for variables to be - copied or imported between environments, - and this is often very useful - (or even downright necessary) - to make it easy for developers - to customize the build in appropriate ways. - The point is <emphasis>not</emphasis> - that copying variables between different environments - is evil and must always be avoided. - Instead, it should be up to the - implementer of the build system - to make conscious choices - about how and when to import - a variable from one environment to another, - making informed decisions about - striking the right balance - between making the build - repeatable on the one hand - and convenient to use on the other. - - </para> - - <section id="sect-external-environments"> - <title>Using Values From the External Environment</title> - - <para> - - The <literal>external environment</literal> - variable settings that - the user has in force - when executing &SCons; - are available through the normal Python - <envar>os.environ</envar> - dictionary. - This means that you must add an - <literal>import os</literal> statement - to any &SConscript; file - in which you want to use - values from the user's external environment. - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - import os - </file> - <file name="foo.c"> - int main() { } - </file> - </scons_example> - - <para> - - More usefully, you can use the - <envar>os.environ</envar> - dictionary in your &SConscript; - files to initialize &consenvs; - with values from the user's external environment. - See the next section, - <xref linkend="sect-construction-environments"></xref>, - for information on how to do this. - - </para> - - </section> - - <section id="sect-construction-environments"> - <title>Construction Environments</title> - - <para> - - It is rare that all of the software in a large, - complicated system needs to be built the same way. - For example, different source files may need different options - enabled on the command line, - or different executable programs need to be linked - with different libraries. - &SCons; accommodates these different build - requirements by allowing you to create and - configure multiple &consenvs; - that control how the software is built. - A &consenv; is an object - that has a number of associated - &consvars;, each with a name and a value. - (A construction environment also has an attached - set of &Builder; methods, - about which we'll learn more later.) - - </para> - - <section> - <title>Creating a &ConsEnv;: the &Environment; Function</title> - - <para> - - A &consenv; is created by the &Environment; method: - - </para> - - <sconstruct> - env = Environment() - </sconstruct> - - <para> - - By default, &SCons; initializes every - new construction environment - with a set of &consvars; - based on the tools that it finds on your system, - plus the default set of builder methods - necessary for using those tools. - The construction variables - are initialized with values describing - the C compiler, - the Fortran compiler, - the linker, - etc., - as well as the command lines to invoke them. - - </para> - - <para> - - When you initialize a construction environment - you can set the values of the - environment's &consvars; - to control how a program is built. - For example: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - env = Environment(CC = 'gcc', - CCFLAGS = '-O2') - - env.Program('foo.c') - </file> - <file name="foo.c"> - int main() { } - </file> - </scons_example> - - <para> - - The construction environment in this example - is still initialized with the same default - construction variable values, - except that the user has explicitly specified use of the - GNU C compiler &gcc;, - and further specifies that the <literal>-O2</literal> - (optimization level two) - flag should be used when compiling the object file. - In other words, the explicit initializations of - &cv-link-CC; and &cv-link-CCFLAGS; - override the default values in the newly-created - construction environment. - So a run from this example would look like: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Fetching Values From a &ConsEnv;</title> - - <para> - - You can fetch individual construction variables - using the normal syntax - for accessing individual named items in a Python dictionary: - - </para> - - <scons_example name="ex6"> - <file name="SConstruct" printme="1"> - env = Environment() - print "CC is:", env['CC'] - </file> - </scons_example> - - <para> - - This example &SConstruct; file doesn't build anything, - but because it's actually a Python script, - it will print the value of &cv-link-CC; for us: - - </para> - - <scons_output example="ex6"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - A construction environment, however, - is actually an object with associated methods, etc. - If you want to have direct access to only the - dictionary of construction variables, - you can fetch this using the &Dictionary; method: - - </para> - - <scons_example name="ex6b"> - <file name="SConstruct" printme="1"> - env = Environment(FOO = 'foo', BAR = 'bar') - dict = env.Dictionary() - for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']: - print "key = %s, value = %s" % (key, dict[key]) - </file> - </scons_example> - - <para> - - This &SConstruct; file - will print the specified dictionary items for us on POSIX - systems as follows: - - </para> - - <scons_output example="ex6b" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - And on Windows: - - </para> - - <scons_output example="ex6b" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - If you want to loop and print the values of - all of the construction variables in a construction environment, - the Python code to do that in sorted order might look something like: - - </para> - - <sconstruct> - env = Environment() - for item in sorted(env.Dictionary().items()): - print "construction variable = '%s', value = '%s'" % item - </sconstruct> - - </section> - - <section> - <title>Expanding Values From a &ConsEnv;: the &subst; Method</title> - - <para> - - Another way to get information from - a construction environment - is to use the &subst; method - on a string containing <literal>$</literal> expansions - of construction variable names. - As a simple example, - the example from the previous - section that used - <literal>env['CC']</literal> - to fetch the value of &cv-link-CC; - could also be written as: - - </para> - - <sconstruct> - env = Environment() - print "CC is:", env.subst('$CC') - </sconstruct> - - <para> - - One advantage of using - &subst; to expand strings is - that construction variables - in the result get re-expanded until - there are no expansions left in the string. - So a simple fetch of a value like - &cv-link-CCCOM;: - - </para> - - <sconstruct> - env = Environment(CCFLAGS = '-DFOO') - print "CCCOM is:", env['CCCOM'] - </sconstruct> - - <para> - - Will print the unexpanded value of &cv-CCCOM;, - showing us the construction - variables that still need to be expanded: - - </para> - - <screen> - % <userinput>scons -Q</userinput> - CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES - scons: `.' is up to date. - </screen> - - <para> - - Calling the &subst; method on <varname>$CCOM</varname>, - however: - - </para> - - <sconstruct> - env = Environment(CCFLAGS = '-DFOO') - print "CCCOM is:", env.subst('$CCCOM') - </sconstruct> - - <para> - - Will recursively expand all of - the construction variables prefixed - with <literal>$</literal> (dollar signs), - showing us the final output: - - </para> - - <screen> - % <userinput>scons -Q</userinput> - CCCOM is: gcc -DFOO -c -o - scons: `.' is up to date. - </screen> - - <para> - - Note that because we're not expanding this - in the context of building something - there are no target or source files - for &cv-link-TARGET; and &cv-link-SOURCES; to expand. - - </para> - - </section> - - <section> - <title>Handling Problems With Value Expansion</title> - - <para> - - If a problem occurs when expanding a construction variable, - by default it is expanded to <literal>''</literal> - (a null string), and will not cause scons to fail. - </para> - - <scons_example name="missing1"> - <file name="SConstruct" printme="1"> - env = Environment() - print "value is:", env.subst( '->$MISSING<-' ) - </file> - </scons_example> - - <scons_output example="missing1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - This default behaviour can be changed using the &AllowSubstExceptions; - function. - When a problem occurs with a variable expansion it generates - an exception, and the &AllowSubstExceptions; function controls - which of these exceptions are actually fatal and which are - allowed to occur safely. By default, &NameError; and &IndexError; - are the two exceptions that are allowed to occur: so instead of - causing scons to fail, these are caught, the variable expanded to - <literal>''</literal> - and scons execution continues. - To require that all construction variable names exist, and that - indexes out of range are not allowed, call &AllowSubstExceptions; - with no extra arguments. - </para> - - <scons_example name="missing2"> - <file name="SConstruct" printme="1"> - AllowSubstExceptions() - env = Environment() - print "value is:", env.subst( '->$MISSING<-' ) - </file> - </scons_example> - - <scons_output example="missing2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - This can also be used to allow other exceptions that might occur, - most usefully with the <literal>${...}</literal> construction - variable syntax. For example, this would allow zero-division to - occur in a variable expansion in addition to the default exceptions - allowed - </para> - - <scons_example name="missing3"> - <file name="SConstruct" printme="1"> - AllowSubstExceptions(IndexError, NameError, ZeroDivisionError) - env = Environment() - print "value is:", env.subst( '->${1 / 0}<-' ) - </file> - </scons_example> - - <scons_output example="missing3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - <sconstruct> - </sconstruct> - - <para> - If &AllowSubstExceptions; is called multiple times, each call - completely overwrites the previous list of allowed exceptions. - </para> - - </section> - - <section> - <title>Controlling the Default &ConsEnv;: the &DefaultEnvironment; Function</title> - - <para> - - All of the &Builder; functions that we've introduced so far, - like &Program; and &Library;, - actually use a default &consenv; - that contains settings - for the various compilers - and other tools that - &SCons; configures by default, - or otherwise knows about - and has discovered on your system. - The goal of the default construction environment - is to make many configurations to "just work" - to build software using - readily available tools - with a minimum of configuration changes. - - </para> - - <para> - - You can, however, control the settings - in the default construction environment - by using the &DefaultEnvironment; function - to initialize various settings: - - </para> - - <sconstruct> - - DefaultEnvironment(CC = '/usr/local/bin/gcc') - - </sconstruct> - - <para> - - When configured as above, - all calls to the &Program; - or &Object; Builder - will build object files with the - <filename>/usr/local/bin/gcc</filename> - compiler. - - </para> - - <para> - - Note that the &DefaultEnvironment; function - returns the initialized - default construction environment object, - which can then be manipulated like any - other construction environment. - So the following - would be equivalent to the - previous example, - setting the &cv-CC; - variable to <filename>/usr/local/bin/gcc</filename> - but as a separate step after - the default construction environment has been initialized: - - </para> - - <sconstruct> - - env = DefaultEnvironment() - env['CC'] = '/usr/local/bin/gcc' - - </sconstruct> - - <para> - - One very common use of the &DefaultEnvironment; function - is to speed up &SCons; initialization. - As part of trying to make most default - configurations "just work," - &SCons; will actually - search the local system for installed - compilers and other utilities. - This search can take time, - especially on systems with - slow or networked file systems. - If you know which compiler(s) and/or - other utilities you want to configure, - you can control the search - that &SCons; performs - by specifying some specific - tool modules with which to - initialize the default construction environment: - - </para> - - <sconstruct> - - env = DefaultEnvironment(tools = ['gcc', 'gnulink'], - CC = '/usr/local/bin/gcc') - - </sconstruct> - - <para> - - So the above example would tell &SCons; - to explicitly configure the default environment - to use its normal GNU Compiler and GNU Linker settings - (without having to search for them, - or any other utilities for that matter), - and specifically to use the compiler found at - <filename>/usr/local/bin/gcc</filename>. - - </para> - - </section> - - <section> - <title>Multiple &ConsEnvs;</title> - - <para> - - The real advantage of construction environments - is that you can create as many different construction - environments as you need, - each tailored to a different way to build - some piece of software or other file. - If, for example, we need to build - one program with the <literal>-O2</literal> flag - and another with the <literal>-g</literal> (debug) flag, - we would do this like so: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - opt = Environment(CCFLAGS = '-O2') - dbg = Environment(CCFLAGS = '-g') - - opt.Program('foo', 'foo.c') - - dbg.Program('bar', 'bar.c') - </file> - <file name="foo.c"> - int main() { } - </file> - <file name="bar.c"> - int main() { } - </file> - </scons_example> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - We can even use multiple construction environments to build - multiple versions of a single program. - If you do this by simply trying to use the - &b-link-Program; builder with both environments, though, - like this: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct" printme="1"> - opt = Environment(CCFLAGS = '-O2') - dbg = Environment(CCFLAGS = '-g') - - opt.Program('foo', 'foo.c') - - dbg.Program('foo', 'foo.c') - </file> - <file name="foo.c"> - int main() { } - </file> - </scons_example> - - <para> - - Then &SCons; generates the following error: - - </para> - - <scons_output example="ex3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - This is because the two &b-Program; calls have - each implicitly told &SCons; to generate an object file named - <filename>foo.o</filename>, - one with a &cv-link-CCFLAGS; value of - <literal>-O2</literal> - and one with a &cv-link-CCFLAGS; value of - <literal>-g</literal>. - &SCons; can't just decide that one of them - should take precedence over the other, - so it generates the error. - To avoid this problem, - we must explicitly specify - that each environment compile - <filename>foo.c</filename> - to a separately-named object file - using the &b-link-Object; builder, like so: - - </para> - - <scons_example name="ex4"> - <file name="SConstruct" printme="1"> - opt = Environment(CCFLAGS = '-O2') - dbg = Environment(CCFLAGS = '-g') - - o = opt.Object('foo-opt', 'foo.c') - opt.Program(o) - - d = dbg.Object('foo-dbg', 'foo.c') - dbg.Program(d) - </file> - <file name="foo.c"> - int main() { } - </file> - </scons_example> - - <para> - - Notice that each call to the &b-Object; builder - returns a value, - an internal &SCons; object that - represents the object file that will be built. - We then use that object - as input to the &b-Program; builder. - This avoids having to specify explicitly - the object file name in multiple places, - and makes for a compact, readable - &SConstruct; file. - Our &SCons; output then looks like: - - </para> - - <scons_output example="ex4"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Making Copies of &ConsEnvs;: the &Clone; Method</title> - - <para> - - Sometimes you want more than one construction environment - to share the same values for one or more variables. - Rather than always having to repeat all of the common - variables when you create each construction environment, - you can use the &Clone; method - to create a copy of a construction environment. - - </para> - - <para> - - Like the &Environment; call that creates a construction environment, - the &Clone; method takes &consvar; assignments, - which will override the values in the copied construction environment. - For example, suppose we want to use &gcc; - to create three versions of a program, - one optimized, one debug, and one with neither. - We could do this by creating a "base" construction environment - that sets &cv-link-CC; to &gcc;, - and then creating two copies, - one which sets &cv-link-CCFLAGS; for optimization - and the other which sets &cv-CCFLAGS; for debugging: - - </para> - - <scons_example name="ex5"> - <file name="SConstruct" printme="1"> - env = Environment(CC = 'gcc') - opt = env.Clone(CCFLAGS = '-O2') - dbg = env.Clone(CCFLAGS = '-g') - - env.Program('foo', 'foo.c') - - o = opt.Object('foo-opt', 'foo.c') - opt.Program(o) - - d = dbg.Object('foo-dbg', 'foo.c') - dbg.Program(d) - </file> - <file name="foo.c"> - int main() { } - </file> - </scons_example> - - <para> - - Then our output would look like: - - </para> - - <scons_output example="ex5"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Replacing Values: the &Replace; Method</title> - - <para> - - You can replace existing construction variable values - using the &Replace; method: - - </para> - - <scons_example name="Replace1"> - <file name="SConstruct" printme="1"> - env = Environment(CCFLAGS = '-DDEFINE1') - env.Replace(CCFLAGS = '-DDEFINE2') - env.Program('foo.c') - </file> - <file name="foo.c"> - int main() { } - </file> - </scons_example> - - <para> - - The replacing value - (<literal>-DDEFINE2</literal> in the above example) - completely replaces the value in the - construction environment: - - </para> - - <scons_output example="Replace1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - You can safely call &Replace; - for construction variables that - don't exist in the construction environment: - - </para> - - <scons_example name="Replace-nonexistent"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Replace(NEW_VARIABLE = 'xyzzy') - print "NEW_VARIABLE =", env['NEW_VARIABLE'] - </file> - </scons_example> - - <para> - - In this case, - the construction variable simply - gets added to the construction environment: - - </para> - - <scons_output example="Replace-nonexistent"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Because the variables - aren't expanded until the construction environment - is actually used to build the targets, - and because &SCons; function and method calls - are order-independent, - the last replacement "wins" - and is used to build all targets, - regardless of the order in which - the calls to Replace() are - interspersed with calls to - builder methods: - - </para> - - <scons_example name="Replace2"> - <file name="SConstruct" printme="1"> - env = Environment(CCFLAGS = '-DDEFINE1') - print "CCFLAGS =", env['CCFLAGS'] - env.Program('foo.c') - - env.Replace(CCFLAGS = '-DDEFINE2') - print "CCFLAGS =", env['CCFLAGS'] - env.Program('bar.c') - </file> - <file name="foo.c"> - int main() { } - </file> - <file name="bar.c"> - int main() { } - </file> - </scons_example> - - <para> - - The timing of when the replacement - actually occurs relative - to when the targets get built - becomes apparent - if we run &scons; without the <literal>-Q</literal> - option: - - </para> - - <scons_output example="Replace2"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - Because the replacement occurs while - the &SConscript; files are being read, - the &cv-link-CCFLAGS; - variable has already been set to - <literal>-DDEFINE2</literal> - by the time the &foo_o; target is built, - even though the call to the &Replace; - method does not occur until later in - the &SConscript; file. - - </para> - - </section> - - <section> - <title>Setting Values Only If They're Not Already Defined: the &SetDefault; Method</title> - - <para> - - Sometimes it's useful to be able to specify - that a construction variable should be - set to a value only if the construction environment - does not already have that variable defined - You can do this with the &SetDefault; method, - which behaves similarly to the <function>set_default</function> - method of Python dictionary objects: - - </para> - - <sconstruct> - env.SetDefault(SPECIAL_FLAG = '-extra-option') - </sconstruct> - - <para> - - This is especially useful - when writing your own <literal>Tool</literal> modules - to apply variables to construction environments. - <!-- - See <xref linkend="chap-tool-modules"></xref> - for more information about writing - Tool modules. - --> - - </para> - - </section> - - <section> - <title>Appending to the End of Values: the &Append; Method</title> - - <para> - - You can append a value to - an existing construction variable - using the &Append; method: - - </para> - - <scons_example name="ex8"> - <file name="SConstruct" printme="1"> - env = Environment(CCFLAGS = ['-DMY_VALUE']) - env.Append(CCFLAGS = ['-DLAST']) - env.Program('foo.c') - </file> - <file name="foo.c"> - int main() { } - </file> - </scons_example> - - <para> - - &SCons; then supplies both the <literal>-DMY_VALUE</literal> and - <literal>-DLAST</literal> flags when compiling the object file: - - </para> - - <scons_output example="ex8"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - If the construction variable doesn't already exist, - the &Append; method will create it: - - </para> - - <scons_example name="Append-nonexistent"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Append(NEW_VARIABLE = 'added') - print "NEW_VARIABLE =", env['NEW_VARIABLE'] - </file> - </scons_example> - - <para> - - Which yields: - - </para> - - <scons_output example="Append-nonexistent"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note that the &Append; function tries to be "smart" - about how the new value is appended to the old value. - If both are strings, the previous and new strings - are simply concatenated. - Similarly, if both are lists, - the lists are concatenated. - If, however, one is a string and the other is a list, - the string is added as a new element to the list. - - </para> - - </section> - - <section> - <title>Appending Unique Values: the &AppendUnique; Method</title> - - <para> - - Some times it's useful to add a new value - only if the existing construction variable - doesn't already contain the value. - This can be done using the &AppendUnique; method: - - </para> - - <sconstruct> - env.AppendUnique(CCFLAGS=['-g']) - </sconstruct> - - <para> - - In the above example, - the <literal>-g</literal> would be added - only if the &cv-CCFLAGS; variable - does not already contain a <literal>-g</literal> value. - - </para> - - </section> - - <section> - <title>Appending to the Beginning of Values: the &Prepend; Method</title> - - <para> - - You can append a value to the beginning of - an existing construction variable - using the &Prepend; method: - - </para> - - <scons_example name="ex9"> - <file name="SConstruct" printme="1"> - env = Environment(CCFLAGS = ['-DMY_VALUE']) - env.Prepend(CCFLAGS = ['-DFIRST']) - env.Program('foo.c') - </file> - <file name="foo.c"> - int main() { } - </file> - </scons_example> - - <para> - - &SCons; then supplies both the <literal>-DFIRST</literal> and - <literal>-DMY_VALUE</literal> flags when compiling the object file: - - </para> - - <scons_output example="ex9"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - If the construction variable doesn't already exist, - the &Prepend; method will create it: - - </para> - - <scons_example name="Prepend-nonexistent"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Prepend(NEW_VARIABLE = 'added') - print "NEW_VARIABLE =", env['NEW_VARIABLE'] - </file> - </scons_example> - - <para> - - Which yields: - - </para> - - <scons_output example="Prepend-nonexistent"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Like the &Append; function, - the &Prepend; function tries to be "smart" - about how the new value is appended to the old value. - If both are strings, the previous and new strings - are simply concatenated. - Similarly, if both are lists, - the lists are concatenated. - If, however, one is a string and the other is a list, - the string is added as a new element to the list. - - </para> - - </section> - - <section> - <title>Prepending Unique Values: the &PrependUnique; Method</title> - - <para> - - Some times it's useful to add a new value - to the beginning of a construction variable - only if the existing value - doesn't already contain the to-be-added value. - This can be done using the &PrependUnique; method: - - </para> - - <sconstruct> - env.PrependUnique(CCFLAGS=['-g']) - </sconstruct> - - <para> - - In the above example, - the <literal>-g</literal> would be added - only if the &cv-CCFLAGS; variable - does not already contain a <literal>-g</literal> value. - - </para> - - </section> - - </section> - - <section id="sect-execution-environments"> - <title>Controlling the Execution Environment for Issued Commands</title> - - <para> - - When &SCons; builds a target file, - it does not execute the commands with - the same external environment - that you used to execute &SCons;. - Instead, it uses the dictionary - stored in the &cv-link-ENV; construction variable - as the external environment - for executing commands. - - </para> - - <para> - - The most important ramification of this behavior - is that the &PATH; environment variable, - which controls where the operating system - will look for commands and utilities, - is not the same as in the external environment - from which you called &SCons;. - This means that &SCons; will not, by default, - necessarily find all of the tools - that you can execute from the command line. - - </para> - - <para> - - The default value of the &PATH; environment variable - on a POSIX system - is <literal>/usr/local/bin:/bin:/usr/bin</literal>. - The default value of the &PATH; environment variable - on a Windows system comes from the Windows registry - value for the command interpreter. - If you want to execute any commands--compilers, linkers, etc.--that - are not in these default locations, - you need to set the &PATH; value - in the &cv-ENV; dictionary - in your construction environment. - - </para> - - <para> - - The simplest way to do this is to initialize explicitly - the value when you create the construction environment; - this is one way to do that: - - </para> - - <sconstruct> - path = ['/usr/local/bin', '/bin', '/usr/bin'] - env = Environment(ENV = {'PATH' : path}) - </sconstruct> - - <para> - - Assign a dictionary to the &cv-ENV; - construction variable in this way - completely resets the external environment - so that the only variable that will be - set when external commands are executed - will be the &PATH; value. - If you want to use the rest of - the values in &cv-ENV; and only - set the value of &PATH;, - the most straightforward way is probably: - - </para> - - <sconstruct> - env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin'] - </sconstruct> - - <para> - - Note that &SCons; does allow you to define - the directories in the &PATH; in a string, - separated by the pathname-separator character - for your system (':' on POSIX systems, ';' on Windows): - - </para> - - <sconstruct> - env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin' - </sconstruct> - - <para> - - But doing so makes your &SConscript; file less portable, - (although in this case that may not be a huge concern - since the directories you list are likley system-specific, anyway). - - </para> - - <!-- - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Command('foo', [], '__ROOT__/usr/bin/printenv.py') - </file> - <file name="__ROOT__/usr/bin/printenv.py" chmod="0755"> - #!/usr/bin/env python - import os - import sys - if len(sys.argv) > 1: - keys = sys.argv[1:] - else: - keys = sorted(os.environ.keys()) - for key in keys: - print " " + key + "=" + os.environ[key] - </file> - </scons_example> - - <para> - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - --> - - <section> - <title>Propagating &PATH; From the External Environment</title> - - <para> - - You may want to propagate the external &PATH; - to the execution environment for commands. - You do this by initializing the &PATH; - variable with the &PATH; value from - the <literal>os.environ</literal> - dictionary, - which is Python's way of letting you - get at the external environment: - - </para> - - <sconstruct> - import os - env = Environment(ENV = {'PATH' : os.environ['PATH']}) - </sconstruct> - - <para> - - Alternatively, you may find it easier - to just propagate the entire external - environment to the execution environment - for commands. - This is simpler to code than explicity - selecting the &PATH; value: - - </para> - - <sconstruct> - import os - env = Environment(ENV = os.environ) - </sconstruct> - - <para> - - Either of these will guarantee that - &SCons; will be able to execute - any command that you can execute from the command line. - The drawback is that the build can behave - differently if it's run by people with - different &PATH; values in their environment--for example, - if both the <literal>/bin</literal> and - <literal>/usr/local/bin</literal> directories - have different &cc; commands, - then which one will be used to compile programs - will depend on which directory is listed - first in the user's &PATH; variable. - - </para> - - </section> - - <section> - <title>Adding to <varname>PATH</varname> Values in the Execution Environment</title> - - <para> - - One of the most common requirements - for manipulating a variable in the execution environment - is to add one or more custom directories to a search - like the <envar>$PATH</envar> variable on Linux or POSIX systems, - or the <envar>%PATH%</envar> variable on Windows, - so that a locally-installed compiler or other utility - can be found when &SCons; tries to execute it to update a target. - &SCons; provides &PrependENVPath; and &AppendENVPath; functions - to make adding things to execution variables convenient. - You call these functions by specifying the variable - to which you want the value added, - and then value itself. - So to add some <filename>/usr/local</filename> directories - to the <envar>$PATH</envar> and <envar>$LIB</envar> variables, - you might: - - </para> - - <sconstruct> - env = Environment(ENV = os.environ) - env.PrependENVPath('PATH', '/usr/local/bin') - env.AppendENVPath('LIB', '/usr/local/lib') - </sconstruct> - - <para> - - Note that the added values are strings, - and if you want to add multiple directories to - a variable like <envar>$PATH</envar>, - you must include the path separate character - (<literal>:</literal> on Linux or POSIX, - <literal>;</literal> on Windows) - in the string. - - </para> - - </section> - - </section> diff --git a/doc/user/environments.xml b/doc/user/environments.xml index eaf4ba3..9f39347 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -466,9 +466,14 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> import os - </programlisting> + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> <para> @@ -518,9 +523,9 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env = Environment() - </programlisting> + </sconstruct> <para> @@ -550,14 +555,17 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> - import os - + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> env = Environment(CC = 'gcc', CCFLAGS = '-O2') env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> <para> @@ -577,11 +585,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - gcc -o foo.o -c -O2 foo.c - gcc -o foo foo.o - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -596,10 +602,12 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="ex6"> + <file name="SConstruct" printme="1"> env = Environment() print "CC is:", env['CC'] - </programlisting> + </file> + </scons_example> <para> @@ -609,11 +617,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - CC is: cc - scons: `.' is up to date. - </screen> + <scons_output example="ex6"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -625,12 +631,14 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="ex6b"> + <file name="SConstruct" printme="1"> env = Environment(FOO = 'foo', BAR = 'bar') dict = env.Dictionary() for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']: print "key = %s, value = %s" % (key, dict[key]) - </programlisting> + </file> + </scons_example> <para> @@ -640,13 +648,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - key = OBJSUFFIX, value = .o - key = LIBSUFFIX, value = .a - key = PROGSUFFIX, value = - scons: `.' is up to date. - </screen> + <scons_output example="ex6b" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -654,13 +658,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - C:\><userinput>scons -Q</userinput> - key = OBJSUFFIX, value = .obj - key = LIBSUFFIX, value = .lib - key = PROGSUFFIX, value = .exe - scons: `.' is up to date. - </screen> + <scons_output example="ex6b" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -670,11 +670,11 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env = Environment() for item in sorted(env.Dictionary().items()): print "construction variable = '%s', value = '%s'" % item - </programlisting> + </sconstruct> </section> @@ -697,10 +697,10 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env = Environment() print "CC is:", env.subst('$CC') - </programlisting> + </sconstruct> <para> @@ -714,10 +714,10 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env = Environment(CCFLAGS = '-DFOO') print "CCCOM is:", env['CCCOM'] - </programlisting> + </sconstruct> <para> @@ -740,10 +740,10 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env = Environment(CCFLAGS = '-DFOO') print "CCCOM is:", env.subst('$CCCOM') - </programlisting> + </sconstruct> <para> @@ -781,16 +781,16 @@ environment, of directory names, suffixes, etc. (a null string), and will not cause scons to fail. </para> - <programlisting> + <scons_example name="missing1"> + <file name="SConstruct" printme="1"> env = Environment() - print "value is:", env.subst( '->$MISSING<-' ) - </programlisting> + print "value is:", env.subst( '->$MISSING<-' ) + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - value is: -><- - scons: `.' is up to date. - </screen> + <scons_output example="missing1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> This default behaviour can be changed using the &AllowSubstExceptions; @@ -808,18 +808,17 @@ environment, of directory names, suffixes, etc. with no extra arguments. </para> - <programlisting> + <scons_example name="missing2"> + <file name="SConstruct" printme="1"> AllowSubstExceptions() env = Environment() - print "value is:", env.subst( '->$MISSING<-' ) - </programlisting> + print "value is:", env.subst( '->$MISSING<-' ) + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - value is: - scons: *** NameError `MISSING' trying to evaluate `$MISSING' - File "/home/my/project/SConstruct", line 3, in <module> - </screen> + <scons_output example="missing2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> This can also be used to allow other exceptions that might occur, @@ -829,19 +828,19 @@ environment, of directory names, suffixes, etc. allowed </para> - <programlisting> + <scons_example name="missing3"> + <file name="SConstruct" printme="1"> AllowSubstExceptions(IndexError, NameError, ZeroDivisionError) env = Environment() - print "value is:", env.subst( '->${1 / 0}<-' ) - </programlisting> + print "value is:", env.subst( '->${1 / 0}<-' ) + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - value is: -><- - scons: `.' is up to date. - </screen> - <programlisting> - </programlisting> + <scons_output example="missing3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + <sconstruct> + </sconstruct> <para> If &AllowSubstExceptions; is called multiple times, each call @@ -881,11 +880,11 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> DefaultEnvironment(CC = '/usr/local/bin/gcc') - </programlisting> + </sconstruct> <para> @@ -915,12 +914,12 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env = DefaultEnvironment() env['CC'] = '/usr/local/bin/gcc' - </programlisting> + </sconstruct> <para> @@ -944,12 +943,12 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env = DefaultEnvironment(tools = ['gcc', 'gnulink'], CC = '/usr/local/bin/gcc') - </programlisting> + </sconstruct> <para> @@ -982,22 +981,26 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> opt = Environment(CCFLAGS = '-O2') dbg = Environment(CCFLAGS = '-g') opt.Program('foo', 'foo.c') dbg.Program('bar', 'bar.c') - </programlisting> - - <screen> - % <userinput>scons -Q</userinput> - cc -o bar.o -c -g bar.c - cc -o bar bar.o - cc -o foo.o -c -O2 foo.c - cc -o foo foo.o - </screen> + </file> + <file name="foo.c"> + int main() { } + </file> + <file name="bar.c"> + int main() { } + </file> + </scons_example> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1009,14 +1012,19 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> opt = Environment(CCFLAGS = '-O2') dbg = Environment(CCFLAGS = '-g') opt.Program('foo', 'foo.c') dbg.Program('foo', 'foo.c') - </programlisting> + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> <para> @@ -1024,12 +1032,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - - scons: *** Two environments with different actions were specified for the same target: foo.o - File "/home/my/project/SConstruct", line 6, in <module> - </screen> + <scons_output example="ex3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1052,7 +1057,8 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> opt = Environment(CCFLAGS = '-O2') dbg = Environment(CCFLAGS = '-g') @@ -1061,7 +1067,11 @@ environment, of directory names, suffixes, etc. d = dbg.Object('foo-dbg', 'foo.c') dbg.Program(d) - </programlisting> + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> <para> @@ -1079,13 +1089,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o foo-dbg.o -c -g foo.c - cc -o foo-dbg foo-dbg.o - cc -o foo-opt.o -c -O2 foo.c - cc -o foo-opt foo-opt.o - </screen> + <scons_output example="ex4"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -1119,7 +1125,8 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> env = Environment(CC = 'gcc') opt = env.Clone(CCFLAGS = '-O2') dbg = env.Clone(CCFLAGS = '-g') @@ -1131,7 +1138,11 @@ environment, of directory names, suffixes, etc. d = dbg.Object('foo-dbg', 'foo.c') dbg.Program(d) - </programlisting> + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> <para> @@ -1139,15 +1150,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - gcc -o foo.o -c foo.c - gcc -o foo foo.o - gcc -o foo-dbg.o -c -g foo.c - gcc -o foo-dbg foo-dbg.o - gcc -o foo-opt.o -c -O2 foo.c - gcc -o foo-opt foo-opt.o - </screen> + <scons_output example="ex5"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -1161,11 +1166,16 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="Replace1"> + <file name="SConstruct" printme="1"> env = Environment(CCFLAGS = '-DDEFINE1') env.Replace(CCFLAGS = '-DDEFINE2') env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> <para> @@ -1176,11 +1186,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o foo.o -c -DDEFINE2 foo.c - cc -o foo foo.o - </screen> + <scons_output example="Replace1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1190,11 +1198,13 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="Replace-nonexistent"> + <file name="SConstruct" printme="1"> env = Environment() env.Replace(NEW_VARIABLE = 'xyzzy') print "NEW_VARIABLE =", env['NEW_VARIABLE'] - </programlisting> + </file> + </scons_example> <para> @@ -1204,11 +1214,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - NEW_VARIABLE = xyzzy - scons: `.' is up to date. - </screen> + <scons_output example="Replace-nonexistent"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1226,7 +1234,8 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="Replace2"> + <file name="SConstruct" printme="1"> env = Environment(CCFLAGS = '-DDEFINE1') print "CCFLAGS =", env['CCFLAGS'] env.Program('foo.c') @@ -1234,7 +1243,14 @@ environment, of directory names, suffixes, etc. env.Replace(CCFLAGS = '-DDEFINE2') print "CCFLAGS =", env['CCFLAGS'] env.Program('bar.c') - </programlisting> + </file> + <file name="foo.c"> + int main() { } + </file> + <file name="bar.c"> + int main() { } + </file> + </scons_example> <para> @@ -1247,19 +1263,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - CCFLAGS = -DDEFINE1 - CCFLAGS = -DDEFINE2 - scons: done reading SConscript files. - scons: Building targets ... - cc -o bar.o -c -DDEFINE2 bar.c - cc -o bar bar.o - cc -o foo.o -c -DDEFINE2 foo.c - cc -o foo foo.o - scons: done building targets. - </screen> + <scons_output example="Replace2"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -1292,9 +1298,9 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env.SetDefault(SPECIAL_FLAG = '-extra-option') - </programlisting> + </sconstruct> <para> @@ -1322,11 +1328,16 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="ex8"> + <file name="SConstruct" printme="1"> env = Environment(CCFLAGS = ['-DMY_VALUE']) env.Append(CCFLAGS = ['-DLAST']) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> <para> @@ -1335,11 +1346,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o foo.o -c -DMY_VALUE -DLAST foo.c - cc -o foo foo.o - </screen> + <scons_output example="ex8"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1348,11 +1357,13 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="Append-nonexistent"> + <file name="SConstruct" printme="1"> env = Environment() env.Append(NEW_VARIABLE = 'added') print "NEW_VARIABLE =", env['NEW_VARIABLE'] - </programlisting> + </file> + </scons_example> <para> @@ -1360,11 +1371,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - NEW_VARIABLE = added - scons: `.' is up to date. - </screen> + <scons_output example="Append-nonexistent"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1393,9 +1402,9 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env.AppendUnique(CCFLAGS=['-g']) - </programlisting> + </sconstruct> <para> @@ -1419,11 +1428,16 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="ex9"> + <file name="SConstruct" printme="1"> env = Environment(CCFLAGS = ['-DMY_VALUE']) env.Prepend(CCFLAGS = ['-DFIRST']) env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> <para> @@ -1432,11 +1446,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o foo.o -c -DFIRST -DMY_VALUE foo.c - cc -o foo foo.o - </screen> + <scons_output example="ex9"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1445,11 +1457,13 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <scons_example name="Prepend-nonexistent"> + <file name="SConstruct" printme="1"> env = Environment() env.Prepend(NEW_VARIABLE = 'added') print "NEW_VARIABLE =", env['NEW_VARIABLE'] - </programlisting> + </file> + </scons_example> <para> @@ -1457,11 +1471,9 @@ environment, of directory names, suffixes, etc. </para> - <screen> - % <userinput>scons -Q</userinput> - NEW_VARIABLE = added - scons: `.' is up to date. - </screen> + <scons_output example="Prepend-nonexistent"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1492,9 +1504,9 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env.PrependUnique(CCFLAGS=['-g']) - </programlisting> + </sconstruct> <para> @@ -1563,10 +1575,10 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> path = ['/usr/local/bin', '/bin', '/usr/bin'] env = Environment(ENV = {'PATH' : path}) - </programlisting> + </sconstruct> <para> @@ -1583,9 +1595,9 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin'] - </programlisting> + </sconstruct> <para> @@ -1596,9 +1608,9 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin' - </programlisting> + </sconstruct> <para> @@ -1654,10 +1666,10 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> import os env = Environment(ENV = {'PATH' : os.environ['PATH']}) - </programlisting> + </sconstruct> <para> @@ -1670,10 +1682,10 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> import os env = Environment(ENV = os.environ) - </programlisting> + </sconstruct> <para> @@ -1717,11 +1729,11 @@ environment, of directory names, suffixes, etc. </para> - <programlisting> + <sconstruct> env = Environment(ENV = os.environ) env.PrependENVPath('PATH', '/usr/local/bin') env.AppendENVPath('LIB', '/usr/local/lib') - </programlisting> + </sconstruct> <para> diff --git a/doc/user/errors.in b/doc/user/errors.in deleted file mode 100644 index 0891bf8..0000000 --- a/doc/user/errors.in +++ /dev/null @@ -1,41 +0,0 @@ -<!-- - - __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> - - XXX - - </para> - - <section> - <title>XXX</title> - - <para> - - XXX - - </para> - - </section> diff --git a/doc/user/example.in b/doc/user/example.in deleted file mode 100644 index 0891bf8..0000000 --- a/doc/user/example.in +++ /dev/null @@ -1,41 +0,0 @@ -<!-- - - __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> - - XXX - - </para> - - <section> - <title>XXX</title> - - <para> - - XXX - - </para> - - </section> diff --git a/doc/user/factories.in b/doc/user/factories.in deleted file mode 100644 index cbe313a..0000000 --- a/doc/user/factories.in +++ /dev/null @@ -1,507 +0,0 @@ -<!-- - - __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> - - &SCons; provides a number of platform-independent functions, - called <literal>factories</literal>, - that perform common file system manipulations - like copying, moving or deleting files and directories, - or making directories. - These functions are <literal>factories</literal> - because they don't perform the action - at the time they're called, - they each return an &Action; object - that can be executed at the appropriate time. - - </para> - - <section> - <title>Copying Files or Directories: The &Copy; Factory</title> - - <para> - - Suppose you want to arrange to make a copy of a file, - and don't have a suitable pre-existing builder. - <footnote> - <para> - Unfortunately, in the early days of SCons design, - we used the name &Copy; for the function that - returns a copy of the environment, - otherwise that would be the logical choice for - a Builder that copies a file or directory tree - to a target location. - </para> - </footnote> - One way would be to use the &Copy; action factory - in conjunction with the &Command; builder: - - </para> - - <scons_example name="Copy1"> - <file name="SConstruct" printme="1"> - Command("file.out", "file.in", Copy("$TARGET", "$SOURCE")) - </file> - <file name="file.in">file.in</file> - </scons_example> - - <para> - - Notice that the action returned by the &Copy; factory - will expand the &cv-link-TARGET; and &cv-link-SOURCE; strings - at the time &file_out; is built, - and that the order of the arguments - is the same as that of a builder itself--that is, - target first, followed by source: - - </para> - - <scons_output example="Copy1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - You can, of course, name a file explicitly - instead of using &cv-TARGET; or &cv-SOURCE;: - - </para> - - <scons_example name="Copy2"> - <file name="SConstruct" printme="1"> - Command("file.out", [], Copy("$TARGET", "file.in")) - </file> - <file name="file.in">file.in</file> - </scons_example> - - <para> - - Which executes as: - - </para> - - <scons_output example="Copy2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - The usefulness of the &Copy; factory - becomes more apparent when - you use it in a list of actions - passed to the &Command; builder. - For example, suppose you needed to run a - file through a utility that only modifies files in-place, - and can't "pipe" input to output. - One solution is to copy the source file - to a temporary file name, - run the utility, - and then copy the modified temporary file to the target, - which the &Copy; factory makes extremely easy: - - </para> - - <scons_example name="Copy3"> - <file name="S" printme="1"> - Command("file.out", "file.in", - [ - Copy("tempfile", "$SOURCE"), - "modify tempfile", - Copy("$TARGET", "tempfile"), - ]) - </file> - <file name="SConstruct"> - env = DefaultEnvironment() - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - SConscript('S') - </file> - <file name="file.in">file.in</file> - <file name="modify" chmod="0755"> - touch $* - </file> - </scons_example> - - <para> - - The output then looks like: - - </para> - - <scons_output example="Copy3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Deleting Files or Directories: The &Delete; Factory</title> - - <para> - - If you need to delete a file, - then the &Delete; factory - can be used in much the same way as - the &Copy; factory. - For example, if we want to make sure that - the temporary file - in our last example doesn't exist before - we copy to it, - we could add &Delete; to the beginning - of the command list: - - </para> - - <scons_example name="Delete1"> - <file name="S" printme="1"> - Command("file.out", "file.in", - [ - Delete("tempfile"), - Copy("tempfile", "$SOURCE"), - "modify tempfile", - Copy("$TARGET", "tempfile"), - ]) - </file> - <file name="SConstruct"> - env = DefaultEnvironment() - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - SConscript('S') - </file> - <file name="file.in">file.in</file> - <file name="modify" chmod="0755"> - touch $* - </file> - </scons_example> - - <para> - - Which then executes as follows: - - </para> - - <scons_output example="Delete1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Of course, like all of these &Action; factories, - the &Delete; factory also expands - &cv-link-TARGET; and &cv-link-SOURCE; variables appropriately. - For example: - - </para> - - <scons_example name="Delete2"> - <file name="SConstruct" printme="1"> - Command("file.out", "file.in", - [ - Delete("$TARGET"), - Copy("$TARGET", "$SOURCE") - ]) - </file> - <file name="file.in">file.in</file> - </scons_example> - - <para> - - Executes as: - - </para> - - <scons_output example="Delete2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note, however, that you typically don't need to - call the &Delete; factory explicitly in this way; - by default, &SCons; deletes its target(s) - for you before executing any action. - - </para> - - <para> - - One word of caution about using the &Delete; factory: - it has the same variable expansions available - as any other factory, including the &cv-SOURCE; variable. - Specifying <literal>Delete("$SOURCE")</literal> - is not something you usually want to do! - - </para> - - </section> - - <section> - <title>Moving (Renaming) Files or Directories: The &Move; Factory</title> - - <para> - - The &Move; factory - allows you to rename a file or directory. - For example, if we don't want to copy the temporary file, - we could use: - - </para> - - <scons_example name="Move"> - <file name="S" printme="1"> - Command("file.out", "file.in", - [ - Copy("tempfile", "$SOURCE"), - "modify tempfile", - Move("$TARGET", "tempfile"), - ]) - </file> - <file name="SConstruct"> - env = DefaultEnvironment() - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - SConscript('S') - </file> - <file name="file.in">file.in</file> - <file name="modify" chmod="0755"> - touch $* - </file> - </scons_example> - - <para> - - Which would execute as: - - </para> - - <scons_output example="Move"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Updating the Modification Time of a File: The &Touch; Factory</title> - - <para> - - If you just need to update the - recorded modification time for a file, - use the &Touch; factory: - - </para> - - <scons_example name="Touch"> - <file name="S" printme="1"> - Command("file.out", "file.in", - [ - Copy("$TARGET", "$SOURCE"), - Touch("$TARGET"), - ]) - </file> - <file name="SConstruct"> - env = DefaultEnvironment() - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - SConscript('S') - </file> - <file name="file.in">file.in</file> - </scons_example> - - <para> - - Which executes as: - - </para> - - <scons_output example="Touch"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Creating a Directory: The &Mkdir; Factory</title> - - <para> - - If you need to create a directory, - use the &Mkdir; factory. - For example, if we need to process - a file in a temporary directory - in which the processing tool - will create other files that we don't care about, - you could use: - - </para> - - <scons_example name="Mkdir"> - <file name="S" printme="1"> - Command("file.out", "file.in", - [ - Delete("tempdir"), - Mkdir("tempdir"), - Copy("tempdir/${SOURCE.file}", "$SOURCE"), - "process tempdir", - Move("$TARGET", "tempdir/output_file"), - Delete("tempdir"), - ]) - </file> - <file name="SConstruct"> - env = DefaultEnvironment() - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - SConscript('S') - </file> - <file name="file.in">file.in</file> - <file name="process" chmod="0755"> - touch $* - </file> - </scons_example> - - <para> - - Which executes as: - - </para> - - <scons_output example="Mkdir"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Changing File or Directory Permissions: The &Chmod; Factory</title> - - <para> - - To change permissions on a file or directory, - use the &Chmod; factory. - The permission argument uses POSIX-style - permission bits and should typically - be expressed as an octal, - not decimal, number: - - </para> - - <scons_example name="Chmod"> - <file name="SConstruct" printme="1"> - Command("file.out", "file.in", - [ - Copy("$TARGET", "$SOURCE"), - Chmod("$TARGET", 0755), - ]) - </file> - <file name="file.in">file.in</file> - </scons_example> - - <para> - - Which executes: - - </para> - - <scons_output example="Chmod"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Executing an action immediately: the &Execute; Function</title> - - <para> - - We've been showing you how to use &Action; factories - in the &Command; function. - You can also execute an &Action; returned by a factory - (or actually, any &Action;) - at the time the &SConscript; file is read - by using the &Execute; function. - For example, if we need to make sure that - a directory exists before we build any targets, - - </para> - - <scons_example name="Execute"> - <file name="SConstruct" printme="1"> - Execute(Mkdir('__ROOT__/tmp/my_temp_directory')) - </file> - </scons_example> - - <para> - - Notice that this will - create the directory while - the &SConscript; file is being read: - - </para> - - <scons_output example="Execute"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - If you're familiar with Python, - you may wonder why you would want to use this - instead of just calling the native Python - <function>os.mkdir()</function> function. - The advantage here is that the &Mkdir; - action will behave appropriately if the user - specifies the &SCons; <option>-n</option> or - <option>-q</option> options--that is, - it will print the action but not actually - make the directory when <option>-n</option> is specified, - or make the directory but not print the action - when <option>-q</option> is specified. - - </para> - - <para> - - The &Execute; function returns the exit status - or return value of the underlying action being executed. - It will also print an error message if the action - fails and returns a non-zero value. - &SCons; will <emphasis>not</emphasis>, however, - actually stop the build if the action fails. - If you want the build to stop - in response to a failure in an action called by &Execute;, - you must do so by explicitly - checking the return value - and calling the &Exit; function - (or a Python equivalent): - - </para> - - <sconstruct> - if Execute(Mkdir('__ROOT__/tmp/my_temp_directory')): - # A problem occurred while making the temp directory. - Exit(1) - </sconstruct> - - </section> diff --git a/doc/user/factories.xml b/doc/user/factories.xml index f6ea89d..cbe313a 100644 --- a/doc/user/factories.xml +++ b/doc/user/factories.xml @@ -60,9 +60,12 @@ </para> - <programlisting> + <scons_example name="Copy1"> + <file name="SConstruct" printme="1"> Command("file.out", "file.in", Copy("$TARGET", "$SOURCE")) - </programlisting> + </file> + <file name="file.in">file.in</file> + </scons_example> <para> @@ -75,10 +78,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Copy("file.out", "file.in") - </screen> + <scons_output example="Copy1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -87,9 +89,12 @@ </para> - <programlisting> + <scons_example name="Copy2"> + <file name="SConstruct" printme="1"> Command("file.out", [], Copy("$TARGET", "file.in")) - </programlisting> + </file> + <file name="file.in">file.in</file> + </scons_example> <para> @@ -97,10 +102,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Copy("file.out", "file.in") - </screen> + <scons_output example="Copy2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -119,14 +123,26 @@ </para> - <programlisting> + <scons_example name="Copy3"> + <file name="S" printme="1"> Command("file.out", "file.in", [ Copy("tempfile", "$SOURCE"), "modify tempfile", Copy("$TARGET", "tempfile"), ]) - </programlisting> + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + <file name="modify" chmod="0755"> + touch $* + </file> + </scons_example> <para> @@ -134,12 +150,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Copy("tempfile", "file.in") - modify tempfile - Copy("file.out", "tempfile") - </screen> + <scons_output example="Copy3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -161,7 +174,8 @@ </para> - <programlisting> + <scons_example name="Delete1"> + <file name="S" printme="1"> Command("file.out", "file.in", [ Delete("tempfile"), @@ -169,7 +183,18 @@ "modify tempfile", Copy("$TARGET", "tempfile"), ]) - </programlisting> + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + <file name="modify" chmod="0755"> + touch $* + </file> + </scons_example> <para> @@ -177,13 +202,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Delete("tempfile") - Copy("tempfile", "file.in") - modify tempfile - Copy("file.out", "tempfile") - </screen> + <scons_output example="Delete1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -194,13 +215,16 @@ </para> - <programlisting> + <scons_example name="Delete2"> + <file name="SConstruct" printme="1"> Command("file.out", "file.in", [ Delete("$TARGET"), Copy("$TARGET", "$SOURCE") ]) - </programlisting> + </file> + <file name="file.in">file.in</file> + </scons_example> <para> @@ -208,11 +232,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Delete("file.out") - Copy("file.out", "file.in") - </screen> + <scons_output example="Delete2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -247,14 +269,26 @@ </para> - <programlisting> + <scons_example name="Move"> + <file name="S" printme="1"> Command("file.out", "file.in", [ Copy("tempfile", "$SOURCE"), "modify tempfile", Move("$TARGET", "tempfile"), ]) - </programlisting> + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + <file name="modify" chmod="0755"> + touch $* + </file> + </scons_example> <para> @@ -262,12 +296,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Copy("tempfile", "file.in") - modify tempfile - Move("file.out", "tempfile") - </screen> + <scons_output example="Move"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -282,13 +313,22 @@ </para> - <programlisting> + <scons_example name="Touch"> + <file name="S" printme="1"> Command("file.out", "file.in", [ Copy("$TARGET", "$SOURCE"), Touch("$TARGET"), ]) - </programlisting> + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + </scons_example> <para> @@ -296,11 +336,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Copy("file.out", "file.in") - Touch("file.out") - </screen> + <scons_output example="Touch"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -319,7 +357,8 @@ </para> - <programlisting> + <scons_example name="Mkdir"> + <file name="S" printme="1"> Command("file.out", "file.in", [ Delete("tempdir"), @@ -329,7 +368,18 @@ Move("$TARGET", "tempdir/output_file"), Delete("tempdir"), ]) - </programlisting> + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="file.in">file.in</file> + <file name="process" chmod="0755"> + touch $* + </file> + </scons_example> <para> @@ -337,15 +387,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Delete("tempdir") - Mkdir("tempdir") - Copy("tempdir/file.in", "file.in") - process tempdir - Move("file.out", "tempdir/output_file") - scons: *** [file.out] tempdir/output_file: No such file or directory - </screen> + <scons_output example="Mkdir"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -363,13 +407,16 @@ </para> - <programlisting> + <scons_example name="Chmod"> + <file name="SConstruct" printme="1"> Command("file.out", "file.in", [ Copy("$TARGET", "$SOURCE"), Chmod("$TARGET", 0755), ]) - </programlisting> + </file> + <file name="file.in">file.in</file> + </scons_example> <para> @@ -377,11 +424,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Copy("file.out", "file.in") - Chmod("file.out", 0755) - </screen> + <scons_output example="Chmod"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -401,9 +446,11 @@ </para> - <programlisting> - Execute(Mkdir('/tmp/my_temp_directory')) - </programlisting> + <scons_example name="Execute"> + <file name="SConstruct" printme="1"> + Execute(Mkdir('__ROOT__/tmp/my_temp_directory')) + </file> + </scons_example> <para> @@ -413,15 +460,9 @@ </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - Mkdir("/tmp/my_temp_directory") - scons: done reading SConscript files. - scons: Building targets ... - scons: `.' is up to date. - scons: done building targets. - </screen> + <scons_output example="Execute"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -457,10 +498,10 @@ </para> - <programlisting> - if Execute(Mkdir('/tmp/my_temp_directory')): + <sconstruct> + if Execute(Mkdir('__ROOT__/tmp/my_temp_directory')): # A problem occurred while making the temp directory. Exit(1) - </programlisting> + </sconstruct> </section> diff --git a/doc/user/file-removal.in b/doc/user/file-removal.in deleted file mode 100644 index 1d1b604..0000000 --- a/doc/user/file-removal.in +++ /dev/null @@ -1,223 +0,0 @@ -<!-- - - __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> - - There are two occasions when &SCons; will, - by default, remove target files. - The first is when &SCons; determines that - an target file needs to be rebuilt - and removes the existing version of the target - before executing - The second is when &SCons; is invoked with the - <literal>-c</literal> option to "clean" - a tree of its built targets. - - These behaviours can be suppressed with the - &Precious; and &NoClean; functions, respectively. - - </para> - - <section> - <title>Preventing target removal during build: the &Precious; Function</title> - - <para> - - By default, &SCons; removes targets before building them. - Sometimes, however, this is not what you want. - For example, you may want to update a library incrementally, - not by having it deleted and then rebuilt from all - of the constituent object files. - In such cases, you can use the - &Precious; method to prevent - &SCons; from removing the target before it is built: - - </para> - - <scons_example name="precious-ex1"> - <file name="SConstruct" printme="1"> - env = Environment(RANLIBCOM='') - lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) - env.Precious(lib) - </file> - <file name="f1.c"> - int f1() { } - </file> - <file name="f2.c"> - int f2() { } - </file> - <file name="f3.c"> - int f3() { } - </file> - </scons_example> - - <para> - - Although the output doesn't look any different, - &SCons; does not, in fact, - delete the target library before rebuilding it: - - </para> - - <scons_output example="precious-ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - &SCons; will, however, still delete files marked as &Precious; - when the <literal>-c</literal> option is used. - - </para> - - </section> - - <section> - <title>Preventing target removal during clean: the &NoClean; Function</title> - - <para> - - By default, &SCons; removes all built targets when invoked - with the <literal>-c</literal> option to clean a source tree - of built targets. - Sometimes, however, this is not what you want. - For example, you may want to remove only intermediate generated files - (such as object files), - but leave the final targets - (the libraries) - untouched. - - In such cases, you can use the &NoClean; method to prevent &SCons; - from removing a target during a clean: - - </para> - - <scons_example name="noclean-ex1"> - <file name="SConstruct" printme="1"> - env = Environment(RANLIBCOM='') - lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) - env.NoClean(lib) - </file> - <file name="f1.c"> - int f1() { } - </file> - <file name="f2.c"> - int f2() { } - </file> - <file name="f3.c"> - int f3() { } - </file> - </scons_example> - - <para> - - Notice that the <filename>libfoo.a</filename> - is not listed as a removed file: - - </para> - - <scons_output example="noclean-ex1"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -c</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Removing additional files during clean: the &Clean; Function</title> - - <para> - - There may be additional files that you want removed - when the <literal>-c</literal> option is used, - but which &SCons; doesn't know about - because they're not normal target files. - For example, perhaps a command you invoke - creates a log file as - part of building the target file you want. - You would like the log file cleaned, - but you don't want to have to teach - SCons that the command - "builds" two files. - - </para> - - <para> - - You can use the &Clean; function to arrange for additional files - to be removed when the <literal>-c</literal> option is used. - Notice, however, that the &Clean; function takes two arguments, - and the <emphasis>second</emphasis> argument - is the name of the additional file you want cleaned - (<filename>foo.log</filename> in this example): - - </para> - - <scons_example name="clean-ex1"> - <file name="S" printme="1"> - t = Command('foo.out', 'foo.in', 'build -o $TARGET $SOURCE') - Clean(t, 'foo.log') - </file> - <file name="SConstruct"> - env = DefaultEnvironment() - import os - env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() - SConscript('S') - </file> - <file name="foo.in"> - foo.in - </file> - <file name="foo.log"> - foo.log - </file> - <file name="build" chmod="0755"> - cat $3 > $2 - </file> - </scons_example> - - <para> - - The first argument is the target with which you want - the cleaning of this additional file associated. - In the above example, - we've used the return value from the - &Command; function, - which represents the - <filename>foo.out</filename> - target. - Now whenever the - <filename>foo.out</filename> target is cleaned - by the <literal>-c</literal> option, - the <filename>foo.log</filename> file - will be removed as well: - - </para> - - <scons_output example="clean-ex1"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q -c</scons_output_command> - </scons_output> - - </section> diff --git a/doc/user/file-removal.xml b/doc/user/file-removal.xml index bfec7ac..1d1b604 100644 --- a/doc/user/file-removal.xml +++ b/doc/user/file-removal.xml @@ -56,11 +56,22 @@ </para> - <programlisting> + <scons_example name="precious-ex1"> + <file name="SConstruct" printme="1"> env = Environment(RANLIBCOM='') lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) env.Precious(lib) - </programlisting> + </file> + <file name="f1.c"> + int f1() { } + </file> + <file name="f2.c"> + int f2() { } + </file> + <file name="f3.c"> + int f3() { } + </file> + </scons_example> <para> @@ -70,13 +81,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o f1.o -c f1.c - cc -o f2.o -c f2.c - cc -o f3.o -c f3.c - ar rc libfoo.a f1.o f2.o f3.o - </screen> + <scons_output example="precious-ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -107,11 +114,22 @@ </para> - <programlisting> + <scons_example name="noclean-ex1"> + <file name="SConstruct" printme="1"> env = Environment(RANLIBCOM='') lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) env.NoClean(lib) - </programlisting> + </file> + <file name="f1.c"> + int f1() { } + </file> + <file name="f2.c"> + int f2() { } + </file> + <file name="f3.c"> + int f3() { } + </file> + </scons_example> <para> @@ -120,21 +138,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o f1.o -c f1.c - cc -o f2.o -c f2.c - cc -o f3.o -c f3.c - ar rc libfoo.a f1.o f2.o f3.o - % <userinput>scons -c</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Cleaning targets ... - Removed f1.o - Removed f2.o - Removed f3.o - scons: done cleaning targets. - </screen> + <scons_output example="noclean-ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -c</scons_output_command> + </scons_output> </section> @@ -168,10 +175,27 @@ </para> - <programlisting> + <scons_example name="clean-ex1"> + <file name="S" printme="1"> t = Command('foo.out', 'foo.in', 'build -o $TARGET $SOURCE') Clean(t, 'foo.log') - </programlisting> + </file> + <file name="SConstruct"> + env = DefaultEnvironment() + import os + env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + SConscript('S') + </file> + <file name="foo.in"> + foo.in + </file> + <file name="foo.log"> + foo.log + </file> + <file name="build" chmod="0755"> + cat $3 > $2 + </file> + </scons_example> <para> @@ -191,12 +215,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - build -o foo.out foo.in - % <userinput>scons -Q -c</userinput> - Removed foo.out - Removed foo.log - </screen> + <scons_output example="clean-ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c</scons_output_command> + </scons_output> </section> diff --git a/doc/user/functions.in b/doc/user/functions.in deleted file mode 100644 index 1b1b280..0000000 --- a/doc/user/functions.in +++ /dev/null @@ -1,38 +0,0 @@ -<!-- - - __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> - -This appendix contains descriptions of all of the -function and construction environment methods -in this version of &SCons; - -</para> - -<variablelist> - -&functions-gen; - -</variablelist> diff --git a/doc/user/gettext.in b/doc/user/gettext.in deleted file mode 100644 index ba09071..0000000 --- a/doc/user/gettext.in +++ /dev/null @@ -1,351 +0,0 @@ -<!-- - - __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> - The &t-link-gettext; toolset supports internationalization and localization - of SCons-based projects. Builders provided by &t-link-gettext; automatize - generation and updates of translation files. You can manage translations and - translation templates similarly to how it's done with autotools. - </para> - - <section> - <title>Prerequisites</title> - <para> - To follow examples provided in this chapter set up your operating system to - support two or more languages. In following examples we use locales - <literal>en_US</literal>, <literal>de_DE</literal>, and - <literal>pl_PL</literal>. - </para> - - <para> - Ensure, that you have <ulink - url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext - utilities</ulink> installed on your system. - </para> - - <para> - To edit translation files you may wish to install <ulink - url="http://www.poedit.net/">poedit</ulink> editor. - </para> - </section> - - <section> - <title>Simple project</title> - <para> - Let's start with a very simple project, the "Hello world" program - for example - <scons_example name="ex1"> - <file name="hello.c" printme="1"> - /* hello.c */ - #include <stdio.h> - int main(int argc, char* argv[]) - { - printf("Hello world\n"); - return 0; - } - </file> - </scons_example> - - Prepare a <filename>SConstruct</filename> to compile the program - as usual. - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - # SConstruct - env = Environment() - hello = Program(["hello.c"]) - </file> - </scons_example> - </para> - - <para> - Now we'll convert the project to a multi-lingual one. If you don't - already have <ulink - url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext - utilities</ulink> installed, install them from your preffered - package repository, or download from <ulink - url="http://ftp.gnu.org/gnu/gettext/"> - http://ftp.gnu.org/gnu/gettext/</ulink>. For the purpose of this example, - you should have following three locales installed on your system: - <literal>en_US</literal>, <literal>de_DE</literal> and - <literal>pl_PL</literal>. On debian, for example, you may enable certain - locales through <command>dpkg-reconfigure locales</command>. - </para> - - <para> - First prepare the <filename>hello.c</filename> program for - internationalization. Change the previous code so it reads as follows: - <scons_example name="ex3"> - <file name="hello.c" printme="1"> - /* hello.c */ - #include <stdio.h> - #include <libintl.h> - #include <locale.h> - int main(int argc, char* argv[]) - { - bindtextdomain("hello", "locale"); - setlocale(LC_ALL, ""); - textdomain("hello"); - printf(gettext("Hello world\n")); - return 0; - } - </file> - </scons_example> - Detailed recipes for such conversion can - be found at <ulink - url="http://www.gnu.org/software/gettext/manual/gettext.html#Sources"> - http://www.gnu.org/software/gettext/manual/gettext.html#Sources</ulink>. - The <function>gettext("...")</function> has two purposes. - First, it marks messages for the <command>xgettext(1)</command> program, which - we will use to extract from the sources the messages for localization. - Second, it calls the <literal>gettext</literal> library internals to - translate the message at runtime. - </para> - - <para> - Now we shall instruct SCons how to generate and maintain translation files. - For that, use the &b-link-Translate; builder and &b-link-MOFiles; builder. - The first one takes source files, extracts internationalized - messages from them, creates so-called <literal>POT</literal> file - (translation template), and then creates <literal>PO</literal> translation - files, one for each requested language. Later, during the development - lifecycle, the builder keeps all these files up-to date. The - &b-link-MOFiles; builder compiles the <literal>PO</literal> files to binary - form. Then install the <literal>MO</literal> files under directory - called <filename>locale</filename>. - </para> - - <para> The completed - <filename>SConstruct</filename> is as follows: - <scons_example name="ex4"> - <file name="SConstruct" printme="1"> - # SConstruct - env = Environment( tools = ['default', 'gettext'] ) - hello = env.Program(["hello.c"]) - env['XGETTEXTFLAGS'] = [ - '--package-name=%s' % 'hello', - '--package-version=%s' % '1.0', - ] - po = env.Translate(["pl","en", "de"], ["hello.c"], POAUTOINIT = 1) - mo = env.MOFiles(po) - InstallAs(["locale/en/LC_MESSAGES/hello.mo"], ["en.mo"]) - InstallAs(["locale/pl/LC_MESSAGES/hello.mo"], ["pl.mo"]) - InstallAs(["locale/de/LC_MESSAGES/hello.mo"], ["de.mo"]) - </file> - </scons_example> - </para> - <para> - Generate the translation files with <command>scons po-update</command>. - You should see the output from SCons simillar to this: - <screen> - user@host:$ scons po-update - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - Entering '/home/ptomulik/projects/tmp' - xgettext --package-name=hello --package-version=1.0 -o - hello.c - Leaving '/home/ptomulik/projects/tmp' - Writting 'messages.pot' (new file) - msginit --no-translator -l pl -i messages.pot -o pl.po - Created pl.po. - msginit --no-translator -l en -i messages.pot -o en.po - Created en.po. - msginit --no-translator -l de -i messages.pot -o de.po - Created de.po. - scons: done building targets. - </screen> - </para> - - <para> - If everything is right, you should see following new files. - <screen> - user@host:$ ls *.po* - de.po en.po messages.pot pl.po - </screen> - </para> - - <para> - Open <filename>en.po</filename> in <command>poedit</command> and provide - the English translation to message <literal>"Hello world\n"</literal>. Do the - same for <filename>de.po</filename> (deutsch) and - <filename>pl.po</filename> (polish). Let the translations be, for example: - <itemizedlist> - <listitem><para> - <literal>en: "Welcome to beautiful world!\n"</literal> - </para></listitem> - <listitem><para> - <literal>de: "Hallo Welt!\n"</literal> - </para></listitem> - <listitem><para> - <literal>pl: "Witaj swiecie!\n"</literal> - </para></listitem> - </itemizedlist> - </para> - <para> - Now compile the project by executing <command>scons</command>. The - output should be similar to this: - <screen> - user@host:$ scons - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - msgfmt -c -o de.mo de.po - msgfmt -c -o en.mo en.po - gcc -o hello.o -c hello.c - gcc -o hello hello.o - Install file: "de.mo" as "locale/de/LC_MESSAGES/hello.mo" - Install file: "en.mo" as "locale/en/LC_MESSAGES/hello.mo" - msgfmt -c -o pl.mo pl.po - Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo" - scons: done building targets. - </screen> - SCons automatically compiled the <literal>PO</literal> files to binary format - <literal>MO</literal>, and the <literal>InstallAs</literal> lines installed - these files under <filename>locale</filename> folder. - </para> - <para> - Your program should be now ready. You may try it as follows (linux): - <screen> - user@host:$ LANG=en_US.UTF-8 ./hello - Welcome to beautiful world - </screen> - <screen> - user@host:$ LANG=de_DE.UTF-8 ./hello - Hallo Welt - </screen> - <screen> - user@host:$ LANG=pl_PL.UTF-8 ./hello - Witaj swiecie - </screen> - </para> - <para> - To demonstrate the further life of translation files, let's change Polish - translation (<command>poedit pl.po</command>) to <literal>"Witaj drogi - swiecie\n"</literal>. Run <command>scons</command> to see how scons - reacts to this - <screen> - user@host:$scons - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - msgfmt -c -o pl.mo pl.po - Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo" - scons: done building targets. - </screen> - </para> - <para> - Now, open <filename>hello.c</filename> and add another one - <literal>printf</literal> line with new message. - <scons_example name="ex5"> - <file name="hello.c" printme="1"> - /* hello.c */ - #include <stdio.h> - #include <libintl.h> - #include <locale.h> - int main(int argc, char* argv[]) - { - bindtextdomain("hello", "locale"); - setlocale(LC_ALL, ""); - textdomain("hello"); - printf(gettext("Hello world\n")); - printf(gettext("and good bye\n")); - return 0; - } - </file> - </scons_example> - </para> - <para> - Compile project with <command>scons</command>. This time, the - <command>msgmerge(1)</command> program is used by SCons to update - <literal>PO</literal> file. The output from compilation is like: - <screen> - user@host:$scons - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - Entering '/home/ptomulik/projects/tmp' - xgettext --package-name=hello --package-version=1.0 -o - hello.c - Leaving '/home/ptomulik/projects/tmp' - Writting 'messages.pot' (messages in file were outdated) - msgmerge --update de.po messages.pot - ... done. - msgfmt -c -o de.mo de.po - msgmerge --update en.po messages.pot - ... done. - msgfmt -c -o en.mo en.po - gcc -o hello.o -c hello.c - gcc -o hello hello.o - Install file: "de.mo" as "locale/de/LC_MESSAGES/hello.mo" - Install file: "en.mo" as "locale/en/LC_MESSAGES/hello.mo" - msgmerge --update pl.po messages.pot - ... done. - msgfmt -c -o pl.mo pl.po - Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo" - scons: done building targets. - </screen> - </para> - <para> - The next example demonstrates what happens if we change the source code - in such way that the internationalized messages do not change. The answer - is that none of translation files (<literal>POT</literal>, - <literal>PO</literal>) are touched (i.e. no content changes, no - creation/modification time changed and so on). Let's append another - line to the program (after the last printf), so its code becomes: - <scons_example name="ex6"> - <file name="hello.c" printme="1"> - /* hello.c */ - #include <stdio.h> - #include <libintl.h> - #include <locale.h> - int main(int argc, char* argv[]) - { - bindtextdomain("hello", "locale"); - setlocale(LC_ALL, ""); - textdomain("hello"); - printf(gettext("Hello world\n")); - printf(gettext("and good bye\n")); - printf("----------------\n"); - return a; - } - </file> - </scons_example> - Compile the project. You'll see on your screen - <screen> - user@host:$scons - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - Entering '/home/ptomulik/projects/tmp' - xgettext --package-name=hello --package-version=1.0 -o - hello.c - Leaving '/home/ptomulik/projects/tmp' - Not writting 'messages.pot' (messages in file found to be up-to-date) - gcc -o hello.o -c hello.c - gcc -o hello hello.o - scons: done building targets. - </screen> - As you see, the internationalized messages ditn't change, so the - <literal>POT</literal> and the rest of translation files have not - even been touched. - </para> - </section> diff --git a/doc/user/gettext.xml b/doc/user/gettext.xml index d929203..ba09071 100644 --- a/doc/user/gettext.xml +++ b/doc/user/gettext.xml @@ -40,12 +40,14 @@ </para> <para> - Ensure, that you have <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext + Ensure, that you have <ulink + url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext utilities</ulink> installed on your system. </para> <para> - To edit translation files you may wish to install <ulink url="http://www.poedit.net/">poedit</ulink> editor. + To edit translation files you may wish to install <ulink + url="http://www.poedit.net/">poedit</ulink> editor. </para> </section> @@ -54,7 +56,8 @@ <para> Let's start with a very simple project, the "Hello world" program for example - <programlisting> + <scons_example name="ex1"> + <file name="hello.c" printme="1"> /* hello.c */ #include <stdio.h> int main(int argc, char* argv[]) @@ -62,22 +65,27 @@ printf("Hello world\n"); return 0; } - </programlisting> + </file> + </scons_example> Prepare a <filename>SConstruct</filename> to compile the program as usual. - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> # SConstruct env = Environment() hello = Program(["hello.c"]) - </programlisting> + </file> + </scons_example> </para> <para> Now we'll convert the project to a multi-lingual one. If you don't - already have <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext + already have <ulink + url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext utilities</ulink> installed, install them from your preffered - package repository, or download from <ulink url="http://ftp.gnu.org/gnu/gettext/"> + package repository, or download from <ulink + url="http://ftp.gnu.org/gnu/gettext/"> http://ftp.gnu.org/gnu/gettext/</ulink>. For the purpose of this example, you should have following three locales installed on your system: <literal>en_US</literal>, <literal>de_DE</literal> and @@ -88,7 +96,8 @@ <para> First prepare the <filename>hello.c</filename> program for internationalization. Change the previous code so it reads as follows: - <programlisting> + <scons_example name="ex3"> + <file name="hello.c" printme="1"> /* hello.c */ #include <stdio.h> #include <libintl.h> @@ -101,9 +110,11 @@ printf(gettext("Hello world\n")); return 0; } - </programlisting> + </file> + </scons_example> Detailed recipes for such conversion can - be found at <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html#Sources"> + be found at <ulink + url="http://www.gnu.org/software/gettext/manual/gettext.html#Sources"> http://www.gnu.org/software/gettext/manual/gettext.html#Sources</ulink>. The <function>gettext("...")</function> has two purposes. First, it marks messages for the <command>xgettext(1)</command> program, which @@ -127,7 +138,8 @@ <para> The completed <filename>SConstruct</filename> is as follows: - <programlisting> + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> # SConstruct env = Environment( tools = ['default', 'gettext'] ) hello = env.Program(["hello.c"]) @@ -140,7 +152,8 @@ InstallAs(["locale/en/LC_MESSAGES/hello.mo"], ["en.mo"]) InstallAs(["locale/pl/LC_MESSAGES/hello.mo"], ["pl.mo"]) InstallAs(["locale/de/LC_MESSAGES/hello.mo"], ["de.mo"]) - </programlisting> + </file> + </scons_example> </para> <para> Generate the translation files with <command>scons po-update</command>. @@ -244,7 +257,8 @@ <para> Now, open <filename>hello.c</filename> and add another one <literal>printf</literal> line with new message. - <programlisting> + <scons_example name="ex5"> + <file name="hello.c" printme="1"> /* hello.c */ #include <stdio.h> #include <libintl.h> @@ -258,7 +272,8 @@ printf(gettext("and good bye\n")); return 0; } - </programlisting> + </file> + </scons_example> </para> <para> Compile project with <command>scons</command>. This time, the @@ -297,7 +312,8 @@ <literal>PO</literal>) are touched (i.e. no content changes, no creation/modification time changed and so on). Let's append another line to the program (after the last printf), so its code becomes: - <programlisting> + <scons_example name="ex6"> + <file name="hello.c" printme="1"> /* hello.c */ #include <stdio.h> #include <libintl.h> @@ -312,7 +328,8 @@ printf("----------------\n"); return a; } - </programlisting> + </file> + </scons_example> Compile the project. You'll see on your screen <screen> user@host:$scons diff --git a/doc/user/hierarchy.in b/doc/user/hierarchy.in deleted file mode 100644 index d70633d..0000000 --- a/doc/user/hierarchy.in +++ /dev/null @@ -1,794 +0,0 @@ -<!-- - - __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. - ---> - -<!-- - - -=head2 The Build command - -By default, Cons does not change its working directory to the directory -containing a subsidiary F<Conscript> file it is including. This behavior -can be enabled for a build by specifying, in the top-level F<Construct> -file: - - Conscript_chdir 1; - -When enabled, Cons will change to the subsidiary F<Conscript> file's -containing directory while reading in that file, and then change back -to the top-level directory once the file has been processed. - -It is expected that this behavior will become the default in some future -version of Cons. To prepare for this transition, builds that expect -Cons to remain at the top of the build while it reads in a subsidiary -F<Conscript> file should explicitly disable this feature as follows: - - Conscript_chdir 0; - -=head2 Relative, top-relative, and absolute file names - -(There is another file prefix, ``!'', that is interpreted specially by -Cons. See discussion of the C<Link> command, below, for details.) - - -=head2 Using modules in build scripts - -You may pull modules into each F<Conscript> file using the normal Perl -C<use> or C<require> statements: - - use English; - require My::Module; - -Each C<use> or C<require> only affects the one F<Conscript> file in which -it appears. To use a module in multiple F<Conscript> files, you must -put a C<use> or C<require> statement in each one that needs the module. - - -=head2 Scope of variables - -The top-level F<Construct> file and all F<Conscript> files begin life in -a common, separate Perl package. B<Cons> controls the symbol table for -the package so that, the symbol table for each script is empty, except -for the F<Construct> file, which gets some of the command line arguments. -All of the variables that are set or used, therefore, are set by the -script itself, not by some external script. - -Variables can be explicitly B<imported> by a script from its parent -script. To import a variable, it must have been B<exported> by the parent -and initialized (otherwise an error will occur). - - -=head2 The Export command - -The C<Export> command is used as in the following example: - - $env = new cons(); - $INCLUDE = "#export/include"; - $LIB = "#export/lib"; - Export qw( env INCLUDE LIB ); - Build qw( util/Conscript ); - -The values of the simple variables mentioned in the C<Export> list will be -squirreled away by any subsequent C<Build> commands. The C<Export> command -will only export Perl B<scalar> variables, that is, variables whose name -begins with C<$>. Other variables, objects, etc. can be exported by -reference, but all scripts will refer to the same object, and this object -should be considered to be read-only by the subsidiary scripts and by the -original exporting script. It's acceptable, however, to assign a new value -to the exported scalar variable, that won't change the underlying variable -referenced. This sequence, for example, is OK: - - $env = new cons(); - Export qw( env INCLUDE LIB ); - Build qw( util/Conscript ); - $env = new cons(CFLAGS => '-O'); - Build qw( other/Conscript ); - -It doesn't matter whether the variable is set before or after the C<Export> -command. The important thing is the value of the variable at the time the -C<Build> command is executed. This is what gets squirreled away. Any -subsequent C<Export> commands, by the way, invalidate the first: you must -mention all the variables you wish to export on each C<Export> command. - - -=head2 The Import command - -Variables exported by the C<Export> command can be imported into subsidiary -scripts by the C<Import> command. The subsidiary script always imports -variables directly from the superior script. Consider this example: - - Import qw( env INCLUDE ); - -This is only legal if the parent script exported both C<$env> and -C<$INCLUDE>. It also must have given each of these variables values. It is -OK for the subsidiary script to only import a subset of the exported -variables (in this example, C<$LIB>, which was exported by the previous -example, is not imported). - -All the imported variables are automatically re-exported, so the sequence: - - Import qw ( env INCLUDE ); - Build qw ( beneath-me/Conscript ); - -will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only -C<$env> is to be exported, then the following will suffice: - - Import qw ( env INCLUDE ); - Export qw ( env ); - Build qw ( beneath-me/Conscript ); - -Needless to say, the variables may be modified locally before invoking -C<Build> on the subsidiary script. - -=head2 Build script evaluation order - -The only constraint on the ordering of build scripts is that superior -scripts are evaluated before their inferior scripts. The top-level -F<Construct> file, for instance, is evaluated first, followed by any -inferior scripts. This is all you really need to know about the evaluation -order, since order is generally irrelevant. Consider the following C<Build> -command: - - Build qw( - drivers/display/Conscript - drivers/mouse/Conscript - parser/Conscript - utilities/Conscript - ); - -We've chosen to put the script names in alphabetical order, simply because -that's the most convenient for maintenance purposes. Changing the order will -make no difference to the build. - ---> - - <para> - - The source code for large software projects - rarely stays in a single directory, - but is nearly always divided into a - hierarchy of directories. - Organizing a large software build using &SCons; - involves creating a hierarchy of build scripts - using the &SConscript; function. - - </para> - - <section> - <title>&SConscript; Files</title> - - <para> - - As we've already seen, - the build script at the top of the tree is called &SConstruct;. - The top-level &SConstruct; file can - use the &SConscript; function to - include other subsidiary scripts in the build. - These subsidiary scripts can, in turn, - use the &SConscript; function - to include still other scripts in the build. - By convention, these subsidiary scripts are usually - named &SConscript;. - For example, a top-level &SConstruct; file might - arrange for four subsidiary scripts to be included - in the build as follows: - - </para> - - <sconstruct> - SConscript(['drivers/display/SConscript', - 'drivers/mouse/SConscript', - 'parser/SConscript', - 'utilities/SConscript']) - </sconstruct> - - <para> - - In this case, the &SConstruct; file - lists all of the &SConscript; files in the build explicitly. - (Note, however, that not every directory in the tree - necessarily has an &SConscript; file.) - Alternatively, the <literal>drivers</literal> - subdirectory might contain an intermediate - &SConscript; file, - in which case the &SConscript; call in - the top-level &SConstruct; file - would look like: - - </para> - - <sconstruct> - SConscript(['drivers/SConscript', - 'parser/SConscript', - 'utilities/SConscript']) - </sconstruct> - - <para> - - And the subsidiary &SConscript; file in the - <literal>drivers</literal> subdirectory - would look like: - - </para> - - <sconstruct> - SConscript(['display/SConscript', - 'mouse/SConscript']) - </sconstruct> - - <para> - - Whether you list all of the &SConscript; files in the - top-level &SConstruct; file, - or place a subsidiary &SConscript; file in - intervening directories, - or use some mix of the two schemes, - is up to you and the needs of your software. - - </para> - - </section> - - <section> - <title>Path Names Are Relative to the &SConscript; Directory</title> - - <para> - - Subsidiary &SConscript; files make it easy to create a build - hierarchy because all of the file and directory names - in a subsidiary &SConscript; files are interpreted - relative to the directory in which the &SConscript; file lives. - Typically, this allows the &SConscript; file containing the - instructions to build a target file - to live in the same directory as the source files - from which the target will be built, - making it easy to update how the software is built - whenever files are added or deleted - (or other changes are made). - - </para> - - <para> - - For example, suppose we want to build two programs - &prog1; and &prog2; in two separate directories - with the same names as the programs. - One typical way to do this would be - with a top-level &SConstruct; file like this: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - SConscript(['prog1/SConscript', - 'prog2/SConscript']) - </file> - <file name="prog1/SConscript"> - env = Environment() - env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c']) - </file> - <file name="prog2/SConscript"> - env = Environment() - env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c']) - </file> - <directory name="prog1"></directory> - <file name="prog1/main.c"> - x - </file> - <file name="prog1/foo1.c"> - x - </file> - <file name="prog1/foo2.c"> - x - </file> - <directory name="prog2"></directory> - <file name="prog2/main.c"> - x - </file> - <file name="prog2/bar1.c"> - x - </file> - <file name="prog2/bar2.c"> - x - </file> - </scons_example> - - <para> - - And subsidiary &SConscript; files that look like this: - - </para> - - <scons_example_file example="ex1" name="prog1/SConscript"> - </scons_example_file> - - <para> - - And this: - - </para> - - <scons_example_file example="ex1" name="prog2/SConscript"> - </scons_example_file> - - <para> - - Then, when we run &SCons; in the top-level directory, - our build looks like: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Notice the following: - - First, you can have files with the same names - in multiple directories, like main.c in the above example. - - Second, unlike standard recursive use of &Make;, - &SCons; stays in the top-level directory - (where the &SConstruct; file lives) - and issues commands that use the path names - from the top-level directory to the - target and source files within the hierarchy. - - </para> - - </section> - - <section> - <title>Top-Level Path Names in Subsidiary &SConscript; Files</title> - - <para> - - If you need to use a file from another directory, - it's sometimes more convenient to specify - the path to a file in another directory - from the top-level &SConstruct; directory, - even when you're using that file in - a subsidiary &SConscript; file in a subdirectory. - You can tell &SCons; to interpret a path name - as relative to the top-level &SConstruct; directory, - not the local directory of the &SConscript; file, - by appending a &hash; (hash mark) - to the beginning of the path name: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct"> - SConscript('src/prog/SConscript') - </file> - <file name="src/prog/SConscript" printme="1"> - env = Environment() - env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c']) - </file> - <file name="src/prog/main.c"> - x - </file> - <file name="lib/foo1.c"> - x - </file> - <file name="src/prog/foo2.c"> - x - </file> - </scons_example> - - <para> - - In this example, - the <literal>lib</literal> directory is - directly underneath the top-level &SConstruct; directory. - If the above &SConscript; file is in a subdirectory - named <literal>src/prog</literal>, - the output would look like: - - </para> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - (Notice that the <literal>lib/foo1.o</literal> object file - is built in the same directory as its source file. - See <xref linkend="chap-separate"></xref>, below, - for information about - how to build the object file in a different subdirectory.) - - </para> - - </section> - - <section> - <title>Absolute Path Names</title> - - <para> - - Of course, you can always specify - an absolute path name for a file--for example: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct"> - SConscript('src/prog/SConscript') - </file> - <file name="src/prog/SConscript" printme="1"> - env = Environment() - env.Program('prog', ['main.c', '__ROOT__/usr/joe/lib/foo1.c', 'foo2.c']) - </file> - <file name="src/prog/main.c"> - x - </file> - <file name="__ROOT__/usr/joe/lib/foo1.c"> - x - </file> - <file name="src/prog/foo2.c"> - x - </file> - </scons_example> - - <para> - - Which, when executed, would yield: - - </para> - - <scons_output example="ex3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - (As was the case with top-relative path names, - notice that the <literal>/usr/joe/lib/foo1.o</literal> object file - is built in the same directory as its source file. - See <xref linkend="chap-separate"></xref>, below, - for information about - how to build the object file in a different subdirectory.) - - </para> - - </section> - - <section> - <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title> - - <para> - - In the previous example, - each of the subsidiary &SConscript; files - created its own construction environment - by calling &Environment; separately. - This obviously works fine, - but if each program must be built - with the same construction variables, - it's cumbersome and error-prone to initialize - separate construction environments - in the same way over and over in each subsidiary - &SConscript; file. - - </para> - - <para> - - &SCons; supports the ability to <emphasis>export</emphasis> variables - from a parent &SConscript; file - to its subsidiary &SConscript; files, - which allows you to share common initialized - values throughout your build hierarchy. - - </para> - - <section> - <title>Exporting Variables</title> - - <para> - - There are two ways to export a variable, - such as a construction environment, - from an &SConscript; file, - so that it may be used by other &SConscript; files. - First, you can call the &Export; - function with a list of variables, - or a string of white-space separated variable names. - Each call to &Export; adds one - or more variables to a global list - of variables that are available for import - by other &SConscript; files. - - </para> - - <sconstruct> - env = Environment() - Export('env') - </sconstruct> - - <para> - - You may export more than one variable name at a time: - - </para> - - <sconstruct> - env = Environment() - debug = ARGUMENTS['debug'] - Export('env', 'debug') - </sconstruct> - - <para> - - Because white space is not legal in Python variable names, - the &Export; function will even automatically split - a string into separate names for you: - - </para> - - <sconstruct> - Export('env debug') - </sconstruct> - - <para> - - Second, you can specify a list of - variables to export as a second argument - to the &SConscript; function call: - - </para> - - <sconstruct> - SConscript('src/SConscript', 'env') - </sconstruct> - - <para> - - Or as the &exports; keyword argument: - - </para> - - <sconstruct> - SConscript('src/SConscript', exports='env') - </sconstruct> - - <para> - - These calls export the specified variables - to only the listed &SConscript; files. - You may, however, specify more than one - &SConscript; file in a list: - - </para> - - <sconstruct> - SConscript(['src1/SConscript', - 'src2/SConscript'], exports='env') - </sconstruct> - - <para> - - This is functionally equivalent to - calling the &SConscript; function - multiple times with the same &exports; argument, - one per &SConscript; file. - - </para> - - </section> - - <section> - <title>Importing Variables</title> - - <para> - - Once a variable has been exported from a calling - &SConscript; file, - it may be used in other &SConscript; files - by calling the &Import; function: - - </para> - - <sconstruct> - Import('env') - env.Program('prog', ['prog.c']) - </sconstruct> - - <para> - - The &Import; call makes the <literal>env</literal> construction - environment available to the &SConscript; file, - after which the variable can be used to build - programs, libraries, etc. - - </para> - - <para> - - Like the &Export; function, - the &Import; function can be used - with multiple variable names: - - </para> - - <sconstruct> - Import('env', 'debug') - env = env.Clone(DEBUG = debug) - env.Program('prog', ['prog.c']) - </sconstruct> - - <para> - - And the &Import; function will similarly - split a string along white-space - into separate variable names: - - </para> - - <sconstruct> - Import('env debug') - env = env.Clone(DEBUG = debug) - env.Program('prog', ['prog.c']) - </sconstruct> - - <para> - - Lastly, as a special case, - you may import all of the variables that - have been exported by supplying an asterisk - to the &Import; function: - - </para> - - <sconstruct> - Import('*') - env = env.Clone(DEBUG = debug) - env.Program('prog', ['prog.c']) - </sconstruct> - - <para> - - If you're dealing with a lot of &SConscript; files, - this can be a lot simpler than keeping - arbitrary lists of imported variables in each file. - - </para> - - </section> - - <section> - <title>Returning Values From an &SConscript; File</title> - - <para> - - Sometimes, you would like to be able to - use information from a subsidiary - &SConscript; file in some way. - For example, - suppose that you want to create one - library from source files - scattered throughout a number - of subsidiary &SConscript; files. - You can do this by using the &Return; - function to return values - from the subsidiary &SConscript; files - to the calling file. - - </para> - - <para> - - If, for example, we have two subdirectories - &foo; and &bar; - that should each contribute a source - file to a Library, - what we'd like to be able to do is - collect the object files - from the subsidiary &SConscript; calls - like this: - - </para> - - <scons_example name="Return"> - <file name="SConstruct" printme="1"> - env = Environment() - Export('env') - objs = [] - for subdir in ['foo', 'bar']: - o = SConscript('%s/SConscript' % subdir) - objs.append(o) - env.Library('prog', objs) - </file> - <directory name="foo"></directory> - <directory name="bar"></directory> - <file name="foo/SConscript"> - Import('env') - obj = env.Object('foo.c') - Return('obj') - </file> - <file name="bar/SConscript"> - Import('env') - obj = env.Object('bar.c') - Return('obj') - </file> - <file name="foo/foo.c"> - void foo(void) { printf("foo/foo.c\n"); } - </file> - <file name="bar/bar.c"> - void bar(void) { printf("bar/bar.c\n"); } - </file> - </scons_example> - - <para> - - We can do this by using the &Return; - function in the - <literal>foo/SConscript</literal> file like this: - - </para> - - <scons_example_file example="Return" name="foo/SConscript"> - </scons_example_file> - - <para> - - (The corresponding - <literal>bar/SConscript</literal> - file should be pretty obvious.) - Then when we run &SCons;, - the object files from the subsidiary subdirectories - are all correctly archived in the desired library: - - </para> - - <scons_output example="Return"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <!-- - XXX Return(stop=False) - --> - - </section> - - </section> - - <!-- - - <section> - <title>Executing From a Subdirectory: the -D, -u and -U Options</title> - - <para> - - XXX -D, -u and -U - - </para> - - </section> - - --> diff --git a/doc/user/hierarchy.xml b/doc/user/hierarchy.xml index 2e2941c..d70633d 100644 --- a/doc/user/hierarchy.xml +++ b/doc/user/hierarchy.xml @@ -196,12 +196,12 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> SConscript(['drivers/display/SConscript', 'drivers/mouse/SConscript', 'parser/SConscript', 'utilities/SConscript']) - </programlisting> + </sconstruct> <para> @@ -218,11 +218,11 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> SConscript(['drivers/SConscript', 'parser/SConscript', 'utilities/SConscript']) - </programlisting> + </sconstruct> <para> @@ -232,10 +232,10 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> SConscript(['display/SConscript', 'mouse/SConscript']) - </programlisting> + </sconstruct> <para> @@ -279,10 +279,40 @@ make no difference to the build. </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> SConscript(['prog1/SConscript', 'prog2/SConscript']) - </programlisting> + </file> + <file name="prog1/SConscript"> + env = Environment() + env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c']) + </file> + <file name="prog2/SConscript"> + env = Environment() + env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c']) + </file> + <directory name="prog1"></directory> + <file name="prog1/main.c"> + x + </file> + <file name="prog1/foo1.c"> + x + </file> + <file name="prog1/foo2.c"> + x + </file> + <directory name="prog2"></directory> + <file name="prog2/main.c"> + x + </file> + <file name="prog2/bar1.c"> + x + </file> + <file name="prog2/bar2.c"> + x + </file> + </scons_example> <para> @@ -290,11 +320,8 @@ make no difference to the build. </para> - - <programlisting> - env = Environment() - env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c']) - </programlisting> + <scons_example_file example="ex1" name="prog1/SConscript"> + </scons_example_file> <para> @@ -302,11 +329,8 @@ make no difference to the build. </para> - - <programlisting> - env = Environment() - env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c']) - </programlisting> + <scons_example_file example="ex1" name="prog2/SConscript"> + </scons_example_file> <para> @@ -315,17 +339,9 @@ make no difference to the build. </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o prog1/foo1.o -c prog1/foo1.c - cc -o prog1/foo2.o -c prog1/foo2.c - cc -o prog1/main.o -c prog1/main.c - cc -o prog1/prog1 prog1/main.o prog1/foo1.o prog1/foo2.o - cc -o prog2/bar1.o -c prog2/bar1.c - cc -o prog2/bar2.o -c prog2/bar2.c - cc -o prog2/main.o -c prog2/main.c - cc -o prog2/prog2 prog2/main.o prog2/bar1.o prog2/bar2.o - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -364,10 +380,24 @@ make no difference to the build. </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct"> + SConscript('src/prog/SConscript') + </file> + <file name="src/prog/SConscript" printme="1"> env = Environment() env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c']) - </programlisting> + </file> + <file name="src/prog/main.c"> + x + </file> + <file name="lib/foo1.c"> + x + </file> + <file name="src/prog/foo2.c"> + x + </file> + </scons_example> <para> @@ -380,13 +410,9 @@ make no difference to the build. </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o lib/foo1.o -c lib/foo1.c - cc -o src/prog/foo2.o -c src/prog/foo2.c - cc -o src/prog/main.o -c src/prog/main.c - cc -o src/prog/prog src/prog/main.o lib/foo1.o src/prog/foo2.o - </screen> + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -410,10 +436,24 @@ make no difference to the build. </para> - <programlisting> + <scons_example name="ex3"> + <file name="SConstruct"> + SConscript('src/prog/SConscript') + </file> + <file name="src/prog/SConscript" printme="1"> env = Environment() - env.Program('prog', ['main.c', '/usr/joe/lib/foo1.c', 'foo2.c']) - </programlisting> + env.Program('prog', ['main.c', '__ROOT__/usr/joe/lib/foo1.c', 'foo2.c']) + </file> + <file name="src/prog/main.c"> + x + </file> + <file name="__ROOT__/usr/joe/lib/foo1.c"> + x + </file> + <file name="src/prog/foo2.c"> + x + </file> + </scons_example> <para> @@ -421,13 +461,9 @@ make no difference to the build. </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o src/prog/foo2.o -c src/prog/foo2.c - cc -o src/prog/main.o -c src/prog/main.c - cc -o /usr/joe/lib/foo1.o -c /usr/joe/lib/foo1.c - cc -o src/prog/prog src/prog/main.o /usr/joe/lib/foo1.o src/prog/foo2.o - </screen> + <scons_output example="ex3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -490,10 +526,10 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> env = Environment() Export('env') - </programlisting> + </sconstruct> <para> @@ -501,11 +537,11 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> env = Environment() debug = ARGUMENTS['debug'] Export('env', 'debug') - </programlisting> + </sconstruct> <para> @@ -515,9 +551,9 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> Export('env debug') - </programlisting> + </sconstruct> <para> @@ -527,9 +563,9 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> SConscript('src/SConscript', 'env') - </programlisting> + </sconstruct> <para> @@ -537,9 +573,9 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> SConscript('src/SConscript', exports='env') - </programlisting> + </sconstruct> <para> @@ -550,10 +586,10 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> SConscript(['src1/SConscript', 'src2/SConscript'], exports='env') - </programlisting> + </sconstruct> <para> @@ -578,10 +614,10 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> Import('env') env.Program('prog', ['prog.c']) - </programlisting> + </sconstruct> <para> @@ -600,11 +636,11 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> Import('env', 'debug') env = env.Clone(DEBUG = debug) env.Program('prog', ['prog.c']) - </programlisting> + </sconstruct> <para> @@ -614,11 +650,11 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> Import('env debug') env = env.Clone(DEBUG = debug) env.Program('prog', ['prog.c']) - </programlisting> + </sconstruct> <para> @@ -629,11 +665,11 @@ make no difference to the build. </para> - <programlisting> + <sconstruct> Import('*') env = env.Clone(DEBUG = debug) env.Program('prog', ['prog.c']) - </programlisting> + </sconstruct> <para> @@ -678,7 +714,8 @@ make no difference to the build. </para> - <programlisting> + <scons_example name="Return"> + <file name="SConstruct" printme="1"> env = Environment() Export('env') objs = [] @@ -686,7 +723,26 @@ make no difference to the build. o = SConscript('%s/SConscript' % subdir) objs.append(o) env.Library('prog', objs) - </programlisting> + </file> + <directory name="foo"></directory> + <directory name="bar"></directory> + <file name="foo/SConscript"> + Import('env') + obj = env.Object('foo.c') + Return('obj') + </file> + <file name="bar/SConscript"> + Import('env') + obj = env.Object('bar.c') + Return('obj') + </file> + <file name="foo/foo.c"> + void foo(void) { printf("foo/foo.c\n"); } + </file> + <file name="bar/bar.c"> + void bar(void) { printf("bar/bar.c\n"); } + </file> + </scons_example> <para> @@ -696,12 +752,8 @@ make no difference to the build. </para> - - <programlisting> - Import('env') - obj = env.Object('foo.c') - Return('obj') - </programlisting> + <scons_example_file example="Return" name="foo/SConscript"> + </scons_example_file> <para> @@ -714,13 +766,9 @@ make no difference to the build. </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o bar/bar.o -c bar/bar.c - cc -o foo/foo.o -c foo/foo.c - ar rc libprog.a foo/foo.o bar/bar.o - ranlib libprog.a - </screen> + <scons_output example="Return"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <!-- XXX Return(stop=False) diff --git a/doc/user/install.in b/doc/user/install.in deleted file mode 100644 index ba179e7..0000000 --- a/doc/user/install.in +++ /dev/null @@ -1,247 +0,0 @@ -<!-- - - __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> - - Once a program is built, - it is often appropriate to install it in another - directory for public use. - You use the &Install; method - to arrange for a program, or any other file, - to be copied into a destination directory: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - env = Environment() - hello = env.Program('hello.c') - env.Install('__ROOT__/usr/bin', hello) - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Note, however, that installing a file is - still considered a type of file "build." - This is important when you remember that - the default behavior of &SCons; is - to build files in or below the current directory. - If, as in the example above, - you are installing files in a directory - outside of the top-level &SConstruct; file's directory tree, - you must specify that directory - (or a higher directory, such as <literal>/</literal>) - for it to install anything there: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q __ROOT__/usr/bin</scons_output_command> - </scons_output> - - <para> - - It can, however, be cumbersome to remember - (and type) the specific destination directory - in which the program (or any other file) - should be installed. - This is an area where the &Alias; - function comes in handy, - allowing you, for example, - to create a pseudo-target named <literal>install</literal> - that can expand to the specified destination directory: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - env = Environment() - hello = env.Program('hello.c') - env.Install('__ROOT__/usr/bin', hello) - env.Alias('install', '__ROOT__/usr/bin') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - This then yields the more natural - ability to install the program - in its destination as follows: - - </para> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q install</scons_output_command> - </scons_output> - - <section> - <title>Installing Multiple Files in a Directory</title> - - <para> - - You can install multiple files into a directory - simply by calling the &Install; function multiple times: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct" printme="1"> - env = Environment() - hello = env.Program('hello.c') - goodbye = env.Program('goodbye.c') - env.Install('__ROOT__/usr/bin', hello) - env.Install('__ROOT__/usr/bin', goodbye) - env.Alias('install', '__ROOT__/usr/bin') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="goodbye.c"> - int main() { printf("Goodbye, world!\n"); } - </file> - </scons_example> - - <para> - - Or, more succinctly, listing the multiple input - files in a list - (just like you can do with any other builder): - - </para> - - <sconstruct> - env = Environment() - hello = env.Program('hello.c') - goodbye = env.Program('goodbye.c') - env.Install('__ROOT__/usr/bin', [hello, goodbye]) - env.Alias('install', '__ROOT__/usr/bin') - </sconstruct> - - <para> - - Either of these two examples yields: - - </para> - - <scons_output example="ex3"> - <scons_output_command>scons -Q install</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Installing a File Under a Different Name</title> - - <para> - - The &Install; method preserves the name - of the file when it is copied into the - destination directory. - If you need to change the name of the file - when you copy it, use the &InstallAs; function: - - </para> - - <scons_example name="ex4"> - <file name="SConstruct" printme="1"> - env = Environment() - hello = env.Program('hello.c') - env.InstallAs('__ROOT__/usr/bin/hello-new', hello) - env.Alias('install', '__ROOT__/usr/bin') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - This installs the <literal>hello</literal> - program with the name <literal>hello-new</literal> - as follows: - - </para> - - <scons_output example="ex4"> - <scons_output_command>scons -Q install</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Installing Multiple Files Under Different Names</title> - - <para> - - Lastly, if you have multiple files that all - need to be installed with different file names, - you can either call the &InstallAs; function - multiple times, or as a shorthand, - you can supply same-length lists - for both the target and source arguments: - - </para> - - <scons_example name="ex5"> - <file name="SConstruct" printme="1"> - env = Environment() - hello = env.Program('hello.c') - goodbye = env.Program('goodbye.c') - env.InstallAs(['__ROOT__/usr/bin/hello-new', - '__ROOT__/usr/bin/goodbye-new'], - [hello, goodbye]) - env.Alias('install', '__ROOT__/usr/bin') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="goodbye.c"> - int main() { printf("Goodbye, world!\n"); } - </file> - </scons_example> - - <para> - - In this case, the &InstallAs; function - loops through both lists simultaneously, - and copies each source file into its corresponding - target file name: - - </para> - - <scons_output example="ex5"> - <scons_output_command>scons -Q install</scons_output_command> - </scons_output> - - </section> diff --git a/doc/user/install.xml b/doc/user/install.xml index dd79153..ba179e7 100644 --- a/doc/user/install.xml +++ b/doc/user/install.xml @@ -34,11 +34,16 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> env = Environment() hello = env.Program('hello.c') - env.Install('/usr/bin', hello) - </programlisting> + env.Install('__ROOT__/usr/bin', hello) + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -56,13 +61,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q /usr/bin</userinput> - Install file: "hello" as "/usr/bin/hello" - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q __ROOT__/usr/bin</scons_output_command> + </scons_output> <para> @@ -78,12 +80,17 @@ </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> env = Environment() hello = env.Program('hello.c') - env.Install('/usr/bin', hello) - env.Alias('install', '/usr/bin') - </programlisting> + env.Install('__ROOT__/usr/bin', hello) + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -93,13 +100,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - % <userinput>scons -Q install</userinput> - Install file: "hello" as "/usr/bin/hello" - </screen> + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> <section> <title>Installing Multiple Files in a Directory</title> @@ -111,14 +115,22 @@ </para> - <programlisting> + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> env = Environment() hello = env.Program('hello.c') goodbye = env.Program('goodbye.c') - env.Install('/usr/bin', hello) - env.Install('/usr/bin', goodbye) - env.Alias('install', '/usr/bin') - </programlisting> + env.Install('__ROOT__/usr/bin', hello) + env.Install('__ROOT__/usr/bin', goodbye) + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> <para> @@ -128,13 +140,13 @@ </para> - <programlisting> + <sconstruct> env = Environment() hello = env.Program('hello.c') goodbye = env.Program('goodbye.c') - env.Install('/usr/bin', [hello, goodbye]) - env.Alias('install', '/usr/bin') - </programlisting> + env.Install('__ROOT__/usr/bin', [hello, goodbye]) + env.Alias('install', '__ROOT__/usr/bin') + </sconstruct> <para> @@ -142,15 +154,9 @@ </para> - <screen> - % <userinput>scons -Q install</userinput> - cc -o goodbye.o -c goodbye.c - cc -o goodbye goodbye.o - Install file: "goodbye" as "/usr/bin/goodbye" - cc -o hello.o -c hello.c - cc -o hello hello.o - Install file: "hello" as "/usr/bin/hello" - </screen> + <scons_output example="ex3"> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> </section> @@ -167,12 +173,17 @@ </para> - <programlisting> + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> env = Environment() hello = env.Program('hello.c') - env.InstallAs('/usr/bin/hello-new', hello) - env.Alias('install', '/usr/bin') - </programlisting> + env.InstallAs('__ROOT__/usr/bin/hello-new', hello) + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -182,12 +193,9 @@ </para> - <screen> - % <userinput>scons -Q install</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - Install file: "hello" as "/usr/bin/hello-new" - </screen> + <scons_output example="ex4"> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> </section> @@ -205,15 +213,23 @@ </para> - <programlisting> + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> env = Environment() hello = env.Program('hello.c') goodbye = env.Program('goodbye.c') - env.InstallAs(['/usr/bin/hello-new', - '/usr/bin/goodbye-new'], + env.InstallAs(['__ROOT__/usr/bin/hello-new', + '__ROOT__/usr/bin/goodbye-new'], [hello, goodbye]) - env.Alias('install', '/usr/bin') - </programlisting> + env.Alias('install', '__ROOT__/usr/bin') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> <para> @@ -224,14 +240,8 @@ </para> - <screen> - % <userinput>scons -Q install</userinput> - cc -o goodbye.o -c goodbye.c - cc -o goodbye goodbye.o - Install file: "goodbye" as "/usr/bin/goodbye-new" - cc -o hello.o -c hello.c - cc -o hello hello.o - Install file: "hello" as "/usr/bin/hello-new" - </screen> + <scons_output example="ex5"> + <scons_output_command>scons -Q install</scons_output_command> + </scons_output> </section> diff --git a/doc/user/java.in b/doc/user/java.in deleted file mode 100644 index 4561a4c..0000000 --- a/doc/user/java.in +++ /dev/null @@ -1,657 +0,0 @@ -<!-- - - __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> - - So far, we've been using examples of - building C and C++ programs - to demonstrate the features of &SCons;. - &SCons; also supports building Java programs, - but Java builds are handled slightly differently, - which reflects the ways in which - the Java compiler and tools - build programs differently than - other languages' tool chains. - - </para> - - <section> - <title>Building Java Class Files: the &b-Java; Builder</title> - - <para> - - The basic activity when programming in Java, - of course, is to take one or more <filename>.java</filename> files - containing Java source code - and to call the Java compiler - to turn them into one or more - <filename>.class</filename> files. - In &SCons;, you do this - by giving the &b-link-Java; Builder - a target directory in which - to put the <filename>.class</filename> files, - and a source directory that contains - the <filename>.java</filename> files: - - </para> - - <scons_example name="java"> - <file name="SConstruct" printme="1"> - Java('classes', 'src') - </file> - <file name="src/Example1.java"> - public class Example1 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - <file name="src/Example2.java"> - public class Example2 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - <file name="src/Example3.java"> - public class Example3 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - </scons_example> - - <para> - - If the <filename>src</filename> directory contains - three <filename>.java</filename> source files, - then running &SCons; might look like this: - - </para> - - <scons_output example="java"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - &SCons; will actually search the <filename>src</filename> - directory tree for all of the <filename>.java</filename> files. - The Java compiler will then create the - necessary class files in the <filename>classes</filename> subdirectory, - based on the class names found in the <filename>.java</filename> files. - - </para> - - </section> - - <section> - <title>How &SCons; Handles Java Dependencies</title> - - <para> - - In addition to searching the source directory for - <filename>.java</filename> files, - &SCons; actually runs the <filename>.java</filename> files - through a stripped-down Java parser that figures out - what classes are defined. - In other words, &SCons; knows, - without you having to tell it, - what <filename>.class</filename> files - will be produced by the &javac; call. - So our one-liner example from the preceding section: - - </para> - - <scons_example name="java-classes"> - <file name="SConstruct" printme="1"> - Java('classes', 'src') - </file> - <file name="src/Example1.java"> - public class Example1 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - public class AdditionalClass1 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - <file name="src/Example2.java"> - public class Example2 - { - class Inner2 { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - } - </file> - <file name="src/Example3.java"> - public class Example3 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - public class AdditionalClass3 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - </scons_example> - - <para> - - Will not only tell you reliably - that the <filename>.class</filename> files - in the <filename>classes</filename> subdirectory - are up-to-date: - - </para> - - <scons_output example="java-classes"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q classes</scons_output_command> - </scons_output> - - <para> - - But it will also remove all of the generated - <filename>.class</filename> files, - even for inner classes, - without you having to specify them manually. - For example, if our - <filename>Example1.java</filename> - and - <filename>Example3.java</filename> - files both define additional classes, - and the class defined in <filename>Example2.java</filename> - has an inner class, - running <userinput>scons -c</userinput> - will clean up all of those <filename>.class</filename> files - as well: - - </para> - - <scons_output example="java-classes"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q -c classes</scons_output_command> - </scons_output> - - <para> - - To ensure correct handling of <filename>.class</filename> - dependencies in all cases, you need to tell &SCons; which Java - version is being used. This is needed because Java 1.5 changed - the <filename>.class</filename> file names for nested anonymous - inner classes. Use the <varname>JAVAVERSION</varname> construction - variable to specify the version in use. With Java 1.6, the - one-liner example can then be defined like this: - - </para> - - <sconstruct> - Java('classes', 'src', JAVAVERSION='1.6') - </sconstruct> - - <para> - See <varname>JAVAVERSION</varname> in the man page for more information. - </para> - - </section> - - <section> - <title>Building Java Archive (<filename>.jar</filename>) Files: the &b-Jar; Builder</title> - - <para> - - After building the class files, - it's common to collect them into - a Java archive (<filename>.jar</filename>) file, - which you do by calling the &b-link-Jar; Builder method. - If you want to just collect all of the - class files within a subdirectory, - you can just specify that subdirectory - as the &b-Jar; source: - - </para> - - <scons_example name="jar1"> - <file name="SConstruct" printme="1"> - Java(target = 'classes', source = 'src') - Jar(target = 'test.jar', source = 'classes') - </file> - <file name="src/Example1.java"> - public class Example1 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - <file name="src/Example2.java"> - public class Example2 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - <file name="src/Example3.java"> - public class Example3 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - </scons_example> - - <para> - - &SCons; will then pass that directory - to the &jar; command, - which will collect all of the underlying - <filename>.class</filename> files: - - </para> - - <scons_output example="jar1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - If you want to keep all of the - <filename>.class</filename> files - for multiple programs in one location, - and only archive some of them in - each <filename>.jar</filename> file, - you can pass the &b-Jar; builder a - list of files as its source. - It's extremely simple to create multiple - <filename>.jar</filename> files this way, - using the lists of target class files created - by calls to the &b-link-Java; builder - as sources to the various &b-Jar; calls: - - </para> - - <scons_example name="jar2"> - <file name="SConstruct" printme="1"> - prog1_class_files = Java(target = 'classes', source = 'prog1') - prog2_class_files = Java(target = 'classes', source = 'prog2') - Jar(target = 'prog1.jar', source = prog1_class_files) - Jar(target = 'prog2.jar', source = prog2_class_files) - </file> - <file name="prog1/Example1.java"> - public class Example1 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - <file name="prog1/Example2.java"> - public class Example2 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - <file name="prog2/Example3.java"> - public class Example3 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - <file name="prog2/Example4.java"> - public class Example4 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - </scons_example> - - <para> - - This will then create - <filename>prog1.jar</filename> - and <filename>prog2.jar</filename> - next to the subdirectories - that contain their <filename>.java</filename> files: - - </para> - - <scons_output example="jar2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Building C Header and Stub Files: the &b-JavaH; Builder</title> - - <para> - - You can generate C header and source files - for implementing native methods, - by using the &b-link-JavaH; Builder. - There are several ways of using the &JavaH; Builder. - One typical invocation might look like: - - </para> - - <scons_example name="javah"> - <file name="SConstruct" printme="1"> - classes = Java(target = 'classes', source = 'src/pkg/sub') - JavaH(target = 'native', source = classes) - </file> - <file name="src/pkg/sub/Example1.java"> - package pkg.sub; - public class Example1 - { - public static void main(String[] args) - { - } - } - </file> - <file name="src/pkg/sub/Example2.java"> - package pkg.sub; - public class Example2 - { - public static void main(String[] args) - { - } - } - </file> - <file name="src/pkg/sub/Example3.java"> - package pkg.sub; - public class Example3 - { - public static void main(String[] args) - { - } - } - </file> - </scons_example> - - <para> - - The source is a list of class files generated by the - call to the &b-link-Java; Builder, - and the target is the output directory in - which we want the C header files placed. - The target - gets converted into the <option>-d</option> - when &SCons; runs &javah;: - - </para> - - <scons_output example="javah"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - In this case, - the call to &javah; - will generate the header files - <filename>native/pkg_sub_Example1.h</filename>, - <filename>native/pkg_sub_Example2.h</filename> - and - <filename>native/pkg_sub_Example3.h</filename>. - Notice that &SCons; remembered that the class - files were generated with a target directory of - <filename>classes</filename>, - and that it then specified that target directory - as the <option>-classpath</option> option - to the call to &javah;. - - </para> - - <para> - - Although it's more convenient to use - the list of class files returned by - the &b-Java; Builder - as the source of a call to the &b-JavaH; Builder, - you <emphasis>can</emphasis> - specify the list of class files - by hand, if you prefer. - If you do, - you need to set the - &cv-link-JAVACLASSDIR; construction variable - when calling &b-JavaH;: - - </para> - - <scons_example name="JAVACLASSDIR"> - <file name="SConstruct" printme="1"> - Java(target = 'classes', source = 'src/pkg/sub') - class_file_list = ['classes/pkg/sub/Example1.class', - 'classes/pkg/sub/Example2.class', - 'classes/pkg/sub/Example3.class'] - JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes') - </file> - <file name="src/pkg/sub/Example1.java"> - package pkg.sub; - public class Example1 - { - public static void main(String[] args) - { - } - } - </file> - <file name="src/pkg/sub/Example2.java"> - package pkg.sub; - public class Example2 - { - public static void main(String[] args) - { - } - } - </file> - <file name="src/pkg/sub/Example3.java"> - package pkg.sub; - public class Example3 - { - public static void main(String[] args) - { - } - } - </file> - </scons_example> - - <para> - - The &cv-JAVACLASSDIR; value then - gets converted into the <option>-classpath</option> - when &SCons; runs &javah;: - - </para> - - <scons_output example="JAVACLASSDIR"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Lastly, if you don't want a separate header file - generated for each source file, - you can specify an explicit File Node - as the target of the &b-JavaH; Builder: - - </para> - - <scons_example name="javah_file"> - <file name="SConstruct" printme="1"> - classes = Java(target = 'classes', source = 'src/pkg/sub') - JavaH(target = File('native.h'), source = classes) - </file> - <file name="src/pkg/sub/Example1.java"> - package pkg.sub; - public class Example1 - { - public static void main(String[] args) - { - } - } - </file> - <file name="src/pkg/sub/Example2.java"> - package pkg.sub; - public class Example2 - { - public static void main(String[] args) - { - } - } - </file> - <file name="src/pkg/sub/Example3.java"> - package pkg.sub; - public class Example3 - { - public static void main(String[] args) - { - } - } - </file> - </scons_example> - - <para> - - Because &SCons; assumes by default - that the target of the &b-JavaH; builder is a directory, - you need to use the &File; function - to make sure that &SCons; doesn't - create a directory named <filename>native.h</filename>. - When a file is used, though, - &SCons; correctly converts the file name - into the &javah; <option>-o</option> option: - - </para> - - <scons_output example="javah_file"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Building RMI Stub and Skeleton Class Files: the &b-RMIC; Builder</title> - - <para> - - You can generate Remote Method Invocation stubs - by using the &b-link-RMIC; Builder. - The source is a list of directories, - typically returned by a call to the &b-link-Java; Builder, - and the target is an output directory - where the <filename>_Stub.class</filename> - and <filename>_Skel.class</filename> files will - be placed: - - </para> - - <scons_example name="RMIC"> - <file name="SConstruct" printme="1"> - classes = Java(target = 'classes', source = 'src/pkg/sub') - RMIC(target = 'outdir', source = classes) - </file> - <file name="src/pkg/sub/Example1.java"> - package pkg.sub; - public class Example1 - { - public static void main(String[] args) - { - } - } - </file> - <file name="src/pkg/sub/Example2.java"> - package pkg.sub; - public class Example2 - { - public static void main(String[] args) - { - } - } - </file> - </scons_example> - - <para> - - As it did with the &b-link-JavaH; Builder, - &SCons; remembers the class directory - and passes it as the <option>-classpath</option> option - to &rmic;: - - </para> - - <scons_output example="RMIC"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - This example would generate the files - <filename>outdir/pkg/sub/Example1_Skel.class</filename>, - <filename>outdir/pkg/sub/Example1_Stub.class</filename>, - <filename>outdir/pkg/sub/Example2_Skel.class</filename> and - <filename>outdir/pkg/sub/Example2_Stub.class</filename>. - - </para> - - </section> diff --git a/doc/user/java.xml b/doc/user/java.xml index fddc646..4561a4c 100644 --- a/doc/user/java.xml +++ b/doc/user/java.xml @@ -57,9 +57,38 @@ </para> - <programlisting> + <scons_example name="java"> + <file name="SConstruct" printme="1"> Java('classes', 'src') - </programlisting> + </file> + <file name="src/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example2.java"> + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> <para> @@ -69,10 +98,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java - </screen> + <scons_output example="java"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -104,9 +132,54 @@ </para> - <programlisting> + <scons_example name="java-classes"> + <file name="SConstruct" printme="1"> Java('classes', 'src') - </programlisting> + </file> + <file name="src/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + public class AdditionalClass1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example2.java"> + public class Example2 + { + class Inner2 { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + } + </file> + <file name="src/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + public class AdditionalClass3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> <para> @@ -117,12 +190,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java - % <userinput>scons -Q classes</userinput> - scons: `classes' is up to date. - </screen> + <scons_output example="java-classes"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q classes</scons_output_command> + </scons_output> <para> @@ -143,17 +214,10 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java - % <userinput>scons -Q -c classes</userinput> - Removed classes/Example1.class - Removed classes/AdditionalClass1.class - Removed classes/Example2$Inner2.class - Removed classes/Example2.class - Removed classes/Example3.class - Removed classes/AdditionalClass3.class - </screen> + <scons_output example="java-classes"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q -c classes</scons_output_command> + </scons_output> <para> @@ -167,9 +231,9 @@ </para> - <programlisting> + <sconstruct> Java('classes', 'src', JAVAVERSION='1.6') - </programlisting> + </sconstruct> <para> See <varname>JAVAVERSION</varname> in the man page for more information. @@ -193,10 +257,39 @@ </para> - <programlisting> + <scons_example name="jar1"> + <file name="SConstruct" printme="1"> Java(target = 'classes', source = 'src') Jar(target = 'test.jar', source = 'classes') - </programlisting> + </file> + <file name="src/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example2.java"> + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> <para> @@ -207,11 +300,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java - jar cf test.jar classes - </screen> + <scons_output example="jar1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -230,12 +321,50 @@ </para> - <programlisting> + <scons_example name="jar2"> + <file name="SConstruct" printme="1"> prog1_class_files = Java(target = 'classes', source = 'prog1') prog2_class_files = Java(target = 'classes', source = 'prog2') Jar(target = 'prog1.jar', source = prog1_class_files) Jar(target = 'prog2.jar', source = prog2_class_files) - </programlisting> + </file> + <file name="prog1/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="prog1/Example2.java"> + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="prog2/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="prog2/Example4.java"> + public class Example4 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> <para> @@ -247,13 +376,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - javac -d classes -sourcepath prog1 prog1/Example1.java prog1/Example2.java - javac -d classes -sourcepath prog2 prog2/Example3.java prog2/Example4.java - jar cf prog1.jar -C classes Example1.class -C classes Example2.class - jar cf prog2.jar -C classes Example3.class -C classes Example4.class - </screen> + <scons_output example="jar2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -270,10 +395,39 @@ </para> - <programlisting> + <scons_example name="javah"> + <file name="SConstruct" printme="1"> classes = Java(target = 'classes', source = 'src/pkg/sub') JavaH(target = 'native', source = classes) - </programlisting> + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example3.java"> + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> <para> @@ -287,11 +441,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java - javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 - </screen> + <scons_output example="javah"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -327,13 +479,42 @@ </para> - <programlisting> + <scons_example name="JAVACLASSDIR"> + <file name="SConstruct" printme="1"> Java(target = 'classes', source = 'src/pkg/sub') class_file_list = ['classes/pkg/sub/Example1.class', 'classes/pkg/sub/Example2.class', 'classes/pkg/sub/Example3.class'] JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes') - </programlisting> + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example3.java"> + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> <para> @@ -343,11 +524,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java - javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 - </screen> + <scons_output example="JAVACLASSDIR"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -358,10 +537,39 @@ </para> - <programlisting> + <scons_example name="javah_file"> + <file name="SConstruct" printme="1"> classes = Java(target = 'classes', source = 'src/pkg/sub') JavaH(target = File('native.h'), source = classes) - </programlisting> + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example3.java"> + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> <para> @@ -376,11 +584,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java - javah -o native.h -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 - </screen> + <scons_output example="javah_file"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -400,10 +606,30 @@ </para> - <programlisting> + <scons_example name="RMIC"> + <file name="SConstruct" printme="1"> classes = Java(target = 'classes', source = 'src/pkg/sub') RMIC(target = 'outdir', source = classes) - </programlisting> + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> <para> @@ -414,11 +640,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java - rmic -d outdir -classpath classes pkg.sub.Example1 pkg.sub.Example2 - </screen> + <scons_output example="RMIC"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> diff --git a/doc/user/less-simple.in b/doc/user/less-simple.in deleted file mode 100644 index fcffa5e..0000000 --- a/doc/user/less-simple.in +++ /dev/null @@ -1,623 +0,0 @@ -<!-- - - __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> - - In this chapter, - you will see several examples of - very simple build configurations using &SCons;, - which will demonstrate how easy - it is to use &SCons; to - build programs from several different programming languages - on different types of systems. - - </para> - - <section> - <title>Specifying the Name of the Target (Output) File</title> - - <para> - - You've seen that when you call the &b-link-Program; builder method, - it builds the resulting program with the same - base name as the source file. - That is, the following call to build an - executable program from the &hello_c; source file - will build an executable program named &hello; on POSIX systems, - and an executable program named &hello_exe; on Windows systems: - - </para> - - <programlisting> - Program('hello.c') - </programlisting> - - <para> - - If you want to build a program with - a different name than the base of the source file name, - you simply put the target file name - to the left of the source file name: - - </para> - - <scons_example name="target"> - <file name="SConstruct" printme="1"> - Program('new_hello', 'hello.c') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - (&SCons; requires the target file name first, - followed by the source file name, - so that the order mimics that of an - assignment statement in most programming languages, - including Python: - <literal>"program = source files"</literal>.) - - </para> - - <para> - - Now &SCons; will build an executable program - named &new_hello; when run on a POSIX system: - - </para> - - <scons_output example="target" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - And &SCons; will build an executable program - named &new_hello_exe; when run on a Windows system: - - </para> - - <scons_output example="target" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Compiling Multiple Source Files</title> - - <para> - - You've just seen how to configure &SCons; - to compile a program from a single source file. - It's more common, of course, - that you'll need to build a program from - many input source files, not just one. - To do this, you need to put the - source files in a Python list - (enclosed in square brackets), - like so: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - Program(['prog.c', 'file1.c', 'file2.c']) - </file> - <file name="prog.c"> - int main() { printf("prog.c\n"); } - </file> - <file name="file1.c"> - void file1() { printf("file1.c\n"); } - </file> - <file name="file2.c"> - void file2() { printf("file2.c\n"); } - </file> - </scons_example> - - <para> - - A build of the above example would look like: - - </para> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Notice that &SCons; - deduces the output program name - from the first source file specified - in the list--that is, - because the first source file was &prog_c;, - &SCons; will name the resulting program &prog; - (or &prog_exe; on a Windows system). - If you want to specify a different program name, - then (as we've seen in the previous section) - you slide the list of source files - over to the right - to make room for the output program file name. - (&SCons; puts the output file name to the left - of the source file names - so that the order mimics that of an - assignment statement: "program = source files".) - This makes our example: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct" printme="1"> - Program('program', ['prog.c', 'file1.c', 'file2.c']) - </file> - <file name="prog.c"> - int main() { printf("prog.c\n"); } - </file> - <file name="file1.c"> - void file1() { printf("file1.c\n"); } - </file> - <file name="file2.c"> - void file2() { printf("file2.c\n"); } - </file> - </scons_example> - - <para> - - On Linux, a build of this example would look like: - - </para> - - <scons_output example="ex3" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Or on Windows: - - </para> - - <scons_output example="ex3" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Making a list of files with &Glob;</title> - - <para> - - You can also use the &Glob; function to find all files matching a - certain template, using the standard shell pattern matching - characters <literal>*</literal>, <literal>?</literal> - and <literal>[abc]</literal> to match any of - <literal>a</literal>, <literal>b</literal> or <literal>c</literal>. - <literal>[!abc]</literal> is also supported, - to match any character <emphasis>except</emphasis> - <literal>a</literal>, <literal>b</literal> or <literal>c</literal>. - This makes many multi-source-file builds quite easy: - - </para> - - <sconstruct> - Program('program', Glob('*.c')) - </sconstruct> - - <para> - - The SCons man page has more details on using &Glob; - with variant directories - (see <xref linkend="chap-variants"></xref>, below) - and repositories - (see <xref linkend="chap-repositories"></xref>, below), - and returning strings rather than Nodes. - - </para> - - </section> - - <section> - <title>Specifying Single Files Vs. Lists of Files</title> - - <para> - - We've now shown you two ways to specify - the source for a program, - one with a list of files: - - </para> - - <sconstruct> - Program('hello', ['file1.c', 'file2.c']) - </sconstruct> - - <para> - - And one with a single file: - - </para> - - <sconstruct> - Program('hello', 'hello.c') - </sconstruct> - - <para> - - You could actually put a single file name in a list, too, - which you might prefer just for the sake of consistency: - - </para> - - <sconstruct> - Program('hello', ['hello.c']) - </sconstruct> - - <para> - - &SCons; functions will accept a single file name in either form. - In fact, internally, &SCons; treats all input as lists of files, - but allows you to omit the square brackets - to cut down a little on the typing - when there's only a single file name. - - </para> - - <important> - - <para> - - Although &SCons; functions - are forgiving about whether or not you - use a string vs. a list for a single file name, - Python itself is more strict about - treating lists and strings differently. - So where &SCons; allows either - a string or list: - - </para> - - <sconstruct> - # The following two calls both work correctly: - Program('program1', 'program1.c') - Program('program2', ['program2.c']) - </sconstruct> - - <para> - - Trying to do "Python things" that mix strings and - lists will cause errors or lead to incorrect results: - - </para> - - <sconstruct> - common_sources = ['file1.c', 'file2.c'] - - # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR - # BECAUSE IT TRIES TO ADD A STRING TO A LIST: - Program('program1', common_sources + 'program1.c') - - # The following works correctly, because it's adding two - # lists together to make another list. - Program('program2', common_sources + ['program2.c']) - </sconstruct> - - </important> - - </section> - - <section> - <title>Making Lists of Files Easier to Read</title> - - <para> - - One drawback to the use of a Python list - for source files is that - each file name must be enclosed in quotes - (either single quotes or double quotes). - This can get cumbersome and difficult to read - when the list of file names is long. - Fortunately, &SCons; and Python provide a number of ways - to make sure that - the &SConstruct; file stays easy to read. - - </para> - - <para> - - To make long lists of file names - easier to deal with, &SCons; provides a - &Split; function - that takes a quoted list of file names, - with the names separated by spaces or other white-space characters, - and turns it into a list of separate file names. - Using the &Split; function turns the - previous example into: - - </para> - - <programlisting> - Program('program', Split('main.c file1.c file2.c')) - </programlisting> - - <para> - - (If you're already familiar with Python, - you'll have realized that this is similar to the - <function>split()</function> method - in the Python standard <function>string</function> module. - Unlike the <function>split()</function> member function of strings, - however, the &Split; function - does not require a string as input - and will wrap up a single non-string object in a list, - or return its argument untouched if it's already a list. - This comes in handy as a way to make sure - arbitrary values can be passed to &SCons; functions - without having to check the type of the variable by hand.) - - </para> - - <para> - - Putting the call to the &Split; function - inside the &b-Program; call - can also be a little unwieldy. - A more readable alternative is to - assign the output from the &Split; call - to a variable name, - and then use the variable when calling the - &b-Program; function: - - </para> - - <programlisting> - src_files = Split('main.c file1.c file2.c') - Program('program', src_files) - </programlisting> - - <para> - - Lastly, the &Split; function - doesn't care how much white space separates - the file names in the quoted string. - This allows you to create lists of file - names that span multiple lines, - which often makes for easier editing: - - </para> - - <programlisting> - src_files = Split("""main.c - file1.c - file2.c""") - Program('program', src_files) - </programlisting> - - <para> - - (Note in this example that we used - the Python "triple-quote" syntax, - which allows a string to contain - multiple lines. - The three quotes can be either - single or double quotes.) - - </para> - - </section> - - <section> - <title>Keyword Arguments</title> - - <para> - - &SCons; also allows you to identify - the output file and input source files - using Python keyword arguments. - The output file is known as the - <emphasis>target</emphasis>, - and the source file(s) are known (logically enough) as the - <emphasis>source</emphasis>. - The Python syntax for this is: - - </para> - - <programlisting> - src_files = Split('main.c file1.c file2.c') - Program(target = 'program', source = src_files) - </programlisting> - - <para> - - Because the keywords explicitly identify - what each argument is, - you can actually reverse the order if you prefer: - - </para> - - <programlisting> - src_files = Split('main.c file1.c file2.c') - Program(source = src_files, target = 'program') - </programlisting> - - <para> - - Whether or not you choose to use keyword arguments - to identify the target and source files, - and the order in which you specify them - when using keywords, - are purely personal choices; - &SCons; functions the same regardless. - - </para> - - </section> - - <section> - <title>Compiling Multiple Programs</title> - - <para> - - In order to compile multiple programs - within the same &SConstruct; file, - simply call the &Program; method - multiple times, - once for each program you need to build: - - </para> - - <scons_example name="ex4"> - <file name="SConstruct" printme="1"> - Program('foo.c') - Program('bar', ['bar1.c', 'bar2.c']) - </file> - <file name="foo.c"> - int main() { printf("foo.c\n"); } - </file> - <file name="bar1.c"> - int main() { printf("bar1.c\n"); } - </file> - <file name="bar2.c"> - void bar2() { printf("bar2.c\n"); } - </file> - </scons_example> - - <para> - - &SCons; would then build the programs as follows: - - </para> - - <scons_output example="ex4"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Notice that &SCons; does not necessarily build the - programs in the same order in which you specify - them in the &SConstruct; file. - &SCons; does, however, recognize that - the individual object files must be built - before the resulting program can be built. - We'll discuss this in greater detail in - the "Dependencies" section, below. - - </para> - - </section> - - <section> - <title>Sharing Source Files Between Multiple Programs</title> - - <para> - - It's common to re-use code by sharing source files - between multiple programs. - One way to do this is to create a library - from the common source files, - which can then be linked into resulting programs. - (Creating libraries is discussed in - <xref linkend="chap-libraries"></xref>, below.) - - </para> - - <para> - - A more straightforward, but perhaps less convenient, - way to share source files between multiple programs - is simply to include the common files - in the lists of source files for each program: - - </para> - - <scons_example name="ex5"> - <file name="SConstruct" printme="1"> - Program(Split('foo.c common1.c common2.c')) - Program('bar', Split('bar1.c bar2.c common1.c common2.c')) - </file> - <file name="foo.c"> - int main() { printf("foo.c\n"); } - </file> - <file name="bar1.c"> - int main() { printf("bar1.c\n"); } - </file> - <file name="bar2.c"> - int bar2() { printf("bar2.c\n"); } - </file> - <file name="common1.c"> - void common1() { printf("common1.c\n"); } - </file> - <file name="common2.c"> - void common22() { printf("common2.c\n"); } - </file> - </scons_example> - - <para> - - &SCons; recognizes that the object files for - the &common1_c; and &common2_c; source files - each need to be built only once, - even though the resulting object files are - each linked in to both of the resulting executable programs: - - </para> - - <scons_output example="ex5"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - If two or more programs - share a lot of common source files, - repeating the common files in the list for each program - can be a maintenance problem when you need to change the - list of common files. - You can simplify this by creating a separate Python list - to hold the common file names, - and concatenating it with other lists - using the Python + operator: - - </para> - - <programlisting> - common = ['common1.c', 'common2.c'] - foo_files = ['foo.c'] + common - bar_files = ['bar1.c', 'bar2.c'] + common - Program('foo', foo_files) - Program('bar', bar_files) - </programlisting> - - <para> - - This is functionally equivalent to the previous example. - - </para> - - </section> diff --git a/doc/user/less-simple.xml b/doc/user/less-simple.xml index a2b5cf6..fcffa5e 100644 --- a/doc/user/less-simple.xml +++ b/doc/user/less-simple.xml @@ -63,9 +63,14 @@ </para> - <programlisting> + <scons_example name="target"> + <file name="SConstruct" printme="1"> Program('new_hello', 'hello.c') - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -85,11 +90,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o new_hello hello.o - </screen> + <scons_output example="target" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -98,12 +101,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - cl /Fohello.obj /c hello.c /nologo - link /nologo /OUT:new_hello.exe hello.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="target" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -124,9 +124,20 @@ </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> Program(['prog.c', 'file1.c', 'file2.c']) - </programlisting> + </file> + <file name="prog.c"> + int main() { printf("prog.c\n"); } + </file> + <file name="file1.c"> + void file1() { printf("file1.c\n"); } + </file> + <file name="file2.c"> + void file2() { printf("file2.c\n"); } + </file> + </scons_example> <para> @@ -134,13 +145,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o file1.o -c file1.c - cc -o file2.o -c file2.c - cc -o prog.o -c prog.c - cc -o prog prog.o file1.o file2.o - </screen> + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -164,9 +171,20 @@ </para> - <programlisting> + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> Program('program', ['prog.c', 'file1.c', 'file2.c']) - </programlisting> + </file> + <file name="prog.c"> + int main() { printf("prog.c\n"); } + </file> + <file name="file1.c"> + void file1() { printf("file1.c\n"); } + </file> + <file name="file2.c"> + void file2() { printf("file2.c\n"); } + </file> + </scons_example> <para> @@ -174,13 +192,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o file1.o -c file1.c - cc -o file2.o -c file2.c - cc -o prog.o -c prog.c - cc -o program prog.o file1.o file2.o - </screen> + <scons_output example="ex3" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -188,14 +202,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - cl /Fofile1.obj /c file1.c /nologo - cl /Fofile2.obj /c file2.c /nologo - cl /Foprog.obj /c prog.c /nologo - link /nologo /OUT:program.exe prog.obj file1.obj file2.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="ex3" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -216,9 +225,9 @@ </para> - <programlisting> + <sconstruct> Program('program', Glob('*.c')) - </programlisting> + </sconstruct> <para> @@ -244,9 +253,9 @@ </para> - <programlisting> + <sconstruct> Program('hello', ['file1.c', 'file2.c']) - </programlisting> + </sconstruct> <para> @@ -254,9 +263,9 @@ </para> - <programlisting> + <sconstruct> Program('hello', 'hello.c') - </programlisting> + </sconstruct> <para> @@ -265,9 +274,9 @@ </para> - <programlisting> + <sconstruct> Program('hello', ['hello.c']) - </programlisting> + </sconstruct> <para> @@ -293,11 +302,11 @@ </para> - <programlisting> + <sconstruct> # The following two calls both work correctly: Program('program1', 'program1.c') Program('program2', ['program2.c']) - </programlisting> + </sconstruct> <para> @@ -306,7 +315,7 @@ </para> - <programlisting> + <sconstruct> common_sources = ['file1.c', 'file2.c'] # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR @@ -316,7 +325,7 @@ # The following works correctly, because it's adding two # lists together to make another list. Program('program2', common_sources + ['program2.c']) - </programlisting> + </sconstruct> </important> @@ -482,10 +491,21 @@ </para> - <programlisting> + <scons_example name="ex4"> + <file name="SConstruct" printme="1"> Program('foo.c') Program('bar', ['bar1.c', 'bar2.c']) - </programlisting> + </file> + <file name="foo.c"> + int main() { printf("foo.c\n"); } + </file> + <file name="bar1.c"> + int main() { printf("bar1.c\n"); } + </file> + <file name="bar2.c"> + void bar2() { printf("bar2.c\n"); } + </file> + </scons_example> <para> @@ -493,14 +513,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o bar1.o -c bar1.c - cc -o bar2.o -c bar2.c - cc -o bar bar1.o bar2.o - cc -o foo.o -c foo.c - cc -o foo foo.o - </screen> + <scons_output example="ex4"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -541,10 +556,27 @@ </para> - <programlisting> + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> Program(Split('foo.c common1.c common2.c')) Program('bar', Split('bar1.c bar2.c common1.c common2.c')) - </programlisting> + </file> + <file name="foo.c"> + int main() { printf("foo.c\n"); } + </file> + <file name="bar1.c"> + int main() { printf("bar1.c\n"); } + </file> + <file name="bar2.c"> + int bar2() { printf("bar2.c\n"); } + </file> + <file name="common1.c"> + void common1() { printf("common1.c\n"); } + </file> + <file name="common2.c"> + void common22() { printf("common2.c\n"); } + </file> + </scons_example> <para> @@ -556,16 +588,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o bar1.o -c bar1.c - cc -o bar2.o -c bar2.c - cc -o common1.o -c common1.c - cc -o common2.o -c common2.c - cc -o bar bar1.o bar2.o common1.o common2.o - cc -o foo.o -c foo.c - cc -o foo foo.o common1.o common2.o - </screen> + <scons_output example="ex5"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> diff --git a/doc/user/libraries.in b/doc/user/libraries.in deleted file mode 100644 index e219e21..0000000 --- a/doc/user/libraries.in +++ /dev/null @@ -1,445 +0,0 @@ -<!-- - - __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> - - It's often useful to organize large software projects - by collecting parts of the software into one or more libraries. - &SCons; makes it easy to create libraries - and to use them in the programs. - - </para> - - <section> - <title>Building Libraries</title> - - <para> - - You build your own libraries by specifying &b-link-Library; - instead of &b-link-Program;: - - </para> - - <scons_example name="ex1" printme="1"> - <file name="SConstruct" printme="1"> - Library('foo', ['f1.c', 'f2.c', 'f3.c']) - </file> - <file name="f1.c"> - void f1() { printf("f1.c\n"); } - </file> - <file name="f2.c"> - void f2() { printf("f2.c\n"); } - </file> - <file name="f3.c"> - void f3() { printf("f3.c\n"); } - </file> - </scons_example> - - <para> - - &SCons; uses the appropriate library prefix and suffix for your system. - So on POSIX or Linux systems, - the above example would build as follows - (although &ranlib; may not be called on all systems): - - </para> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - On a Windows system, - a build of the above example would look like: - - </para> - - <scons_output example="ex1" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - The rules for the target name of the library - are similar to those for programs: - if you don't explicitly specify a target library name, - &SCons; will deduce one from the - name of the first source file specified, - and &SCons; will add an appropriate - file prefix and suffix if you leave them off. - - </para> - - <section> - <title>Building Libraries From Source Code or Object Files</title> - - <para> - - The previous example shows building a library from a - list of source files. - You can, however, also give the &b-link-Library; call - object files, - and it will correctly realize - In fact, you can arbitrarily mix source code files - and object files in the source list: - - </para> - - <scons_example name="objects" printme="1"> - <file name="SConstruct" printme="1"> - Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o']) - </file> - <file name="f1.c"> - void f1() { printf("f1.c\n"); } - </file> - <file name="f2.o"> - object file - </file> - <file name="f3.c"> - void f3() { printf("f3.c\n"); } - </file> - <file name="f4.o"> - object file - </file> - </scons_example> - - <para> - - And SCons realizes that only the source code files - must be compiled into object files - before creating the final library: - - </para> - - <scons_output example="objects" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Of course, in this example, the object files - must already exist for the build to succeed. - See <xref linkend="chap-nodes"></xref>, below, - for information about how you can - build object files explicitly - and include the built files in a library. - - </para> - - </section> - - <section> - <title>Building Static Libraries Explicitly: the &b-StaticLibrary; Builder</title> - - <para> - - The &b-link-Library; function builds a traditional static library. - If you want to be explicit about the type of library being built, - you can use the synonym &b-link-StaticLibrary; function - instead of &b-Library;: - - </para> - - <scons_example name="StaticLibrary" printme="1"> - <file name="SConstruct" printme="1"> - StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) - </file> - </scons_example> - - <para> - - There is no functional difference between the - &b-link-StaticLibrary; and &b-Library; functions. - - </para> - - </section> - - <section> - <title>Building Shared (DLL) Libraries: the &b-SharedLibrary; Builder</title> - - <para> - - If you want to build a shared library (on POSIX systems) - or a DLL file (on Windows systems), - you use the &b-link-SharedLibrary; function: - - </para> - - <scons_example name="SharedLibrary" printme="1"> - <file name="SConstruct" printme="1"> - SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) - </file> - <file name="f1.c"> - void f1() { printf("f1.c\n"); } - </file> - <file name="f2.c"> - void f2() { printf("f2.c\n"); } - </file> - <file name="f3.c"> - void f3() { printf("f3.c\n"); } - </file> - </scons_example> - - <para> - - The output on POSIX: - - </para> - - <scons_output example="SharedLibrary" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - And the output on Windows: - - </para> - - <scons_output example="SharedLibrary" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Notice again that &SCons; takes care of - building the output file correctly, - adding the <literal>-shared</literal> option - for a POSIX compilation, - and the <literal>/dll</literal> option on Windows. - - </para> - - </section> - - </section> - - <section> - <title>Linking with Libraries</title> - - <para> - - Usually, you build a library - because you want to link it with one or more programs. - You link libraries with a program by specifying - the libraries in the &cv-link-LIBS; construction variable, - and by specifying the directory in which - the library will be found in the - &cv-link-LIBPATH; construction variable: - - <!-- In the preceding paragraph, the "$" notation for - LIBS, LIBPATH etc. is used for the first time. - Maybe some words of explanation would be nice. --> - - </para> - - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - Library('foo', ['f1.c', 'f2.c', 'f3.c']) - Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.') - </file> - <file name="f1.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="f2.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="f3.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="prog.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Notice, of course, that you don't need to specify a library - prefix (like <literal>lib</literal>) - or suffix (like <literal>.a</literal> or <literal>.lib</literal>). - &SCons; uses the correct prefix or suffix for the current system. - - </para> - - <para> - - On a POSIX or Linux system, - a build of the above example would look like: - - </para> - - <scons_output example="ex2" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - On a Windows system, - a build of the above example would look like: - - </para> - - <scons_output example="ex2" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - As usual, notice that &SCons; has taken care - of constructing the correct command lines - to link with the specified library on each system. - - </para> - - <para> - - Note also that, - if you only have a single library to link with, - you can specify the library name in single string, - instead of a Python list, - so that: - - </para> - - <sconstruct> - Program('prog.c', LIBS='foo', LIBPATH='.') - </sconstruct> - - <para> - - is equivalent to: - - </para> - - <sconstruct> - Program('prog.c', LIBS=['foo'], LIBPATH='.') - </sconstruct> - - <para> - - This is similar to the way that &SCons; - handles either a string or a list to - specify a single source file. - - </para> - - </section> - - <section> - <title>Finding Libraries: the &cv-LIBPATH; Construction Variable</title> - - <para> - - By default, the linker will only look in - certain system-defined directories for libraries. - &SCons; knows how to look for libraries - in directories that you specify with the - &cv-link-LIBPATH; construction variable. - &cv-LIBPATH; consists of a list of - directory names, like so: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct" printme="1"> - Program('prog.c', LIBS = 'm', - LIBPATH = ['/usr/lib', '/usr/local/lib']) - </file> - <file name="prog.c"> - int main() { printf("prog.c\n"); } - </file> - </scons_example> - - <para> - - Using a Python list is preferred because it's portable - across systems. Alternatively, you could put all of - the directory names in a single string, separated by the - system-specific path separator character: - a colon on POSIX systems: - - </para> - - <sconstruct> - LIBPATH = '/usr/lib:/usr/local/lib' - </sconstruct> - - <para> - - or a semi-colon on Windows systems: - - </para> - - <sconstruct> - LIBPATH = 'C:\\lib;D:\\lib' - </sconstruct> - - <para> - - (Note that Python requires that the backslash - separators in a Windows path name - be escaped within strings.) - - </para> - - <para> - - When the linker is executed, - &SCons; will create appropriate flags - so that the linker will look for - libraries in the same directories as &SCons;. - So on a POSIX or Linux system, - a build of the above example would look like: - - </para> - - <scons_output example="ex3" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - On a Windows system, - a build of the above example would look like: - - </para> - - <scons_output example="ex3" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - <!-- The link command is too wide in the PDF version. - There are some other examples of this throughout the document. --> - - <para> - - Note again that &SCons; has taken care of - the system-specific details of creating - the right command-line options. - - </para> - - </section> diff --git a/doc/user/libraries.xml b/doc/user/libraries.xml index 9347668..e219e21 100644 --- a/doc/user/libraries.xml +++ b/doc/user/libraries.xml @@ -42,9 +42,20 @@ </para> - <programlisting> + <scons_example name="ex1" printme="1"> + <file name="SConstruct" printme="1"> Library('foo', ['f1.c', 'f2.c', 'f3.c']) - </programlisting> + </file> + <file name="f1.c"> + void f1() { printf("f1.c\n"); } + </file> + <file name="f2.c"> + void f2() { printf("f2.c\n"); } + </file> + <file name="f3.c"> + void f3() { printf("f3.c\n"); } + </file> + </scons_example> <para> @@ -55,14 +66,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o f1.o -c f1.c - cc -o f2.o -c f2.c - cc -o f3.o -c f3.c - ar rc libfoo.a f1.o f2.o f3.o - ranlib libfoo.a - </screen> + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -71,13 +77,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - cl /Fof1.obj /c f1.c /nologo - cl /Fof2.obj /c f2.c /nologo - cl /Fof3.obj /c f3.c /nologo - lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj - </screen> + <scons_output example="ex1" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -106,9 +108,23 @@ </para> - <programlisting> + <scons_example name="objects" printme="1"> + <file name="SConstruct" printme="1"> Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o']) - </programlisting> + </file> + <file name="f1.c"> + void f1() { printf("f1.c\n"); } + </file> + <file name="f2.o"> + object file + </file> + <file name="f3.c"> + void f3() { printf("f3.c\n"); } + </file> + <file name="f4.o"> + object file + </file> + </scons_example> <para> @@ -118,13 +134,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o f1.o -c f1.c - cc -o f3.o -c f3.c - ar rc libfoo.a f1.o f2.o f3.o f4.o - ranlib libfoo.a - </screen> + <scons_output example="objects" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -151,9 +163,11 @@ </para> - <programlisting> + <scons_example name="StaticLibrary" printme="1"> + <file name="SConstruct" printme="1"> StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) - </programlisting> + </file> + </scons_example> <para> @@ -175,9 +189,20 @@ </para> - <programlisting> + <scons_example name="SharedLibrary" printme="1"> + <file name="SConstruct" printme="1"> SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) - </programlisting> + </file> + <file name="f1.c"> + void f1() { printf("f1.c\n"); } + </file> + <file name="f2.c"> + void f2() { printf("f2.c\n"); } + </file> + <file name="f3.c"> + void f3() { printf("f3.c\n"); } + </file> + </scons_example> <para> @@ -185,13 +210,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o f1.os -c f1.c - cc -o f2.os -c f2.c - cc -o f3.os -c f3.c - cc -o libfoo.so -shared f1.os f2.os f3.os - </screen> + <scons_output example="SharedLibrary" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -199,15 +220,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - cl /Fof1.obj /c f1.c /nologo - cl /Fof2.obj /c f2.c /nologo - cl /Fof3.obj /c f3.c /nologo - link /nologo /dll /out:foo.dll /implib:foo.lib f1.obj f2.obj f3.obj - RegServerFunc(target, source, env) - embedManifestDllCheck(target, source, env) - </screen> + <scons_output example="SharedLibrary" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -242,10 +257,24 @@ </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> Library('foo', ['f1.c', 'f2.c', 'f3.c']) Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.') - </programlisting> + </file> + <file name="f1.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="f2.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="f3.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="prog.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -263,16 +292,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o f1.o -c f1.c - cc -o f2.o -c f2.c - cc -o f3.o -c f3.c - ar rc libfoo.a f1.o f2.o f3.o - ranlib libfoo.a - cc -o prog.o -c prog.c - cc -o prog prog.o -L. -lfoo -lbar - </screen> + <scons_output example="ex2" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -281,16 +303,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - cl /Fof1.obj /c f1.c /nologo - cl /Fof2.obj /c f2.c /nologo - cl /Fof3.obj /c f3.c /nologo - lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj - cl /Foprog.obj /c prog.c /nologo - link /nologo /OUT:prog.exe /LIBPATH:. foo.lib bar.lib prog.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="ex2" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -310,9 +325,9 @@ </para> - <programlisting> + <sconstruct> Program('prog.c', LIBS='foo', LIBPATH='.') - </programlisting> + </sconstruct> <para> @@ -320,9 +335,9 @@ </para> - <programlisting> + <sconstruct> Program('prog.c', LIBS=['foo'], LIBPATH='.') - </programlisting> + </sconstruct> <para> @@ -349,10 +364,15 @@ </para> - <programlisting> + <scons_example name="ex3"> + <file name="SConstruct" printme="1"> Program('prog.c', LIBS = 'm', LIBPATH = ['/usr/lib', '/usr/local/lib']) - </programlisting> + </file> + <file name="prog.c"> + int main() { printf("prog.c\n"); } + </file> + </scons_example> <para> @@ -364,9 +384,9 @@ </para> - <programlisting> + <sconstruct> LIBPATH = '/usr/lib:/usr/local/lib' - </programlisting> + </sconstruct> <para> @@ -374,9 +394,9 @@ </para> - <programlisting> + <sconstruct> LIBPATH = 'C:\\lib;D:\\lib' - </programlisting> + </sconstruct> <para> @@ -397,11 +417,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o prog.o -c prog.c - cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm - </screen> + <scons_output example="ex3" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -410,12 +428,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - cl /Foprog.obj /c prog.c /nologo - link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="ex3" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <!-- The link command is too wide in the PDF version. There are some other examples of this throughout the document. --> diff --git a/doc/user/main.in b/doc/user/main.in deleted file mode 100644 index 61b544f..0000000 --- a/doc/user/main.in +++ /dev/null @@ -1,411 +0,0 @@ -<?xml version="1.0"?> -<!-- - - __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. - ---> - -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" -"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" -[ - - <!ENTITY % version SYSTEM "../version.xml"> - %version; - - <!ENTITY % scons SYSTEM "../scons.mod"> - %scons; - - <!ENTITY % builders-mod SYSTEM "builders.mod"> - %builders-mod; - - <!ENTITY % functions-mod SYSTEM "functions.mod"> - %functions-mod; - - <!ENTITY % tools-mod SYSTEM "tools.mod"> - %tools-mod; - - <!ENTITY % variables-mod SYSTEM "variables.mod"> - %variables-mod; - - <!ENTITY actions SYSTEM "actions.xml"> - <!ENTITY alias SYSTEM "alias.xml"> - <!ENTITY ant SYSTEM "ant.xml"> - <!ENTITY build-install SYSTEM "build-install.xml"> - <!ENTITY builders SYSTEM "builders.xml"> - <!ENTITY builders-built-in SYSTEM "builders-built-in.xml"> - <!ENTITY builders-commands SYSTEM "builders-commands.xml"> - <!ENTITY builders-writing SYSTEM "builders-writing.xml"> - <!ENTITY add-method SYSTEM "add-method.xml"> - <!ENTITY caching SYSTEM "caching.xml"> - <!ENTITY command-line SYSTEM "command-line.xml"> - <!ENTITY copyright SYSTEM "copyright.xml"> - <!ENTITY depends SYSTEM "depends.xml"> - <!ENTITY environments SYSTEM "environments.xml"> - <!ENTITY errors SYSTEM "errors.xml"> - <!ENTITY example SYSTEM "example.xml"> - <!ENTITY factories SYSTEM "factories.xml"> - <!ENTITY file-removal SYSTEM "file-removal.xml"> - <!ENTITY functions SYSTEM "functions.xml"> - <!ENTITY gettext SYSTEM "gettext.xml"> - <!ENTITY hierarchy SYSTEM "hierarchy.xml"> - <!ENTITY java SYSTEM "java.xml"> - <!ENTITY install SYSTEM "install.xml"> - <!ENTITY less-simple SYSTEM "less-simple.xml"> - <!ENTITY libraries SYSTEM "libraries.xml"> - <!ENTITY make SYSTEM "make.xml"> - <!ENTITY mergeflags SYSTEM "mergeflags.xml"> - <!ENTITY misc SYSTEM "misc.xml"> - <!ENTITY nodes SYSTEM "nodes.xml"> - <!ENTITY output SYSTEM "output.xml"> - <!ENTITY parseconfig SYSTEM "parseconfig.xml"> - <!ENTITY parseflags SYSTEM "parseflags.xml"> - <!ENTITY preface SYSTEM "preface.xml"> - <!ENTITY python SYSTEM "python.xml"> - <!ENTITY repositories SYSTEM "repositories.xml"> - <!ENTITY run SYSTEM "run.xml"> - <!ENTITY scanners SYSTEM "scanners.xml"> - <!ENTITY sconf SYSTEM "sconf.xml"> - <!ENTITY separate SYSTEM "separate.xml"> - <!ENTITY simple SYSTEM "simple.xml"> - <!ENTITY sourcecode SYSTEM "sourcecode.xml"> - <!ENTITY tasks SYSTEM "tasks.xml"> - <!ENTITY tools SYSTEM "tools.xml"> - <!ENTITY troubleshoot SYSTEM "troubleshoot.xml"> - <!ENTITY variables-xml SYSTEM "variables.xml"> - <!ENTITY variants SYSTEM "variants.xml"> - - <!ENTITY builders-gen SYSTEM "builders.gen"> - <!ENTITY functions-gen SYSTEM "functions.gen"> - <!ENTITY tools-gen SYSTEM "tools.gen"> - <!ENTITY variables-gen SYSTEM "variables.gen"> - -]> - - <!-- - - XXX Platform() - XXX Tools() - - XXX GetOption('duplicate') - XXX SetOption('duplicate') - XXX - - duplicate= - - XXX CheckTypeSize() - - XXX - - diskcheck= - - XXX - - warn= - - --> - -<book> - <bookinfo> - <title>SCons User Guide &buildversion;</title> - - <author> - <firstname>Steven</firstname> - <surname>Knight</surname> - </author> - - <edition>Revision &buildrevision; (&builddate;)</edition> - - <pubdate>2004, 2005, 2006, 2007, 2008, 2009, 2010</pubdate> - - <copyright> - <year>2004, 2005, 2006, 2007, 2008, 2009, 2010</year> - <holder>Steven Knight</holder> - </copyright> - - <legalnotice> - ©right; - </legalnotice> - - <releaseinfo>version &buildversion;</releaseinfo> - - </bookinfo> - - <preface id="chap-preface"> - <title>Preface</title> - &preface; - </preface> - - <chapter id="chap-build-install"> - <title>Building and Installing &SCons;</title> - &build-install; - </chapter> - - <chapter id="chap-simple"> - <title>Simple Builds</title> - &simple; - </chapter> - - <chapter id="chap-less-simple"> - <title>Less Simple Things to Do With Builds</title> - &less-simple; - </chapter> - - <chapter id="chap-libraries"> - <title>Building and Linking with Libraries</title> - &libraries; - </chapter> - - <chapter id="chap-nodes"> - <title>Node Objects</title> - &nodes; - </chapter> - - <chapter id="chap-depends"> - <title>Dependencies</title> - &depends; - </chapter> - - <chapter id="chap-environments"> - <title>Environments</title> - &environments; - </chapter> - - <chapter id="chap-manip-options"> - <title>Automatically Putting Command-line Options into their Construction Variables</title> - <!-- TODO: This intro paragraph should describe at a high-level - what these things do. People are likely to use the intro as a - (brief) overview of *what* these functions do to decide if this - chapter is where they should read in more detail. --> - <para> - This chapter describes the &MergeFlags;, &ParseFlags;, and &ParseConfig; methods of a &consenv;. - </para> - <section id="sect-mergeflags"> - <title>Merging Options into the Environment: the &MergeFlags; Function</title> - &mergeflags; - </section> - <section id="sect-parseflags"> - <title>Separating Compile Arguments into their Variables: the &ParseFlags; Function</title> - &parseflags; - </section> - <section id="sect-parseconfig"> - <title>Finding Installed Library Information: the &ParseConfig; Function</title> - &parseconfig; - </section> - <!-- - XXX parse_flags= option of Environment() - - <section id="sect-env-parseflags"> - <title>Adding Flags when Constructing Enviroment: the parse_flags Optional Argument</title> - &envparseflags; - </section> - --> - </chapter> - - <chapter id="chap-output"> - <title>Controlling Build Output</title> - &output; - </chapter> - - <chapter id="chap-command-line"> - <title>Controlling a Build From the Command Line</title> - &command-line; - </chapter> - - <chapter id="chap-install"> - <title>Installing Files in Other Directories: the &Install; Builder</title> - &install; - </chapter> - - <chapter id="chap-factories"> - <title>Platform-Independent File System Manipulation</title> - &factories; - </chapter> - - <chapter id="chap-file-removal"> - <title>Controlling Removal of Targets</title> - &file-removal; - </chapter> - - <chapter id="chap-hierarchical"> - <title>Hierarchical Builds</title> - &hierarchy; - </chapter> - - <chapter id="chap-separate"> - <title>Separating Source and Build Directories</title> - &separate; - </chapter> - - <chapter id="chap-variants"> - <title>Variant Builds</title> - &variants; - </chapter> - - <chapter id="chap-gettext"> - <title>Internationalization and localization with gettext</title> - &gettext; - </chapter> - - <!-- - - <chapter id="chap-builders-built-in"> - <title>Built-In Builders</title> - &builders-built-in; - </chapter> - - --> - - <chapter id="chap-builders-writing"> - <title>Writing Your Own Builders</title> - &builders-writing; - </chapter> - - <chapter id="chap-builders-commands"> - <title>Not Writing a Builder: the &Command; Builder</title> - &builders-commands; - </chapter> - - <chapter id="chap-add-method"> - <title>Pseudo-Builders: the AddMethod function</title> - &add-method; - </chapter> - - <!-- - - XXX Action() - XXX AddPostAction() - XXX AddPreAction() - - <chapter id="chap-actions"> - <title>&SCons; Actions</title> - &actions; - </chapter> - - --> - - <chapter id="chap-scanners"> - <title>Writing Scanners</title> - &scanners; - </chapter> - - <chapter id="chap-repositories"> - <title>Building From Code Repositories</title> - &repositories; - </chapter> - - <chapter id="chap-sconf"> - <title>Multi-Platform Configuration (&Autoconf; Functionality)</title> - &sconf; - </chapter> - - <!-- - - <chapter id="chap-sourcecode"> - <title>Fetching Files From Source Code Management Systems</title> - &sourcecode; - </chapter> - - --> - - <chapter id="chap-caching"> - <title>Caching Built Files</title> - &caching; - </chapter> - - <chapter id="chap-alias"> - <title>Alias Targets</title> - &alias; - </chapter> - - <chapter id="chap-java"> - <title>Java Builds</title> - &java; - </chapter> - - <!-- - - <chapter id="chap-run"> - <title>How to Run &SCons;</title> - &run; - </chapter> - - --> - - <chapter id="chap-misc"> - <title>Miscellaneous Functionality</title> - &misc; - </chapter> - - <chapter id="chap-troubleshooting"> - <title>Troubleshooting</title> - &troubleshoot; - </chapter> - - <appendix id="app-variables"> - <title>Construction Variables</title> - &variables-xml; - </appendix> - - <appendix id="app-builders"> - <title>Builders</title> - &builders; - </appendix> - - <appendix id="app-tools"> - <title>Tools</title> - &tools; - </appendix> - - <appendix id="app-functions"> - <title>Functions and Environment Methods</title> - &functions; - </appendix> - - <appendix id="app-tasks"> - <title>Handling Common Tasks</title> - &tasks; - </appendix> - - <!-- - - <appendix id="app-python"> - <title>Python Overview</title> - &example; - </appendix> - - <appendix id="app-example"> - <title>Complex &SCons; Example</title> - &example; - </appendix> - - <appendix id="app-make"> - <title>Converting From Make</title> - &make; - </appendix> - - <appendix id="app-cons"> - <title>Converting From Cons</title> - &cons; - </appendix> - - <appendix id="app-ant"> - <title>Converting From Ant</title> - &ant; - </appendix> - - --> - -</book> diff --git a/doc/user/make.in b/doc/user/make.in deleted file mode 100644 index 72b2df1..0000000 --- a/doc/user/make.in +++ /dev/null @@ -1,121 +0,0 @@ -<!-- - - __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. - ---> - -<!-- - -=head1 Why Cons? Why not Make? - -Cons is a B<make> replacement. In the following paragraphs, we look at a few -of the undesirable characteristics of make, and typical build environments -based on make, that motivated the development of Cons. - -=head2 Build complexity - -Traditional make-based systems of any size tend to become quite complex. The -original make utility and its derivatives have contributed to this tendency -in a number of ways. Make is not good at dealing with systems that are -spread over multiple directories. Various work-arounds are used to overcome -this difficulty; the usual choice is for make to invoke itself recursively -for each sub-directory of a build. This leads to complicated code, in which -it is often unclear how a variable is set, or what effect the setting of a -variable will have on the build as a whole. The make scripting language has -gradually been extended to provide more possibilities, but these have -largely served to clutter an already overextended language. Often, builds -are done in multiple passes in order to provide appropriate products from -one directory to another directory. This represents a further increase in -build complexity. - - -=head2 Build reproducibility - -The bane of all makes has always been the correct handling of -dependencies. Most often, an attempt is made to do a reasonable job of -dependencies within a single directory, but no serious attempt is made to do -the job between directories. Even when dependencies are working correctly, -make's reliance on a simple time stamp comparison to determine whether a -file is out of date with respect to its dependents is not, in general, -adequate for determining when a file should be rederived. If an external -library, for example, is rebuilt and then ``snapped'' into place, the -timestamps on its newly created files may well be earlier than the last -local build, since it was built before it became visible. - - -=head2 Variant builds - -Make provides only limited facilities for handling variant builds. With the -proliferation of hardware platforms and the need for debuggable -vs. optimized code, the ability to easily create these variants is -essential. More importantly, if variants are created, it is important to -either be able to separate the variants or to be able to reproduce the -original or variant at will. With make it is very difficult to separate the -builds into multiple build directories, separate from the source. And if -this technique isn't used, it's also virtually impossible to guarantee at -any given time which variant is present in the tree, without resorting to a -complete rebuild. - - -=head2 Repositories - -Make provides only limited support for building software from code that -exists in a central repository directory structure. The VPATH feature of -GNU make (and some other make implementations) is intended to provide this, -but doesn't work as expected: it changes the path of target file to the -VPATH name too early in its analysis, and therefore searches for all -dependencies in the VPATH directory. To ensure correct development builds, -it is important to be able to create a file in a local build directory and -have any files in a code repository (a VPATH directory, in make terms) that -depend on the local file get rebuilt properly. This isn't possible with -VPATH, without coding a lot of complex repository knowledge directly into -the makefiles. - ---> - - <para> - - XXX - - </para> - - <section> - <title>Differences Between &Make; and &SCons;</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Advantages of &SCons; Over &Make;</title> - - <para> - - XXX - - </para> - - </section> diff --git a/doc/user/mergeflags.in b/doc/user/mergeflags.in deleted file mode 100644 index a148409..0000000 --- a/doc/user/mergeflags.in +++ /dev/null @@ -1,137 +0,0 @@ -<!-- - - __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> - - &SCons; construction environments have a &MergeFlags; method - that merges a dictionary of values into the construction environment. - &MergeFlags; treats each value in the dictionary - as a list of options such as one might pass to a command - (such as a compiler or linker). - &MergeFlags; will not duplicate an option - if it already exists in the construction environment variable. - - </para> - - <para> - - &MergeFlags; tries to be intelligent about merging options. - When merging options to any variable - whose name ends in <varname>PATH</varname>, - &MergeFlags; keeps the leftmost occurrence of the option, - because in typical lists of directory paths, - the first occurrence "wins." - When merging options to any other variable name, - &MergeFlags; keeps the rightmost occurrence of the option, - because in a list of typical command-line options, - the last occurrence "wins." - - </para> - - <scons_example name="MergeFlags1"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Append(CCFLAGS = '-option -O3 -O1') - flags = { 'CCFLAGS' : '-whatever -O3' } - env.MergeFlags(flags) - print env['CCFLAGS'] - </file> - </scons_example> - - <scons_output example="MergeFlags1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note that the default value for &cv-link-CCFLAGS; - <!-- - [TODO: for when we make CLVar public] - is a <varname>CLVar</varname>, - --> - is an internal &SCons; object - which automatically converts - the options we specified as a string into a list. - - </para> - - <scons_example name="MergeFlags2"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) - flags = { 'CPPPATH' : ['/usr/opt/include', '/usr/local/include'] } - env.MergeFlags(flags) - print env['CPPPATH'] - </file> - </scons_example> - - <scons_output example="MergeFlags2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note that the default value for &cv-link-CPPPATH; - <!-- - [TODO: for when we make CLVar public] - is a Python list, not a <varname>CLVar</varname>, - --> - is a normal Python list, - so we must specify its values as a list - in the dictionary we pass to the &MergeFlags; function. - - </para> - - <para> - - If &MergeFlags; is passed anything other than a dictionary, - it calls the &ParseFlags; method to convert it into a dictionary. - - </para> - - <scons_example name="MergeFlags3"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Append(CCFLAGS = '-option -O3 -O1') - env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) - env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include') - print env['CCFLAGS'] - print env['CPPPATH'] - </file> - </scons_example> - - <scons_output example="MergeFlags3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - In the combined example above, - &ParseFlags; has sorted the options into their corresponding variables - and returned a dictionary for &MergeFlags; to apply - to the construction variables - in the specified construction environment. - - </para> diff --git a/doc/user/mergeflags.xml b/doc/user/mergeflags.xml index 723ab74..a148409 100644 --- a/doc/user/mergeflags.xml +++ b/doc/user/mergeflags.xml @@ -50,19 +50,19 @@ </para> - <programlisting> + <scons_example name="MergeFlags1"> + <file name="SConstruct" printme="1"> env = Environment() env.Append(CCFLAGS = '-option -O3 -O1') flags = { 'CCFLAGS' : '-whatever -O3' } env.MergeFlags(flags) print env['CCFLAGS'] - </programlisting> + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - ['-option', '-O1', '-whatever', '-O3'] - scons: `.' is up to date. - </screen> + <scons_output example="MergeFlags1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -77,19 +77,19 @@ </para> - <programlisting> + <scons_example name="MergeFlags2"> + <file name="SConstruct" printme="1"> env = Environment() env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) flags = { 'CPPPATH' : ['/usr/opt/include', '/usr/local/include'] } env.MergeFlags(flags) print env['CPPPATH'] - </programlisting> + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - ['/include', '/usr/local/include', '/usr/include', '/usr/opt/include'] - scons: `.' is up to date. - </screen> + <scons_output example="MergeFlags2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -111,21 +111,20 @@ </para> - <programlisting> + <scons_example name="MergeFlags3"> + <file name="SConstruct" printme="1"> env = Environment() env.Append(CCFLAGS = '-option -O3 -O1') env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include') print env['CCFLAGS'] print env['CPPPATH'] - </programlisting> - - <screen> - % <userinput>scons -Q</userinput> - ['-option', '-O1', '-whatever', '-O3'] - ['/include', '/usr/local/include', '/usr/include', '/usr/opt/include'] - scons: `.' is up to date. - </screen> + </file> + </scons_example> + + <scons_output example="MergeFlags3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> diff --git a/doc/user/misc.in b/doc/user/misc.in deleted file mode 100644 index dde75bf..0000000 --- a/doc/user/misc.in +++ /dev/null @@ -1,606 +0,0 @@ -<!-- - - __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> - - &SCons; supports a lot of additional functionality - that doesn't readily fit into the other chapters. - - </para> - - <section> - <title>Verifying the Python Version: the &EnsurePythonVersion; Function</title> - - <para> - - Although the &SCons; code itself will run - on any 2.x Python version 2.4 or later, - you are perfectly free to make use of - Python syntax and modules from more modern versions - (for example, Python 2.5 or 2.6) - when writing your &SConscript; files - or your own local modules. - If you do this, it's usually helpful to - configure &SCons; to exit gracefully with an error message - if it's being run with a version of Python - that simply won't work with your code. - This is especially true if you're going to use &SCons; - to build source code that you plan to distribute publicly, - where you can't be sure of the Python version - that an anonymous remote user might use - to try to build your software. - - </para> - - <para> - - &SCons; provides an &EnsurePythonVersion; function for this. - You simply pass it the major and minor versions - numbers of the version of Python you require: - - </para> - - <!-- - - TODO: Figure out how to generate the error message - regardless of executing Python version by faking out - the infrastructure in some way. - - <scons_example name="EnsurePythonVersion"> - <file name="SConstruct" printme="1"> - EnsurePythonVersion(2, 5) - </file> - </scons_example> - - --> - - <sconstruct> - EnsurePythonVersion(2, 5) - </sconstruct> - - <para> - - And then &SCons; will exit with the following error - message when a user runs it with an unsupported - earlier version of Python: - - </para> - - <!-- - - TODO: Figure out how to generate the error message - regardless of executing Python version by faking out - the infrastructure in some way. - - <scons_output example="EnsurePythonVersion"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - --> - - <screen> - % <userinput>scons -Q</userinput> - Python 2.5 or greater required, but you have Python 2.3.6 - </screen> - - </section> - - <section> - <title>Verifying the SCons Version: the &EnsureSConsVersion; Function</title> - - <para> - - You may, of course, write your &SConscript; files - to use features that were only added in - recent versions of &SCons;. - When you publicly distribute software that is built using &SCons;, - it's helpful to have &SCons; - verify the version being used and - exit gracefully with an error message - if the user's version of &SCons; won't work - with your &SConscript; files. - &SCons; provides an &EnsureSConsVersion; function - that verifies the version of &SCons; - in the same - the &EnsurePythonVersion; function - verifies the version of Python, - by passing in the major and minor versions - numbers of the version of SCons you require: - - </para> - - <!-- - - TODO: Figure out how to generate the error message - regardless of executing SCons version by faking out - the infrastructure in some way. - - <scons_example name="EnsureSConsVersion"> - <file name="SConstruct" printme="1"> - EnsureSConsVersion(1, 0) - </file> - </scons_example> - - --> - - <sconstruct> - EnsureSConsVersion(1, 0) - </sconstruct> - - <para> - - And then &SCons; will exit with the following error - message when a user runs it with an unsupported - earlier version of &SCons;: - - </para> - - <!-- - - TODO: Figure out how to generate the error message - regardless of executing SCons version by faking out - the infrastructure in some way. - - <scons_output example="EnsureSConsVersion"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - --> - - <screen> - % <userinput>scons -Q</userinput> - SCons 1.0 or greater required, but you have SCons 0.98.5 - </screen> - - </section> - - <section> - <title>Explicitly Terminating &SCons; While Reading &SConscript; Files: the &Exit; Function</title> - - <para> - - &SCons; supports an &Exit; function - which can be used to terminate &SCons; - while reading the &SConscript; files, - usually because you've detected a condition - under which it doesn't make sense to proceed: - - </para> - - <scons_example name="Exit"> - <file name="SConstruct" printme="1"> - if ARGUMENTS.get('FUTURE'): - print "The FUTURE option is not supported yet!" - Exit(2) - env = Environment() - env.Program('hello.c') - </file> - <file name="hello.c"> - hello.c - </file> - </scons_example> - - <scons_output example="Exit"> - <scons_output_command>scons -Q FUTURE=1</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - The &Exit; function takes as an argument - the (numeric) exit status that you want &SCons; to exit with. - If you don't specify a value, - the default is to exit with <literal>0</literal>, - which indicates successful execution. - - </para> - - <para> - - Note that the &Exit; function - is equivalent to calling the Python - <function>sys.exit</function> function - (which the it actually calls), - but because &Exit; is a &SCons; function, - you don't have to import the Python - <literal>sys</literal> module to use it. - - </para> - - </section> - - <section> - <title>Searching for Files: the &FindFile; Function</title> - - <para> - - The &FindFile; function searches for a file in a list of directories. - If there is only one directory, it can be given as a simple string. - The function returns a File node if a matching file exists, - or None if no file is found. - (See the documentation for the &Glob; function for an alternative way - of searching for entries in a directory.) - - </para> - - <scons_example name="FindFile1a"> - <file name="SConstruct" printme="1"> - # one directory - print FindFile('missing', '.') - t = FindFile('exists', '.') - print t.__class__, t - </file> - <file name="exists"> - exists - </file> - </scons_example> - - <scons_output example="FindFile1a" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <scons_example name="FindFile1b"> - <file name="SConstruct" printme="1"> - # several directories - includes = [ '.', 'include', 'src/include'] - headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h'] - for hdr in headers: - print '%-12s' % ('%s:' % hdr), FindFile(hdr, includes) - </file> - <file name="config.h"> - exists - </file> - <directory name="src"></directory> - <directory name="src/include"></directory> - <file name="src/include/private.h"> - exists - </file> - <directory name="include"></directory> - <file name="include/dist.h"> - exists - </file> - </scons_example> - - <scons_output example="FindFile1b" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <!-- The man page says this should work, but it fails. - <para> - - If the 'file' parameter is a list of files, - a list of File nodes is returned. - - </para> - - <scons_example name="FindFile1c"> - <file name="SConstruct" printme="1"> - # several directories - includes = [ '.', 'include', 'src/include'] - headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h'] - print FindFile(headers, includes) - </file> - <file name="config.h"> - exists - </file> - <directory name="src"></directory> - <directory name="src/include"></directory> - </file> - <file name="src/include/private.h"> - exists - <directory name="include"></directory> - </file> - <file name="include/dist.h"> - exists - </scons_example> - - <scons_output example="FindFile1c" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - --> - - <para> - - If the file exists in more than one directory, - only the first occurrence is returned. - - </para> - - <scons_example name="FindFile1d"> - <file name="SConstruct" printme="1"> - print FindFile('multiple', ['sub1', 'sub2', 'sub3']) - print FindFile('multiple', ['sub2', 'sub3', 'sub1']) - print FindFile('multiple', ['sub3', 'sub1', 'sub2']) - </file> - <directory name="sub1"></directory> - <file name="sub1/multiple"> - exists - </file> - <directory name="sub2"></directory> - <file name="sub2/multiple"> - exists - </file> - <directory name="sub3"></directory> - <file name="sub3/multiple"> - exists - </file> - </scons_example> - - <scons_output example="FindFile1d" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <!-- file may be a list of file names or a single file name. --> - - <para> - - In addition to existing files, &FindFile; will also find derived files - (that is, non-leaf files) that haven't been built yet. - (Leaf files should already exist, or the build will fail!) - - </para> - - <scons_example name="FindFile2"> - <file name="SConstruct" printme="1"> - # Neither file exists, so build will fail - Command('derived', 'leaf', 'cat >$TARGET $SOURCE') - print FindFile('leaf', '.') - print FindFile('derived', '.') - </file> - </scons_example> - - <scons_output example="FindFile2" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <scons_example name="FindFile2"> - <file name="SConstruct" printme="1"> - # Only 'leaf' exists - Command('derived', 'leaf', 'cat >$TARGET $SOURCE') - print FindFile('leaf', '.') - print FindFile('derived', '.') - </file> - <file name="leaf"> - leaf - </file> - </scons_example> - - <scons_output example="FindFile2" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - If a source file exists, &FindFile; will correctly return the name - in the build directory. - - </para> - - <scons_example name="FindFile3"> - <file name="SConstruct" printme="1"> - # Only 'src/leaf' exists - VariantDir('build', 'src') - print FindFile('leaf', 'build') - </file> - <directory name="src"></directory> - <file name="src/leaf"> - leaf - </file> - </scons_example> - - <scons_output example="FindFile3" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Handling Nested Lists: the &Flatten; Function</title> - - <para> - - &SCons; supports a &Flatten; function - which takes an input Python sequence - (list or tuple) - and returns a flattened list - containing just the individual elements of - the sequence. - This can be handy when trying to examine - a list composed of the lists - returned by calls to various Builders. - For example, you might collect - object files built in different ways - into one call to the &Program; Builder - by just enclosing them in a list, as follows: - - </para> - - <scons_example name="Flatten1"> - <file name="SConstruct" printme="1"> - objects = [ - Object('prog1.c'), - Object('prog2.c', CCFLAGS='-DFOO'), - ] - Program(objects) - </file> - <file name="prog1.c"> - prog1.c - </file> - <file name="prog2.c"> - prog2.c - </file> - </scons_example> - - <para> - - Because the Builder calls in &SCons; - flatten their input lists, - this works just fine to build the program: - - </para> - - <scons_output example="Flatten1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - But if you were debugging your build - and wanted to print the absolute path - of each object file in the - <varname>objects</varname> list, - you might try the following simple approach, - trying to print each Node's - <literal>abspath</literal> - attribute: - - </para> - - <scons_example name="Flatten2"> - <file name="SConstruct" printme="1"> - objects = [ - Object('prog1.c'), - Object('prog2.c', CCFLAGS='-DFOO'), - ] - Program(objects) - - for object_file in objects: - print object_file.abspath - </file> - <file name="prog1.c"> - prog1.c - </file> - <file name="prog2.c"> - prog2.c - </file> - </scons_example> - - <para> - - This does not work as expected - because each call to <function>str</function> - is operating an embedded list returned by - each &Object; call, - not on the underlying Nodes within those lists: - - </para> - - <scons_output example="Flatten2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - The solution is to use the &Flatten; function - so that you can pass each Node to - the <function>str</function> separately: - - </para> - - <scons_example name="Flatten3"> - <file name="SConstruct" printme="1"> - objects = [ - Object('prog1.c'), - Object('prog2.c', CCFLAGS='-DFOO'), - ] - Program(objects) - - for object_file in Flatten(objects): - print object_file.abspath - </file> - <file name="prog1.c"> - prog1.c - </file> - <file name="prog2.c"> - prog2.c - </file> - </scons_example> - - <!-- - - TODO: can't use this now because it displays the temporary path name - - <scons_output example="Flatten3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - --> - - <screen> - % <userinput>scons -Q</userinput> - /home/me/project/prog1.o - /home/me/project/prog2.o - cc -o prog1.o -c prog1.c - cc -o prog2.o -c -DFOO prog2.c - cc -o prog1 prog1.o prog2.o - </screen> - - </section> - - <section> - <title>Finding the Invocation Directory: the &GetLaunchDir; Function</title> - - <para> - - If you need to find the directory from - which the user invoked the &scons; command, - you can use the &GetLaunchDir; function: - - </para> - - <sconstruct> - env = Environment( - LAUNCHDIR = GetLaunchDir(), - ) - env.Command('directory_build_info', - '$LAUNCHDIR/build_info' - Copy('$TARGET', '$SOURCE')) - </sconstruct> - - <para> - - Because &SCons; is usually invoked from the top-level - directory in which the &SConstruct; file lives, - the Python <function>os.getcwd()</function> - is often equivalent. - However, the &SCons; - <literal>-u</literal>, - <literal>-U</literal> - and - <literal>-D</literal> - command-line options, - when invoked from a subdirectory, - will cause &SCons; to change to the directory - in which the &SConstruct; file is found. - When those options are used, - &GetLaunchDir; will still return the path to the - user's invoking subdirectory, - allowing the &SConscript; configuration - to still get at configuration (or other) files - from the originating directory. - - </para> - - </section> diff --git a/doc/user/misc.xml b/doc/user/misc.xml index a8885d7..dde75bf 100644 --- a/doc/user/misc.xml +++ b/doc/user/misc.xml @@ -76,9 +76,9 @@ --> - <programlisting> + <sconstruct> EnsurePythonVersion(2, 5) - </programlisting> + </sconstruct> <para> @@ -145,9 +145,9 @@ --> - <programlisting> + <sconstruct> EnsureSConsVersion(1, 0) - </programlisting> + </sconstruct> <para> @@ -189,21 +189,23 @@ </para> - <programlisting> + <scons_example name="Exit"> + <file name="SConstruct" printme="1"> if ARGUMENTS.get('FUTURE'): print "The FUTURE option is not supported yet!" Exit(2) env = Environment() env.Program('hello.c') - </programlisting> + </file> + <file name="hello.c"> + hello.c + </file> + </scons_example> - <screen> - % <userinput>scons -Q FUTURE=1</userinput> - The FUTURE option is not supported yet! - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="Exit"> + <scons_output_command>scons -Q FUTURE=1</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -243,36 +245,47 @@ </para> - <programlisting> + <scons_example name="FindFile1a"> + <file name="SConstruct" printme="1"> # one directory print FindFile('missing', '.') t = FindFile('exists', '.') print t.__class__, t - </programlisting> + </file> + <file name="exists"> + exists + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - None - <class 'SCons.Node.FS.File'> exists - scons: `.' is up to date. - </screen> + <scons_output example="FindFile1a" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> - <programlisting> + <scons_example name="FindFile1b"> + <file name="SConstruct" printme="1"> # several directories includes = [ '.', 'include', 'src/include'] headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h'] for hdr in headers: print '%-12s' % ('%s:' % hdr), FindFile(hdr, includes) - </programlisting> + </file> + <file name="config.h"> + exists + </file> + <directory name="src"></directory> + <directory name="src/include"></directory> + <file name="src/include/private.h"> + exists + </file> + <directory name="include"></directory> + <file name="include/dist.h"> + exists + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - nonesuch.h: None - config.h: config.h - private.h: src/include/private.h - dist.h: include/dist.h - scons: `.' is up to date. - </screen> + <scons_output example="FindFile1b" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <!-- The man page says this should work, but it fails. <para> @@ -315,19 +328,29 @@ </para> - <programlisting> + <scons_example name="FindFile1d"> + <file name="SConstruct" printme="1"> print FindFile('multiple', ['sub1', 'sub2', 'sub3']) print FindFile('multiple', ['sub2', 'sub3', 'sub1']) print FindFile('multiple', ['sub3', 'sub1', 'sub2']) - </programlisting> + </file> + <directory name="sub1"></directory> + <file name="sub1/multiple"> + exists + </file> + <directory name="sub2"></directory> + <file name="sub2/multiple"> + exists + </file> + <directory name="sub3"></directory> + <file name="sub3/multiple"> + exists + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - sub1/multiple - sub2/multiple - sub3/multiple - scons: `.' is up to date. - </screen> + <scons_output example="FindFile1d" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <!-- file may be a list of file names or a single file name. --> @@ -339,38 +362,34 @@ </para> - <programlisting> + <scons_example name="FindFile2"> + <file name="SConstruct" printme="1"> # Neither file exists, so build will fail - Command('derived', 'leaf', 'cat >$TARGET $SOURCE') + Command('derived', 'leaf', 'cat >$TARGET $SOURCE') print FindFile('leaf', '.') print FindFile('derived', '.') - </programlisting> - - <screen> - % <userinput>scons -Q</userinput> - None - derived - scons: *** [derived] Source `leaf' not found, needed by target `derived'. - </screen> + </file> + </scons_example> - <programlisting> - # Neither file exists, so build will fail - Command('derived', 'leaf', 'cat >$TARGET $SOURCE') - print FindFile('leaf', '.') - print FindFile('derived', '.') + <scons_output example="FindFile2" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + <scons_example name="FindFile2"> + <file name="SConstruct" printme="1"> # Only 'leaf' exists - Command('derived', 'leaf', 'cat >$TARGET $SOURCE') + Command('derived', 'leaf', 'cat >$TARGET $SOURCE') print FindFile('leaf', '.') print FindFile('derived', '.') - </programlisting> - - <screen> - % <userinput>scons -Q</userinput> + </file> + <file name="leaf"> leaf - derived - cat > derived leaf - </screen> + </file> + </scons_example> + + <scons_output example="FindFile2" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -379,17 +398,21 @@ </para> - <programlisting> + <scons_example name="FindFile3"> + <file name="SConstruct" printme="1"> # Only 'src/leaf' exists VariantDir('build', 'src') print FindFile('leaf', 'build') - </programlisting> + </file> + <directory name="src"></directory> + <file name="src/leaf"> + leaf + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - build/leaf - scons: `.' is up to date. - </screen> + <scons_output example="FindFile3" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -414,13 +437,21 @@ </para> - <programlisting> + <scons_example name="Flatten1"> + <file name="SConstruct" printme="1"> objects = [ Object('prog1.c'), Object('prog2.c', CCFLAGS='-DFOO'), ] Program(objects) - </programlisting> + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> <para> @@ -430,12 +461,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o prog1.o -c prog1.c - cc -o prog2.o -c -DFOO prog2.c - cc -o prog1 prog1.o prog2.o - </screen> + <scons_output example="Flatten1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -450,7 +478,8 @@ </para> - <programlisting> + <scons_example name="Flatten2"> + <file name="SConstruct" printme="1"> objects = [ Object('prog1.c'), Object('prog2.c', CCFLAGS='-DFOO'), @@ -459,7 +488,14 @@ for object_file in objects: print object_file.abspath - </programlisting> + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> <para> @@ -471,12 +507,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - AttributeError: 'NodeList' object has no attribute 'abspath': - File "/home/my/project/SConstruct", line 8: - print object_file.abspath - </screen> + <scons_output example="Flatten2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -486,7 +519,8 @@ </para> - <programlisting> + <scons_example name="Flatten3"> + <file name="SConstruct" printme="1"> objects = [ Object('prog1.c'), Object('prog2.c', CCFLAGS='-DFOO'), @@ -495,7 +529,14 @@ for object_file in Flatten(objects): print object_file.abspath - </programlisting> + </file> + <file name="prog1.c"> + prog1.c + </file> + <file name="prog2.c"> + prog2.c + </file> + </scons_example> <!-- @@ -529,14 +570,14 @@ </para> - <programlisting> + <sconstruct> env = Environment( LAUNCHDIR = GetLaunchDir(), ) env.Command('directory_build_info', '$LAUNCHDIR/build_info' Copy('$TARGET', '$SOURCE')) - </programlisting> + </sconstruct> <para> diff --git a/doc/user/nodes.in b/doc/user/nodes.in deleted file mode 100644 index fb5ce23..0000000 --- a/doc/user/nodes.in +++ /dev/null @@ -1,431 +0,0 @@ -<!-- - - __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> - - Internally, &SCons; represents all of the files - and directories it knows about as &Nodes;. - These internal objects - (not object <emphasis>files</emphasis>) - can be used in a variety of ways - to make your &SConscript; - files portable and easy to read. - - </para> - - <section> - <title>Builder Methods Return Lists of Target Nodes</title> - - <para> - - All builder methods return a list of - &Node; objects that identify the - target file or files that will be built. - These returned &Nodes; can be passed - as arguments to other builder methods. - - </para> - - <para> - - For example, suppose that we want to build - the two object files that make up a program with different options. - This would mean calling the &b-link-Object; - builder once for each object file, - specifying the desired options: - - </para> - - <sconstruct> - Object('hello.c', CCFLAGS='-DHELLO') - Object('goodbye.c', CCFLAGS='-DGOODBYE') - </sconstruct> - - <para> - - One way to combine these object files - into the resulting program - would be to call the &b-link-Program; - builder with the names of the object files - listed as sources: - - </para> - - <sconstruct> - Object('hello.c', CCFLAGS='-DHELLO') - Object('goodbye.c', CCFLAGS='-DGOODBYE') - Program(['hello.o', 'goodbye.o']) - </sconstruct> - - <para> - - The problem with specifying the names as strings - is that our &SConstruct; file is no longer portable - across operating systems. - It won't, for example, work on Windows - because the object files there would be - named &hello_obj; and &goodbye_obj;, - not &hello_o; and &goodbye_o;. - - </para> - - <para> - - A better solution is to assign the lists of targets - returned by the calls to the &b-Object; builder to variables, - which we can then concatenate in our - call to the &b-Program; builder: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - hello_list = Object('hello.c', CCFLAGS='-DHELLO') - goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE') - Program(hello_list + goodbye_list) - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="goodbye.c"> - int main() { printf("Goodbye, world!\n"); } - </file> - </scons_example> - - <para> - - This makes our &SConstruct; file portable again, - the build output on Linux looking like: - - </para> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - And on Windows: - - </para> - - <scons_output example="ex1" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - We'll see examples of using the list of nodes - returned by builder methods throughout - the rest of this guide. - - </para> - - </section> - - <section> - <title>Explicitly Creating File and Directory Nodes</title> - - <para> - - It's worth mentioning here that - &SCons; maintains a clear distinction - between Nodes that represent files - and Nodes that represent directories. - &SCons; supports &File; and &Dir; - functions that, respectively, - return a file or directory Node: - - </para> - - <scons_example name="print"> - <file name="SConstruct" printme="1"> - hello_c = File('hello.c') - Program(hello_c) - - classes = Dir('classes') - Java(classes, 'src') - </file> - </scons_example> - - <para> - - Normally, you don't need to call - &File; or &Dir; directly, - because calling a builder method automatically - treats strings as the names of files or directories, - and translates them into - the Node objects for you. - The &File; and &Dir; functions can come in handy - in situations where you need to explicitly - instruct &SCons; about the type of Node being - passed to a builder or other function, - or unambiguously refer to a specific - file in a directory tree. - <!-- - (For an example of when you might - need to use &File; or &Dir; to - prevent ambiguous interpretation of a string - naming a file or directory, see - <xref linkend="chap-hierarchy">.) - --> - - </para> - - <para> - - There are also times when you may need to - refer to an entry in a file system - without knowing in advance - whether it's a file or a directory. - For those situations, - &SCons; also supports an &Entry; function, - which returns a Node - that can represent either a file or a directory. - - </para> - - <sconstruct> - xyzzy = Entry('xyzzy') - </sconstruct> - - <para> - - The returned <literal>xyzzy</literal> Node - will be turned into a file or directory Node - the first time it is used by a builder method - or other function that - requires one vs. the other. - - </para> - - </section> - - <section> - <title>Printing &Node; File Names</title> - - <para> - - One of the most common things you can do - with a Node is use it to print the - file name that the node represents. - Keep in mind, though, that because the object - returned by a builder call - is a <emphasis>list</emphasis> of Nodes, - you must use Python subscripts - to fetch individual Nodes from the list. - For example, the following &SConstruct; file: - - </para> - - <scons_example name="print"> - <file name="SConstruct" printme="1"> - object_list = Object('hello.c') - program_list = Program(object_list) - print "The object file is:", object_list[0] - print "The program file is:", program_list[0] - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Would print the following file names on a POSIX system: - - </para> - - <scons_output example="print" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - And the following file names on a Windows system: - - </para> - - <scons_output example="print" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note that in the above example, - the <literal>object_list[0]</literal> - extracts an actual Node <emphasis>object</emphasis> - from the list, - and the Python <literal>print</literal> statement - converts the object to a string for printing. - - </para> - - </section> - - <section> - <title>Using a &Node;'s File Name as a String</title> - - <para> - - Printing a &Node;'s name - as described in the previous section - works because the string representation of a &Node; object - is the name of the file. - If you want to do something other than - print the name of the file, - you can fetch it by using the builtin Python - &str; function. - For example, if you want to use the Python - <function>os.path.exists</function> - to figure out whether a file - exists while the &SConstruct; file - is being read and executed, - you can fetch the string as follows: - - </para> - - <scons_example name="exists"> - <file name="SConstruct" printme="1"> - import os.path - program_list = Program('hello.c') - program_name = str(program_list[0]) - if not os.path.exists(program_name): - print program_name, "does not exist!" - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Which executes as follows on a POSIX system: - - </para> - - <scons_output example="exists" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>&GetBuildPath;: Getting the Path From a &Node; or String</title> - - <para> - - <function>env.GetBuildPath(file_or_list)</function> - returns the path of a &Node; or a string representing a - path. It can also take a list of &Node;s and/or strings, and - returns the list of paths. If passed a single &Node;, the result - is the same as calling <literal>str(node)</literal> (see above). - The string(s) can have embedded construction variables, which are - expanded as usual, using the calling environment's set of - variables. The paths can be files or directories, and do not have - to exist. - - </para> - - <scons_example name="GetBuildPath"> - <file name="SConstruct" printme="1"> - env=Environment(VAR="value") - n=File("foo.c") - print env.GetBuildPath([n, "sub/dir/$VAR"]) - </file> - </scons_example> - - <para> - - Would print the following file names: - - </para> - - <scons_output example="GetBuildPath" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - There is also a function version of &GetBuildPath; which can - be called without an &Environment;; that uses the default SCons - &Environment; to do substitution on any string arguments. - - </para> - - </section> - - <!-- - - <section> - <title>Fetching the Contents of a &Node;</title> - - <para> - - XXX Describe using read() and readlines() - when we add that as a public interface. - - </para> - - <scons_example name="read"> - <file name="SConstruct" printme="1"> - hello_c = File('hello.c') - contents = hello_c.read() - print "contents are:" - print contents - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Which executes as follows on a POSIX system: - - </para> - - <scons_output example="read" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - --> - - <!-- - - <section> - <title>Python Value &Node;</title> - - <para> - - XXX Value() - - </para> - - </section> - - --> diff --git a/doc/user/nodes.xml b/doc/user/nodes.xml index 42d44c6..fb5ce23 100644 --- a/doc/user/nodes.xml +++ b/doc/user/nodes.xml @@ -58,10 +58,10 @@ </para> - <programlisting> + <sconstruct> Object('hello.c', CCFLAGS='-DHELLO') Object('goodbye.c', CCFLAGS='-DGOODBYE') - </programlisting> + </sconstruct> <para> @@ -73,11 +73,11 @@ </para> - <programlisting> + <sconstruct> Object('hello.c', CCFLAGS='-DHELLO') Object('goodbye.c', CCFLAGS='-DGOODBYE') Program(['hello.o', 'goodbye.o']) - </programlisting> + </sconstruct> <para> @@ -100,11 +100,19 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> hello_list = Object('hello.c', CCFLAGS='-DHELLO') goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE') Program(hello_list + goodbye_list) - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> <para> @@ -113,12 +121,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o goodbye.o -c -DGOODBYE goodbye.c - cc -o hello.o -c -DHELLO hello.c - cc -o hello hello.o goodbye.o - </screen> + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -126,13 +131,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - cl /Fogoodbye.obj /c goodbye.c -DGOODBYE - cl /Fohello.obj /c hello.c -DHELLO - link /nologo /OUT:hello.exe hello.obj goodbye.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="ex1" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -159,13 +160,15 @@ </para> - <programlisting> + <scons_example name="print"> + <file name="SConstruct" printme="1"> hello_c = File('hello.c') Program(hello_c) classes = Dir('classes') Java(classes, 'src') - </programlisting> + </file> + </scons_example> <para> @@ -204,9 +207,9 @@ </para> - <programlisting> + <sconstruct> xyzzy = Entry('xyzzy') - </programlisting> + </sconstruct> <para> @@ -237,18 +240,17 @@ </para> - <programlisting> - hello_c = File('hello.c') - Program(hello_c) - - classes = Dir('classes') - Java(classes, 'src') - + <scons_example name="print"> + <file name="SConstruct" printme="1"> object_list = Object('hello.c') program_list = Program(object_list) print "The object file is:", object_list[0] print "The program file is:", program_list[0] - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -256,13 +258,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - The object file is: hello.o - The program file is: hello - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="print" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -270,14 +268,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - The object file is: hello.obj - The program file is: hello.exe - cl /Fohello.obj /c hello.c /nologo - link /nologo /OUT:hello.exe hello.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="print" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -314,13 +307,18 @@ </para> - <programlisting> + <scons_example name="exists"> + <file name="SConstruct" printme="1"> import os.path program_list = Program('hello.c') program_name = str(program_list[0]) if not os.path.exists(program_name): print program_name, "does not exist!" - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -328,12 +326,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - hello does not exist! - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="exists" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -354,11 +349,13 @@ </para> - <programlisting> + <scons_example name="GetBuildPath"> + <file name="SConstruct" printme="1"> env=Environment(VAR="value") n=File("foo.c") print env.GetBuildPath([n, "sub/dir/$VAR"]) - </programlisting> + </file> + </scons_example> <para> @@ -366,11 +363,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - ['foo.c', 'sub/dir/value'] - scons: `.' is up to date. - </screen> + <scons_output example="GetBuildPath" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> diff --git a/doc/user/output.in b/doc/user/output.in deleted file mode 100644 index 1383fc0..0000000 --- a/doc/user/output.in +++ /dev/null @@ -1,681 +0,0 @@ -<!-- - - __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> - - A key aspect of creating a usable build configuration - is providing good output from the build - so its users can readily understand - what the build is doing - and get information about how to control the build. - &SCons; provides several ways of - controlling output from the build configuration - to help make the build - more useful and understandable. - - </para> - - <section> - <title>Providing Build Help: the &Help; Function</title> - - <para> - - It's often very useful to be able to give - users some help that describes the - specific targets, build options, etc., - that can be used for your build. - &SCons; provides the &Help; function - to allow you to specify this help text: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - Help(""" - Type: 'scons program' to build the production program, - 'scons debug' to build the debug version. - """) - </file> - </scons_example> - - <para> - - (Note the above use of the Python triple-quote syntax, - which comes in very handy for - specifying multi-line strings like help text.) - - </para> - - <para> - - When the &SConstruct; or &SConscript; files - contain such a call to the &Help; function, - the specified help text will be displayed in response to - the &SCons; <literal>-h</literal> option: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -h</scons_output_command> - </scons_output> - - <para> - - The &SConscript; files may contain - multiple calls to the &Help; function, - in which case the specified text(s) - will be concatenated when displayed. - This allows you to split up the - help text across multiple &SConscript; files. - In this situation, the order in - which the &SConscript; files are called - will determine the order in which the &Help; functions are called, - which will determine the order in which - the various bits of text will get concatenated. - - </para> - - <para> - - Another use would be to make the help text conditional - on some variable. - For example, suppose you only want to display - a line about building a Windows-only - version of a program when actually - run on Windows. - The following &SConstruct; file: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct" printme="1"> - env = Environment() - - Help("\nType: 'scons program' to build the production program.\n") - - if env['PLATFORM'] == 'win32': - Help("\nType: 'scons windebug' to build the Windows debug version.\n") - </file> - </scons_example> - - <para> - - Will display the complete help text on Windows: - - </para> - - <scons_output example="ex2" os="win32"> - <scons_output_command>scons -h</scons_output_command> - </scons_output> - - <para> - - But only show the relevant option on a Linux or UNIX system: - - </para> - - <scons_output example="ex2" os="posix"> - <scons_output_command>scons -h</scons_output_command> - </scons_output> - - <para> - - If there is no &Help; text in the &SConstruct; or - &SConscript; files, - &SCons; will revert to displaying its - standard list that describes the &SCons; command-line - options. - This list is also always displayed whenever - the <literal>-H</literal> option is used. - - </para> - - </section> - - <section> - <title>Controlling How &SCons; Prints Build Commands: the <envar>$*COMSTR</envar> Variables</title> - - <para> - - Sometimes the commands executed - to compile object files or link programs - (or build other targets) - can get very long, - long enough to make it difficult for users - to distinguish error messages or - other important build output - from the commands themselves. - All of the default <envar>$*COM</envar> variables - that specify the command lines - used to build various types of target files - have a corresponding <envar>$*COMSTR</envar> variable - that can be set to an alternative - string that will be displayed - when the target is built. - - </para> - - <para> - - For example, suppose you want to - have &SCons; display a - <literal>"Compiling"</literal> - message whenever it's compiling an object file, - and a - <literal>"Linking"</literal> - when it's linking an executable. - You could write a &SConstruct; file - that looks like: - - </para> - - <scons_example name="COMSTR"> - <file name="SConstruct" printme="1"> - env = Environment(CCCOMSTR = "Compiling $TARGET", - LINKCOMSTR = "Linking $TARGET") - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - <para> - - Which would then yield the output: - - </para> - - <!-- - - <scons_output example="COMSTR" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - --> - - <screen> - % <userinput>scons -Q</userinput> - Compiling foo.o - Linking foo - </screen> - - <para> - - &SCons; performs complete variable substitution - on <envar>$*COMSTR</envar> variables, - so they have access to all of the - standard variables like &cv-TARGET; &cv-SOURCES;, etc., - as well as any construction variables - that happen to be configured in - the construction environment - used to build a specific target. - - </para> - - <para> - - Of course, sometimes it's still important to - be able to see the exact command - that &SCons; will execute to build a target. - For example, you may simply need to verify - that &SCons; is configured to supply - the right options to the compiler, - or a developer may want to - cut-and-paste a compile command - to add a few options - for a custom test. - - </para> - - <para> - - One common way to give users - control over whether or not - &SCons; should print the actual command line - or a short, configured summary - is to add support for a - <varname>VERBOSE</varname> - command-line variable to your &SConstruct; file. - A simple configuration for this might look like: - - </para> - - <scons_example name="COMSTR-VERBOSE"> - <file name="SConstruct" printme="1"> - env = Environment() - if ARGUMENTS.get('VERBOSE') != "1': - env['CCCOMSTR'] = "Compiling $TARGET" - env['LINKCOMSTR'] = "Linking $TARGET" - env.Program('foo.c') - </file> - <file name="foo.c"> - foo.c - </file> - </scons_example> - - <para> - - - By only setting the appropriate - <envar>$*COMSTR</envar> variables - if the user specifies - <literal>VERBOSE=1</literal> - on the command line, - the user has control - over how &SCons; - displays these particular command lines: - - </para> - - <!-- - - <scons_output example="COMSTR-VERBOSE" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q -c</scons_output_command> - <scons_output_command>scons -Q VERBOSE=1</scons_output_command> - </scons_output> - - --> - - <screen> - % <userinput>scons -Q</userinput> - Compiling foo.o - Linking foo - % <userinput>scons -Q -c</userinput> - Removed foo.o - Removed foo - % <userinput>scons -Q VERBOSE=1</userinput> - cc -o foo.o -c foo.c - cc -o foo foo.o - </screen> - - </section> - - <section> - <title>Providing Build Progress Output: the &Progress; Function</title> - - <para> - - Another aspect of providing good build output - is to give the user feedback - about what &SCons; is doing - even when nothing is being built at the moment. - This can be especially true for large builds - when most of the targets are already up-to-date. - Because &SCons; can take a long time - making absolutely sure that every - target is, in fact, up-to-date - with respect to a lot of dependency files, - it can be easy for users to mistakenly - conclude that &SCons; is hung - or that there is some other problem with the build. - - </para> - - <para> - - One way to deal with this perception - is to configure &SCons; to print something to - let the user know what it's "thinking about." - The &Progress; function - allows you to specify a string - that will be printed for every file - that &SCons; is "considering" - while it is traversing the dependency graph - to decide what targets are or are not up-to-date. - - </para> - - <scons_example name="Progress-TARGET"> - <file name="SConstruct" printme="1"> - Progress('Evaluating $TARGET\n') - Program('f1.c') - Program('f2.c') - </file> - <file name="f1.c"> - f1.c - </file> - <file name="f2.c"> - f2.c - </file> - </scons_example> - - <para> - - Note that the &Progress; function does not - arrange for a newline to be printed automatically - at the end of the string (as does the Python - <literal>print</literal> statement), - and we must specify the - <literal>\n</literal> - that we want printed at the end of the configured string. - This configuration, then, - will have &SCons; - print that it is <literal>Evaluating</literal> - each file that it encounters - in turn as it traverses the dependency graph: - - </para> - - <scons_output example="Progress-TARGET" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Of course, normally you don't want to add - all of these additional lines to your build output, - as that can make it difficult for the user - to find errors or other important messages. - A more useful way to display - this progress might be - to have the file names printed - directly to the user's screen, - not to the same standard output - stream where build output is printed, - and to use a carriage return character - (<literal>\r</literal>) - so that each file name gets re-printed on the same line. - Such a configuration would look like: - - </para> - - <sconstruct> - Progress('$TARGET\r', - file=open('/dev/tty', 'w'), - overwrite=True) - Program('f1.c') - Program('f2.c') - </sconstruct> - - <para> - - Note that we also specified the - <literal>overwrite=True</literal> argument - to the &Progress; function, - which causes &SCons; to - "wipe out" the previous string with space characters - before printing the next &Progress; string. - Without the - <literal>overwrite=True</literal> argument, - a shorter file name would not overwrite - all of the charactes in a longer file name that - precedes it, - making it difficult to tell what the - actual file name is on the output. - Also note that we opened up the - <filename>/dev/tty</filename> file - for direct access (on POSIX) to - the user's screen. - On Windows, the equivalent would be to open - the <filename>con:</filename> file name. - - </para> - - <para> - - Also, it's important to know that although you can use - <literal>$TARGET</literal> to substitute the name of - the node in the string, - the &Progress; function does <emphasis>not</emphasis> - perform general variable substitution - (because there's not necessarily a construction - environment involved in evaluating a node - like a source file, for example). - - </para> - - <para> - - You can also specify a list of strings - to the &Progress; function, - in which case &SCons; will - display each string in turn. - This can be used to implement a "spinner" - by having &SCons; cycle through a - sequence of strings: - - </para> - - <sconstruct> - Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5) - Program('f1.c') - Program('f2.c') - </sconstruct> - - <para> - - Note that here we have also used the - <literal>interval=</literal> - keyword argument to have &SCons; - only print a new "spinner" string - once every five evaluated nodes. - Using an <literal>interval=</literal> count, - even with strings that use <literal>$TARGET</literal> like - our examples above, - can be a good way to lessen the - work that &SCons; expends printing &Progress; strings, - while still giving the user feedback - that indicates &SCons; is still - working on evaluating the build. - - </para> - - <para> - - Lastly, you can have direct control - over how to print each evaluated node - by passing a Python function - (or other Python callable) - to the &Progress; function. - Your function will be called - for each evaluated node, - allowing you to - implement more sophisticated logic - like adding a counter: - - </para> - - <scons_example name="Progress-callable"> - <file name="SConstruct" printme="1"> - screen = open('/dev/tty', 'w') - count = 0 - def progress_function(node) - count += 1 - screen.write('Node %4d: %s\r' % (count, node)) - - Progress(progress_function) - </file> - </scons_example> - - <para> - - Of course, if you choose, - you could completely ignore the - <varname>node</varname> argument to the function, - and just print a count, - or anything else you wish. - - </para> - - <para> - - (Note that there's an obvious follow-on question here: - how would you find the total number of nodes - that <emphasis>will be</emphasis> - evaluated so you can tell the user how - close the build is to finishing? - Unfortunately, in the general case, - there isn't a good way to do that, - short of having &SCons; evaluate its - dependency graph twice, - first to count the total and - the second time to actually build the targets. - This would be necessary because - you can't know in advance which - target(s) the user actually requested - to be built. - The entire build may consist of thousands of Nodes, - for example, - but maybe the user specifically requested - that only a single object file be built.) - - </para> - - </section> - - <section> - <title>Printing Detailed Build Status: the &GetBuildFailures; Function</title> - - <para> - - SCons, like most build tools, returns zero status to - the shell on success and nonzero status on failure. - Sometimes it's useful to give more information about - the build status at the end of the run, for instance - to print an informative message, send an email, or - page the poor slob who broke the build. - - </para> - - <para> - - SCons provides a &GetBuildFailures; method that - you can use in a python <function>atexit</function> function - to get a list of objects describing the actions that failed - while attempting to build targets. There can be more - than one if you're using <literal>-j</literal>. Here's a - simple example: - - </para> - - <scons_example name="gbf1"> - <file name="SConstruct" printme="1"> - import atexit - - def print_build_failures(): - from SCons.Script import GetBuildFailures - for bf in GetBuildFailures(): - print "%s failed: %s" % (bf.node, bf.errstr) - atexit.register(print_build_failures) - </file> - </scons_example> - - <para> - - The <function>atexit.register</function> call - registers <function>print_build_failures</function> - as an <function>atexit</function> callback, to be called - before &SCons; exits. When that function is called, - it calls &GetBuildFailures; to fetch the list of failed objects. - See the man page - for the detailed contents of the returned objects; - some of the more useful attributes are - <literal>.node</literal>, - <literal>.errstr</literal>, - <literal>.filename</literal>, and - <literal>.command</literal>. - The <literal>filename</literal> is not necessarily - the same file as the <literal>node</literal>; the - <literal>node</literal> is the target that was - being built when the error occurred, while the - <literal>filename</literal>is the file or dir that - actually caused the error. - Note: only call &GetBuildFailures; at the end of the - build; calling it at any other time is undefined. - - </para> - - <para> - - Here is a more complete example showing how to - turn each element of &GetBuildFailures; into a string: - - </para> - - <scons_example name="gbf2"> - <file name="SConstruct" printme="1"> - # Make the build fail if we pass fail=1 on the command line - if ARGUMENTS.get('fail', 0): - Command('target', 'source', ['/bin/false']) - - def bf_to_str(bf): - """Convert an element of GetBuildFailures() to a string - in a useful way.""" - import SCons.Errors - if bf is None: # unknown targets product None in list - return '(unknown tgt)' - elif isinstance(bf, SCons.Errors.StopError): - return str(bf) - elif bf.node: - return str(bf.node) + ': ' + bf.errstr - elif bf.filename: - return bf.filename + ': ' + bf.errstr - return 'unknown failure: ' + bf.errstr - import atexit - - def build_status(): - """Convert the build status to a 2-tuple, (status, msg).""" - from SCons.Script import GetBuildFailures - bf = GetBuildFailures() - if bf: - # bf is normally a list of build failures; if an element is None, - # it's because of a target that scons doesn't know anything about. - status = 'failed' - failures_message = "\n".join(["Failed building %s" % bf_to_str(x) - for x in bf if x is not None]) - else: - # if bf is None, the build completed successfully. - status = 'ok' - failures_message = '' - return (status, failures_message) - - def display_build_status(): - """Display the build status. Called by atexit. - Here you could do all kinds of complicated things.""" - status, failures_message = build_status() - if status == 'failed': - print "FAILED!!!!" # could display alert, ring bell, etc. - elif status == 'ok': - print "Build succeeded." - print failures_message - - atexit.register(display_build_status) - </file> - </scons_example> - - <para> - - When this runs, you'll see the appropriate output: - - </para> - - <scons_output example="gbf2"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q fail=1</scons_output_command> - </scons_output> - - </section> diff --git a/doc/user/output.xml b/doc/user/output.xml index ff39fca..1383fc0 100644 --- a/doc/user/output.xml +++ b/doc/user/output.xml @@ -51,12 +51,14 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> Help(""" Type: 'scons program' to build the production program, 'scons debug' to build the debug version. """) - </programlisting> + </file> + </scons_example> <para> @@ -75,16 +77,9 @@ </para> - <screen> - % <userinput>scons -h</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - - Type: 'scons program' to build the production program, - 'scons debug' to build the debug version. - - Use scons -H for help about command-line options. - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -h</scons_output_command> + </scons_output> <para> @@ -114,14 +109,16 @@ </para> - <programlisting> + <scons_example name="ex2"> + <file name="SConstruct" printme="1"> env = Environment() Help("\nType: 'scons program' to build the production program.\n") if env['PLATFORM'] == 'win32': Help("\nType: 'scons windebug' to build the Windows debug version.\n") - </programlisting> + </file> + </scons_example> <para> @@ -129,17 +126,9 @@ </para> - <screen> - C:\><userinput>scons -h</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - - Type: 'scons program' to build the production program. - - Type: 'scons windebug' to build the Windows debug version. - - Use scons -H for help about command-line options. - </screen> + <scons_output example="ex2" os="win32"> + <scons_output_command>scons -h</scons_output_command> + </scons_output> <para> @@ -147,15 +136,9 @@ </para> - <screen> - % <userinput>scons -h</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - - Type: 'scons program' to build the production program. - - Use scons -H for help about command-line options. - </screen> + <scons_output example="ex2" os="posix"> + <scons_output_command>scons -h</scons_output_command> + </scons_output> <para> @@ -208,11 +191,16 @@ </para> - <programlisting> + <scons_example name="COMSTR"> + <file name="SConstruct" printme="1"> env = Environment(CCCOMSTR = "Compiling $TARGET", LINKCOMSTR = "Linking $TARGET") env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> <para> @@ -275,13 +263,18 @@ </para> - <programlisting> + <scons_example name="COMSTR-VERBOSE"> + <file name="SConstruct" printme="1"> env = Environment() if ARGUMENTS.get('VERBOSE') != "1': env['CCCOMSTR'] = "Compiling $TARGET" env['LINKCOMSTR'] = "Linking $TARGET" env.Program('foo.c') - </programlisting> + </file> + <file name="foo.c"> + foo.c + </file> + </scons_example> <para> @@ -356,11 +349,19 @@ </para> - <programlisting> + <scons_example name="Progress-TARGET"> + <file name="SConstruct" printme="1"> Progress('Evaluating $TARGET\n') Program('f1.c') Program('f2.c') - </programlisting> + </file> + <file name="f1.c"> + f1.c + </file> + <file name="f2.c"> + f2.c + </file> + </scons_example> <para> @@ -379,21 +380,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - Evaluating SConstruct - Evaluating f1.c - Evaluating f1.o - cc -o f1.o -c f1.c - Evaluating f1 - cc -o f1 f1.o - Evaluating f2.c - Evaluating f2.o - cc -o f2.o -c f2.c - Evaluating f2 - cc -o f2 f2.o - Evaluating . - </screen> + <scons_output example="Progress-TARGET" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -414,13 +403,13 @@ </para> - <programlisting> + <sconstruct> Progress('$TARGET\r', file=open('/dev/tty', 'w'), overwrite=True) Program('f1.c') Program('f2.c') - </programlisting> + </sconstruct> <para> @@ -471,11 +460,11 @@ </para> - <programlisting> + <sconstruct> Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5) Program('f1.c') Program('f2.c') - </programlisting> + </sconstruct> <para> @@ -510,7 +499,8 @@ </para> - <programlisting> + <scons_example name="Progress-callable"> + <file name="SConstruct" printme="1"> screen = open('/dev/tty', 'w') count = 0 def progress_function(node) @@ -518,7 +508,8 @@ screen.write('Node %4d: %s\r' % (count, node)) Progress(progress_function) - </programlisting> + </file> + </scons_example> <para> @@ -581,7 +572,8 @@ </para> - <programlisting> + <scons_example name="gbf1"> + <file name="SConstruct" printme="1"> import atexit def print_build_failures(): @@ -589,7 +581,8 @@ for bf in GetBuildFailures(): print "%s failed: %s" % (bf.node, bf.errstr) atexit.register(print_build_failures) - </programlisting> + </file> + </scons_example> <para> @@ -623,7 +616,8 @@ </para> - <programlisting> + <scons_example name="gbf2"> + <file name="SConstruct" printme="1"> # Make the build fail if we pass fail=1 on the command line if ARGUMENTS.get('fail', 0): Command('target', 'source', ['/bin/false']) @@ -670,7 +664,8 @@ print failures_message atexit.register(display_build_status) - </programlisting> + </file> + </scons_example> <para> @@ -678,14 +673,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - scons: `.' is up to date. - Build succeeded. - % <userinput>scons -Q fail=1</userinput> - scons: *** [target] Source `source' not found, needed by target `target'. - FAILED!!!! - Failed building target: Source `source' not found, needed by target `target'. - </screen> + <scons_output example="gbf2"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q fail=1</scons_output_command> + </scons_output> </section> diff --git a/doc/user/parseconfig.in b/doc/user/parseconfig.in deleted file mode 100644 index 2dbefff..0000000 --- a/doc/user/parseconfig.in +++ /dev/null @@ -1,140 +0,0 @@ -<!-- - - __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> - - Configuring the right options to build programs to work with - libraries--especially shared libraries--that are available - on POSIX systems can be very complicated. - To help this situation, - various utilies with names that end in <filename>config</filename> - return the command-line options for the GNU Compiler Collection (GCC) - that are needed to use these libraries; - for example, the command-line options - to use a library named <filename>lib</filename> - would be found by calling a utility named <filename>lib-config</filename>. - - </para> - - <para> - - A more recent convention is that these options - are available from the generic <filename>pkg-config</filename> program, - which has common framework, error handling, and the like, - so that all the package creator has to do is provide the set of strings - for his particular package. - - </para> - - <para> - - &SCons; construction environments have a &ParseConfig; method - that executes a <filename>*config</filename> utility - (either <filename>pkg-config</filename> or a - more specific utility) - and configures the appropriate construction variables - in the environment - based on the command-line options - returned by the specified command. - - </para> - - <scons_example name="ParseConfig1"> - <file name="SConstruct" printme="1"> - env = Environment() - env['CPPPATH'] = ['/lib/compat'] - env.ParseConfig("pkg-config x11 --cflags --libs") - print env['CPPPATH'] - </file> - </scons_example> - - <para> - - &SCons; will execute the specified command string, - parse the resultant flags, - and add the flags to the appropriate environment variables. - - </para> - - <!-- - This is how we used to generate the screen output below, but - as of (at least) Ubuntu Karmic, the pkg-config output for x11 - no longer reports back an include directory. Since this is just - for example anyway, we're just hard-coding the output. - - <scons_output example="ParseConfig1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - --> - - <screen> - % <userinput>scons -Q</userinput> - ['/lib/compat', '/usr/X11/include'] - scons: `.' is up to date. - </screen> - - <para> - - In the example above, &SCons; has added the include directory to - <varname>CPPPATH</varname>. - (Depending upon what other flags are emitted by the - <filename>pkg-config</filename> command, - other variables may have been extended as well.) - - </para> - - <para> - - Note that the options are merged with existing options using - the &MergeFlags; method, - so that each option only occurs once in the construction variable: - - </para> - - <scons_example name="ParseConfig2"> - <file name="SConstruct" printme="1"> - env = Environment() - env.ParseConfig("pkg-config x11 --cflags --libs") - env.ParseConfig("pkg-config x11 --cflags --libs") - print env['CPPPATH'] - </file> - </scons_example> - - <!-- - This is how we used to generate the screen output below, but - as of (at least) Ubuntu Karmic, the pkg-config output for x11 - no longer reports back an include directory. Since this is just - for example anyway, we're just hard-coding the output. - - <scons_output example="ParseConfig2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - --> - - <screen> - % <userinput>scons -Q</userinput> - ['/usr/X11/include'] - scons: `.' is up to date. - </screen> diff --git a/doc/user/parseconfig.xml b/doc/user/parseconfig.xml index 3613d77..2dbefff 100644 --- a/doc/user/parseconfig.xml +++ b/doc/user/parseconfig.xml @@ -61,12 +61,14 @@ </para> - <programlisting> + <scons_example name="ParseConfig1"> + <file name="SConstruct" printme="1"> env = Environment() env['CPPPATH'] = ['/lib/compat'] env.ParseConfig("pkg-config x11 --cflags --libs") print env['CPPPATH'] - </programlisting> + </file> + </scons_example> <para> @@ -111,12 +113,14 @@ </para> - <programlisting> + <scons_example name="ParseConfig2"> + <file name="SConstruct" printme="1"> env = Environment() env.ParseConfig("pkg-config x11 --cflags --libs") env.ParseConfig("pkg-config x11 --cflags --libs") print env['CPPPATH'] - </programlisting> + </file> + </scons_example> <!-- This is how we used to generate the screen output below, but diff --git a/doc/user/parseflags.in b/doc/user/parseflags.in deleted file mode 100644 index a0ea290..0000000 --- a/doc/user/parseflags.in +++ /dev/null @@ -1,176 +0,0 @@ -<!-- - - __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> - - &SCons; has a bewildering array of construction variables - for different types of options when building programs. - Sometimes you may not know exactly which variable - should be used for a particular option. - - </para> - - <para> - - &SCons; construction environments have a &ParseFlags; method - that takes a set of typical command-line options - and distrbutes them into the appropriate construction variables. - Historically, it was created to support the &ParseConfig; method, - so it focuses on options used by the GNU Compiler Collection (GCC) - for the C and C++ toolchains. - - </para> - - <para> - - &ParseFlags; returns a dictionary containing the options - distributed into their respective construction variables. - Normally, this dictionary would be passed to &MergeFlags; - to merge the options into a &consenv;, - but the dictionary can be edited if desired to provide - additional functionality. - (Note that if the flags are not going to be edited, - calling &MergeFlags; with the options directly - will avoid an additional step.) - - </para> - - <scons_example name="ParseFlags1"> - <file name="SConstruct" printme="1"> - env = Environment() - d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo") - for k,v in sorted(d.items()): - if v: - print k, v - env.MergeFlags(d) - env.Program('f1.c') - </file> - <file name="f1.c"> - int main() { return 0; } - </file> - </scons_example> - - <scons_output example="ParseFlags1" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Note that if the options are limited to generic types - like those above, - they will be correctly translated for other platform types: - - </para> - - <scons_output example="ParseFlags1" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Since the assumption is that the flags are used for the GCC toolchain, - unrecognized flags are placed in &cv-link-CCFLAGS; - so they will be used for both C and C++ compiles: - - </para> - - <scons_example name="ParseFlags2"> - <file name="SConstruct" printme="1"> - env = Environment() - d = env.ParseFlags("-whatever") - for k,v in sorted(d.items()): - if v: - print k, v - env.MergeFlags(d) - env.Program('f1.c') - </file> - <file name="f1.c"> - int main() { return 0; } - </file> - </scons_example> - - <scons_output example="ParseFlags2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - &ParseFlags; will also accept a (recursive) list of strings as input; - the list is flattened before the strings are processed: - - </para> - - <scons_example name="ParseFlags3"> - <file name="SConstruct" printme="1"> - env = Environment() - d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]]) - for k,v in sorted(d.items()): - if v: - print k, v - env.MergeFlags(d) - env.Program('f1.c') - </file> - <file name="f1.c"> - int main() { return 0; } - </file> - </scons_example> - - <scons_output example="ParseFlags3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - If a string begins with a "!" (an exclamation mark, often called a bang), - the string is passed to the shell for execution. - The output of the command is then parsed: - - </para> - - <scons_example name="ParseFlags4"> - <file name="SConstruct" printme="1"> - env = Environment() - d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"]) - for k,v in sorted(d.items()): - if v: - print k, v - env.MergeFlags(d) - env.Program('f1.c') - </file> - <file name="f1.c"> - int main() { return 0; } - </file> - </scons_example> - - <scons_output example="ParseFlags4"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - &ParseFlags; is regularly updated for new options; - consult the man page for details about those currently recognized. - - </para> diff --git a/doc/user/parseflags.xml b/doc/user/parseflags.xml index d3f33c3..a0ea290 100644 --- a/doc/user/parseflags.xml +++ b/doc/user/parseflags.xml @@ -57,7 +57,8 @@ </para> - <programlisting> + <scons_example name="ParseFlags1"> + <file name="SConstruct" printme="1"> env = Environment() d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo") for k,v in sorted(d.items()): @@ -65,16 +66,15 @@ print k, v env.MergeFlags(d) env.Program('f1.c') - </programlisting> + </file> + <file name="f1.c"> + int main() { return 0; } + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - CPPPATH ['/opt/include'] - LIBPATH ['/opt/lib'] - LIBS ['foo'] - cc -o f1.o -c -I/opt/include f1.c - cc -o f1 f1.o -L/opt/lib -lfoo - </screen> + <scons_output example="ParseFlags1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -84,15 +84,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - CPPPATH ['/opt/include'] - LIBPATH ['/opt/lib'] - LIBS ['foo'] - cl /Fof1.obj /c f1.c /nologo /I\opt\include - link /nologo /OUT:f1.exe /LIBPATH:\opt\lib foo.lib f1.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="ParseFlags1" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -102,7 +96,8 @@ </para> - <programlisting> + <scons_example name="ParseFlags2"> + <file name="SConstruct" printme="1"> env = Environment() d = env.ParseFlags("-whatever") for k,v in sorted(d.items()): @@ -110,14 +105,15 @@ print k, v env.MergeFlags(d) env.Program('f1.c') - </programlisting> + </file> + <file name="f1.c"> + int main() { return 0; } + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - CCFLAGS -whatever - cc -o f1.o -c -whatever f1.c - cc -o f1 f1.o - </screen> + <scons_output example="ParseFlags2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -126,7 +122,8 @@ </para> - <programlisting> + <scons_example name="ParseFlags3"> + <file name="SConstruct" printme="1"> env = Environment() d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]]) for k,v in sorted(d.items()): @@ -134,16 +131,15 @@ print k, v env.MergeFlags(d) env.Program('f1.c') - </programlisting> + </file> + <file name="f1.c"> + int main() { return 0; } + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - CPPPATH ['/opt/include'] - LIBPATH ['/opt/lib'] - LIBS ['foo'] - cc -o f1.o -c -I/opt/include f1.c - cc -o f1 f1.o -L/opt/lib -lfoo - </screen> + <scons_output example="ParseFlags3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -153,7 +149,8 @@ </para> - <programlisting> + <scons_example name="ParseFlags4"> + <file name="SConstruct" printme="1"> env = Environment() d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"]) for k,v in sorted(d.items()): @@ -161,16 +158,15 @@ print k, v env.MergeFlags(d) env.Program('f1.c') - </programlisting> - - <screen> - % <userinput>scons -Q</userinput> - CPPPATH ['/opt/include'] - LIBPATH ['/opt/lib'] - LIBS ['foo'] - cc -o f1.o -c -I/opt/include f1.c - cc -o f1 f1.o -L/opt/lib -lfoo - </screen> + </file> + <file name="f1.c"> + int main() { return 0; } + </file> + </scons_example> + + <scons_output example="ParseFlags4"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> diff --git a/doc/user/preface.in b/doc/user/preface.in deleted file mode 100644 index 6f3140b..0000000 --- a/doc/user/preface.in +++ /dev/null @@ -1,426 +0,0 @@ -<!-- - - __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> - - Thank you for taking the time to read about &SCons;. - &SCons; is a next-generation - software construction tool, - or make tool--that is, a software utility - for building software (or other files) - and keeping built software up-to-date - whenever the underlying input files change. - - </para> - - <para> - - The most distinctive thing about &SCons; - is that its configuration files are - actually <emphasis>scripts</emphasis>, - written in the &Python; programming language. - This is in contrast to most alternative build tools, - which typically invent a new language to - configure the build. - &SCons; still has a learning curve, of course, - because you have to know what functions to call - to set up your build properly, - but the underlying syntax used should be familiar - to anyone who has ever looked at a Python script. - - </para> - - <para> - - Paradoxically, - using Python as the configuration file format - makes &SCons; - <emphasis>easier</emphasis> - for non-programmers to learn - than the cryptic languages of other build tools, - which are usually invented by programmers for other programmers. - This is in no small part due to the - consistency and readability that are hallmarks of Python. - It just so happens that making a real, live - scripting language the basis for the - configuration files - makes it a snap for more accomplished programmers - to do more complicated things with builds, - as necessary. - - </para> - - <!-- - - <section> - <title>Why &SCons;?</title> - - <para> - - &SCons; is a response to a perennial problem: - building software is harder than it should be. - In a nutshell: the old, reliable model of the - venerable and ubiquitous &Make; program - has had a hard time keeping up with - how complicated building software has become. - The fact that &Make; has kept up as well as it has is impressive, - and a testament to how the simplicity. - But anyone who has wrestled with &Automake; and &Autoconf; - to try to guarantee that a bit of software - will build correctly on multiple platforms - can tell you that it takes a lot of work to get right. - - </para> - - </section> - - --> - - <section> - <title>&SCons; Principles</title> - - <para> - - There are a few overriding principles - we try to live up to in designing and implementing &SCons;: - - </para> - - <variablelist> - - <varlistentry> - <term>Correctness</term> - - <listitem> - <para> - - First and foremost, - by default, &SCons; guarantees a correct build - even if it means sacrificing performance a little. - We strive to guarantee the build is correct - regardless of how the software being built is structured, - how it may have been written, - or how unusual the tools are that build it. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Performance</term> - - <listitem> - <para> - - Given that the build is correct, - we try to make &SCons; build software - as quickly as possible. - In particular, wherever we may have needed to slow - down the default &SCons; behavior to guarantee a correct build, - we also try to make it easy to speed up &SCons; - through optimization options that let you trade off - guaranteed correctness in all end cases for - a speedier build in the usual cases. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Convenience</term> - - <listitem> - <para> - - &SCons; tries to do as much for you out of the box as reasonable, - including detecting the right tools on your system - and using them correctly to build the software. - - </para> - </listitem> - </varlistentry> - - </variablelist> - - <para> - - In a nutshell, we try hard to make &SCons; just - "do the right thing" and build software correctly, - with a minimum of hassles. - - </para> - - </section> - - <!-- - - <section> - <title>History</title> - - <para> - - &SCons; originated with a design - that was submitted to the Software Carpentry - design competition in 2000. - - </para> - - <para> - - &SCons; is the direct descendant - of a Perl utility called &Cons;. - &Cons; in turn based some of its ideas on &Jam;, - a build tool from Perforce Systems. - - </para> - - <para> - - XXX history of SCons - - </para> - - </section> - - --> - - <!-- - - <section> - <title>Conventions</title> - - <para> - - XXX conventions used in this manual - - </para> - - </section> - - --> - - <section> - <title>A Caveat About This Guide's Completeness</title> - - <para> - - One word of warning as you read through this Guide: - Like too much Open Source software out there, - the &SCons; documentation isn't always - kept up-to-date with the available features. - In other words, - there's a lot that &SCons; can do that - isn't yet covered in this User's Guide. - (Come to think of it, - that also describes a lot of proprietary software, doesn't it?) - - </para> - - <para> - - Although this User's Guide isn't as complete as we'd like it to be, - our development process does emphasize - making sure that the &SCons; man page is kept up-to-date - with new features. - So if you're trying to figure out how to do something - that &SCons; supports - but can't find enough (or any) information here, - it would be worth your while to look - at the man page to see if the information is covered there. - And if you do, - maybe you'd even consider contributing - a section to the User's Guide - so the next person looking for - that information won't have to - go through the same thing...? - - </para> - - </section> - - <section> - <title>Acknowledgements</title> - - <para> - - &SCons; would not exist without a lot of help - from a lot of people, - many of whom may not even be aware - that they helped or served as inspiration. - So in no particular order, - and at the risk of leaving out someone: - - </para> - - <para> - - First and foremost, - &SCons; owes a tremendous debt to Bob Sidebotham, - the original author of the classic Perl-based &Cons; tool - which Bob first released to the world back around 1996. - Bob's work on Cons classic provided the underlying architecture - and model of specifying a build configuration - using a real scripting language. - My real-world experience working on Cons - informed many of the design decisions in SCons, - including the improved parallel build support, - making Builder objects easily definable by users, - and separating the build engine from the wrapping interface. - - </para> - - <para> - - Greg Wilson was instrumental in getting - &SCons; started as a real project - when he initiated the Software Carpentry design - competition in February 2000. - Without that nudge, - marrying the advantages of the Cons classic - architecture with the readability of Python - might have just stayed no more than a nice idea. - - </para> - - <para> - - The entire &SCons; team have been - absolutely wonderful to work with, - and &SCons; would be nowhere near as useful a - tool without the energy, enthusiasm - and time people have contributed over the past few years. - The "core team" - of Chad Austin, Anthony Roach, - Bill Deegan, Charles Crain, Steve Leblanc, Greg Noel, - Gary Oberbrunner, Greg Spencer and Christoph Wiedemann - have been great about reviewing my (and other) changes - and catching problems before they get in the code base. - Of particular technical note: - Anthony's outstanding and innovative work on the tasking engine - has given &SCons; a vastly superior parallel build model; - Charles has been the master of the crucial Node infrastructure; - Christoph's work on the Configure infrastructure - has added crucial Autoconf-like functionality; - and Greg has provided excellent support - for Microsoft Visual Studio. - - </para> - - <para> - - Special thanks to David Snopek for contributing - his underlying "Autoscons" code that formed - the basis of Christoph's work with the Configure functionality. - David was extremely generous in making - this code available to &SCons;, - given that he initially released it under the GPL - and &SCons; is released under a less-restrictive MIT-style license. - - </para> - - <!-- - - <para> - - &SCons; has received contributions - from many other people, of course: - Matt Balvin (extending long command-line support on Windows), - Allen Bierbaum (extensions and fixes to Options), - Steve Christensen (help text sorting and function action signature fixes), - Michael Cook (avoiding losing signal bits from executed commands), - Derrick 'dman' Hudson (), - Alex Jacques (work on the Windows scons.bat file), - Stephen Kennedy (performance enhancements), - Lachlan O'Dea (SharedObject() support for masm - and normalized paths for the WhereIs() function), - Damyan Pepper (keeping output like Make), - Jeff Petkau (significant fixes for CacheDir and other areas), - Stefan Reichor (Ghostscript support), - Zed Shaw (Append() and Replace() environment methods), - Terrel Shumway (build and test fixes, as well as the SCons Wiki) - and - sam th (dynamic checks for utilities). - - </para> - - --> - - <para> - - Thanks to Peter Miller - for his splendid change management system, &Aegis;, - which has provided the &SCons; project - with a robust development methodology from day one, - and which showed me how you could - integrate incremental regression tests into - a practical development cycle - (years before eXtreme Programming arrived on the scene). - - </para> - - <para> - - And last, thanks to Guido van Rossum - for his elegant scripting language, - which is the basis not only for the &SCons; implementation, - but for the interface itself. - - </para> - - </section> - - <section> - <title>Contact</title> - - <para> - - The best way to contact people involved with SCons, - including the author, - is through the SCons mailing lists. - - </para> - - <para> - - If you want to ask general questions about how to use &SCons; - send email to &scons-users;. - - </para> - - <para> - - If you want to contact the &SCons; development community directly, - send email to &scons-devel;. - - </para> - - <para> - - If you want to receive announcements about &SCons;, - join the low-volume &scons-announce; mailing list. - - </para> - - </section> diff --git a/doc/user/python.in b/doc/user/python.in deleted file mode 100644 index e2a7cdd..0000000 --- a/doc/user/python.in +++ /dev/null @@ -1,154 +0,0 @@ -<!-- - - __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. - ---> - - <!-- - - <section> - <title>Python Overview</title> - - <para> - - This section will provide a brief overview of - the Python programming language. - Skip this section if you are already familiar with Python - (or you're really intent on diving into &SCons; - and just picking up things as you go). - - </para> - - <para> - - Python has a lot of good - documentation freely available on-line - to help you get started. - The standard tutorial is available at XXX. - - - </para> - - <para> - - Python is very easy to pick up. - - </para> - - <para> - - Python variables must be assigned to before they can be referenced. - - </para> - - <para> - - Assignment is like most programming languages: - - x = 1 + 2 - z = 3 * x - - </para> - - <para> - - Function calls look like most language function calls: - - a = f(g) - - </para> - - <para> - - Define functions like so: - - def func(arg1, arg2): - return arg1 * arg 2 - - The number of parameters - - </para> - - <para> - - Strings can be enclosed in single quotes or double quotes, - backslashes are used to escape characters, - triple-quote syntax lets you include quotes and newlines, - raw strings begin with 'r'. - - </para> - - <para> - - Lists are enclosed in square brackets, - list items are separated by commas. - List references use square brackets and integer index values, - slice notation lets you select, delete or replace a range. - - </para> - - <para> - - Dictionaries (hashes) are enclosed in curly brackets, - : separates keys from values, - , separates items. - Dictionary values are referenced using square brackets. - - </para> - - <para> - - Access class attributes (including methods) using a '.'. - - </para> - - <para> - - if: statements look like - - elif: statements look like - - else: statements look like - - </para> - - <para> - - for: statements look like - - while: statements look like - - break statements look like - - continue statements look like - - </para> - - <para> - - pass - - </para> - - </section> - - --> diff --git a/doc/user/repositories.in b/doc/user/repositories.in deleted file mode 100644 index 33de530..0000000 --- a/doc/user/repositories.in +++ /dev/null @@ -1,641 +0,0 @@ -<!-- - - __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> - - Often, a software project will have - one or more central repositories, - directory trees that contain - source code, or derived files, or both. - You can eliminate additional unnecessary - rebuilds of files by having &SCons; - use files from one or more code repositories - to build files in your local build tree. - - </para> - - <section> - <title>The &Repository; Method</title> - - <!-- - - The repository directories specified may contain source files, derived files - (objects, libraries and executables), or both. If there is no local file - (source or derived) under the directory in which Cons is executed, then the - first copy of a same-named file found under a repository directory will be - used to build any local derived files. - - --> - - <para> - - It's often useful to allow multiple programmers working - on a project to build software from - source files and/or derived files that - are stored in a centrally-accessible repository, - a directory copy of the source code tree. - (Note that this is not the sort of repository - maintained by a source code management system - like BitKeeper, CVS, or Subversion.) - <!-- - For information about using &SCons; - with these systems, see the section, - "Fetching Files From Source Code Management Systems," - below.) - --> - You use the &Repository; method - to tell &SCons; to search one or more - central code repositories (in order) - for any source files and derived files - that are not present in the local build tree: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Program('hello.c') - Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Multiple calls to the &Repository; method - will simply add repositories to the global list - that &SCons; maintains, - with the exception that &SCons; will automatically eliminate - the current directory and any non-existent - directories from the list. - - </para> - - </section> - - <section> - <title>Finding source files in repositories</title> - - <para> - - The above example - specifies that &SCons; - will first search for files under - the <filename>/usr/repository1</filename> tree - and next under the <filename>/usr/repository2</filename> tree. - &SCons; expects that any files it searches - for will be found in the same position - relative to the top-level directory. - In the above example, if the &hello_c; file is not - found in the local build tree, - &SCons; will search first for - a <filename>/usr/repository1/hello.c</filename> file - and then for a <filename>/usr/repository2/hello.c</filename> file - to use in its place. - - </para> - - <para> - - So given the &SConstruct; file above, - if the &hello_c; file exists in the local - build directory, - &SCons; will rebuild the &hello; program - as normal: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - If, however, there is no local &hello_c; file, - but one exists in <filename>/usr/repository1</filename>, - &SCons; will recompile the &hello; program - from the source file it finds in the repository: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct"> - env = Environment() - env.Program('hello.c') - Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') - </file> - <file name="__ROOT__/usr/repository1/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - And similarly, if there is no local &hello_c; file - and no <filename>/usr/repository1/hello.c</filename>, - but one exists in <filename>/usr/repository2</filename>: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct"> - env = Environment() - env.Program('hello.c') - Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') - </file> - <file name="__ROOT__/usr/repository2/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <scons_output example="ex3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - </para> - - </section> - - <section> - <title>Finding <literal>#include</literal> files in repositories</title> - - <para> - - We've already seen that SCons will scan the contents of - a source file for <literal>#include</literal> file names - and realize that targets built from that source file - also depend on the <literal>#include</literal> file(s). - For each directory in the &cv-link-CPPPATH; list, - &SCons; will actually search the corresponding directories - in any repository trees and establish the - correct dependencies on any - <literal>#include</literal> files that it finds - in repository directory. - - </para> - - <para> - - Unless the C compiler also knows about these directories - in the repository trees, though, - it will be unable to find the <literal>#include</literal> files. - If, for example, the &hello_c; file in - our previous example includes the &hello_h; - in its current directory, - and the &hello_h; only exists in the repository: - - </para> - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - hello.c:1: hello.h: No such file or directory - </screen> - - <para> - - In order to inform the C compiler about the repositories, - &SCons; will add appropriate - <literal>-I</literal> flags to the compilation commands - for each directory in the &cv-CPPPATH; list. - So if we add the current directory to the - construction environment &cv-CPPPATH; like so: - - </para> - - <scons_example name="CPPPATH"> - <file name="SConstruct" printme="1"> - env = Environment(CPPPATH = ['.']) - env.Program('hello.c') - Repository('__ROOT__/usr/repository1') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Then re-executing &SCons; yields: - - </para> - - <scons_output example="CPPPATH"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - The order of the <literal>-I</literal> options replicates, - for the C preprocessor, - the same repository-directory search path - that &SCons; uses for its own dependency analysis. - If there are multiple repositories and multiple &cv-CPPPATH; - directories, &SCons; will add the repository directories - to the beginning of each &cv-CPPPATH; directory, - rapidly multiplying the number of <literal>-I</literal> flags. - If, for example, the &cv-CPPPATH; contains three directories - (and shorter repository path names!): - - </para> - - <scons_example name="CPPPATH3"> - <file name="SConstruct" printme="1"> - env = Environment(CPPPATH = ['dir1', 'dir2', 'dir3']) - env.Program('hello.c') - Repository('__ROOT__/r1', '__ROOT__/r2') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Then we'll end up with nine <literal>-I</literal> options - on the command line, - three (for each of the &cv-CPPPATH; directories) - times three (for the local directory plus the two repositories): - - </para> - - <scons_output example="CPPPATH3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - -<!-- - -Cons classic did the following, does SCons? - -In order to shorten the command lines as much as possible, Cons will -remove C<-I> flags for any directories, locally or in the repositories, -which do not actually exist. (Note that the C<-I> flags are not included -in the MD5 signature calculation for the target file, so the target will -not be recompiled if the compilation command changes due to a directory -coming into existence.) - ---> - - <section> - <title>Limitations on <literal>#include</literal> files in repositories</title> - - <para> - - &SCons; relies on the C compiler's - <literal>-I</literal> options to control the order in which - the preprocessor will search the repository directories - for <literal>#include</literal> files. - This causes a problem, however, with how the C preprocessor - handles <literal>#include</literal> lines with - the file name included in double-quotes. - - </para> - - <para> - - As we've seen, - &SCons; will compile the &hello_c; file from - the repository if it doesn't exist in - the local directory. - If, however, the &hello_c; file in the repository contains - a <literal>#include</literal> line with the file name in - double quotes: - - </para> - - <programlisting> - #include "hello.h" - int - main(int argc, char *argv[]) - { - printf(HELLO_MESSAGE); - return (0); - } - </programlisting> - - <para> - - Then the C preprocessor will <emphasis>always</emphasis> - use a &hello_h; file from the repository directory first, - even if there is a &hello_h; file in the local directory, - despite the fact that the command line specifies - <literal>-I</literal> as the first option: - - </para> - - <scons_example name="quote1"> - <file name="SConstruct"> - env = Environment(CPPPATH = ['.']) - env.Program('hello.c') - Repository('__ROOT__/usr/repository1') - </file> - <file name="__ROOT__/usr/repository1/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <scons_output example="quote1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - This behavior of the C preprocessor--always search - for a <literal>#include</literal> file in double-quotes - first in the same directory as the source file, - and only then search the <literal>-I</literal>--can - not, in general, be changed. - In other words, it's a limitation - that must be lived with if you want to use - code repositories in this way. - There are three ways you can possibly - work around this C preprocessor behavior: - - </para> - - <orderedlist> - - <listitem> - <para> - - Some modern versions of C compilers do have an option - to disable or control this behavior. - If so, add that option to &cv-link-CFLAGS; - (or &cv-link-CXXFLAGS; or both) in your construction environment(s). - Make sure the option is used for all construction - environments that use C preprocessing! - - </para> - </listitem> - - <listitem> - <para> - - Change all occurrences of <literal>#include "file.h"</literal> - to <literal>#include &lt;file.h&gt;</literal>. - Use of <literal>#include</literal> with angle brackets - does not have the same behavior--the <literal>-I</literal> - directories are searched first - for <literal>#include</literal> files--which - gives &SCons; direct control over the list of - directories the C preprocessor will search. - - </para> - </listitem> - - <listitem> - <para> - - Require that everyone working with compilation from - repositories check out and work on entire directories of files, - not individual files. - (If you use local wrapper scripts around - your source code control system's command, - you could add logic to enforce this restriction there. - - </para> - </listitem> - - </orderedlist> - - </section> - - </section> - - <section> - <title>Finding the &SConstruct; file in repositories</title> - - <para> - - &SCons; will also search in repositories - for the &SConstruct; file and any specified &SConscript; files. - This poses a problem, though: how can &SCons; search a - repository tree for an &SConstruct; file - if the &SConstruct; file itself contains the information - about the pathname of the repository? - To solve this problem, &SCons; allows you - to specify repository directories - on the command line using the <literal>-Y</literal> option: - - </para> - - <screen> - % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput> - </screen> - - <para> - - When looking for source or derived files, - &SCons; will first search the repositories - specified on the command line, - and then search the repositories - specified in the &SConstruct; or &SConscript; files. - - </para> - - </section> - - <section> - <title>Finding derived files in repositories</title> - - <para> - - If a repository contains not only source files, - but also derived files (such as object files, - libraries, or executables), &SCons; will perform - its normal MD5 signature calculation to - decide if a derived file in a repository is up-to-date, - or the derived file must be rebuilt in the local build directory. - For the &SCons; signature calculation to work correctly, - a repository tree must contain the &sconsign; files - that &SCons; uses to keep track of signature information. - - </para> - - <para> - - Usually, this would be done by a build integrator - who would run &SCons; in the repository - to create all of its derived files and &sconsign; files, - or who would run &SCons; in a separate build directory - and copy the resulting tree to the desired repository: - - </para> - - <scons_example name="ex4"> - <file name="SConstruct"> - env = Environment() - env.Program(['hello.c', 'file1.c', 'file2.c']) - Repository('/usr/repository1', '/usr/repository2') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="file1.c"> - int f1() { printf("file1\n"); } - </file> - <file name="file2.c"> - int f2() { printf("file2.c\n"); } - </file> - </scons_example> - - <scons_output example="ex4"> - <scons_output_command>cd /usr/repository1</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - (Note that this is safe even if the &SConstruct; file - lists <filename>/usr/repository1</filename> as a repository, - because &SCons; will remove the current build directory - from its repository list for that invocation.) - - </para> - - <para> - - Now, with the repository populated, - we only need to create the one local source file - we're interested in working with at the moment, - and use the <literal>-Y</literal> option to - tell &SCons; to fetch any other files it needs - from the repository: - - </para> - - <!-- - <scons_output example="ex4"> - <scons_output_command>cd $HOME/build</scons_output_command> - <scons_output_command>edit hello.c</scons_output_command> - <scons_output_command>scons -Q -Y __ROOT__/usr/repository1</scons_output_command> - </scons_output> - --> - <screen> - % <userinput>cd $HOME/build</userinput> - % <userinput>edit hello.c</userinput> - % <userinput>scons -Q -Y /usr/repository1</userinput> - cc -c -o hello.o hello.c - cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o - </screen> - - <para> - - Notice that &SCons; realizes that it does not need to - rebuild local copies <filename>file1.o</filename> and <filename>file2.o</filename> files, - but instead uses the already-compiled files - from the repository. - - </para> - - </section> - - <section> - <title>Guaranteeing local copies of files</title> - - <para> - - If the repository tree contains the complete results of a build, - and we try to build from the repository - without any files in our local tree, - something moderately surprising happens: - - </para> - - <screen> - % <userinput>mkdir $HOME/build2</userinput> - % <userinput>cd $HOME/build2</userinput> - % <userinput>scons -Q -Y /usr/all/repository hello</userinput> - scons: `hello' is up-to-date. - </screen> - - <para> - - Why does &SCons; say that the &hello; program - is up-to-date when there is no &hello; program - in the local build directory? - Because the repository (not the local directory) - contains the up-to-date &hello; program, - and &SCons; correctly determines that nothing - needs to be done to rebuild that - up-to-date copy of the file. - - </para> - - <para> - - There are, however, many times when you want to ensure that a - local copy of a file always exists. - A packaging or testing script, for example, - may assume that certain generated files exist locally. - To tell &SCons; to make a copy of any up-to-date repository - file in the local build directory, - use the &Local; function: - - </para> - - <scons_example name="ex5"> - <file name="SConstruct" printme="1"> - env = Environment() - hello = env.Program('hello.c') - Local(hello) - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - If we then run the same command, - &SCons; will make a local copy of the program - from the repository copy, - and tell you that it is doing so: - - </para> - - <screen> - % <userinput>scons -Y /usr/all/repository hello</userinput> - Local copy of hello from /usr/all/repository/hello - scons: `hello' is up-to-date. - </screen> - - <para> - - (Notice that, because the act of making the local copy - is not considered a "build" of the &hello; file, - &SCons; still reports that it is up-to-date.) - - </para> - - </section> diff --git a/doc/user/repositories.xml b/doc/user/repositories.xml index 2600381..33de530 100644 --- a/doc/user/repositories.xml +++ b/doc/user/repositories.xml @@ -73,11 +73,16 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> env = Environment() env.Program('hello.c') - Repository('/usr/repository1', '/usr/repository2') - </programlisting> + Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -124,11 +129,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -139,13 +142,20 @@ </para> - - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c /usr/repository1/hello.c - cc -o hello hello.o - </screen> + <scons_example name="ex2"> + <file name="SConstruct"> + env = Environment() + env.Program('hello.c') + Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') + </file> + <file name="__ROOT__/usr/repository1/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="ex2"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -155,13 +165,20 @@ </para> - - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c /usr/repository2/hello.c - cc -o hello hello.o - </screen> + <scons_example name="ex3"> + <file name="SConstruct"> + env = Environment() + env.Program('hello.c') + Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') + </file> + <file name="__ROOT__/usr/repository2/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="ex3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -216,11 +233,16 @@ </para> - <programlisting> + <scons_example name="CPPPATH"> + <file name="SConstruct" printme="1"> env = Environment(CPPPATH = ['.']) env.Program('hello.c') - Repository('/usr/repository1') - </programlisting> + Repository('__ROOT__/usr/repository1') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -228,11 +250,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c -I. -I/usr/repository1 hello.c - cc -o hello hello.o - </screen> + <scons_output example="CPPPATH"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -249,11 +269,16 @@ </para> - <programlisting> + <scons_example name="CPPPATH3"> + <file name="SConstruct" printme="1"> env = Environment(CPPPATH = ['dir1', 'dir2', 'dir3']) env.Program('hello.c') - Repository('/r1', '/r2') - </programlisting> + Repository('__ROOT__/r1', '__ROOT__/r2') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -264,11 +289,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c -Idir1 -I/r1/dir1 -I/r2/dir1 -Idir2 -I/r1/dir2 -I/r2/dir2 -Idir3 -I/r1/dir3 -I/r2/dir3 hello.c - cc -o hello hello.o - </screen> + <scons_output example="CPPPATH3"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <!-- @@ -330,13 +353,20 @@ coming into existence.) </para> - - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c -I. -I/usr/repository1 /usr/repository1/hello.c - cc -o hello hello.o - </screen> + <scons_example name="quote1"> + <file name="SConstruct"> + env = Environment(CPPPATH = ['.']) + env.Program('hello.c') + Repository('__ROOT__/usr/repository1') + </file> + <file name="__ROOT__/usr/repository1/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="quote1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -372,7 +402,7 @@ coming into existence.) <para> Change all occurrences of <literal>#include "file.h"</literal> - to <literal>#include <file.h></literal>. + to <literal>#include &lt;file.h&gt;</literal>. Use of <literal>#include</literal> with angle brackets does not have the same behavior--the <literal>-I</literal> directories are searched first @@ -462,16 +492,27 @@ coming into existence.) </para> - + <scons_example name="ex4"> + <file name="SConstruct"> + env = Environment() + env.Program(['hello.c', 'file1.c', 'file2.c']) + Repository('/usr/repository1', '/usr/repository2') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="file1.c"> + int f1() { printf("file1\n"); } + </file> + <file name="file2.c"> + int f2() { printf("file2.c\n"); } + </file> + </scons_example> - <screen> - % <userinput>cd /usr/repository1</userinput> - % <userinput>scons -Q</userinput> - cc -o file1.o -c file1.c - cc -o file2.o -c file2.c - cc -o hello.o -c hello.c - cc -o hello hello.o file1.o file2.o - </screen> + <scons_output example="ex4"> + <scons_output_command>cd /usr/repository1</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -563,11 +604,16 @@ coming into existence.) </para> - <programlisting> + <scons_example name="ex5"> + <file name="SConstruct" printme="1"> env = Environment() hello = env.Program('hello.c') Local(hello) - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> diff --git a/doc/user/run.in b/doc/user/run.in deleted file mode 100644 index 56b8fa2..0000000 --- a/doc/user/run.in +++ /dev/null @@ -1,375 +0,0 @@ -<!-- - - __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. - ---> - -<!-- - -=head1 Invoking Cons - -The C<cons> command is usually invoked from the root of the build tree. A -F<Construct> file must exist in that directory. If the C<-f> argument is -used, then an alternate F<Construct> file may be used (and, possibly, an -alternate root, since C<cons> will cd to F<Construct> file's containing -directory). - -If C<cons> is invoked from a child of the root of the build tree with -the C<-t> argument, it will walk up the directory hierarchy looking for a -F<Construct> file. (An alternate name may still be specified with C<-f>.) -The targets supplied on the command line will be modified to be relative -to the discovered F<Construct> file. For example, from a directory -containing a top-level F<Construct> file, the following invocation: - - % cd libfoo/subdir - % cons -t target - -is exactly equivalent to: - - % cons libfoo/subdir/target - -If there are any C<Default> targets specified in the directory hierarchy's -F<Construct> or F<Conscript> files, only the default targets at or below -the directory from which C<cons -t> was invoked will be built. - -The command is invoked as follows: - - cons <arguments> , <construct-args> - -where I<arguments> can be any of the following, in any order: - -=over 10 - -=item I<target> - -Build the specified target. If I<target> is a directory, then recursively -build everything within that directory. - -=item I<+pattern> - -Limit the F<Conscript> files considered to just those that match I<pattern>, -which is a Perl regular expression. Multiple C<+> arguments are accepted. - -=item I<name>=<val> - -Sets I<name> to value I<val> in the C<ARG> hash passed to the top-level -F<Construct> file. - -=item C<-cc> - -Show command that would have been executed, when retrieving from cache. No -indication that the file has been retrieved is given; this is useful for -generating build logs that can be compared with real build logs. - -=item C<-cd> - -Disable all caching. Do not retrieve from cache nor flush to cache. - -=item C<-cr> - -Build dependencies in random order. This is useful when building multiple -similar trees with caching enabled. - -=item C<-cs> - -Synchronize existing build targets that are found to be up-to-date with -cache. This is useful if caching has been disabled with -cc or just recently -enabled with UseCache. - -=item C<-d> - -Enable dependency debugging. - -=item C<-f> <file> - -Use the specified file instead of F<Construct> (but first change to -containing directory of I<file>). - -=item C<-h> - -Show a help message local to the current build if one such is defined, and -exit. - -=item C<-k> - -Keep going as far as possible after errors. - -=item C<-o> <file> - -Read override file I<file>. - -=item C<-p> - -Show construction products in specified trees. No build is attempted. - -=item C<-pa> - -Show construction products and associated actions. No build is attempted. - -=item C<-pw> - -Show products and where they are defined. No build is attempted. - -=item C<-q> - -Make the build quiet. Multiple C<-q> options may be specified. - -A single C<-q> options suppress messages about Installing and Removing -targets. - -Two C<-q> options suppress build command lines and target up-to-date -messages. - -=item C<-r> - -Remove construction products associated with <targets>. No build is -attempted. - -=item C<-R> <repos> - -Search for files in I<repos>. Multiple B<-R> I<repos> directories are -searched in the order specified. - -=item C<-S> <pkg> - -Use the sig::<pkg> package to calculate. Supported <pkg> values -include "md5" for MD5 signature calculation and "md5::debug" for debug -information about MD5 signature calculation. - -If the specified package ends in <::debug>, signature debug information -will be printed to the file name specified in the C<CONS_SIG_DEBUG> -environment variable, or to standard output if the environment variable -is not set. - -=item C<-t> - -Traverse up the directory hierarchy looking for a F<Construct> file, -if none exists in the current directory. Targets will be modified to -be relative to the F<Construct> file. - -Internally, C<cons> will change its working directory to the directory -which contains the top-level F<Construct> file and report: - - cons: Entering directory `top-level-directory' - -This message indicates to an invoking editor (such as emacs) or build -environment that Cons will now report all file names relative to the -top-level directory. This message can not be suppressed with the C<-q> -option. - -=item C<-v> - -Show C<cons> version and continue processing. - -=item C<-V> - -Show C<cons> version and exit. - -=item C<-wf> <file> - -Write all filenames considered into I<file>. - -=item C<-x> - -Show a help message similar to this one, and exit. - -=back - -And I<construct-args> can be any arguments that you wish to process in the -F<Construct> file. Note that there should be a B<-,-> separating the arguments -to cons and the arguments that you wish to process in the F<Construct> file. - -Processing of I<construct-args> can be done by any standard package like -B<Getopt> or its variants, or any user defined package. B<cons> will pass in -the I<construct-args> as B<@ARGV> and will not attempt to interpret anything -after the B<-,->. - - % cons -R /usr/local/repository -d os=solaris +driver -,- -c test -f DEBUG - -would pass the following to cons - - -R /usr/local/repository -d os=solaris +driver - -and the following, to the top level F<Construct> file as B<@ARGV> - - -c test -f DEBUG - -Note that C<cons -r .> is equivalent to a full recursive C<make clean>, -but requires no support in the F<Construct> file or any F<Conscript> -files. This is most useful if you are compiling files into source -directories (if you separate the F<build> and F<export> directories, -then you can just remove the directories). - -The options C<-p>, C<-pa>, and C<-pw> are extremely useful for use as an aid -in reading scripts or debugging them. If you want to know what script -installs F<export/include/foo.h>, for example, just type: - - % cons -pw export/include/foo.h - -=head1 Selective builds - -Cons provides two methods for reducing the size of given build. The first is -by specifying targets on the command line, and the second is a method for -pruning the build tree. We'll consider target specification first. - - -=head2 Selective targeting - -Like make, Cons allows the specification of ``targets'' on the command -line. Cons targets may be either files or directories. When a directory is -specified, this is simply a short-hand notation for every derivable -product-,-that Cons knows about-,-in the specified directory and below. For -example: - - % cons build/hello/hello.o - -means build F<hello.o> and everything that F<hello.o> might need. This is -from a previous version of the B<Hello, World!> program in which F<hello.o> -depended upon F<export/include/world.h>. If that file is not up-to-date -(because someone modified F<src/world/world.h)>, then it will be rebuilt, -even though it is in a directory remote from F<build/hello>. - -In this example: - - % cons build - -Everything in the F<build> directory is built, if necessary. Again, this may -cause more files to be built. In particular, both F<export/include/world.h> -and F<export/lib/libworld.a> are required by the F<build/hello> directory, -and so they will be built if they are out-of-date. - -If we do, instead: - - % cons export - -then only the files that should be installed in the export directory will be -rebuilt, if necessary, and then installed there. Note that C<cons build> -might build files that C<cons export> doesn't build, and vice-versa. - - -=head1 Build Pruning - -In conjunction with target selection, B<build pruning> can be used to reduce -the scope of the build. In the previous peAcH and baNaNa example, we have -already seen how script-driven build pruning can be used to make only half -of the potential build available for any given invocation of C<cons>. Cons -also provides, as a convenience, a command line convention that allows you -to specify which F<Conscript> files actually get ``built''-,-that is, -incorporated into the build tree. For example: - - % cons build +world - -The C<+> argument introduces a Perl regular expression. This must, of -course, be quoted at the shell level if there are any shell meta-characters -within the expression. The expression is matched against each F<Conscript> -file which has been mentioned in a C<Build> statement, and only those -scripts with matching names are actually incorporated into the build -tree. Multiple such arguments are allowed, in which case a match against any -of them is sufficient to cause a script to be included. - -In the example, above, the F<hello> program will not be built, since Cons -will have no knowledge of the script F<hello/Conscript>. The F<libworld.a> -archive will be built, however, if need be. - -There are a couple of uses for build pruning via the command line. Perhaps -the most useful is the ability to make local changes, and then, with -sufficient knowledge of the consequences of those changes, restrict the size -of the build tree in order to speed up the rebuild time. A second use for -build pruning is to actively prevent the recompilation of certain files that -you know will recompile due to, for example, a modified header file. You may -know that either the changes to the header file are immaterial, or that the -changes may be safely ignored for most of the tree, for testing -purposes.With Cons, the view is that it is pragmatic to admit this type of -behavior, with the understanding that on the next full build everything that -needs to be rebuilt will be. There is no equivalent to a ``make touch'' -command, to mark files as permanently up-to-date. So any risk that is -incurred by build pruning is mitigated. For release quality work, obviously, -we recommend that you do not use build pruning (it's perfectly OK to use -during integration, however, for checking compilation, etc. Just be sure to -do an unconstrained build before committing the integration). - ---> - - <para> - - XXX - - </para> - - <section> - <title>Command-Line Options</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Getting at Command-Line Arguments</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Selective Builds</title> - - <para> - - XXX - - </para> - - </section> - - <!-- - - <section> - <title>Build Pruning</title> - - <para> - - XXX - - </para> - - </section> - - --> - - <section> - <title>Overriding Construction Variables</title> - - <para> - - XXX - - </para> - - </section> diff --git a/doc/user/scanners.in b/doc/user/scanners.in deleted file mode 100644 index 50524e0..0000000 --- a/doc/user/scanners.in +++ /dev/null @@ -1,392 +0,0 @@ -<!-- - - __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. - ---> - -<!-- - -=head1 Using and writing dependency scanners - -QuickScan allows simple target-independent scanners to be set up for -source files. Only one QuickScan scanner may be associated with any given -source file and environment, although the same scanner may (and should) -be used for multiple files of a given type. - -A QuickScan scanner is only ever invoked once for a given source file, -and it is only invoked if the file is used by some target in the tree -(i.e., there is a dependency on the source file). - -QuickScan is invoked as follows: - - QuickScan CONSENV CODEREF, FILENAME [, PATH] - -The subroutine referenced by CODEREF is expected to return a list of -filenames included directly by FILE. These filenames will, in turn, be -scanned. The optional PATH argument supplies a lookup path for finding -FILENAME and/or files returned by the user-supplied subroutine. The PATH -may be a reference to an array of lookup-directory names, or a string of -names separated by the system's separator character (':' on UNIX systems, -';' on Windows NT). - -The subroutine is called once for each line in the file, with $_ set to the -current line. If the subroutine needs to look at additional lines, or, for -that matter, the entire file, then it may read them itself, from the -filehandle SCAN. It may also terminate the loop, if it knows that no further -include information is available, by closing the filehandle. - -Whether or not a lookup path is provided, QuickScan first tries to lookup -the file relative to the current directory (for the top-level file -supplied directly to QuickScan), or from the directory containing the -file which referenced the file. This is not very general, but seems good -enough, especially if you have the luxury of writing your own utilities -and can control the use of the search path in a standard way. - -Here's a real example, taken from a F<Construct> file here: - - sub cons::SMFgen { - my($env, @tables) = @_; - foreach $t (@tables) { - $env->QuickScan(sub { /\b\S*?\.smf\b/g }, "$t.smf", - $env->{SMF_INCLUDE_PATH}); - $env->Command(["$t.smdb.cc","$t.smdb.h","$t.snmp.cc", - "$t.ami.cc", "$t.http.cc"], "$t.smf", - q(smfgen %( %SMF_INCLUDE_OPT %) %<)); - } - } - -The subroutine above finds all names of the form <name>.smf in the -file. It will return the names even if they're found within comments, -but that's OK (the mechanism is forgiving of extra files; they're just -ignored on the assumption that the missing file will be noticed when -the program, in this example, smfgen, is actually invoked). - -[NOTE that the form C<$env-E<gt>QuickScan ...> and C<$env-E<gt>Command -...> should not be necessary, but, for some reason, is required -for this particular invocation. This appears to be a bug in Perl or -a misunderstanding on my part; this invocation style does not always -appear to be necessary.] - -Here is another way to build the same scanner. This one uses an -explicit code reference, and also (unnecessarily, in this case) reads -the whole file itself: - - sub myscan { - my(@includes); - do { - push(@includes, /\b\S*?\.smf\b/g); - } while <SCAN>; - @includes - } - -Note that the order of the loop is reversed, with the loop test at the -end. This is because the first line is already read for you. This scanner -can be attached to a source file by: - - QuickScan $env \&myscan, "$_.smf"; - -This final example, which scans a different type of input file, takes -over the file scanning rather than being called for each input line: - - $env->QuickScan( - sub { my(@includes) = (); - do { - push(@includes, $3) - if /^(#include|import)\s+(\")(.+)(\")/ && $3 - } while <SCAN>; - @includes - }, - "$idlFileName", - "$env->{CPPPATH};$BUILD/ActiveContext/ACSCLientInterfaces" - ); - ---> - - <para> - - &SCons; has built-in scanners that know how to look in - C, Fortran and IDL source files for information about - other files that targets built from those files depend on--for example, - in the case of files that use the C preprocessor, - the <filename>.h</filename> files that are specified - using <literal>#include</literal> lines in the source. - You can use the same mechanisms that &SCons; uses to create - its built-in scanners to write scanners of your own for file types - that &SCons; does not know how to scan "out of the box." - - </para> - - <section> - <title>A Simple Scanner Example</title> - - <para> - - Suppose, for example, that we want to create a simple scanner - for <filename>.foo</filename> files. - A <filename>.foo</filename> file contains some text that - will be processed, - and can include other files on lines that begin - with <literal>include</literal> - followed by a file name: - - </para> - - <programlisting> - include filename.foo - </programlisting> - - <para> - - Scanning a file will be handled by a Python function - that you must supply. - Here is a function that will use the Python - <filename>re</filename> module - to scan for the <literal>include</literal> lines in our example: - - </para> - - <programlisting> - import re - - include_re = re.compile(r'^include\s+(\S+)$', re.M) - - def kfile_scan(node, env, path, arg): - contents = node.get_text_contents() - return env.File(include_re.findall(contents)) - </programlisting> - - <para> - - It is important to note that you - have to return a list of File nodes from the scanner function, simple - strings for the file names won't do. As in the examples we are showing here, - you can use the &File; - function of your current Environment in order to create nodes on the fly from - a sequence of file names with relative paths. - - </para> - - <para> - - The scanner function must - accept the four specified arguments - and return a list of implicit dependencies. - Presumably, these would be dependencies found - from examining the contents of the file, - although the function can perform any - manipulation at all to generate the list of - dependencies. - - </para> - - <variablelist> - - <varlistentry> - <term>node</term> - - <listitem> - <para> - - An &SCons; node object representing the file being scanned. - The path name to the file can be - used by converting the node to a string - using the <literal>str()</literal> function, - or an internal &SCons; <literal>get_text_contents()</literal> - object method can be used to fetch the contents. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>env</term> - - <listitem> - <para> - - The construction environment in effect for this scan. - The scanner function may choose to use construction - variables from this environment to affect its behavior. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>path</term> - - <listitem> - <para> - - A list of directories that form the search path for included files - for this scanner. - This is how &SCons; handles the &cv-link-CPPPATH; and &cv-link-LIBPATH; - variables. - - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term>arg</term> - - <listitem> - <para> - - An optional argument that you can choose to - have passed to this scanner function by - various scanner instances. - - </para> - </listitem> - </varlistentry> - - </variablelist> - - <para> - - A Scanner object is created using the &Scanner; function, - which typically takes an <literal>skeys</literal> argument - to associate the type of file suffix with this scanner. - The Scanner object must then be associated with the - &cv-link-SCANNERS; construction variable of a construction environment, - typically by using the &Append; method: - - </para> - - <programlisting> - kscan = Scanner(function = kfile_scan, - skeys = ['.k']) - env.Append(SCANNERS = kscan) - </programlisting> - - <para> - - When we put it all together, it looks like: - - </para> - - <scons_example name="scan"> - <file name="SConstruct" printme="1"> - import re - - include_re = re.compile(r'^include\s+(\S+)$', re.M) - - def kfile_scan(node, env, path): - contents = node.get_text_contents() - includes = include_re.findall(contents) - return env.File(includes) - - kscan = Scanner(function = kfile_scan, - skeys = ['.k']) - - env = Environment(ENV = {'PATH' : '__ROOT__/usr/local/bin'}) - env.Append(SCANNERS = kscan) - - env.Command('foo', 'foo.k', 'kprocess < $SOURCES > $TARGET') - </file> - <file name="foo.k"> - include other_file - </file> - <file name="other_file"> - other_file - </file> - <directory name="__ROOT__/usr"></directory> - <directory name="__ROOT__/usr/local"></directory> - <directory name="__ROOT__/usr/local/bin"></directory> - <file name="__ROOT_/usr/local/bin/kprocess" chmod="755"> - cat - </file> - </scons_example> - - <!-- - - <para> - - Now if we run &scons; - and then re-run it after changing the contents of - <filename>other_file</filename>, - the <filename>foo</filename> - target file will be automatically rebuilt: - - </para> - - <scons_output example="scan"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command output=" [CHANGE THE CONTENTS OF other_file]">edit other_file</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - --> - - </section> - - <section> - <title>Adding a search path to a scanner: &FindPathDirs;</title> - - <para> - - Many scanners need to search for included files or dependencies - using a path variable; this is how &cv-link-CPPPATH; and - &cv-link-LIBPATH; work. The path to search is passed to your - scanner as the <literal>path</literal> argument. Path variables - may be lists of nodes, semicolon-separated strings, or even - contain SCons variables which need to be expanded. Fortunately, - &SCons; provides the &FindPathDirs; function which itself returns - a function to expand a given path (given as a SCons construction - variable name) to a list of paths at the time the scanner is - called. Deferring evaluation until that point allows, for - instance, the path to contain $TARGET references which differ for - each file scanned. - - </para> - - <para> - - Using &FindPathDirs; is quite easy. Continuing the above example, - using KPATH as the construction variable with the search path - (analogous to &cv-link-CPPPATH;), we just modify the &Scanner; - constructor call to include a path keyword arg: - - </para> - - <scons_example name="findpathdirs"> - <file name="SConstruct" printme="1"> - kscan = Scanner(function = kfile_scan, - skeys = ['.k'], - path=FindPathDirs('KPATH')) - </file> - </scons_example> - - <para> - - FindPathDirs returns a callable object that, when called, will - essentially expand the elements in env['KPATH'] and tell the - scanner to search in those dirs. It will also properly add - related repository and variant dirs to the search list. As a side - note, the returned method stores the path in an efficient way so - lookups are fast even when variable substitutions may be needed. - This is important since many files get scanned in a typical build. - - </para> - </section> diff --git a/doc/user/scanners.xml b/doc/user/scanners.xml index f150d33..50524e0 100644 --- a/doc/user/scanners.xml +++ b/doc/user/scanners.xml @@ -285,7 +285,8 @@ over the file scanning rather than being called for each input line: </para> - <programlisting> + <scons_example name="scan"> + <file name="SConstruct" printme="1"> import re include_re = re.compile(r'^include\s+(\S+)$', re.M) @@ -298,11 +299,24 @@ over the file scanning rather than being called for each input line: kscan = Scanner(function = kfile_scan, skeys = ['.k']) - env = Environment(ENV = {'PATH' : '/usr/local/bin'}) + env = Environment(ENV = {'PATH' : '__ROOT__/usr/local/bin'}) env.Append(SCANNERS = kscan) env.Command('foo', 'foo.k', 'kprocess < $SOURCES > $TARGET') - </programlisting> + </file> + <file name="foo.k"> + include other_file + </file> + <file name="other_file"> + other_file + </file> + <directory name="__ROOT__/usr"></directory> + <directory name="__ROOT__/usr/local"></directory> + <directory name="__ROOT__/usr/local/bin"></directory> + <file name="__ROOT_/usr/local/bin/kprocess" chmod="755"> + cat + </file> + </scons_example> <!-- @@ -356,11 +370,13 @@ over the file scanning rather than being called for each input line: </para> - <programlisting> + <scons_example name="findpathdirs"> + <file name="SConstruct" printme="1"> kscan = Scanner(function = kfile_scan, skeys = ['.k'], path=FindPathDirs('KPATH')) - </programlisting> + </file> + </scons_example> <para> diff --git a/doc/user/sconf.in b/doc/user/sconf.in deleted file mode 100644 index 584a82e..0000000 --- a/doc/user/sconf.in +++ /dev/null @@ -1,486 +0,0 @@ -<!-- - - __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> - - &SCons; has integrated support for multi-platform build configuration - similar to that offered by GNU &Autoconf;, - such as - figuring out what libraries or header files - are available on the local system. - This section describes how to use - this &SCons; feature. - - </para> - - <note> - <para> - This chapter is still under development, - so not everything is explained as well as it should be. - See the &SCons; man page for additional information. - </para> - </note> - - <section> - <title>&Configure_Contexts;</title> - - <para> - - The basic framework for multi-platform build configuration - in &SCons; is to attach a &configure_context; to a - construction environment by calling the &Configure; function, - perform a number of checks for - libraries, functions, header files, etc., - and to then call the configure context's &Finish; method - to finish off the configuration: - - </para> - - <sconstruct> - env = Environment() - conf = Configure(env) - # Checks for libraries, header files, etc. go here! - env = conf.Finish() - </sconstruct> - - <para> - - &SCons; provides a number of basic checks, - as well as a mechanism for adding your own custom checks. - - </para> - - <para> - - Note that &SCons; uses its own dependency - mechanism to determine when a check - needs to be run--that is, - &SCons; does not run the checks - every time it is invoked, - but caches the values returned by previous checks - and uses the cached values unless something has changed. - This saves a tremendous amount - of developer time while working on - cross-platform build issues. - - </para> - - <para> - - The next sections describe - the basic checks that &SCons; supports, - as well as how to add your own custom checks. - - </para> - - </section> - - <section> - <title>Checking for the Existence of Header Files</title> - - <para> - - Testing the existence of a header file - requires knowing what language the header file is. - A configure context has a &CheckCHeader; method - that checks for the existence of a C header file: - - </para> - - <sconstruct> - env = Environment() - conf = Configure(env) - if not conf.CheckCHeader('math.h'): - print 'Math.h must be installed!' - Exit(1) - if conf.CheckCHeader('foo.h'): - conf.env.Append('-DHAS_FOO_H') - env = conf.Finish() - </sconstruct> - - <para> - - Note that you can choose to terminate - the build if a given header file doesn't exist, - or you can modify the construction environment - based on the existence of a header file. - - </para> - - <para> - - If you need to check for the existence - a C++ header file, - use the &CheckCXXHeader; method: - - </para> - - <sconstruct> - env = Environment() - conf = Configure(env) - if not conf.CheckCXXHeader('vector.h'): - print 'vector.h must be installed!' - Exit(1) - env = conf.Finish() - </sconstruct> - - </section> - - <section> - <title>Checking for the Availability of a Function</title> - - <para> - - Check for the availability of a specific function - using the &CheckFunc; method: - - </para> - - <sconstruct> - env = Environment() - conf = Configure(env) - if not conf.CheckFunc('strcpy'): - print 'Did not find strcpy(), using local version' - conf.env.Append(CPPDEFINES = '-Dstrcpy=my_local_strcpy') - env = conf.Finish() - </sconstruct> - - </section> - - <section> - <title>Checking for the Availability of a Library</title> - - <para> - - Check for the availability of a library - using the &CheckLib; method. - You only specify the basename of the library, - you don't need to add a <literal>lib</literal> - prefix or a <literal>.a</literal> or <literal>.lib</literal> suffix: - - </para> - - <sconstruct> - env = Environment() - conf = Configure(env) - if not conf.CheckLib('m'): - print 'Did not find libm.a or m.lib, exiting!' - Exit(1) - env = conf.Finish() - </sconstruct> - - <para> - - Because the ability to use a library successfully - often depends on having access to a header file - that describes the library's interface, - you can check for a library - <emphasis>and</emphasis> a header file - at the same time by using the - &CheckLibWithHeader; method: - - </para> - - <sconstruct> - env = Environment() - conf = Configure(env) - if not conf.CheckLibWithHeader('m', 'math.h', 'c'): - print 'Did not find libm.a or m.lib, exiting!' - Exit(1) - env = conf.Finish() - </sconstruct> - - <para> - - This is essentially shorthand for - separate calls to the &CheckHeader; and &CheckLib; - functions. - - </para> - - </section> - - <section> - <title>Checking for the Availability of a &typedef;</title> - - <para> - - Check for the availability of a &typedef; - by using the &CheckType; method: - - </para> - - <sconstruct> - env = Environment() - conf = Configure(env) - if not conf.CheckType('off_t'): - print 'Did not find off_t typedef, assuming int' - conf.env.Append(CCFLAGS = '-Doff_t=int') - env = conf.Finish() - </sconstruct> - - <para> - - You can also add a string that will be - placed at the beginning of the test file - that will be used to check for the &typedef;. - This provide a way to specify - files that must be included to find the &typedef;: - - </para> - - <sconstruct> - env = Environment() - conf = Configure(env) - if not conf.CheckType('off_t', '#include &lt;sys/types.h&gt;\n'): - print 'Did not find off_t typedef, assuming int' - conf.env.Append(CCFLAGS = '-Doff_t=int') - env = conf.Finish() - </sconstruct> - - </section> - - <section> - <title>Adding Your Own Custom Checks</title> - - <para> - - A custom check is a Python function - that checks for a certain condition to exist - on the running system, - usually using methods that &SCons; - supplies to take care of the details - of checking whether a compilation succeeds, - a link succeeds, - a program is runnable, - etc. - A simple custom check for the existence of - a specific library might look as follows: - - </para> - - <sconstruct> - mylib_test_source_file = """ - #include &lt;mylib.h&gt; - int main(int argc, char **argv) - { - MyLibrary mylib(argc, argv); - return 0; - } - """ - - def CheckMyLibrary(context): - context.Message('Checking for MyLibrary...') - result = context.TryLink(mylib_test_source_file, '.c') - context.Result(result) - return result - </sconstruct> - - <para> - - The &Message; and &Result; methods - should typically begin and end a custom check to - let the user know what's going on: - the &Message; call prints the - specified message (with no trailing newline) - and the &Result; call prints - <literal>yes</literal> if the check succeeds and - <literal>no</literal> if it doesn't. - The &TryLink; method - actually tests for whether the - specified program text - will successfully link. - - </para> - - <para> - - (Note that a custom check can modify - its check based on any arguments you - choose to pass it, - or by using or modifying the configure context environment - in the <literal>context.env</literal> attribute.) - - </para> - - <para> - - This custom check function is - then attached to the &configure_context; - by passing a dictionary - to the &Configure; call - that maps a name of the check - to the underlying function: - - </para> - - <sconstruct> - env = Environment() - conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) - </sconstruct> - - <para> - - You'll typically want to make - the check and the function name the same, - as we've done here, - to avoid potential confusion. - - </para> - - <para> - - We can then put these pieces together - and actually call the <literal>CheckMyLibrary</literal> check - as follows: - - </para> - - <sconstruct> - mylib_test_source_file = """ - #include &lt;mylib.h&gt; - int main(int argc, char **argv) - { - MyLibrary mylib(argc, argv); - return 0; - } - """ - - def CheckMyLibrary(context): - context.Message('Checking for MyLibrary... ') - result = context.TryLink(mylib_test_source_file, '.c') - context.Result(result) - return result - - env = Environment() - conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) - if not conf.CheckMyLibrary(): - print 'MyLibrary is not installed!' - Exit(1) - env = conf.Finish() - - # We would then add actual calls like Program() to build - # something using the "env" construction environment. - </sconstruct> - - <para> - - If MyLibrary is not installed on the system, - the output will look like: - - </para> - - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript file ... - Checking for MyLibrary... failed - MyLibrary is not installed! - </screen> - - <para> - - If MyLibrary is installed, - the output will look like: - - </para> - - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript file ... - Checking for MyLibrary... failed - scons: done reading SConscript - scons: Building targets ... - . - . - . - </screen> - - </section> - - <section> - <title>Not Configuring When Cleaning Targets</title> - - <para> - - Using multi-platform configuration - as described in the previous sections - will run the configuration commands - even when invoking - <userinput>scons -c</userinput> - to clean targets: - - </para> - - <screen> - % <userinput>scons -Q -c</userinput> - Checking for MyLibrary... yes - Removed foo.o - Removed foo - </screen> - - <para> - - Although running the platform checks - when removing targets doesn't hurt anything, - it's usually unnecessary. - You can avoid this by using the - &GetOption; method to - check whether the <option>-c</option> (clean) - option has been invoked on the command line: - - </para> - - <sconstruct> - env = Environment() - if not env.GetOption('clean'): - conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) - if not conf.CheckMyLibrary(): - print 'MyLibrary is not installed!' - Exit(1) - env = conf.Finish() - </sconstruct> - - <screen> - % <userinput>scons -Q -c</userinput> - Removed foo.o - Removed foo - </screen> - - </section> - - <!-- - - <section> - <title>Controlling Configuration: the &config; Option</title> - - <para> - - XXX -D, -u and -U - - </para> - - </section> - - --> diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml index f5db744..584a82e 100644 --- a/doc/user/sconf.xml +++ b/doc/user/sconf.xml @@ -58,12 +58,12 @@ </para> - <programlisting> + <sconstruct> env = Environment() conf = Configure(env) # Checks for libraries, header files, etc. go here! env = conf.Finish() - </programlisting> + </sconstruct> <para> @@ -109,7 +109,7 @@ </para> - <programlisting> + <sconstruct> env = Environment() conf = Configure(env) if not conf.CheckCHeader('math.h'): @@ -118,7 +118,7 @@ if conf.CheckCHeader('foo.h'): conf.env.Append('-DHAS_FOO_H') env = conf.Finish() - </programlisting> + </sconstruct> <para> @@ -137,14 +137,14 @@ </para> - <programlisting> + <sconstruct> env = Environment() conf = Configure(env) if not conf.CheckCXXHeader('vector.h'): print 'vector.h must be installed!' Exit(1) env = conf.Finish() - </programlisting> + </sconstruct> </section> @@ -158,14 +158,14 @@ </para> - <programlisting> + <sconstruct> env = Environment() conf = Configure(env) if not conf.CheckFunc('strcpy'): print 'Did not find strcpy(), using local version' conf.env.Append(CPPDEFINES = '-Dstrcpy=my_local_strcpy') env = conf.Finish() - </programlisting> + </sconstruct> </section> @@ -182,14 +182,14 @@ </para> - <programlisting> + <sconstruct> env = Environment() conf = Configure(env) if not conf.CheckLib('m'): print 'Did not find libm.a or m.lib, exiting!' Exit(1) env = conf.Finish() - </programlisting> + </sconstruct> <para> @@ -203,14 +203,14 @@ </para> - <programlisting> + <sconstruct> env = Environment() conf = Configure(env) if not conf.CheckLibWithHeader('m', 'math.h', 'c'): print 'Did not find libm.a or m.lib, exiting!' Exit(1) env = conf.Finish() - </programlisting> + </sconstruct> <para> @@ -232,14 +232,14 @@ </para> - <programlisting> + <sconstruct> env = Environment() conf = Configure(env) if not conf.CheckType('off_t'): print 'Did not find off_t typedef, assuming int' conf.env.Append(CCFLAGS = '-Doff_t=int') env = conf.Finish() - </programlisting> + </sconstruct> <para> @@ -251,14 +251,14 @@ </para> - <programlisting> + <sconstruct> env = Environment() conf = Configure(env) - if not conf.CheckType('off_t', '#include <sys/types.h>\n'): + if not conf.CheckType('off_t', '#include &lt;sys/types.h&gt;\n'): print 'Did not find off_t typedef, assuming int' conf.env.Append(CCFLAGS = '-Doff_t=int') env = conf.Finish() - </programlisting> + </sconstruct> </section> @@ -281,9 +281,9 @@ </para> - <programlisting> + <sconstruct> mylib_test_source_file = """ - #include <mylib.h> + #include &lt;mylib.h&gt; int main(int argc, char **argv) { MyLibrary mylib(argc, argv); @@ -296,7 +296,7 @@ result = context.TryLink(mylib_test_source_file, '.c') context.Result(result) return result - </programlisting> + </sconstruct> <para> @@ -336,10 +336,10 @@ </para> - <programlisting> + <sconstruct> env = Environment() conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) - </programlisting> + </sconstruct> <para> @@ -358,9 +358,9 @@ </para> - <programlisting> + <sconstruct> mylib_test_source_file = """ - #include <mylib.h> + #include &lt;mylib.h&gt; int main(int argc, char **argv) { MyLibrary mylib(argc, argv); @@ -383,7 +383,7 @@ # We would then add actual calls like Program() to build # something using the "env" construction environment. - </programlisting> + </sconstruct> <para> @@ -452,7 +452,7 @@ </para> - <programlisting> + <sconstruct> env = Environment() if not env.GetOption('clean'): conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) @@ -460,7 +460,7 @@ print 'MyLibrary is not installed!' Exit(1) env = conf.Finish() - </programlisting> + </sconstruct> <screen> % <userinput>scons -Q -c</userinput> diff --git a/doc/user/separate.in b/doc/user/separate.in deleted file mode 100644 index 75605fe..0000000 --- a/doc/user/separate.in +++ /dev/null @@ -1,540 +0,0 @@ -<!-- - - __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. - ---> - -<!-- - -=head1 Separating source and build trees - -It's often desirable to keep any derived files from the build completely -separate from the source files. This makes it much easier to keep track of -just what is a source file, and also makes it simpler to handle B<variant> -builds, especially if you want the variant builds to co-exist. - -=head2 Separating build and source directories using the Link command - -Cons provides a simple mechanism that handles all of these requirements. The -C<Link> command is invoked as in this example: - - Link 'build' => 'src'; - -The specified directories are ``linked'' to the specified source -directory. Let's suppose that you setup a source directory, F<src>, with the -sub-directories F<world> and F<hello> below it, as in the previous -example. You could then substitute for the original build lines the -following: - - Build qw( - build/world/Conscript - build/hello/Conscript - ); - -Notice that you treat the F<Conscript> file as if it existed in the build -directory. Now if you type the same command as before, you will get the -following results: - - % cons export - Install build/world/world.h as export/include/world.h - cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o - cc -Iexport/include -c build/world/world.c -o build/world/world.o - ar r build/world/libworld.a build/world/world.o - ar: creating build/world/libworld.a - ranlib build/world/libworld.a - Install build/world/libworld.a as export/lib/libworld.a - cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld - Install build/hello/hello as export/bin/hello - -Again, Cons has taken care of the details for you. In particular, you will -notice that all the builds are done using source files and object files from -the build directory. For example, F<build/world/world.o> is compiled from -F<build/world/world.c>, and F<export/include/world.h> is installed from -F<build/world/world.h>. This is accomplished on most systems by the simple -expedient of ``hard'' linking the required files from each source directory -into the appropriate build directory. - -The links are maintained correctly by Cons, no matter what you do to the -source directory. If you modify a source file, your editor may do this ``in -place'' or it may rename it first and create a new file. In the latter case, -any hard link will be lost. Cons will detect this condition the next time -the source file is needed, and will relink it appropriately. - -You'll also notice, by the way, that B<no> changes were required to the -underlying F<Conscript> files. And we can go further, as we shall see in the -next section. - -=head2 Explicit references to the source directory - -When using the C<Link> command on some operating systems or with some -tool chains, it's sometimes useful to have a command actually use -the path name to the source directory, not the build directory. For -example, on systems that must copy, not "hard link," the F<src/> and -F<build/> copies of C<Linked> files, using the F<src/> path of a file -name might make an editor aware that a syntax error must be fixed in the -source directory, not the build directory. - -You can tell Cons that you want to use the "source path" for a file by -preceding the file name with a ``!'' (exclamation point). For example, -if we add a ``!'' to the beginning of a source file: - - Program $env "foo", "!foo.c"; # Notice initial ! on foo.c - -Cons will compile the target as follows: - - cc -c src/foo.c -o build/foo.o - cc -o build/foo build/foo.o - -Notice that Cons has compiled the program from the the F<src/foo.c> -source file. Without the initial ``!'', Cons would have compiled the -program using the F<build/foo.c> path name. - ---> - - <para> - - It's often useful to keep any built files completely - separate from the source files. - In &SCons;, this is usually done by creating one or more separate - <emphasis>variant directory trees</emphasis> - that are used to hold the built objects files, libraries, - and executable programs, etc. - for a specific flavor, or variant, of build. - &SCons; provides two ways to do this, - one through the &SConscript; function that we've already seen, - and the second through a more flexible &VariantDir; function. - - </para> - - <para> - - One historical note: the &VariantDir; function - used to be called &BuildDir;. - That name is still supported - but has been deprecated - because the &SCons; functionality - differs from the model of a "build directory" - implemented by other build systems like the GNU Autotools. - - </para> - - <section> - <title>Specifying a Variant Directory Tree as Part of an &SConscript; Call</title> - - <para> - - The most straightforward way to establish a variant directory tree - uses the fact that the usual way to - set up a build hierarchy is to have an - &SConscript; file in the source subdirectory. - If you then pass a &variant_dir; argument to the - &SConscript; function call: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - SConscript('src/SConscript', variant_dir='build') - </file> - <file name="src/SConscript"> - env = Environment() - env.Program('hello.c') - </file> - <file name="src/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - &SCons; will then build all of the files in - the &build; subdirectory: - - </para> - - <scons_output example="ex1"> - <scons_output_command>ls src</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>ls build</scons_output_command> - </scons_output> - - <para> - - But wait a minute--what's going on here? - &SCons; created the object file - <filename>build/hello.o</filename> - in the &build; subdirectory, - as expected. - But even though our &hello_c; file lives in the &src; subdirectory, - &SCons; has actually compiled a - <filename>build/hello.c</filename> file - to create the object file. - - </para> - - <para> - - What's happened is that &SCons; has <emphasis>duplicated</emphasis> - the &hello_c; file from the &src; subdirectory - to the &build; subdirectory, - and built the program from there. - The next section explains why &SCons; does this. - - </para> - - </section> - - <section> - <title>Why &SCons; Duplicates Source Files in a Variant Directory Tree</title> - - <para> - - &SCons; duplicates source files in variant directory trees - because it's the most straightforward way to guarantee a correct build - <emphasis>regardless of include-file directory paths, - relative references between files, - or tool support for putting files in different locations</emphasis>, - and the &SCons; philosophy is to, by default, - guarantee a correct build in all cases. - - </para> - - <para> - - The most direct reason to duplicate source files - in variant directories - is simply that some tools (mostly older versions) - are written to only build their output files - in the same directory as the source files. - In this case, the choices are either - to build the output file in the source directory - and move it to the variant directory, - or to duplicate the source files in the variant directory. - - </para> - - <para> - - Additionally, - relative references between files - can cause problems if we don't - just duplicate the hierarchy of source files - in the variant directory. - You can see this at work in - use of the C preprocessor <literal>#include</literal> - mechanism with double quotes, not angle brackets: - - </para> - - <sconstruct> - #include "file.h" - </sconstruct> - - <para> - - The <emphasis>de facto</emphasis> standard behavior - for most C compilers in this case - is to first look in the same directory - as the source file that contains the <literal>#include</literal> line, - then to look in the directories in the preprocessor search path. - Add to this that the &SCons; implementation of - support for code repositories - (described below) - means not all of the files - will be found in the same directory hierarchy, - and the simplest way to make sure - that the right include file is found - is to duplicate the source files into the variant directory, - which provides a correct build - regardless of the original location(s) of the source files. - - </para> - - <para> - - Although source-file duplication guarantees a correct build - even in these end-cases, - it <emphasis>can</emphasis> usually be safely disabled. - The next section describes - how you can disable the duplication of source files - in the variant directory. - - </para> - - </section> - - <section> - <title>Telling &SCons; to Not Duplicate Source Files in the Variant Directory Tree</title> - - <para> - - In most cases and with most tool sets, - &SCons; can place its target files in a build subdirectory - <emphasis>without</emphasis> - duplicating the source files - and everything will work just fine. - You can disable the default &SCons; behavior - by specifying <literal>duplicate=0</literal> - when you call the &SConscript; function: - - </para> - - <sconstruct> - SConscript('src/SConscript', variant_dir='build', duplicate=0) - </sconstruct> - - <para> - - When this flag is specified, - &SCons; uses the variant directory - like most people expect--that is, - the output files are placed in the variant directory - while the source files stay in the source directory: - - </para> - - <screen> - % <userinput>ls src</userinput> - SConscript - hello.c - % <userinput>scons -Q</userinput> - cc -c src/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % <userinput>ls build</userinput> - hello - hello.o - </screen> - - </section> - - <section> - <title>The &VariantDir; Function</title> - - <para> - - Use the &VariantDir; function to establish that target - files should be built in a separate directory - from the source files: - - </para> - - <scons_example name="ex_builddir"> - <file name="SConstruct" printme="1"> - VariantDir('build', 'src') - env = Environment() - env.Program('build/hello.c') - </file> - <file name="src/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Note that when you're not using - an &SConscript; file in the &src; subdirectory, - you must actually specify that - the program must be built from - the <filename>build/hello.c</filename> - file that &SCons; will duplicate in the - &build; subdirectory. - - </para> - - <para> - - When using the &VariantDir; function directly, - &SCons; still duplicates the source files - in the variant directory by default: - - </para> - - <scons_output example="ex_builddir"> - <scons_output_command>ls src</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>ls build</scons_output_command> - </scons_output> - - <para> - - You can specify the same <literal>duplicate=0</literal> argument - that you can specify for an &SConscript; call: - - </para> - - <scons_example name="ex_duplicate_0"> - <file name="SConstruct" printme="1"> - VariantDir('build', 'src', duplicate=0) - env = Environment() - env.Program('build/hello.c') - </file> - <file name="src/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - In which case &SCons; - will disable duplication of the source files: - - </para> - - <scons_output example="ex_duplicate_0"> - <scons_output_command>ls src</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>ls build</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Using &VariantDir; With an &SConscript; File</title> - - <para> - - Even when using the &VariantDir; function, - it's much more natural to use it with - a subsidiary &SConscript; file. - For example, if the - <filename>src/SConscript</filename> - looks like this: - - </para> - - <scons_example name="example_builddir_sconscript"> - <file name="SConstruct"> - VariantDir('build', 'src') - SConscript('build/SConscript') - </file> - <file name="src/SConscript" printme="1"> - env = Environment() - env.Program('hello.c') - </file> - <file name="src/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Then our &SConstruct; file could look like: - - </para> - - <scons_example_file example="example_builddir_sconscript" name="SConstruct"> - </scons_example_file> - - <para> - - Yielding the following output: - - </para> - - <scons_output example="example_builddir_sconscript"> - <scons_output_command>ls src</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>ls build</scons_output_command> - </scons_output> - - <para> - - Notice that this is completely equivalent - to the use of &SConscript; that we - learned about in the previous section. - - </para> - - </section> - - <section> - <title>Using &Glob; with &VariantDir;</title> - - <para> - - The &Glob; file name pattern matching function - works just as usual when using &VariantDir;. - For example, if the - <filename>src/SConscript</filename> - looks like this: - - </para> - - <scons_example name="example_glob_builddir_sconscript"> - <file name="SConstruct"> - VariantDir('build', 'src') - SConscript('build/SConscript') - </file> - <file name="src/SConscript" printme="1"> - env = Environment() - env.Program('hello', Glob('*.c')) - </file> - <file name="src/f1.c"> - #include "f2.h" - int main() { printf(f2()); } - </file> - <file name="src/f2.c"> - const char * f2() { return("Hello, world!\n"); } - </file> - <file name="src/f2.h"> - const char * f2(); - </file> - </scons_example> - - <para> - - Then with the same &SConstruct; file as in the previous section, - and source files <filename>f1.c</filename> - and <filename>f2.c</filename> in src, - we would see the following output: - - </para> - - <scons_output example="example_glob_builddir_sconscript"> - <scons_output_command>ls src</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>ls build</scons_output_command> - </scons_output> - - <para> - - The &Glob; function returns Nodes in the - <filename>build/</filename> tree, as you'd expect. - - </para> - - </section> - - <!-- - - <section> - <title>Why You'd Want to Call &VariantDir; Instead of &SConscript;</title> - - <para> - - XXX why call VariantDir() instead of SConscript(variant_dir=) - - </para> - - </section> - - --> diff --git a/doc/user/separate.xml b/doc/user/separate.xml index 6b449fe..75605fe 100644 --- a/doc/user/separate.xml +++ b/doc/user/separate.xml @@ -151,9 +151,18 @@ program using the F<build/foo.c> path name. </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> SConscript('src/SConscript', variant_dir='build') - </programlisting> + </file> + <file name="src/SConscript"> + env = Environment() + env.Program('hello.c') + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -162,15 +171,11 @@ program using the F<build/foo.c> path name. </para> - <screen> - % <userinput>ls src</userinput> - SConscript hello.c - % <userinput>scons -Q</userinput> - cc -o build/hello.o -c build/hello.c - cc -o build/hello build/hello.o - % <userinput>ls build</userinput> - SConscript hello hello.c hello.o - </screen> + <scons_output example="ex1"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> <para> @@ -240,9 +245,9 @@ program using the F<build/foo.c> path name. </para> - <programlisting> + <sconstruct> #include "file.h" - </programlisting> + </sconstruct> <para> @@ -293,9 +298,9 @@ program using the F<build/foo.c> path name. </para> - <programlisting> + <sconstruct> SConscript('src/SConscript', variant_dir='build', duplicate=0) - </programlisting> + </sconstruct> <para> @@ -332,11 +337,16 @@ program using the F<build/foo.c> path name. </para> - <programlisting> + <scons_example name="ex_builddir"> + <file name="SConstruct" printme="1"> VariantDir('build', 'src') env = Environment() env.Program('build/hello.c') - </programlisting> + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -358,15 +368,11 @@ program using the F<build/foo.c> path name. </para> - <screen> - % <userinput>ls src</userinput> - hello.c - % <userinput>scons -Q</userinput> - cc -o build/hello.o -c build/hello.c - cc -o build/hello build/hello.o - % <userinput>ls build</userinput> - hello hello.c hello.o - </screen> + <scons_output example="ex_builddir"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> <para> @@ -375,11 +381,16 @@ program using the F<build/foo.c> path name. </para> - <programlisting> + <scons_example name="ex_duplicate_0"> + <file name="SConstruct" printme="1"> VariantDir('build', 'src', duplicate=0) env = Environment() env.Program('build/hello.c') - </programlisting> + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -388,15 +399,11 @@ program using the F<build/foo.c> path name. </para> - <screen> - % <userinput>ls src</userinput> - hello.c - % <userinput>scons -Q</userinput> - cc -o build/hello.o -c src/hello.c - cc -o build/hello build/hello.o - % <userinput>ls build</userinput> - hello hello.o - </screen> + <scons_output example="ex_duplicate_0"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> </section> @@ -414,10 +421,19 @@ program using the F<build/foo.c> path name. </para> - <programlisting> + <scons_example name="example_builddir_sconscript"> + <file name="SConstruct"> + VariantDir('build', 'src') + SConscript('build/SConscript') + </file> + <file name="src/SConscript" printme="1"> env = Environment() env.Program('hello.c') - </programlisting> + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -425,11 +441,8 @@ program using the F<build/foo.c> path name. </para> - - <programlisting> - VariantDir('build', 'src') - SConscript('build/SConscript') - </programlisting> + <scons_example_file example="example_builddir_sconscript" name="SConstruct"> + </scons_example_file> <para> @@ -437,15 +450,11 @@ program using the F<build/foo.c> path name. </para> - <screen> - % <userinput>ls src</userinput> - SConscript hello.c - % <userinput>scons -Q</userinput> - cc -o build/hello.o -c build/hello.c - cc -o build/hello build/hello.o - % <userinput>ls build</userinput> - SConscript hello hello.c hello.o - </screen> + <scons_output example="example_builddir_sconscript"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> <para> @@ -470,10 +479,26 @@ program using the F<build/foo.c> path name. </para> - <programlisting> + <scons_example name="example_glob_builddir_sconscript"> + <file name="SConstruct"> + VariantDir('build', 'src') + SConscript('build/SConscript') + </file> + <file name="src/SConscript" printme="1"> env = Environment() env.Program('hello', Glob('*.c')) - </programlisting> + </file> + <file name="src/f1.c"> + #include "f2.h" + int main() { printf(f2()); } + </file> + <file name="src/f2.c"> + const char * f2() { return("Hello, world!\n"); } + </file> + <file name="src/f2.h"> + const char * f2(); + </file> + </scons_example> <para> @@ -484,16 +509,11 @@ program using the F<build/foo.c> path name. </para> - <screen> - % <userinput>ls src</userinput> - SConscript f1.c f2.c f2.h - % <userinput>scons -Q</userinput> - cc -o build/f1.o -c build/f1.c - cc -o build/f2.o -c build/f2.c - cc -o build/hello build/f1.o build/f2.o - % <userinput>ls build</userinput> - SConscript f1.c f1.o f2.c f2.h f2.o hello - </screen> + <scons_output example="example_glob_builddir_sconscript"> + <scons_output_command>ls src</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>ls build</scons_output_command> + </scons_output> <para> diff --git a/doc/user/sideeffect.in b/doc/user/sideeffect.in deleted file mode 100644 index cbeefae..0000000 --- a/doc/user/sideeffect.in +++ /dev/null @@ -1,216 +0,0 @@ -<!-- - - __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> diff --git a/doc/user/sideeffect.xml b/doc/user/sideeffect.xml index 2cb4254..cbeefae 100644 --- a/doc/user/sideeffect.xml +++ b/doc/user/sideeffect.xml @@ -134,14 +134,21 @@ </para> - <programlisting> + <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) - </programlisting> + </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> @@ -155,11 +162,9 @@ </para> - <screen> - % <userinput>scons -Q --jobs=2</userinput> - ./build --log logfile.txt file1.in file1.out - ./build --log logfile.txt file2.in file2.out - </screen> + <scons_output example="SideEffectShared"> + <scons_output_command>scons -Q --jobs=2</scons_output_command> + </scons_output> <para> @@ -173,19 +178,19 @@ </para> - <programlisting> + <scons_example name="SideEffectParallel"> + <file name="SConstruct" printme="1"> env = Environment() - f1 = env.Command('file1.out', [], 'echo >$TARGET data1') + f1 = env.Command('file1.out', [], 'echo >$TARGET data1') env.SideEffect('not_really_updated', f1) - f2 = env.Command('file2.out', [], 'echo >$TARGET data2') + f2 = env.Command('file2.out', [], 'echo >$TARGET data2') env.SideEffect('not_really_updated', f2) - </programlisting> + </file> + </scons_example> - <screen> - % <userinput>scons -Q --jobs=2</userinput> - echo > file1.out data1 - echo > file2.out data2 - </screen> + <scons_output example="SideEffectParallel"> + <scons_output_command>scons -Q --jobs=2</scons_output_command> + </scons_output> <para> diff --git a/doc/user/simple.in b/doc/user/simple.in deleted file mode 100644 index 8a25be5..0000000 --- a/doc/user/simple.in +++ /dev/null @@ -1,517 +0,0 @@ -<!-- - - __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> - - In this chapter, - you will see several examples of - very simple build configurations using &SCons;, - which will demonstrate how easy - it is to use &SCons; to - build programs from several different programming languages - on different types of systems. - - </para> - - <section> - <title>Building Simple C / C++ Programs</title> - - <para> - - Here's the famous "Hello, World!" program in C: - - </para> - - <programlisting> - int - main() - { - printf("Hello, world!\n"); - } - </programlisting> - - <para> - - And here's how to build it using &SCons;. - Enter the following into a file named &SConstruct;: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - Program('hello.c') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - This minimal configuration file gives - &SCons; two pieces of information: - what you want to build - (an executable program), - and the input file from - which you want it built - (the <filename>hello.c</filename> file). - &b-link-Program; is a <firstterm>builder_method</firstterm>, - a Python call that tells &SCons; that you want to build an - executable program. - - </para> - - <para> - - That's it. Now run the &scons; command to build the program. - On a POSIX-compliant system like Linux or UNIX, - you'll see something like: - - </para> - - <scons_output example="ex1" os="posix"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - On a Windows system with the Microsoft Visual C++ compiler, - you'll see something like: - - </para> - - <scons_output example="ex1" os="win32"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - First, notice that you only need - to specify the name of the source file, - and that &SCons; correctly deduces the names of - the object and executable files to be built - from the base of the source file name. - - </para> - - <para> - - Second, notice that the same input &SConstruct; file, - without any changes, - generates the correct output file names on both systems: - <filename>hello.o</filename> and <filename>hello</filename> - on POSIX systems, - <filename>hello.obj</filename> and <filename>hello.exe</filename> - on Windows systems. - This is a simple example of how &SCons; - makes it extremely easy to - write portable software builds. - - </para> - - <para> - - (Note that we won't provide duplicate side-by-side - POSIX and Windows output for all of the examples in this guide; - just keep in mind that, unless otherwise specified, - any of the examples should work equally well on both types of systems.) - - </para> - - </section> - - <section> - <title>Building Object Files</title> - - <para> - - The &b-link-Program; builder method is only one of - many builder methods that &SCons; provides - to build different types of files. - Another is the &b-link-Object; builder method, - which tells &SCons; to build an object file - from the specified source file: - - </para> - - <scons_example name="Object"> - <file name="SConstruct" printme="1"> - Object('hello.c') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Now when you run the &scons; command to build the program, - it will build just the &hello_o; object file on a POSIX system: - - </para> - - <scons_output example="Object" os="posix"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - And just the &hello_obj; object file - on a Windows system (with the Microsoft Visual C++ compiler): - - </para> - - <scons_output example="Object" os="win32"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Simple Java Builds</title> - - <para> - - &SCons; also makes building with Java extremely easy. - Unlike the &b-link-Program; and &b-link-Object; builder methods, - however, the &b-link-Java; builder method - requires that you specify - the name of a destination directory in which - you want the class files placed, - followed by the source directory - in which the <filename>.java</filename> files live: - - </para> - - <scons_example name="java"> - <file name="SConstruct" printme="1"> - Java('classes', 'src') - </file> - <file name="src/hello.java"> - public class Example1 - { - public static void main(String[] args) - { - System.out.println("Hello Java world!\n"); - } - } - </file> - </scons_example> - - <para> - - If the <filename>src</filename> directory - contains a single <filename>hello.java</filename> file, - then the output from running the &scons; command - would look something like this - (on a POSIX system): - - </para> - - <scons_output example="java" os="posix"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - We'll cover Java builds in more detail, - including building Java archive (<filename>.jar</filename>) - and other types of file, - in <xref linkend="chap-java"></xref>. - - </para> - - </section> - - <section> - <title>Cleaning Up After a Build</title> - - <para> - - When using &SCons;, it is unnecessary to add special - commands or target names to clean up after a build. - Instead, you simply use the - <literal>-c</literal> or <literal>--clean</literal> - option when you invoke &SCons;, - and &SCons; removes the appropriate built files. - So if we build our example above - and then invoke <literal>scons -c</literal> - afterwards, the output on POSIX looks like: - - </para> - - <scons_example name="clean"> - <file name="SConstruct"> - Program('hello.c') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <scons_output example="clean" os="posix"> - <scons_output_command>scons</scons_output_command> - <scons_output_command>scons -c</scons_output_command> - </scons_output> - - <para> - - And the output on Windows looks like: - - </para> - - <scons_output example="clean" os="win32"> - <scons_output_command>scons</scons_output_command> - <scons_output_command>scons -c</scons_output_command> - </scons_output> - - <para> - - Notice that &SCons; changes its output to tell you that it - is <literal>Cleaning targets ...</literal> and - <literal>done cleaning targets.</literal> - - </para> - - </section> - - <section> - <title>The &SConstruct; File</title> - - <para> - - If you're used to build systems like &Make; - you've already figured out that the &SConstruct; file - is the &SCons; equivalent of a &Makefile;. - That is, the &SConstruct; file is the input file - that &SCons; reads to control the build. - - </para> - - <section> - <title>&SConstruct; Files Are Python Scripts</title> - - <para> - - There is, however, an important difference between - an &SConstruct; file and a &Makefile;: - the &SConstruct; file is actually a Python script. - If you're not already familiar with Python, don't worry. - This User's Guide will introduce you step-by-step - to the relatively small amount of Python you'll - need to know to be able to use &SCons; effectively. - And Python is very easy to learn. - - </para> - - <para> - - One aspect of using Python as the - scripting language is that you can put comments - in your &SConstruct; file using Python's commenting convention; - that is, everything between a '#' and the end of the line - will be ignored: - - </para> - - <programlisting> - # Arrange to build the "hello" program. - Program('hello.c') # "hello.c" is the source file. - </programlisting> - - <para> - - You'll see throughout the remainder of this Guide - that being able to use the power of a - real scripting language - can greatly simplify the solutions - to complex requirements of real-world builds. - - </para> - - </section> - - <section> - <title>&SCons; Functions Are Order-Independent</title> - - <para> - - One important way in which the &SConstruct; - file is not exactly like a normal Python script, - and is more like a &Makefile;, - is that the order in which - the &SCons; functions are called in - the &SConstruct; file - does <emphasis>not</emphasis> - affect the order in which &SCons; - actually builds the programs and object files - you want it to build.<footnote> - <para>In programming parlance, - the &SConstruct; file is - <emphasis>declarative</emphasis>, - meaning you tell &SCons; what you want done - and let it figure out the order in which to do it, - rather than strictly <emphasis>imperative</emphasis>, - where you specify explicitly the order in - which to do things. - </para> - </footnote> - In other words, when you call the &b-link-Program; builder - (or any other builder method), - you're not telling &SCons; to build - the program at the instant the builder method is called. - Instead, you're telling &SCons; to build the program - that you want, for example, - a program built from a file named &hello_c;, - and it's up to &SCons; to build that program - (and any other files) whenever it's necessary. - (We'll learn more about how - &SCons; decides when building or rebuilding a file - is necessary in <xref linkend="chap-depends"></xref>, below.) - - </para> - - <para> - - &SCons; reflects this distinction between - <emphasis>calling a builder method like</emphasis> &b-Program; - and <emphasis>actually building the program</emphasis> - by printing the status messages that indicate - when it's "just reading" the &SConstruct; file, - and when it's actually building the target files. - This is to make it clear when &SCons; is - executing the Python statements that make up the &SConstruct; file, - and when &SCons; is actually executing the - commands or other actions to - build the necessary files. - - </para> - - <para> - - Let's clarify this with an example. - Python has a <literal>print</literal> statement that - prints a string of characters to the screen. - If we put <literal>print</literal> statements around - our calls to the &b-Program; builder method: - - </para> - - <scons_example name="declarative"> - <file name="SConstruct" printme="1"> - print "Calling Program('hello.c')" - Program('hello.c') - print "Calling Program('goodbye.c')" - Program('goodbye.c') - print "Finished calling Program()" - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="goodbye.c"> - int main() { printf("Goodbye, world!\n"); } - </file> - </scons_example> - - <para> - - Then when we execute &SCons;, - we see the output from the <literal>print</literal> - statements in between the messages about - reading the &SConscript; files, - indicating that that is when the - Python statements are being executed: - - </para> - - <scons_output example="declarative" os="posix"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - Notice also that &SCons; built the &goodbye; program first, - even though the "reading &SConscript;" output - shows that we called <literal>Program('hello.c')</literal> - first in the &SConstruct; file. - - </para> - - </section> - - </section> - - <section> - <title>Making the &SCons; Output Less Verbose</title> - - <para> - - You've already seen how &SCons; prints - some messages about what it's doing, - surrounding the actual commands used to build the software: - - </para> - - <scons_output example="ex1" os="win32"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - These messages emphasize the - order in which &SCons; does its work: - all of the configuration files - (generically referred to as &SConscript; files) - are read and executed first, - and only then are the target files built. - Among other benefits, these messages help to distinguish between - errors that occur while the configuration files are read, - and errors that occur while targets are being built. - - </para> - - <para> - - One drawback, of course, is that these messages clutter the output. - Fortunately, they're easily disabled by using - the &Q; option when invoking &SCons;: - - </para> - - <scons_output example="ex1" os="win32"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Because we want this User's Guide to focus - on what &SCons; is actually doing, - we're going to use the &Q; option - to remove these messages from the - output of all the remaining examples in this Guide. - - </para> - - </section> diff --git a/doc/user/simple.xml b/doc/user/simple.xml index 2a687a0..8a25be5 100644 --- a/doc/user/simple.xml +++ b/doc/user/simple.xml @@ -59,9 +59,14 @@ </para> - <programlisting> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> Program('hello.c') - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -86,15 +91,9 @@ </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - cc -o hello.o -c hello.c - cc -o hello hello.o - scons: done building targets. - </screen> + <scons_output example="ex1" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -103,16 +102,9 @@ </para> - <screen> - C:\><userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - cl /Fohello.obj /c hello.c /nologo - link /nologo /OUT:hello.exe hello.obj - embedManifestExeCheck(target, source, env) - scons: done building targets. - </screen> + <scons_output example="ex1" os="win32"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -164,9 +156,14 @@ </para> - <programlisting> + <scons_example name="Object"> + <file name="SConstruct" printme="1"> Object('hello.c') - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> <para> @@ -175,14 +172,9 @@ </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - cc -o hello.o -c hello.c - scons: done building targets. - </screen> + <scons_output example="Object" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -191,14 +183,9 @@ </para> - <screen> - C:\><userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - cl /Fohello.obj /c hello.c /nologo - scons: done building targets. - </screen> + <scons_output example="Object" os="win32"> + <scons_output_command>scons</scons_output_command> + </scons_output> </section> @@ -218,9 +205,20 @@ </para> - <programlisting> + <scons_example name="java"> + <file name="SConstruct" printme="1"> Java('classes', 'src') - </programlisting> + </file> + <file name="src/hello.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> <para> @@ -232,14 +230,9 @@ </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - javac -d classes -sourcepath src src/hello.java - scons: done building targets. - </screen> + <scons_output example="java" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -269,24 +262,19 @@ </para> - - - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - cc -o hello.o -c hello.c - cc -o hello hello.o - scons: done building targets. - % <userinput>scons -c</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Cleaning targets ... - Removed hello.o - Removed hello - scons: done cleaning targets. - </screen> + <scons_example name="clean"> + <file name="SConstruct"> + Program('hello.c') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="clean" os="posix"> + <scons_output_command>scons</scons_output_command> + <scons_output_command>scons -c</scons_output_command> + </scons_output> <para> @@ -294,23 +282,10 @@ </para> - <screen> - C:\><userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - cl /Fohello.obj /c hello.c /nologo - link /nologo /OUT:hello.exe hello.obj - embedManifestExeCheck(target, source, env) - scons: done building targets. - C:\><userinput>scons -c</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Cleaning targets ... - Removed hello.obj - Removed hello.exe - scons: done cleaning targets. - </screen> + <scons_output example="clean" os="win32"> + <scons_output_command>scons</scons_output_command> + <scons_output_command>scons -c</scons_output_command> + </scons_output> <para> @@ -444,13 +419,21 @@ </para> - <programlisting> + <scons_example name="declarative"> + <file name="SConstruct" printme="1"> print "Calling Program('hello.c')" Program('hello.c') print "Calling Program('goodbye.c')" Program('goodbye.c') print "Finished calling Program()" - </programlisting> + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> <para> @@ -463,20 +446,9 @@ </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - Calling Program('hello.c') - Calling Program('goodbye.c') - Finished calling Program() - scons: done reading SConscript files. - scons: Building targets ... - cc -o goodbye.o -c goodbye.c - cc -o goodbye goodbye.o - cc -o hello.o -c hello.c - cc -o hello hello.o - scons: done building targets. - </screen> + <scons_output example="declarative" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -502,16 +474,9 @@ </para> - <screen> - C:\><userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - cl /Fohello.obj /c hello.c /nologo - link /nologo /OUT:hello.exe hello.obj - embedManifestExeCheck(target, source, env) - scons: done building targets. - </screen> + <scons_output example="ex1" os="win32"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -535,12 +500,9 @@ </para> - <screen> - C:\><userinput>scons -Q</userinput> - cl /Fohello.obj /c hello.c /nologo - link /nologo /OUT:hello.exe hello.obj - embedManifestExeCheck(target, source, env) - </screen> + <scons_output example="ex1" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> diff --git a/doc/user/sourcecode.in b/doc/user/sourcecode.in deleted file mode 100644 index 04c76d0..0000000 --- a/doc/user/sourcecode.in +++ /dev/null @@ -1,162 +0,0 @@ -<!-- - - __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> - - XXX - - </para> - - <section> - <title>Fetching Source Code From BitKeeper</title> - - <para> - - XXX - - </para> - - <scons_example name="ex_bitkeeper"> - <file name="SConstruct" printme="1"> - env = Environment() - env.SourceCode('.', env.BitKeeper()) - env.Program('hello.c') - </file> - <file name="s.hello.c"> - s.hello.c - </file> - </scons_example> - - <scons_output example="ex_bitkeeper"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Fetching Source Code From CVS</title> - - <para> - - XXX - - </para> - - <scons_example name="ex_cvs"> - <file name="SConstruct" printme="1"> - env = Environment() - env.SourceCode('.', env.CVS('/usr/local/CVS')) - env.Program('hello.c') - </file> - </scons_example> - - <scons_output example="ex_cvs"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Fetching Source Code From RCS</title> - - <para> - - XXX - - </para> - - <scons_example name="ex_rcs"> - <file name="SConstruct" printme="1"> - env = Environment() - env.SourceCode('.', env.RCS()) - env.Program('hello.c') - </file> - <file name="hello.c,v"> - hello.c,v - </file> - </scons_example> - - <scons_output example="ex_rcs"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <section> - <title>Fetching Source Code From SCCS</title> - - <para> - - XXX - - </para> - - <scons_example name="ex_sccs"> - <file name="SConstruct" printme="1"> - env = Environment() - env.SourceCode('.', env.SCCS()) - env.Program('hello.c') - </file> - <file name="s.hello.c"> - s.hello.c - </file> - </scons_example> - - <scons_output example="ex_sccs"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - <!-- - - <section> - <title>Fetching Source Code From Subversion</title> - - <para> - - XXX - - </para> - - <scons_example name="ex_subversion"> - <file name="SConstruct" printme="1"> - env = Environment() - env.SourceCode('.', env.Subversion('XXX')) - env.Program('hello.c') - </file> - </scons_example> - - <scons_output example="ex_subversion"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - </section> - - --> diff --git a/doc/user/sourcecode.xml b/doc/user/sourcecode.xml index 1818d8e..04c76d0 100644 --- a/doc/user/sourcecode.xml +++ b/doc/user/sourcecode.xml @@ -42,18 +42,20 @@ </para> - <programlisting> + <scons_example name="ex_bitkeeper"> + <file name="SConstruct" printme="1"> env = Environment() env.SourceCode('.', env.BitKeeper()) env.Program('hello.c') - </programlisting> + </file> + <file name="s.hello.c"> + s.hello.c + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - bk get hello.c - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="ex_bitkeeper"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -66,18 +68,17 @@ </para> - <programlisting> + <scons_example name="ex_cvs"> + <file name="SConstruct" printme="1"> env = Environment() env.SourceCode('.', env.CVS('/usr/local/CVS')) env.Program('hello.c') - </programlisting> + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - cvs -d /usr/local/CVS co hello.c - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="ex_cvs"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -90,18 +91,20 @@ </para> - <programlisting> + <scons_example name="ex_rcs"> + <file name="SConstruct" printme="1"> env = Environment() env.SourceCode('.', env.RCS()) env.Program('hello.c') - </programlisting> + </file> + <file name="hello.c,v"> + hello.c,v + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - co hello.c - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + <scons_output example="ex_rcs"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> @@ -114,18 +117,20 @@ </para> - <programlisting> + <scons_example name="ex_sccs"> + <file name="SConstruct" printme="1"> env = Environment() env.SourceCode('.', env.SCCS()) env.Program('hello.c') - </programlisting> - - <screen> - % <userinput>scons -Q</userinput> - sccs get hello.c - cc -o hello.o -c hello.c - cc -o hello hello.o - </screen> + </file> + <file name="s.hello.c"> + s.hello.c + </file> + </scons_example> + + <scons_output example="ex_sccs"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </section> diff --git a/doc/user/tasks.in b/doc/user/tasks.in deleted file mode 100644 index 79787a6..0000000 --- a/doc/user/tasks.in +++ /dev/null @@ -1,146 +0,0 @@ -<!-- - - __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> -There is a common set of simple tasks that many build configurations rely -on as they become more complex. Most build tools have special -purpose constructs for performing these tasks, but since &SConscript; -files are &Python; scripts, you can use more flexible built-in &Python; -services to perform these tasks. This appendix lists a number of these -tasks and how to implement them in &Python; and &SCons;. -</para> - -<example> -<title>Wildcard globbing to create a list of filenames</title> -<programlisting> -files = Glob(wildcard) -</programlisting> -</example> - -<example> -<title>Filename extension substitution</title> -<programlisting> -import os.path -filename = os.path.splitext(filename)[0]+extension -</programlisting> -</example> - -<example> -<title>Appending a path prefix to a list of filenames</title> -<programlisting> -import os.path -filenames = [os.path.join(prefix, x) for x in filenames] -</programlisting> -</example> - -<example> -<title>Substituting a path prefix with another one</title> -<programlisting> -if filename.find(old_prefix) == 0: - filename = filename.replace(old_prefix, new_prefix) -</programlisting> -</example> - -<example> -<title>Filtering a filename list to exclude/retain only a specific set -of extensions</title> -<programlisting> -import os.path -filenames = [x for x in filenames if os.path.splitext(x)[1] in extensions] -</programlisting> -</example> - -<example> -<title>The "backtick function": run a shell command and capture the -output</title> -<programlisting>import os -output = os.popen(command).read() -</programlisting> -</example> - -<example> -<title>Generating source code: how code can be generated and used by SCons</title> - -<para> - -The Copy builders here could be any arbitrary shell or python function -that produces one or more files. This example shows how to create -those files and use them in &SCons;. - -</para> - -<scons_example name="ex1"> -<file name="SConstruct" printme="1"> -#### SConstruct -env = Environment() -env.Append(CPPPATH = "#") - -## Header example -env.Append(BUILDERS = - {'Copy1' : Builder(action = 'cat < $SOURCE > $TARGET', - suffix='.h', src_suffix='.bar')}) -env.Copy1('test.bar') # produces test.h from test.bar. -env.Program('app','main.cpp') # indirectly depends on test.bar - -## Source file example -env.Append(BUILDERS = - {'Copy2' : Builder(action = 'cat < $SOURCE > $TARGET', - suffix='.cpp', src_suffix='.bar2')}) -foo = env.Copy2('foo.bar2') # produces foo.cpp from foo.bar2. -env.Program('app2',['main2.cpp'] + foo) # compiles main2.cpp and foo.cpp into app2. -</file> - -<file name="main.cpp"> -#include "test.h" -</file> -<file name="test.bar"> -// nothing here -</file> -<file name="main2.cpp"> -//// main2.cpp -</file> -<file name="foo.bar2"> -// nothing here -</file> -</scons_example> - -<para> - -Where main.cpp looks like this: - -</para> - - <scons_example_file example="ex1" name="main.cpp"> - </scons_example_file> - -<para> -produces this: -</para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - -</example> diff --git a/doc/user/tasks.xml b/doc/user/tasks.xml index 1a13a5b..79787a6 100644 --- a/doc/user/tasks.xml +++ b/doc/user/tasks.xml @@ -91,25 +91,40 @@ those files and use them in &SCons;. </para> -<programlisting> +<scons_example name="ex1"> +<file name="SConstruct" printme="1"> #### SConstruct env = Environment() env.Append(CPPPATH = "#") ## Header example env.Append(BUILDERS = - {'Copy1' : Builder(action = 'cat < $SOURCE > $TARGET', + {'Copy1' : Builder(action = 'cat < $SOURCE > $TARGET', suffix='.h', src_suffix='.bar')}) env.Copy1('test.bar') # produces test.h from test.bar. env.Program('app','main.cpp') # indirectly depends on test.bar ## Source file example env.Append(BUILDERS = - {'Copy2' : Builder(action = 'cat < $SOURCE > $TARGET', + {'Copy2' : Builder(action = 'cat < $SOURCE > $TARGET', suffix='.cpp', src_suffix='.bar2')}) foo = env.Copy2('foo.bar2') # produces foo.cpp from foo.bar2. env.Program('app2',['main2.cpp'] + foo) # compiles main2.cpp and foo.cpp into app2. -</programlisting> +</file> + +<file name="main.cpp"> +#include "test.h" +</file> +<file name="test.bar"> +// nothing here +</file> +<file name="main2.cpp"> +//// main2.cpp +</file> +<file name="foo.bar2"> +// nothing here +</file> +</scons_example> <para> @@ -117,21 +132,15 @@ Where main.cpp looks like this: </para> - - <programlisting> -#include "test.h" -</programlisting> + <scons_example_file example="ex1" name="main.cpp"> + </scons_example_file> <para> produces this: </para> - <screen> - % <userinput>scons -Q</userinput> - cc -o app main.cpp - cat < foo.bar2 > foo.cpp - cc -o app2 main2.cpp foo.cpp - cat < test.bar > test.h - </screen> + <scons_output example="ex1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> </example> diff --git a/doc/user/tools.in b/doc/user/tools.in deleted file mode 100644 index 512bf97..0000000 --- a/doc/user/tools.in +++ /dev/null @@ -1,38 +0,0 @@ -<!-- - - __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> - -This appendix contains descriptions of all of the -Tools modules that are -available "out of the box" in this version of SCons. - -</para> - -<variablelist> - -&tools-gen; - -</variablelist> diff --git a/doc/user/troubleshoot.in b/doc/user/troubleshoot.in deleted file mode 100644 index d171293..0000000 --- a/doc/user/troubleshoot.in +++ /dev/null @@ -1,914 +0,0 @@ -<!-- - - __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> - - The experience of configuring any - software build tool to build a large code base - usually, at some point, - involves trying to figure out why - the tool is behaving a certain way, - and how to get it to behave the way you want. - &SCons; is no different. - This appendix contains a number of - different ways in which you can - get some additional insight into &SCons;' behavior. - - </para> - - <para> - - Note that we're always interested in trying to - improve how you can troubleshoot configuration problems. - If you run into a problem that has - you scratching your head, - and which there just doesn't seem to be a good way to debug, - odds are pretty good that someone else will run into - the same problem, too. - If so, please let the SCons development team know - (preferably by filing a bug report - or feature request at our project pages at tigris.org) - so that we can use your feedback - to try to come up with a better way to help you, - and others, get the necessary insight into &SCons; behavior - to help identify and fix configuration issues. - - </para> - - <section> - <title>Why is That Target Being Rebuilt? the &debug-explain; Option</title> - - <para> - - Let's look at a simple example of - a misconfigured build - that causes a target to be rebuilt - every time &SCons; is run: - - </para> - - <scons_example name="explain1"> - <file name="SConstruct" printme="1"> - # Intentionally misspell the output file name in the - # command used to create the file: - Command('file.out', 'file.in', 'cp $SOURCE file.oout') - </file> - <file name="file.in"> - file.in - </file> - </scons_example> - - <para> - - (Note to Windows users: The POSIX &cp; command - copies the first file named on the command line - to the second file. - In our example, it copies the &file_in; file - to the &file_out; file.) - - </para> - - <para> - - Now if we run &SCons; multiple times on this example, - we see that it re-runs the &cp; - command every time: - - </para> - - <scons_output example="explain1" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - In this example, - the underlying cause is obvious: - we've intentionally misspelled the output file name - in the &cp; command, - so the command doesn't actually - build the &file_out; file that we've told &SCons; to expect. - But if the problem weren't obvious, - it would be helpful - to specify the &debug-explain; option - on the command line - to have &SCons; tell us very specifically - why it's decided to rebuild the target: - - </para> - - <scons_output example="explain1" os="posix"> - <scons_output_command>scons -Q --debug=explain</scons_output_command> - </scons_output> - - <para> - - If this had been a more complicated example - involving a lot of build output, - having &SCons; tell us that - it's trying to rebuild the target file - because it doesn't exist - would be an important clue - that something was wrong with - the command that we invoked to build it. - - </para> - - <para> - - The &debug-explain; option also comes in handy - to help figure out what input file changed. - Given a simple configuration that builds - a program from three source files, - changing one of the source files - and rebuilding with the &debug-explain; - option shows very specifically - why &SCons; rebuilds the files that it does: - - </para> - - <scons_example name="explain2"> - <file name="SConstruct"> - Program('prog', ['file1.c', 'file2.c', 'file3.c']) - </file> - <file name="file1.c"> - file1.c - </file> - <file name="file2.c"> - file2.c - </file> - <file name="file3.c"> - file3.c - </file> - </scons_example> - - <scons_output example="explain2" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command output=" [CHANGE THE CONTENTS OF file2.c]">edit file2.c</scons_output_command> - <scons_output_command>scons -Q --debug=explain</scons_output_command> - </scons_output> - - <para> - - This becomes even more helpful - in identifying when a file is rebuilt - due to a change in an implicit dependency, - such as an incuded <filename>.h</filename> file. - If the <filename>file1.c</filename> - and <filename>file3.c</filename> files - in our example - both included a &hello_h; file, - then changing that included file - and re-running &SCons; with the &debug-explain; option - will pinpoint that it's the change to the included file - that starts the chain of rebuilds: - - </para> - - <scons_example name="explain3"> - <file name="SConstruct"> - Program('prog', ['file1.c', 'file2.c', 'file3.c'], CPPPATH='.') - </file> - <file name="file1.c"> - #include <hello.h> - file1.c - </file> - <file name="file2.c"> - file2.c - </file> - <file name="file3.c"> - #include <hello.h> - file3.c - </file> - <file name="hello.h"> - #define string "world" - </file> - </scons_example> - - <scons_output example="explain3" os="posix"> - <scons_output_command>scons -Q</scons_output_command> - <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> - <scons_output_command>scons -Q --debug=explain</scons_output_command> - </scons_output> - - <para> - - (Note that the &debug-explain; option will only tell you - why &SCons; decided to rebuild necessary targets. - It does not tell you what files it examined - when deciding <emphasis>not</emphasis> - to rebuild a target file, - which is often a more valuable question to answer.) - - </para> - - </section> - - <section> - <title>What's in That Construction Environment? the &Dump; Method</title> - - <para> - - When you create a construction environment, - &SCons; populates it - with construction variables that are set up - for various compilers, linkers and utilities - that it finds on your system. - Although this is usually helpful and what you want, - it might be frustrating if &SCons; - doesn't set certain variables that you - expect to be set. - In situations like this, - it's sometimes helpful to use the - construction environment &Dump; method - to print all or some of - the construction variables. - Note that the &Dump; method - <emphasis>returns</emphasis> - the representation of the variables - in the environment - for you to print (or otherwise manipulate): - - </para> - - <scons_example name="Dump"> - <file name="SConstruct" printme="1"> - env = Environment() - print env.Dump() - </file> - </scons_example> - - <para> - - On a POSIX system with gcc installed, - this might generate: - - </para> - - <scons_output example="Dump" os="posix" tools="gcc"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - On a Windows system with Visual C++ - the output might look like: - - </para> - - <scons_output example="Dump" os="win32" tools="msvc"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - The construction environments in these examples have - actually been restricted to just gcc and Visual C++, - respectively. - In a real-life situation, - the construction environments will - likely contain a great many more variables. - Also note that we've massaged the example output above - to make the memory address of all objects a constant 0x700000. - In reality, you would see a different hexadecimal - number for each object. - - </para> - - <para> - - To make it easier to see just what you're - interested in, - the &Dump; method allows you to - specify a specific constrcution variable - that you want to disply. - For example, - it's not unusual to want to verify - the external environment used to execute build commands, - to make sure that the PATH and other - environment variables are set up the way they should be. - You can do this as follows: - - </para> - - <scons_example name="Dump_ENV"> - <file name="SConstruct" printme="1"> - env = Environment() - print env.Dump('ENV') - </file> - </scons_example> - - <para> - - Which might display the following when executed on a POSIX system: - - </para> - - <scons_output example="Dump_ENV" os="posix"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - <para> - - And the following when executed on a Windows system: - - </para> - - <scons_output example="Dump_ENV" os="win32"> - <scons_output_command>scons</scons_output_command> - </scons_output> - - </section> - - <section> - - <title>What Dependencies Does &SCons; Know About? the &tree; Option</title> - - <para> - - Sometimes the best way to try to figure out what - &SCons; is doing is simply to take a look at the - dependency graph that it constructs - based on your &SConscript; files. - The <literal>--tree</literal> option - will display all or part of the - &SCons; dependency graph in an - "ASCII art" graphical format - that shows the dependency hierarchy. - - </para> - - <para> - - For example, given the following input &SConstruct; file: - - </para> - - <scons_example name="tree1"> - <file name="SConstruct" printme="1"> - env = Environment(CPPPATH = ['.']) - env.Program('prog', ['f1.c', 'f2.c', 'f3.c']) - </file> - <file name="f1.c"> - #include "inc.h" - </file> - <file name="f2.c"> - #include "inc.h" - </file> - <file name="f3.c"> - #include "inc.h" - </file> - <file name="inc.h"> - inc.h - </file> - </scons_example> - - <para> - - Running &SCons; with the <literal>--tree=all</literal> - option yields: - - </para> - - <scons_output example="tree1"> - <scons_output_command>scons -Q --tree=all</scons_output_command> - </scons_output> - - <para> - - The tree will also be printed when the - <literal>-n</literal> (no execute) option is used, - which allows you to examine the dependency graph - for a configuration without actually - rebuilding anything in the tree. - - </para> - - <para> - - The <literal>--tree</literal> option only prints - the dependency graph for the specified targets - (or the default target(s) if none are specified on the command line). - So if you specify a target like <filename>f2.o</filename> - on the command line, - the <literal>--tree</literal> option will only - print the dependency graph for that file: - - </para> - - <scons_output example="tree1"> - <scons_output_command>scons -Q --tree=all f2.o</scons_output_command> - </scons_output> - - <para> - - This is, of course, useful for - restricting the output from a very large - build configuration to just a - portion in which you're interested. - Multiple targets are fine, - in which case a tree will be printed - for each specified target: - - </para> - - <scons_output example="tree1"> - <scons_output_command>scons -Q --tree=all f1.o f3.o</scons_output_command> - </scons_output> - - <para> - - The <literal>status</literal> argument may be used - to tell &SCons; to print status information about - each file in the dependency graph: - - </para> - - <scons_output example="tree1"> - <scons_output_command>scons -Q --tree=status</scons_output_command> - </scons_output> - - <para> - - Note that <literal>--tree=all,status</literal> is equivalent; - the <literal>all</literal> - is assumed if only <literal>status</literal> is present. - As an alternative to <literal>all</literal>, - you can specify <literal>--tree=derived</literal> - to have &SCons; only print derived targets - in the tree output, - skipping source files - (like <filename>.c</filename> and <filename>.h</filename> files): - - </para> - - <scons_output example="tree1"> - <scons_output_command>scons -Q --tree=derived</scons_output_command> - </scons_output> - - <para> - - You can use the <literal>status</literal> - modifier with <literal>derived</literal> as well: - - </para> - - <scons_output example="tree1"> - <scons_output_command>scons -Q --tree=derived,status</scons_output_command> - </scons_output> - - <para> - - Note that the order of the <literal>--tree=</literal> - arguments doesn't matter; - <literal>--tree=status,derived</literal> is - completely equivalent. - - </para> - - <para> - - The default behavior of the <literal>--tree</literal> option - is to repeat all of the dependencies each time the library dependency - (or any other dependency file) is encountered in the tree. - If certain target files share other target files, - such as two programs that use the same library: - - </para> - - <scons_example name="tree2"> - <file name="SConstruct" printme="1"> - env = Environment(CPPPATH = ['.'], - LIBS = ['foo'], - LIBPATH = ['.']) - env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) - env.Program('prog1.c') - env.Program('prog2.c') - </file> - <file name="prog1.c"> - #include "inc.h" - </file> - <file name="prog2.c"> - #include "inc.h" - </file> - <file name="f1.c"> - #include "inc.h" - </file> - <file name="f2.c"> - #include "inc.h" - </file> - <file name="f3.c"> - #include "inc.h" - </file> - <file name="inc.h"> - inc.h - </file> - </scons_example> - - <para> - - Then there can be a <emphasis>lot</emphasis> of repetition in the - <literal>--tree=</literal> output: - - </para> - - <scons_output example="tree2"> - <scons_output_command>scons -Q --tree=all</scons_output_command> - </scons_output> - - <para> - - In a large configuration with many internal libraries - and include files, - this can very quickly lead to huge output trees. - To help make this more manageable, - a <literal>prune</literal> modifier may - be added to the option list, - in which case &SCons; - will print the name of a target that has - already been visited during the tree-printing - in <literal>[square brackets]</literal> - as an indication that the dependencies - of the target file may be found - by looking farther up the tree: - - </para> - - <scons_output example="tree2"> - <scons_output_command>scons -Q --tree=prune</scons_output_command> - </scons_output> - - <para> - - Like the <literal>status</literal> keyword, - the <literal>prune</literal> argument by itself - is equivalent to <literal>--tree=all,prune</literal>. - - </para> - - </section> - - <section> - - <title>How is &SCons; Constructing the Command Lines It Executes? the &debug-presub; Option</title> - - <para> - - Sometimes it's useful to look at the - pre-substitution string - that &SCons; uses to generate - the command lines it executes. - This can be done with the &debug-presub; option: - - </para> - - <scons_example name="presub"> - <file name="SConstruct"> - env = Environment(CPPPATH = ['.']) - env.Program('prog', 'prog.c') - </file> - <file name="prog.c"> - prog.c - </file> - </scons_example> - - <!-- - - Have to capture output here, otherwise the - -debug=presub output - shows the Python functions from the sconsdoc.py execution wrapper - used to generate this manual, not the underlying command-line strings. - - <scons_output example="presub"> - <scons_output_command>scons -Q - -debug=presub</scons_output_command> - </scons_output> - - --> - - <screen> - % <userinput>scons -Q --debug=presub</userinput> - Building prog.o with action: - $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCOMCOM $SOURCES - cc -o prog.o -c -I. prog.c - Building prog with action: - $SMART_LINKCOM - cc -o prog prog.o - </screen> - - </section> - - <section> - - <title>Where is &SCons; Searching for Libraries? the &debug-findlibs; Option</title> - - <para> - - To get some insight into what library names - &SCons; is searching for, - and in which directories it is searching, - Use the <literal>--debug=findlibs</literal> option. - Given the following input &SConstruct; file: - - </para> - - <scons_example name="findlibs"> - <file name="SConstruct" printme="1"> - env = Environment(LIBPATH = ['libs1', 'libs2']) - env.Program('prog.c', LIBS=['foo', 'bar']) - </file> - <file name="prog.c"> - prog.c - </file> - <file name="libs1/libfoo.a"> - libs1/libfoo.a - </file> - <file name="libs2/libbar.a"> - libs2/libbar.a - </file> - </scons_example> - - <para> - - And the libraries <filename>libfoo.a</filename> - and <filename>libbar.a</filename> - in <filename>libs1</filename> and <filename>libs2</filename>, - respectively, - use of the <literal>--debug=findlibs</literal> option yields: - - </para> - - <scons_output example="findlibs"> - <scons_output_command>scons -Q --debug=findlibs</scons_output_command> - </scons_output> - - </section> - - <!-- - - <section> - - <title>What Implicit Dependencies Did the &SCons; Scanner find? the &debug-includes; Option</title> - - <para> - - XXX explain the - - debug=includes option - - </para> - - <scons_example name="includes"> - <file name="SConstruct" printme="1"> - env = Environment(CPPPATH = ['inc1', 'inc2']) - env.Program('prog.c') - </file> - <file name="prog.c"> - #include "file1.h" - #include "file2.h" - prog.c - </file> - <file name="inc1/file1.h"> - inc1/file1.h - </file> - <file name="inc2/file2.h"> - inc2/file2.h - </file> - </scons_example> - - <scons_output example="includes"> - <scons_output_command>scons -Q - - debug=includes prog</scons_output_command> - </scons_output> - - </section> - - --> - - <section> - - <title>Where is &SCons; Blowing Up? the &debug-stacktrace; Option</title> - - <para> - - In general, &SCons; tries to keep its error - messages short and informative. - That means we usually try to avoid showing - the stack traces that are familiar - to experienced Python programmers, - since they usually contain much more - information than is useful to most people. - - </para> - - <para> - - For example, the following &SConstruct; file: - - </para> - - <scons_example name="stacktrace"> - <file name="SConstruct" printme="1"> - Program('prog.c') - </file> - </scons_example> - - <para> - - Generates the following error if the - <filename>prog.c</filename> file - does not exist: - - </para> - - <scons_output example="stacktrace"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - In this case, - the error is pretty obvious. - But if it weren't, - and you wanted to try to get more information - about the error, - the &debug-stacktrace; option - would show you exactly where in the &SCons; source code - the problem occurs: - - </para> - - <scons_output example="stacktrace"> - <scons_output_command>scons -Q --debug=stacktrace</scons_output_command> - </scons_output> - - <para> - - Of course, if you do need to dive into the &SCons; source code, - we'd like to know if, or how, - the error messages or troubleshooting options - could have been improved to avoid that. - Not everyone has the necessary time or - Python skill to dive into the source code, - and we'd like to improve &SCons; - for those people as well... - - </para> - - </section> - - <section> - - <title>How is &SCons; Making Its Decisions? the &taskmastertrace; Option</title> - - <para> - - The internal &SCons; subsystem that handles walking - the dependency graph - and controls the decision-making about what to rebuild - is the <literal>Taskmaster</literal>. - &SCons; supports a <literal>--taskmastertrace</literal> - option that tells the Taskmaster to print - information about the children (dependencies) - of the various Nodes on its walk down the graph, - which specific dependent Nodes are being evaluated, - and in what order. - - </para> - - <para> - - The <literal>--taskmastertrace</literal> option - takes as an argument the name of a file in - which to put the trace output, - with <filename>-</filename> (a single hyphen) - indicating that the trace messages - should be printed to the standard output: - - </para> - - <scons_example name="taskmastertrace"> - <file name="SConstruct" printme="1"> - env = Environment(CPPPATH = ['.']) - env.Program('prog.c') - </file> - <file name="prog.c"> - #include "inc.h" - prog.c - </file> - <file name="inc.h"> - #define STRING "one" - </file> - </scons_example> - - <scons_output example="taskmastertrace" os="posix"> - <scons_output_command>scons -Q --taskmastertrace=- prog</scons_output_command> - </scons_output> - - <para> - - The <literal>--taskmastertrace</literal> option - doesn't provide information about the actual - calculations involved in deciding if a file is up-to-date, - but it does show all of the dependencies - it knows about for each Node, - and the order in which those dependencies are evaluated. - This can be useful as an alternate way to determine - whether or not your &SCons; configuration, - or the implicit dependency scan, - has actually identified all the correct dependencies - you want it to. - - </para> - - </section> - - <section> - - <title>Watch &SCons; prepare targets for building: the &debug-prepare; Option</title> - - <para> - - Sometimes SCons doesn't build the target you want - and it's difficult to figure out why. You can use - the <literal>--debug=prepare</literal> option - to see all the targets &SCons; is considering, whether - they are already up-to-date or not. The message is - printed before &SCons; decides whether to build the target. - </para> - - </section> - - <section> - - <title>Why is a file disappearing? the --debug=duplicate Option</title> - - <para> - - When using the &Duplicate; option to create variant dirs, - sometimes you may find files not getting copied to where you - expect (or not at all), or files mysteriously disappearing. These - are usually because of a misconfiguration of some kind in the - SConstruct/SConscript, but they can be tricky to debug. The - --debug=duplicate option shows each time a variant file is - unlinked and relinked from its source (or copied, depending on - settings), and also shows a message for removing "stale" - variant-dir files that no longer have a corresponding source file. - It also prints a line for each target that's removed just before - building, since that can also be mistaken for the same thing. - - </para> - - </section> - - <!-- - - - <section> - - <title>Where Are My Build Bottlenecks? the &profile; Option</title> - - <para> - - XXX explain the - - profile= option - - </para> - - </section> - - --> - - <!-- - - <section> - <title>Troubleshooting Shared Caching: the &cache-debug; Option</title> - - <para> - - XXX describe the - - cache-debug option - XXX maybe point to the caching.in chapter? - - </para> - - </section> - - --> diff --git a/doc/user/troubleshoot.xml b/doc/user/troubleshoot.xml index 093574c..d171293 100644 --- a/doc/user/troubleshoot.xml +++ b/doc/user/troubleshoot.xml @@ -69,11 +69,16 @@ </para> - <programlisting> + <scons_example name="explain1"> + <file name="SConstruct" printme="1"> # Intentionally misspell the output file name in the # command used to create the file: Command('file.out', 'file.in', 'cp $SOURCE file.oout') - </programlisting> + </file> + <file name="file.in"> + file.in + </file> + </scons_example> <para> @@ -93,14 +98,11 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - cp file.in file.oout - % <userinput>scons -Q</userinput> - cp file.in file.oout - % <userinput>scons -Q</userinput> - cp file.in file.oout - </screen> + <scons_output example="explain1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -119,11 +121,9 @@ </para> - <screen> - % <userinput>scons -Q --debug=explain</userinput> - scons: building `file.out' because it doesn't exist - cp file.in file.oout - </screen> + <scons_output example="explain1" os="posix"> + <scons_output_command>scons -Q --debug=explain</scons_output_command> + </scons_output> <para> @@ -151,22 +151,26 @@ </para> - + <scons_example name="explain2"> + <file name="SConstruct"> + Program('prog', ['file1.c', 'file2.c', 'file3.c']) + </file> + <file name="file1.c"> + file1.c + </file> + <file name="file2.c"> + file2.c + </file> + <file name="file3.c"> + file3.c + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - cc -o file1.o -c file1.c - cc -o file2.o -c file2.c - cc -o file3.o -c file3.c - cc -o prog file1.o file2.o file3.o - % <userinput>edit file2.c</userinput> - [CHANGE THE CONTENTS OF file2.c] - % <userinput>scons -Q --debug=explain</userinput> - scons: rebuilding `file2.o' because `file2.c' changed - cc -o file2.o -c file2.c - scons: rebuilding `prog' because `file2.o' changed - cc -o prog file1.o file2.o file3.o - </screen> + <scons_output example="explain2" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF file2.c]">edit file2.c</scons_output_command> + <scons_output_command>scons -Q --debug=explain</scons_output_command> + </scons_output> <para> @@ -185,26 +189,31 @@ </para> - + <scons_example name="explain3"> + <file name="SConstruct"> + Program('prog', ['file1.c', 'file2.c', 'file3.c'], CPPPATH='.') + </file> + <file name="file1.c"> + #include <hello.h> + file1.c + </file> + <file name="file2.c"> + file2.c + </file> + <file name="file3.c"> + #include <hello.h> + file3.c + </file> + <file name="hello.h"> + #define string "world" + </file> + </scons_example> - <screen> - % <userinput>scons -Q</userinput> - cc -o file1.o -c -I. file1.c - cc -o file2.o -c -I. file2.c - cc -o file3.o -c -I. file3.c - cc -o prog file1.o file2.o file3.o - % <userinput>edit hello.h</userinput> - [CHANGE THE CONTENTS OF hello.h] - % <userinput>scons -Q --debug=explain</userinput> - scons: rebuilding `file1.o' because `hello.h' changed - cc -o file1.o -c -I. file1.c - scons: rebuilding `file3.o' because `hello.h' changed - cc -o file3.o -c -I. file3.c - scons: rebuilding `prog' because: - `file1.o' changed - `file3.o' changed - cc -o prog file1.o file2.o file3.o - </screen> + <scons_output example="explain3" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command> + <scons_output_command>scons -Q --debug=explain</scons_output_command> + </scons_output> <para> @@ -246,10 +255,12 @@ </para> - <programlisting> + <scons_example name="Dump"> + <file name="SConstruct" printme="1"> env = Environment() print env.Dump() - </programlisting> + </file> + </scons_example> <para> @@ -258,79 +269,9 @@ </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - { 'BUILDERS': {'_InternalInstall': <function InstallBuilderWrapper at 0x700000>, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>}, - 'CONFIGUREDIR': '#/.sconf_temp', - 'CONFIGURELOG': '#/config.log', - 'CPPSUFFIXES': [ '.c', - '.C', - '.cxx', - '.cpp', - '.c++', - '.cc', - '.h', - '.H', - '.hxx', - '.hpp', - '.hh', - '.F', - '.fpp', - '.FPP', - '.m', - '.mm', - '.S', - '.spp', - '.SPP', - '.sx'], - 'DSUFFIXES': ['.d'], - 'Dir': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'Dirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'ENV': { 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}, - 'ESCAPE': <function escape at 0x700000>, - 'File': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'HOST_ARCH': None, - 'HOST_OS': None, - 'IDLSUFFIXES': ['.idl', '.IDL'], - 'INSTALL': <function copyFunc at 0x700000>, - 'LIBPREFIX': 'lib', - 'LIBPREFIXES': ['$LIBPREFIX'], - 'LIBSUFFIX': '.a', - 'LIBSUFFIXES': ['$LIBSUFFIX', '$SHLIBSUFFIX'], - 'MAXLINELENGTH': 128072, - 'OBJPREFIX': '', - 'OBJSUFFIX': '.o', - 'PLATFORM': 'posix', - 'PROGPREFIX': '', - 'PROGSUFFIX': '', - 'PSPAWN': <function piped_env_spawn at 0x700000>, - 'RDirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'SCANNERS': [], - 'SHELL': 'sh', - 'SHLIBPREFIX': '$LIBPREFIX', - 'SHLIBSUFFIX': '.so', - 'SHOBJPREFIX': '$OBJPREFIX', - 'SHOBJSUFFIX': '$OBJSUFFIX', - 'SPAWN': <function spawnvpe_spawn at 0x700000>, - 'TARGET_ARCH': None, - 'TARGET_OS': None, - 'TEMPFILE': <class 'SCons.Platform.TempFileMunge'>, - 'TEMPFILEPREFIX': '@', - 'TOOLS': ['install', 'install'], - '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', - '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', - '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', - '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', - '__RPATH': '$_RPATH', - '_concat': <function _concat at 0x700000>, - '_defines': <function _defines at 0x700000>, - '_stripixes': <function _stripixes at 0x700000>} - scons: done reading SConscript files. - scons: Building targets ... - scons: `.' is up to date. - scons: done building targets. - </screen> + <scons_output example="Dump" os="posix" tools="gcc"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -339,112 +280,9 @@ </para> - <screen> - C:\><userinput>scons</userinput> - scons: Reading SConscript files ... - { 'BUILDERS': {'_InternalInstall': <function InstallBuilderWrapper at 0x700000>, 'Object': <SCons.Builder.CompositeBuilder object at 0x700000>, 'PCH': <SCons.Builder.BuilderBase object at 0x700000>, 'RES': <SCons.Builder.BuilderBase object at 0x700000>, 'SharedObject': <SCons.Builder.CompositeBuilder object at 0x700000>, 'StaticObject': <SCons.Builder.CompositeBuilder object at 0x700000>, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>}, - 'CC': 'cl', - 'CCCOM': <SCons.Action.FunctionAction object at 0x700000>, - 'CCFLAGS': ['/nologo'], - 'CCPCHFLAGS': ['${(PCH and "/Yu%s \\"/Fp%s\\""%(PCHSTOP or "",File(PCH))) or ""}'], - 'CCPDBFLAGS': ['${(PDB and "/Z7") or ""}'], - 'CFILESUFFIX': '.c', - 'CFLAGS': [], - 'CONFIGUREDIR': '#/.sconf_temp', - 'CONFIGURELOG': '#/config.log', - 'CPPDEFPREFIX': '/D', - 'CPPDEFSUFFIX': '', - 'CPPSUFFIXES': [ '.c', - '.C', - '.cxx', - '.cpp', - '.c++', - '.cc', - '.h', - '.H', - '.hxx', - '.hpp', - '.hh', - '.F', - '.fpp', - '.FPP', - '.m', - '.mm', - '.S', - '.spp', - '.SPP', - '.sx'], - 'CXX': '$CC', - 'CXXCOM': '${TEMPFILE("$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM")}', - 'CXXFILESUFFIX': '.cc', - 'CXXFLAGS': ['$(', '/TP', '$)'], - 'DSUFFIXES': ['.d'], - 'Dir': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'Dirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'ENV': { 'PATH': 'C:\\WINDOWS\\System32', - 'PATHEXT': '.COM;.EXE;.BAT;.CMD', - 'SystemRoot': 'C:\\WINDOWS'}, - 'ESCAPE': <function escape at 0x700000>, - 'File': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'HOST_ARCH': '', - 'HOST_OS': 'win32', - 'IDLSUFFIXES': ['.idl', '.IDL'], - 'INCPREFIX': '/I', - 'INCSUFFIX': '', - 'INSTALL': <function copyFunc at 0x700000>, - 'LIBPREFIX': '', - 'LIBPREFIXES': ['$LIBPREFIX'], - 'LIBSUFFIX': '.lib', - 'LIBSUFFIXES': ['$LIBSUFFIX'], - 'MAXLINELENGTH': 2048, - 'MSVC_SETUP_RUN': True, - 'OBJPREFIX': '', - 'OBJSUFFIX': '.obj', - 'PCHCOM': '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS', - 'PCHPDBFLAGS': ['${(PDB and "/Yd") or ""}'], - 'PLATFORM': 'win32', - 'PROGPREFIX': '', - 'PROGSUFFIX': '.exe', - 'PSPAWN': <function piped_spawn at 0x700000>, - 'RC': 'rc', - 'RCCOM': <SCons.Action.FunctionAction object at 0x700000>, - 'RCFLAGS': [], - 'RCSUFFIXES': ['.rc', '.rc2'], - 'RDirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'SCANNERS': [], - 'SHCC': '$CC', - 'SHCCCOM': <SCons.Action.FunctionAction object at 0x700000>, - 'SHCCFLAGS': ['$CCFLAGS'], - 'SHCFLAGS': ['$CFLAGS'], - 'SHCXX': '$CXX', - 'SHCXXCOM': '${TEMPFILE("$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM")}', - 'SHCXXFLAGS': ['$CXXFLAGS'], - 'SHELL': None, - 'SHLIBPREFIX': '', - 'SHLIBSUFFIX': '.dll', - 'SHOBJPREFIX': '$OBJPREFIX', - 'SHOBJSUFFIX': '$OBJSUFFIX', - 'SPAWN': <function spawn at 0x700000>, - 'STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME': 1, - 'TARGET_ARCH': '', - 'TARGET_OS': 'win32', - 'TEMPFILE': <class 'SCons.Platform.TempFileMunge'>, - 'TEMPFILEPREFIX': '@', - 'TOOLS': ['msvc', 'install', 'install'], - '_CCCOMCOM': '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $CCPCHFLAGS $CCPDBFLAGS', - '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', - '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', - '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', - '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', - '_MSVC_OUTPUT_FLAG': <function msvc_output_flag at 0x700000>, - '_concat': <function _concat at 0x700000>, - '_defines': <function _defines at 0x700000>, - '_stripixes': <function _stripixes at 0x700000>} - scons: done reading SConscript files. - scons: Building targets ... - scons: `.' is up to date. - scons: done building targets. - </screen> + <scons_output example="Dump" os="win32" tools="msvc"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -477,10 +315,12 @@ </para> - <programlisting> + <scons_example name="Dump_ENV"> + <file name="SConstruct" printme="1"> env = Environment() print env.Dump('ENV') - </programlisting> + </file> + </scons_example> <para> @@ -488,15 +328,9 @@ </para> - <screen> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - { 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'} - scons: done reading SConscript files. - scons: Building targets ... - scons: `.' is up to date. - scons: done building targets. - </screen> + <scons_output example="Dump_ENV" os="posix"> + <scons_output_command>scons</scons_output_command> + </scons_output> <para> @@ -504,17 +338,9 @@ </para> - <screen> - C:\><userinput>scons</userinput> - scons: Reading SConscript files ... - { 'PATH': 'C:\\WINDOWS\\System32', - 'PATHEXT': '.COM;.EXE;.BAT;.CMD', - 'SystemRoot': 'C:\\WINDOWS'} - scons: done reading SConscript files. - scons: Building targets ... - scons: `.' is up to date. - scons: done building targets. - </screen> + <scons_output example="Dump_ENV" os="win32"> + <scons_output_command>scons</scons_output_command> + </scons_output> </section> @@ -542,10 +368,24 @@ </para> - <programlisting> + <scons_example name="tree1"> + <file name="SConstruct" printme="1"> env = Environment(CPPPATH = ['.']) env.Program('prog', ['f1.c', 'f2.c', 'f3.c']) - </programlisting> + </file> + <file name="f1.c"> + #include "inc.h" + </file> + <file name="f2.c"> + #include "inc.h" + </file> + <file name="f3.c"> + #include "inc.h" + </file> + <file name="inc.h"> + inc.h + </file> + </scons_example> <para> @@ -554,38 +394,9 @@ </para> - <screen> - % <userinput>scons -Q --tree=all</userinput> - cc -o f1.o -c -I. f1.c - cc -o f2.o -c -I. f2.c - cc -o f3.o -c -I. f3.c - cc -o prog f1.o f2.o f3.o - +-. - +-SConstruct - +-f1.c - +-f1.o - | +-f1.c - | +-inc.h - +-f2.c - +-f2.o - | +-f2.c - | +-inc.h - +-f3.c - +-f3.o - | +-f3.c - | +-inc.h - +-inc.h - +-prog - +-f1.o - | +-f1.c - | +-inc.h - +-f2.o - | +-f2.c - | +-inc.h - +-f3.o - +-f3.c - +-inc.h - </screen> + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=all</scons_output_command> + </scons_output> <para> @@ -609,13 +420,9 @@ </para> - <screen> - % <userinput>scons -Q --tree=all f2.o</userinput> - cc -o f2.o -c -I. f2.c - +-f2.o - +-f2.c - +-inc.h - </screen> + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=all f2.o</scons_output_command> + </scons_output> <para> @@ -629,17 +436,9 @@ </para> - <screen> - % <userinput>scons -Q --tree=all f1.o f3.o</userinput> - cc -o f1.o -c -I. f1.c - +-f1.o - +-f1.c - +-inc.h - cc -o f3.o -c -I. f3.c - +-f3.o - +-f3.c - +-inc.h - </screen> + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=all f1.o f3.o</scons_output_command> + </scons_output> <para> @@ -649,49 +448,9 @@ </para> - <screen> - % <userinput>scons -Q --tree=status</userinput> - cc -o f1.o -c -I. f1.c - cc -o f2.o -c -I. f2.c - cc -o f3.o -c -I. f3.c - cc -o prog f1.o f2.o f3.o - E = exists - R = exists in repository only - b = implicit builder - B = explicit builder - S = side effect - P = precious - A = always build - C = current - N = no clean - H = no cache - - [E b ]+-. - [E C ] +-SConstruct - [E C ] +-f1.c - [E B C ] +-f1.o - [E C ] | +-f1.c - [E C ] | +-inc.h - [E C ] +-f2.c - [E B C ] +-f2.o - [E C ] | +-f2.c - [E C ] | +-inc.h - [E C ] +-f3.c - [E B C ] +-f3.o - [E C ] | +-f3.c - [E C ] | +-inc.h - [E C ] +-inc.h - [E B C ] +-prog - [E B C ] +-f1.o - [E C ] | +-f1.c - [E C ] | +-inc.h - [E B C ] +-f2.o - [E C ] | +-f2.c - [E C ] | +-inc.h - [E B C ] +-f3.o - [E C ] +-f3.c - [E C ] +-inc.h - </screen> + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=status</scons_output_command> + </scons_output> <para> @@ -707,21 +466,9 @@ </para> - <screen> - % <userinput>scons -Q --tree=derived</userinput> - cc -o f1.o -c -I. f1.c - cc -o f2.o -c -I. f2.c - cc -o f3.o -c -I. f3.c - cc -o prog f1.o f2.o f3.o - +-. - +-f1.o - +-f2.o - +-f3.o - +-prog - +-f1.o - +-f2.o - +-f3.o - </screen> + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=derived</scons_output_command> + </scons_output> <para> @@ -730,32 +477,9 @@ </para> - <screen> - % <userinput>scons -Q --tree=derived,status</userinput> - cc -o f1.o -c -I. f1.c - cc -o f2.o -c -I. f2.c - cc -o f3.o -c -I. f3.c - cc -o prog f1.o f2.o f3.o - E = exists - R = exists in repository only - b = implicit builder - B = explicit builder - S = side effect - P = precious - A = always build - C = current - N = no clean - H = no cache - - [E b ]+-. - [E B C ] +-f1.o - [E B C ] +-f2.o - [E B C ] +-f3.o - [E B C ] +-prog - [E B C ] +-f1.o - [E B C ] +-f2.o - [E B C ] +-f3.o - </screen> + <scons_output example="tree1"> + <scons_output_command>scons -Q --tree=derived,status</scons_output_command> + </scons_output> <para> @@ -776,14 +500,34 @@ </para> - <programlisting> + <scons_example name="tree2"> + <file name="SConstruct" printme="1"> env = Environment(CPPPATH = ['.'], LIBS = ['foo'], LIBPATH = ['.']) env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) env.Program('prog1.c') env.Program('prog2.c') - </programlisting> + </file> + <file name="prog1.c"> + #include "inc.h" + </file> + <file name="prog2.c"> + #include "inc.h" + </file> + <file name="f1.c"> + #include "inc.h" + </file> + <file name="f2.c"> + #include "inc.h" + </file> + <file name="f3.c"> + #include "inc.h" + </file> + <file name="inc.h"> + inc.h + </file> + </scons_example> <para> @@ -792,79 +536,9 @@ </para> - <screen> - % <userinput>scons -Q --tree=all</userinput> - cc -o f1.o -c -I. f1.c - cc -o f2.o -c -I. f2.c - cc -o f3.o -c -I. f3.c - ar rc libfoo.a f1.o f2.o f3.o - ranlib libfoo.a - cc -o prog1.o -c -I. prog1.c - cc -o prog1 prog1.o -L. -lfoo - cc -o prog2.o -c -I. prog2.c - cc -o prog2 prog2.o -L. -lfoo - +-. - +-SConstruct - +-f1.c - +-f1.o - | +-f1.c - | +-inc.h - +-f2.c - +-f2.o - | +-f2.c - | +-inc.h - +-f3.c - +-f3.o - | +-f3.c - | +-inc.h - +-inc.h - +-libfoo.a - | +-f1.o - | | +-f1.c - | | +-inc.h - | +-f2.o - | | +-f2.c - | | +-inc.h - | +-f3.o - | +-f3.c - | +-inc.h - +-prog1 - | +-prog1.o - | | +-prog1.c - | | +-inc.h - | +-libfoo.a - | +-f1.o - | | +-f1.c - | | +-inc.h - | +-f2.o - | | +-f2.c - | | +-inc.h - | +-f3.o - | +-f3.c - | +-inc.h - +-prog1.c - +-prog1.o - | +-prog1.c - | +-inc.h - +-prog2 - | +-prog2.o - | | +-prog2.c - | | +-inc.h - | +-libfoo.a - | +-f1.o - | | +-f1.c - | | +-inc.h - | +-f2.o - | | +-f2.c - | | +-inc.h - | +-f3.o - | +-f3.c - | +-inc.h - +-prog2.c - +-prog2.o - +-prog2.c - +-inc.h - </screen> + <scons_output example="tree2"> + <scons_output_command>scons -Q --tree=all</scons_output_command> + </scons_output> <para> @@ -884,51 +558,9 @@ </para> - <screen> - % <userinput>scons -Q --tree=prune</userinput> - cc -o f1.o -c -I. f1.c - cc -o f2.o -c -I. f2.c - cc -o f3.o -c -I. f3.c - ar rc libfoo.a f1.o f2.o f3.o - ranlib libfoo.a - cc -o prog1.o -c -I. prog1.c - cc -o prog1 prog1.o -L. -lfoo - cc -o prog2.o -c -I. prog2.c - cc -o prog2 prog2.o -L. -lfoo - +-. - +-SConstruct - +-f1.c - +-f1.o - | +-f1.c - | +-inc.h - +-f2.c - +-f2.o - | +-f2.c - | +-inc.h - +-f3.c - +-f3.o - | +-f3.c - | +-inc.h - +-inc.h - +-libfoo.a - | +-[f1.o] - | +-[f2.o] - | +-[f3.o] - +-prog1 - | +-prog1.o - | | +-prog1.c - | | +-inc.h - | +-[libfoo.a] - +-prog1.c - +-[prog1.o] - +-prog2 - | +-prog2.o - | | +-prog2.c - | | +-inc.h - | +-[libfoo.a] - +-prog2.c - +-[prog2.o] - </screen> + <scons_output example="tree2"> + <scons_output_command>scons -Q --tree=prune</scons_output_command> + </scons_output> <para> @@ -954,7 +586,15 @@ </para> - + <scons_example name="presub"> + <file name="SConstruct"> + env = Environment(CPPPATH = ['.']) + env.Program('prog', 'prog.c') + </file> + <file name="prog.c"> + prog.c + </file> + </scons_example> <!-- @@ -994,10 +634,21 @@ </para> - <programlisting> + <scons_example name="findlibs"> + <file name="SConstruct" printme="1"> env = Environment(LIBPATH = ['libs1', 'libs2']) env.Program('prog.c', LIBS=['foo', 'bar']) - </programlisting> + </file> + <file name="prog.c"> + prog.c + </file> + <file name="libs1/libfoo.a"> + libs1/libfoo.a + </file> + <file name="libs2/libbar.a"> + libs2/libbar.a + </file> + </scons_example> <para> @@ -1009,20 +660,9 @@ </para> - <screen> - % <userinput>scons -Q --debug=findlibs</userinput> - findlibs: looking for 'libfoo.a' in 'libs1' ... - findlibs: ... FOUND 'libfoo.a' in 'libs1' - findlibs: looking for 'libfoo.so' in 'libs1' ... - findlibs: looking for 'libfoo.so' in 'libs2' ... - findlibs: looking for 'libbar.a' in 'libs1' ... - findlibs: looking for 'libbar.a' in 'libs2' ... - findlibs: ... FOUND 'libbar.a' in 'libs2' - findlibs: looking for 'libbar.so' in 'libs1' ... - findlibs: looking for 'libbar.so' in 'libs2' ... - cc -o prog.o -c prog.c - cc -o prog prog.o -Llibs1 -Llibs2 -lfoo -lbar - </screen> + <scons_output example="findlibs"> + <scons_output_command>scons -Q --debug=findlibs</scons_output_command> + </scons_output> </section> @@ -1086,9 +726,11 @@ </para> - <programlisting> + <scons_example name="stacktrace"> + <file name="SConstruct" printme="1"> Program('prog.c') - </programlisting> + </file> + </scons_example> <para> @@ -1098,10 +740,9 @@ </para> - <screen> - % <userinput>scons -Q</userinput> - scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. - </screen> + <scons_output example="stacktrace"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> <para> @@ -1116,19 +757,9 @@ </para> - <screen> - % <userinput>scons -Q --debug=stacktrace</userinput> - scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. - scons: internal stack trace: - File "bootstrap/src/engine/SCons/Job.py", line 199, in start - task.prepare() - File "bootstrap/src/engine/SCons/Script/Main.py", line 168, in prepare - return SCons.Taskmaster.OutOfDateTask.prepare(self) - File "bootstrap/src/engine/SCons/Taskmaster.py", line 189, in prepare - executor.prepare() - File "bootstrap/src/engine/SCons/Executor.py", line 392, in prepare - raise SCons.Errors.StopError(msg % (s, self.batches[0].targets[0])) - </screen> + <scons_output example="stacktrace"> + <scons_output_command>scons -Q --debug=stacktrace</scons_output_command> + </scons_output> <para> @@ -1175,74 +806,23 @@ </para> - <programlisting> + <scons_example name="taskmastertrace"> + <file name="SConstruct" printme="1"> env = Environment(CPPPATH = ['.']) env.Program('prog.c') - </programlisting> + </file> + <file name="prog.c"> + #include "inc.h" + prog.c + </file> + <file name="inc.h"> + #define STRING "one" + </file> + </scons_example> - <screen> - % <userinput>scons -Q --taskmastertrace=- prog</userinput> - - Taskmaster: Looking for a node to evaluate - Taskmaster: Considering node <no_state 0 'prog'> and its children: - Taskmaster: <no_state 0 'prog.o'> - Taskmaster: adjusted ref count: <pending 1 'prog'>, child 'prog.o' - Taskmaster: Considering node <no_state 0 'prog.o'> and its children: - Taskmaster: <no_state 0 'prog.c'> - Taskmaster: <no_state 0 'inc.h'> - Taskmaster: adjusted ref count: <pending 1 'prog.o'>, child 'prog.c' - Taskmaster: adjusted ref count: <pending 2 'prog.o'>, child 'inc.h' - Taskmaster: Considering node <no_state 0 'prog.c'> and its children: - Taskmaster: Evaluating <pending 0 'prog.c'> - - Task.make_ready_current(): node <pending 0 'prog.c'> - Task.prepare(): node <up_to_date 0 'prog.c'> - Task.executed_with_callbacks(): node <up_to_date 0 'prog.c'> - Task.postprocess(): node <up_to_date 0 'prog.c'> - Task.postprocess(): removing <up_to_date 0 'prog.c'> - Task.postprocess(): adjusted parent ref count <pending 1 'prog.o'> - - Taskmaster: Looking for a node to evaluate - Taskmaster: Considering node <no_state 0 'inc.h'> and its children: - Taskmaster: Evaluating <pending 0 'inc.h'> - - Task.make_ready_current(): node <pending 0 'inc.h'> - Task.prepare(): node <up_to_date 0 'inc.h'> - Task.executed_with_callbacks(): node <up_to_date 0 'inc.h'> - Task.postprocess(): node <up_to_date 0 'inc.h'> - Task.postprocess(): removing <up_to_date 0 'inc.h'> - Task.postprocess(): adjusted parent ref count <pending 0 'prog.o'> - - Taskmaster: Looking for a node to evaluate - Taskmaster: Considering node <pending 0 'prog.o'> and its children: - Taskmaster: <up_to_date 0 'prog.c'> - Taskmaster: <up_to_date 0 'inc.h'> - Taskmaster: Evaluating <pending 0 'prog.o'> - - Task.make_ready_current(): node <pending 0 'prog.o'> - Task.prepare(): node <executing 0 'prog.o'> - Task.execute(): node <executing 0 'prog.o'> - cc -o prog.o -c -I. prog.c - Task.executed_with_callbacks(): node <executing 0 'prog.o'> - Task.postprocess(): node <executed 0 'prog.o'> - Task.postprocess(): removing <executed 0 'prog.o'> - Task.postprocess(): adjusted parent ref count <pending 0 'prog'> - - Taskmaster: Looking for a node to evaluate - Taskmaster: Considering node <pending 0 'prog'> and its children: - Taskmaster: <executed 0 'prog.o'> - Taskmaster: Evaluating <pending 0 'prog'> - - Task.make_ready_current(): node <pending 0 'prog'> - Task.prepare(): node <executing 0 'prog'> - Task.execute(): node <executing 0 'prog'> - cc -o prog prog.o - Task.executed_with_callbacks(): node <executing 0 'prog'> - Task.postprocess(): node <executed 0 'prog'> - - Taskmaster: Looking for a node to evaluate - Taskmaster: No candidate anymore. - </screen> + <scons_output example="taskmastertrace" os="posix"> + <scons_output_command>scons -Q --taskmastertrace=- prog</scons_output_command> + </scons_output> <para> diff --git a/doc/user/variables.in b/doc/user/variables.in deleted file mode 100644 index 7009996..0000000 --- a/doc/user/variables.in +++ /dev/null @@ -1,56 +0,0 @@ -<!-- - - __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> - -This appendix contains descriptions of all of the -construction variables that are <emphasis>potentially</emphasis> -available "out of the box" in this version of SCons. -Whether or not setting a construction variable -in a construction environment -will actually have an effect depends on -whether any of the Tools and/or Builders -that use the variable have been -included in the construction environment. - -</para> - -<para> - -In this appendix, we have -appended the initial <envar>$</envar> -(dollar sign) to the beginning of each -variable name when it appears in the text, -but left off the dollar sign -in the left-hand column -where the name appears for each entry. - -</para> - -<variablelist> - -&variables-gen; - -</variablelist> diff --git a/doc/user/variants.in b/doc/user/variants.in deleted file mode 100644 index 9980b1d..0000000 --- a/doc/user/variants.in +++ /dev/null @@ -1,151 +0,0 @@ -<!-- - - __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. - ---> - -<!-- - -=head1 Variant builds - -=head2 Variations on a theme - -Other variations of this model are possible. For example, you might decide -that you want to separate out your include files into platform dependent and -platform independent files. In this case, you'd have to define an -alternative to C<$INCLUDE> for platform-dependent files. Most F<Conscript> -files, generating purely platform-independent include files, would not have -to change. - -You might also want to be able to compile your whole system with debugging -or profiling, for example, enabled. You could do this with appropriate -command line options, such as C<DEBUG=on>. This would then be translated -into the appropriate platform-specific requirements to enable debugging -(this might include turning off optimization, for example). You could -optionally vary the name space for these different types of systems, but, as -we'll see in the next section, it's not B<essential> to do this, since Cons -is pretty smart about rebuilding things when you change options. - ---> - - <para> - - The &variant_dir; keyword argument of - the &SConscript; function provides everything - we need to show how easy it is to create - variant builds using &SCons;. - Suppose, for example, that we want to - build a program for both Windows and Linux platforms, - but that we want to build it in a shared directory - with separate side-by-side build directories - for the Windows and Linux versions of the program. - - </para> - - <scons_example name="ex_variants"> - <file name="SConstruct" printme="1"> - platform = ARGUMENTS.get('OS', Platform()) - - include = "#export/$PLATFORM/include" - lib = "#export/$PLATFORM/lib" - bin = "#export/$PLATFORM/bin" - - env = Environment(PLATFORM = platform, - BINDIR = bin, - INCDIR = include, - LIBDIR = lib, - CPPPATH = [include], - LIBPATH = [lib], - LIBS = 'world') - - Export('env') - - env.SConscript('src/SConscript', variant_dir='build/$PLATFORM') - </file> - <directory name="src"></directory> - <directory name="src/hello"></directory> - <directory name="src/world"></directory> - <file name="src/SConscript"> - Import('env') - SConscript('hello/SConscript') - SConscript('world/SConscript') - </file> - <file name="src/hello/SConscript"> - Import('env') - hello = env.Program('hello.c') - env.Install('$BINDIR', hello) - </file> - <file name="src/hello/hello.c"> - #include "world.h" - int main(int argc, char *argv[]) { printf "hello.c\n"; world(); } - </file> - <file name="src/world/SConscript"> - Import('env') - world = env.Library('world.c') - env.Install('$LIBDIR', world) - env.Install('$INCDIR', 'world.h') - </file> - <file name="src/world/world.h"> - #define STRING "world.h" - extern int world(); - </file> - <file name="src/world/world.c"> - int world() { printf "world.c\n"; } - </file> - </scons_example> - - <para> - - This SConstruct file, - when run on a Linux system, yields: - - </para> - - <scons_output example="ex_variants" os="posix"> - <scons_output_command>scons -Q OS=linux</scons_output_command> - </scons_output> - - <para> - - The same SConstruct file on Windows would build: - - </para> - - <scons_output example="ex_variants" os="win32"> - <scons_output_command>scons -Q OS=windows</scons_output_command> - </scons_output> - - <!-- - - <scons_example name="ex_var2"> - <file name="SConstruct" printme="1"> - env = Environment(OS = ARGUMENTS.get('OS')) - for os in ['newell', 'post']: - SConscript('src/SConscript', variant_dir='build/' + os) - </file> - </scons_example> - - <scons_output example="ex_var2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - --> diff --git a/doc/user/variants.xml b/doc/user/variants.xml index 29d2d65..9980b1d 100644 --- a/doc/user/variants.xml +++ b/doc/user/variants.xml @@ -61,7 +61,8 @@ is pretty smart about rebuilding things when you change options. </para> - <programlisting> + <scons_example name="ex_variants"> + <file name="SConstruct" printme="1"> platform = ARGUMENTS.get('OS', Platform()) include = "#export/$PLATFORM/include" @@ -79,7 +80,38 @@ is pretty smart about rebuilding things when you change options. Export('env') env.SConscript('src/SConscript', variant_dir='build/$PLATFORM') - </programlisting> + </file> + <directory name="src"></directory> + <directory name="src/hello"></directory> + <directory name="src/world"></directory> + <file name="src/SConscript"> + Import('env') + SConscript('hello/SConscript') + SConscript('world/SConscript') + </file> + <file name="src/hello/SConscript"> + Import('env') + hello = env.Program('hello.c') + env.Install('$BINDIR', hello) + </file> + <file name="src/hello/hello.c"> + #include "world.h" + int main(int argc, char *argv[]) { printf "hello.c\n"; world(); } + </file> + <file name="src/world/SConscript"> + Import('env') + world = env.Library('world.c') + env.Install('$LIBDIR', world) + env.Install('$INCDIR', 'world.h') + </file> + <file name="src/world/world.h"> + #define STRING "world.h" + extern int world(); + </file> + <file name="src/world/world.c"> + int world() { printf "world.c\n"; } + </file> + </scons_example> <para> @@ -88,17 +120,9 @@ is pretty smart about rebuilding things when you change options. </para> - <screen> - % <userinput>scons -Q OS=linux</userinput> - Install file: "build/linux/world/world.h" as "export/linux/include/world.h" - cc -o build/linux/hello/hello.o -c -Iexport/linux/include build/linux/hello/hello.c - cc -o build/linux/world/world.o -c -Iexport/linux/include build/linux/world/world.c - ar rc build/linux/world/libworld.a build/linux/world/world.o - ranlib build/linux/world/libworld.a - Install file: "build/linux/world/libworld.a" as "export/linux/lib/libworld.a" - cc -o build/linux/hello/hello build/linux/hello/hello.o -Lexport/linux/lib -lworld - Install file: "build/linux/hello/hello" as "export/linux/bin/hello" - </screen> + <scons_output example="ex_variants" os="posix"> + <scons_output_command>scons -Q OS=linux</scons_output_command> + </scons_output> <para> @@ -106,17 +130,9 @@ is pretty smart about rebuilding things when you change options. </para> - <screen> - C:\><userinput>scons -Q OS=windows</userinput> - Install file: "build/windows/world/world.h" as "export/windows/include/world.h" - cl /Fobuild\windows\hello\hello.obj /c build\windows\hello\hello.c /nologo /Iexport\windows\include - cl /Fobuild\windows\world\world.obj /c build\windows\world\world.c /nologo /Iexport\windows\include - lib /nologo /OUT:build\windows\world\world.lib build\windows\world\world.obj - Install file: "build/windows/world/world.lib" as "export/windows/lib/world.lib" - link /nologo /OUT:build\windows\hello\hello.exe /LIBPATH:export\windows\lib world.lib build\windows\hello\hello.obj - embedManifestExeCheck(target, source, env) - Install file: "build/windows/hello/hello.exe" as "export/windows/bin/hello.exe" - </screen> + <scons_output example="ex_variants" os="win32"> + <scons_output_command>scons -Q OS=windows</scons_output_command> + </scons_output> <!-- |