Branch for User's Guide changes.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 16 Aug 2003 04:19:30 +0000 (04:19 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 16 Aug 2003 04:19:30 +0000 (04:19 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@767 fdb21ef1-2011-0410-befe-b5e4ea1792b1

37 files changed:
SConstruct
bin/sconsexamples.py [new file with mode: 0644]
doc/SConscript
doc/user/actions.in [new file with mode: 0644]
doc/user/alias.in [new file with mode: 0644]
doc/user/ant.in [new file with mode: 0644]
doc/user/builders-built-in.in [new file with mode: 0644]
doc/user/builders-commands.in [new file with mode: 0644]
doc/user/builders-writing.in [new file with mode: 0644]
doc/user/caching.in [new file with mode: 0644]
doc/user/cons.in [new file with mode: 0644]
doc/user/copyright.in [new file with mode: 0644]
doc/user/default.in [new file with mode: 0644]
doc/user/depends.in [new file with mode: 0644]
doc/user/environments.in [new file with mode: 0644]
doc/user/errors.in [new file with mode: 0644]
doc/user/example.in [new file with mode: 0644]
doc/user/help.in [new file with mode: 0644]
doc/user/hierarchy.in [new file with mode: 0644]
doc/user/install.in [new file with mode: 0644]
doc/user/libraries.in [new file with mode: 0644]
doc/user/main.in [new file with mode: 0644]
doc/user/make.in [new file with mode: 0644]
doc/user/precious.in [new file with mode: 0644]
doc/user/preface.in [new file with mode: 0644]
doc/user/repositories.in [new file with mode: 0644]
doc/user/run.in [new file with mode: 0644]
doc/user/scanners.in [new file with mode: 0644]
doc/user/separate.in [new file with mode: 0644]
doc/user/simple.in [new file with mode: 0644]
doc/user/sourcecode.in [new file with mode: 0644]
doc/user/troubleshoot.in [new file with mode: 0644]
doc/user/variants.in [new file with mode: 0644]
src/engine/SCons/Defaults.py
src/engine/SCons/Environment.py
src/engine/SCons/EnvironmentTests.py
test/ToolSurrogate.py [new file with mode: 0644]

index b59c472ffc537126b2461e3c3e61ed433c99190b..fac85238f884df6128a0314f10ea32aaaf26f5d5 100644 (file)
@@ -878,11 +878,9 @@ SConscript('etc/SConscript')
 #
 # Documentation.
 #
-BuildDir('build/doc', 'doc')
-
 Export('env', 'whereis')
 
-SConscript('build/doc/SConscript')
+SConscript('doc/SConscript')
 
 #
 # If we're running in the actual Aegis project, pack up a complete
diff --git a/bin/sconsexamples.py b/bin/sconsexamples.py
new file mode 100644 (file)
index 0000000..5fbdc41
--- /dev/null
@@ -0,0 +1,502 @@
+#!/usr/bin/env python2
+#
+# scons_examples.py -   an SGML preprocessor for capturing SCons output
+#                       and inserting into examples in our DocBook
+#                       documentation
+#
+
+# This script looks for some SGML tags that describe SCons example
+# configurations and commands to execute in those configurations, and
+# uses TestCmd.py to execute the commands and insert the output into
+# the output SGML.  This way, we can run a script and update all of
+# our example output without having to do a lot of laborious by-hand
+# checking.
+#
+# An "SCons example" looks like this, and essentially describes a set of
+# input files (program source files as well as SConscript files):
+#
+#       <scons_example name="ex1">
+#         <file name="SConstruct" printme="1">
+#           env = Environment()
+#           env.Program('foo')
+#         </file>
+#         <file name="foo.c">
+#           int main() { printf("foo.c\n"); }
+#         </file>
+#       </scons_example>
+#
+# The <file> contents within the <scons_example> tag will get written
+# into a temporary directory whenever example output needs to be
+# generated.  By default, the <file> contents are not inserted into text
+# directly, unless you set the "printme" attribute on one or more files,
+# in which case they will get inserted within a <programlisting> tag.
+# This makes it easy to define the example at the appropriate
+# point in the text where you intend to show the SConstruct file.
+#
+# Note that you should usually give the <scons_example> a "name"
+# attribute so that you can refer to the example configuration later to
+# run SCons and generate output.
+#
+# If you just want to show a file's contents without worry about running
+# SCons, there's a shorter <sconstruct> tag:
+#
+#       <sconstruct>
+#         env = Environment()
+#         env.Program('foo')
+#       </sconstruct>
+#
+# This is essentially equivalent to <scons_example><file printme="1">,
+# but it's more straightforward.
+#
+# SCons output is generated from the following sort of tag:
+#
+#       <scons_output example="ex1" os="posix">
+#         <command>scons -Q foo</command>
+#         <command>scons -Q foo</command>
+#       </scons_output>
+#
+# You tell it which example to use with the "example" attribute, and
+# then give it a list of <command> tags to execute.  You can also supply
+# an "os" tag, which specifies the type of operating system this example
+# is intended to show; if you omit this, default value is "posix".
+#
+# The generated SGML will show the command line (with the appropriate
+# command-line prompt for the operating system), execute the command in
+# a temporary directory with the example files, capture the standard
+# output from SCons, and insert it into the text as appropriate.
+# Error output gets passed through to your error output so you
+# can see if there are any problems executing the command.
+#
+
+import os
+import os.path
+import re
+import sgmllib
+import string
+import sys
+
+sys.path.append(os.path.join(os.getcwd(), 'etc'))
+sys.path.append(os.path.join(os.getcwd(), 'build', 'etc'))
+
+scons_py = os.path.join('bootstrap', 'src', 'script', 'scons.py')
+if not os.path.exists(scons_py):
+    scons_py = os.path.join('src', 'script', 'scons.py')
+
+scons_lib_dir = os.path.join(os.getcwd(), 'bootstrap', 'src', 'engine')
+if not os.path.exists(scons_lib_dir):
+    scons_lib_dir = os.path.join(os.getcwd(), 'src', 'engine')
+
+import TestCmd
+
+# The regular expression that identifies entity references in the
+# standard sgmllib omits the underscore from the legal characters.
+# Override it with our own regular expression that adds underscore.
+sgmllib.entityref = re.compile('&([a-zA-Z][-_.a-zA-Z0-9]*)[^-_a-zA-Z0-9]')
+
+class DataCollector:
+    """Generic class for collecting data between a start tag and end
+    tag.  We subclass for various types of tags we care about."""
+    def __init__(self):
+        self.data = ""
+    def afunc(self, data):
+        self.data = self.data + data
+
+class Example(DataCollector):
+    """An SCons example.  This is essentially a list of files that
+    will get written to a temporary directory to collect output
+    from one or more SCons runs."""
+    def __init__(self):
+        DataCollector.__init__(self)
+        self.files = []
+        self.dirs = []
+
+class File(DataCollector):
+    """A file, that will get written out to a temporary directory
+    for one or more SCons runs."""
+    def __init__(self, name):
+        DataCollector.__init__(self)
+        self.name = name
+
+class Directory(DataCollector):
+    """A directory, that will get created in a temporary directory
+    for one or more SCons runs."""
+    def __init__(self, name):
+        DataCollector.__init__(self)
+        self.name = name
+
+class Output(DataCollector):
+    """Where the command output goes.  This is essentially
+    a list of commands that will get executed."""
+    def __init__(self):
+        DataCollector.__init__(self)
+        self.commandlist = []
+
+class Command(DataCollector):
+    """A tag for where the command output goes.  This is essentially
+    a list of commands that will get executed."""
+    pass
+
+Prompt = {
+    'posix' : '% ',
+    'win32' : 'C:\\>'
+}
+
+# Magick SCons hackery.
+#
+# So that our examples can still use the default SConstruct file, we
+# actually feed the following into SCons via stdin and then have it
+# SConscript() the SConstruct file.  This stdin wrapper creates a set
+# of ToolSurrogates for the tools for the appropriate platform.  These
+# Surrogates print output like the real tools and behave like them
+# without actually having to be on the right platform or have the right
+# tool installed.
+#
+# The upshot:  We transparently change the world out from under the
+# top-level SConstruct file in an example just so we can get the
+# command output.
+
+Stdin = """\
+import SCons.Defaults
+
+platform = '%s'
+
+class Curry:
+    def __init__(self, fun, *args, **kwargs):
+        self.fun = fun
+        self.pending = args[:]
+        self.kwargs = kwargs.copy()
+
+    def __call__(self, *args, **kwargs):
+        if kwargs and self.kwargs:
+            kw = self.kwargs.copy()
+            kw.update(kwargs)
+        else:
+            kw = kwargs or self.kwargs
+
+        return apply(self.fun, self.pending + args, kw)
+
+def Str(target, source, env, cmd=""):
+    return env.subst(cmd, target=target, source=source)
+
+class ToolSurrogate:
+    def __init__(self, tool, variable, func):
+        self.tool = tool
+        self.variable = variable
+        self.func = func
+    def __call__(self, env):
+        t = Tool(self.tool)
+        t.generate(env)
+        orig = env[self.variable]
+        env[self.variable] = Action(self.func, strfunction=Curry(Str, cmd=orig))
+
+def Null(target, source, env):
+    pass
+
+def Cat(target, source, env):
+    target = str(target[0])
+    f = open(target, "wb")
+    for src in map(str, source):
+        f.write(open(src, "rb").read())
+    f.close()
+
+ToolList = {
+    'posix' :   [('cc', 'CCCOM', Cat),
+                 ('link', 'LINKCOM', Cat),
+                 ('tar', 'TARCOM', Null),
+                 ('zip', 'ZIPCOM', Null)],
+    'win32' :   [('msvc', 'CCCOM', Cat),
+                 ('mslink', 'LINKCOM', Cat)]
+}
+
+tools = map(lambda t: apply(ToolSurrogate, t), ToolList[platform])
+
+SCons.Defaults.ConstructionEnvironment.update({
+    'PLATFORM' : platform,
+    'TOOLS'    : tools,
+})
+
+SConscript('SConstruct')
+"""
+
+class MySGML(sgmllib.SGMLParser):
+    """A subclass of the standard Python 2.2 sgmllib SGML parser.
+
+    Note that this doesn't work with the 1.5.2 sgmllib module, because
+    that didn't have the ability to work with ENTITY declarations.
+    """
+    def __init__(self):
+        sgmllib.SGMLParser.__init__(self)
+        self.examples = {}
+        self.afunclist = []
+
+    def handle_data(self, data):
+        try:
+            f = self.afunclist[-1]
+        except IndexError:
+            sys.stdout.write(data)
+        else:
+            f(data)
+
+    def handle_comment(self, data):
+        sys.stdout.write('<!--' + data + '-->')
+
+    def handle_decl(self, data):
+        sys.stdout.write('<!' + data + '>')
+
+    def unknown_starttag(self, tag, attrs):
+        try:
+            f = self.example.afunc
+        except AttributeError:
+            f = sys.stdout.write
+        if not attrs:
+            f('<' + tag + '>')
+        else:
+            f('<' + tag)
+            for name, value in attrs:
+                f(' ' + name + '=' + '"' + value + '"')
+            f('>')
+
+    def unknown_endtag(self, tag):
+        sys.stdout.write('</' + tag + '>')
+
+    def unknown_entityref(self, ref):
+        sys.stdout.write('&' + ref + ';')
+
+    def unknown_charref(self, ref):
+        sys.stdout.write('&#' + ref + ';')
+
+    def start_scons_example(self, attrs):
+        t = filter(lambda t: t[0] == 'name', attrs)
+        if t:
+            name = t[0][1]
+            try:
+               e = self.examples[name]
+            except KeyError:
+               e = self.examples[name] = Example()
+        else:
+            e = Example()
+        for name, value in attrs:
+            setattr(e, name, value)
+        self.e = e
+        self.afunclist.append(e.afunc)
+
+    def end_scons_example(self):
+        e = self.e
+        files = filter(lambda f: f.printme, e.files)
+        if files:
+            sys.stdout.write('<programlisting>')
+            for f in files:
+                if f.printme:
+                    i = len(f.data) - 1
+                    while f.data[i] == ' ':
+                        i = i - 1
+                    output = string.replace(f.data[:i+1], '__ROOT__', '')
+                    sys.stdout.write(output)
+            if e.data and e.data[0] == '\n':
+                e.data = e.data[1:]
+            sys.stdout.write(e.data + '</programlisting>')
+        delattr(self, 'e')
+        self.afunclist = self.afunclist[:-1]
+
+    def start_file(self, attrs):
+        try:
+            e = self.e
+        except AttributeError:
+            self.error("<file> tag outside of <scons_example>")
+        t = filter(lambda t: t[0] == 'name', attrs)
+        if not t:
+            self.error("no <file> name attribute found")
+        try:
+            e.prefix
+        except AttributeError:
+            e.prefix = e.data
+            e.data = ""
+        f = File(t[0][1])
+        f.printme = None
+        for name, value in attrs:
+            setattr(f, name, value)
+        e.files.append(f)
+        self.afunclist.append(f.afunc)
+
+    def end_file(self):
+        self.e.data = ""
+        self.afunclist = self.afunclist[:-1]
+
+    def start_directory(self, attrs):
+        try:
+            e = self.e
+        except AttributeError:
+            self.error("<directory> tag outside of <scons_example>")
+        t = filter(lambda t: t[0] == 'name', attrs)
+        if not t:
+            self.error("no <directory> name attribute found")
+        try:
+            e.prefix
+        except AttributeError:
+            e.prefix = e.data
+            e.data = ""
+        d = Directory(t[0][1])
+        for name, value in attrs:
+            setattr(d, name, value)
+        e.dirs.append(d)
+        self.afunclist.append(d.afunc)
+
+    def end_directory(self):
+        self.e.data = ""
+        self.afunclist = self.afunclist[:-1]
+
+    def start_scons_example_file(self, attrs):
+        t = filter(lambda t: t[0] == 'example', attrs)
+        if not t:
+            self.error("no <scons_example_file> example attribute found")
+        exname = t[0][1]
+        try:
+            e = self.examples[exname]
+        except KeyError:
+            self.error("unknown example name '%s'" % exname)
+        fattrs = filter(lambda t: t[0] == 'name', attrs)
+        if not fattrs:
+            self.error("no <scons_example_file> name attribute found")
+        fname = fattrs[0][1]
+        f = filter(lambda f, fname=fname: f.name == fname, e.files)
+        if not f:
+            self.error("example '%s' does not have a file named '%s'" % (exname, fname))
+        self.f = f[0]
+
+    def end_scons_example_file(self):
+        f = self.f
+        sys.stdout.write('<programlisting>')
+        i = len(f.data) - 1
+        while f.data[i] == ' ':
+            i = i - 1
+        sys.stdout.write(f.data[:i+1] + '</programlisting>')
+        delattr(self, 'f')
+
+    def start_scons_output(self, attrs):
+        t = filter(lambda t: t[0] == 'example', attrs)
+        if not t:
+            self.error("no <scons_output> example attribute found")
+        exname = t[0][1]
+        try:
+            e = self.examples[exname]
+        except KeyError:
+            self.error("unknown example name '%s'" % exname)
+        # Default values for an example.
+        o = Output()
+        o.os = 'posix'
+        o.e = e
+        # Locally-set.
+        for name, value in attrs:
+            setattr(o, name, value)
+        self.o = o
+        self.afunclist.append(o.afunc)
+
+    def end_scons_output(self):
+        o = self.o
+        e = o.e
+        t = TestCmd.TestCmd(workdir='', combine=1)
+        t.subdir('ROOT', 'WORK')
+        for d in e.dirs:
+            dir = t.workpath('WORK', d.name)
+            if not os.path.exists(dir):
+                os.makedirs(dir)
+        for f in e.files:
+            i = 0
+            while f.data[i] == '\n':
+                i = i + 1
+            lines = string.split(f.data[i:], '\n')
+            i = 0
+            while lines[0][i] == ' ':
+                i = i + 1
+            lines = map(lambda l, i=i: l[i:], lines)
+            path = string.replace(f.name, '__ROOT__', t.workpath('ROOT'))
+            dir, name = os.path.split(f.name)
+            if dir:
+                dir = t.workpath('WORK', dir)
+                if not os.path.exists(dir):
+                    os.makedirs(dir)
+            content = string.join(lines, '\n')
+            content = string.replace(content,
+                                     '__ROOT__',
+                                     t.workpath('ROOT'))
+            t.write(t.workpath('WORK', f.name), content)
+        i = len(o.prefix)
+        while o.prefix[i-1] != '\n':
+            i = i - 1
+        sys.stdout.write('<literallayout>' + o.prefix[:i])
+        p = o.prefix[i:]
+        for c in o.commandlist:
+            sys.stdout.write(p + Prompt[o.os])
+            d = string.replace(c.data, '__ROOT__', '')
+            sys.stdout.write('<userinput>' + d + '</userinput>\n')
+            e = string.replace(c.data, '__ROOT__', t.workpath('ROOT'))
+            args = string.split(e)[1:]
+            os.environ['SCONS_LIB_DIR'] = scons_lib_dir
+            t.run(interpreter = sys.executable,
+                  program = scons_py,
+                  arguments = '-f - ' + string.join(args),
+                  chdir = t.workpath('WORK'),
+                  stdin = Stdin % o.os)
+            out = string.replace(t.stdout(), t.workpath('ROOT'), '')
+            if out:
+                lines = string.split(out, '\n')
+                if lines:
+                    while lines[-1] == '':
+                        lines = lines[:-1]
+                    for l in lines:
+                        sys.stdout.write(p + l + '\n')
+            #err = t.stderr()
+            #if err:
+            #    sys.stderr.write(err)
+        if o.data[0] == '\n':
+            o.data = o.data[1:]
+        sys.stdout.write(o.data + '</literallayout>')
+        delattr(self, 'o')
+        self.afunclist = self.afunclist[:-1]
+
+    def start_command(self, attrs):
+        try:
+            o = self.o
+        except AttributeError:
+            self.error("<command> tag outside of <scons_output>")
+        try:
+            o.prefix
+        except AttributeError:
+            o.prefix = o.data
+            o.data = ""
+        c = Command()
+        o.commandlist.append(c)
+        self.afunclist.append(c.afunc)
+
+    def end_command(self):
+        self.o.data = ""
+        self.afunclist = self.afunclist[:-1]
+
+    def start_sconstruct(self, attrs):
+        sys.stdout.write('<programlisting>')
+
+    def end_sconstruct(self):
+        sys.stdout.write('</programlisting>')
+
+try:
+    file = sys.argv[1]
+except IndexError:
+    file = '-'
+
+if file == '-':
+    f = sys.stdin
+else:
+    try:
+        f = open(file, 'r')
+    except IOError, msg:
+        print file, ":", msg
+        sys.exit(1)
+
+data = f.read()
+if f is not sys.stdin:
+    f.close()
+
+x = MySGML()
+for c in data:
+    x.feed(c)
+x.close()
index 25ad6bf5223a92287d05a0cb2f1fdfcd6f07b9cd..e3b6eff53c1f8732a8406dc2014032c299069249 100644 (file)
@@ -31,6 +31,8 @@ import string
 
 Import('env', 'whereis')
 
+build = os.path.join('#build', 'doc')
+
 #
 #
 #
@@ -53,7 +55,7 @@ jw = whereis('jw')
 tidy = whereis('tidy')
 
 tar_deps = []
-tar_list = ""
+tar_list = []
 
 entity_re = re.compile(r'<!entity\s+(?:%\s+)?(?:\S+)\s+SYSTEM\s+"([^"]*)">', re.I)
 format_re = re.compile(r'<(?:graphic|imagedata)\s+fileref="([^"]*)"(?:\s+format="([^"]*)")?')
@@ -104,7 +106,9 @@ if jw:
     # rebuild all the docs every time just because the date changes.
     #
     date, ver, rev = env.Dictionary('DATE', 'VERSION', 'REVISION')
-    verfile = str(File("version.sgml"))
+    #version_sgml = File(os.path.join(build, "version.sgml"))
+    version_sgml = File("version.sgml")
+    verfile = str(version_sgml)
     try:
         os.unlink(verfile)
     except OSError:
@@ -174,12 +178,17 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE.  DO NOT EDIT.
         main = os.path.join(doc, 'main.sgml')
         out = 'main.out'
 
-        htmldir = os.path.join('HTML', 'scons-%s' % doc)
+        # Hard-coding the scons-src path is a bit of a hack.  This can
+        # be reworked when a better solution presents itself.
+        scons_src_main = os.path.join('#build', 'scons-src', 'doc', main)
+        env.Ignore(scons_src_main, version_sgml)
+
+        htmldir = os.path.join(build, 'HTML', 'scons-%s' % doc)
         htmlindex = os.path.join(htmldir, docs[doc]['htmlindex'])
-        html = os.path.join('HTML', 'scons-%s.html' % doc)
-        ps = os.path.join('PS', 'scons-%s.ps' % doc)
-        pdf = os.path.join('PDF', 'scons-%s.pdf' % doc)
-        text = os.path.join('TEXT', 'scons-%s.txt' % doc)
+        html = os.path.join(build, 'HTML', 'scons-%s.html' % doc)
+        ps = os.path.join(build, 'PS', 'scons-%s.ps' % doc)
+        pdf = os.path.join(build, 'PDF', 'scons-%s.pdf' % doc)
+        text = os.path.join(build, 'TEXT', 'scons-%s.txt' % doc)
 
         if docs[doc].get('html') and jade:
             cmds = [
@@ -202,10 +211,10 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE.  DO NOT EDIT.
             env.Command(html, main, cmds)
             Local(html)
 
-            env.Ignore([html, htmlindex], "version.sgml")
+            env.Ignore([html, htmlindex], version_sgml)
 
             tar_deps.extend([html, htmlindex])
-            tar_list = string.join([tar_list, html, htmldir], " ")
+            tar_list.extend([html, htmldir])
 
             if fig2dev:
                 for g in docs[doc].get('graphics', []):
@@ -225,15 +234,15 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE.  DO NOT EDIT.
             ])
             Local(ps)
 
-            env.Ignore(ps, "version.sgml")
+            env.Ignore(ps, version_sgml)
 
             tar_deps.append(ps)
-            tar_list = tar_list + " " + ps
+            tar_list.append(ps)
 
             if fig2dev:
                 for g in docs[doc].get('graphics', []):
                     fig = os.path.join(doc, '%s.fig' % g)
-                    eps = os.path.join('PS', '%s.eps' % g)
+                    eps = os.path.join(build, 'PS', '%s.eps' % g)
                     env.Command(eps, fig, "%s -L eps $SOURCES $TARGET" % fig2dev)
                     env.Depends(ps, eps)
                     Local(eps)
@@ -247,19 +256,19 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE.  DO NOT EDIT.
             ])
             Local(pdf)
 
-            env.Ignore(pdf, "version.sgml")
+            env.Ignore(pdf, version_sgml)
 
             tar_deps.append(pdf)
-            tar_list = tar_list + " " + pdf
+            tar_list.append(pdf)
 
         if docs[doc].get('text') and jade and lynx:
             env.Command(text, html, "lynx -dump ${SOURCE.abspath} > $TARGET")
             Local(text)
 
-            env.Ignore(text, "version.sgml")
+            env.Ignore(text, version_sgml)
 
             tar_deps.append(text)
-            tar_list = tar_list + " " + text
+            tar_list.append(text)
 
 #
 # Man page(s), in good ol' troff format.
@@ -270,8 +279,8 @@ for man in man_page_list:
     man_1 = os.path.join('man', '%s.1' % man)
 
     if groff:
-        ps = os.path.join('PS', '%s-man.ps' % man)
-        text = os.path.join('TEXT', '%s-man.txt' % man)
+        ps = os.path.join(build, 'PS', '%s-man.ps' % man)
+        text = os.path.join(build, 'TEXT', '%s-man.txt' % man)
 
         env.Command(ps, man_1, "groff -man -Tps $SOURCES > $TARGET")
         Local(ps)
@@ -280,10 +289,10 @@ for man in man_page_list:
         Local(text)
 
         tar_deps.extend([ps, text])
-        tar_list = string.join([tar_list, ps, text], " ")
+        tar_list.extend([ps, text])
 
     if man2html:
-        html = os.path.join('HTML' , '%s-man.html' % man)
+        html = os.path.join(build, 'HTML' , '%s-man.html' % man)
 
         cmds = [ "man2html $SOURCES > $TARGET" ]
         if tidy:
@@ -292,13 +301,14 @@ for man in man_page_list:
         Local(html)
 
         tar_deps.append(html)
-        tar_list = tar_list + " " + html
+        tar_list.append(html)
 
 #
 # Now actually create the tar file of the documentation,
 # for easy distribution to the web site.
 #
 if tar_deps:
+    tar_list = map(lambda x: x[11:], tar_list)
     env.Command(doc_tar_gz, tar_deps,
                 "tar cf${TAR_HFLAG} - -C build/doc %s | gzip > $TARGET" % tar_list)
     Local(doc_tar_gz)
diff --git a/doc/user/actions.in b/doc/user/actions.in
new file mode 100644 (file)
index 0000000..c35ccdd
--- /dev/null
@@ -0,0 +1,240 @@
+<!--
+
+  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.
+
+-->
+
+<!--
+
+=head1 Build actions
+
+Cons supports several types of B<build actions> that can be performed
+to construct one or more target files.  Usually, a build action is
+a construction command, that is, a command-line string that invokes
+an external command.  Cons can also execute Perl code embedded in a
+command-line string, and even supports an experimental ability to build
+a target file by executing a Perl code reference directly.
+
+A build action is usually specified as the value of a construction
+variable:
+
+  $env = new cons(
+       CCCOM         => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
+       LINKCOM       => '[perl] &link_executable("%>", "%<")',
+       ARCOM         => sub { my($env, $target, @sources) = @_;
+                                # code to create an archive
+                               }
+  );
+
+A build action may be associated directly with one or more target files
+via the C<Command> method; see below.
+
+=head2 Construction commands
+
+A construction command goes through expansion of construction variables
+and C<%-> pseudo-variables, as described above, to create the actual
+command line that Cons will execute to generate the target file or
+files.
+
+After substitution occurs, strings of white space are converted into
+single blanks, and leading and trailing white space is eliminated. It
+is therefore currently not possible to introduce variable length white
+space in strings passed into a command.
+
+If a multi-line command string is provided, the commands are executed
+sequentially. If any of the commands fails, then none of the rest are
+executed, and the target is not marked as updated, i.e. a new signature is
+not stored for the target.
+
+Normally, if all the commands succeed, and return a zero status (or whatever
+platform-specific indication of success is required), then a new signature
+is stored for the target. If a command erroneously reports success even
+after a failure, then Cons will assume that the target file created by that
+command is accurate and up-to-date.
+
+The first word of each command string, after expansion, is assumed to be an
+executable command looked up on the C<PATH> environment variable (which is,
+in turn, specified by the C<ENV> construction variable). If this command is
+found on the path, then the target will depend upon it: the command will
+therefore be automatically built, as necessary. It's possible to write
+multi-part commands to some shells, separated by semi-colons. Only the first
+command word will be depended upon, however, so if you write your command
+strings this way, you must either explicitly set up a dependency (with the
+C<Depends> method), or be sure that the command you are using is a system
+command which is expected to be available. If it isn't available, you will,
+of course, get an error.
+
+Cons normally prints a command before executing it.  This behavior is
+suppressed if the first character of the command is C<@>.  Note that
+you may need to separate the C<@> from the command name or escape it to
+prevent C<@cmd> from looking like an array to Perl quote operators that
+perform interpolation:
+
+  # The first command line is incorrect,
+  # because "@cp" looks like an array
+  # to the Perl qq// function.
+  # Use the second form instead.
+  Command $env 'foo', 'foo.in', qq(
+       @cp %< tempfile
+       @ cp tempfile %>
+  );
+
+If there are shell meta characters anywhere in the expanded command line,
+such as C<E<lt>>, C<E<gt>>, quotes, or semi-colon, then the command
+will actually be executed by invoking a shell. This means that a command
+such as:
+
+  cd foo
+
+alone will typically fail, since there is no command C<cd> on the path. But
+the command string:
+
+  cd $<:d; tar cf $>:f $<:f
+
+when expanded will still contain the shell meta character semi-colon, and a
+shell will be invoked to interpret the command. Since C<cd> is interpreted
+by this sub-shell, the command will execute as expected.
+
+=head2 Perl expressions
+
+If any command (even one within a multi-line command) begins with
+C<[perl]>, the remainder of that command line will be evaluated by the
+running Perl instead of being forked by the shell.  If an error occurs
+in parsing the Perl code, or if the Perl expression returns 0 or undef,
+the command will be considered to have failed.  For example, here is a
+simple command which creates a file C<foo> directly from Perl:
+
+  $env = new cons();
+  Command $env 'foo',
+    qq([perl] open(FOO,'>foo');print FOO "hi\\n"; close(FOO); 1);
+
+Note that when the command is executed, you are in the same package as
+when the F<Construct> or F<Conscript> file was read, so you can call
+Perl functions you've defined in the same F<Construct> or F<Conscript>
+file in which the C<Command> appears:
+
+  $env = new cons();
+  sub create_file {
+       my $file = shift;
+       open(FILE, ">$file");
+       print FILE "hi\n";
+       close(FILE);
+       return 1;
+  }
+  Command $env 'foo', "[perl] &create_file('%>')";
+
+The Perl string will be used to generate the signature for the derived
+file, so if you change the string, the file will be rebuilt.  The contents
+of any subroutines you call, however, are not part of the signature,
+so if you modify a called subroutine such as C<create_file> above,
+the target will I<not> be rebuilt.  Caveat user.
+
+=head2 Perl code references [EXPERIMENTAL]
+
+Cons supports the ability to create a derived file by directly executing
+a Perl code reference.  This feature is considered EXPERIMENTAL and
+subject to change in the future.
+
+A code reference may either be a named subroutine referenced by the
+usual C<\&> syntax:
+
+  sub build_output {
+       my($env, $target, @sources) = @_;
+       print "build_output building $target\n";
+       open(OUT, ">$target");
+       foreach $src (@sources) {
+           if (! open(IN, "<$src")) {
+               print STDERR "cannot open '$src': $!\n";
+               return undef;
+           }
+           print OUT, <IN>;
+       }
+       close(OUT);
+       return 1;
+  }
+  Command $env 'output', \&build_output;
+
+or the code reference may be an anonymous subroutine:
+
+  Command $env 'output', sub {
+       my($env, $target, @sources) = @_;
+       print "building $target\n";
+       open(FILE, ">$target");
+       print FILE "hello\n";
+       close(FILE);
+       return 1;
+  };
+
+To build the target file, the referenced subroutine is passed, in order:
+the construction environment used to generate the target; the path
+name of the target itself; and the path names of all the source files
+necessary to build the target file.
+
+The code reference is expected to generate the target file, of course,
+but may manipulate the source and target files in any way it chooses.
+The code reference must return a false value (C<undef> or C<0>) if
+the build of the file failed.  Any true value indicates a successful
+build of the target.
+
+Building target files using code references is considered EXPERIMENTAL
+due to the following current limitations:
+
+=over 4
+
+Cons does I<not> print anything to indicate the code reference is being
+called to build the file.  The only way to give the user any indication
+is to have the code reference explicitly print some sort of "building"
+message, as in the above examples.
+
+Cons does not generate any signatures for code references, so if the
+code in the reference changes, the target will I<not> be rebuilt.
+
+Cons has no public method to allow a code reference to extract
+construction variables.  This would be good to allow generalization of
+code references based on the current construction environment, but would
+also complicate the problem of generating meaningful signatures for code
+references.
+
+=back
+
+Support for building targets via code references has been released in
+this version to encourage experimentation and the seeking of possible
+solutions to the above limitations.
+
+-->
+
+ <para>
+
+   XXX
+
+ </para>
+
+ <section>
+ <title>XXX</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
diff --git a/doc/user/alias.in b/doc/user/alias.in
new file mode 100644 (file)
index 0000000..22fc128
--- /dev/null
@@ -0,0 +1,102 @@
+<!--
+
+  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>
+
+  We've already seen how you can use the &Alias;
+  function to create a target named <literal>install</literal>:
+
+  </para>
+
+  <scons_example name="ex1">
+     <file name="SConstruct" printme="1">
+     env = Environment()
+     hello = env.Program('hello.c')
+     env.Install('__ROOT__/usr/bin', hello)
+     env.Alias('install', '__ROOT__/usr/bin')
+     </file>
+     <file name="hello.c">
+     int main() { printf("Hello, world!\n"); }
+     </file>
+  </scons_example>
+
+  <para>
+
+  You can then use this alias on the command line
+  to tell &SCons; more naturally that you want to install files:
+
+  </para>
+
+  <scons_output example="ex1" os="posix">
+     <command>scons install</command>
+  </scons_output>
+
+  <para>
+
+  Like other &Builder; methods, though,
+  the &Alias; method returns an object
+  representing the alias being built.
+  You can then use this object as input to anothother &Builder;.
+  This is especially useful if you use such an object
+  as input to another call to the &Alias; &Builder;,
+  allowing you to create a hierarchy
+  of nested aliases:
+
+  </para>
+
+  <scons_example name="ex2">
+     <file name="SConstruct" printme="1">
+     env = Environment()
+     p = env.Program('foo.c')
+     l = env.Library('bar.c')
+     env.Install('__ROOT__/usr/bin', p)
+     env.Install('__ROOT__/usr/lib', l)
+     ib = env.Alias('install-bin', '__ROOT__/usr/bin')
+     il = env.Alias('install-lib', '__ROOT__/usr/lib')
+     env.Alias('install', [ib, il])
+     </file>
+     <file name="foo.c">
+     int main() { printf("foo.c\n"); }
+     </file>
+     <file name="bar.c">
+     void bar() { printf("bar.c\n"); }
+     </file>
+  </scons_example>
+
+  <para>
+
+  This example defines separate <literal>install</literal>,
+  <literal>install-bin</literal>,
+  and <literal>install-lib</literal> aliases,
+  allowing you finer control over what gets installed:
+
+  </para>
+
+  <scons_output example="ex2" os="posix">
+     <command>scons install-bin</command>
+     <command>scons install-lib</command>
+     <command>scons -c __ROOT__/</command>
+     <command>scons install</command>
+  </scons_output>
diff --git a/doc/user/ant.in b/doc/user/ant.in
new file mode 100644 (file)
index 0000000..4eb5007
--- /dev/null
@@ -0,0 +1,52 @@
+<!--
+
+  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>
+
+   XXX
+
+ </para>
+
+ <section>
+ <title>Differences Between &Ant; and &SCons;</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
+
+ <section>
+ <title>Advantages of &SCons; Over &Ant;</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
diff --git a/doc/user/builders-built-in.in b/doc/user/builders-built-in.in
new file mode 100644 (file)
index 0000000..89f0af3
--- /dev/null
@@ -0,0 +1,652 @@
+<!--
+
+  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>
+
+  &SCons; provides the ability to build a lot of different
+  types of files right "out of the box."
+  So far, we've been using &SCons;' ability to build
+  programs, objects and libraries to
+  illustrate much of the underlying functionality of &SCons;
+  This section will describe all of the different
+  types of files that you can build with &SCons;,
+  and the built-in &Builder; objects used to build them.
+
+  </para>
+
+  <section>
+  <title>Programs:  the &Program; Builder</title>
+
+    <para>
+
+    As we've seen, the &Program; Builder
+    is used to build an executable program.
+    The &source; argument is one or more
+    source-code files or object files,
+    and the &target; argument is the
+    name of the executable program name to be created.
+    For example:
+
+    </para>
+
+    <programlisting>
+      env = Environment()
+      env.Program('prog', 'file1.o')
+    </programlisting>
+
+    <para>
+
+    Will create the &prog;
+    executable on a POSIX system,
+    the &prog_exe; executable on a Windows system.
+
+    </para>
+
+    <para>
+
+    The target file's prefix and suffix may be omitted,
+    and the values from the
+    $PROGPREFIX
+    and
+    $PROGSUFFIX
+    construction variables
+    will be appended appropriately.
+    For example:
+
+    </para>
+
+    <programlisting>
+      env = Environment(PROGPREFIX='my', PROGSUFFIX='.xxx')
+      env.Program('prog', ['file1.o', 'file2.o'])
+    </programlisting>
+
+    <para>
+
+    Will create a program named
+    <filename>myprog.xxx</filename>
+    regardless of the system on which it is run.
+
+    </para>
+
+    <para>
+
+    If you omit the &target;,
+    the base of the first input
+    file name specified
+    because the base of the target
+    program created.
+    For example:
+
+    </para>
+
+    <programlisting>
+      env = Environment()
+      env.Program(['hello.c', 'goodbye.c'])
+    </programlisting>
+
+    <para>
+
+    Will create the &hello;
+    executable on a POSIX system,
+    the &hello_exe; executable on a Windows system.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Object-File Builders</title>
+
+    <para>
+
+    &SCons; provides separate Builder objects
+    to create both static and shared object files.
+
+    </para>
+
+    <section>
+    <title>The &StaticObject; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+    <section>
+    <title>The &SharedObject; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+    <section>
+    <title>The &Object; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <para>
+
+      Creates a static object file.
+
+      </para>
+
+    </section>
+
+  </section>
+
+  <section>
+  <title>Library Builders</title>
+
+    <para>
+
+    &SCons; provides separate Builder objects
+    to create both static and shared libraries.
+
+    </para>
+
+    <section>
+    <title>The &StaticLibrary; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+    <section>
+    <title>The &SharedLibrary; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+    </section>
+
+    <section>
+    <title>The &Library; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+      <para>
+
+      Creates a static library file.
+
+      </para>
+
+    </section>
+
+  </section>
+
+  <section>
+  <title>Pre-Compiled Headers:  the &PCH; Builder</title>
+
+    <para>
+
+    XXX
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Microsoft Visual C++ Resource Files: the &RES; Builder</title>
+
+    <para>
+
+    XXX
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Source Files</title>
+
+    <para>
+
+    By default
+    &SCons; supports two Builder objects
+    that know how to build source files
+    from other input files.
+
+    </para>
+
+    <section>
+    <title>The &CFile; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+    <section>
+    <title>The &CXXFile; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+  </section>
+
+  <section>
+  <title>Documents</title>
+
+    <para>
+
+    &SCons; provides a number of Builder objects
+    for creating different types of documents.
+
+    </para>
+
+    <section>
+    <title>The &DVI; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+    <section>
+    <title>The &PDF; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+    </section>
+
+    <section>
+    <title>The &PostScript; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+  </section>
+
+  <section>
+  <title>Archives</title>
+
+    <para>
+
+    &SCons; provides Builder objects
+    for creating two different types of archive files.
+
+    </para>
+
+    <section>
+    <title>The &Tar; Builder</title>
+
+      <para>
+
+      The &Tar; Builder object uses the &tar;
+      utility to create archives of files
+      and/or directory trees:
+
+      </para>
+
+      <scons_example name="ex1">
+        <file name="SConstruct" printme="1">
+        env = Environment()
+        env.Tar('out1.tar', ['file1', 'file2'])
+        env.Tar('out2', 'directory')
+        </file>
+        <file name="file1">
+        file1
+        </file>
+        <file name="file2">
+        file2
+        </file>
+        <file name="directory/file3">
+        directory/file3
+        </file>
+      </scons_example>
+
+      <scons_output example="ex1" os="posix">
+        <command>scons .</command>
+      </scons_output>
+
+      <para>
+
+      One common requirement when creating a &tar; archive
+      is to create a compressed archive using the
+      <option>-z</option> option.
+      This is easily handled by specifying
+      the value of the &TARFLAGS; variable
+      when you create the construction environment.
+      Note, however, that the <option>-c</option> used to
+      to instruct &tar; to create the archive
+      is part of the default value of &TARFLAGS;,
+      so you need to set it both options:
+
+      </para>
+
+      <scons_example name="ex2">
+        <file name="SConstruct" printme="1">
+        env = Environment(TARFLAGS = '-c -z')
+        env.Tar('out.tar.gz', 'directory')
+        </file>
+        <file name="directory/file">
+        directory/file
+        </file>
+      </scons_example>
+
+      <scons_output example="ex2" os="posix">
+        <command>scons .</command>
+      </scons_output>
+
+      <para>
+
+      you may also wish to set the value of the
+      &TARSUFFIX; construction variable
+      to your desired suffix for compress &tar; archives,
+      so that &SCons; can append it to the target file name
+      without your having to specify it explicitly:
+
+      </para>
+
+      <scons_example name="ex3">
+        <file name="SConstruct" printme="1">
+        env = Environment(TARFLAGS = '-c -z',
+                          TARSUFFIX = '.tgz')
+        env.Tar('out', 'directory')
+        </file>
+        <file name="directory/file">
+        directory/file
+        </file>
+      </scons_example>
+
+      <scons_output example="ex3" os="posix">
+        <command>scons .</command>
+      </scons_output>
+
+    </section>
+
+    <section>
+    <title>The &Zip; Builder</title>
+
+      <para>
+
+      The &Zip; Builder object creates archives of files
+      and/or directory trees in the ZIP file format.
+      Python versions 1.6 or later
+      contain an internal &zipfile; module
+      that &SCons; will use.
+      In this case, given the following
+      &SConstruct; file:
+
+      </para>
+
+      <scons_example name="ex4">
+        <file name="SConstruct" printme="1">
+        env = Environment()
+        env.Zip('out', ['file1', 'file2'])
+        </file>
+        <file name="file1">
+        file1
+        </file>
+        <file name="file2">
+        file2
+        </file>
+      </scons_example>
+
+      <para>
+
+      Your output will reflect the fact
+      that an internal Python function
+      is being used to create the output ZIP archive:
+
+      </para>
+
+      <scons_output example="ex4" os="posix">
+        <command>scons .</command>
+      </scons_output>
+
+      <para>
+
+      If you're using Python version 1.5.2 to run &SCons;,
+      then &SCons; will try to use an external
+      &zip; program as follows:
+
+      </para>
+
+      <literallayout>
+        % <userinput>scons .</userinput>
+        zip /home/my/project/zip.out file1 file2
+      </literallayout>
+
+    </section>
+
+  </section>
+
+  <section>
+  <title>Java</title>
+
+    <para>
+
+    &SCons; provides Builder objects
+    for creating various types of Java output files.
+
+    </para>
+
+    <section>
+    <title>Building Class Files:  the &Java; Builder</title>
+
+      <para>
+
+      The &Java; builder takes one or more input
+      <filename>.java</filename> files
+      and turns them into one or more
+      <filename>.class</filename> files
+      Unlike most builders, however,
+      the &Java; builder takes
+      target and source <emphasis>directories</emphasis>,
+      not files, as input.
+
+      </para>
+
+      <programlisting>
+        env = Environment()
+        env.Java(target = 'classes', source = 'src')
+      </programlisting>
+
+      <para>
+
+      The &Java; builder will then
+      search the specified source directory
+      tree for all <filename>.java</filename> files,
+      and pass any out-of-date
+
+      </para>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+    <section>
+    <title>The &Jar; Builder</title>
+
+      <para>
+
+      The &Jar; builder object XXX
+
+      </para>
+
+      <programlisting>
+        env = Environment()
+        env.Java(target = 'classes', source = 'src')
+        env.Jar(target = '', source = 'classes')
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+    <section>
+    <title>Building C header and stub files:  the &JavaH; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+    <section>
+    <title>Building RMI stub and skeleton class files:  the &RMIC; Builder</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <programlisting>
+        XXX
+      </programlisting>
+
+      <literallayout>
+        XXX
+      </literallayout>
+
+    </section>
+
+  </section>
diff --git a/doc/user/builders-commands.in b/doc/user/builders-commands.in
new file mode 100644 (file)
index 0000000..5fc2c73
--- /dev/null
@@ -0,0 +1,116 @@
+<!--
+
+  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<Command> method
+
+
+  The C<Command> method is called as follows:
+
+    Command $env <target>, <inputs>, <build action>;
+
+  The target is made dependent upon the list of input files specified, and the
+  inputs must be built successfully or Cons will not attempt to build the
+  target.
+
+  To specify a command with multiple targets, you can specify a reference to a
+  list of targets. In Perl, a list reference can be created by enclosing a
+  list in square brackets. Hence the following command:
+
+    Command $env ['foo.h', 'foo.c'], 'foo.template', q(
+       gen %1
+    );
+
+  could be used in a case where the command C<gen> creates two files, both
+  F<foo.h> and F<foo.c>.
+
+  -->
+
+  <para>
+
+  Creating a &Builder; and attaching it to a &consenv;
+  allows for a lot of flexibility when you
+  want to re-use actions
+  to build multiple files of the same type.
+  This can, however, be cumbersome
+  if you only need to execute one specific command
+  to build a single file (or group of files).
+  For these situations, &SCons; supports a
+  &Command; &Builder; that arranges
+  for a specific action to be executed
+  to build a specific file or files.
+  This looks a lot like the other builders
+  (like &Program;, &Object;, etc.),
+  but takes as an additional argument
+  the command to be executed to build the file:
+
+  </para>
+
+  <scons_example name="ex1">
+     <file name="SConstruct" printme="1">
+     env = Environment()
+     env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET")
+     </file>
+     <file name="foo.in">
+     foo.in
+     </file>
+  </scons_example>
+
+  <scons_output example="ex1">
+    <command>scons .</command>
+  </scons_output>
+
+  <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>
+
+  <scons_example name="ex2">
+     <file name="SConstruct" printme="1">
+     env = Environment()
+     def build(target, source, env):
+         # Whatever it takes to build
+         return None
+     env.Command('foo.out', 'foo.in', build)
+     </file>
+     <file name="foo.in">
+     foo.in
+     </file>
+  </scons_example>
+
+  <scons_output example="ex2">
+    <command>scons .</command>
+  </scons_output>
diff --git a/doc/user/builders-writing.in b/doc/user/builders-writing.in
new file mode 100644 (file)
index 0000000..d911f6c
--- /dev/null
@@ -0,0 +1,703 @@
+<!--
+
+  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 Adding new methods
+
+For slightly more demanding changes, you may wish to add new methods to the
+C<cons> package. Here's an example of a very simple extension,
+C<InstallScript>, which installs a tcl script in a requested location, but
+edits the script first to reflect a platform-dependent path that needs to be
+installed in the script:
+
+  # cons::InstallScript - Create a platform dependent version of a shell
+  # script by replacing string ``#!your-path-here'' with platform specific
+  # path $BIN_DIR.
+
+  sub cons::InstallScript {
+       my ($env, $dst, $src) = @_;
+       Command $env $dst, $src, qq(
+               sed s+your-path-here+$BIN_DIR+ %< > %>
+               chmod oug+x %>
+       );
+  }
+
+Notice that this method is defined directly in the C<cons> package (by
+prefixing the name with C<cons::>). A change made in this manner will be
+globally visible to all environments, and could be called as in the
+following example:
+
+  InstallScript $env "$BIN/foo", "foo.tcl";
+
+For a small improvement in generality, the C<BINDIR> variable could be
+passed in as an argument or taken from the construction environment-,-as
+C<%BINDIR>.
+
+
+=head2 Overriding methods
+
+Instead of adding the method to the C<cons> name space, you could define a
+new package which inherits existing methods from the C<cons> package and
+overrides or adds others. This can be done using Perl's inheritance
+mechanisms.
+
+The following example defines a new package C<cons::switch> which
+overrides the standard C<Library> method. The overridden method builds
+linked library modules, rather than library archives. A new
+constructor is provided. Environments created with this constructor
+will have the new library method; others won't.
+
+  package cons::switch;
+  BEGIN {@ISA = 'cons'}
+
+  sub new {
+       shift;
+       bless new cons(@_);
+  }
+
+  sub Library {
+       my($env) = shift;
+       my($lib) = shift;
+       my(@objs) = Objects $env @_;
+       Command $env $lib, @objs, q(
+               %LD -r %LDFLAGS %< -o %>
+       );
+  }
+
+This functionality could be invoked as in the following example:
+
+  $env = new cons::switch(@overrides);
+  ...
+  Library $env 'lib.o', 'foo.c', 'bar.c';
+
+-->
+
+  <para>
+
+  Although &SCons; provides many useful methods
+  for building common software products:
+  programs, libraries, documents.
+  you frequently want to be
+  able to build some other type of file
+  not supported directly by &SCons;
+  Fortunately, &SCons; makes it very easy
+  to define your own &Builder; objects
+  for any custom file types you want to build.
+  (In fact, the &SCons; interfaces for creating
+  &Builder; objects are flexible enough and easy enough to use
+  that all of the the &SCons; built-in &Builder; objects
+  are created the mechanisms described in this section.)
+
+  </para>
+
+  <section>
+  <title>Writing Builders That Execute External Commands</title>
+
+    <para>
+
+    The simplest &Builder; to create is
+    one that executes an external command.
+    For example, if we want to build
+    an output file by running the contents
+    of the input file through a command named
+    <literal>foobuild</literal>,
+    creating that &Builder; might look like:
+
+    </para>
+
+    <programlisting>
+       bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+    </programlisting>
+
+    <para>
+
+    All the above line does is create a free-standing
+    &Builder; object.
+    The next section will show us how to actually use it.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Attaching a Builder to a &ConsEnv;</title>
+
+    <para>
+
+    A &Builder; object isn't useful
+    until it's attached to a &consenv;
+    so that we can call it to arrange
+    for files to be built.
+    This is done through the &BUILDERS;
+    &consvar; in an environment.
+    The &BUILDERS; variable is a Python dictionary
+    that maps the names by which you want to call
+    various &Builder; objects to the objects themselves.
+    For example, if we want to call the
+    &Builder; we just defined by the name
+    <function>Foo</function>,
+    our &SConstruct; file might look like:
+
+    </para>
+
+    <scons_example name="ex1">
+       <file name="SConstruct">
+       bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+       env = Environment(BUILDERS = {'Foo' : bld})
+       env.Foo('file.foo', 'file.input')
+       </file>
+       <file name="file.input">
+       file.input
+       </file>
+    </scons_example>
+
+    <programlisting>
+       bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+       env = Environment(BUILDERS = {'Foo' : bld})
+    </programlisting>
+
+    <para>
+
+    With the &Builder; so attached to our &consenv;
+    we can now actually call it like so:
+
+    </para>
+
+    <programlisting>
+       env.Foo('file.foo', 'file.input')
+    </programlisting>
+
+    <para>
+
+    Then when we run &SCons; it looks like:
+
+    </para>
+
+    <scons_output example="ex1">
+      <command>scons</command>
+    </scons_output>
+
+    <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>
+
+    <scons_example name="ex2">
+       <file name="SConstruct" printme="1">
+       bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+       env = Environment(BUILDERS = {'Foo' : bld})
+       env.Foo('file.foo', 'file.input')
+       env.Program('hello.c')
+       </file>
+       <file name="file.input">
+       file.input
+       </file>
+       <file name="hello.c">
+       hello.c
+       </file>
+    </scons_example>
+
+    <!--
+      scons: 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'
+    -->
+
+    <scons_output example="ex2">
+      <command>scons</command>
+    </scons_output>
+
+    <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>
+
+    <scons_example name="ex3">
+       <file name="SConstruct">
+       env = Environment()
+       bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+       env.Append(BUILDERS = {'Foo' : bld})
+       env.Foo('file.foo', 'file.input')
+       env.Program('hello.c')
+       </file>
+       <file name="file.input">
+       file.input
+       </file>
+       <file name="hello.c">
+       hello.c
+       </file>
+    </scons_example>
+
+    <para>
+
+    Or you can explicitly set the appropriately-named
+    key in the &BUILDERS; dictionary:
+
+    </para>
+
+    <programlisting>
+       env = Environment()
+       bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+       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>
+
+    <scons_output example="ex3">
+      <command>scons</command>
+    </scons_output>
+
+  </section>
+
+  <section>
+  <title>Letting &SCons; Handle The File Suffixes</title>
+
+    <para>
+
+    By supplying additional information
+    when you create a &Builder;,
+    you can let &SCons; add appropriate file
+    suffixes to the target and/or the source file.
+    For example, rather than having to specify
+    explicitly that you want the <literal>Foo</literal>
+    &Builder; to build the <literal>file.foo</literal>
+    target file from the <literal>file.input</literal> source file,
+    you can give the <literal>.foo</literal>
+    and <literal>.input</literal> suffixes to the &Builder;,
+    making for more compact and readable calls to
+    the <literal>Foo</literal> &Builder;:
+
+    </para>
+
+    <scons_example name="ex4">
+       <file name="SConstruct" printme="1">
+       bld = Builder(action = 'foobuild < $TARGET > $SOURCE',
+                     suffix = '.foo',
+                     src_suffix = '.input')
+       env = Environment(BUILDERS = {'Foo' : bld})
+       env.Foo('file1')
+       env.Foo('file2')
+       </file>
+       <file name="file1.input">
+       file1.input
+       </file>
+       <file name="file2.input">
+       file2.input
+       </file>
+    </scons_example>
+
+    <scons_output example="ex4">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    You can also supply a <literal>prefix</literal> keyword argument
+    if it's appropriate to have &SCons; append a prefix
+    to the beginning of target file names.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Builders That Execute Python Functions</title>
+
+    <para>
+
+    In &SCons;, you don't have to call an external command
+    to build a file.
+    You can, instead, define a Python function
+    that a &Builder; object can invoke
+    to build your target file (or files).
+    Such a &buildfunc; definition looks like:
+
+    </para>
+
+    <programlisting>
+       def build_function(target, source, env):
+           # XXX
+           return None
+    </programlisting>
+
+    <para>
+
+    The arguments of a &buildfunc; are:
+
+    </para>
+
+    <variablelist>
+
+      <varlistentry>
+      <term>target</term>
+
+      <listitem>
+      <para>
+
+      A list of Node objects representing
+      the target or targets to be
+      built by this builder function.
+      The file names of these target(s)
+      may be extracted using the Python &str; funcion.
+
+      </para>
+      </listitem>
+      </varlistentry>
+
+      <varlistentry>
+      <term>source</term>
+
+      <listitem>
+      <para>
+
+      A list of Node objects representing
+      the sources to be
+      used by this builder function to build the targets.
+      The file names of these source(s)
+      may be extracted using the Python &str; funcion.
+
+      </para>
+      </listitem>
+      </varlistentry>
+
+      <varlistentry>
+      <term>env</term>
+
+      <listitem>
+      <para>
+
+      The &consenv; used for building the target(s).
+      The builder function may use any of the
+      environment's construction variables
+      in any way to affect how it builds the targets.
+
+      </para>
+      </listitem>
+      </varlistentry>
+
+    </variablelist>
+
+    <para>
+
+    The builder function must
+    return a <literal>0</literal> or <literal>None</literal> value
+    if the target(s) are built successfully.
+    The builder function
+    may raise an exception
+    or return any non-zero value
+    to indicate that the build is unsuccessful,
+
+    </para>
+
+    <para>
+
+    Once you've defined the Python function
+    that will build your target file,
+    defining a &Builder; object for it is as
+    simple as specifying the name of the function,
+    instead of an external command,
+    as the &Builder;'s
+    <literal>action</literal>
+    argument:
+
+    </para>
+
+    <scons_example name="ex5">
+       <file name="SConstruct" printme="1">
+       def build_function(target, source, env):
+           # XXX
+           return None
+       bld = Builder(action = build_function,
+                     suffix = '.foo',
+                     src_suffix = '.input')
+       env = Environment(BUILDERS = {'Foo' : bld})
+       env.Foo('file')
+       </file>
+       <file name="file.input">
+       file.input
+       </file>
+    </scons_example>
+
+    <para>
+
+    And notice that the output changes slightly,
+    reflecting the fact that a Python function,
+    not an external command,
+    is now called to build the target file:
+
+    </para>
+
+    <scons_output example="ex5">
+      <command>scons</command>
+    </scons_output>
+
+  </section>
+
+  <section>
+  <title>Builders That Create Actions Using a &Generator;</title>
+
+    <para>
+
+    &SCons; Builder objects can create an action "on the fly"
+    by using a function called a &generator;.
+    This provides a great deal of flexibility XXX
+    A &generator; looks like:
+
+    </para>
+
+    <programlisting>
+       def generate_actions(source, target, env, for_signature):
+           return XXX
+    </programlisting>
+
+    <para>
+
+    The arguments of a &generator; are:
+
+    </para>
+
+    <variablelist>
+
+      <varlistentry>
+      <term>source</term>
+
+      <listitem>
+      <para>
+
+      A list of Node objects representing
+      the sources to be built
+      by the command or other action
+      generated by this function.
+      The file names of these source(s)
+      may be extracted using the Python &str; funcion.
+
+      </para>
+      </listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+      <term>target</term>
+
+      <listitem>
+      <para>
+
+      A list of Node objects representing
+      the target or targets to be built
+      by the command or other action
+      generated by this function.
+      The file names of these target(s)
+      may be extracted using the Python &str; funcion.
+
+      </para>
+      </listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+      <term>env</term>
+
+      <listitem>
+      <para>
+
+      The &consenv; used for building the target(s).
+      The generator may use any of the
+      environment's construction variables
+      in any way to determine what command
+      or other action to return.
+
+      </para>
+      </listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+      <term>for_signature</term>
+
+      <listitem>
+      <para>
+
+      A flag that specifies whether the
+      generator is being called to contribute to a build signature,
+      as opposed to actually executing the command.
+
+      XXX
+
+      </para>
+      </listitem>
+
+      </varlistentry>
+
+    </variablelist>
+
+    <para>
+
+    The &generator; must return a
+    command string or other action that will be used to
+    build the specified target(s) from the specified source(s).
+
+    </para>
+
+    <para>
+
+    Once you've defined a &generator;,
+    you create a &Builder; to use it
+    by specifying the generator keyword argument
+    instead of <literal>action</literal>.
+
+    </para>
+
+    <scons_example name="ex6">
+       <file name="SConstruct" printme="1">
+       bld = Builder(generator = generate_actions,
+                     suffix = '.foo',
+                     src_suffix = '.input')
+       env = Environment(BUILDERS = {'Foo' : bld})
+       env.Foo('file')
+       </file>
+       <file name="file.input">
+       file.input
+       </file>
+    </scons_example>
+
+    <scons_output example="ex6">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    Note that it's illegal to specify both an
+    <literal>action</literal>
+    and a
+    <literal>generator</literal>
+    for a &Builder;.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Builders That Modify the Target or Source Lists Using an &Emitter;</title>
+
+    <para>
+
+    &SCons; supports the ability for a Builder to modify the
+    lists of target(s) from the specified source(s).
+
+    </para>
+
+    <scons_example name="ex7">
+       <file name="SConstruct" printme="1">
+       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')
+       </file>
+       <file name="file.input">
+       file.input
+       </file>
+    </programlisting>
+
+    <scons_output example="ex7">
+      <command>scons</command>
+    </scons_output>
+
+    <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>
+
+    XXX
+
+    </para>
+
+    <scons_example name="ex8">
+       <file name="SConstruct" printme="1">
+       env = Environment()
+       env.SourceCode('.', env.BitKeeper('XXX'))
+       env.Program('hello.c')
+       </file>
+    </programlisting>
+
+    <scons_output example="ex8">
+      <command>scons</command>
+    </scons_output>
+
+  </section>
diff --git a/doc/user/caching.in b/doc/user/caching.in
new file mode 100644 (file)
index 0000000..2301784
--- /dev/null
@@ -0,0 +1,242 @@
+<!--
+
+  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>
+
+  On multi-developer software projects,
+  you can sometimes speed up every developer's builds a lot by
+  allowing them to share the derived files that they build.
+  &SCons; makes this easy, as well as reliable.
+
+  </para>
+
+  <section>
+  <title>Specifying the Shared Cache Directory</title>
+
+    <para>
+
+    To enable sharing of derived files,
+    use the &CacheDir; function
+    in any &SConscript; file:
+
+    </para>
+
+    <scons_example name="ex1">
+       <file name="SConstruct">
+       env = Environment()
+       env.Program('hello.c')
+       CacheDir('cache')
+       </file>
+       <file name="hello.c">
+       hello.c
+       </file>
+       <directory name="cache">
+       </directory>
+       <file name="not_used" printme="1">
+       CacheDir('/usr/local/build_cache')
+       </file>
+    </scons_example>
+
+    <para>
+
+    Note that the directory you specify must already exist
+    and be readable and writable by all developers
+    who will be sharing derived files.
+    It should also be in some central location
+    that all builds will be able to access.
+    In environments where developers are using separate systems
+    (like individual workstations) for builds,
+    this directory would typically be
+    on a shared or NFS-mounted file system.
+
+    </para>
+
+    <para>
+
+    Here's what happens:
+    When a build has a &CacheDir; specified,
+    every time a file is built,
+    it is stored in the shared cache directory
+    along with its MD5 build signature.
+    On subsequent builds,
+    before an action is invoked to build a file,
+    &SCons; will check the shared cache directory
+    to see if a file with the exact same build
+    signature already exists.
+    If so, the derived file will not be built locally,
+    but will be copied into the local build directory
+    from the shared cache directory,
+    like so:
+
+    </para>
+
+    <scons_output example="ex1">
+      <command>scons</command>
+      <command>scons -c</command>
+      <command>scons</command>
+    </scons_output>
+
+  </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>
+
+    <scons_output example="ex1">
+      <command>scons</command>
+      <command>scons -c</command>
+      <command>scons --cache-show</command>
+    </scons_output>
+
+    <para>
+
+    The trade-off, of course, is that you no longer
+    know whether or not &SCons;
+    has retrieved a derived file from cache
+    or has rebuilt it locally.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Not 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>
+
+    <scons_output example="ex1">
+      <command>scons</command>
+      <command>scons -c</command>
+      <command>scons</command>
+      <command>scons -c</command>
+      <command>scons --cache-disable</command>
+    </scons_output>
+
+  </section>
+
+  <section>
+  <title>Populating a Shared Cache With Already-Built Files</title>
+
+    <para>
+
+    Sometimes, you may have one or more derived files
+    already built in your local build tree
+    that you wish to make available to other people doing builds.
+    For example, you may find it more effective to perform
+    integration builds with the cache disabled
+    (per the previous section)
+    and only populate the shared cache directory
+    with the built files after the integration build
+    has completed successfully.
+    This way, the cache will only get filled up
+    with derived files that are part of a complete, successful build
+    not with files that might be later overwritten
+    while you debug integration problems.
+
+    </para>
+
+    <para>
+
+    In this case, you can use the
+    the <literal>--cache-force</literal> option
+    to tell &SCons; to put all derived files in the cache,
+    even if the files had already been built
+    by a previous invocation:
+
+    </para>
+
+    <scons_output example="ex1">
+      <command>scons --cache-disable</command>
+      <command>scons -c</command>
+      <command>scons --cache-disable</command>
+      <command>scons --cache-force</command>
+      <command>scons -c</command>
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    Notice how the above sample run
+    demonstrates that the <literal>--cache-disable</literal>
+    option avoids putting the built
+    <filename>hello.o</filename>
+    and 
+    <filename>hello</filename> files in the cache,
+    but after using the <literal>--cache-force</literal> option,
+    the files have been put in the cache
+    for the next invocation to retrieve.
+
+    </para>
+
+  </section>
diff --git a/doc/user/cons.in b/doc/user/cons.in
new file mode 100644 (file)
index 0000000..be02a51
--- /dev/null
@@ -0,0 +1,52 @@
+<!--
+
+  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>
+
+   XXX
+
+ </para>
+
+ <section>
+ <title>Differences Between &Cons; and &SCons;</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
+
+ <section>
+ <title>Advantages of &SCons; Over &Cons;</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
diff --git a/doc/user/copyright.in b/doc/user/copyright.in
new file mode 100644 (file)
index 0000000..7f6059c
--- /dev/null
@@ -0,0 +1,32 @@
+<!--
+
+  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.
+
+-->
+
+<blockquote>
+ <para>
+
+  SCons User's Guide Copyright (c) 2003 Steven Knight
+
+ </para>
+</blockquote>
diff --git a/doc/user/default.in b/doc/user/default.in
new file mode 100644 (file)
index 0000000..dbe6ecd
--- /dev/null
@@ -0,0 +1,216 @@
+<!--
+
+  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.
+
+-->
+
+<!--
+
+=head1 Default targets
+
+Until now, we've demonstrated invoking Cons with an explicit target
+to build:
+
+  % cons hello
+
+Normally, Cons does not build anything unless a target is specified,
+but specifying '.' (the current directory) will build everything:
+
+  % cons               # does not build anything
+
+  % cons .             # builds everything under the top-level directory
+
+Adding the C<Default> method to any F<Construct> or F<Conscript> file will add
+the specified targets to a list of default targets.  Cons will build
+these defaults if there are no targets specified on the command line.
+So adding the following line to the top-level F<Construct> file will mimic
+Make's typical behavior of building everything by default:
+
+  Default '.';
+
+The following would add the F<hello> and F<goodbye> commands (in the
+same directory as the F<Construct> or F<Conscript> file) to the default list:
+
+  Default qw(
+       hello
+       goodbye
+  );
+
+The C<Default> method may be used more than once to add targets to the
+default list.
+
+-->
+
+   <para>
+
+   As mentioned previously,
+   &SCons; will build every target
+   in or below the current directory
+   by default--that is, when you don't
+   explicitly specify one or more targets
+   on the command line.
+   Sometimes, however, you may want
+   to specify explicitly that only
+   certain programs should be built by default.
+   You do this with the &Default; function:
+
+   </para>
+
+   <scons_example name="ex1">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      hello = env.Program('hello.c')
+      env.Program('goodbye.c')
+      Default(hello)
+      </file>
+      <file name="hello.c">
+      hello.c
+      </file>
+      <file name="goodbye.c">
+      goodbye.c
+      </file>
+   </scons_example>
+
+   <para>
+
+   This &SConstruct; file knows how to build two programs,
+   &hello; and &goodbye;,
+   but only builds the
+   &hello; program by default:
+
+   </para>
+
+   <scons_output example="ex1">
+      <command>scons</command>
+      <command>scons</command>
+      <command>scons goodbye</command>
+   </scons_output>
+
+   <para>
+
+   Note that, even when you use the &Default;
+   function in your &SConstruct; file,
+   you can still explicitly specify the current directory
+   (<literal>.</literal>) on the command line
+   to tell &SCons; to build
+   everything in (or below) the current directory:
+
+   </para>
+
+   <scons_output example="ex1">
+      <command>scons .</command>
+   </scons_output>
+
+   <para>
+
+   You can also call the &Default;
+   function more than once,
+   in which case each call
+   adds to the list of targets to be built by default:
+
+   </para>
+
+   <scons_example name="ex2">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      prog1 = env.Program('prog1.c')
+      Default(prog1)
+      prog2 = env.Program('prog2.c')
+      prog3 = env.Program('prog3.c')
+      Default(prog3)
+      </file>
+      <file name="prog1.c">
+      prog1.c
+      </file>
+      <file name="prog2.c">
+      prog2.c
+      </file>
+      <file name="prog3.c">
+      prog3.c
+      </file>
+   </scons_example>
+
+   <para>
+
+   Or you can specify more than one target
+   in a single call to the &Default; function:
+
+   </para>
+
+   <programlisting>
+      env = Environment()
+      prog1 = env.Program('prog1.c')
+      prog2 = env.Program('prog2.c')
+      prog3 = env.Program('prog3.c')
+      Default(prog1, prog3)
+   </programlisting>
+
+   <para>
+
+   Either of these last two examples
+   will build only the
+   <application>prog1</application>
+   and
+   <application>prog3</application>
+   programs by default:
+
+   </para>
+
+   <scons_output example="ex2">
+      <command>scons</command>
+      <command>scons .</command>
+   </scons_output>
+
+   <para>
+
+   Lastly, if for some reason you don't want
+   any targets built by default,
+   you can use the Python <literal>None</literal>
+   variable:
+
+   </para>
+
+   <scons_example name="ex3">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      prog1 = env.Program('prog1.c')
+      prog2 = env.Program('prog2.c')
+      Default(None)
+      </file>
+      <file name="prog1.c">
+      prog1.c
+      </file>
+      <file name="prog2.c">
+      prog2.c
+      </file>
+   </scons_example>
+
+   <para>
+
+   Which would produce build output like:
+
+   </para>
+
+   <scons_output example="ex3">
+      <command>scons</command>
+      <command>scons .</command>
+   </scons_output>
diff --git a/doc/user/depends.in b/doc/user/depends.in
new file mode 100644 (file)
index 0000000..aa69dc7
--- /dev/null
@@ -0,0 +1,766 @@
+<!--
+
+  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<Salt> method
+
+The C<Salt> method adds a constant value to the signature calculation
+for every derived file.  It is invoked as follows:
+
+  Salt $string;
+
+Changing the Salt value will force a complete rebuild of every derived
+file.  This can be used to force rebuilds in certain desired
+circumstances.  For example,
+
+  Salt `uname -s`;
+
+Would force a complete rebuild of every derived file whenever the
+operating system on which the build is performed (as reported by C<uname
+-s>) changes.
+
+-->
+
+  <para>
+
+  So far we've seen how &SCons; handles one-time builds.
+  But the real point of a build tool like &SCons;
+  is to rebuild only the necessary things
+  when source files change--or, 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>
+
+  <scons_example name="ex1">
+    <file name="SConstruct">
+    env = Environment()
+    env.Program('hello.c')
+    </file>
+    <file name="hello.c">
+    int main() { printf("Hello, world!\n"); }
+    </file>
+  </scons_example>
+
+  <scons_output example="ex1" os="posix">
+     <command>scons</command>
+     <command>scons</command>
+  </scons_output>
+
+  <para>
+
+  The second time it is executed,
+  &SCons; realizes that the &hello; program
+  is up-to-date with respect to the current &hello_c; source file,
+  and avoids rebuilding it.
+  You can see this more clearly by naming
+  the &hello; program explicitly on the command line:
+
+  </para>
+
+  <scons_output example="ex1" os="posix">
+     <command>scons hello</command>
+     <command>scons hello</command>
+  </scons_output>
+
+  <para>
+
+  Note that &SCons; reports <literal>"...is up to date"</literal>
+  only for target files named explicitly on the command line,
+  to avoid cluttering the output.
+
+  </para>
+
+  <section>
+  <title>Source File Signatures</title>
+
+    <para>
+
+    The other side of avoiding unnecessary rebuilds
+    is the fundamental build tool behavior
+    of <emphasis>rebuilding</emphasis>
+    things when a source file changes,
+    so that the built software is up to date.
+    &SCons; keeps track of this through a
+    &signature; for each source file,
+    and allows you to configure
+    whether you want to use the source
+    file contents or the modification time (timestamp)
+    as the signature.
+
+    </para>
+
+    <section>
+    <title>MD5 Source File Signatures</title>
+
+      <para>
+
+      By default,
+      &SCons; keeps track of whether a source file has changed
+      based on the file's contents,
+      not the modification time.
+      This means that you may be surprised by the
+      default &SCons; behavior if you are used to the
+      &Make; convention of forcing
+      a rebuild by updating the file's modification time
+      (using the &touch; command, for example):
+
+      </para>
+
+      <scons_output example="ex1" os="posix">
+         <command>scons hello</command>
+         <command>touch hello.c</command>
+         <command>scons hello</command>
+      </scons_output>
+
+      <para>
+
+      Even though the file's modification time has changed,
+      &SCons; realizes that the contents of the
+      &hello_c; file have <emphasis>not</emphasis> changed,
+      and therefore that the &hello; program
+      need not be rebuilt.
+      This avoids unnecessary rebuilds when,
+      for example, someone rewrites the
+      contents of a file without making a change.
+      But if the contents of the file really do change,
+      then &SCons; detects the change
+      and rebuilds the program as required:
+
+      </para>
+
+      <scons_output example="ex1" os="posix">
+         <command>scons hello</command>
+         <command output="[CHANGE THE CONTENTS OF hello.c]">edit hello.c</command>
+         <command>scons hello</command>
+      </scons>
+
+      <!--
+
+      <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>
+
+      Note that you can, if you wish,
+      specify this default behavior
+      (MD5 signatures) explicitly
+      using the &SourceSignatures; function as follows:
+
+      </para>
+
+      <sconstruct>
+        env = Environment()
+        env.Program('hello.c')
+        SourceSignatures('MD5')
+      </sconstruct>
+
+    </section>
+
+    <section>
+    <title>Source File Time Stamps</title>
+
+      <para>
+
+      If you prefer, you can
+      configure &SCons; to use the modification time
+      of source files,
+      not the file contents,
+      when deciding if something needs to be rebuilt.
+      To do this, call the &SourceSignatures;
+      function as follows:
+
+      </para>
+
+      <scons_example name="ex2">
+        <file name="SConstruct" printme="1">
+        env = Environment()
+        env.Program('hello.c')
+        SourceSignatures('timestamp')
+        </file>
+        <file name="hello.c">
+        int main() { printf("Hello, world!\n"); }
+        </file>
+      </scons_example>
+
+      <para>
+
+      This makes &SCons; act like &Make;
+      when a file's modification time is updated
+      (using the &touch; command, for example):
+
+      </para>
+
+      <scons_output example="ex1" os="posix">
+         <command>scons hello</command>
+         <command>touch hello.c</command>
+         <command>scons hello</command>
+      </scons>
+
+    </section>
+
+  </section>
+
+  <section>
+  <title>Target File Signatures</title>
+
+    <para>
+
+    As you've just seen,
+    &SCons; uses signatures to decide whether a 
+    target file is up to date or must be rebuilt.
+    When a target file depends on another target file,
+    &SCons; allows you to separately configure
+    how the signatures of an "intermediate" target file
+    is used when deciding if a dependent target file
+    must be rebuilt.
+
+    </para>
+
+    <section>
+    <title>Build Signatures</title>
+
+      <para>
+
+      Modifying a source file
+      will cause not only its direct target file to be rebuilt,
+      but also the target file(s)
+      that depend on that direct target file.
+      In our example,
+      changing the contents of the &hello_c; file causes
+      the &hello_o; file to be rebuilt,
+      which in turn causes the
+      &hello; program to be rebuilt:
+
+      </para>
+
+      <scons_output example="ex1" os="posix">
+         <command>scons hello</command>
+         <command output="[CHANGE THE CONTENTS OF hello.c]">edit hello.c</command>
+         <command>scons hello</command>
+      </scons>
+
+      <!--
+
+      <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>
+
+      What's not obvious, though,
+      is that &SCons; internally handles the signature of
+      the target file(s)
+      (&hello_o; in the above example)
+      differently from the signature of the source file
+      (&hello_c;).
+      By default,
+      &SCons; tracks whether a target file must be rebuilt
+      by using a &buildsignature;
+      that consists of the combined
+      signatures of all the files
+      that go into making the target file.
+      This is efficient because
+      the accumulated signatures
+      actually give &SCons; all of the
+      information it needs
+      to decide if the target file is out of date.
+
+      </para>
+
+      <para>
+
+      If you wish, you can
+      specify this default behavior
+      (build signatures) explicitly
+      using the &TargetSignatures; function:
+
+      </para>
+
+      <sconstruct>
+        env = Environment()
+        env.Program('hello.c')
+        TargetSignatures('build')
+      </sconstruct>
+
+    </section>
+
+    <section>
+    <title>File Contents</title>
+
+      <para>
+
+      Sometimes a source file can be changed
+      in such a way that the contents of the
+      rebuilt target file(s)
+      will be exactly the same as the last time
+      the file was built.
+      If so, then any other target files
+      that depend on such a built-but-not-changed target
+      file actually need not be rebuilt.
+      You can have &SCons;
+      realize that a dependent target file
+      need not be rebuilt in this situation
+      using the &TargetSignatures; function as follows:
+
+      </para>
+
+      <scons_example name="ex3">
+        <file name="SConstruct" printme="1">
+        env = Environment()
+        env.Program('hello.c')
+        TargetSignatures('content')
+        </file>
+        <file name="hello.c">
+        int main() { printf("Hello, world!\n"); }
+        </file>
+      </scons_example>
+
+      <para>
+
+      So if, for example,
+      a user were to only change a comment in a C file,
+      then the rebuilt &hello_o; file
+      would be exactly the same as the one previously built
+      (assuming the compiler doesn't put any build-specific
+      information in the object file).
+      &SCons; would then realize that it would not
+      need to rebuild the &hello; program as follows:
+
+      </para>
+
+      <scons_output example="ex3" os="posix">
+         <command>scons hello</command>
+         <command output="[CHANGE A COMMENT IN hello.c]">edit hello.c</command>
+         <command>scons hello</command>
+      </scons>
+
+      <para>
+
+      In essence, &SCons; has
+      "short-circuited" any dependent builds
+      when it realizes that a target file
+      has been rebuilt to exactly the same file as the last build.
+      So configured,
+      &SCons; does take some extra processing time
+      to scan the contents of the target (&hello_o;) file,
+      but this may save time
+      if the rebuild that was avoided
+      would have been very time-consuming and expensive.
+
+      </para>
+
+    </section>
+
+  </section>
+
+  <section>
+  <title>Implicit Dependencies:  The &CPPPATH; Construction Variable</title>
+
+    <para>
+
+    Now suppose that our "Hello, World!" program
+    actually has a <literal>#include</literal> line
+    to include the &hello_h; file in the compilation:
+
+    </para>
+
+    <scons_example name="ex4">
+      <file name="SConstruct">
+      env = Environment(CPPPATH = '.')
+      hello = env.Program('hello.c')
+      </file>
+      <file name="hello.c" printme="1">
+      #include "hello.h" 
+      int
+      main()
+      {
+          printf("Hello, %s!\n", string);
+      }
+      </file>
+      <file name="hello.h">
+      #define string    "world"
+      </file>
+    </scons_example>
+
+    <para>
+
+    And, for completeness, the &hello_h; file looks like this:
+
+    </para>
+
+    <scons_example_file example="ex4"  name="hello.h">
+    </scons_example_file>
+
+    <para>
+
+    In this case, we want &SCons; to recognize that,
+    if the contents of the &hello_h; file change,
+    the &hello; program must be recompiled.
+    To do this, we need to modify the
+    &SConstruct; file like so:
+
+    </para>
+
+    <scons_example_file example="ex4"  name="SConstruct">
+    </scons_example_file>
+
+    <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>
+
+    <scons_output example="ex4" os="posix">
+       <command>scons hello</command>
+       <command>scons hello</command>
+       <command output="[CHANGE THE CONTENTS IN hello.h]">edit hello.h</command>
+       <command>scons hello</command>
+    </scons>
+
+    <para>
+
+    First, notice that &SCons;
+    added the <literal>-I.</literal> argument
+    from the &CPPPATH; variable
+    so that the compilation would find the
+    &hello_h; file in the local directory.
+
+    </para>
+
+    <para>
+
+    Second, realize that &SCons; knows that the &hello;
+    program must be rebuilt
+    because it scans the contents of
+    the &hello_c; file
+    for the <literal>#include</literal> lines that indicate
+    another file is being included in the compilation.
+    &SCons; records these as
+    <emphasis>implicit dependencies</emphasis>
+    of the target file,
+    Consequently,
+    when the &hello_h; file changes,
+    &SCons; realizes that the &hello_c; file includes it,
+    and rebuilds the resulting &hello; program
+    that depends on both the &hello_c; and &hello_h; files.
+
+    </para>
+
+    <para>
+
+    Like the &LIBPATH; variable,
+    the &CPPPATH; variable
+    may be a list of directories,
+    or a string separated by
+    the system-specific path separate character
+    (':' on POSIX/Linux, ';' on Windows).
+    Either way, &SCons; creates the
+    right command-line options
+    so that the following example:
+
+    </para>
+
+    <programlisting>
+    </programlisting>
+
+    <scons_example name="ex5">
+      <file name="SConstruct">
+      env = Environment(CPPPATH = ['include', '/home/project/inc'])
+      hello = env.Program('hello.c')
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    Will look like this on POSIX or Linux:
+
+    </para>
+
+    <scons_output example="ex4" os="posix">
+       <command>scons hello</command>
+    </scons_output>
+
+    <para>
+
+    And like this on Windows:
+
+    </para>
+
+    <scons_output example="ex4" os="win32">
+       <command>scons hello</command>
+    </scons_output>
+
+  </section>
+
+  <section>
+  <title>Caching Implicit Dependencies</title>
+
+    <para>
+
+    Scanning each file for <literal>#include</literal> lines
+    does take some extra processing time.
+    When you're doing a full build of a large system,
+    the scanning time is usually a very small percentage
+    of the overall time spent on the build.
+    You're most likely to notice the scanning time,
+    however, when you <emphasis>rebuild</emphasis>
+    all or part of a large system:
+    &SCons; will likely take some extra time to "think about"
+    what must be built before it issues the
+    first build command
+    (or decides that everything is up to date
+    and nothing must be rebuilt).
+
+ <!--
+ Isn't this expensive? The answer is, it depends. If you do a full build of a
+ large system, the scanning time is insignificant. If you do a rebuild of a
+ large system, then Cons will spend a fair amount of time thinking about it
+ before it decides that nothing has to be done (although not necessarily more
+ time than make!). The good news is that Cons makes it very easy to
+ intelligently subset your build, when you are working on localized changes.
+ -->
+
+    </para>
+
+    <para>
+
+    In practice, having &SCons; scan files saves time
+    relative to the amount of potential time
+    lost to tracking down subtle problems
+    introduced by incorrect dependencies.
+    Nevertheless, the "waiting time"
+    while &SCons; scans files can annoy
+    individual developers waiting for their builds to finish.
+    Consequently, &SCons; lets you cache
+    the implicit dependencies
+    that its scanners find,
+    for use by later builds.
+    You do this either by specifying the
+    &implicit-cache; option on the command line:
+
+    </para>
+
+    <scons_output example="ex1" os="win32">
+       <command>scons --implicit-cache hello</command>
+       <command>scons hello</command>
+    </scons_output>
+
+    <para>
+
+    Or by setting the &implicit_cache; option
+    in an &SConscript; file:
+
+    </para>
+
+    <sconstruct>
+       SetOption('implicit_cache', 1)
+    </sconstruct>
+
+    <para>
+
+    &SCons; does not cache implicit dependencies like this by default
+    because XXX
+    
+    </para>
+
+    <para>
+    
+    XXX
+
+    </para>
+
+    <section>
+    <title>The &implicit-deps-changed; Option</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+    </section>
+
+    <section>
+    <title>The &implicit-deps-unchanged; Option</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+    </section>
+
+  </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 has no &SCons; scanner will detect.
+    For this situation,
+    &SCons; allows you to specific explicitly that one file
+    depends on another file,
+    and must be rebuilt whenever that file changes.
+    This is specified using the &Depends; method:
+
+    </para>
+
+    <programlisting>
+       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>
+
+    XXX
+
+    </para>
+
+  </section>
+
+  -->
diff --git a/doc/user/environments.in b/doc/user/environments.in
new file mode 100644 (file)
index 0000000..7f022c1
--- /dev/null
@@ -0,0 +1,829 @@
+<!--
+
+  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.
+
+-->
+
+<!--
+
+=head1 More on construction environments
+
+As previously mentioned, a B<construction environment> is an object that
+has a set of keyword/value pairs and a set of methods, and which is used
+to tell Cons how target files should be built.  This section describes
+how Cons uses and expands construction environment values to control its
+build behavior.
+
+=head2 Construction variable expansion
+
+Construction variables from a construction environment are expanded
+by preceding the keyword with a C<%> (percent sign):
+
+  Construction variables:
+       XYZZY => 'abracadabra',
+
+  The string:  "The magic word is:  %XYZZY!"
+  expands to:  "The magic word is:  abracadabra!"
+
+A construction variable name may be surrounded by C<{> and C<}> (curly
+braces), which are stripped as part of the expansion.  This can
+sometimes be necessary to separate a variable expansion from trailing
+alphanumeric characters:
+
+  Construction variables:
+       OPT    => 'value1',
+       OPTION => 'value2',
+
+  The string:  "%OPT %{OPT}ION %OPTION %{OPTION}"
+  expands to:  "value1 value1ION value2 value2"
+
+Construction variable expansion is recursive, that is, a string
+containing C<%->expansions after substitution will be re-expanded until
+no further substitutions can be made:
+
+  Construction variables:
+       STRING => 'The result is:  %FOO',
+       FOO    => '%BAR',
+       BAR    => 'final value',
+
+  The string:  "The string says:  %STRING"
+  expands to:  "The string says:  The result is:  final value"
+
+If a construction variable is not defined in an environment, then the
+null string is substituted:
+
+  Construction variables:
+       FOO => 'value1',
+       BAR => 'value2',
+
+  The string:  "%FOO <%NO_VARIABLE> %BAR"
+  expands to:  "value1 <> value2"
+
+A doubled C<%%> will be replaced by a single C<%>:
+
+  The string:  "Here is a percent sign:  %%"
+  expands to:  "Here is a percent sign: %"
+
+=head2 Default construction variables
+
+When you specify no arguments when creating a new construction
+environment:
+
+  $env = new cons();
+
+Cons creates a reference to a new, default construction
+environment. This contains a number of construction variables and some
+methods. At the present writing, the default construction variables on a
+UNIX system are:
+
+  CC            => 'cc',
+  CFLAGS        => '',
+  CCCOM         => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
+  CXX           => '%CC',
+  CXXFLAGS      => '%CFLAGS',
+  CXXCOM        => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>',
+  INCDIRPREFIX  => '-I',
+  INCDIRSUFFIX  => '',
+  LINK          => '%CXX',
+  LINKCOM       => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS',
+  LINKMODULECOM => '%LD -r -o %> %<',
+  LIBDIRPREFIX  => '-L',
+  LIBDIRSUFFIX  => '',
+  AR           => 'ar',
+  ARFLAGS      => 'r',
+  ARCOM                => ['%AR %ARFLAGS %> %<', '%RANLIB %>'],
+  RANLIB       => 'ranlib',
+  AS           => 'as',
+  ASFLAGS      => '',
+  ASCOM                => '%AS %ASFLAGS %< -o %>',
+  LD           => 'ld',
+  LDFLAGS      => '',
+  PREFLIB      => 'lib',
+  SUFLIB       => '.a',
+  SUFLIBS      => '.so:.a',
+  SUFOBJ       => '.o',
+  SIGNATURE     => [ '*' => 'build' ],
+  ENV          => { 'PATH' => '/bin:/usr/bin' },
+
+
+And on a Win32 system (Windows NT), the default construction variables
+are (unless the default rule style is set using the B<DefaultRules>
+method):
+
+  CC           => 'cl',
+  CFLAGS       => '/nologo',
+  CCCOM                => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>',
+  CXXCOM        => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>',
+  INCDIRPREFIX  => '/I',
+  INCDIRSUFFIX  => '',
+  LINK          => 'link',
+  LINKCOM       => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS',
+  LINKMODULECOM => '%LD /r /o %> %<',
+  LIBDIRPREFIX  => '/LIBPATH:',
+  LIBDIRSUFFIX  => '',
+  AR            => 'lib',
+  ARFLAGS       => '/nologo ',
+  ARCOM         => "%AR %ARFLAGS /out:%> %<",
+  RANLIB        => '',
+  LD            => 'link',
+  LDFLAGS       => '/nologo ',
+  PREFLIB       => '',
+  SUFEXE       => '.exe',
+  SUFLIB       => '.lib',
+  SUFLIBS      => '.dll:.lib',
+  SUFOBJ       => '.obj',
+  SIGNATURE     => [ '*' => 'build' ],
+
+These variables are used by the various methods associated with the
+environment. In particular, any method that ultimately invokes an external
+command will substitute these variables into the final command, as
+appropriate. For example, the C<Objects> method takes a number of source
+files and arranges to derive, if necessary, the corresponding object
+files:
+
+  Objects $env 'foo.c', 'bar.c';
+
+This will arrange to produce, if necessary, F<foo.o> and F<bar.o>. The
+command invoked is simply C<%CCCOM>, which expands, through substitution,
+to the appropriate external command required to build each object. The
+substitution rules will be discussed in detail in the next section.
+
+The construction variables are also used for other purposes. For example,
+C<CPPPATH> is used to specify a colon-separated path of include
+directories. These are intended to be passed to the C preprocessor and are
+also used by the C-file scanning machinery to determine the dependencies
+involved in a C Compilation.
+
+Variables beginning with underscore are created by various methods,
+and should normally be considered ``internal'' variables. For example,
+when a method is called which calls for the creation of an object from
+a C source, the variable C<_IFLAGS> is created: this corresponds to the
+C<-I> switches required by the C compiler to represent the directories
+specified by C<CPPPATH>.
+
+Note that, for any particular environment, the value of a variable is set
+once, and then never reset (to change a variable, you must create a new
+environment. Methods are provided for copying existing environments for this
+purpose). Some internal variables, such as C<_IFLAGS> are created on demand,
+but once set, they remain fixed for the life of the environment.
+
+The C<CFLAGS>, C<LDFLAGS>, and C<ARFLAGS> variables all supply a place
+for passing options to the compiler, loader, and archiver, respectively.
+
+The C<INCDIRPREFIX> and C<INCDIRSUFFIX> variables specify option
+strings to be appended to the beginning and end, respectively, of each
+include directory so that the compiler knows where to find F<.h> files.
+Similarly, the C<LIBDIRPREFIX> and C<LIBDIRSUFFIX> variables specify the
+option string to be appended to the beginning of and end, respectively,
+of each directory that the linker should search for libraries.
+
+Another variable, C<ENV>, is used to determine the system environment during
+the execution of an external command. By default, the only environment
+variable that is set is C<PATH>, which is the execution path for a UNIX
+command. For the utmost reproducibility, you should really arrange to set
+your own execution path, in your top-level F<Construct> file (or perhaps by
+importing an appropriate construction package with the Perl C<use>
+command). The default variables are intended to get you off the ground.
+
+=head2 Expanding variables in construction commands
+
+Within a construction command, construction variables will be expanded
+according to the rules described above.  In addition to normal variable
+expansion from the construction environment, construction commands also
+expand the following pseudo-variables to insert the specific input and
+output files in the command line that will be executed:
+
+=over 10
+
+=item %>
+
+The target file name.  In a multi-target command, this expands to the
+first target mentioned.)
+
+=item %0
+
+Same as C<%E<gt>>.
+
+=item %1, %2, ..., %9
+
+These refer to the first through ninth input file, respectively.
+
+=item %E<lt>
+
+The full set of input file names. If any of these have been used
+anywhere else in the current command line (via C<%1>, C<%2>, etc.), then
+those will be deleted from the list provided by C<%E<lt>>. Consider the
+following command found in a F<Conscript> file in the F<test> directory:
+
+  Command $env 'tgt', qw(foo bar baz), qq(
+       echo %< -i %1 > %>
+       echo %< -i %2 >> %>
+       echo %< -i %3 >> %>
+  );
+
+If F<tgt> needed to be updated, then this would result in the execution of
+the following commands, assuming that no remapping has been established for
+the F<test> directory:
+
+  echo test/bar test/baz -i test/foo > test/tgt
+  echo test/foo test/baz -i test/bar >> test/tgt
+  echo test/foo test/bar -i test/baz >> test/tgt
+
+=back
+
+Any of the above pseudo-variables may be followed immediately by one of
+the following suffixes to select a portion of the expanded path name:
+
+  :a    the absolute path to the file name
+  :b    the directory plus the file name stripped of any suffix
+  :d    the directory
+  :f    the file name
+  :s    the file name suffix
+  :F    the file name stripped of any suffix
+  :S    the absolute path path to a Linked source file
+
+Continuing with the above example, C<%E<lt>:f> would expand to C<foo bar baz>,
+and C<%E<gt>:d> would expand to C<test>.
+
+There are additional C<%> elements which affect the command line(s):
+
+=over 10
+
+=item %[ %]
+
+It is possible to programmatically rewrite part of the command by
+enclosing part of it between C<%[> and C<%]>.  This will call the
+construction variable named as the first word enclosed in the brackets
+as a Perl code reference; the results of this call will be used to
+replace the contents of the brackets in the command line.  For example,
+given an existing input file named F<tgt.in>:
+
+  @keywords = qw(foo bar baz);
+  $env = new cons(X_COMMA => sub { join(",", @_) });
+  Command $env 'tgt', 'tgt.in', qq(
+       echo '# Keywords: %[X_COMMA @keywords %]' > %>
+       cat %< >> %>
+  );
+
+This will execute:
+
+  echo '# Keywords: foo,bar,baz' > tgt
+  cat tgt.in >> tgt
+
+=item %( %)
+
+Cons includes the text of the command line in the MD5 signature for a
+build, so that targets get rebuilt if you change the command line (to
+add or remove an option, for example).  Command-line text in between
+C<%(> and C<%)>, however, will be ignored for MD5 signature calculation.
+
+Internally, Cons uses C<%(> and C<%)> around include and library
+directory options (C<-I> and C<-L> on UNIX systems, C</I> and
+C</LIBPATH> on Windows NT) to avoid rebuilds just because the directory
+list changes.  Rebuilds occur only if the changed directory list causes
+any included I<files> to change, and a changed include file is detected
+by the MD5 signature calculation on the actual file contents.
+
+=back
+
+XXX
+
+DESCRIBE THE Literal() FUNCTION, TOO
+
+XXX
+
+=head2 Expanding construction variables in file names
+
+Cons expands construction variables in the source and target file names
+passed to the various construction methods according to the expansion
+rules described above:
+
+  $env = new cons(
+       DESTDIR =>      'programs',
+       SRCDIR  =>      'src',
+  );
+  Program $env '%DESTDIR/hello', '%SRCDIR/hello.c';
+
+This allows for flexible configuration, through the construction
+environment, of directory names, suffixes, etc.
+
+=head1 Default construction methods
+
+The list of default construction methods includes the following:
+
+
+=head2 The C<new> constructor
+
+The C<new> method is a Perl object constructor. That is, it is not invoked
+via a reference to an existing construction environment B<reference>, but,
+rather statically, using the name of the Perl B<package> where the
+constructor is defined. The method is invoked like this:
+
+  $env = new cons(<overrides>);
+
+The environment you get back is blessed into the package C<cons>, which
+means that it will have associated with it the default methods described
+below. Individual construction variables can be overridden by providing
+name/value pairs in an override list. Note that to override any command
+environment variable (i.e. anything under C<ENV>), you will have to override
+all of them. You can get around this difficulty by using the C<copy> method
+on an existing construction environment.
+
+
+=head2 The C<clone> method
+
+The C<clone> method creates a clone of an existing construction environment,
+and can be called as in the following example:
+
+  $env2 = $env1->clone(<overrides>);
+
+You can provide overrides in the usual manner to create a different
+environment from the original. If you just want a new name for the same
+environment (which may be helpful when exporting environments to existing
+components), you can just use simple assignment.
+
+
+=head2 The C<copy> method
+
+The C<copy> method extracts the externally defined construction variables
+from an environment and returns them as a list of name/value
+pairs. Overrides can also be provided, in which case, the overridden values
+will be returned, as appropriate. The returned list can be assigned to a
+hash, as shown in the prototype, below, but it can also be manipulated in
+other ways:
+
+  %env = $env1->copy(<overrides>);
+
+The value of C<ENV>, which is itself a hash, is also copied to a new hash,
+so this may be changed without fear of affecting the original
+environment. So, for example, if you really want to override just the
+C<PATH> variable in the default environment, you could do the following:
+
+  %cons = new cons()->copy();
+  $cons{ENV}{PATH} = "<your path here>";
+  $cons = new cons(%cons);
+
+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.
+   For example, different source files may need different options
+   enabled on the command line,
+   or different executable programs need to be linked
+   with different libraries.
+   &SCons; 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.)
+
+ </para>
+
+ <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>
+
+  <scons_example name="ex1">
+    <file name="SConstruct">
+    env = Environment(CC = 'gcc',
+                      CCFLAGS = '-O2')
+
+    env.Program('foo.c')
+    </file>
+    <file name="foo.c">
+   int main() { }
+    </file>
+  </scons_example>
+
+ <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:
+
+ </para>
+
+ <scons_output example="ex1">
+    <command>scons</command>
+ </scons_output>
+
+ <section>
+ <title>Multiple &ConsEnvs;</title>
+
+   <para>
+
+   So far,
+   all of our examples have
+   created a single &consenv; named
+   <literal>env</literal>.
+   <literal>env</literal>, however,
+   is simply a Python variable name,
+   and you can use any other variable name that you like.
+   For example:
+
+   </para>
+
+   <sconstruct>
+      my_env = Environment(CC = 'gcc',
+                           CCFLAGS = '-O2')
+
+      my_env.Program('foo.c')
+   </sconstruct>
+
+   <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>
+
+   <scons_example name="ex2">
+     <file name="SConstruct">
+      opt = Environment(CCFLAGS = '-O2')
+      dbg = Environment(CCFLAGS = '-g')
+
+      opt.Program('foo', 'foo.c')
+
+      dbg.Program('bar', 'bar.c')
+     </file>
+     <file name="foo.c">
+     int main() { }
+     </file>
+     <file name="bar.c">
+     int main() { }
+     </file>
+   </scons_example>
+
+   <scons_output example="ex2">
+      <command>scons</command>
+   </scons_output>
+
+   <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>
+
+   <scons_example name="ex3">
+     <file name="SConstruct">
+      opt = Environment(CCFLAGS = '-O2')
+      dbg = Environment(CCFLAGS = '-g')
+
+      opt.Program('foo', 'foo.c')
+
+      dbg.Program('foo', 'foo.c')
+     </file>
+     <file name="foo.c">
+     int main() { }
+     </file>
+   </scons_example>
+
+   <para>
+
+   Then &SCons; generates the following error:
+
+   </para>
+
+   <scons_output example="ex3">
+      <command>scons</command>
+   </scons_output>
+
+   <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 avoid this problem,
+   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>
+   </programlisting>
+
+   <scons_example name="ex4">
+     <file name="SConstruct">
+      opt = Environment(CCFLAGS = '-O2')
+      dbg = Environment(CCFLAGS = '-g')
+
+      o = opt.Object('foo-opt', 'foo.c')
+      opt.Program(o)
+
+      d = dbg.Object('foo-dbg', 'foo.c')
+      dbg.Program(d)
+     </file>
+     <file name="foo.c">
+     int main() { }
+     </file>
+   </scons_example>
+
+   <para>
+
+   Notice that each call to the &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>
+
+   <scons_output example="ex4">
+      <command>scons</command>
+   </scons_output>
+
+ </section>
+
+ <section>
+ <title>Copying &ConsEnvs;</title>
+
+   <para>
+
+   Sometimes you want more than one &consenv;
+   to share the same values for one or more variables.
+   Rather than always having to repeat all of the common
+   variables when you create each &consenv;,
+   you can use the &Copy; method
+   to create a copy of a &consenv;.
+
+   </para>
+
+   <para>
+
+   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>
+
+   <scons_example name="ex5">
+     <file name="SConstruct" printme="1">
+      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)
+     </file>
+     <file name="foo.c">
+     int main() { }
+     </file>
+   </scons_example>
+
+   <para>
+
+   Then our output would look like:
+
+   </para>
+
+   <scons_output example="ex5">
+      <command>scons</command>
+   </scons_output>
+
+ </section>
+
+ <section>
+ <title>Fetching Values From a &ConsEnv;</title>
+
+   <para>
+
+   You can fetch individual construction variables
+   using the normal syntax
+   for accessing individual named items in a Python dictionary:
+
+   </para>
+
+   <scons_example name="ex6">
+     <file name="SConstruct" printme="1">
+      env = Environment()
+      print "CC is:", env['CC']
+     </file>
+   </scons_example>
+
+   <para>
+
+   This example &SConstruct; file doesn't build anything,
+   but because it's actually a Python script,
+   it will print the value of &CC; for us:
+
+   </para>
+
+   <scons_output example="ex6">
+      <command>scons</command>
+      CC is: cc
+   </scons_output>
+
+   <para>
+
+   A &consenv;, however,
+   is actually a Python object with
+   associated methods, etc.
+   If you want to have direct access to only the
+   dictionary of construction variables,
+   you can fetch this using the &Dictionary; method:
+
+   </para>
+
+   <scons_example name="ex6b">
+      <file name="SConstruct" printme="1">
+      env = Environment(FOO = 'foo', BAR = 'bar')
+      dict = env.Dictionary()
+      for key, value in dict.items():
+          print "key = %s, value = %s % (key, value)
+      </file>
+   </scons_Example>
+
+   <para>
+
+   This &SConstruct; file
+   will print the dictionary items for us as follows:
+
+   </para>
+
+   <scons_output example="ex6b">
+      % <userinput>scons</userinput>
+      key = FOO, value = foo
+      key = BAR, value = bar
+   </scons_output>
+
+ </section>
+
+ <section>
+ <title>Modifying a &ConsEnv;</title>
+
+   <para>
+
+   &SCons; provides various methods that
+   support modifying existing values in a &consenv;.
+
+   </para>
+
+   <section>
+   <title>Replacing Values in a &ConsEnv;</title>
+
+     <para>
+
+     You can replace existing construction variable values
+     using the &Replace; method:
+
+     </para>
+
+     <scons_example name="ex7">
+       <file name="SConstruct" printme="1">
+        env = Environment(CCFLAGS = '-DDEFINE1')
+        env.Program('foo.c')
+        env.Replace(CCFLAGS = '-DDEFINE2')
+        env.Program('bar.c')
+       </file>
+       <file name="foo.c">
+       int main() { }
+       </file>
+       <file name="bar.c">
+       int main() { }
+       </file>
+     </scons_example>
+
+     <para>
+
+     The replaced value completely overwrites
+
+     </para>
+
+     <scons_output example="ex7">
+        <command>scons</command>
+     </scons_output>
+
+   </section>
+
+   <section>
+   <title>Appending to the End of Values in a &ConsEnv;</title>
+
+     <para>
+
+     You can append a value to
+     an existing construction variable
+     using the &Append; method:
+
+     </para>
+
+     <scons_example name="ex8">
+       <file name="SConstruct" printme="1">
+        env = Environment(CCFLAGS = '-DMY_VALUE')
+        env.Append(CCFLAGS = ' -DLAST')
+        env.Program('foo.c')
+       </file>
+       <file name="foo.c">
+       int main() { }
+       </file>
+     </scons_example>
+
+     <scons_output example="ex8">
+        <command>scons</command>
+     </scons_output>
+
+   </section>
+
+   <section>
+   <title>Appending to the Beginning of Values in a &ConsEnv;</title>
+
+     <para>
+
+     You can append a value to the beginning
+     an existing construction variable
+     using the &Prepend; method:
+
+     </para>
+
+     <scons_example name="ex9">
+       <file name="SConstruct" printme="1">
+        env = Environment(CCFLAGS = '-DMY_VALUE')
+        env.Prepend(CCFLAGS = '-DFIRST ')
+        env.Program('foo.c')
+       </file>
+       <file name="foo.c">
+       int main() { }
+       </file>
+     </scons_example>
+
+     <scons_output example="ex9">
+        <command>scons</command>
+     </scons_output>
+
+   </section>
+
+ </section>
diff --git a/doc/user/errors.in b/doc/user/errors.in
new file mode 100644 (file)
index 0000000..f83ab63
--- /dev/null
@@ -0,0 +1,41 @@
+<!--
+
+  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>
+
+   XXX
+
+ </para>
+
+ <section>
+ <title>XXX</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
diff --git a/doc/user/example.in b/doc/user/example.in
new file mode 100644 (file)
index 0000000..f83ab63
--- /dev/null
@@ -0,0 +1,41 @@
+<!--
+
+  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>
+
+   XXX
+
+ </para>
+
+ <section>
+ <title>XXX</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
diff --git a/doc/user/help.in b/doc/user/help.in
new file mode 100644 (file)
index 0000000..96e775b
--- /dev/null
@@ -0,0 +1,77 @@
+<!--
+
+  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>
+
+   It's often very useful to be able to give
+   users some help that describes the
+   specific targets, build options, etc.,
+   that can be used for the build.
+   &SCons; provides the &Help; function
+   to allow you to specify this help text:
+
+   </para>
+
+   <scons_example name="ex1">
+      <file name="SConstruct">
+      Help("""
+      Type: 'scons program' to build the production program,
+            'scons debug' to build the debug version.
+      """)
+      </file>
+   </scons_example>
+
+   <para>
+
+   (Note the above use of the Python triple-quote syntax,
+   which comes in very handy for
+   specifying multi-line strings like help text.)
+
+   </para>
+
+   <para>
+
+   When the &SConstruct; or &SConscript; files
+   contain such a call to the &Help; function,
+   the specified help text will be displayed in response to
+   the &SCons; <literal>-h</literal> option:
+
+   </para>
+
+   <scons_output example="ex1">
+      <command>scons -h</command>
+   </scons_output>
+
+   <para>
+
+   If there is no &Help; text in the &SConstruct; or
+   &SConscript; files,
+   &SCons; will revert to displaying its
+   standard list that describes the &SCons; command-line
+   options.
+   This list is also always displayed whenever
+   the <literal>-H</literal> option is used.
+
+   </para>
diff --git a/doc/user/hierarchy.in b/doc/user/hierarchy.in
new file mode 100644 (file)
index 0000000..5a34be2
--- /dev/null
@@ -0,0 +1,683 @@
+<!--
+
+  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 Build command
+
+By default, Cons does not change its working directory to the directory
+containing a subsidiary F<Conscript> file it is including.  This behavior
+can be enabled for a build by specifying, in the top-level F<Construct>
+file:
+
+  Conscript_chdir 1;
+
+When enabled, Cons will change to the subsidiary F<Conscript> file's
+containing directory while reading in that file, and then change back
+to the top-level directory once the file has been processed.
+
+It is expected that this behavior will become the default in some future
+version of Cons.  To prepare for this transition, builds that expect
+Cons to remain at the top of the build while it reads in a subsidiary
+F<Conscript> file should explicitly disable this feature as follows:
+
+  Conscript_chdir 0;
+
+=head2 Relative, top-relative, and absolute file names
+
+(There is another file prefix, ``!'', that is interpreted specially by
+Cons.  See discussion of the C<Link> command, below, for details.)
+
+
+=head2 Using modules in build scripts
+
+You may pull modules into each F<Conscript> file using the normal Perl
+C<use> or C<require> statements:
+
+  use English;
+  require My::Module;
+
+Each C<use> or C<require> only affects the one F<Conscript> file in which
+it appears.  To use a module in multiple F<Conscript> files, you must
+put a C<use> or C<require> statement in each one that needs the module.
+
+
+=head2 Scope of variables
+
+The top-level F<Construct> file and all F<Conscript> files begin life in
+a common, separate Perl package.  B<Cons> controls the symbol table for
+the package so that, the symbol table for each script is empty, except
+for the F<Construct> file, which gets some of the command line arguments.
+All of the variables that are set or used, therefore, are set by the
+script itself, not by some external script.
+
+Variables can be explicitly B<imported> by a script from its parent
+script. To import a variable, it must have been B<exported> by the parent
+and initialized (otherwise an error will occur).
+
+
+=head2 The Export command
+
+The C<Export> command is used as in the following example:
+
+  $env = new cons();
+  $INCLUDE = "#export/include";
+  $LIB = "#export/lib";
+  Export qw( env INCLUDE LIB );
+  Build qw( util/Conscript );
+
+The values of the simple variables mentioned in the C<Export> list will be
+squirreled away by any subsequent C<Build> commands. The C<Export> command
+will only export Perl B<scalar> variables, that is, variables whose name
+begins with C<$>. Other variables, objects, etc. can be exported by
+reference, but all scripts will refer to the same object, and this object
+should be considered to be read-only by the subsidiary scripts and by the
+original exporting script. It's acceptable, however, to assign a new value
+to the exported scalar variable, that won't change the underlying variable
+referenced. This sequence, for example, is OK:
+
+  $env = new cons();
+  Export qw( env INCLUDE LIB );
+  Build qw( util/Conscript );
+  $env = new cons(CFLAGS => '-O');
+  Build qw( other/Conscript );
+
+It doesn't matter whether the variable is set before or after the C<Export>
+command. The important thing is the value of the variable at the time the
+C<Build> command is executed. This is what gets squirreled away. Any
+subsequent C<Export> commands, by the way, invalidate the first: you must
+mention all the variables you wish to export on each C<Export> command.
+
+
+=head2 The Import command
+
+Variables exported by the C<Export> command can be imported into subsidiary
+scripts by the C<Import> command. The subsidiary script always imports
+variables directly from the superior script. Consider this example:
+
+  Import qw( env INCLUDE );
+
+This is only legal if the parent script exported both C<$env> and
+C<$INCLUDE>. It also must have given each of these variables values. It is
+OK for the subsidiary script to only import a subset of the exported
+variables (in this example, C<$LIB>, which was exported by the previous
+example, is not imported).
+
+All the imported variables are automatically re-exported, so the sequence:
+
+  Import qw ( env INCLUDE );
+  Build qw ( beneath-me/Conscript );
+
+will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only
+C<$env> is to be exported, then the following will suffice:
+
+  Import qw ( env INCLUDE );
+  Export qw ( env );
+  Build qw ( beneath-me/Conscript );
+
+Needless to say, the variables may be modified locally before invoking
+C<Build> on the subsidiary script.
+
+=head2 Build script evaluation order
+
+The only constraint on the ordering of build scripts is that superior
+scripts are evaluated before their inferior scripts. The top-level
+F<Construct> file, for instance, is evaluated first, followed by any
+inferior scripts. This is all you really need to know about the evaluation
+order, since order is generally irrelevant. Consider the following C<Build>
+command:
+
+  Build qw(
+       drivers/display/Conscript
+       drivers/mouse/Conscript
+       parser/Conscript
+       utilities/Conscript
+  );
+
+We've chosen to put the script names in alphabetical order, simply because
+that's the most convenient for maintenance purposes. Changing the order will
+make no difference to the build.
+
+-->
+
+  <para>
+
+  The source code for large software projects
+  rarely stays in a single directory,
+  but is nearly always divided into a
+  hierarchy of directories.
+  Organizing a large software build using &SCons;
+  involves creating a hierarchy of build scripts
+  using the &SConscript; function.
+
+  </para>
+
+  <section>
+  <title>&SConscript; Files</title>
+
+    <para>
+
+    As we've already seen,
+    the build script at the top of the tree is called &SConstruct;.
+    The top-level &SConstruct; file can
+    use the &SConscript; function to
+    include other subsidiary scripts in the build.
+    These subsidiary scripts can, in turn,
+    use the &SConscript; function
+    to include still other scripts in the build.
+    By convention, these subsidiary scripts are usually
+    named &SConscript;.
+    For example, a top-level &SConstruct; file might
+    arrange for four subsidiary scripts to be included
+    in the build as follows:
+
+    </para>
+
+    <sconstruct>
+      SConscript(['drivers/display/SConscript',
+                  'drivers/mouse/SConscript',
+                  'parser/SConscript',
+                  'utilities/SConscript'])
+    </sconstruct>
+
+    <para>
+
+    In this case, the &SConstruct; file
+    lists all of the &SConscript; files in the build explicitly.
+    (Note, however, that not every directory in the tree
+    necessarily has an &SConscript; file.)
+    Alternatively, the <literal>drivers</literal>
+    subdirectory might contain an intermediate
+    &SConscript; file,
+    in which case the &SConscript; call in
+    the top-level &SConstruct; file
+    would look like:
+
+    </para>
+
+    <sconstruct>
+      SConscript(['drivers/SConscript',
+                  'parser/SConscript',
+                  'utilities/SConscript'])
+    </sconstruct>
+
+    <para>
+
+    And the subsidiary &SConscript; file in the
+    <literal>drivers</literal> subdirectory
+    would look like:
+
+    </para>
+
+    <sconstruct>
+      SConscript(['display/SConscript',
+                  'mouse/SConscript'])
+    </sconstruct>
+
+    <para>
+
+    Whether you list all of the &SConscript; files in the
+    top-level &SConstruct; file,
+    or place a subsidiary &SConscript; file in
+    intervening directories,
+    or use some mix of the two schemes,
+    is up to you and the needs of your software.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Path Names Are Relative to the &SConscript; Directory</title>
+
+    <para>
+
+    Subsidiary &SConscript; files make it easy to create a build
+    hierarchy because all of the file and directory names
+    in a subsidiary &SConscript; files are interpreted
+    relative to the directory in which the &SConscript; file lives.
+    Typically, this allows the &SConscript; file containing the
+    instructions to build a target file
+    to live in the same directory as the source files
+    from which the target will be built,
+    making it easy to update how the software is built
+    whenever files are added or deleted
+    (or other changes are made).
+
+    </para>
+
+    <para>
+
+    For example, suppose we want to build two programs
+    &prog1; and &prog2; in two separate directories
+    with the same names as the programs.
+    One typical way to do this would be
+    with a top-level &SConstruct; file like this:
+
+    </para>
+
+    <scons_example name="ex1">
+      <file name="SConstruct" printme="1">
+      SConscript(['prog1/SConscript',
+                  'prog2/SConscript'])
+      </file>
+      <file name="prog1/SConscript">
+      env = Environment()
+      env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c'])
+      </file>
+      <file name="prog2/SConscript">
+      env = Environment()
+      env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c'])
+      </file>
+      <directory name="prog1"></directory>
+      <file name="prog1/main.c">
+      x
+      </file>
+      <file name="prog1/foo1.c">
+      x
+      </file>
+      <file name="prog1/foo2.c">
+      x
+      </file>
+      <directory name="prog2"></directory>
+      <file name="prog2/main.c">
+      x
+      </file>
+      <file name="prog2/bar1.c">
+      x
+      </file>
+      <file name="prog2/bar2.c">
+      x
+      </file>
+    </scons_example>
+
+    <para>
+
+    And subsidiary &SConscript; files that look like this:
+
+    </para>
+
+    <scons_example_file example="ex1" name="prog1/SConscript">
+    </scons_example_file>
+
+    <para>
+
+    And this:
+
+    </para>
+
+    <scons_example_file example="ex1" name="prog2/SConscript">
+    </scons_example_file>
+
+    <para>
+
+    Then, when we run &SCons; in the top-level directory,
+    our build looks like:
+
+    </para>
+
+    <scons_output example="ex1">
+       <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    Notice the following:
+
+    First, you can have files with the same names
+    in multiple directories, like main.c in the above example.
+
+    Second, unlike standard recursive use of &Make;,
+    &SCons; stays in the top-level directory and
+    issues commands
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Top-Level Path Names in Subsidiary &SConscript; Files</title>
+
+    <para>
+
+    If you need to use a file from another directory,
+    it's sometimes more convenient to specify
+    the path to a file in another directory
+    from the top-level &SConstruct; directory,
+    even when you're using that file in
+    a subsidiary &SConscript; file in a subdirectory.
+    You can tell &SCons; to interpret a path name
+    as relative to the top-level &SConstruct; directory,
+    not the local directory of the &SConscript; file,
+    by appending a &hash; (hash mark)
+    to the beginning of the path name:
+
+
+    </para>
+
+    <scons_example name="ex2">
+       <file name="SConstruct">
+       SConscript('src/prog/SConscript')
+       </file>
+       <file name="src/prog/SConscript" printme="1">
+       env = Environment()
+       env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c'])
+       </file>
+       <file name="src/prog/main.c">
+       x
+       </file>
+       <file name="lib/foo1.c">
+       x
+       </file>
+       <file name="src/prog/foo2.c">
+       x
+       </file>
+    </scons_example>
+
+    <para>
+
+    In this example,
+    the <literal>lib</literal> directory is
+    directly underneath the top-level &SConstruct; directory.
+    If the above &SConscript; file is in a subdirectory
+    named <literal>src/prog</literal>,
+    the output would look like:
+
+    </para>
+
+    <scons_output example="ex2">
+       <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    (Notice that the <literal>lib/foo1.o</literal> object file
+    is built in the same directory as its source file.
+    See section XXX, below,
+    for information about 
+    how to build the object file in a different subdirectory.)
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Absolute Path Names</title>
+
+    <para>
+
+    Of course, you can always specify
+    an absolute path name for a file--for example:
+
+    </para>
+
+    <scons_example name="ex3">
+       <file name="SConstruct">
+       SConscript('src/prog/SConscript')
+       </file>
+       <file name="src/prog/SConscript" printme="1">
+       env = Environment()
+       env.Program('prog', ['main.c', '__ROOT__/usr/joe/lib/foo1.c', 'foo2.c'])
+       </file>
+       <file name="src/prog/main.c">
+       x
+       </file>
+       <file name="__ROOT__/usr/joe/lib/foo1.c">
+       x
+       </file>
+       <file name="src/prog/foo2.c">
+       x
+       </file>
+    </scons_example>
+
+    <para>
+
+    Which, when executed, would yield:
+
+    </para>
+
+    <scons_output example="ex3">
+       <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    (As was the case with top-relative path names,
+    notice that the <literal>/usr/joe/lib/foo1.o</literal> object file
+    is built in the same directory as its source file.
+    See section XXX, below,
+    for information about 
+    how to build the object file in a different subdirectory.)
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title>
+
+    <para>
+
+    In the previous example,
+    each of the subsidiary &SConscript; files
+    created its own construction environment
+    by calling &Environment; separately.
+    This obviously works fine,
+    but if each program must be built
+    with the same construction variables,
+    it's cumbersome and error-prone to initialize
+    separate construction environments
+    in the same way over and over in each subsidiary
+    &SConscript; file.
+
+    </para>
+
+    <para>
+
+    &SCons; supports the ability to <emphasis>export</emphasis> variables
+    from a parent &SConscript; file
+    to its subsidiary &SConscript; files,
+    which allows you to share common initialized
+    values throughout your build hierarchy.
+
+    </para>
+
+    <section>
+    <title>Exporting Variables</title>
+
+      <para>
+
+      There are two ways to export a variable,
+      such as a construction environment,
+      from one &SConscript; file,
+      so that it may be used by other &SConscript; files.
+      First, you can call the &Export;
+      function with a list of variables,
+      or a string white-space separated variable names.
+      Each call to &Export; adds one
+      or more variables to a global list
+      of variables that are available for import
+      by other &SConscript; files.
+
+      </para>
+
+      <sconstruct>
+        env = Environment()
+        Export('env')
+      </sconstruct>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <sconstruct>
+        env = Environment()
+        debug = ARGUMENTS['debug']
+        Export('env', 'debug')
+      </sconstruct>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <sconstruct>
+        Export('env debug')
+      </sconstruct>
+
+      <para>
+
+      Second, you can specify a list of
+      variables to export as a second argument
+      to the &SConscript; function call:
+
+      </para>
+
+      <sconstruct>
+        SConscript('src/SConscript', 'env')
+      </sconstruct>
+
+      <para>
+
+      Or as the &exports; keyword argument:
+
+      </para>
+
+      <sconstruct>
+        SConscript('src/SConscript', exports='env')
+      </sconstruct>
+
+      <para>
+
+      These calls export the specified variables
+      to only the listed &SConscript; files.
+      You may, however, specify more than one
+      &SConscript; file in a list:
+
+      </para>
+
+      <sconstruct>
+        SConscript(['src1/SConscript',
+                    'src2/SConscript'], exports='env')
+      </sconstruct>
+
+      <para>
+
+      This is functionally equivalent to
+      calling the &SConscript; function
+      multiple times with the same &exports; argument,
+      one per &SConscript; file.
+
+      </para>
+
+    </section>
+
+    <section>
+    <title>Importing Variables</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <sconstruct>
+        Import('env')
+        env.Program('prog', ['prog.c'])
+      </sconstruct>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <sconstruct>
+        Import('env', 'debug')
+        env = env.Copy(DEBUG = debug)
+        env.Program('prog', ['prog.c'])
+      </sconstruct>
+
+      <para>
+
+      Which is exactly equivalent to:
+
+      </para>
+
+      <sconstruct>
+        Import('env debug')
+        env = env.Copy(DEBUG = debug)
+        env.Program('prog', ['prog.c'])
+      </sconstruct>
+
+      <para>
+
+      XXX
+
+      </para>
+
+    </section>
+
+    <section>
+    <title>Returning Values From an &SConscript; File</title>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <sconstruct>
+        obj = env.Object('foo.c')
+        Return('obj')
+      </sconstruct>
+
+      <para>
+
+      XXX
+
+      </para>
+
+      <sconstruct>
+        objs = []
+        for subdir in ['foo', 'bar']:
+            o = SConscript('%s/SConscript' % subdir)
+            objs.append(o)
+        env.Library('prog', objs)
+      </sconstruct>
+
+      <para>
+
+      XXX
+
+      </para>
+
+    </section>
+
+  </section>
diff --git a/doc/user/install.in b/doc/user/install.in
new file mode 100644 (file)
index 0000000..a263f65
--- /dev/null
@@ -0,0 +1,240 @@
+<!--
+
+  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>
+
+  Once a program is built,
+  it is often appropriate to install it in another
+  directory for public use.
+  You use the &Install; method 
+  to arrange for a program, or any other file,
+  to be copied into a destination directory:
+
+  </para>
+
+  <scons_example name="ex1">
+     <file name="SConstruct" printme="1">
+     env = Environment()
+     hello = env.Program('hello.c')
+     env.Install('__ROOT__/usr/bin', hello)
+     </file>
+     <file name="hello.c">
+     int main() { printf("Hello, world!\n"); }
+     </file>
+  </scons_example>
+
+  <para>
+
+  Note, however, that installing a file is
+  still considered a type of file "build."
+  This is important when you remember that
+  the default behavior of &SCons; is
+  to build files in or below the current directory.
+  If, as in the example above,
+  you are installing files in a directory
+  outside of the top-level &SConstruct; file's directory tree,
+  you must specify that directory
+  (or a higher directory, such as <literal>/</literal>)
+  for it to install anything there:
+
+  </para>
+
+  <scons_output example="ex1">
+     <command>scons</command>
+     <command>scons __ROOT__/usr/bin</command>
+  </scons_output>
+
+  <para>
+
+  It can, however, be cumbersome to remember
+  (and type) the specific destination directory
+  in which the program (or any other file)
+  should be installed.
+  This is an area where the &Alias;
+  function comes in handy,
+  allowing you, for example,
+  to create a pseudo-target named <literal>install</literal>
+  that can expand to the specified destination directory:
+
+  </para>
+
+  <scons_example name="ex2">
+    <file name="SConstruct" printme="1">
+     env = Environment()
+     hello = env.Program('hello.c')
+     env.Install('__ROOT__/usr/bin', hello)
+     env.Alias('install', '__ROOT__/usr/bin')
+    </file>
+    <file name="hello.c">
+    int main() { printf("Hello, world!\n"); }
+    </file>
+  </scons_example>
+
+  <para>
+
+  This then yields the more natural
+  ability to install the program
+  in its destination as follows:
+
+  </para>
+
+  <scons_output example="ex1">
+     <command>scons</command>
+     <command>scons install</command>
+  </scons_output>
+
+  <section>
+  <title>Installing Multiple Files in a Directory</title>
+
+    <para>
+
+    You can install multiple files into a directory
+    simply by calling the &Install; function multiple times:
+
+    </para>
+
+    <scons_example name="ex3">
+      <file name="SConstruct" printme="1">
+       env = Environment()
+       hello = env.Program('hello.c')
+       goodbye = env.Program('goodbye.c')
+       env.Install('__ROOT__/usr/bin', hello)
+       env.Install('__ROOT__/usr/bin', goodbye)
+       env.Alias('install', '__ROOT__/usr/bin')
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    Or, more succinctly, listing the multiple input
+    files in a list
+    (just like you can do with any other builder):
+
+    </para>
+
+    <sconstruct>
+       env = Environment()
+       hello = env.Program('hello.c')
+       goodbye = env.Program('goodbye.c')
+       env.Install('__ROOT__/usr/bin', [hello, goodbye])
+       env.Alias('install', '__ROOT__/usr/bin')
+    </sconstruct>
+
+    <para>
+
+    Either of these two examples yields:
+
+    </para>
+
+    <scons_output example="ex3">
+       <command>scons install</command>
+    </scons_output>
+
+  </section>
+
+  <section>
+  <title>Installing a File Under a Different Name</title>
+
+    <para>
+
+    The &Install; method preserves the name
+    of the file when it is copied into the
+    destination directory.
+    If you need to change the name of the file
+    when you copy it, use the &InstallAs; function:
+
+    </para>
+
+    <scons_example name="ex4">
+      <file name="SConstruct" printme="1">
+       env = Environment()
+       hello = env.Program('hello.c')
+       env.InstallAs('__ROOT__/usr/bin/hello-new', hello)
+       env.Alias('install', '__ROOT__/usr/bin')
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    This installs the <literal>hello</literal>
+    program with the name <literal>hello-new</literal>
+    as follows:
+
+    </para>
+
+    <scons_output example="ex4">
+       <command>scons install</command>
+    </scons_output>
+
+  </section>
+
+  <section>
+  <title>Installing Multiple Files Under Different Names</title>
+
+    <para>
+
+    Lastly, if you have multiple files that all
+    need to be installed with different file names,
+    you can either call the &InstallAs; function
+    multiple times, or as a shorthand,
+    you can supply same-length lists
+    for the both the target and source arguments:
+
+    </para>
+
+    <scons_example name="ex5">
+      <file name="SConstruct" printme="1">
+       env = Environment()
+       hello = env.Program('hello.c')
+       goodbye = env.Program('goodbye.c')
+       env.InstallAs(['__ROOT__/usr/bin/hello-new',
+                      '__ROOT__/usr/bin/goodbye-new'],
+                     [hello, goodbye])
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    In this case, the &InstallAs; function
+    loops through both lists simultaneously,
+    and copies each source file into its corresponding
+    target file name:
+
+    </para>
+
+    <scons_output example="ex5">
+       <command>scons install</command>
+    </scons_output>
+
+  </section>
diff --git a/doc/user/libraries.in b/doc/user/libraries.in
new file mode 100644 (file)
index 0000000..337b0da
--- /dev/null
@@ -0,0 +1,261 @@
+<!--
+
+  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>
+
+  One of the more useful ways in which you can use multiple
+  construction environments is to link programs
+  with different sets of libraries.
+
+  </para>
+
+  <section>
+  <title>Building Libraries</title>
+
+    <para>
+
+    You build your own libraries by specifying &Library;
+    instead of &Program;:
+
+    </para>
+
+    <scons_example name="ex1" printme="1">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+      <file name="f1.c">
+      void f1() { printf("f1.c\n"); }
+      </file>
+      <file name="f2.c">
+      void f2() { printf("f2.c\n"); }
+      </file>
+      <file name="f3.c">
+      void f3() { printf("f3.c\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    &SCons; uses the appropriate library prefix and suffix for your system.
+    So on POSIX or Linux systems,
+    the above example would build as follows
+    (although &ranlib may not be called on all systems):
+
+    </para>
+
+    <scons_output example="ex1">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    On a Windows system,
+    a build of the above example would look like:
+
+    </para>
+
+    <scons_output example="ex1">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    The rules for the target name of the library
+    are similar to those for programs:
+    if you don't explicitly specify a target library name,
+    &SCons; will deduce one from the
+    name of the first source file specified,
+    and &SCons; will add an appropriate
+    file prefix and suffix if you leave them off.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Linking with Libraries</title>
+
+    <para>
+
+    Usually, you build a library
+    because you want to link it with one or more programs.
+    You link libraries with a program by specifying
+    the libraries in the &LIBS; construction variable,
+    and by specifying the directory in which
+    the library will be found in the 
+    &LIBPATH; construction variable:
+
+    </para>
+
+    <scons_example name="ex2">
+      <file name="SConstruct">
+      env = Environment(LIBS = 'foo', LIBPATH = '.')
+      env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+      env.Program('prog.c')
+      </file>
+      <file name="f1.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+      <file name="f2.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+      <file name="f3.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+      <file name="prog.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    Notice, of course, that you don't need to specify a library
+    prefix (like <literal>lib</literal>)
+    or suffix (like <literal>.a</literal> or <literal>.lib</literal>).
+    &SCons; uses the correct prefix or suffix for the current system.
+
+    </para>
+
+    <para>
+
+    On a POSIX or Linux system,
+    a build of the above example would look like:
+
+    </para>
+
+    <scons_output example="ex2">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    On a Windows system,
+    a build of the above example would look like:
+
+    </para>
+
+    <scons_output example="ex2" os="win32">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    As usual, notice that &SCons; has taken care
+    of constructing the correct command lines
+    to link with the specified library on each system.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Finding Libraries:  the &LIBPATH; Construction Variable</title>
+
+    <para>
+
+    By default, the linker will only look in
+    certain system-defined directories for libraries.
+    &SCons; knows how to look for libraries
+    in directories that you specify with the
+    &LIBPATH; construction variable.
+    &LIBPATH; consists of a list of
+    directory names, like so:
+
+    </para>
+
+    <scons_example name="ex3">
+      <file name="SConstruct" printme="1">
+      env = Environment(LIBS = 'm',
+                        LIBPATH = ['/usr/lib', '/usr/local/lib'])
+      env.Program('prog.c')
+      </file>
+      <file name="prog.c">
+      int main() { printf("prog.c\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    Using a Python list is preferred because it's portable
+    across systems.  Alternatively, you could put all of
+    the directory names in a single string, separated by the
+    system-specific path separator character:
+    a colon on POSIX systems:
+
+    </para>
+
+    <sconstruct>
+      LIBPATH = '/usr/lib:/usr/local/lib'
+    </sconstruct>
+
+    <para>
+
+    or a semi-colon on Windows systems:
+
+    </para>
+
+    <sconstruct>
+      LIBPATH = 'C:\lib;D:\lib'
+    </sconstruct>
+
+    <para>
+
+    When the linker is executed,
+    &SCons; will create appropriate flags
+    so that the linker will look for
+    libraries in the same directories as &SCons;.
+    So on a POSIX or Linux system,
+    a build of the above example would look like:
+
+    </para>
+
+    <scons_output example="ex3">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    On a Windows system,
+    a build of the above example would look like:
+
+    </para>
+
+    <scons_output example="ex3" os="win32">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    Note again that &SCons; has taken care of
+    the system-specific details of creating
+    the right command-line options.
+
+    </para>
+
+  </section>
diff --git a/doc/user/main.in b/doc/user/main.in
new file mode 100644 (file)
index 0000000..12b0480
--- /dev/null
@@ -0,0 +1,243 @@
+<!--
+
+  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.
+
+-->
+
+<!doctype book PUBLIC "-//OASIS//DTD DocBook V4.1//EN"
+[
+
+    <!ENTITY % version SYSTEM "../version.sgml">
+    %version;
+
+    <!ENTITY % scons SYSTEM "../scons.mod">
+    %scons;
+
+    <!ENTITY actions SYSTEM "actions.sgml">
+    <!ENTITY alias SYSTEM "alias.sgml">
+    <!ENTITY ant SYSTEM "ant.sgml">
+    <!ENTITY builders-built-in SYSTEM "builders-built-in.sgml">
+    <!ENTITY builders-commands SYSTEM "builders-commands.sgml">
+    <!ENTITY builders-writing SYSTEM "builders-writing.sgml">
+    <!ENTITY caching SYSTEM "caching.sgml">
+    <!ENTITY cons SYSTEM "cons.sgml">
+    <!ENTITY copyright SYSTEM "copyright.sgml">
+    <!ENTITY default SYSTEM "default.sgml">
+    <!ENTITY depends SYSTEM "depends.sgml">
+    <!ENTITY environments SYSTEM "environments.sgml">
+    <!ENTITY errors SYSTEM "errors.sgml">
+    <!ENTITY example SYSTEM "example.sgml">
+    <!ENTITY help SYSTEM "help.sgml">
+    <!ENTITY hierarchy SYSTEM "hierarchy.sgml">
+    <!ENTITY install SYSTEM "install.sgml">
+    <!ENTITY libraries SYSTEM "libraries.sgml">
+    <!ENTITY make SYSTEM "make.sgml">
+    <!ENTITY precious SYSTEM "precious.sgml">
+    <!ENTITY preface SYSTEM "preface.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">
+
+]>
+
+<book>
+  <bookinfo>
+    <title>SCons User Guide &buildversion;</title>
+
+    <author>
+      <firstname>Steven</firstname>
+      <surname>Knight</surname>
+    </author>
+
+    <edition>Revision &buildrevision; (&builddate;)</edition>
+
+    <pubdate>2003</pubdate>
+
+    <copyright>
+      <year>2003</year>
+      <holder>Steven Knight</holder>
+    </copyright>
+
+    <legalnotice>
+      &copyright;
+    </legalnotice>
+
+    <releaseinfo>version &buildversion;</releaseinfo>
+
+  </bookinfo>
+
+  <chapter id="chap-preface">
+    <title>Preface</title>
+    &preface;
+  </chapter>
+
+  <chapter id="chap-simple">
+    <title>Simple Builds</title>
+    &simple;
+  </chapter>
+
+  <chapter id="chap-environments">
+    <title>Construction Environments</title>
+    &environments;
+  </chapter>
+
+  <chapter id="chap-libraries">
+    <title>Building and Linking with Libraries</title>
+    &libraries;
+  </chapter>
+
+  <chapter id="chap-depends">
+    <title>Dependencies</title>
+    &depends;
+  </chapter>
+
+  <chapter id="chap-default">
+    <title>Default Targets</title>
+    &default;
+  </chapter>
+
+  <chapter id="chap-help">
+    <title>Providing Build Help</title>
+    &help;
+  </chapter>
+
+  <chapter id="chap-install">
+    <title>Installing Files in Other Directories</title>
+    &install;
+  </chapter>
+
+  <chapter id="chap-precious">
+    <title>Preventing Removal of Targets</title>
+    &precious;
+  </chapter>
+
+  <chapter id="chap-hierarchical">
+    <title>Hierarchical Builds</title>
+    &hierarchy;
+  </chapter>
+
+  <chapter id="chap-separate">
+    <title>Separating Source and Build Directories</title>
+    &separate;
+  </chapter>
+
+  <chapter id="chap-variants">
+    <title>Variant Builds</title>
+    &variants;
+  </chapter>
+
+  <chapter id="chap-builders-built-in">
+    <title>Built-In Builders</title>
+    &builders-built-in;
+  </chapter>
+
+  <chapter id="chap-builders-writing">
+    <title>Writing Your Own Builders</title>
+    &builders-writing;
+  </chapter>
+
+  <chapter id="chap-builders-commands">
+    <title>Not Writing a Builder:  The &Command; Builder</title>
+    &builders-commands;
+  </chapter>
+
+  <chapter id="chap-actions">
+    <title>SCons Actions</title>
+    &actions;
+  </chapter>
+
+  <chapter id="chap-scanners">
+    <title>Writing Scanners</title>
+    &scanners;
+  </chapter>
+
+  <chapter id="chap-repositories">
+    <title>Building From Code Repositories</title>
+    &repositories;
+  </chapter>
+
+  <chapter id="chap-sourcecode">
+    <title>Fetching Files From Source Code Management Systems</title>
+    &sourcecode;
+  </chapter>
+
+  <chapter id="chap-caching">
+    <title>Caching Built Files</title>
+    &caching;
+  </chapter>
+
+  <chapter id="chap-alias">
+    <title>Alias Targets</title>
+    &alias;
+  </chapter>
+
+  <chapter id="chap-run">
+    <title>How to Run &SCons;</title>
+    &run;
+  </chapter>
+
+  <chapter id="chap-troubleshooting">
+    <title>Troubleshooting</title>
+    &troubleshoot;
+  </chapter>
+
+  <!--
+  AddPostAction()
+  AddPreAction()
+  Clean()
+  Dir()
+  File()
+  FindFile()
+  GetJobs()
+  SetJobs()
+  SideEffect()
+  ParseConfig()
+  Platform()
+  Tools()
+  -->
+
+  <appendix id="app-example">
+    <title>Complex &SCons; Example</title>
+    &example;
+  </appendix>
+
+  <appendix id="app-make">
+    <title>Converting From Make</title>
+    &make;
+  </appendix>
+
+  <appendix id="app-cons">
+    <title>Converting From Cons</title>
+    &cons;
+  </appendix>
+
+  <appendix id="app-ant">
+    <title>Converting From Ant</title>
+    &ant;
+  </appendix>
+
+</book>
diff --git a/doc/user/make.in b/doc/user/make.in
new file mode 100644 (file)
index 0000000..fe697a0
--- /dev/null
@@ -0,0 +1,121 @@
+<!--
+
+  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.
+
+-->
+
+<!--
+
+=head1 Why Cons? Why not Make?
+
+Cons is a B<make> replacement. In the following paragraphs, we look at a few
+of the undesirable characteristics of make, and typical build environments
+based on make, that motivated the development of Cons.
+
+=head2 Build complexity
+
+Traditional make-based systems of any size tend to become quite complex. The
+original make utility and its derivatives have contributed to this tendency
+in a number of ways. Make is not good at dealing with systems that are
+spread over multiple directories. Various work-arounds are used to overcome
+this difficulty; the usual choice is for make to invoke itself recursively
+for each sub-directory of a build. This leads to complicated code, in which
+it is often unclear how a variable is set, or what effect the setting of a
+variable will have on the build as a whole. The make scripting language has
+gradually been extended to provide more possibilities, but these have
+largely served to clutter an already overextended language. Often, builds
+are done in multiple passes in order to provide appropriate products from
+one directory to another directory. This represents a further increase in
+build complexity.
+
+
+=head2 Build reproducibility
+
+The bane of all makes has always been the correct handling of
+dependencies. Most often, an attempt is made to do a reasonable job of
+dependencies within a single directory, but no serious attempt is made to do
+the job between directories. Even when dependencies are working correctly,
+make's reliance on a simple time stamp comparison to determine whether a
+file is out of date with respect to its dependents is not, in general,
+adequate for determining when a file should be rederived. If an external
+library, for example, is rebuilt and then ``snapped'' into place, the
+timestamps on its newly created files may well be earlier than the last
+local build, since it was built before it became visible.
+
+
+=head2 Variant builds
+
+Make provides only limited facilities for handling variant builds. With the
+proliferation of hardware platforms and the need for debuggable
+vs. optimized code, the ability to easily create these variants is
+essential. More importantly, if variants are created, it is important to
+either be able to separate the variants or to be able to reproduce the
+original or variant at will. With make it is very difficult to separate the
+builds into multiple build directories, separate from the source. And if
+this technique isn't used, it's also virtually impossible to guarantee at
+any given time which variant is present in the tree, without resorting to a
+complete rebuild.
+
+
+=head2 Repositories
+
+Make provides only limited support for building software from code that
+exists in a central repository directory structure.  The VPATH feature of
+GNU make (and some other make implementations) is intended to provide this,
+but doesn't work as expected: it changes the path of target file to the
+VPATH name too early in its analysis, and therefore searches for all
+dependencies in the VPATH directory.  To ensure correct development builds,
+it is important to be able to create a file in a local build directory and
+have any files in a code repository (a VPATH directory, in make terms) that
+depend on the local file get rebuilt properly.  This isn't possible with
+VPATH, without coding a lot of complex repository knowledge directly into
+the makefiles.
+
+-->
+
+ <para>
+
+   XXX
+
+ </para>
+
+ <section>
+ <title>Differences Between &Make; and &SCons;</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
+
+ <section>
+ <title>Advantages of &SCons; Over &Make;</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
diff --git a/doc/user/precious.in b/doc/user/precious.in
new file mode 100644 (file)
index 0000000..2be22ec
--- /dev/null
@@ -0,0 +1,89 @@
+<!--
+
+  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<AfterBuild> method
+
+The C<AfterBuild> method evaluates the specified perl string after
+building the given file or files (or finding that they are up to date).
+The eval will happen once per specified file.  C<AfterBuild> is called
+as follows:
+
+  AfterBuild $env 'foo.o', qq(print "foo.o is up to date!\n");
+
+The perl string is evaluated in the C<script> package, and has access
+to all variables and subroutines defined in the F<Conscript> file in
+which the C<AfterBuild> method is called.
+
+-->
+
+ <para>
+
+ By default, &SCons; removes targets before building them.
+ Sometimes, however, this is not what you want.
+ For example, you may want to update a library incrementally,
+ not by having it deleted and then rebuilt from all
+ of the constituent object files.
+ In such cases, you can use the
+ &Precious; method to prevent
+ &SCons; from removing the target before it is built:
+
+ </para>
+
+ <scons_example name="ex1">
+   <file name="SConstruct" printme="1">
+    env = Environment(XXX NEED LIBRARY FLAGS
+                      LIBFLAGS = '-r')
+    lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+    env.Precious(lib)
+   </file>
+   <file name="f1.c">
+   int f1() { }
+   </file>
+   <file name="f2.c">
+   int f2() { }
+   </file>
+   <file name="f3.c">
+   int f3() { }
+   </file>
+ </scons_example>
+
+ <para>
+
+ XXX:
+
+ </para>
+
+ <scons_output example="ex1">
+    <command>scons</command>
+ </scons_output>
+
+ <para>
+
+ &SCons; will still delete files marked as &Precious;
+ when the <literal>-c</literal> option is used.
+
+ </para>
diff --git a/doc/user/preface.in b/doc/user/preface.in
new file mode 100644 (file)
index 0000000..589399d
--- /dev/null
@@ -0,0 +1,373 @@
+<!--
+
+  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>
+
+  Thank you for taking the time to read about &SCons;.
+  &SCons; is a next-generation
+  software construction tool,
+  or make tool--that is, a software utility
+  for building software (or other files)
+  and keeping built software up-to-date
+  whenever the underlying input files change.
+
+  </para>
+
+  <para>
+
+  The most distinctive thing about &SCons;
+  is that its configuration files are
+  actually <emphasis>scripts</emphasis>,
+  written in the &Python; programming language.
+  This is in contrast to most alternative build tools,
+  which typically invent a new language to
+  configure the build.
+  &SCons; still has a learning curve, of course,
+  because you have to know what functions to call
+  to set up your build properly,
+  but the underlying syntax used should be familiar
+  to anyone who has ever looked at a Python script.
+
+  </para>
+
+  <para>
+
+  Paradoxically,
+  using Python as the configuration file format
+  makes &SCons;
+  <emphasis>easier</emphasis>
+  for non-programmers to learn
+  than the cryptic languages of other build tools,
+  which are usally invented by programmers for other programmers.
+  This is in no small part to the
+  consistency and readability that are built in to Python.
+  It just so happens that making a real, live
+  scripting language the basis for the
+  configuration files
+  makes it a snap for more accomplished programmers
+  to do more complicated things with builds,
+  as necessary.
+
+  </para>
+
+  <section>
+  <title>Why &SCons;?</title>
+
+    <para>
+
+    &SCons; is a response to a perennial problem:
+    building software is harder than it should be.
+    In a nutshell:  the old, reliable model of the
+    venerable and ubiquitous &Make; program
+    has had a hard time keeping up with
+    how complicated building software has become.
+    The fact that &Make; has kept up as well as it has is impressive,
+    and a testament to how the simplicity.
+    But anyone who has wrestled with &Automake; and &Autoconf;
+    to try to guarantee that a bit of software
+    will build correctly on multiple platforms
+    can tell you that it takes a lot of work to get right.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>&SCons; Principles</title>
+
+    <para>
+
+    There are a few overriding principles
+    we try to live up to in designing and implementing &SCons:
+
+    </para>
+
+    <variablelist>
+
+      <varlistentry>
+      <term>Correctness</term>
+
+      <listitem>
+      <para>
+
+      First and foremost,
+      by default, &SCons; guarantees a correct build
+      even if it means sacrificing performance a little.
+      We strive to guarantee the build is correct
+      regardless of how the software being built is structured,
+      how it may have been written,
+      or how unusual the tools are that build it.
+
+      </para>
+      </listitem>
+      </varlistentry>
+
+      <varlistentry>
+      <term>Performance</term>
+
+      <listitem>
+      <para>
+
+      Given that the build is correct,
+      we try to make &SCons; build software
+      as quickly as possible.
+      In particular, wherever we may have needed to slow
+      down the default &SCons; behavior to guarantee a correct build,
+      we also try to make it easy to speed up &SCons;
+      through optimization options that let you trade off
+      guaranteed correctness for speed.
+
+      </para>
+      </listitem>
+      </varlistentry>
+
+      <varlistentry>
+      <term>Convenience</term>
+
+      <listitem>
+      <para>
+
+      &SCons; tries to do as much for you out of the box as reasonable,
+      including detecting the right tools on your system
+      and using them correctly to build the software.
+
+      </para>
+      </listitem>
+      </varlistentry>
+
+    </variablelist>
+
+    <para>
+
+    In a nutshell, we try hard to make &SCons; just
+    "do the right thing" and build software correctly,
+    with a minimum of hassles.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>History</title>
+
+    <para>
+
+    &SCons; originated with a design
+    that was submitted to the Software Carpentry
+    design competition in 2000.
+
+    </para>
+
+    <para>
+
+    &SCons; is the direct descendant
+    of a Perl utility called &Cons;.
+    &Cons; in turn based some of its ideas on &Jam;,
+    a build tool from Perforce Systems.
+
+    </para>
+
+    <para>
+
+    XXX
+
+    </para>
+
+  </section>
+
+  <!--
+
+  <section>
+  <title>Conventions</title>
+
+    <para>
+
+    XXX
+
+    </para>
+
+  </section>
+
+  -->
+
+  <section>
+  <title>Acknowledgements</title>
+
+    <para>
+
+    &SCons; would not exist without a lot of help
+    from a lot of people,
+    many of whom may not even be aware
+    that they helped or served as inspiration.
+    So in no particular order,
+    and at the risk of leaving out someone:
+
+    </para>
+
+    <para>
+
+    First and foremost,
+    &SCons; owes a tremendous debt to Bob Sidebotham,
+    the original author of the classic Perl-based &Cons; tool
+    which Bob first released to the world back around 1996.
+    Bob's work on Cons classic provided the underlying architecture
+    and model of specifying a build configuration
+    using a real scripting language.
+    My real-world experience working on Cons
+    informed many of the design decisions in SCons,
+    including the improved parallel build support,
+    making Builder objects easily definable by users,
+    and separating the build engine from the wrapping interface.
+
+    </para>
+
+    <para>
+
+    Greg Wilson was instrumental in getting
+    &SCons; started as a real project
+    when he initiated the Software Carpentry design
+    competition in February 2000.
+    Without that nudge,
+    marrying the advantages of the Cons classic
+    architecture with the readability of Python
+    might have just stayed no more than a nice idea.
+
+    </para>
+
+    <para>
+
+    The entire &SCons; team have been
+    absolutely wonderful to work with,
+    and &SCons; would be nowhere near as useful a
+    tool without the energy, enthusiasm
+    and time people have contributed over the past few years.
+    The "core team"
+    of Chad Austin, Anthony Roach, Charles Crain,
+    Steve Leblanc, Greg Spencer and Christoph Wiedemann
+    have been great about reviewing my (and other) changes
+    and catching problems before they get in the code base.
+    Of particular technical note:
+    Anthony's outstanding and innovative work on the tasking engine
+    has given &SCons; a vastly superior parallel build model;
+    Charles has been the master of the crucial Node infrastructure;
+    Christoph's work on the Configure infrastructure
+    has added crucial Autoconf-like functionality;
+    and Greg has provided excellent support
+    for Microsoft Visual Studio.
+
+    </para>
+
+    <para>
+
+    Special thanks to David Snopek for contributing
+    his underlying "Autocons" code that formed
+    the basis of Christoph's work with the Configure functionality.
+    David was extremely generous in making
+    this code available to &SCons;,
+    given that he initially released it under the GPL
+    and &SCons; is released under a less-restrictive MIT-style license.
+
+    </para>
+
+    <para>
+
+    &SCons; has received contributions
+    from many other people, of course:
+    Matt Balvin (extending long command-line support on Win32),
+    Allen Bierbaum (extensions and fixes to Options),
+    Steve Christensen (help text sorting and function action signature fixes),
+    Michael Cook (avoiding losing signal bits from executed commands),
+    Derrick 'dman' Hudson (),
+    Alex Jacques (work on the Win32 scons.bat file),
+    Stephen Kennedy (performance enhancements),
+    Lachlan O'Dea (SharedObject() support for masm
+    and normalized paths for the WhereIs() function),
+    Damyan Pepper (keeping output like Make),
+    Jeff Petkau (significant fixes for CacheDir and other areas),
+    Stefan Reichor (Ghostscript support),
+    Zed Shaw (Append() and Replace() environment methods),
+    Terrel Shumway (build and test fixes, as well as the SCons Wiki),
+    sam th (dynamic checks for utilities)
+    and Moshe Zadke (Debian packaging).
+
+    </para>
+
+    <para>
+
+    Thanks to Peter Miller
+    for his splendid change management system, &Aegis;,
+    which has provided the &SCons; project
+    with a robust development methodology from day one,
+    and which showed me how you could
+    integrate incremental regression tests into
+    a practical development cycle
+    (years before eXtreme Programming arrived on the scene).
+
+    </para>
+
+    <para>
+
+    And last, thanks to Guido van Rossum
+    for his elegant scripting language,
+    which is the basis not only for the &SCons; implementation,
+    but for the interface itself.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Contact</title>
+
+    <para>
+
+    The best way to contact people involved with SCons,
+    including the author,
+    is through the SCons mailing lists.
+
+    </para>
+
+    <para>
+
+    If you want to ask general questions about how to use &SCons;
+    send email to &scons-users;.
+
+    </para>
+
+    <para>
+
+    If you want to contact the &SCons; development community directly,
+    send email to &scons-devel;.
+
+    </para>
+
+    <para>
+
+    If you want to receive announcements about &SCons,
+    join the low-volume &scons-announce; mailing list.
+
+    </para>
+
+  </section>
diff --git a/doc/user/repositories.in b/doc/user/repositories.in
new file mode 100644 (file)
index 0000000..c155617
--- /dev/null
@@ -0,0 +1,499 @@
+<!--
+
+  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 Repository dependency analysis
+
+Due to its built-in scanning, Cons will search the specified repository
+trees for included F<.h> files.  Unless the compiler also knows about the
+repository trees, though, it will be unable to find F<.h> files that only
+exist in a repository.  If, for example, the F<hello.c> file includes the
+F<hello.h> file in its current directory:
+
+  % cons -R /usr/all/repository hello
+  gcc -c /usr/all/repository/hello.c -o hello.o
+  /usr/all/repository/hello.c:1: hello.h: No such file or directory
+
+Solving this problem forces some requirements onto the way construction
+environments are defined and onto the way the C C<#include> preprocessor
+directive is used to include files.
+
+In order to inform the compiler about the repository trees, Cons will add
+appropriate C<-I> flags to the compilation commands.  This means that the
+C<CPPPATH> variable in the construction environment must explicitly specify
+all subdirectories which are to be searched for included files, including the
+current directory.  Consequently, we can fix the above example by changing
+the environment creation in the F<Construct> file as follows:
+
+  $env = new cons(
+       CC      => 'gcc',
+       CPPPATH => '.',
+       LIBS    => 'libworld.a',
+  );
+
+Due to the definition of the C<CPPPATH> variable, this yields, when we
+re-execute the command:
+
+  % cons -R /usr/all/repository hello
+  gcc -c -I. -I/usr/all/repository /usr/all/repository/hello.c -o hello.o
+  gcc -o hello hello.o /usr/all/repository/libworld.a
+
+The order of the C<-I> flags replicates, for the C preprocessor, the same
+repository-directory search path that Cons uses for its own dependency
+analysis.  If there are multiple repositories and multiple C<CPPPATH>
+directories, Cons will append the repository directories to the beginning of
+each C<CPPPATH> directory, rapidly multiplying the number of C<-I> flags.
+As an extreme example, a F<Construct> file containing:
+
+  Repository qw(
+       /u1
+       /u2
+  );
+
+  $env = new cons(
+       CPPPATH => 'a:b:c',
+  );
+
+Would yield a compilation command of:
+
+  cc -Ia -I/u1/a -I/u2/a -Ib -I/u1/b -I/u2/b -Ic -I/u1/c -I/u2/c -c hello.c -o hello.o
+
+In order to shorten the command lines as much as possible, Cons will
+remove C<-I> flags for any directories, locally or in the repositories,
+which do not actually exist.  (Note that the C<-I> flags are not included
+in the MD5 signature calculation for the target file, so the target will
+not be recompiled if the compilation command changes due to a directory
+coming into existence.)
+
+Because Cons relies on the compiler's C<-I> flags to communicate the
+order in which repository directories must be searched, Cons' handling
+of repository directories is fundamentally incompatible with using
+double-quotes on the C<#include> directives in any C source code that
+you plan to modify:
+
+  #include "file.h"    /* DON'T USE DOUBLE-QUOTES LIKE THIS */
+
+This is because most C preprocessors, when faced with such a directive, will
+always first search the directory containing the source file.  This
+undermines the elaborate C<-I> options that Cons constructs to make the
+preprocessor conform to its preferred search path.
+
+Consequently, when using repository trees in Cons, B<always> use
+angle-brackets for included files in any C source (.c or .h) files that
+you plan to modify locally:
+
+  #include <file.h>    /* USE ANGLE-BRACKETS INSTEAD */
+
+Code that will not change can still safely use double quotes on #include
+lines.
+
+
+=head2 Repository_List
+
+Cons provides a C<Repository_List> command to return a list of all
+repository directories in their current search order.  This can be used for
+debugging, or to do more complex Perl stuff:
+
+  @list = Repository_List;
+  print join(' ', @list), "\n";
+
+
+=head2 Repository interaction with other Cons features
+
+Cons' handling of repository trees interacts correctly with other Cons
+features, which is to say, it generally does what you would expect.
+
+Most notably, repository trees interact correctly, and rather powerfully,
+with the 'Link' command.  A repository tree may contain one or more
+subdirectories for version builds established via C<Link> to a source
+subdirectory.  Cons will search for derived files in the appropriate build
+subdirectories under the repository tree.
+
+-->
+
+  <para>
+
+  Often, a software project will have
+  one or more central repositories,
+  directory trees that contain
+  source code, or derived files, or both.
+  You can eliminate additional unnecessary
+  rebuilds of files by having &SCons;
+  use files from one or more code repositories
+  to build files in your local build tree.
+
+  </para>
+
+  <section>
+  <title>The &Repository; Method</title>
+
+ <!--
+
+ The repository directories specified may contain source files, derived files
+ (objects, libraries and executables), or both.  If there is no local file
+ (source or derived) under the directory in which Cons is executed, then the
+ first copy of a same-named file found under a repository directory will be
+ used to build any local derived files.
+
+ -->
+
+    <para>
+
+    It's often useful to allow multiple programmers working
+    on a project to build software from
+    source files and/or derived files that
+    are stored in a centrally-accessible repository,
+    a directory copy of the source code tree.
+    (Note that this is not the sort of repository
+    maintained by a source code management system
+    like BitKeeper, CVS, or Subversion.
+    For information about using &SCons;
+    with these systems, see the section,
+    "Fetching Files From Source Code Management Systems,"
+    below.)
+    You use the &Repository; method
+    to tell &SCons; to search one or more
+    central code repositories (in order)
+    for any source files and derived files
+    that are not present in the local build tree:
+
+    </para>
+
+    <scons_example name="ex1">
+      <file name="SConstruct" printme="1">
+       env = Environment()
+       env.Program('hello.c')
+       Repository('/usr/repository1', '/usr/repository2')
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    Multiple calls to the &Repository; method
+    will simply add repositories to the global list
+    that &SCons; maintains,
+    with the exception that &SCons; will automatically eliminate
+    the current directory and any non-existent
+    directories from the list.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Finding source files in repositories</title>
+
+    <para>
+
+    The above example
+    specifies that &SCons;
+    will first search for files under
+    the <filename>/usr/repository1</filename> tree
+    and next under the <filename>/usr/repository2</filename> tree.
+    &SCons; expects that any files it searches
+    for will be found in the same position
+    relative to the top-level directory 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>
+
+    <scons_output example="ex1">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    If, however, there is no local &hello_c; file,
+    but one exists in <filename>/usr/repository1</filename>,
+    &SCons; will recompile the &hello; program
+    from the source file it finds in the repository:
+
+    </para>
+
+    <scons_example name="ex2">
+      <file name="SConstruct">
+       env = Environment()
+       env.Program('hello.c')
+       Repository('/usr/repository1', '/usr/repository2')
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <scons_output example="ex2">
+      <command>scons</command>
+      gcc -c /usr/repository1/hello.c -o hello.o
+      gcc -o hello hello.o
+    </scons_output>
+
+    <para>
+
+    And similarly, if there is no local &hello_c; file
+    and no <filename>/usr/repository1/hello.c</filename>,
+    but one exists in <filename>/usr/repository2</filename>:
+
+    </para>
+
+    <scons_example name="ex3">
+      <file name="SConstruct">
+       env = Environment()
+       env.Program('hello.c')
+       Repository('/usr/repository1', '/usr/repository2')
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <scons_output example="ex3">
+      <command>scons</command>
+    </scons_output>
+
+    <para>
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Finding the &SConstruct; file in repositories</title>
+
+    <para>
+
+    &SCons; will also search in repositories
+    for the &SConstruct; file and any specified &SConscript; files.
+    This poses a problem, though:  how can &SCons; search a
+    repository tree for an &SConstruct; file
+    if the &SConstruct; file itself contains the information
+    about the pathname of the repository?
+    To solve this problem, &SCons; allows you
+    to specify repository directories
+    on the command line using the <literal>-Y</literal> option:
+
+    </para>
+
+    <literallayout>
+      % <userinput>scons -Y /usr/repository1 -Y /usr/repository2</userinput>
+    </literallayout>
+
+    <para>
+
+    When looking for source or derived files,
+    &SCons; will first search the repositories
+    specified on the command line,
+    and then search the repositories
+    specified in the &SConstruct; or &SConscript; files.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Finding derived files in repositories</title>
+
+    <para>
+
+    If a repository contains not only source files,
+    but also derived files (such as object files,
+    libraries, or executables), &SCons; will perform
+    its normal MD5 signature calculation to
+    decide if a derived file in a repository is up-to-date,
+    or the derived file must be rebuilt in the local build directory.
+    For the &SCons; signature calculation to work correctly,
+    a repository tree must contain the &sconsign; files
+    that &SCons; uses to keep track of signature information.
+
+    </para>
+
+    <para>
+
+    Usually, this would be done by a build integrator
+    who would run &SCons; in the repository
+    to create all of its derived files and &sconsign; files,
+    or who would &SCons; in a separate build directory
+    and copying the resulting tree to the desired repository:
+
+    </para>
+
+    <scons_example name="ex4">
+      <file name="SConstruct">
+       env = Environment()
+       env.Program('hello.c')
+       Repository('/usr/repository1', '/usr/repository2')
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <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>
+
+    <para>
+
+    Now, with the repository populated,
+    we only need to create the one local source file
+    we're interested in working with at the moment,
+    and use the <literal>-Y</literal> option to
+    tell &SCons; to fetch any other files it needs
+    from the repository:
+
+    </para>
+
+    <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>
+
+    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>
+
+  </section>
+
+  <section>
+  <title>Guaranteeing local copies of files</title>
+
+    <para>
+
+    If the repository tree contains the complete results of a build,
+    and we try to build from the repository
+    without any files in our local tree,
+    something moderately surprising happens:
+
+    </para>
+
+    <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>
+
+    Why does &SCons; say that the &hello; program
+    is up-to-date when there is no &hello; program
+    in the local build directory?
+    Because the repository (not the local directory)
+    contains the up-to-date &hello; program,
+    and &SCons; correctly determines that nothing
+    needs to be done to rebuild that
+    up-to-date copy of the file.
+
+    </para>
+
+    <para>
+
+    There are, however, many times when you want to ensure that a
+    local copy of a file always exists.
+    A packaging or testing script, for example,
+    may assume that certain generated files exist locally.
+    To tell &SCons; to make a copy of any up-to-date repository
+    file in the local build directory,
+    use the &Local; function:
+
+    </para>
+
+    <scons_example name="ex1">
+      <file name="SConstruct" printme="1">
+       env = Environment()
+       hello = env.Program('hello.c')
+       Local(hello)
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    If we then run the same command,
+    &SCons; will make a local copy of the program
+    from the repository copy,
+    and tell you that it is doing so:
+
+    </para>
+
+    <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>
+
+    (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>
+
+  </section>
diff --git a/doc/user/run.in b/doc/user/run.in
new file mode 100644 (file)
index 0000000..83ca3d2
--- /dev/null
@@ -0,0 +1,364 @@
+<!--
+
+  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.
+
+-->
+
+<!--
+
+=head1 Invoking Cons
+
+The C<cons> command is usually invoked from the root of the build tree. A
+F<Construct> file must exist in that directory. If the C<-f> argument is
+used, then an alternate F<Construct> file may be used (and, possibly, an
+alternate root, since C<cons> will cd to F<Construct> file's containing
+directory).
+
+If C<cons> is invoked from a child of the root of the build tree with
+the C<-t> argument, it will walk up the directory hierarchy looking for a
+F<Construct> file.  (An alternate name may still be specified with C<-f>.)
+The targets supplied on the command line will be modified to be relative
+to the discovered F<Construct> file.  For example, from a directory
+containing a top-level F<Construct> file, the following invocation:
+
+  % cd libfoo/subdir
+  % cons -t target
+
+is exactly equivalent to:
+
+  % cons libfoo/subdir/target
+
+If there are any C<Default> targets specified in the directory hierarchy's
+F<Construct> or F<Conscript> files, only the default targets at or below
+the directory from which C<cons -t> was invoked will be built.
+
+The command is invoked as follows:
+
+  cons <arguments> ,  <construct-args>
+
+where I<arguments> can be any of the following, in any order:
+
+=over 10
+
+=item I<target>
+
+Build the specified target. If I<target> is a directory, then recursively
+build everything within that directory.
+
+=item I<+pattern>
+
+Limit the F<Conscript> files considered to just those that match I<pattern>,
+which is a Perl regular expression. Multiple C<+> arguments are accepted.
+
+=item I<name>=<val>
+
+Sets I<name> to value I<val> in the C<ARG> hash passed to the top-level
+F<Construct> file.
+
+=item C<-cc>
+
+Show command that would have been executed, when retrieving from cache. No
+indication that the file has been retrieved is given; this is useful for
+generating build logs that can be compared with real build logs.
+
+=item C<-cd>
+
+Disable all caching. Do not retrieve from cache nor flush to cache.
+
+=item C<-cr>
+
+Build dependencies in random order. This is useful when building multiple
+similar trees with caching enabled.
+
+=item C<-cs>
+
+Synchronize existing build targets that are found to be up-to-date with
+cache. This is useful if caching has been disabled with -cc or just recently
+enabled with UseCache.
+
+=item C<-d>
+
+Enable dependency debugging.
+
+=item C<-f> <file>
+
+Use the specified file instead of F<Construct> (but first change to
+containing directory of I<file>).
+
+=item C<-h>
+
+Show a help message local to the current build if one such is defined, and
+exit.
+
+=item C<-k>
+
+Keep going as far as possible after errors.
+
+=item C<-o> <file>
+
+Read override file I<file>.
+
+=item C<-p>
+
+Show construction products in specified trees. No build is attempted.
+
+=item C<-pa>
+
+Show construction products and associated actions. No build is attempted.
+
+=item C<-pw>
+
+Show products and where they are defined. No build is attempted.
+
+=item C<-q>
+
+Make the build quiet.  Multiple C<-q> options may be specified.
+
+A single C<-q> options suppress messages about Installing and Removing
+targets.
+
+Two C<-q> options suppress build command lines and target up-to-date
+messages.
+
+=item C<-r>
+
+Remove construction products associated with <targets>. No build is
+attempted.
+
+=item C<-R> <repos>
+
+Search for files in I<repos>.  Multiple B<-R> I<repos> directories are
+searched in the order specified.
+
+=item C<-S> <pkg>
+
+Use the sig::<pkg> package to calculate.  Supported <pkg> values
+include "md5" for MD5 signature calculation and "md5::debug" for debug
+information about MD5 signature calculation.
+
+If the specified package ends in <::debug>, signature debug information
+will be printed to the file name specified in the C<CONS_SIG_DEBUG>
+environment variable, or to standard output if the environment variable
+is not set.
+
+=item C<-t>
+
+Traverse up the directory hierarchy looking for a F<Construct> file,
+if none exists in the current directory.  Targets will be modified to
+be relative to the F<Construct> file.
+
+Internally, C<cons> will change its working directory to the directory
+which contains the top-level F<Construct> file and report:
+
+  cons: Entering directory `top-level-directory'
+
+This message indicates to an invoking editor (such as emacs) or build
+environment that Cons will now report all file names relative to the
+top-level directory.  This message can not be suppressed with the C<-q>
+option.
+
+=item C<-v>
+
+Show C<cons> version and continue processing.
+
+=item C<-V>
+
+Show C<cons> version and exit.
+
+=item C<-wf> <file>
+
+Write all filenames considered into I<file>.
+
+=item C<-x>
+
+Show a help message similar to this one, and exit.
+
+=back
+
+And I<construct-args> can be any arguments that you wish to process in the
+F<Construct> file. Note that there should be a B<-,-> separating the arguments
+to cons and the arguments that you wish to process in the F<Construct> file.
+
+Processing of I<construct-args> can be done by any standard package like
+B<Getopt> or its variants, or any user defined package. B<cons> will pass in
+the I<construct-args> as B<@ARGV> and will not attempt to interpret anything
+after the B<-,->.
+
+  % cons -R /usr/local/repository -d os=solaris +driver -,- -c test -f DEBUG
+
+would pass the following to cons
+
+  -R /usr/local/repository -d os=solaris +driver
+
+and the following, to the top level F<Construct> file as B<@ARGV>
+
+  -c test -f DEBUG
+
+Note that C<cons -r .> is equivalent to a full recursive C<make clean>,
+but requires no support in the F<Construct> file or any F<Conscript>
+files. This is most useful if you are compiling files into source
+directories (if you separate the F<build> and F<export> directories,
+then you can just remove the directories).
+
+The options C<-p>, C<-pa>, and C<-pw> are extremely useful for use as an aid
+in reading scripts or debugging them. If you want to know what script
+installs F<export/include/foo.h>, for example, just type:
+
+  % cons -pw export/include/foo.h
+
+=head1 Selective builds
+
+Cons provides two methods for reducing the size of given build. The first is
+by specifying targets on the command line, and the second is a method for
+pruning the build tree. We'll consider target specification first.
+
+
+=head2 Selective targeting
+
+Like make, Cons allows the specification of ``targets'' on the command
+line. Cons targets may be either files or directories. When a directory is
+specified, this is simply a short-hand notation for every derivable
+product-,-that Cons knows about-,-in the specified directory and below. For
+example:
+
+  % cons build/hello/hello.o
+
+means build F<hello.o> and everything that F<hello.o> might need. This is
+from a previous version of the B<Hello, World!> program in which F<hello.o>
+depended upon F<export/include/world.h>. If that file is not up-to-date
+(because someone modified F<src/world/world.h)>, then it will be rebuilt,
+even though it is in a directory remote from F<build/hello>.
+
+In this example:
+
+  % cons build
+
+Everything in the F<build> directory is built, if necessary. Again, this may
+cause more files to be built. In particular, both F<export/include/world.h>
+and F<export/lib/libworld.a> are required by the F<build/hello> directory,
+and so they will be built if they are out-of-date.
+
+If we do, instead:
+
+  % cons export
+
+then only the files that should be installed in the export directory will be
+rebuilt, if necessary, and then installed there. Note that C<cons build>
+might build files that C<cons export> doesn't build, and vice-versa.
+
+
+=head1 Build Pruning
+
+In conjunction with target selection, B<build pruning> can be used to reduce
+the scope of the build. In the previous peAcH and baNaNa example, we have
+already seen how script-driven build pruning can be used to make only half
+of the potential build available for any given invocation of C<cons>. Cons
+also provides, as a convenience, a command line convention that allows you
+to specify which F<Conscript> files actually get ``built''-,-that is,
+incorporated into the build tree. For example:
+
+  % cons build +world
+
+The C<+> argument introduces a Perl regular expression. This must, of
+course, be quoted at the shell level if there are any shell meta-characters
+within the expression. The expression is matched against each F<Conscript>
+file which has been mentioned in a C<Build> statement, and only those
+scripts with matching names are actually incorporated into the build
+tree. Multiple such arguments are allowed, in which case a match against any
+of them is sufficient to cause a script to be included.
+
+In the example, above, the F<hello> program will not be built, since Cons
+will have no knowledge of the script F<hello/Conscript>. The F<libworld.a>
+archive will be built, however, if need be.
+
+There are a couple of uses for build pruning via the command line. Perhaps
+the most useful is the ability to make local changes, and then, with
+sufficient knowledge of the consequences of those changes, restrict the size
+of the build tree in order to speed up the rebuild time. A second use for
+build pruning is to actively prevent the recompilation of certain files that
+you know will recompile due to, for example, a modified header file. You may
+know that either the changes to the header file are immaterial, or that the
+changes may be safely ignored for most of the tree, for testing
+purposes.With Cons, the view is that it is pragmatic to admit this type of
+behavior, with the understanding that on the next full build everything that
+needs to be rebuilt will be. There is no equivalent to a ``make touch''
+command, to mark files as permanently up-to-date. So any risk that is
+incurred by build pruning is mitigated. For release quality work, obviously,
+we recommend that you do not use build pruning (it's perfectly OK to use
+during integration, however, for checking compilation, etc. Just be sure to
+do an unconstrained build before committing the integration).
+
+-->
+
+  <para>
+
+    XXX
+
+  </para>
+
+  <section>
+  <title>Selective Builds</title>
+
+    <para>
+
+    XXX
+
+    </para>
+
+  </section>
+
+  <!--
+
+  <section>
+  <title>Build Pruning</title>
+
+    <para>
+
+    XXX
+
+    </para>
+
+  </section>
+
+  -->
+
+  <section>
+  <title>Overriding Construction Variables</title>
+
+    <para>
+
+    XXX
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>The &SCONSFLAGS; Environment Variable</title>
+
+    <para>
+
+    XXX
+
+    </para>
+
+  </section>
diff --git a/doc/user/scanners.in b/doc/user/scanners.in
new file mode 100644 (file)
index 0000000..76b2a1a
--- /dev/null
@@ -0,0 +1,139 @@
+<!--
+
+  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.
+
+-->
+
+<!--
+
+=head1 Using and writing dependency scanners
+
+QuickScan allows simple target-independent scanners to be set up for
+source files. Only one QuickScan scanner may be associated with any given
+source file and environment, although the same scanner may (and should)
+be used for multiple files of a given type.
+
+A QuickScan scanner is only ever invoked once for a given source file,
+and it is only invoked if the file is used by some target in the tree
+(i.e., there is a dependency on the source file).
+
+QuickScan is invoked as follows:
+
+  QuickScan CONSENV CODEREF, FILENAME [, PATH]
+
+The subroutine referenced by CODEREF is expected to return a list of
+filenames included directly by FILE. These filenames will, in turn, be
+scanned. The optional PATH argument supplies a lookup path for finding
+FILENAME and/or files returned by the user-supplied subroutine.  The PATH
+may be a reference to an array of lookup-directory names, or a string of
+names separated by the system's separator character (':' on UNIX systems,
+';' on Windows NT).
+
+The subroutine is called once for each line in the file, with $_ set to the
+current line. If the subroutine needs to look at additional lines, or, for
+that matter, the entire file, then it may read them itself, from the
+filehandle SCAN. It may also terminate the loop, if it knows that no further
+include information is available, by closing the filehandle.
+
+Whether or not a lookup path is provided, QuickScan first tries to lookup
+the file relative to the current directory (for the top-level file
+supplied directly to QuickScan), or from the directory containing the
+file which referenced the file. This is not very general, but seems good
+enough, especially if you have the luxury of writing your own utilities
+and can control the use of the search path in a standard way.
+
+Here's a real example, taken from a F<Construct> file here:
+
+  sub cons::SMFgen {
+      my($env, @tables) = @_;
+      foreach $t (@tables) {
+         $env->QuickScan(sub { /\b\S*?\.smf\b/g }, "$t.smf",
+                         $env->{SMF_INCLUDE_PATH});
+         $env->Command(["$t.smdb.cc","$t.smdb.h","$t.snmp.cc",
+                        "$t.ami.cc", "$t.http.cc"], "$t.smf",
+                       q(smfgen %( %SMF_INCLUDE_OPT %) %<));
+      }
+  }
+
+The subroutine above finds all names of the form <name>.smf in the
+file. It will return the names even if they're found within comments,
+but that's OK (the mechanism is forgiving of extra files; they're just
+ignored on the assumption that the missing file will be noticed when
+the program, in this example, smfgen, is actually invoked).
+
+[NOTE that the form C<$env-E<gt>QuickScan ...>  and C<$env-E<gt>Command
+...> should not be necessary, but, for some reason, is required
+for this particular invocation. This appears to be a bug in Perl or
+a misunderstanding on my part; this invocation style does not always
+appear to be necessary.]
+
+Here is another way to build the same scanner. This one uses an
+explicit code reference, and also (unnecessarily, in this case) reads
+the whole file itself:
+
+  sub myscan {
+      my(@includes);
+      do {
+         push(@includes, /\b\S*?\.smf\b/g);
+      } while <SCAN>;
+      @includes
+  }
+
+Note that the order of the loop is reversed, with the loop test at the
+end. This is because the first line is already read for you. This scanner
+can be attached to a source file by:
+
+  QuickScan $env \&myscan, "$_.smf";
+
+This final example, which scans a different type of input file, takes
+over the file scanning rather than being called for each input line:
+
+  $env->QuickScan(
+      sub { my(@includes) = ();
+         do {
+            push(@includes, $3)
+                if /^(#include|import)\s+(\")(.+)(\")/ && $3
+         } while <SCAN>;
+         @includes
+      },
+      "$idlFileName",
+      "$env->{CPPPATH};$BUILD/ActiveContext/ACSCLientInterfaces"
+  );
+
+-->
+
+ <para>
+
+   XXX
+
+ </para>
+
+ <section>
+ <title>XXX</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
diff --git a/doc/user/separate.in b/doc/user/separate.in
new file mode 100644 (file)
index 0000000..c1b3c32
--- /dev/null
@@ -0,0 +1,429 @@
+<!--
+
+  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.
+
+-->
+
+<!--
+
+=head1 Separating source and build trees
+
+It's often desirable to keep any derived files from the build completely
+separate from the source files. This makes it much easier to keep track of
+just what is a source file, and also makes it simpler to handle B<variant>
+builds, especially if you want the variant builds to co-exist.
+
+=head2 Separating build and source directories using the Link command
+
+Cons provides a simple mechanism that handles all of these requirements. The
+C<Link> command is invoked as in this example:
+
+  Link 'build' => 'src';
+
+The specified directories are ``linked'' to the specified source
+directory. Let's suppose that you setup a source directory, F<src>, with the
+sub-directories F<world> and F<hello> below it, as in the previous
+example. You could then substitute for the original build lines the
+following:
+
+  Build qw(
+       build/world/Conscript
+       build/hello/Conscript
+  );
+
+Notice that you treat the F<Conscript> file as if it existed in the build
+directory. Now if you type the same command as before, you will get the
+following results:
+
+  % cons export
+  Install build/world/world.h as export/include/world.h
+  cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o
+  cc -Iexport/include -c build/world/world.c -o build/world/world.o
+  ar r build/world/libworld.a build/world/world.o
+  ar: creating build/world/libworld.a
+  ranlib build/world/libworld.a
+  Install build/world/libworld.a as export/lib/libworld.a
+  cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld
+  Install build/hello/hello as export/bin/hello
+
+Again, Cons has taken care of the details for you. In particular, you will
+notice that all the builds are done using source files and object files from
+the build directory. For example, F<build/world/world.o> is compiled from
+F<build/world/world.c>, and F<export/include/world.h> is installed from
+F<build/world/world.h>. This is accomplished on most systems by the simple
+expedient of ``hard'' linking the required files from each source directory
+into the appropriate build directory.
+
+The links are maintained correctly by Cons, no matter what you do to the
+source directory. If you modify a source file, your editor may do this ``in
+place'' or it may rename it first and create a new file. In the latter case,
+any hard link will be lost. Cons will detect this condition the next time
+the source file is needed, and will relink it appropriately.
+
+You'll also notice, by the way, that B<no> changes were required to the
+underlying F<Conscript> files. And we can go further, as we shall see in the
+next section.
+
+=head2 Explicit references to the source directory
+
+When using the C<Link> command on some operating systems or with some
+tool chains, it's sometimes useful to have a command actually use
+the path name to the source directory, not the build directory.  For
+example, on systems that must copy, not "hard link," the F<src/> and
+F<build/> copies of C<Linked> files, using the F<src/> path of a file
+name might make an editor aware that a syntax error must be fixed in the
+source directory, not the build directory.
+
+You can tell Cons that you want to use the "source path" for a file by
+preceding the file name with a ``!'' (exclamation point).  For example,
+if we add a ``!'' to the beginning of a source file:
+
+  Program $env "foo", "!foo.c";        # Notice initial ! on foo.c
+
+Cons will compile the target as follows:
+
+  cc -c src/foo.c -o build/foo.o
+  cc -o build/foo build/foo.o
+
+Notice that Cons has compiled the program from the the F<src/foo.c>
+source file.  Without the initial ``!'', Cons would have compiled the
+program using the F<build/foo.c> path name.
+
+-->
+
+  <para>
+
+  It's often useful to keep any built files completely
+  separate from the source files.
+  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 to do this,
+  one through the &SConscript; function that we've already seen,
+  and the second through a more flexible &BuildDir; function.
+
+  </para>
+
+  <section>
+  <title>Specifying a Build Directory as Part of an &SConscript; Call</title>
+
+    <para>
+
+    The most straightforward way to establish a build directory
+    uses the fact that the usual way to
+    set up a build hierarcy is to have an
+    &SConscript; file in the source subdirectory.
+    If you then pass a &build_dir; argument to the
+    &SConscript; function call:
+
+    </para>
+
+    <sconstruct>
+      SConscript('src/SConscript', build_dir='build')
+    </sconstruct>
+
+    <para>
+
+    &SCons; will then build all of the files in
+    the &build; subdirectory:
+
+    </para>
+
+    <scons_example name="ex1">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.Program('hello.c')
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <scons_output example="ex1">
+      <command>ls -1 src</command>
+      <command>scons</command>
+      <command>ls -1 build</command>
+    </scons_output>
+
+    <para>
+
+    But wait a minute--what's going on here?
+    &SCons; created the object file
+    <filename>build/hello.o</filename>
+    in the &build; subdirectory,
+    as expected.
+    But even though our &hello_c; file lives in the &src; subdirectory,
+    &SCons; has actually compiled a
+    <filename>build/hello.c</filename> file
+    to create the object file.
+
+    </para>
+
+    <para>
+
+    What's happened is that &SCons; has <emphasis>duplicated</emphasis>
+    the &hello_c; file from the &src; subdirectory
+    to the &build; subdirectory,
+    and built the program from there.
+    The next section explains why &SCons; does this.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Why &SCons; Duplicates Source Files in a Build Directory</title>
+
+    <para>
+
+    &SCons; duplicates source files in build directories
+    because it's the most straightforward way to guarantee a correct build
+     <emphasis>regardless of include-file directory paths</emphasis>,
+    and the &SCons; philosophy is to, by default,
+    guarantee a correct build in all cases.
+    Here is an example of an end case where duplicating
+    source files in a build directory
+    is necessary for a correct build:
+
+    </para>
+
+    <para>
+
+    XXX
+
+    </para>
+
+    <sconstruct>
+      env = Environmnet()
+    </sconstruct>
+
+    <para>
+
+    XXX
+
+    </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>Telling &SCons; to Not Duplicate Source Files in the Build Directory</title>
+
+    <para>
+
+    In most cases, however,
+    having &SCons; place its target files in a build subdirectory
+    <emphasis>without</emphasis>
+    duplicating the source files works just fine.
+    You can disable the default &SCons; behavior
+    by specifying <literal>duplicate=0</literal>
+    when you call the &SConscript; function:
+
+    </para>
+
+    <sconstruct>
+      SConscript('src/SConscript', build_dir='build', duplicate=0)
+    </sconstruct>
+
+    <para>
+
+    When this flag is specified,
+    &SCons; uses the build directory
+    like most people expect--that is,
+    the output files are placed in the build directory
+    while the source files stay in the source directory:
+
+    </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>
+
+  <section>
+  <title>The &BuildDir; Function</title>
+
+    <para>
+
+    Use the &BuildDir; function to establish that target
+    files should be built in a separate directory
+    from the source files:
+
+    </para>
+
+    <scons_example name="ex_builddir">
+      <file name="SConstruct" printme="1">
+      BuildDir('build', 'src')
+      env = Environment()
+      env.Program('build/hello.c')
+      </file>
+      <file name="src/hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    Note that when you're not using
+    an &SConscript; file in the &src; subdirectory,
+    you must actually specify that
+    the program must be built from
+    the <filename>build/hello.c</filename>
+    file that &SCons; will duplicate in the
+    &build; subdirectory.
+
+    </para>
+
+    <para>
+
+    XXX
+
+    </para>
+
+    <para>
+
+    When using the &BuildDir; function directly,
+    &SCons; still duplicates the source files
+    in the build directory by default:
+
+    </para>
+
+    <scons_output example="ex_builddir">
+      <command>ls src</command>
+      <command>scons</command>
+      <command>ls -1 build</command>
+    </scons_output>
+
+    <para>
+
+    You can specify the same <literal>duplicate=0</literal> argument
+    that you can specify for an &SConscript; call:
+
+    </para>
+
+    <scons_example name="ex_duplicate_0">
+      <file name="SConstruct" printme="1">
+      BuildDir('build', 'src', duplicate=0)
+      env = Environment()
+      env.Program('build/hello.c')
+      </file>
+      <file name="src/hello.c">
+      int main() { printf("Hello, world!\n"); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    In which case &SCons;
+    will disable duplication of the source files:
+
+    </para>
+
+    <scons_output example="ex_duplicate_0">
+      <command>ls src</command>
+      <command>scons</command>
+      <command>ls -1 build</command>
+    </scons_output>
+
+  </section>
+
+  <section>
+  <title>Using &BuildDir; With an &SConscript; File</title>
+
+    <para>
+
+    Even when using the &BuildDir; function,
+    it's much more natural to use it with
+    a subsidiary &SConscript; file.
+    For example, if the
+    <filename>src/SConscript</filename>
+    looks like this:
+
+    </para>
+
+    <scons_example name="example_builddir_sconscript">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.Program('hello.c')
+      </file>
+      <file name="SConscript">
+      BuildDir('build', 'src')
+      SConscript('build/SConscript')
+    </scons_example>
+
+    <para>
+
+    Then our &SConscript; file could look like:
+
+    </para>
+
+    <scons_example_file example="example_builddir_sconscript" name="SConscript">
+    </scons_example_file>
+
+    <para>
+
+    Yielding the following output:
+
+    </para>
+
+    <scons_output example="example_builddir_sconscript">
+      <command>ls -1 src</command>
+      <command>scons</command>
+      <command>ls -1 build</command>
+    </scons_output>
+
+    <para>
+
+    Notice that this is completely equivalent
+    to the use of &SConscript; that we
+    learned about in the previous section.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Why You'd Want to Call &BuildDir; Instead of &SConscript;</title>
+
+    <para>
+    
+    XXX
+
+    </para>
+
+  </section>
diff --git a/doc/user/simple.in b/doc/user/simple.in
new file mode 100644 (file)
index 0000000..df82ea2
--- /dev/null
@@ -0,0 +1,522 @@
+<!--
+
+  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>
+
+ Here's the famous "Hello, World!" program in C:
+
+ </para>
+
+ <programlisting>
+    int
+    main()
+    {
+        printf("Hello, world!\n");
+    }
+ </programlisting>
+
+ <para>
+
+ And here's how to build it using &SCons;.
+ Enter the following into a file named &SConstruct;:
+
+ </para>
+
+ <scons_example name="ex1">
+    <file name="SConstruct" printme="1">
+    env = Environment()
+    env.Program('hello.c')
+    </file>
+    <file name="hello.c">
+    int main() { printf("Hello, world!\n"); }
+    </file>
+ </scons_example>
+
+ <para>
+
+ That's it.  Now run the &scons; command to build the program.
+ On a POSIX-compliant system like Linux or UNIX,
+ you'll see something like:
+
+ </para>
+
+ <scons_output example="ex1" os="posix">
+    <command>scons</command>
+ </scons_output>
+
+ <para>
+
+ On a Windows system with the Microsoft Visual C++ compiler,
+ you'll see something like:
+
+ </para>
+
+ <scons_output example="ex1" os="win32">
+    <command>scons</command>
+ </scons_output>
+
+ <para>
+
+ First, notice that you only need
+ to specify the name of the source file,
+ and that &SCons; deduces the names of
+ the object and executable files
+ correctly from the base of the source file name.
+
+ </para>
+
+ <para>
+
+ Second, notice that the same input &SConstruct; file,
+ without any changes,
+ generates the correct output file names on both systems:
+ <filename>hello.o</filename> and <filename>hello</filename>
+ on POSIX systems,
+ <filename>hello.obj</filename> and <filename>hello.exe</filename>
+ on Windows systems.
+ This is a simple example of how &SCons;
+ makes it extremely easy to
+ write portable software builds.
+
+ </para>
+
+ <para>
+
+ (Note that we won't provide duplicate side-by-side
+ POSIX and Windows output for all of the examples in this guide;
+ just keep in mind that, unless otherwise specified,
+ any of the examples should work equally well on both types of systems.)
+
+ </para>
+
+ <section>
+ <title>The &SConstruct; File</title>
+
+   <para>
+
+   If you're used to build systems like &Make;
+   you've already figured out that the &SConstruct; file
+   is the &SCons; equivalent of a &Makefile;.
+   That is, the &SConstruct; file is the input file
+   that &SCons; reads to control the build.
+
+   </para>
+
+   <para>
+
+   There is, however, an important difference between
+   an &SConstruct; file and a &Makefile;:
+   the &SConstruct; file is actually a Python script.
+   If you're not already familiar with Python, don't worry.
+   This User's Guide will introduce you step-by-step
+   to the relatively small amount of Python you'll
+   need to know to be able to use &SCons; effectively.
+   And Python is very easy to learn.
+
+   </para>
+
+   <para>
+
+   One aspect of using Python as the
+   scripting language is that you can put comments
+   in your &SConstruct; file using Python's commenting convention;
+   that is, everything between a '#' and the end of the line
+   will be ignored:
+
+   </para>
+
+   <programlisting>
+      env = Environment()    # Create an environment.
+      # Arrange to build the "hello" program.
+      env.Program('hello.c')
+   </programlisting>
+
+   <para>
+
+   You'll see throughout the remainder of this Guide
+   that being able to use the power of a
+   real scripting language
+   can greatly simplify the solutions
+   to complex requirements of real-world builds.
+
+   </para>
+
+ </section>
+
+ <section>
+ <title>Compiling Multiple Source Files</title>
+
+   <para>
+
+   You've just seen how to configure &SCons;
+   to compile a program from a single source file.
+   It's more common, of course,
+   that you'll need to build a program from
+   many input source files, not just one.
+   To do this, you need to put the
+   source files in a Python list
+   (enclosed in square brackets),
+   like so:
+
+   </para>
+
+   <scons_example name="ex2">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.Program(['prog.c', 'file1.c', 'file2.c'])
+      </file>
+      <file name="prog.c">
+      int main() { printf("prog.c\n"); }
+      </file>
+      <file name="file1.c">
+      void file1() { printf("file1.c\n"); }
+      </file>
+      <file name="file2.c">
+      void file2() { printf("file2.c\n"); }
+      </file>
+   </scons_example>
+
+   <para>
+
+   A build of the above example would look like:
+
+   </para>
+
+   <scons_output example="ex2">
+      <command>scons</command>
+   </scons_output>
+
+   <para>
+
+   Notice that &SCons;
+   deduces the output program name
+   from the first source file specified
+   in the list--that is,
+   because the first source file was &prog_c;,
+   &SCons; will name the resulting program &prog;
+   (or &prog_exe; on a Windows system).
+   If you want to specify a different program name,
+   then you slide the list of source files
+   over to the right
+   to make room for the output program file name.
+   (&SCons; puts the output file name to the left
+   of the source file names
+   so that the order mimics that of an
+   assignment statement:  "program = source files".)
+   This makes our example:
+
+   </para>
+
+   <scons_example name="ex3">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.Program('program', ['main.c', 'file1.c', 'file2.c'])
+      </file>
+      <file name="main.c">
+      int main() { printf("prog.c\n"); }
+      </file>
+      <file name="file1.c">
+      void file1() { printf("file1.c\n"); }
+      </file>
+      <file name="file2.c">
+      void file2() { printf("file2.c\n"); }
+      </file>
+   </scons_example>
+
+   <para>
+
+   On Linux, a build of this example would look like:
+
+   </para>
+
+   <scons_output example="ex3" os="posix">
+      <command>scons</command>
+   </scons_output>
+
+   <para>
+
+   Or on Windows:
+
+   </para>
+
+   <scons_output example="ex3" os="win32">
+      <command>scons</command>
+   </scons_output>
+
+ </section>
+
+ <section>
+ <title>Keeping &SConstruct; Files Easy to Read</title>
+
+   <para>
+
+   One drawback to the use of a Python list
+   for source files is that 
+   each file name must be enclosed in quotes
+   (either single quotes or double quotes).
+   This can get cumbersome and difficult to read
+   when the list of file names is long.
+   Fortunately, &SCons; and Python provide a number of ways
+   to make sure that
+   the &SConstruct; file stays easy to read.
+
+   </para>
+
+   <para>
+
+   To make long lists of file names
+   easier to deal with, &SCons; provides a
+   &Split; function
+   that takes a quoted list of file names,
+   with the names separated by spaces or other white-space characters,
+   and turns it into a list of separate file names.
+   Using the &Split; function turns the
+   previous example into:
+
+   </para>
+
+   <programlisting>
+      env = Environment()
+      env.Program('program', Split('main.c file1.c file2.'))
+   </programlisting>
+
+   <para>
+
+   Putting the call to the &Split; function
+   inside the <function>env.Program</function> call
+   can also be a little unwieldy.
+   A more readable alternative is to
+   assign the output from the &Split; call
+   to a variable name,
+   and then use the variable when calling the
+   <function>env.Program</function> function:
+
+   </para>
+
+   <programlisting>
+      env = Environment()
+      list = Split('main.c file1.c file2.')
+      env.Program('program', list)
+   </programlisting>
+
+   <para>
+
+   Lastly, the &Split; function
+   doesn't care how much white space separates
+   the file names in the quoted string.
+   This allows you to create lists of file
+   names that span multiple lines,
+   which often makes for easier editing:
+
+   </para>
+
+   <programlisting>
+      env = Environment()
+      list = Split('main.c
+                    file1.c
+                    file2.c')
+      env.Program('program', list)
+   </programlisting>
+
+ </section>
+
+ <section>
+ <title>Keyword Arguments</title>
+
+   <para>
+
+   &SCons; also allows you to identify
+   the output file and input source files
+   using Python keyword arguments.
+   The output file is known as the
+   <emphasis>target</emphasis>,
+   and the source file(s) are known (logically enough) as the
+   <emphasis>source</emphasis>.
+   The Python syntax for this is:
+
+   </para>
+
+   <programlisting>
+      env = Environment()
+      list = Split('main.c file1.c file2.')
+      env.Program(target = 'program', source = list)
+   </programlisting>
+
+   <para>
+
+   Whether or not you choose to use keyword arguments
+   to identify the target and source files
+   is purely a personal choice;
+   &SCons; functions the same either way.
+
+   </para>
+
+ </section>
+
+ <section>
+ <title>Compiling Multiple Programs</title>
+
+   <para>
+
+   In order to compile multiple programs
+   within the same &SConstruct; file,
+   simply call the <function>env.Program</function> method
+   multiple times,
+   once for each program you need to build:
+
+   </para>
+
+   <scons_example name="ex4">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.Program('foo.c')
+      env.Program('bar', ['bar1.c', 'bar2.c'])
+      </file>
+      <file name="foo.c">
+      int main() { printf("foo.c\n"); }
+      </file>
+      <file name="bar1.c">
+      int main() { printf("bar1.c\n"); }
+      </file>
+      <file name="bar2.c">
+      void bar2() { printf("bar2.c\n"); }
+      </file>
+   </scons_example>
+
+   <para>
+
+   &SCons; would then build the programs as follows:
+
+   </para>
+
+   <scons_output example="ex4">
+      <command>scons</command>
+   </scons_output>
+
+   <para>
+
+   Notice that &SCons; does not necessarily build the
+   programs in the same order in which you specify
+   them in the &SConstruct; file.
+   &SCons; does, however, recognize that
+   the individual object files must be built
+   before the resulting program can be built.
+   We'll discuss this in greater detail in
+   the "Dependencies" section, below.
+
+   </para>
+
+ </section>
+
+ <section>
+ <title>Sharing Source Files Between Multiple Programs</title>
+
+   <para>
+
+   It's common to re-use code by sharing source files
+   between multiple programs.
+   One way to do this is to create a library
+   from the common source files,
+   which can then be linked into resulting programs.
+   (Creating libraries is discussed in
+   section XXX, below.)
+
+   </para>
+
+   <para>
+
+   A more straightforward, but perhaps less convenient,
+   way to share source files between multiple programs
+   is simply to include the common files
+   in the lists of source files for each program:
+
+   </para>
+
+   <scons_example name="ex5">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.Program(Split('foo.c common1.c common2.c'))
+      env.Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
+      </file>
+      <file name="foo.c">
+      int main() { printf("foo.c\n"); }
+      </file>
+      <file name="bar1.c">
+      int main() { printf("bar1.c\n"); }
+      </file>
+      <file name="bar2.c">
+      int bar2() { printf("bar2.c\n"); }
+      </file>
+      <file name="common1.c">
+      void common1() { printf("common1.c\n"); }
+      </file>
+      <file name="common2.c">
+      void common22() { printf("common2.c\n"); }
+      </file>
+   </scons_example>
+
+   <para>
+
+   &SCons; recognizes that the object files for
+   the &common1_c; and &common2_c; source files
+   each only need to be built once,
+   even though the files are listed multiple times:
+
+   </para>
+
+   <scons_output example="ex5">
+      <command>scons</command>
+   </scons_output>
+
+   <para>
+
+   If two or more programs
+   share a lot of common source files,
+   repeating the common files in the list for each program
+   can be a maintenance problem when you need to change the
+   list of common files.
+   You can simplify this by creating a separate Python list
+   to hold the common file names,
+   and concatenating it with other lists
+   using the Python &plus; operator:
+
+   </para>
+
+   <programlisting>
+      common = ['common1.c', 'common2.c']
+      foo_files = ['foo.c'] + common
+      bar_files = ['bar1.c', 'bar2.c'] + common
+      env = Environment()
+      env.Program('foo', foo_files)
+      env.Program('bar', bar_files)
+   </programlisting>
+
+   <para>
+
+   This is functionally equivalent to the previous example.
+
+   </para>
+
+ </section>
diff --git a/doc/user/sourcecode.in b/doc/user/sourcecode.in
new file mode 100644 (file)
index 0000000..b794c09
--- /dev/null
@@ -0,0 +1,153 @@
+<!--
+
+  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>
+
+   <scons_example name="ex_bitkeeper">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.SourceCode('.', env.BitKeeper('XXX'))
+      env.Program('hello.c')
+      </file>
+   </scons_example>
+
+   <scons_output example="ex_bitkeeper">
+     <userinput>scons</userinput>
+   </scons_output>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From CVS</title>
+
+   <para>
+
+   X
+
+   </para>
+
+   <scons_example name="ex_cvs">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.SourceCode('.', env.CVS('XXX'))
+      env.Program('hello.c')
+      </file>
+   </scons_example>
+
+   <scons_output example="ex_cvs">
+     <userinput>scons</userinput>
+   </scons_output>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From RCS</title>
+
+   <para>
+
+   X
+
+   </para>
+
+   <scons_example name="ex_rcs">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.SourceCode('.', env.RCS())
+      env.Program('hello.c')
+      </file>
+   </scons_example>
+
+   <scons_output example="ex_rcs">
+     <userinput>scons</userinput>
+   </scons_output>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From SCCS</title>
+
+   <para>
+
+   X
+
+   </para>
+
+   <scons_example name="ex_sccs">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.SourceCode('.', env.SCCS())
+      env.Program('hello.c')
+      </file>
+   </scons_example>
+
+   <scons_output example="ex_sccs">
+     <userinput>scons</userinput>
+   </scons_output>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Fetching Source Code From Subversion</title>
+
+   <para>
+
+   X
+
+   </para>
+
+   <scons_example name="ex_subversion">
+      <file name="SConstruct" printme="1">
+      env = Environment()
+      env.SourceCode('.', env.Subversion('XXX'))
+      env.Program('hello.c')
+      </file>
+   </scons_example>
+
+   <scons_output example="ex_subversion">
+     <userinput>scons</userinput>
+   </scons_output>
+
+ </section>
+
+ -->
diff --git a/doc/user/troubleshoot.in b/doc/user/troubleshoot.in
new file mode 100644 (file)
index 0000000..f83ab63
--- /dev/null
@@ -0,0 +1,41 @@
+<!--
+
+  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>
+
+   XXX
+
+ </para>
+
+ <section>
+ <title>XXX</title>
+
+   <para>
+
+   XXX
+
+   </para>
+
+ </section>
diff --git a/doc/user/variants.in b/doc/user/variants.in
new file mode 100644 (file)
index 0000000..1fb461a
--- /dev/null
@@ -0,0 +1,179 @@
+<!--
+
+  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.
+
+-->
+
+<!--
+
+=head1 Variant builds
+
+
+=head2 Hello, World! for baNaNa and peAcH OS's
+
+Variant builds require just another simple extension. Let's take as an
+example a requirement to allow builds for both the baNaNa and peAcH
+operating systems. In this case, we are using a distributed file system,
+such as NFS to access the particular system, and only one or the other of
+the systems has to be compiled for any given invocation of C<cons>. Here's
+one way we could set up the F<Construct> file for our B<Hello, World!>
+application:
+
+  # Construct file for Hello, World!
+
+  die qq(OS must be specified) unless $OS = $ARG{OS};
+  die qq(OS must be "peach" or "banana")
+       if $OS ne "peach" && $OS ne "banana";
+
+  # Where to put all our shared products.
+  $EXPORT = "#export/$OS";
+
+  Export qw( CONS INCLUDE LIB BIN );
+
+  # Standard directories for sharing products.
+  $INCLUDE = "$EXPORT/include";
+  $LIB = "$EXPORT/lib";
+  $BIN = "$EXPORT/bin";
+
+  # A standard construction environment.
+  $CONS = new cons (
+       CPPPATH => $INCLUDE,    # Include path for C Compilations
+       LIBPATH => $LIB,        # Library path for linking programs
+       LIBS => '-lworld',      # List of standard libraries
+  );
+
+  # $BUILD is where we will derive everything.
+  $BUILD = "#build/$OS";
+
+  # Tell cons where the source files for $BUILD are.
+  Link $BUILD => 'src';
+
+  Build (
+       "$BUILD/hello/Conscript",
+       "$BUILD/world/Conscript",
+  );
+
+Now if we login to a peAcH system, we can build our B<Hello, World!>
+application for that platform:
+
+  % cons export OS=peach
+  Install build/peach/world/world.h as export/peach/include/world.h
+  cc -Iexport/peach/include -c build/peach/hello/hello.c -o build/peach/hello/hello.o
+  cc -Iexport/peach/include -c build/peach/world/world.c -o build/peach/world/world.o
+  ar r build/peach/world/libworld.a build/peach/world/world.o
+  ar: creating build/peach/world/libworld.a
+  ranlib build/peach/world/libworld.a
+  Install build/peach/world/libworld.a as export/peach/lib/libworld.a
+  cc -o build/peach/hello/hello build/peach/hello/hello.o -Lexport/peach/lib -lworld
+  Install build/peach/hello/hello as export/peach/bin/hello
+
+
+=head2 Variations on a theme
+
+Other variations of this model are possible. For example, you might decide
+that you want to separate out your include files into platform dependent and
+platform independent files. In this case, you'd have to define an
+alternative to C<$INCLUDE> for platform-dependent files. Most F<Conscript>
+files, generating purely platform-independent include files, would not have
+to change.
+
+You might also want to be able to compile your whole system with debugging
+or profiling, for example, enabled. You could do this with appropriate
+command line options, such as C<DEBUG=on>. This would then be translated
+into the appropriate platform-specific requirements to enable debugging
+(this might include turning off optimization, for example). You could
+optionally vary the name space for these different types of systems, but, as
+we'll see in the next section, it's not B<essential> to do this, since Cons
+is pretty smart about rebuilding things when you change options.
+
+-->
+
+  <para>
+
+  The &BuildDir; function now gives us everything
+  we need to show how easy it is to create
+  variant builds using &SCons;.
+  Suppose, for example, that we want to
+  build a program for both Windows and Linux platforms,
+  but that we want to build it in a shared directory
+  with separate side-by-side build directories
+  for the Windows and Linux versions of the program.
+
+  </para>
+
+  <scons_example name="ex_variants">
+    <file name="SConstruct" printme="1">
+    platform = ARGUMENT.get('OS', Platform())
+
+    include = "#export/$PLATFORM/include"
+    lib = "#export/$PLATFORM/lib"
+    bin = "#export/$PLATFORM/bin"
+
+    env = Environment(PLATFORM = platform,
+                      CPPPATH = [include],
+                      LIB = lib,
+                      LIBS = '-lworld')
+
+    Export('env')
+
+    SConscript('src/SConscript', build_dir='build/$PLATFORM')
+
+    #
+    #BuildDir("#build/$PLATFORM", 'src')
+    #SConscript("build/$PLATFORM/hello/SConscript")
+    #SConscript("build/$PLATFORM/world/SConscript")
+    </file>
+  </scons_example>
+
+  <para>
+
+  This SConstruct file,
+  when run on a Linux system, yields:
+
+  </para>
+
+  <scons_output example="ex_variants" os="posix">
+    <command>scons OS=linux</command>
+  </scons_output>
+
+  <para>
+
+  The same SConstruct file on Windows would build:
+
+  </para>
+
+  <scons_output example="ex_variants" os="win32">
+    <command>scons OS=windows</command>
+  </scons_output>
+
+  <scons_example name="ex_var2">
+  <programlisting>
+    <file name="SConstruct" printme="1">
+    env = Environment(OS = )
+    for os in ['newell', 'post']:
+        SConscript('src/SConscript', build_dir='build/' + os)
+    </file>
+  </scons_example>
+
+  <scons_output example="ex_var2">
+    % <userinput>scons</userinput>
+  </scons_output>
index 87420aa098169bece035e2c21afae3409f748c02..5ade3e0ba1ebb6f257c692df77850aa3d811e7d2 100644 (file)
@@ -257,7 +257,7 @@ class NullCmdGenerator:
     def __init__(self, cmd):
         self.cmd = cmd
 
-    def __call__(self, target, source, env):
+    def __call__(self, target, source, env, for_signature=None):
         return self.cmd
 
 ConstructionEnvironment = {
index d0a22b5672129ba983a6273b77e44cc960fcea54..fae86e44c8e0ce4db12d06ac6ecb0c5ea45256b6 100644 (file)
@@ -165,7 +165,7 @@ class Environment:
     """
 
     def __init__(self,
-                 platform=SCons.Platform.Platform(),
+                 platform=None,
                  tools=None,
                  options=None,
                  **kw):
@@ -174,6 +174,10 @@ class Environment:
 
         self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
 
+        if platform is None:
+            platform = self._dict.get('PLATFORM', None)
+            if platform is None:
+                platform = SCons.Platform.Platform()
         if SCons.Util.is_String(platform):
             platform = SCons.Platform.Platform(platform)
         self._dict['PLATFORM'] = str(platform)
@@ -189,7 +193,9 @@ class Environment:
             options.Update(self)
 
         if tools is None:
-            tools = ['default']
+            tools = self._dict.get('TOOLS', None)
+            if tools is None:
+                tools = ['default']
         apply_tools(self, tools)
 
         # Reapply the passed in variables after calling the tools,
index 503841989abf6c995f48cfc35854e39578fe69da..e79ce7c0fe2584684489e429bf19760789e76bc3 100644 (file)
@@ -909,11 +909,37 @@ class EnvironmentTestCase(unittest.TestCase):
             def __call__(self, env):  env['XYZZY'] = 777
 
         def tool(env):
+            env['SET_TOOL'] = 'initialized'
             assert env['PLATFORM'] == "TestPlatform"
 
         env = Environment(platform = platform(), tools = [tool])
         assert env['XYZZY'] == 777, env
         assert env['PLATFORM'] == "TestPlatform"
+        assert env['SET_TOOL'] == "initialized"
+
+    def test_Default_PLATFORM(self):
+        """Test overriding the default PLATFORM variable"""
+        class platform:
+            def __str__(self):        return "DefaultTestPlatform"
+            def __call__(self, env):  env['XYZZY'] = 888
+
+        def tool(env):
+            env['SET_TOOL'] = 'abcde'
+            assert env['PLATFORM'] == "DefaultTestPlatform"
+
+        import SCons.Defaults
+        save = SCons.Defaults.ConstructionEnvironment.copy()
+        try:
+            import SCons.Defaults
+            SCons.Defaults.ConstructionEnvironment.update({
+                'PLATFORM' : platform(),
+            })
+            env = Environment(tools = [tool])
+            assert env['XYZZY'] == 888, env
+            assert env['PLATFORM'] == "DefaultTestPlatform"
+            assert env['SET_TOOL'] == "abcde"
+        finally:
+            SCons.Defaults.ConstructionEnvironment = save
 
     def test_tools(self):
         """Test specifying a tool callable when instantiating."""
@@ -932,6 +958,31 @@ class EnvironmentTestCase(unittest.TestCase):
         t4(env)
         assert env['TOOL4'] == 444, env
         
+    def test_Default_TOOLS(self):
+        """Test overriding the default TOOLS variable"""
+        def t5(env):
+            env['TOOL5'] = 555
+        def t6(env):
+            env['TOOL6'] = 666
+        def t7(env):
+            env['BBB'] = env['XYZ']
+        def t8(env):
+            env['TOOL8'] = 888
+
+        import SCons.Defaults
+        save = SCons.Defaults.ConstructionEnvironment.copy()
+        try:
+            SCons.Defaults.ConstructionEnvironment.update({
+                'TOOLS' : [t5, t6, t7],
+            })
+            env = Environment(XYZ = 'bbb')
+            assert env['TOOL5'] == 555, env['TOOL5']
+            assert env['TOOL6'] == 666, env
+            assert env['BBB'] == 'bbb', env        
+            t8(env)
+            assert env['TOOL8'] == 888, env
+        finally:
+            SCons.Defaults.ConstructionEnvironment = save
 
     def test_get(self):
         """Test the get() method."""
diff --git a/test/ToolSurrogate.py b/test/ToolSurrogate.py
new file mode 100644 (file)
index 0000000..f33d804
--- /dev/null
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that SCons supports use of a home-brew ToolSurrogate class
+like we use in our bin/sconsexamples.py script.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+class Curry:
+    def __init__(self, fun, *args, **kwargs):
+        self.fun = fun
+        self.pending = args[:]
+        self.kwargs = kwargs.copy()
+
+    def __call__(self, *args, **kwargs):
+        if kwargs and self.kwargs:
+            kw = self.kwargs.copy()
+            kw.update(kwargs)
+        else:
+            kw = kwargs or self.kwargs
+
+        return apply(self.fun, self.pending + args, kw)
+
+def Str(target, source, env, cmd=""):
+    return env.subst(cmd, target=target, source=source)
+
+class ToolSurrogate:
+    def __init__(self, tool, variable, func):
+        self.tool = tool
+        self.variable = variable
+        self.func = func
+    def __call__(self, env):
+        t = Tool(self.tool)
+        t.generate(env)
+        orig = env[self.variable]
+        env[self.variable] = Action(self.func, strfunction=Curry(Str, cmd=orig))
+
+def Cat(target, source, env):
+    target = str(target[0])
+    f = open(target, "wb")
+    for src in map(str, source):
+        f.write(open(src, "rb").read())
+    f.close()
+
+ToolList = {
+    'posix' :   [('cc', 'CCCOM', Cat),
+                 ('link', 'LINKCOM', Cat)],
+    'win32' :   [('msvc', 'CCCOM', Cat),
+                 ('mslink', 'LINKCOM', Cat)]
+}
+
+platform = ARGUMENTS['platform']
+tools = map(lambda t: apply(ToolSurrogate, t), ToolList[platform])
+
+env = Environment(tools = tools)
+env.Program('foo.c')
+""")
+
+test.write('foo.c', "foo.c posix\n")
+
+test.run(arguments = '. platform=posix', stdout = test.wrap_stdout("""\
+cc -c -o foo.o foo.c
+c++ -o foo foo.o
+"""))
+
+test.write('foo.c', "foo.c win32\n")
+
+test.run(arguments = '. platform=win32', stdout = test.wrap_stdout("""\
+cl /nologo /c foo.c /Fofoo.o
+link /nologo /OUT:foo foo.o
+"""))
+
+test.pass_test()