summaryrefslogtreecommitdiffstats
path: root/doc/user
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-03-25 05:13:22 (GMT)
committerSteven Knight <knight@baldmt.com>2003-03-25 05:13:22 (GMT)
commitc24f1504b711f871c0c4310a460727ac1a859936 (patch)
treeba6a8eb0d60129fab1da2c249696500580d0c699 /doc/user
parent8d8e5b7a7edcfb7ac3795977c33c7f6e561abdda (diff)
downloadSCons-c24f1504b711f871c0c4310a460727ac1a859936.zip
SCons-c24f1504b711f871c0c4310a460727ac1a859936.tar.gz
SCons-c24f1504b711f871c0c4310a460727ac1a859936.tar.bz2
Branch for in-progress User's Guide changes.
Diffstat (limited to 'doc/user')
-rw-r--r--doc/user/alias.sgml71
-rw-r--r--doc/user/builders.sgml375
-rw-r--r--doc/user/caching.sgml242
-rw-r--r--doc/user/command.sgml79
-rw-r--r--doc/user/default.sgml10
-rw-r--r--doc/user/depends.sgml662
-rw-r--r--doc/user/environments.sgml391
-rw-r--r--doc/user/help.sgml2
-rw-r--r--doc/user/hierarchy.sgml207
-rw-r--r--doc/user/install.sgml246
-rw-r--r--doc/user/library.sgml81
-rw-r--r--doc/user/main.sgml76
-rw-r--r--doc/user/more.sgml63
-rw-r--r--doc/user/object.sgml71
-rw-r--r--doc/user/precious.sgml46
-rw-r--r--doc/user/program.sgml77
-rw-r--r--doc/user/reference.sgml63
-rw-r--r--doc/user/repositories.sgml530
-rw-r--r--doc/user/separate.sgml211
-rw-r--r--doc/user/simple.sgml6
-rw-r--r--doc/user/sourcecode.sgml144
-rw-r--r--doc/user/variants.sgml21
22 files changed, 2385 insertions, 1289 deletions
diff --git a/doc/user/alias.sgml b/doc/user/alias.sgml
index 33c236a..3f48ee0 100644
--- a/doc/user/alias.sgml
+++ b/doc/user/alias.sgml
@@ -23,23 +23,72 @@
-->
-<!--
+ <para>
--->
+ We've already seen how you can use the &Alias;
+ function to create a target named <literal>install</literal>:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('/usr/bin', hello)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ You can then use this alias on the command line
+ to tell &SCons; more naturally that you want to install files:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons install</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ </literallayout>
- <para>
+ <para>
- X
+ 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>
+ </para>
- <section>
- <title>Alias Targets</title>
+ <programlisting>
+ env = Environment()
+ p = env.Program('hello.c')
+ l = env.Library('hello.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.Alias('install', [ib, il])
+ </programlisting>
- <para>
+ <para>
- X
+ 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>
+ </para>
- </section>
+ <literallayout>
+ % <userinput>scons install-bin</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ % <userinput>scons install-lib</userinput>
+ Install file: "libhello.a" as "/usr/lib/libhello.a"
+ % <userinput>scons -c /</userinput>
+ % <userinput>scons install</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ Install file: "libhello.a" as "/usr/lib/libhello.a"
+ </literallayout>
diff --git a/doc/user/builders.sgml b/doc/user/builders.sgml
index ac5f193..c1b4269 100644
--- a/doc/user/builders.sgml
+++ b/doc/user/builders.sgml
@@ -95,30 +95,375 @@ This functionality could be invoked as in the following example:
-->
- <para>
+ <para>
+
+ &SCons; provides many useful methods
+ for building common software products:
+ programs, libraries, documents.
+ Frequently, however, you 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.
+
+ </para>
+
+ <section>
+ <title>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 < $TARGET > $SOURCE')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Attaching a Builder to a &ConsEnv;</title>
+
+ <para>
+
+ A &Builder; object by itself, though,
+ 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 &BUILDERS;
+ &consvar; in an environment.
+ The &BUILDERS; variable is a Python dictionary
+ that maps the names by which you want to call various &Builder;
+ to the &Builder; objects themselves.
+ For example, if we want to call the
+ &Builder; we defined by the name
+ <function>Foo</function>,
+ our &SConstruct; file might look like:
+
+ </para>
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ </programlisting>
+
+ <para>
+
+ Then when we run &SCons; it looks like:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ foobuild < file.input > file.foo
+ </literallayout>
+
+ <para>
+
+ Note, however, that the default &BUILDERS;
+ variable in a &consenv;
+ comes with a default set of &Builder; objects
+ already defined:
+ &Program;, &Library;, etc.
+ And when we explicitly set the &BUILDERS; variable
+ when we create the &consenv;,
+ the default &Builder;s are no longer part of
+ the environment:
+
+ </para>
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ other errors
+ Traceback (most recent call last):
+ File "/usr/lib/scons/SCons/Script/__init__.py", line 901, in main
+ _main()
+ File "/usr/lib/scons/SCons/Script/__init__.py", line 762, in _main
+ SCons.Script.SConscript.SConscript(script)
+ File "/usr/lib/scons/SCons/Script/SConscript.py", line 207, in SConscript
+ exec _file_ in stack[-1].globals
+ File "SConstruct", line 4, in ?
+ env.Program('hello.c')
+ scons: Environment instance has no attribute 'Program'
+ </literallayout>
+
+ <para>
+
+ To be able use both our own defined &Builder; objects
+ and the default &Builder; objects in the same &consenv;,
+ you can either add to the &BUILDERS; variable
+ using the &Append; function:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ env.Append(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ Or you can explicitly set the appropriately-named
+ key in the &BUILDERS; dictionary:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ env['BUILDERS']['Foo'] = bld
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ Either way, the same &consenv;
+ can then use both the newly-defined
+ <function>Foo</function> &Builder;
+ and the default &Program; &Builder;:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ foobuild < file.input > file.foo
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ </literallayout>
+
+ </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>
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE',
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file1')
+ env.Foo('file2')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ foobuild < file1.input > file1.foo
+ foobuild < file2.input > file2.foo
+ </literallayout>
+
+ <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>
- X
+ <section>
+ <title>Builders That Execute Python Functions</title>
- </para>
+ <para>
- <section>
- <title>Builders That Execute External Commands</title>
+ 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).
- <para>
+ </para>
- X
+ <programlisting>
+ def build_function(target, source, env):
+ # XXX
+ return None
+ </programlisting>
- </para>
+ <para>
- </section>
+ XXX explain the function
+ XXX define the arguments
- <section>
- <title>Builders That Execute Python Functions</title>
+ </para>
- <para>
+ <para>
- X
+ 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>
+
+ <programlisting>
+ def build_function(target, source, env):
+ # XXX
+ return None
+ bld = Builder(action = build_function,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <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>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ build_function("file.foo", "file.input")
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Builders That Generate Actions</title>
- </para>
+ <para>
- </section>
+ X
+
+ </para>
+
+ <programlisting>
+ def generate_actions(XXX):
+ return XXX
+ bld = Builder(generator = generate_actions,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ <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 List</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ def modify_targets(XXX):
+ return XXX
+ bld = Builder(action = 'XXX',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = modify_targets)
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ <programlisting>
+ bld = Builder(action = 'XXX',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = 'MY_EMITTER')
+ def modify1(XXX):
+ return XXX
+ def modify2(XXX):
+ return XXX
+ env1 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify1)
+ env2 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify2)
+ env1.Foo('file1')
+ env2.Foo('file2')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Builders That Use Other Builders</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.BitKeeper('XXX')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
diff --git a/doc/user/caching.sgml b/doc/user/caching.sgml
index 5403c43..ed72c1e 100644
--- a/doc/user/caching.sgml
+++ b/doc/user/caching.sgml
@@ -23,30 +23,242 @@
-->
-<!--
+ <para>
-=head2 The C<UseCache> method
+ 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.
-The C<UseCache> method instructs Cons to maintain a cache of derived
-files, to be shared among separate build trees of the same project.
+ </para>
- UseCache("cache/<buildname>") || warn("cache directory not found");
+ <section>
+ <title>Specifying the Shared Cache Directory</title>
--->
+ <para>
+
+ To enable sharing of derived files,
+ use the &CacheDir; function
+ in any &SConscript; file:
+
+ </para>
+
+ <programlisting>
+ CacheDir('/usr/local/build_cache')
+ </programlisting>
+
+ <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.
+ 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>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons -c</userinput>
+ % <userinput>scons</userinput>
+ Retrieved `hello.o' from cache
+ Retrieved `hello' from cache
+ %
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Keeping Build Output Consistent</title>
+
+ <para>
+
+ One potential drawback to using a shared cache
+ is that your build output 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>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons --cache-show</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ %
+ </literallayout>
+
+ <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 Retrieving Files From a 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>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons</userinput>
+ Retrieved `hello.o' from cache
+ Retrieved `hello' from cache
+ % <userinput>scons -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons --cache-disable</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ %
+ </literallayout>
+
+ </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>
+ <para>
- X
+ 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 had already been built
+ by a previous invocation:
- </para>
+ </para>
- <section>
- <title>The &Cache; Method</title>
+ <literallayout>
+ % <userinput>scons --cache-disable</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons --cache-disable</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons --cache-force</userinput>
+ % <userinput>scons -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons</userinput>
+ Retrieved `hello.o' from cache
+ Retrieved `hello' from cache
+ %
+ </literallayout>
- <para>
+ <para>
- X
+ 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>
+ </para>
- </section>
+ </section>
diff --git a/doc/user/command.sgml b/doc/user/command.sgml
index abb3a58..945c656 100644
--- a/doc/user/command.sgml
+++ b/doc/user/command.sgml
@@ -27,12 +27,6 @@
=head2 The C<Command> method
-The C<Command> method is a catchall method which can be used to arrange for
-any build action to be executed to update the target. For this command, a
-target file and list of inputs is provided. In addition, a build action
-is specified as the last argument. The build action is typically a
-command line or lines, but may also contain Perl code to be executed;
-see the section above on build actions for details.
The C<Command> method is called as follows:
@@ -55,19 +49,60 @@ F<foo.h> and F<foo.c>.
-->
- <para>
-
- X
-
- </para>
-
- <section>
- <title>The &Command; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
+ <para>
+
+ Creating a &Builder; and attaching it to a &consenv;
+ allows for a lot of flexibility when you
+ want to re-use the same 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 single 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 &Program;, &Object;, etc.),
+ but takes as an additional argument
+ the command to be executed to build the file:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $TARGET > $SOURCE")
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons .</userinput>
+ sed 's/x/y' < foo.in > foo.out
+ </literallayout>
+
+ <para>
+
+ This is often more convenient than
+ creating a &Builder; object
+ and adding it to the &BUILDERS; variable
+ of a &consenv;
+
+ </para>
+
+ <para>
+
+ Note that the action you
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ def build(target, source, env)
+ XXX
+ return None
+ env.Command('foo.out', 'foo.in', build)
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons .</userinput>
+ build("foo.out", "foo.in")
+ </literallayout>
diff --git a/doc/user/default.sgml b/doc/user/default.sgml
index eb2bdc1..981ac42 100644
--- a/doc/user/default.sgml
+++ b/doc/user/default.sgml
@@ -69,9 +69,9 @@ default list.
explicitly specify one or more targets
on the command line.
Sometimes, however, you may want
- to explicitly specify that only
- certain programs should be built by default,
- which you do using the &Default; function:
+ to specify explicitly that only
+ certain programs should be built by default.
+ You do this with the &Default; function:
</para>
@@ -84,7 +84,7 @@ default list.
<para>
- This &SConstruct; file builds two programs,
+ This &SConstruct; file knows how to build two programs,
&hello; and &goodbye;,
but only builds the
&hello program by default:
@@ -162,7 +162,7 @@ default list.
<application>prog1</application>
and
<application>prog3</application>
- programs:
+ programs by default:
</para>
diff --git a/doc/user/depends.sgml b/doc/user/depends.sgml
index e8491e4..8669c72 100644
--- a/doc/user/depends.sgml
+++ b/doc/user/depends.sgml
@@ -46,369 +46,369 @@ operating system on which the build is performed (as reported by C<uname
-->
- <para>
-
- So far we've seen how &SCons; handles one-time builds.
- But the real point of a build tool like &SCons;
- is to rebuild the necessary things when source files change.
- The other side of rebuilding all the necessary things
- is that &SCons; should <emphasis>not</emphasis>
- unnecessarily rebuild things that have already
- been built.
- You can see this at work simply be re-invoking &SCons;
- after building our simple &hello; example:
-
- </para>
-
- <literallayout>
- % <userinput>scons</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons</userinput>
- %
- </literallayout>
-
- <para>
-
- &SCons; has remembered 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>
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- %
- </literallayout>
-
- <para>
-
- Note that &SCons; only reports "...is up to date"
- for target files named explicitly on the command line,
- to avoid cluttering the output.
-
- </para>
-
- <section>
- <title>MD5 Signatures</title>
-
- <para>
-
- &SCons; keeps track of whether a file has changed
- based on the file's contents,
- not the modification time.
- This means that you may be surprised by the
- behavior of &SCons; if you are used to the
- &Make; convention of forcing
- a rebuild by updating the file's
- modification time like so:
-
- </para>
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>touch hello.c</userinput>
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- %
- </literallayout>
-
- <para>
-
- This saves time by avoiding unnecessary rebuilds when,
- for example, someone rewrites the
- contents of a file without making a change.
- But if the contents of the file change,
- then &SCons; detects the change
- and rebuilds the program as required:
-
- </para>
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>edit hello.c</userinput>
- [CHANGE THE CONTENTS OF hello.c]
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- %
- </literallayout>
-
- <para>
-
- X
-
- </para>
-
- </section>
+ <para>
+
+ So far we've seen how &SCons; handles one-time builds.
+ But the real point of a build tool like &SCons;
+ is to rebuild the necessary things,
+ and only the necessary thing, when source files change.
+ Put another way,
+ &SCons; should <emphasis>not</emphasis>
+ waste time rebuilding things that have already been built.
+ You can see this at work simply be re-invoking &SCons;
+ after building our simple &hello; example:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons</userinput>
+ %
+ </literallayout>
+
+ <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>
+
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons hello</userinput>
+ scons: `hello' is up to date.
+ %
+ </literallayout>
+
+ <para>
+
+ Note that &SCons; only reports "...is up to date"
+ for target files named explicitly on the command line,
+ to avoid cluttering the output.
+
+ </para>
+
+ <section>
+ <title>MD5 Signatures</title>
+
+ <para>
+
+ &SCons; keeps track of whether a file has changed
+ based on the file's contents,
+ not the modification time.
+ This means that you may be surprised by the
+ behavior of &SCons; if you are used to the
+ &Make; convention of forcing
+ a rebuild by updating the file's
+ modification time like so:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>touch hello.c</userinput>
+ % <userinput>scons hello</userinput>
+ scons: `hello' is up to date.
+ %
+ </literallayout>
+
+ <para>
+
+ This saves time by avoiding unnecessary rebuilds when,
+ for example, someone rewrites the
+ contents of a file without making a change.
+ But if the contents of the file change,
+ then &SCons; detects the change
+ and rebuilds the program as required:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>edit hello.c</userinput>
+ [CHANGE THE CONTENTS OF hello.c]
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ %
+ </literallayout>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <!--
+
+ Now it turns out that F<hello.c> also includes the interface definition
+ file, F<world.h>:
+
+ How does Cons know that F<hello.c> includes F<world.h>, and that F<hello.o>
+ must therefore be recompiled? For now, suffice it to say that when
+ considering whether or not F<hello.o> is up-to-date, Cons invokes a scanner
+ for its dependency, F<hello.c>. This scanner enumerates the files included
+ by F<hello.c> to come up with a list of further dependencies, beyond those
+ made explicit by the Cons script. This process is recursive: any files
+ included by included files will also be scanned.
-<!--
-
-Now it turns out that F<hello.c> also includes the interface definition
-file, F<world.h>:
-
-How does Cons know that F<hello.c> includes F<world.h>, and that F<hello.o>
-must therefore be recompiled? For now, suffice it to say that when
-considering whether or not F<hello.o> is up-to-date, Cons invokes a scanner
-for its dependency, F<hello.c>. This scanner enumerates the files included
-by F<hello.c> to come up with a list of further dependencies, beyond those
-made explicit by the Cons script. This process is recursive: any files
-included by included files will also be scanned.
-
--->
-
- <section>
- <title>Implicit Dependencies</title>
+ -->
- <para>
+ <section>
+ <title>Implicit Dependencies</title>
+
+ <para>
+
+ Now suppose that our "Hello, World!" program
+ actually has a <literal>#include</literal> line
+ to include &hello_h; file in the compilation:
+
+ </para>
+
+ <programlisting>
+ #include "hello.h"
+ int
+ main()
+ {
+ printf("Hello, %s!\n", string);
+ }
+ </programlisting>
+
+ <para>
+
+ And, for completeness, the &hello_h; file looks like this:
+
+ </para>
+
+ <programlisting>
+ #define string "world"
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ env = Environment(CPPPATH = '.') XXX IS CPPPATH NECESSARY?
+ hello = env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ The &CPPPATH; assignment in the &Environment; call
+ 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>
+
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit hello.h</userinput>
+ [CHANGE THE CONTENTS OF hello.h]
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ %
+ </literallayout>
+
+ <para>
+
+ &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>
+
+ X
+
+ <!--
+ 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.
+ -->
- Now suppose that our "Hello, World!" program
- actually looks like this:
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Ignore; Method</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>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Ignore(hello, 'hello.h')
+ </programlisting>
- </para>
+ <!-- XXX mention that you can use arrays for target and source? -->
- <programlisting>
- #include "hello.h"
- int
- main()
- {
- printf("Hello, %s!\n", string);
- }
- </programlisting>
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit hello.h</userinput>
+ [CHANGE THE CONTENTS OF hello.h]
+ % <userinput>scons hello</userinput>
+ scons: `hello' is up to date.
+ </literallayout>
- <para>
+ <para>
- That is, the first line
- includes a &hello_h;
- that looks like this:
+ Now, the above example is a little contrived,
+ because it's hard to imagine a real-world situation
+ where you wouldn't 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>
+ </para>
- <programlisting>
- #define string "world"
- </programlisting>
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Ignore(hello, '/usr/include/stdio.h')
+ </programlisting>
- <para>
+ </section>
- 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:
+ <section>
+ <title>The &Depends; Method</title>
- </para>
+ <para>
- <programlisting>
- env = Environment(CPPPATH = '.') XXX IS CPPPATH NECESSARY?
- hello = env.Program('hello.c')
- </programlisting>
+ On the other hand,
+ sometimes a file depends on another
+ file that the scanner(s) in &SCons; will not detect.
+ For this situation,
+ &SCons; allows you to specific that one file explicitly
+ depends on another file,
+ and must be rebuilt whenever that file changes,
+ using the &Depends; method:
- <para>
+ </para>
- The &CPPPATH; assignment in the &Environment; call
- 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:
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Depends(hello, 'other_file')
+ </programlisting>
- </para>
+ <!-- XXX mention that you can use arrays for target and source? -->
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- % <userinput>edit hello.h</userinput>
- [CHANGE THE CONTENTS OF hello.h]
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- %
- </literallayout>
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit other_file</userinput>
+ [CHANGE THE CONTENTS OF other_file]
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ </literallayout>
- <para>
+ </section>
- &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>
+ <section>
+ <title>The &Salt; Method</title>
- <para>
+ <para>
- X
+ X
-<!--
-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>
-
- </section>
-
- <section>
- <title>The &Ignore; Method</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>
-
- <programlisting>
- env = Environment()
- hello = env.Program('hello.c')
- env.Ignore(hello, 'hello.h')
- </programlisting>
-
- <!-- XXX mention that you can use arrays for target and source? -->
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- % <userinput>edit hello.h</userinput>
- [CHANGE THE CONTENTS OF hello.h]
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- </literallayout>
-
- <para>
-
- Now, the above example is a little contrived,
- because it's hard to imagine a real-world situation
- where you wouldn't 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>
- env = Environment()
- hello = env.Program('hello.c')
- env.Ignore(hello, '/usr/include/stdio.h')
- </programlisting>
-
- </section>
-
- <section>
- <title>The &Depends; Method</title>
-
- <para>
-
- On the other hand,
- sometimes a file depends on another
- file that the scanner(s) in &SCons; will not detect.
- For this situation,
- &SCons; allows you to specific that one file explicitly
- depends on another file,
- and must be rebuilt whenever that file changes,
- using the &Depends; method:
-
- </para>
-
- <programlisting>
- env = Environment()
- hello = env.Program('hello.c')
- env.Depends(hello, 'other_file')
- </programlisting>
-
- <!-- XXX mention that you can use arrays for target and source? -->
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- % <userinput>edit other_file</userinput>
- [CHANGE THE CONTENTS OF other_file]
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- </literallayout>
-
- </section>
-
- <!-->
-
- <section>
- <title>The &Salt; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
+ </section>
- -->
+ -->
- <section>
- <title>Time Stamps</title>
+ <section>
+ <title>Time Stamps</title>
- <para>
+ <para>
- X
+ X
- </para>
+ </para>
- </section>
+ </section>
- <section>
- <title>The &SourceSignature; Method</title>
+ <section>
+ <title>The &SourceSignature; Method</title>
- <para>
+ <para>
- X
+ X
- </para>
+ </para>
- </section>
+ </section>
diff --git a/doc/user/environments.sgml b/doc/user/environments.sgml
index b06ade1..8117cf0 100644
--- a/doc/user/environments.sgml
+++ b/doc/user/environments.sgml
@@ -25,47 +25,6 @@
<!--
-=head2 Construction environments
-
-A key simplification of Cons is the idea of a B<construction environment>. A
-construction environment is an B<object> characterized by a set of key/value
-pairs and a set of B<methods>. In order to tell Cons how to build something,
-you invoke the appropriate method via an appropriate construction
-environment. Consider the following example:
-
-
-
- $env = new cons(
- CC => 'gcc',
- LIBS => 'libworld.a'
- );
-
- Program $env 'hello', 'hello.c';
-
-In this case, rather than using the default construction environment, as is,
-we have overridden the value of C<CC> so that the GNU C Compiler equivalent
-is used, instead. Since this version of B<Hello, World!> requires a library,
-F<libworld.a>, we have specified that any program linked in this environment
-should be linked with that library. If the library exists already, well and
-good, but if not, then we'll also have to include the statement:
-
-
-
- Library $env 'libworld', 'world.c';
-
-Now if you type C<cons hello>, the library will be built before the program
-is linked, and, of course, C<gcc> will be used to compile both modules:
-
-
-
- % cons hello
- gcc -c hello.c -o hello.o
- gcc -c world.c -o world.o
- ar r libworld.a world.o
- ar: creating libworld.a
- ranlib libworld.a
- gcc -o hello hello.o libworld.a
-
=head1 More on construction environments
As previously mentioned, a B<construction environment> is an object that
@@ -346,6 +305,12 @@ 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
@@ -420,101 +385,261 @@ C<PATH> variable in the default environment, you could do the following:
This will leave anything else that might be in the default execution
environment undisturbed.
+-->
+
+ <para>
+ It is rare that all of the software in a large,
+ complicated system needs to be built the same way.
+ Different source files need different options
+ enabled on the command line;
+ different executable programs need to be linked
+ with different libraries (shared or static);
+ XXX
+ &SCons; accomodates these different build
+ requirements by allowing you to create and
+ configure multiple &consenvs;
+ that control how the software is built.
+ Technically, a &consenv; is an object
+ that has a number of associated
+ &consvars;, each with a name and a value.
+ (A &consenv; also has an attached
+ set of &Builder; methods,
+ about which we'll learn more later.)
-=head2 Overriding construction variables
+ </para>
-There are several ways of extending Cons, which vary in degree of
-difficulty. The simplest method is to define your own construction
-environment, based on the default environment, but modified to reflect your
-particular needs. This will often suffice for C-based applications. You can
-use the C<new> constructor, and the C<clone> and C<copy> methods to create
-hybrid environments. These changes can be entirely transparent to the
-underlying F<Conscript> files.
+ <para>
--->
+ A &consenv; is created by the &Environment;
+ method which you have already seen.
+ What you haven't seen, though,
+ is that when you initialize a &consenv;,
+ you can set the values of the
+ environment's &consvars;
+ to control how a program is built.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CC = 'gcc',
+ CCFLAGS = '-O2')
+
+ env.Program('foo.c')
+ </programlisting>
<para>
+
+ This example, rather than using the default,
+ explicitly specifies 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.
+ So a run from this example would look like:
- X
+ </para>
-<!--
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c -O2 foo.c -o foo.o
+ gcc -o foo foo.o
+ </literallayout>
-A key simplification of Cons is the idea of a B<construction environment>. A
-construction environment is an B<object> characterized by a set of key/value
-pairs and a set of B<methods>. In order to tell Cons how to build something,
-you invoke the appropriate method via an appropriate construction
-environment. Consider the following example:
+ <section>
+ <title>Multiple &ConsEnvs;</title>
+ <para>
+ So far, we've always created a &consenv; named
+ <literal>env</literal>.
+ <literal>env</literal>, however,
+ is simply a Python variable name,
+ and you can use any other variable name that we like.
+ For example:
- $env = new cons(
- CC => 'gcc',
- LIBS => 'libworld.a'
- );
+ </para>
+
+ <programlisting>
+ my_env = Environment(CC = 'gcc',
+ CCFLAGS = '-O2')
- Program $env 'hello', 'hello.c';
+ my_env.Program('foo.c')
+ </programlisting>
-In this case, rather than using the default construction environment, as is,
-we have overridden the value of C<CC> so that the GNU C Compiler equivalent
-is used, instead. Since this version of B<Hello, World!> requires a library,
-F<libworld.a>, we have specified that any program linked in this environment
-should be linked with that library. If the library exists already, well and
-good, but if not, then we'll also have to include the statement:
+ <para>
+ This opens up the possibility of
+ using multiple &consenvs;,
+ each with a separate variable name.
+ We can then use these separate &consenvs;
+ to build different programs in different ways:
+ </para>
- Library $env 'libworld', 'world.c';
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
-Now if you type C<cons hello>, the library will be built before the program
-is linked, and, of course, C<gcc> will be used to compile both modules:
+ opt.Program('foo', 'foo.c')
+ dbg.Program('bar', 'bar.c')
+ </programlisting>
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c -O2 bar.c -o bar.o
+ cc -o bar bar.o
+ cc -c -g foo.c -o foo.o
+ cc -o foo foo.o
+ </literallayout>
- % cons hello
- gcc -c hello.c -o hello.o
- gcc -c world.c -o world.o
- ar r libworld.a world.o
- ar: creating libworld.a
- ranlib libworld.a
- gcc -o hello hello.o libworld.a
+ <para>
--->
+ We can even use multiple &consenvs; to build
+ multiple versions of a single program.
+ If you do this by simply trying to use the
+ &Program; builder with both environments, though,
+ like this:
- </para>
+ </para>
- <programlisting>
- optimize = Environment(CCFLAGS = '-O2')
- debug = Environment(CCFLAGS = '-g')
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
- o = optimize.Object('foo-opt', 'foo.c')
- optimize.Program(o)
+ opt.Program('foo', 'foo.c')
- d = debug.Object('foo-debug', 'foo.c')
- debug.Program(d)
- </programlisting>
+ dbg.Program('foo', 'foo.c')
+ </programlisting>
- <literallayout>
- % <userinput>scons .</userinput>
- cc -c -g foo.c -o foo-debug.o
- cc -o foo-debug foo-debug.o
- cc -c -O2 foo.c -o foo-opt.o
- cc -o foo-opt foo-opt.o
- </literallayout>
+ <para>
+
+ Then &SCons; generates the following error:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ scons: *** Two different environments were specified for the same target: foo.o
+ File "SConstruct", line 6, in ?
+ </literallayout>
+
+ <para>
+
+ This is because the two &Program; calls have
+ each implicitly told &SCons; to generate an object file named
+ <filename>foo.o</filename>,
+ one with a &CCFLAGS; value of
+ <literal>-O2</literal>
+ and one with a &CCFLAGS; value of
+ <literal>-g</literal>.
+ To work around this,
+ we must explicitly specify
+ that each environment compile
+ <filename>foo.c</filename>
+ to a separately-named object file
+ using the &Object; call, like so:
+
+ </para>
+
+ <programlisting>
+ 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)
+ </programlisting>
+
+ <para>
+
+ Notice that each call to the &Object; builder
+ returns a value,
+ an internal &SCons; object that
+ represents the file that will be built.
+ We then use that object
+ as input to the &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>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c -g foo.c -o foo-dbg.o
+ cc -o foo-dbg foo-dbg.o
+ cc -c -O2 foo.c -o foo-opt.o
+ cc -o foo-opt foo-opt.o
+ </literallayout>
+
+ </section>
<section>
- <title>The &Environment; Constructor</title>
+ <title>Copying &ConsEnvs;</title>
<para>
- X
+ Sometimes you want to more than one &consenv;
+ to use the same values for one or more variables.
+ Rather than always having to repeat all of the common
+ variables when you create each &consenv;,
+ you can use the &Copy; method
+ to create a copy of a &consenv;.
+ Like the &Environment; call that creates a &consenv;,
+ the &Copy; method takes &consvar; assignments,
+ which will override the values in the copied &consenv;.
+ 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" &consenv;
+ that sets &CC; to &gcc;,
+ and then creating two copies,
+ one which sets &CCFLAGS; for optimization
+ and the other with sets &CCFLAGS; for debugging:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CC = 'gcc')
+ opt = env.Copy(CCFLAGS = '-O2')
+ dbg = env.Copy(CCFLAGS = '-g')
+
+ e = opt.Object('foo', 'foo.c')
+
+ o = opt.Object('foo-opt', 'foo.c')
+ opt.Program(o)
+
+ d = dbg.Object('foo-dbg', 'foo.c')
+ dbg.Program(d)
+ </programlisting>
+
+ <para>
+
+ Then our output would look like:
</para>
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c foo.c -o foo.o
+ gcc -o foo foo.o
+ gcc -c -g foo.c -o foo-dbg.o
+ gcc -o foo-dbg foo-dbg.o
+ gcc -c -O2 foo.c -o foo-opt.o
+ gcc -o foo-opt foo-opt.o
+ </literallayout>
+
</section>
<section>
- <title>The &Copy; Method</title>
+ <title>Fetching Values From a &ConsEnv;</title>
<para>
@@ -522,4 +647,74 @@ is linked, and, of course, C<gcc> will be used to compile both modules:
</para>
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Modifying a &ConsEnv;</title>
+
+ <section>
+ <title>Replacing Values in a &ConsEnv;</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Appending to the End of Values in a &ConsEnv;</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Appending to the Beginning of Values in a &ConsEnv;</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ </literallayout>
+
+ </section>
+
</section>
diff --git a/doc/user/help.sgml b/doc/user/help.sgml
index 5e2ced3..233809e 100644
--- a/doc/user/help.sgml
+++ b/doc/user/help.sgml
@@ -69,7 +69,7 @@
If there is no &Help; text in the &SConstruct; or
&SConscript; files,
&SCons; will revert to displaying its
- standard list and description of available command-line
+ standard list that describes the &SCons; command-line
options.
This list is also always displayed whenever
the <literal>-H</literal> option is used.
diff --git a/doc/user/hierarchy.sgml b/doc/user/hierarchy.sgml
index aa56c8d..617eb59 100644
--- a/doc/user/hierarchy.sgml
+++ b/doc/user/hierarchy.sgml
@@ -36,44 +36,6 @@ C<Import> commands.
=head2 The Build command
-The C<Build> command takes a list of F<Conscript> file names, and arranges
-for them to be included in the build. For example:
-
- Build qw(
- drivers/display/Conscript
- drivers/mouse/Conscript
- parser/Conscript
- utilities/Conscript
- );
-
-This is a simple two-level hierarchy of build scripts: all the subsidiary
-F<Conscript> files are mentioned in the top-level F<Construct> file. Notice
-that not all directories in the tree necessarily have build scripts
-associated with them.
-
-This could also be written as a multi-level script. For example, the
-F<Construct> file might contain this command:
-
- Build qw(
- parser/Conscript
- drivers/Conscript
- utilities/Conscript
- );
-
-and the F<Conscript> file in the F<drivers> directory might contain this:
-
- Build qw(
- display/Conscript
- mouse/Conscript
- );
-
-Experience has shown that the former model is a little easier to understand,
-since the whole construction tree is laid out in front of you, at the
-top-level. Hybrid schemes are also possible. A separately maintained
-component that needs to be incorporated into a build tree, for example,
-might hook into the build tree in one place, but define its own construction
-hierarchy.
-
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>
@@ -220,30 +182,169 @@ make no difference to the build.
-->
- <para>
+ <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>
+
+ <programlisting>
+ SConscript(['drivers/display/SConscript',
+ 'drivers/mouse/SConscript',
+ 'parser/SConscript',
+ 'utilities/SConscript'])
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ SConscript(['drivers/SConscript',
+ 'parser/SConscript',
+ 'utilities/SConscript'])
+ </programlisting>
+
+ <para>
+
+ And the subsidiary &SConscript; file in the
+ <literal>drivers</literal> subdirectory
+ would look like:
+
+ </para>
+
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
+
+ <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>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
+
+ <section>
+ <title>Exporting Variables</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Importing Variables</title>
- X
+ <para>
- </para>
+ X
- <section>
- <title>&SConscript; Files</title>
+ </para>
- <para>
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
- X
+ </section>
- </para>
+ <section>
+ <title>Returning Values</title>
- </section>
+ <para>
- <section>
- <title>X</title>
+ X
- <para>
+ </para>
- X
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
- </para>
+ </section>
- </section>
+ </section>
diff --git a/doc/user/install.sgml b/doc/user/install.sgml
index 530fa7a..2cebbd4 100644
--- a/doc/user/install.sgml
+++ b/doc/user/install.sgml
@@ -23,75 +23,211 @@
-->
-<!--
-
-=head2 The C<Install> method
-
-The C<Install> method arranges for the specified files to be installed in
-the specified directory. The installation is optimized: the file is not
-copied if it can be linked. If this is not the desired behavior, you will
-need to use a different method to install the file. It is called as follows:
-
- Install $env <directory>, <names>;
-
-Note that, while the files to be installed may be arbitrarily named,
-only the last component of each name is used for the installed target
-name. So, for example, if you arrange to install F<foo/bar> in F<baz>,
-this will create a F<bar> file in the F<baz> directory (not F<foo/bar>).
-
-
-=head2 The C<InstallAs> method
+ <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>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('/usr/bin', hello)
+ </programlisting>
+
+ <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>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons /usr/bin</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ </literallayout>
+
+ <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, if you wish,
+ to create a pseudo-target named <literal>install</literal>
+ that can expand to the specified destination directory:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('/usr/bin', hello)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ This then yields the more natural
+ ability to install the program
+ in its destination as follows:
+
+ </para>
-The C<InstallAs> method arranges for the specified source file(s) to be
-installed as the specified target file(s). Multiple files should be
-specified as a file list. The installation is optimized: the file is not
-copied if it can be linked. If this is not the desired behavior, you will
-need to use a different method to install the file. It is called as follows:
+ <literallayout>
+ % <userinput>scons install</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ </literallayout>
+
+ <section>
+ <title>Installing Multiple Files in a Directory</title>
+
+ <para>
+
+ You can install multiple files into a directory
+ simploy by calling the &Install; function multiple times:
+
+ </para>
+
+ <programlisting>
+ 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>
+
+ <para>
+
+ Or, more succinctly, listing the multiple input
+ files in a list
+ (just like you can do with any other builder):
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.Install('/usr/bin', [hello, goodbye])
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ Either of these two examples yields:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons install</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
+ Install file: "goodbye" as "/usr/bin/goodbye"
+ Install file: "hello" as "/usr/bin/hello"
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Installing a File Under a Different Name</title>
-C<InstallAs> works in two ways:
+ <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:
-Single file install:
+ </para>
- InstallAs $env TgtFile, SrcFile;
-
-Multiple file install:
-
- InstallAs $env ['tgt1', 'tgt2'], ['src1', 'src2'];
-
-Or, even as:
-
- @srcs = qw(src1 src2 src3);
- @tgts = qw(tgt1 tgt2 tgt3);
- InstallAs $env [@tgts], [@srcs];
-
-Both the target and the sources lists should be of the same length.
-
--->
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.InstallAs('/usr/bin/hello-new', hello)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
- <para>
+ <para>
- X
+ This installs the <literal>hello</literal>
+ program with the name <literal>hello-new</literal>
+ as follows:
- </para>
+ </para>
- <section>
- <title>The &Install; Builder</title>
+ <literallayout>
+ % <userinput>scons install</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ Install file: "hello" as "/usr/bin/hello-new"
+ </literallayout>
- <para>
+ </section>
- X
+ <section>
+ <title>Installing Multiple Files Under Different Names</title>
- </para>
+ <para>
- </section>
+ 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 the both the target and source arguments:
- <section>
- <title>The &InstallAs; Method</title>
+ </para>
- <para>
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.InstallAs(['/usr/bin/hello-new',
+ '/usr/bin/goodbye-new',
+ [hello, goodbye])
+ </programlisting>
+
+ <para>
- X
+ In this case, the &InstallAs; function
+ loops through both lists simultaneously,
+ and copies each source file into its corresponding
+ target file name:
- </para>
+ </para>
+
+ <literallayout>
+ % <userinput>scons install</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
+ Install file: "goodbye" as "/usr/bin/goodbye-new"
+ Install file: "hello" as "/usr/bin/hello-new"
+ </literallayout>
- </section>
+ </section>
diff --git a/doc/user/library.sgml b/doc/user/library.sgml
deleted file mode 100644
index 0c9292c..0000000
--- a/doc/user/library.sgml
+++ /dev/null
@@ -1,81 +0,0 @@
-<!--
-
- Copyright (c) 2001, 2002, 2003 Steven Knight
-
- 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<Library> method
-
-The C<Library> method arranges to create the specified library from the
-specified object files. It is invoked as follows:
-
- Library $env <library name>, <source or object files>;
-
-The library name will have the value of the C<SUFLIB> construction
-variable appended (by default, C<.lib> on Win32 systems, C<.a> on Unix
-systems) if the suffix is not already present.
-
-Source files may be specified in place of objects files-,-the C<Objects>
-method will be invoked to arrange the conversion of all the files into
-object files, and hence all the observations about the C<Objects> method,
-above, apply to this method also.
-
-The actual creation of the library will be handled by an external
-command which results from expanding the C<ARCOM> construction variable,
-with C<%E<lt>> set to the library members (in the order presented),
-and C<%E<gt>> to the library to be created. (See the section above
-on construction variable expansion for details.) The user may set
-variables in the construction environment which will affect the
-operation of the command. These include C<AR>, the archive program
-to use, C<ARFLAGS>, which can be used to modify the flags given to
-the program specified by C<AR>, and C<RANLIB>, the name of a archive
-index generation program, if needed (if the particular need does not
-require the latter functionality, then C<ARCOM> must be redefined to not
-reference C<RANLIB>).
-
-The C<Library> method allows the same library to be specified in multiple
-method invocations. All of the contributing objects from all the invocations
-(which may be from different directories) are combined and generated by a
-single archive command. Note, however, that if you prune a build so that
-only part of a library is specified, then only that part of the library will
-be generated (the rest will disappear!).
-
--->
-
- <para>
-
- X
-
- </para>
-
- <section>
- <title>The &Library; Builder</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
diff --git a/doc/user/main.sgml b/doc/user/main.sgml
index b285696..68bc59c 100644
--- a/doc/user/main.sgml
+++ b/doc/user/main.sgml
@@ -47,19 +47,15 @@
<!ENTITY help SYSTEM "help.sgml">
<!ENTITY hierarchy SYSTEM "hierarchy.sgml">
<!ENTITY install SYSTEM "install.sgml">
- <!ENTITY library SYSTEM "library.sgml">
<!ENTITY make SYSTEM "make.sgml">
- <!ENTITY more SYSTEM "more.sgml">
- <!ENTITY object SYSTEM "object.sgml">
<!ENTITY precious SYSTEM "precious.sgml">
<!ENTITY preface SYSTEM "preface.sgml">
- <!ENTITY program SYSTEM "program.sgml">
- <!ENTITY reference SYSTEM "reference.sgml">
<!ENTITY repositories SYSTEM "repositories.sgml">
<!ENTITY run SYSTEM "run.sgml">
<!ENTITY scanners SYSTEM "scanners.sgml">
<!ENTITY separate SYSTEM "separate.sgml">
<!ENTITY simple SYSTEM "simple.sgml">
+ <!ENTITY sourcecode SYSTEM "sourcecode.sgml">
<!ENTITY troubleshoot SYSTEM "troubleshoot.sgml">
<!ENTITY variants SYSTEM "variants.sgml">
@@ -111,8 +107,6 @@
&depends;
</chapter>
-
-
<chapter id="chap-default">
<title>Default Targets</title>
&default;
@@ -128,31 +122,6 @@
&install;
</chapter>
- <chapter id="chap-program">
- <title>The Program Builder</title>
- &program;
- </chapter>
-
- <chapter id="chap-library">
- <title>The Library Builder</title>
- &library;
- </chapter>
-
- <chapter id="chap-more">
- <title>More Things to Do With Builds</title>
- &more;
- </chapter>
-
- <chapter id="chap-command">
- <title>The Command Builder</title>
- &command;
- </chapter>
-
- <chapter id="chap-object">
- <title>The Object Builder</title>
- &object;
- </chapter>
-
<chapter id="chap-precious">
<title>Preventing Removal of Targets</title>
&precious;
@@ -178,6 +147,11 @@
&builders;
</chapter>
+ <chapter id="chap-command">
+ <title>Avoiding Having to Write Builders</title>
+ &command;
+ </chapter>
+
<chapter id="chap-actions">
<title>SCons Actions</title>
&actions;
@@ -193,35 +167,45 @@
&repositories;
</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-run">
- <title>How to Run &SCons;</title>
- &run;
- </chapter>
-
<chapter id="chap-alias">
<title>Alias Targets</title>
&alias;
</chapter>
+ <chapter id="chap-run">
+ <title>How to Run &SCons;</title>
+ &run;
+ </chapter>
+
<chapter id="chap-troubleshooting">
<title>Troubleshooting</title>
&troubleshoot;
</chapter>
- <appendix id="app-quick">
- <title>Quick Reference</title>
- &reference;
- </appendix>
-
- <appendix id="app-errors">
- <title>Errors Generated by &SCons;</title>
- &errors;
- </appendix>
+ <!--
+ AddPostAction()
+ AddPreAction()
+ Clean()
+ Dir()
+ File()
+ FindFile()
+ GetJobs()
+ SetJobs()
+ SideEffect()
+ ParseConfig()
+ Platform()
+ Tools()
+ -->
<appendix id="app-example">
<title>Complex &SCons; Example</title>
diff --git a/doc/user/more.sgml b/doc/user/more.sgml
deleted file mode 100644
index 7defa41..0000000
--- a/doc/user/more.sgml
+++ /dev/null
@@ -1,63 +0,0 @@
-<!--
-
- Copyright (c) 2001, 2002, 2003 Steven Knight
-
- 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>
-
- X
-
- </para>
-
- <section>
- <title>The &Module; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
-
- <section>
- <title>The &RuleSet; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
-
- <section>
- <title>The &DefaultRules; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
diff --git a/doc/user/object.sgml b/doc/user/object.sgml
deleted file mode 100644
index 9e887d8..0000000
--- a/doc/user/object.sgml
+++ /dev/null
@@ -1,71 +0,0 @@
-<!--
-
- Copyright (c) 2001, 2002, 2003 Steven Knight
-
- 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<Objects> method
-
-The C<Objects> method arranges to create the object files that correspond to
-the specified source files. It is invoked as shown below:
-
- @files = Objects $env <source or object files>;
-
-Under Unix, source files ending in F<.s> and F<.c> are currently
-supported, and will be compiled into a name of the same file ending
-in F<.o>. By default, all files are created by invoking the external
-command which results from expanding the C<CCCOM> construction variable,
-with C<%E<lt>> and C<%E<gt>> set to the source and object files,
-respectively. (See the section above on construction variable expansion
-for details). The variable C<CPPPATH> is also used when scanning source
-files for dependencies. This is a colon separated list of pathnames, and
-is also used to create the construction variable C<_IFLAGS,> which will
-contain the appropriate list of -C<I> options for the compilation. Any
-relative pathnames in C<CPPPATH> is interpreted relative to the
-directory in which the associated construction environment was created
-(absolute and top-relative names may also be used). This variable is
-used by C<CCCOM>. The behavior of this command can be modified by
-changing any of the variables which are interpolated into C<CCCOM>, such
-as C<CC>, C<CFLAGS>, and, indirectly, C<CPPPATH>. It's also possible
-to replace the value of C<CCCOM>, itself. As a convenience, this file
-returns the list of object filenames.
-
--->
-
- <para>
-
- X
-
- </para>
-
- <section>
- <title>The &Object; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
diff --git a/doc/user/precious.sgml b/doc/user/precious.sgml
index 9cd2a43..26ad345 100644
--- a/doc/user/precious.sgml
+++ b/doc/user/precious.sgml
@@ -25,17 +25,6 @@
<!--
-=head2 The C<Precious> method
-
-The C<Precious> method asks cons not to delete the specified file or
-list of files before building them again. It is invoked as:
-
- Precious <files>;
-
-This is especially useful for allowing incremental updates to libraries
-or debug information files which are updated rather than rebuilt anew each
-time. Cons will still delete the files when the C<-r> flag is specified.
-
=head2 The C<AfterBuild> method
The C<AfterBuild> method evaluates the specified perl string after
@@ -53,17 +42,38 @@ which the C<AfterBuild> method is called.
<para>
- X
+ 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>
- <section>
- <title>The &Precious; Method</title>
+ <programlisting>
+ env = Environment(XXX NEED LIBRARY FLAGS
+ LIBFLAGS = '-r')
+ lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ env.Precious(lib)
+ </programlisting>
- <para>
+ <para>
- X
+ XXX:
- </para>
+ </para>
- </section>
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX ANY INPUT HERE?
+ </literallayout>
+
+ <para>
+
+ &SCons; will still delete files marked as &Precious;
+ when the <literal>-c</literal> option is used.
+
+ </para>
diff --git a/doc/user/program.sgml b/doc/user/program.sgml
deleted file mode 100644
index 30f90d2..0000000
--- a/doc/user/program.sgml
+++ /dev/null
@@ -1,77 +0,0 @@
-<!--
-
- Copyright (c) 2001, 2002, 2003 Steven Knight
-
- 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<Program> method
-
-The C<Program> method arranges to link the specified program with the
-specified object files. It is invoked in the following manner:
-
- Program $env <program name>, <source or object files>;
-
-The program name will have the value of the C<SUFEXE> construction
-variable appended (by default, C<.exe> on Win32 systems, nothing on Unix
-systems) if the suffix is not already present.
-
-Source files may be specified in place of objects files-,-the C<Objects>
-method will be invoked to arrange the conversion of all the files into
-object files, and hence all the observations about the C<Objects> method,
-above, apply to this method also.
-
-The actual linking of the program will be handled by an external command
-which results from expanding the C<LINKCOM> construction variable, with
-C<%E<lt>> set to the object files to be linked (in the order presented),
-and C<%E<gt>> set to the target. (See the section above on construction
-variable expansion for details.) The user may set additional variables
-in the construction environment, including C<LINK>, to define which
-program to use for linking, C<LIBPATH>, a colon-separated list of
-library search paths, for use with library specifications of the form
-I<-llib>, and C<LIBS>, specifying the list of libraries to link against
-(in either I<-llib> form or just as pathnames. Relative pathnames in
-both C<LIBPATH> and C<LIBS> are interpreted relative to the directory
-in which the associated construction environment is created (absolute
-and top-relative names may also be used). Cons automatically sets up
-dependencies on any libraries mentioned in C<LIBS>: those libraries will
-be built before the command is linked.
-
--->
-
- <para>
-
- X
-
- </para>
-
- <section>
- <title>The &Program; Builder</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
diff --git a/doc/user/reference.sgml b/doc/user/reference.sgml
deleted file mode 100644
index ef8e5a9..0000000
--- a/doc/user/reference.sgml
+++ /dev/null
@@ -1,63 +0,0 @@
-<!--
-
- Copyright (c) 2001, 2002, 2003 Steven Knight
-
- 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>
-
- X
-
- </para>
-
- <section>
- <title>Command-Line Options</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
-
- <section>
- <title>Default Builders</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
-
- <section>
- <title>X</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
diff --git a/doc/user/repositories.sgml b/doc/user/repositories.sgml
index 2193a8f..616e903 100644
--- a/doc/user/repositories.sgml
+++ b/doc/user/repositories.sgml
@@ -135,314 +135,326 @@ subdirectories under the repository tree.
-->
- <para>
+ <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:
- 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>
+
+ <programlisting>
+ env = Environment()
+ env.Program('hello.c')
+ Repository('/usr/repository1', '/usr/repository2')
+ </programlisting>
+
+ <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>
+ </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 XXX
+ 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/repository1/hello.c</filename> file
+ to use in its place.
+
+ </para>
+
+ <para>
- <section>
- <title>The &Repository; Method</title>
+ 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>
-<!--
-
-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>
-
- The &Repository; method
- tells &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>
-
- <programlisting>
- env = Environment()
- env.Program('hello.c')
- Repository('/usr/repository1', '/usr/repository2')
- </programlisting>
-
- <para>
-
- (Note that 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 XXX
- 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/repository1/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>
-
- <literallayout>
- % <userinput>scons</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
- </literallayout>
-
- <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>
-
- <literallayout>
- % <userinput>scons</userinput>
- gcc -c /usr/repository1/hello.c -o hello.o
- gcc -o hello hello.o
- </literallayout>
-
- <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>
-
- <literallayout>
- % <userinput>scons</userinput>
- gcc -c /usr/repository2/hello.c -o hello.o
- gcc -o hello hello.o
- </literallayout>
-
- <para>
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -o hello hello.o
+ </literallayout>
+
+ <para>
- </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>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c /usr/repository1/hello.c -o hello.o
+ gcc -o hello hello.o
+ </literallayout>
+
+ <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>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c /usr/repository2/hello.c -o hello.o
+ gcc -o hello hello.o
+ </literallayout>
+
+ <para>
+
+ </para>
- </section>
+ </section>
- <section>
- <title>Finding the &SConstruct; file in repositories</title>
+ <section>
+ <title>Finding the &SConstruct; file in repositories</title>
- <para>
+ <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>:
+ &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>:
- </para>
+ </para>
- <literallayout>
- % <userinput>scons -Y /usr/repository1 -Y /usr/repository2</userinput>
- </literallayout>
+ <literallayout>
+ % <userinput>scons -Y /usr/repository1 -Y /usr/repository2</userinput>
+ </literallayout>
- <para>
+ <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.
+ 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>
+ </para>
- </section>
+ </section>
- <section>
- <title>Finding derived files in repositories</title>
+ <section>
+ <title>Finding derived files in repositories</title>
- <para>
+ <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.
+ 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>
- <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 &SCons; in a separate build directory
- and copying the resulting tree to the desired repository:
+ 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 &SCons; in a separate build directory
+ and copying the resulting tree to the desired repository:
- </para>
+ </para>
- <literallayout>
- % <userinput>cd /usr/repository1</userinput>
- % <userinput>scons</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
- </literallayout>
+ <literallayout>
+ % <userinput>cd /usr/repository1</userinput>
+ % <userinput>scons</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -o hello hello.o
+ </literallayout>
- <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>
+
+ (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>
- <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:
+ 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>
+ </para>
- <literallayout>
- % <userinput>cd $HOME/build</userinput>
- % <userinput>edit hello.c</userinput>
- % <userinput>scons -Y /usr/repository1</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
- XXXXXXX
- </literallayout>
+ <literallayout>
+ % <userinput>cd $HOME/build</userinput>
+ % <userinput>edit hello.c</userinput>
+ % <userinput>scons -Y /usr/repository1</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -o hello hello.o
+ XXXXXXX
+ </literallayout>
- <para>
+ <para>
- Notice that &SCons; realizes that it does not need to
- rebuild a local XXX.o file,
- but instead uses the already-compiled XXX.o file
- from the repository.
+ Notice that &SCons; realizes that it does not need to
+ rebuild a local XXX.o file,
+ but instead uses the already-compiled XXX.o file
+ from the repository.
- </para>
+ </para>
- </section>
+ </section>
- <section>
- <title>Guaranteeing local copies of files</title>
+ <section>
+ <title>Guaranteeing local copies of files</title>
- <para>
+ <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:
+ 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>
+ </para>
- <literallayout>
- % <userinput>mkdir $HOME/build2</userinput>
- % <userinput>cd $HOME/build2</userinput>
- % <userinput>scons -Y /usr/all/repository hello</userinput>
- scons: `hello' is up-to-date.
- </literallayout>
+ <literallayout>
+ % <userinput>mkdir $HOME/build2</userinput>
+ % <userinput>cd $HOME/build2</userinput>
+ % <userinput>scons -Y /usr/all/repository hello</userinput>
+ scons: `hello' is up-to-date.
+ </literallayout>
- <para>
+ <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.
+ 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>
+ </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:
+ 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>
+ </para>
- <programlisting>
- env = Environment()
- hello = env.Program('hello.c')
- Local(hello)
- </programlisting>
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ Local(hello)
+ </programlisting>
- <para>
+ <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:
+ 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>
+ </para>
- <literallayout>
- % cons -R /usr/all/repository hello
- Local copy of hello from /usr/all/repository/hello
- scons: `hello' is up-to-date.
- XXXXXX DO WE REALLY REPORT up-to-date, TOO?
- </literallayout>
+ <literallayout>
+ % scons -Y /usr/all/repository hello
+ Local copy of hello from /usr/all/repository/hello
+ scons: `hello' is up-to-date.
+ XXXXXX DO WE REALLY REPORT up-to-date, TOO?
+ </literallayout>
- <para>
+ <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.)
- XXXXXX DO WE REALLY REPORT up-to-date, TOO?
+ (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.)
+ XXXXXX DO WE REALLY REPORT up-to-date, TOO?
- </para>
+ </para>
- </section>
+ </section>
diff --git a/doc/user/separate.sgml b/doc/user/separate.sgml
index e1c0e49..9050eb7 100644
--- a/doc/user/separate.sgml
+++ b/doc/user/separate.sgml
@@ -112,12 +112,178 @@ program using the F<build/foo.c> path name.
<para>
- X
+ It's often useful to keep any built files completely
+ separate from the source files.
+ This is usually done by creating one or more separate
+ <emphasis>build directories</emphasis>
+ that are used to hold the built objects files, libraries,
+ and executable programs, etc.
+ for a specific flavor of build.
+ &SCons; provides two ways of doing this,
+ one with a little more flexibility.
</para>
<section>
- <title>X</title>
+ <title>The &BuildDir; Function</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ BuildDir('build', 'src')
+ env = Environment()
+ env.Program('build/hello.c')
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <literallayout>
+ % <userinput>ls src</userinput>
+ hello.c
+ % <userinput>scons</userinput>
+ cc -c build/hello.c -o build/hello.o
+ cc -o build/hello build/hello.o
+ % <userinput>ls -1 build</userinput>
+ hello
+ hello.c
+ hello.o
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Avoiding Duplicate Source Files in the Build Directory</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ BuildDir('build', 'src', duplicate=0)
+ env = Environment()
+ env.Program('build/hello.c')
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <literallayout>
+ % <userinput>ls -1 src</userinput>
+ hello.c
+ % <userinput>scons</userinput>
+ cc -c src/hello.c -o build/hello.o
+ cc -o build/hello build/hello.o
+ % <userinput>ls -1 build</userinput>
+ hello
+ hello.o
+ </literallayout>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Why &SCons; Duplicates Source Files by Default</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environmnet()
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c build/hello.c -o build/hello.o
+ cc -o build/hello build/hello.o
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Using &BuildDir; With an &SConscript; File</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ BuildDir('build', 'src')
+ SConscript('build/SConscript')
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <literallayout>
+ % <userinput>ls -1 src</userinput>
+ SConscript
+ hello.c
+ % <userinput>scons</userinput>
+ cc -c build/hello.c -o build/hello.o
+ cc -o build/hello build/hello.o
+ % <userinput>ls -1 build</userinput>
+ hello
+ hello.c
+ hello.o
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Specifying a Build Directory as Part of an &SConscript; Call</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript', build_dir='build')
+ </programlisting>
<para>
@@ -125,4 +291,45 @@ program using the F<build/foo.c> path name.
</para>
+ <literallayout>
+ % <userinput>ls -1 src</userinput>
+ SConscript
+ hello.c
+ % <userinput>scons</userinput>
+ cc -c build/hello.c -o build/hello.o
+ cc -o build/hello build/hello.o
+ % <userinput>ls -1 build</userinput>
+ hello
+ hello.c
+ hello.o
+ </literallayout>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript', build_dir='build', duplicate=0)
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <literallayout>
+ % <userinput>ls -1 src</userinput>
+ SConscript
+ hello.c
+ % <userinput>scons</userinput>
+ cc -c src/hello.c -o build/hello.o
+ cc -o build/hello build/hello.o
+ % <userinput>ls -1 build</userinput>
+ hello
+ hello.o
+ </literallayout>
+
</section>
diff --git a/doc/user/simple.sgml b/doc/user/simple.sgml
index 8cafe2d..a86fd34 100644
--- a/doc/user/simple.sgml
+++ b/doc/user/simple.sgml
@@ -147,10 +147,10 @@ requirements of a build.
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;
- Python is extremely easy to learn,
+ Python is very easy to learn,
and this User's Guide will introduce you step-by-step
to the relatively small amount of Python you'll
- neede to know to be able to use &SCons; effectively.
+ need to know to be able to use &SCons; effectively.
</para>
@@ -254,7 +254,7 @@ requirements of a build.
<para>
- One minor drawback to the use of a Python list
+ 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).
diff --git a/doc/user/sourcecode.sgml b/doc/user/sourcecode.sgml
new file mode 100644
index 0000000..4ee49d4
--- /dev/null
+++ b/doc/user/sourcecode.sgml
@@ -0,0 +1,144 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003 Steven Knight
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>Fetching Source Code From BitKeeper</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.BitKeeper('XXX')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From CVS</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.CVS('XXX')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From RCS</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.RCS()
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From SCCS</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.SCCS()
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From Subversion</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.Subversion('XXX')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
diff --git a/doc/user/variants.sgml b/doc/user/variants.sgml
index fdd209e..6ad9360 100644
--- a/doc/user/variants.sgml
+++ b/doc/user/variants.sgml
@@ -122,4 +122,25 @@ is pretty smart about rebuilding things when you change options.
</para>
+ <programlisting>
+ env = Environment(OS = ARGUMENT['os'])
+ SConscript('src/SConscript', build_dir='build/$OS')
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment(OS = )
+ for os in ['newell', 'post']:
+ SConscript('src/SConscript', build_dir='build/' + os)
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ </literallayout>
+
</section>