summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDirk Baechle <dl9obn@darc.de>2013-05-03 22:08:59 (GMT)
committerDirk Baechle <dl9obn@darc.de>2013-05-03 22:08:59 (GMT)
commit9e7cf970a730549348fd22a0921ea0ed2e894a69 (patch)
tree0bbe0e399fa2f8bb9328c012c5931e0172ea4547
parente3827a98511acc0d208193920bc40d5e2724bf12 (diff)
downloadSCons-9e7cf970a730549348fd22a0921ea0ed2e894a69.zip
SCons-9e7cf970a730549348fd22a0921ea0ed2e894a69.tar.gz
SCons-9e7cf970a730549348fd22a0921ea0ed2e894a69.tar.bz2
- removed *.in files from the user guide
-rw-r--r--doc/user/actions.in404
-rw-r--r--doc/user/actions.xml8
-rw-r--r--doc/user/add-method.in127
-rw-r--r--doc/user/add-method.xml51
-rw-r--r--doc/user/alias.in102
-rw-r--r--doc/user/alias.xml74
-rw-r--r--doc/user/ant.in52
-rw-r--r--doc/user/build-install.in709
-rw-r--r--doc/user/builders-built-in.in950
-rw-r--r--doc/user/builders-built-in.xml105
-rw-r--r--doc/user/builders-commands.in156
-rw-r--r--doc/user/builders-commands.xml40
-rw-r--r--doc/user/builders-writing.in1108
-rw-r--r--doc/user/builders-writing.xml284
-rw-r--r--doc/user/builders.in57
-rw-r--r--doc/user/caching.in502
-rw-r--r--doc/user/caching.xml144
-rw-r--r--doc/user/command-line.in2345
-rw-r--r--doc/user/command-line.xml824
-rw-r--r--doc/user/copyright.in32
-rw-r--r--doc/user/depends.in1872
-rw-r--r--doc/user/depends.xml536
-rw-r--r--doc/user/environments.in1752
-rw-r--r--doc/user/environments.xml392
-rw-r--r--doc/user/errors.in41
-rw-r--r--doc/user/example.in41
-rw-r--r--doc/user/factories.in507
-rw-r--r--doc/user/factories.xml209
-rw-r--r--doc/user/file-removal.in223
-rw-r--r--doc/user/file-removal.xml91
-rw-r--r--doc/user/functions.in38
-rw-r--r--doc/user/gettext.in351
-rw-r--r--doc/user/gettext.xml51
-rw-r--r--doc/user/hierarchy.in794
-rw-r--r--doc/user/hierarchy.xml214
-rw-r--r--doc/user/install.in247
-rw-r--r--doc/user/install.xml136
-rw-r--r--doc/user/java.in657
-rw-r--r--doc/user/java.xml366
-rw-r--r--doc/user/less-simple.in623
-rw-r--r--doc/user/less-simple.xml171
-rw-r--r--doc/user/libraries.in445
-rw-r--r--doc/user/libraries.xml193
-rw-r--r--doc/user/main.in411
-rw-r--r--doc/user/make.in121
-rw-r--r--doc/user/mergeflags.in137
-rw-r--r--doc/user/mergeflags.xml45
-rw-r--r--doc/user/misc.in606
-rw-r--r--doc/user/misc.xml221
-rw-r--r--doc/user/nodes.in431
-rw-r--r--doc/user/nodes.xml117
-rw-r--r--doc/user/output.in681
-rw-r--r--doc/user/output.xml138
-rw-r--r--doc/user/parseconfig.in140
-rw-r--r--doc/user/parseconfig.xml12
-rw-r--r--doc/user/parseflags.in176
-rw-r--r--doc/user/parseflags.xml92
-rw-r--r--doc/user/preface.in426
-rw-r--r--doc/user/python.in154
-rw-r--r--doc/user/repositories.in641
-rw-r--r--doc/user/repositories.xml160
-rw-r--r--doc/user/run.in375
-rw-r--r--doc/user/scanners.in392
-rw-r--r--doc/user/scanners.xml26
-rw-r--r--doc/user/sconf.in486
-rw-r--r--doc/user/sconf.xml54
-rw-r--r--doc/user/separate.in540
-rw-r--r--doc/user/separate.xml150
-rw-r--r--doc/user/sideeffect.in216
-rw-r--r--doc/user/sideeffect.xml37
-rw-r--r--doc/user/simple.in517
-rw-r--r--doc/user/simple.xml194
-rw-r--r--doc/user/sourcecode.in162
-rw-r--r--doc/user/sourcecode.xml71
-rw-r--r--doc/user/tasks.in146
-rw-r--r--doc/user/tasks.xml39
-rw-r--r--doc/user/tools.in38
-rw-r--r--doc/user/troubleshoot.in914
-rw-r--r--doc/user/troubleshoot.xml798
-rw-r--r--doc/user/variables.in56
-rw-r--r--doc/user/variants.in151
-rw-r--r--doc/user/variants.xml64
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 &lt; $SOURCE &gt; $TARGET')
- </sconstruct>
-
- <para>
-
- Is equivalent to:
-
- </para>
-
- <sconstruct>
- b = Builder(action = Action('build &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $TARGET')
- </programlisting>
+ </sconstruct>
<para>
@@ -254,9 +254,9 @@ solutions to the above limitations.
</para>
- <programlisting>
+ <sconstruct>
b = Builder(action = Action('build &lt; $SOURCE &gt; $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 &target; 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 &target;,
- 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 &target; 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 &target;,
- 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 &target; 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 &target;,
- 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 &target; 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 &target;,
- 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 &target; 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 &target;,
- 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/' &lt; $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/' &lt; $SOURCE &gt; $TARGET")
- </programlisting>
+ env.Command('foo.out', 'foo.in', "sed 's/x/y/' &lt; $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/' &lt; foo.in &gt; 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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; %s &gt; %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 &lt; %s &gt; %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 &lt; %s &gt; %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 &gt; $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 &gt; $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" &gt; $TARGET',
- 'cat $SOURCE &gt;&gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; file.input &gt; 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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; file.input &gt; 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 &lt; $SOURCE &gt; $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 &lt; $SOURCE &gt; $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 &lt; file1.input &gt; file1.foo
- foobuild &lt; file2.input &gt; 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 &lt; %s &gt; %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 &lt; %s &gt; %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 &lt; %s &gt; %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 &lt; file.input &gt; 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 &gt; $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 &gt; $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 &gt; file1.foo
- my_command file2.input modify2.in &gt; 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" &gt; $TARGET',
'cat $SOURCE &gt;&gt; $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 &map; 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 &lt;module&gt;
- </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 &lt;module&gt;
- </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 &lt;module&gt;
- % <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 &lt;module&gt;
- % <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 &lt;module&gt;
- </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 &lt;module&gt;
- </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 &lt;module&gt;
- </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 &target;.
- 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 &target; 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 &target; 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 &lt;hello.h&gt;
- 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 &lt;foo.h&gt;
- #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 &lt;foo.h&gt;
- #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 &lt;foo.h&gt;
- #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 =&gt; 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 &lt;hello.h&gt;
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 &lt;foo.h&gt;
#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 &lt;foo.h&gt;
+ #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 &lt;foo.h&gt;
+ #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&lt;-' )
- </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&lt;-' )
- </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}&lt;-' )
- </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) &gt; 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( '-&gt;$MISSING&lt;-' )
- </programlisting>
+ print "value is:", env.subst( '->$MISSING&lt;-' )
+ </file>
+ </scons_example>
- <screen>
- % <userinput>scons -Q</userinput>
- value is: -&gt;&lt;-
- 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( '-&gt;$MISSING&lt;-' )
- </programlisting>
+ print "value is:", env.subst( '->$MISSING&lt;-' )
+ </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 &lt;module&gt;
- </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( '-&gt;${1 / 0}&lt;-' )
- </programlisting>
+ print "value is:", env.subst( '->${1 / 0}&lt;-' )
+ </file>
+ </scons_example>
- <screen>
- % <userinput>scons -Q</userinput>
- value is: -&gt;&lt;-
- 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 &lt;module&gt;
- </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 &lt;stdio.h&gt;
- 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 &lt;stdio.h&gt;
- #include &lt;libintl.h&gt;
- #include &lt;locale.h&gt;
- 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 &lt;stdio.h&gt;
- #include &lt;libintl.h&gt;
- #include &lt;locale.h&gt;
- 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 &lt;stdio.h&gt;
- #include &lt;libintl.h&gt;
- #include &lt;locale.h&gt;
- 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 &lt;stdio.h&gt;
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 &lt;stdio.h&gt;
#include &lt;libintl.h&gt;
@@ -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 &lt;stdio.h&gt;
#include &lt;libintl.h&gt;
@@ -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 &lt;stdio.h&gt;
#include &lt;libintl.h&gt;
@@ -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 &plus; 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>
- &copyright;
- </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
- &lt;class 'SCons.Node.FS.File'&gt; 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 &gt;$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 &gt;$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 &gt;$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 &gt; 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 &amp;lt;file.h&amp;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 &lt;file.h&gt;</literal>.
+ to <literal>#include &amp;lt;file.h&amp;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 &lt; $SOURCES &gt; $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 &lt; $SOURCES &gt; $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 &amp;lt;sys/types.h&amp;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 &amp;lt;mylib.h&amp;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 &amp;lt;mylib.h&amp;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 &lt;sys/types.h&gt;\n'):
+ if not conf.CheckType('off_t', '#include &amp;lt;sys/types.h&amp;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 &lt;mylib.h&gt;
+ #include &amp;lt;mylib.h&amp;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 &lt;mylib.h&gt;
+ #include &amp;lt;mylib.h&amp;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 &gt;$TARGET data1')
+ f1 = env.Command('file1.out', [], 'echo >$TARGET data1')
env.SideEffect('not_really_updated', f1)
- f2 = env.Command('file2.out', [], 'echo &gt;$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 &gt; file1.out data1
- echo &gt; 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 &lt; $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 &lt; $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 &lt; $SOURCE &gt; $TARGET',
+ {'Copy1' : Builder(action = 'cat &lt; $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 &lt; $SOURCE &gt; $TARGET',
+ {'Copy2' : Builder(action = 'cat &lt; $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 &lt; foo.bar2 &gt; foo.cpp
- cc -o app2 main2.cpp foo.cpp
- cat &lt; test.bar &gt; 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 &lt;hello.h&gt;
- file1.c
- </file>
- <file name="file2.c">
- file2.c
- </file>
- <file name="file3.c">
- #include &lt;hello.h&gt;
- 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 &lt;hello.h&gt;
+ file1.c
+ </file>
+ <file name="file2.c">
+ file2.c
+ </file>
+ <file name="file3.c">
+ #include &lt;hello.h&gt;
+ 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': &lt;function InstallBuilderWrapper at 0x700000&gt;, '_InternalInstallAs': &lt;function InstallAsBuilderWrapper at 0x700000&gt;},
- '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': &lt;SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;,
- 'Dirs': &lt;SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;,
- 'ENV': { 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'},
- 'ESCAPE': &lt;function escape at 0x700000&gt;,
- 'File': &lt;SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;,
- 'HOST_ARCH': None,
- 'HOST_OS': None,
- 'IDLSUFFIXES': ['.idl', '.IDL'],
- 'INSTALL': &lt;function copyFunc at 0x700000&gt;,
- 'LIBPREFIX': 'lib',
- 'LIBPREFIXES': ['$LIBPREFIX'],
- 'LIBSUFFIX': '.a',
- 'LIBSUFFIXES': ['$LIBSUFFIX', '$SHLIBSUFFIX'],
- 'MAXLINELENGTH': 128072,
- 'OBJPREFIX': '',
- 'OBJSUFFIX': '.o',
- 'PLATFORM': 'posix',
- 'PROGPREFIX': '',
- 'PROGSUFFIX': '',
- 'PSPAWN': &lt;function piped_env_spawn at 0x700000&gt;,
- 'RDirs': &lt;SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;,
- 'SCANNERS': [],
- 'SHELL': 'sh',
- 'SHLIBPREFIX': '$LIBPREFIX',
- 'SHLIBSUFFIX': '.so',
- 'SHOBJPREFIX': '$OBJPREFIX',
- 'SHOBJSUFFIX': '$OBJSUFFIX',
- 'SPAWN': &lt;function spawnvpe_spawn at 0x700000&gt;,
- 'TARGET_ARCH': None,
- 'TARGET_OS': None,
- 'TEMPFILE': &lt;class 'SCons.Platform.TempFileMunge'&gt;,
- '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': &lt;function _concat at 0x700000&gt;,
- '_defines': &lt;function _defines at 0x700000&gt;,
- '_stripixes': &lt;function _stripixes at 0x700000&gt;}
- 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': &lt;function InstallBuilderWrapper at 0x700000&gt;, 'Object': &lt;SCons.Builder.CompositeBuilder object at 0x700000&gt;, 'PCH': &lt;SCons.Builder.BuilderBase object at 0x700000&gt;, 'RES': &lt;SCons.Builder.BuilderBase object at 0x700000&gt;, 'SharedObject': &lt;SCons.Builder.CompositeBuilder object at 0x700000&gt;, 'StaticObject': &lt;SCons.Builder.CompositeBuilder object at 0x700000&gt;, '_InternalInstallAs': &lt;function InstallAsBuilderWrapper at 0x700000&gt;},
- 'CC': 'cl',
- 'CCCOM': &lt;SCons.Action.FunctionAction object at 0x700000&gt;,
- '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': &lt;SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;,
- 'Dirs': &lt;SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;,
- 'ENV': { 'PATH': 'C:\\WINDOWS\\System32',
- 'PATHEXT': '.COM;.EXE;.BAT;.CMD',
- 'SystemRoot': 'C:\\WINDOWS'},
- 'ESCAPE': &lt;function escape at 0x700000&gt;,
- 'File': &lt;SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;,
- 'HOST_ARCH': '',
- 'HOST_OS': 'win32',
- 'IDLSUFFIXES': ['.idl', '.IDL'],
- 'INCPREFIX': '/I',
- 'INCSUFFIX': '',
- 'INSTALL': &lt;function copyFunc at 0x700000&gt;,
- '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': &lt;function piped_spawn at 0x700000&gt;,
- 'RC': 'rc',
- 'RCCOM': &lt;SCons.Action.FunctionAction object at 0x700000&gt;,
- 'RCFLAGS': [],
- 'RCSUFFIXES': ['.rc', '.rc2'],
- 'RDirs': &lt;SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;,
- 'SCANNERS': [],
- 'SHCC': '$CC',
- 'SHCCCOM': &lt;SCons.Action.FunctionAction object at 0x700000&gt;,
- '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': &lt;function spawn at 0x700000&gt;,
- 'STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME': 1,
- 'TARGET_ARCH': '',
- 'TARGET_OS': 'win32',
- 'TEMPFILE': &lt;class 'SCons.Platform.TempFileMunge'&gt;,
- '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': &lt;function msvc_output_flag at 0x700000&gt;,
- '_concat': &lt;function _concat at 0x700000&gt;,
- '_defines': &lt;function _defines at 0x700000&gt;,
- '_stripixes': &lt;function _stripixes at 0x700000&gt;}
- 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 &lt;no_state 0 'prog'&gt; and its children:
- Taskmaster: &lt;no_state 0 'prog.o'&gt;
- Taskmaster: adjusted ref count: &lt;pending 1 'prog'&gt;, child 'prog.o'
- Taskmaster: Considering node &lt;no_state 0 'prog.o'&gt; and its children:
- Taskmaster: &lt;no_state 0 'prog.c'&gt;
- Taskmaster: &lt;no_state 0 'inc.h'&gt;
- Taskmaster: adjusted ref count: &lt;pending 1 'prog.o'&gt;, child 'prog.c'
- Taskmaster: adjusted ref count: &lt;pending 2 'prog.o'&gt;, child 'inc.h'
- Taskmaster: Considering node &lt;no_state 0 'prog.c'&gt; and its children:
- Taskmaster: Evaluating &lt;pending 0 'prog.c'&gt;
-
- Task.make_ready_current(): node &lt;pending 0 'prog.c'&gt;
- Task.prepare(): node &lt;up_to_date 0 'prog.c'&gt;
- Task.executed_with_callbacks(): node &lt;up_to_date 0 'prog.c'&gt;
- Task.postprocess(): node &lt;up_to_date 0 'prog.c'&gt;
- Task.postprocess(): removing &lt;up_to_date 0 'prog.c'&gt;
- Task.postprocess(): adjusted parent ref count &lt;pending 1 'prog.o'&gt;
-
- Taskmaster: Looking for a node to evaluate
- Taskmaster: Considering node &lt;no_state 0 'inc.h'&gt; and its children:
- Taskmaster: Evaluating &lt;pending 0 'inc.h'&gt;
-
- Task.make_ready_current(): node &lt;pending 0 'inc.h'&gt;
- Task.prepare(): node &lt;up_to_date 0 'inc.h'&gt;
- Task.executed_with_callbacks(): node &lt;up_to_date 0 'inc.h'&gt;
- Task.postprocess(): node &lt;up_to_date 0 'inc.h'&gt;
- Task.postprocess(): removing &lt;up_to_date 0 'inc.h'&gt;
- Task.postprocess(): adjusted parent ref count &lt;pending 0 'prog.o'&gt;
-
- Taskmaster: Looking for a node to evaluate
- Taskmaster: Considering node &lt;pending 0 'prog.o'&gt; and its children:
- Taskmaster: &lt;up_to_date 0 'prog.c'&gt;
- Taskmaster: &lt;up_to_date 0 'inc.h'&gt;
- Taskmaster: Evaluating &lt;pending 0 'prog.o'&gt;
-
- Task.make_ready_current(): node &lt;pending 0 'prog.o'&gt;
- Task.prepare(): node &lt;executing 0 'prog.o'&gt;
- Task.execute(): node &lt;executing 0 'prog.o'&gt;
- cc -o prog.o -c -I. prog.c
- Task.executed_with_callbacks(): node &lt;executing 0 'prog.o'&gt;
- Task.postprocess(): node &lt;executed 0 'prog.o'&gt;
- Task.postprocess(): removing &lt;executed 0 'prog.o'&gt;
- Task.postprocess(): adjusted parent ref count &lt;pending 0 'prog'&gt;
-
- Taskmaster: Looking for a node to evaluate
- Taskmaster: Considering node &lt;pending 0 'prog'&gt; and its children:
- Taskmaster: &lt;executed 0 'prog.o'&gt;
- Taskmaster: Evaluating &lt;pending 0 'prog'&gt;
-
- Task.make_ready_current(): node &lt;pending 0 'prog'&gt;
- Task.prepare(): node &lt;executing 0 'prog'&gt;
- Task.execute(): node &lt;executing 0 'prog'&gt;
- cc -o prog prog.o
- Task.executed_with_callbacks(): node &lt;executing 0 'prog'&gt;
- Task.postprocess(): node &lt;executed 0 'prog'&gt;
-
- 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>
<!--