summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorLuca Falavigna <dktrkranz@debian.org>2010-01-02 20:56:27 +0100
committerLuca Falavigna <dktrkranz@debian.org>2010-01-02 20:56:27 +0100
commit72c578fd4b0b4a5a43e18594339ac4ff26c376dc (patch)
treecadaf3abe37a1066ceae933bc8fe7b75c85f56d2 /doc
parent548ed1064f327bccc6e538806740d41ea2d928a1 (diff)
Imported Upstream version 1.2.0.d20091224upstream/1.2.0.d20091224
Diffstat (limited to 'doc')
-rw-r--r--doc/MANIFEST1
-rw-r--r--doc/SConscript530
-rw-r--r--doc/design/MANIFEST14
-rw-r--r--doc/design/acks.xml179
-rw-r--r--doc/design/bground.xml86
-rw-r--r--doc/design/copyright.xml39
-rw-r--r--doc/design/engine.fig179
-rw-r--r--doc/design/engine.jpgbin0 -> 41228 bytes
-rw-r--r--doc/design/engine.xml1964
-rw-r--r--doc/design/goals.xml216
-rw-r--r--doc/design/install.xml28
-rw-r--r--doc/design/intro.xml111
-rw-r--r--doc/design/issues.xml195
-rw-r--r--doc/design/main.xml158
-rw-r--r--doc/design/native.xml364
-rw-r--r--doc/design/overview.xml498
-rw-r--r--doc/design/scons.mod429
-rw-r--r--doc/developer/MANIFEST9
-rw-r--r--doc/developer/architecture.xml40
-rw-r--r--doc/developer/branches.xml40
-rw-r--r--doc/developer/copyright.xml32
-rw-r--r--doc/developer/cycle.xml40
-rw-r--r--doc/developer/main.xml110
-rw-r--r--doc/developer/packaging.xml40
-rw-r--r--doc/developer/preface.xml175
-rw-r--r--doc/developer/sourcetree.xml40
-rw-r--r--doc/developer/testing.xml40
-rw-r--r--doc/man/MANIFEST2
-rw-r--r--doc/man/scons-time.11017
-rw-r--r--doc/man/scons.110149
-rw-r--r--doc/man/sconsign.1208
-rw-r--r--doc/python10/MANIFEST16
-rw-r--r--doc/python10/abstract.xml32
-rw-r--r--doc/python10/acks.xml27
-rw-r--r--doc/python10/arch.eps134
-rw-r--r--doc/python10/arch.fig35
-rw-r--r--doc/python10/arch.jpgbin0 -> 22004 bytes
-rw-r--r--doc/python10/builder.eps325
-rw-r--r--doc/python10/builder.fig128
-rw-r--r--doc/python10/builder.jpgbin0 -> 53107 bytes
-rw-r--r--doc/python10/copyright.xml32
-rw-r--r--doc/python10/design.xml898
-rw-r--r--doc/python10/future.xml170
-rw-r--r--doc/python10/install.xml179
-rw-r--r--doc/python10/intro.xml212
-rw-r--r--doc/python10/job-task.eps238
-rw-r--r--doc/python10/job-task.fig90
-rw-r--r--doc/python10/job-task.jpgbin0 -> 25895 bytes
-rw-r--r--doc/python10/main.xml221
-rw-r--r--doc/python10/node.eps351
-rw-r--r--doc/python10/node.fig165
-rw-r--r--doc/python10/node.jpgbin0 -> 61105 bytes
-rw-r--r--doc/python10/process.xml353
-rw-r--r--doc/python10/scanner.eps168
-rw-r--r--doc/python10/scanner.fig57
-rw-r--r--doc/python10/scanner.jpgbin0 -> 26788 bytes
-rw-r--r--doc/python10/scons.mod428
-rw-r--r--doc/python10/sig.eps147
-rw-r--r--doc/python10/sig.fig44
-rw-r--r--doc/python10/sig.jpgbin0 -> 13913 bytes
-rw-r--r--doc/reference/Alias.xml41
-rw-r--r--doc/reference/CFile.xml41
-rw-r--r--doc/reference/CXXFile.xml41
-rw-r--r--doc/reference/Command.xml73
-rw-r--r--doc/reference/Install.xml41
-rw-r--r--doc/reference/InstallAs.xml41
-rw-r--r--doc/reference/Library.xml152
-rw-r--r--doc/reference/MANIFEST21
-rw-r--r--doc/reference/Object.xml71
-rw-r--r--doc/reference/PCH.xml41
-rw-r--r--doc/reference/PDF.xml41
-rw-r--r--doc/reference/PostScript.xml41
-rw-r--r--doc/reference/Program.xml77
-rw-r--r--doc/reference/RES.xml41
-rw-r--r--doc/reference/SharedLibrary.xml41
-rw-r--r--doc/reference/SharedObject.xml41
-rw-r--r--doc/reference/StaticLibrary.xml41
-rw-r--r--doc/reference/StaticObject.xml41
-rw-r--r--doc/reference/copyright.xml32
-rw-r--r--doc/reference/errors.xml41
-rw-r--r--doc/reference/main.xml207
-rw-r--r--doc/reference/preface.xml85
-rw-r--r--doc/scons.mod521
-rw-r--r--doc/user/MANIFEST50
-rw-r--r--doc/user/README21
-rw-r--r--doc/user/SCons-win32-install-1.jpgbin0 -> 28857 bytes
-rw-r--r--doc/user/SCons-win32-install-2.jpgbin0 -> 27131 bytes
-rw-r--r--doc/user/SCons-win32-install-3.jpgbin0 -> 25137 bytes
-rw-r--r--doc/user/SCons-win32-install-4.jpgbin0 -> 19549 bytes
-rw-r--r--doc/user/actions.in404
-rw-r--r--doc/user/actions.xml404
-rw-r--r--doc/user/add-method.in127
-rw-r--r--doc/user/add-method.xml135
-rw-r--r--doc/user/alias.in102
-rw-r--r--doc/user/alias.xml112
-rw-r--r--doc/user/ant.in52
-rw-r--r--doc/user/ant.xml52
-rw-r--r--doc/user/build-install.in719
-rw-r--r--doc/user/build-install.xml719
-rw-r--r--doc/user/builders-built-in.in963
-rw-r--r--doc/user/builders-built-in.xml949
-rw-r--r--doc/user/builders-commands.in156
-rw-r--r--doc/user/builders-commands.xml146
-rw-r--r--doc/user/builders-writing.in1087
-rw-r--r--doc/user/builders-writing.xml953
-rw-r--r--doc/user/builders.in57
-rw-r--r--doc/user/builders.xml57
-rw-r--r--doc/user/caching.in502
-rw-r--r--doc/user/caching.xml506
-rw-r--r--doc/user/command-line.in2327
-rw-r--r--doc/user/command-line.xml2243
-rw-r--r--doc/user/cons.pl720
-rw-r--r--doc/user/copyright.in32
-rw-r--r--doc/user/copyright.xml32
-rw-r--r--doc/user/depends.in1816
-rw-r--r--doc/user/depends.xml1776
-rw-r--r--doc/user/environments.in1678
-rw-r--r--doc/user/environments.xml1684
-rw-r--r--doc/user/errors.in41
-rw-r--r--doc/user/errors.xml41
-rw-r--r--doc/user/example.in41
-rw-r--r--doc/user/example.xml41
-rw-r--r--doc/user/factories.in507
-rw-r--r--doc/user/factories.xml466
-rw-r--r--doc/user/file-removal.in223
-rw-r--r--doc/user/file-removal.xml202
-rw-r--r--doc/user/hierarchy.in794
-rw-r--r--doc/user/hierarchy.xml746
-rw-r--r--doc/user/install.in247
-rw-r--r--doc/user/install.xml237
-rw-r--r--doc/user/java.in657
-rw-r--r--doc/user/java.xml433
-rw-r--r--doc/user/less-simple.in623
-rw-r--r--doc/user/less-simple.xml608
-rw-r--r--doc/user/libraries.in445
-rw-r--r--doc/user/libraries.xml451
-rw-r--r--doc/user/main.in385
-rw-r--r--doc/user/main.xml385
-rw-r--r--doc/user/make.in121
-rw-r--r--doc/user/make.xml121
-rw-r--r--doc/user/mergeflags.in137
-rw-r--r--doc/user/mergeflags.xml138
-rw-r--r--doc/user/misc.in606
-rw-r--r--doc/user/misc.xml565
-rw-r--r--doc/user/nodes.in386
-rw-r--r--doc/user/nodes.xml401
-rw-r--r--doc/user/output.in681
-rw-r--r--doc/user/output.xml703
-rw-r--r--doc/user/parseconfig.in114
-rw-r--r--doc/user/parseconfig.xml132
-rw-r--r--doc/user/parseflags.in184
-rw-r--r--doc/user/parseflags.xml199
-rw-r--r--doc/user/preface.in426
-rw-r--r--doc/user/preface.xml426
-rw-r--r--doc/user/python.in154
-rw-r--r--doc/user/python.xml154
-rw-r--r--doc/user/repositories.in641
-rw-r--r--doc/user/repositories.xml595
-rw-r--r--doc/user/run.in375
-rw-r--r--doc/user/run.xml375
-rw-r--r--doc/user/scanners.in331
-rw-r--r--doc/user/scanners.xml317
-rw-r--r--doc/user/sconf.in486
-rw-r--r--doc/user/sconf.xml486
-rw-r--r--doc/user/separate.in540
-rw-r--r--doc/user/separate.xml520
-rw-r--r--doc/user/sideeffect.in216
-rw-r--r--doc/user/sideeffect.xml211
-rw-r--r--doc/user/simple.in517
-rw-r--r--doc/user/simple.xml587
-rw-r--r--doc/user/sourcecode.in162
-rw-r--r--doc/user/sourcecode.xml157
-rw-r--r--doc/user/tasks.in108
-rw-r--r--doc/user/tasks.xml108
-rw-r--r--doc/user/tools.in38
-rw-r--r--doc/user/tools.xml38
-rw-r--r--doc/user/troubleshoot.in875
-rw-r--r--doc/user/troubleshoot.xml1313
-rw-r--r--doc/user/variables.in56
-rw-r--r--doc/user/variables.xml56
-rw-r--r--doc/user/variants.in151
-rw-r--r--doc/user/variants.xml146
182 files changed, 66403 insertions, 0 deletions
diff --git a/doc/MANIFEST b/doc/MANIFEST
new file mode 100644
index 0000000..008afab
--- /dev/null
+++ b/doc/MANIFEST
@@ -0,0 +1 @@
+scons.mod
diff --git a/doc/SConscript b/doc/SConscript
new file mode 100644
index 0000000..fd18ef4
--- /dev/null
+++ b/doc/SConscript
@@ -0,0 +1,530 @@
+#
+# SConscript file for building SCons documentation.
+#
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+#
+# 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.
+#
+
+import os.path
+import re
+import string
+
+Import('build_dir', 'env', 'whereis')
+
+env = env.Clone()
+
+build = os.path.join(build_dir, 'doc')
+
+#
+#
+#
+dist_doc_tar_gz = '$DISTDIR/scons-doc-${VERSION}.tar.gz'
+
+#
+# We'll only try to build text files (for some documents)
+# if lynx is available to do the dump.
+#
+fig2dev = whereis('fig2dev')
+epydoc = whereis('epydoc')
+groff = whereis('groff')
+lynx = whereis('lynx')
+man2html = whereis('man2html')
+jade_original = whereis('jade')
+jade = whereis('openjade') or jade_original
+jadetex = whereis('jadetex')
+pdfjadetex = whereis('pdfjadetex')
+jw = whereis('jw')
+tidy = whereis('tidy')
+
+tar_deps = []
+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="([^"]*)")?')
+
+#
+# Find internal dependencies in .xml files:
+#
+# <!entity bground SYSTEM "bground.xml">
+# <graphic fileref="file.jpg">
+# <imagedata fileref="file.jpg">
+#
+# This only finds one per line, and assumes that anything
+# defined as a SYSTEM entity is, in fact, a file included
+# somewhere in the document.
+#
+def scanxml(node, env, target):
+ includes = []
+
+ contents = node.get_text_contents()
+
+ includes.extend(entity_re.findall(contents))
+
+ matches = format_re.findall(contents)
+ for m in matches:
+ file, format = m
+ if format and file[-len(format):] != format:
+ file = file + '.' + format
+ if not os.path.isabs(file):
+ a = []
+ f = file
+ while f:
+ f, tail = os.path.split(f)
+ if tail == 'doc':
+ break
+ a = [tail] + a
+ file = apply(os.path.join, a, {})
+ includes.append(file)
+
+ return includes
+
+s = Scanner(name = 'xml', function = scanxml, skeys = ['.xml', '.mod'])
+
+orig_env = env
+env = orig_env.Clone(SCANNERS = [s],
+ SCONS_PROC_PY = File('#bin/scons-proc.py').rfile(),
+ SCONSOUTPUT_PY = File('#bin/sconsoutput.py').rfile())
+
+# Fetch the list of files in the build engine that contain
+# SCons documentation XML for processing.
+def chop(s): return s[:-1]
+
+# If we ever read doc from __scons_doc__ strings in *.py files again,
+# here's how it's done:
+#manifest_in = File('#src/engine/MANIFEST.in').rstr()
+#manifest_xml_in = File('#src/engine/MANIFEST-xml.in').rstr()
+#scons_doc_files = map(chop, open(manifest_in).readlines() +\
+# open(manifest_xml_in).readlines())
+#scons_doc_files = map(lambda x: '#src/engine/'+x, scons_doc_files)
+#manifest_in = File('#src/engine/MANIFEST.in').rstr()
+
+manifest_xml_in = File('#src/engine/MANIFEST-xml.in').rstr()
+scons_doc_files = map(chop, open(manifest_xml_in).readlines())
+scons_doc_files = map(lambda x: File('#src/engine/'+x).rstr(), scons_doc_files)
+
+if not jw:
+ print "jw not found, skipping building User Guide."
+else:
+ #
+ # Always create a version.xml file containing the version information
+ # for this run. Ignore it for dependency purposes so we don't
+ # rebuild all the docs every time just because the date changes.
+ #
+ date, ver, rev = env.Dictionary('DATE', 'VERSION', 'REVISION')
+ version_xml = File(os.path.join(build, "version.xml"))
+ #version_xml = File("version.xml")
+ verfile = str(version_xml)
+ try:
+ os.unlink(verfile)
+ except OSError:
+ pass # okay if the file didn't exist
+ dir, f = os.path.split(verfile)
+ try:
+ os.makedirs(dir)
+ except OSError:
+ pass # okay if the directory already exists
+ open(verfile, "w").write("""<!--
+THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
+-->
+<!ENTITY builddate "%s">
+<!ENTITY buildversion "%s">
+<!ENTITY buildrevision "%s">
+""" % (date, ver, rev))
+
+ builders_gen = os.path.join(build, 'user', 'builders.gen')
+ builders_mod = os.path.join(build, 'user', 'builders.mod')
+ tools_gen = os.path.join(build, 'user', 'tools.gen')
+ tools_mod = os.path.join(build, 'user', 'tools.mod')
+ variables_gen = os.path.join(build, 'user', 'variables.gen')
+ variables_mod = os.path.join(build, 'user', 'variables.mod')
+
+ # We put $( - $) around $SOURCES in the command line below because
+ # the path names will change when a given input file is found in
+ # a repository one run and locally the next, and we don't want
+ # to rebuild documentation just because it's found in one location
+ # vs. the other. The *.gen and *.mod targets will still be dependent
+ # on the list of the files themselves.
+ doc_output_files = [builders_gen, builders_mod,
+ tools_gen, tools_mod,
+ variables_gen, variables_mod]
+ b = env.Command(doc_output_files,
+ scons_doc_files,
+ "$PYTHON $SCONS_PROC_PY --xml -b ${TARGETS[0]},${TARGETS[1]} -t ${TARGETS[2]},${TARGETS[3]} -v ${TARGETS[4]},${TARGETS[5]} $( $SOURCES $)")
+ env.Depends(b, "$SCONS_PROC_PY")
+
+ env.Local(b)
+
+ #
+ # Each document will live in its own subdirectory. List them here
+ # as hash keys, with a hash of the info to control its build.
+ #
+ docs = {
+ 'design' : {
+ 'htmlindex' : 'book1.html',
+ 'ps' : 1,
+ 'pdf' : 1,
+ 'text' : 0,
+ },
+ # This doesn't build on all systems, and the document is old
+ # enough that there's reallyno need to build it every time any
+ # more, so just comment it out for now.
+ #'python10' : {
+ # 'htmlindex' : 't1.html',
+ # 'html' : 1,
+ # 'ps' : 1,
+ # 'pdf' : 0,
+ # 'text' : 0,
+ # 'graphics' : [
+ # 'arch.fig',
+ # 'builder.fig',
+ # 'job-task.fig',
+ # 'node.fig',
+ # 'scanner.fig',
+ # 'sig.fig'
+ # ],
+ #},
+ 'reference' : {
+ 'htmlindex' : 'book1.html',
+ 'html' : 1,
+ 'ps' : 1,
+ 'pdf' : 1,
+ 'text' : 0,
+ },
+ # For whenever (if ever?) we start putting developer guide
+ # information in a printable document instead of the wiki.
+ #'developer' : {
+ # 'htmlindex' : 'book1.html',
+ # 'html' : 1,
+ # 'ps' : 1,
+ # 'pdf' : 1,
+ # 'text' : 0,
+ #},
+ 'user' : {
+ 'htmlindex' : 'book1.html',
+ 'html' : 1,
+ 'ps' : 1,
+ 'pdf' : 1,
+ 'text' : 1,
+ 'graphics' : [
+ 'SCons-win32-install-1.jpg',
+ 'SCons-win32-install-2.jpg',
+ 'SCons-win32-install-3.jpg',
+ 'SCons-win32-install-4.jpg',
+ ],
+ 'sconsoutput' : 1,
+ },
+ }
+
+ #
+ # We have to tell SCons to scan the top-level XML files which
+ # get included by the document XML files in the subdirectories.
+ #
+ manifest = File('MANIFEST').rstr()
+ src_files = map(lambda x: x[:-1], open(manifest).readlines())
+ for s in src_files:
+ base, ext = os.path.splitext(s)
+ if ext in ['.fig', '.jpg']:
+ orig_env.Install(build, s)
+ else:
+ orig_env.SCons_revision(os.path.join(build, s), s)
+ Local(os.path.join(build, s))
+
+ #
+ # For each document, build the document itself in HTML, Postscript,
+ # and PDF formats.
+ #
+ for doc in docs.keys():
+ manifest = File(os.path.join(doc, 'MANIFEST')).rstr()
+ src_files = map(lambda x: x[:-1],
+ open(manifest).readlines())
+ build_doc = docs[doc].get('sconsoutput') and int(ARGUMENTS.get('BUILDDOC', 0))
+ for s in src_files:
+ doc_s = os.path.join(doc, s)
+ build_s = os.path.join(build, doc, s)
+ base, ext = os.path.splitext(doc_s)
+ if ext in ['.fig', '.jpg']:
+ orig_env.InstallAs(build_s, doc_s)
+ else:
+ if build_doc and ext == '.xml':
+ env.Command(doc_s,
+ base + '.in',
+ "$PYTHON $SCONSOUTPUT_PY $SOURCE > $TARGET")
+ orig_env.SCons_revision(build_s, doc_s)
+ Local(build_s)
+
+ main = os.path.join(build, doc, 'main.xml')
+ out = 'main.out'
+
+ # 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_dir, 'scons-src', 'doc', main)
+ env.Ignore(scons_src_main, version_xml)
+
+ htmldir = os.path.join(build, 'HTML', 'scons-%s' % doc)
+ htmlindex = os.path.join(htmldir, docs[doc]['htmlindex'])
+ 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:
+ def copy_index_html(target, source, env):
+ # Older versions of DocBook|jw|jade|whatever would
+ # create a book1.html file, while newer versions create
+ # an index.html file (logically enough). The scons.org
+ # web site links expect book1.html, so we're going to
+ # leave the target as is, and run this post-processing
+ # action function to check that the target really did
+ # get created, and if it didn't, copy it from index.html.
+ t = str(target[0])
+ if not os.path.exists(t):
+ i = os.path.join(os.path.split(t)[0], 'index.html')
+ open(t, 'w').write(open(i, 'r').read())
+ return None
+
+ cmds = [
+ Delete("${TARGET.dir}/*.html"),
+ "jw -b html -o ${TARGET.dir} $SOURCES",
+ ]
+ if tidy:
+ cmds.append("tidy -m -q $TARGET || true")
+ cmds.append(Action(copy_index_html))
+ env.Command(htmlindex, File(main), cmds)
+ Local(htmlindex)
+
+ cmds = [
+ Delete("${TARGET.dir}/main.html"),
+ "jw -u -b html -o ${TARGET.dir} $SOURCES",
+ Move("$TARGET", "${TARGET.dir}/main.html"),
+ ]
+ if tidy:
+ cmds.append("tidy -m -q $TARGET || true")
+ env.Command(html, File(main), cmds)
+ Local(html)
+
+ env.Ignore([html, htmlindex], version_xml)
+
+ tar_deps.extend([html, htmlindex])
+ tar_list.extend([html, htmldir])
+
+ for g in docs[doc].get('graphics', []):
+ base, ext = os.path.splitext(g)
+ if ext == '.fig':
+ jpg = base + '.jpg'
+ htmldir_jpg = os.path.join(htmldir, jpg)
+ if fig2dev:
+ fig = os.path.join(build, doc, g)
+ env.Command(htmldir_jpg, fig,
+ "%s -L jpeg -q 100 $SOURCES $TARGET" % fig2dev)
+ else:
+ env.InstallAs(htmldir_jpg, jpg)
+ env.Depends(html, htmldir_jpg)
+ Local(htmldir_jpg)
+ else:
+ src = os.path.join(build, doc, g)
+ Local(env.Install(htmldir, src))
+
+ if docs[doc].get('ps') and jadetex and jade_original:
+ env.Command(ps, main, [
+ Delete("${TARGET.dir}/%s" % out),
+ "jw -b ps -o ${TARGET.dir} -p %s $SOURCES" % jade_original,
+ "mv ${TARGET.dir}/main.ps $TARGET",
+ Delete("${TARGET.dir}/%s" % out),
+ ])
+ Local(ps)
+
+ env.Ignore(ps, version_xml)
+
+ tar_deps.append(ps)
+ tar_list.append(ps)
+
+ for g in docs[doc].get('graphics', []):
+ base, ext = os.path.splitext(g)
+ if ext == '.fig':
+ eps = base + '.eps'
+ build_eps = os.path.join(build, 'PS', eps)
+ if fig2dev:
+ fig = os.path.join(build, doc, g)
+ env.Command(build_eps, fig, "%s -L eps $SOURCES $TARGET" % fig2dev)
+ else:
+ env.InstallAs(build_eps, eps)
+ env.Depends(ps, build_eps)
+ Local(build_eps)
+ else:
+ src = os.path.join(build, doc, g)
+ Local(env.Install(htmldir, src))
+
+ if docs[doc].get('pdf') and pdfjadetex and jade_original:
+ env.Command(pdf, main, [
+ Delete("${TARGET.dir}/%s" % out),
+ "jw -b pdf -o ${TARGET.dir} -p %s $SOURCES" % jade_original,
+ "mv ${TARGET.dir}/main.pdf $TARGET",
+ Delete("${TARGET.dir}/out"),
+ ])
+ Local(pdf)
+
+ env.Ignore(pdf, version_xml)
+
+ tar_deps.append(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_xml)
+
+ tar_deps.append(text)
+ tar_list.append(text)
+
+#
+# Man page(s), in good ol' troff format.
+#
+man_page_list = ['scons.1', 'sconsign.1', 'scons-time.1']
+
+for m in man_page_list:
+ x = orig_env.SCons_revision(os.path.join(build, 'man', m),
+ os.path.join('man', m))
+
+man_i_files = ['builders.man', 'tools.man', 'variables.man']
+
+man_intermediate_files = map(lambda x: os.path.join(build, 'man', x),
+ man_i_files)
+
+cmd = "$PYTHON $SCONS_PROC_PY --man -b ${TARGETS[0]} -t ${TARGETS[1]} -v ${TARGETS[2]} $( $SOURCES $)"
+man_intermediate_files = env.Command(man_intermediate_files,
+ scons_doc_files,
+ cmd)
+env.Depends(man_intermediate_files, "$SCONS_PROC_PY")
+Local(man_intermediate_files)
+
+for man_1 in man_page_list:
+ man, _1 = os.path.splitext(man_1)
+
+ man_1 = os.path.join(build, 'man', man_1)
+
+ if groff:
+ ps = os.path.join(build, 'PS', '%s-man.ps' % man)
+ text = os.path.join(build, 'TEXT', '%s-man.txt' % man)
+
+ b = env.Command(ps, man_1, "( cd ${SOURCES.dir} && groff -man -Tps ${SOURCES.file} ) > $TARGET")
+ Local(ps)
+ env.Depends(b, man_intermediate_files)
+
+ b = env.Command(text, man_1, "( cd ${SOURCES.dir} && groff -man -Tascii ${SOURCES.file} ) > $TARGET")
+ Local(text)
+ env.Depends(b, man_intermediate_files)
+
+ tar_deps.extend([ps, text])
+ tar_list.extend([ps, text])
+
+ if man2html:
+ html = os.path.join(build, 'HTML' , '%s-man.html' % man)
+
+ def strip_to_first_html_tag(target, source, env):
+ t = str(target[0])
+ contents = open(t).read()
+ contents = contents[string.find(contents, '<HTML>'):]
+ open(t, 'w').write(contents)
+ return 0
+
+ cmds = [
+ "( cd %s/man && cp %s .. )" % (build, string.join(man_i_files)),
+ "( cd ${SOURCE.dir} && man2html ${SOURCE.file} ) > $TARGET",
+ Action(strip_to_first_html_tag),
+ ]
+ if tidy:
+ cmds.append("tidy -m -q $TARGET || true")
+ b = env.Command(html, man_1, cmds)
+ Local(html)
+ env.Depends(b, man_intermediate_files)
+
+ tar_deps.append(html)
+ tar_list.append(html)
+
+if not epydoc:
+ print "epydoc not found, skipping building API documentation."
+else:
+ # XXX Should be in common with reading the same thing in
+ # the SConstruct file.
+ e = os.path.join('#src', 'engine')
+ manifest_in = File(os.path.join(e, 'MANIFEST.in')).rstr()
+ sources = map(lambda x: x[:-1], open(manifest_in).readlines())
+ sources = filter(lambda x: string.find(x, 'Optik') == -1, sources)
+ sources = filter(lambda x: string.find(x, 'Platform') == -1, sources)
+ sources = filter(lambda x: string.find(x, 'Tool') == -1, sources)
+ # XXX
+ sources = filter(lambda x: string.find(x, 'Options') == -1, sources)
+
+ e = os.path.join(build, '..', 'scons', 'engine')
+ sources = map(lambda x, e=e: os.path.join(e, x), sources)
+
+ epydoc_commands = [
+ Delete('$OUTDIR'),
+ '$EPYDOC $EPYDOCFLAGS --debug --output $OUTDIR --docformat=restructuredText --name SCons --url http://www.scons.org/ $SOURCES',
+ Touch('$TARGET'),
+ ]
+
+ htmldir = os.path.join(build, 'HTML', 'scons-api')
+ env.Command('${OUTDIR}/index.html', sources, epydoc_commands,
+ EPYDOC=epydoc, EPYDOCFLAGS='--html', OUTDIR=htmldir)
+ tar_deps.append(htmldir)
+ tar_list.append(htmldir)
+
+ # PDF and PostScript and TeX are built from the
+ # same invocation.
+ api_dir = os.path.join(build, 'scons-api')
+ api_pdf = os.path.join(api_dir, 'api.pdf')
+ api_ps = os.path.join(api_dir, 'api.ps')
+ api_tex = os.path.join(api_dir, 'api.tex')
+ api_targets = [api_pdf, api_ps, api_tex]
+ env.Command(api_targets, sources, epydoc_commands,
+ EPYDOC=epydoc, EPYDOCFLAGS='--pdf', OUTDIR=api_dir)
+ Local(api_targets)
+
+ pdf_install = os.path.join(build, 'PDF', 'scons-api.pdf')
+ env.InstallAs(pdf_install, api_pdf)
+ tar_deps.append(pdf_install)
+ tar_list.append(pdf_install)
+ Local(pdf_install)
+
+ ps_install = os.path.join(build, 'PS', 'scons-api.ps')
+ env.InstallAs(ps_install, api_ps)
+ tar_deps.append(ps_install)
+ tar_list.append(ps_install)
+ Local(ps_install)
+
+#
+# Now actually create the tar file of the documentation,
+# for easy distribution to the web site.
+#
+if tar_deps:
+ tar_list = string.join(map(lambda x, b=build+'/': string.replace(x, b, ''),
+ tar_list))
+ t = env.Command(dist_doc_tar_gz, tar_deps,
+ "tar cf${TAR_HFLAG} - -C %s %s | gzip > $TARGET" % (build, tar_list))
+ AddPostAction(dist_doc_tar_gz, Chmod(dist_doc_tar_gz, 0644))
+ Local(t)
+ Alias('doc', t)
+else:
+ Alias('doc', os.path.join(build_dir, 'doc'))
diff --git a/doc/design/MANIFEST b/doc/design/MANIFEST
new file mode 100644
index 0000000..33ab8f0
--- /dev/null
+++ b/doc/design/MANIFEST
@@ -0,0 +1,14 @@
+acks.xml
+bground.xml
+copyright.xml
+engine.fig
+engine.jpg
+engine.xml
+goals.xml
+install.xml
+intro.xml
+issues.xml
+main.xml
+native.xml
+overview.xml
+scons.mod
diff --git a/doc/design/acks.xml b/doc/design/acks.xml
new file mode 100644
index 0000000..b1a8a58
--- /dev/null
+++ b/doc/design/acks.xml
@@ -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.
+
+-->
+
+ <para>
+
+ I'm grateful to the following people
+ for their influence, knowing or not,
+ on the design of &SCons;:
+
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Bob Sidebotham</term>
+ <listitem>
+ <para>
+
+ First, as the original author of &Cons;, Bob did the real heavy
+ lifting of creating the underlying model for dependency management
+ and software construction, as well as implementing it in Perl.
+ During the first years of &Cons;' existence, Bob did a skillful
+ job of integrating input and code from the first users, and
+ consequently is a source of practical wisdom and insight into the
+ problems of real-world software construction. His continuing
+ advice has been invaluable.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>The &SCons; Development Team</term>
+ <listitem>
+ <para>
+
+ A big round of thanks go to those brave souls who have
+ gotten in on the ground floor:
+ David Abrahams,
+ Charles Crain,
+ Steven Leblanc.
+ Anthony Roach,
+ and
+ Steven Shaw.
+ Their contributions,
+ through their general knowledge of software build issues in general
+ Python in particular,
+ have made &SCons; what it is today.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>The &Cons; Community</term>
+ <listitem>
+ <para>
+
+ The real-world build problems that the users of &Cons;
+ share on the <command>cons-discuss</command> mailing list
+ have informed much of the thinking that
+ has gone into the &SCons; design.
+ In particular,
+ Rajesh Vaidheeswarran,
+ the current maintainer of &Cons;,
+ has been a very steady influence.
+ I've also picked up valuable insight from
+ mailing-list participants
+ Johan Holmberg,
+ Damien Neil,
+ Gary Oberbrunner,
+ Wayne Scott,
+ and Greg Spencer.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Peter Miller</term>
+ <listitem>
+
+ <para>
+
+ Peter has indirectly
+ influenced two aspects of the &SCons; design:
+
+ </para>
+
+ <para>
+
+ Miller's influential paper
+ <citetitle>Recursive Make Considered Harmful</citetitle>
+ was what led me, indirectly, to my involvement with &Cons;
+ in the first place.
+ Experimenting with the single-Makefile approach he describes in
+ <citetitle>RMCH</citetitle> led me to conclude that while it worked
+ as advertised, it was not an extensible scheme. This solidified
+ my frustration with Make and led me to try &Cons;, which at its
+ core shares the single-process, universal-DAG model of the "RMCH"
+ single-Makefile technique.
+
+ </para>
+
+ <para>
+
+ The testing framework that Miller created for his
+ Aegis change management system
+ changed the way I approach software development
+ by providing a framework for rigorous, repeatable
+ testing during development.
+ It was my success at using Aegis for personal projects
+ that led me to begin my involvement with &Cons;
+ by creating the <command>cons-test</command> regression suite.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Stuart Stanley</term>
+ <listitem>
+ <para>
+
+ An experienced Python programmer,
+ Stuart provided valuable advice and insight
+ into some of the more useful Python idioms at my disposal
+ during the original <literal>ScCons</literal>; design
+ for the Software Carpentry contest.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Gary Holt</term>
+ <listitem>
+ <para>
+
+ I don't know which came first,
+ the first-round Software Carpentry contest entry
+ or the tool itself,
+ but Gary's design for &Makepp;
+ showed me that it is possible to marry
+ the strengths of &Cons;-like dependency management
+ with backwards compatibility for &Makefile;s.
+ Striving to support both
+ &Makefile; compatibility and
+ a native Python interface
+ cleaned up the &SCons; design immeasurably
+ by factoring out the common elements
+ into the Build Engine.
+
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
diff --git a/doc/design/bground.xml b/doc/design/bground.xml
new file mode 100644
index 0000000..c404e86
--- /dev/null
+++ b/doc/design/bground.xml
@@ -0,0 +1,86 @@
+<!--
+
+ 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>
+
+ Most of the ideas in &SCons; originate with &Cons;, a Perl-based
+ software construction utility that has been in use by a small but
+ growing community since its development by Bob Sidebotham at FORE
+ Systems in 1996. The &Cons; copyright was transferred in 2000 from
+ Marconi (who purchased FORE Systems) to the Free Software Foundation.
+ I've been a principal implementer and maintainer of &Cons; for several
+ years.
+
+ </para>
+
+ <para>
+
+ &Cons; was originally designed to handle complicated software build
+ problems (multiple directories, variant builds) while keeping the
+ input files simple and maintainable. The general philosophy is that
+ the build tool should ``do the right thing'' with minimal input
+ from an unsophisticated user, while still providing a rich set of
+ underlying functionality for more complicated software construction
+ tasks needed by experts.
+
+ </para>
+
+ <para>
+
+ In 2000, the Software Carpentry sought entries in a contest for a
+ new, Python-based build tool that would provide an improvement
+ over Make for physical scientists and other non-programmers
+ struggling to use their computers more effectively. Prior to that,
+ the idea of combining the superior build architecture of &Cons;
+ with the easier syntax of Python had come up several times on
+ the <literal>cons-discuss</literal> mailing list. The Software
+ Carpentry contest provided the right motivation to spend some
+ actual time working on a design document.
+
+ </para>
+
+ <para>
+
+ After two rounds of competition, the submitted design, named
+ <application>ScCons</application>, won the competition. Software
+ Carpentry, however, did not immediately fund implementation of the
+ build tool, instead contracting for additional, more detailed draft(s)
+ of the design document. This proved to be not as strong motivation as
+ actual coding, and after several months of inactivity, I essentially
+ resigned from the Software Carpentry effort in early 2001 to start
+ working on the tool independently.
+
+ </para>
+
+ <para>
+
+ After half a year of prototyping some of the important infrastructure,
+ I accumulated enough code to take the project public at SourceForge,
+ renaming it &SCons; to distinguish it slightly from the version of the
+ design that won the Software Carpentry contest while still honoring
+ its roots there and in the original &Cons; utility. And also because
+ it would be a teensy bit easier to type.
+
+ </para>
diff --git a/doc/design/copyright.xml b/doc/design/copyright.xml
new file mode 100644
index 0000000..d73906e
--- /dev/null
+++ b/doc/design/copyright.xml
@@ -0,0 +1,39 @@
+<!--
+
+ 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>
+
+ Copyright (c) 2001 Steven Knight
+
+ Portions of this document, by the same author, were previously
+ published Copyright 2000 by CodeSourcery LLC, under the Software Carpentry
+ Open Publication License, the terms of which are available at
+ <ulink url="http://www.software-carpentry.com/openpub-license.html">
+ http://www.software-carpentry.com/openpub-license.html
+ </ulink>.
+
+ </para>
+</blockquote>
diff --git a/doc/design/engine.fig b/doc/design/engine.fig
new file mode 100644
index 0000000..90f3d4f
--- /dev/null
+++ b/doc/design/engine.fig
@@ -0,0 +1,179 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 2100 8700 3600 9300
+2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5
+ 2100 8700 3600 8700 3600 9300 2100 9300 2100 8700
+4 0 0 100 0 18 14 0.0000 4 165 900 2400 9075 Node.FS\001
+-6
+6 7050 6900 9000 7500
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 7050 6900 9000 6900 9000 7500 7050 7500 7050 6900
+4 0 0 100 0 18 14 0.0000 4 165 1530 7200 7275 Intercessor.FS\001
+-6
+6 9450 6900 11400 7500
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 9450 6900 11400 6900 11400 7500 9450 7500 9450 6900
+4 0 0 100 0 18 14 0.0000 4 165 1560 9600 7275 Intercessor.DB\001
+-6
+6 1200 4200 2400 4800
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 1200 4200 2400 4200 2400 4800 1200 4800 1200 4200
+4 0 0 100 0 18 14 0.0000 4 165 870 1350 4575 Scanner\001
+-6
+6 2400 3300 3600 3900
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 2400 3300 3600 3300 3600 3900 2400 3900 2400 3300
+4 0 0 100 0 18 14 0.0000 4 165 750 2625 3675 Builder\001
+-6
+6 8700 1650 10500 2250
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 8700 1650 10500 1650 10500 2250 8700 2250 8700 1650
+4 0 0 100 0 18 14 0.0000 4 165 1185 9000 2025 Intercessor\001
+-6
+6 1500 1650 3300 2250
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 1500 1650 3300 1650 3300 2250 1500 2250 1500 1650
+4 0 0 100 0 18 14 0.0000 4 165 1320 1725 2025 Environment\001
+-6
+6 7800 8700 9300 9300
+2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5
+ 7800 8700 9300 8700 9300 9300 7800 9300 7800 8700
+4 0 0 100 0 18 14 0.0000 4 165 930 8100 9075 Node.DB\001
+-6
+6 1500 10200 2400 10800
+2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5
+ 1500 10200 2400 10200 2400 10800 1500 10800 1500 10200
+4 0 0 100 0 18 14 0.0000 4 165 315 1800 10575 Dir\001
+-6
+6 3300 10200 4200 10800
+2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5
+ 3300 10200 4200 10200 4200 10800 3300 10800 3300 10200
+4 0 0 100 0 18 14 0.0000 4 165 375 3600 10575 File\001
+-6
+6 6000 10200 7200 10800
+2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5
+ 6000 10200 7200 10200 7200 10800 6000 10800 6000 10200
+4 0 0 100 0 18 14 0.0000 4 165 555 6300 10575 Table\001
+-6
+6 7800 10200 9300 10800
+2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5
+ 7800 10200 9300 10200 9300 10800 7800 10800 7800 10200
+4 0 0 100 0 18 14 0.0000 4 165 765 8100 10575 Record\001
+-6
+6 9900 10200 11100 10800
+2 2 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5
+ 9900 10200 11100 10200 11100 10800 9900 10800 9900 10200
+4 0 0 100 0 18 14 0.0000 4 165 510 10200 10575 Field\001
+-6
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 6900 5250 6825 5175 6900 5100 6975 5175 6900 5250
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 6300 5250 6225 5175 6300 5100 6375 5175 6300 5250
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 5700 5250 5625 5175 5700 5100 5775 5175 5700 5250
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 4800 2700 7200 2700 7200 5100 4800 5100 4800 2700
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4
+ 5100 5100 5025 5250 5175 5250 5100 5100
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 5
+ 0 0 1.00 60.00 120.00
+ 6300 5250 6300 5700 8400 5700 8400 4200 7200 4200
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 5
+ 0 0 1.00 60.00 120.00
+ 5700 5250 5700 6000 9000 6000 9000 3600 7200 3600
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 5100 5250 5100 8100
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 4725 3675 4650 3600 4725 3525 4800 3600 4725 3675
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 4725 4575 4650 4500 4725 4425 4800 4500 4725 4575
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 4650 3600 3600 3600
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 4650 4500 2400 4500
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 1800 2400 1800 4200
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 3000 2400 3000 3300
+2 1 1 1 0 7 100 0 -1 4.000 0 0 7 0 0 2
+ 5850 1950 5850 2700
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 3000 2400 2925 2325 3000 2250 3075 2325 3000 2400
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 1800 2400 1725 2325 1800 2250 1875 2325 1800 2400
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 3300 1950 8700 1950
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 9600 2400 9600 6600
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4
+ 7950 6900 7950 6600 10350 6600 10350 6900
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4
+ 9600 2250 9525 2400 9675 2400 9600 2250
+2 1 0 1 0 7 100 0 -1 4.000 0 0 7 0 0 2
+ 4800 3000 7200 3000
+2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2
+ 4800 3300 7200 3300
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4
+ 2850 9300 2775 9450 2925 9450 2850 9300
+2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 4
+ 2100 10200 2100 9900 3750 9900 3750 10200
+2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 5
+ 6600 10200 6600 9900 10500 9900 10500 10200 10500 10125
+2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2
+ 2850 9450 2850 9900
+2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2
+ 8475 9450 8475 10200
+2 3 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 4
+ 8475 9300 8400 9450 8550 9450 8475 9300
+2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 1
+ 2775 6825
+2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 3
+ 0 0 1.00 60.00 120.00
+ 1800 10200 1800 9000 2100 9000
+2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 9900 10500 9300 10500
+2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 7800 10500 7200 10500
+2 1 0 1 0 7 100 0 -1 4.000 0 0 7 0 0 4
+ 2850 8700 2850 8100 8550 8100 8550 8700
+2 1 1 1 0 7 100 0 -1 4.000 0 0 -1 1 0 3
+ 0 0 1.00 60.00 120.00
+ 10350 7500 10350 9000 9300 9000
+2 1 1 1 0 7 100 0 -1 4.000 0 0 -1 1 0 3
+ 0 0 1.00 60.00 120.00
+ 7050 7200 2400 7200 2400 8700
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 5
+ 0 0 1.00 60.00 120.00
+ 6900 5250 6900 5400 7800 5400 7800 4800 7200 4800
+4 0 0 100 0 18 14 0.0000 4 165 555 4950 2925 Node\001
+4 0 0 100 0 16 10 0.0000 4 150 825 7350 3525 dependency\001
+4 0 0 100 0 16 10 0.0000 4 45 60 7425 3825 *\001
+4 0 0 100 0 16 10 0.0000 4 120 555 7350 4125 srcnode\001
+4 0 0 100 0 16 10 0.0000 4 120 90 7425 4425 1\001
+4 0 0 100 0 16 10 0.0000 4 150 570 7350 4725 repnode\001
+4 0 0 100 0 16 10 0.0000 4 120 90 7425 5025 1\001
+4 0 0 100 0 16 10 0.0000 4 120 270 2550 4725 0..1\001
+4 0 0 100 0 16 10 0.0000 4 120 270 3750 3825 0..1\001
+4 0 0 100 0 0 12 0.0000 4 75 90 1875 4050 *\001
+4 0 0 100 0 0 12 0.0000 4 75 90 3075 3150 *\001
+4 0 0 100 0 16 14 0.0000 4 210 600 5100 3750 build()\001
+4 0 0 100 0 16 14 0.0000 4 210 630 5100 4260 scan()\001
+4 0 0 100 0 0 12 0.0000 4 135 90 9750 10725 1\001
+4 0 0 100 0 16 10 0.0000 4 120 90 1650 10125 1\001
+4 0 0 100 0 16 10 0.0000 4 45 60 1875 9225 *\001
+4 0 0 100 0 16 10 0.0000 4 120 90 7650 10725 1\001
+4 0 0 100 0 16 10 0.0000 4 45 60 7275 10725 *\001
+4 0 0 100 0 16 10 0.0000 4 45 60 9375 10725 *\001
diff --git a/doc/design/engine.jpg b/doc/design/engine.jpg
new file mode 100644
index 0000000..2e82232
--- /dev/null
+++ b/doc/design/engine.jpg
Binary files differ
diff --git a/doc/design/engine.xml b/doc/design/engine.xml
new file mode 100644
index 0000000..1a1e335
--- /dev/null
+++ b/doc/design/engine.xml
@@ -0,0 +1,1964 @@
+<!--
+
+ 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.
+
+-->
+
+<section id="sect-principles">
+ <title>General Principles</title>
+
+ <section>
+ <title>Keyword arguments</title>
+
+ <para>
+
+ All methods and functions in this API will support the use of keyword
+ arguments in calls, for the sake of explicitness and readability.
+ For brevity in the hands of experts, most methods and functions
+ will also support positional arguments for their most-commonly-used
+ arguments. As an explicit example, the following two lines will each
+ arrange for an executable program named <filename>foo</filename> (or
+ <filename>foo.exe</filename> on a Win32 system) to be compiled from
+ the <filename>foo.c</filename> source file:
+
+ </para>
+
+ <programlisting>
+ env.Program(target = 'foo', source = 'foo.c')
+
+ env.Program('foo', 'foo.c')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Internal object representation</title>
+
+ <para>
+
+ All methods and functions use internal (Python) objects that
+ represent the external objects (files, for example) for which they
+ perform dependency analysis.
+
+ </para>
+
+ <para>
+
+ All methods and functions in this API that accept an external object
+ as an argument will accept <emphasis>either</emphasis> a string
+ description or an object reference. For example, the two following
+ two-line examples are equivalent:
+
+ </para>
+
+ <programlisting>
+ env.Object(target = 'foo.o', source = 'foo.c')
+ env.Program(target = 'foo', 'foo.o') # builds foo from foo.o
+
+ foo_obj = env.Object(target = 'foo.o', source = 'foo.c')
+ env.Program(target = 'foo', foo_obj) # builds foo from foo.o
+ </programlisting>
+
+ </section>
+
+</section>
+
+
+
+<section id="sect-envs">
+ <title>&ConsEnvs</title>
+
+ <para>
+
+ A &consenv; is the basic means by which a software system interacts
+ with the &SCons; Python API to control a build process.
+
+ </para>
+
+ <para>
+
+ A &consenv; is an object with associated methods for generating target
+ files of various types (&Builder; objects), other associated object
+ methods for automatically determining dependencies from the contents
+ of various types of source files (&Scanner; objects), and a dictionary
+ of values used by these methods.
+
+ </para>
+
+ <para>
+
+ Passing no arguments to the &Environment; instantiation creates a
+ &consenv; with default values for the current platform:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <section>
+ <title>&Consvars;</title>
+
+ <para>
+
+ A &consenv; has an associated dictionary of &consvars; that control how
+ the build is performed. By default, the &Environment; method creates
+ a &consenv; with values that make most software build "out of the box"
+ on the host system. These default values will be generated at the
+ time &SCons; is installed using functionality similar to that provided
+ by GNU &Autoconf;.
+ <footnote>
+ <para>
+ It would be nice if we could avoid re-inventing the wheel here by
+ using some other Python-based tool &Autoconf replacement--like what
+ was supposed to come out of the Software Carpentry configuration
+ tool contest. It will probably be most efficient to roll our own
+ logic initially and convert if something better does come along.
+ </para>
+ </footnote>
+ At a minimum, there will be pre-configured sets of default values
+ that will provide reasonable defaults for UNIX and Windows NT.
+
+ </para>
+
+ <para>
+
+ The default &consenv; values may be overridden when a new &consenv; is
+ created by specifying keyword arguments:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CC = 'gcc',
+ CCFLAGS = '-g',
+ CPPPATH = ['.', 'src', '/usr/include'],
+ LIBPATH = ['/usr/lib', '.'])
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Fetching &consvars;</title>
+
+ <para>
+
+ A copy of the dictionary of &consvars; can be returned using
+ the &Dictionary; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ dict = env.Dictionary()
+ </programlisting>
+
+ <para>
+
+ If any arguments are supplied, then just the corresponding value(s)
+ are returned:
+
+ </para>
+
+ <programlisting>
+ ccflags = env.Dictionary('CCFLAGS')
+ cc, ld = env.Dictionary('CC', 'LD')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Copying a &consenv;</title>
+
+ <para>
+
+ A method exists to return a copy of an existing environment, with
+ any overridden values specified as keyword arguments to the method:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ debug = env.Copy(CCFLAGS = '-g')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Multiple &consenvs;</title>
+
+ <para>
+
+ Different external objects often require different build
+ characteristics. Multiple &consenvs; may be defined, each with
+ different values:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CCFLAGS = '')
+ debug = Environment(CCFLAGS = '-g')
+ env.Make(target = 'hello', source = 'hello.c')
+ debug.Make(target = 'hello-debug', source = 'hello.c')
+ </programlisting>
+
+ <para>
+
+ Dictionaries of values from multiple &consenvs; may be passed to the
+ &Environment; instantiation or the &Copy; method, in which case the
+ last-specified dictionary value wins:
+
+ </para>
+
+ <programlisting>
+ env1 = Environment(CCFLAGS = '-O', LDFLAGS = '-d')
+ env2 = Environment(CCFLAGS = '-g')
+ new = Environment(env1.Dictionary(), env2.Dictionary())
+ </programlisting>
+
+ <para>
+
+ The <varname>new</varname> environment in the above example retains
+ <literal>LDFLAGS = '-d'</literal> from the <varname>env1</varname>
+ environment, and <literal>CCFLAGS = '-g'</literal> from the
+ <varname>env2</varname> environment.
+
+ </para>
+
+ <!--
+
+ hardware details
+ current directory
+ OS environment variables
+ compilers and options,
+ aliases for commands,
+ versions of tools
+
+ environment overrides a la Cons
+
+ compilation options
+
+ cross compilation via selection of tool+options
+
+ paths for header files (specify alternate path)
+
+ accomodate smart compilers that can tell you
+ "I know how to turn .c or .ccp into .o",
+ "I know how to turn .f into .o"
+
+ -->
+
+ </section>
+
+ <section>
+ <title>Variable substitution</title>
+
+ <para>
+
+ Within a construction command, any variable from the &consenv; may
+ be interpolated by prefixing the name of the construction with
+ <symbol>$</symbol>:
+
+ </para>
+
+ <programlisting>
+ MyBuilder = Builder(command = "$XX $XXFLAGS -c $_INPUTS -o $target")
+
+ env.Command(targets = 'bar.out', sources = 'bar.in',
+ command = "sed '1d' < $source > $target")
+ </programlisting>
+
+ <para>
+
+ Variable substitution is recursive: the command line is expanded
+ until no more substitutions can be made.
+
+ </para>
+
+ <para>
+
+ Variable names following the <symbol>$</symbol> may be enclosed in
+ braces. This can be used to concatenate an interpolated value with an
+ alphanumeric character:
+
+ </para>
+
+ <programlisting>
+ VerboseBuilder = Builder(command = "$XX -${XXFLAGS}v > $target")
+ </programlisting>
+
+ <para>
+
+ The variable within braces may contain a pair of parentheses
+ after a Python function name to be evaluated (for example,
+ <literal>${map()}</literal>). &SCons; will interpolate the return
+ value from the function (presumably a string):
+
+ </para>
+
+ <programlisting>
+ env = Environment(FUNC = myfunc)
+ env.Command(target = 'foo.out', source = 'foo.in',
+ command = "${FUNC($<)}")
+ </programlisting>
+
+ <para>
+
+ If a referenced variable is not defined in the &consenv;,
+ the null string is interpolated.
+
+ </para>
+
+ <para>
+
+ The following special variables can also be used:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><literal>$targets</literal></term>
+ <listitem>
+ <para>
+
+ All target file names. If multiple targets are specified in an
+ array, <literal>$targets</literal> expands to the entire list of
+ targets, separated by a single space.
+
+ </para>
+
+ <para>
+
+ Individual targets from a list may be extracted by enclosing
+ the <literal>targets</literal> keyword in braces and using the
+ appropriate Python array index or slice:
+
+ </para>
+
+ <programlisting>
+ ${targets[0]} # expands to the first target
+
+ ${targets[1:]} # expands to all but the first target
+
+ ${targets[1:-1]} # expands to all but the first and last targets
+ </programlisting>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>$target</literal></term>
+ <listitem>
+ <para>
+
+ A synonym for <literal>${targets[0]}</literal>, the first target
+ specified.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>$sources</literal></term>
+ <listitem>
+ <para>
+
+ All input file names. Any input file names that
+ are used anywhere else on the current command
+ line (via <literal>${sources[0]}</literal>,
+ <literal>${sources{[1]}</literal>, etc.) are removed from the
+ expanded list.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ Any of the above special variables may be enclosed in braces and
+ followed immediately by one of the following attributes to select just
+ a portion of the expanded path name:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><literal>.base</literal></term>
+ <listitem>
+ <para>
+
+ Basename: the directory plus the file name, minus any file suffix.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>.dir</literal></term>
+ <listitem>
+ <para>
+
+ The directory in which the file lives. This is a relative path,
+ where appropriate.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>.file</literal></term>
+ <listitem>
+ <para>
+
+ The file name, minus any directory portion.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>.suffix</literal></term>
+ <listitem>
+ <para>
+
+ The file name suffix (that is, the right-most dot in the file name,
+ and all characters to the right of that).
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>.filebase</literal></term>
+ <listitem>
+ <para>
+
+ The file name (no directory portion), minus any file suffix.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>.abspath</literal></term>
+ <listitem>
+ <para>
+
+ The absolute path to the file.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </section>
+
+</section>
+
+
+
+<section id="sect-builders">
+ <title>&Builder; Objects</title>
+
+ <para>
+
+ By default, &SCons; supplies (and uses) a number of pre-defined
+ &Builder; objects:
+
+ </para>
+
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+
+ <row>
+ <entry>&Object;</entry>
+ <entry>compile or assemble an object file</entry>
+ </row>
+
+ <row>
+ <entry>&Library;</entry>
+ <entry>archive files into a library</entry>
+ </row>
+
+ <row>
+ <entry>&SharedLibrary;</entry>
+ <entry>archive files into a shared library</entry>
+ </row>
+
+ <row>
+ <entry>&Program;</entry>
+ <entry>link objects and/or libraries into an executable</entry>
+ </row>
+
+ <row>
+ <entry>&MakeBuilder;</entry>
+ <entry>build according to file suffixes; see below</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+<!--
+&Library; and &SharedLibrary; have nearly identical
+semantics, just different
+tools and &consenvs (paths, etc.) that they use.
+In other words, you can construct a shared library
+using just the &Library; &Builder; object
+with a different environment.
+I think that's a better way to do it.
+Feedback?
+-->
+
+ <para>
+
+ A &consenv; can be explicitly initialized with associated &Builder;
+ objects that will be bound to the &consenv; object:
+
+ </para>
+
+ <programlisting>
+ env = Environment(BUILDERS = ['Object', 'Program'])
+ </programlisting>
+
+ <para>
+
+ &Builder; objects bound to a &consenv; can be called directly as
+ methods. When invoked, a &Builder; object returns a (list of) objects
+ that it will build:
+
+ </para>
+
+ <programlisting>
+ obj = env.Object(target ='hello.o', source = 'hello.c')
+ lib = env.Library(target ='libfoo.a',
+ source = ['aaa.c', 'bbb.c'])
+ slib = env.SharedLibrary(target ='libbar.so',
+ source = ['xxx.c', 'yyy.c'])
+ prog = env.Program(target ='hello',
+ source = ['hello.o', 'libfoo.a', 'libbar.so'])
+ </programlisting>
+
+ <section>
+ <title>Specifying multiple inputs</title>
+
+ <para>
+
+ Multiple input files that go into creating a target file may be passed
+ in as a single string, with the individual file names separated by
+ white space:
+
+ </para>
+
+ <programlisting>
+ env.Library(target = 'foo.a', source = 'aaa.c bbb.c ccc.c')
+ env.Object(target = 'yyy.o', source = 'yyy.c')
+ env.Program(target = 'bar', source = 'xxx.c yyy.o foo.a')
+ </programlisting>
+
+ <para>
+
+ Alternatively, multiple input files that go into creating a target
+ file may be passed in as an array. This allows input files to be
+ specified using their object representation:
+
+ </para>
+
+ <programlisting>
+ env.Library(target = 'foo.a', source = ['aaa.c', 'bbb.c', 'ccc.c'])
+ yyy_obj = env.Object(target = 'yyy.o', source = 'yyy.c')
+ env.Program(target = 'bar', source = ['xxx.c', yyy_obj, 'foo.a'])
+ </programlisting>
+
+ <para>
+
+ Individual string elements within an array of input files are
+ <emphasis>not</emphasis> further split into white-space separated
+ file names. This allows file names that contain white space to
+ be specified by putting the value into an array:
+
+ <programlisting>
+ env.Program(target = 'foo', source = ['an input file.c'])
+ </programlisting>
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Specifying multiple targets</title>
+
+ <para>
+
+ Conversely, the generated target may be a string listing multiple
+ files separated by white space:
+
+ </para>
+
+ <programlisting>
+ env.Object(target = 'grammar.o y.tab.h', source = 'grammar.y')
+ </programlisting>
+
+ <para>
+
+ An array of multiple target files can be used to mix string and object
+ representations, or to accomodate file names that contain white space:
+
+ </para>
+
+ <programlisting>
+ env.Program(target = ['my program'], source = 'input.c')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>File prefixes and suffixes</title>
+
+ <para>
+
+ For portability, if the target file name does not already have an
+ appropriate file prefix or suffix, the &Builder; objects will
+ append one appropriate for the file type on the current system:
+
+ </para>
+
+ <programlisting>
+ # builds 'hello.o' on UNIX, 'hello.obj' on Windows NT:
+ obj = env.Object(target ='hello', source = 'hello.c')
+
+ # builds 'libfoo.a' on UNIX, 'foo.lib' on Windows NT:
+ lib = env.Library(target ='foo', source = ['aaa.c', 'bbb.c'])
+
+ # builds 'libbar.so' on UNIX, 'bar.dll' on Windows NT:
+ slib = env.SharedLibrary(target ='bar', source = ['xxx.c', 'yyy.c'])
+
+ # builds 'hello' on UNIX, 'hello.exe' on Windows NT:
+ prog = env.Program(target ='hello',
+ source = ['hello.o', 'libfoo.a', 'libbar.so'])
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>&Builder; object exceptions</title>
+
+ <para>
+
+ &Builder; objects raise the following exceptions on error:
+
+ <!--
+ LIST THESE ONCE WE FIGURE OUT WHAT THEY ARE FROM CODING THEM.
+ -->
+
+ </para>
+ </section>
+
+ <section>
+ <title>User-defined &Builder; objects</title>
+
+ <para>
+
+ Users can define additional &Builder; objects for specific external
+ object types unknown to &SCons;. A &Builder; object may build its
+ target by executing an external command:
+
+ </para>
+
+ <programlisting>
+ WebPage = Builder(command = 'htmlgen $HTMLGENFLAGS $sources > $target',
+ suffix = '.html',
+ src_suffix = '.in')
+ </programlisting>
+
+ <para>
+
+ Alternatively, a &Builder; object may also build its target by
+ executing a Python function:
+
+ </para>
+
+ <programlisting>
+ def update(dest):
+ # [code to update the object]
+ return 1
+
+ OtherBuilder1 = Builder(function = update,
+ src_suffix = ['.in', '.input'])
+ </programlisting>
+
+ <para>
+
+ An optional argument to pass to the function may be specified:
+
+ </para>
+
+ <programlisting>
+ def update_arg(dest, arg):
+ # [code to update the object]
+ return 1
+
+ OtherBuilder2 = Builder(function = update_arg,
+ function_arg = 'xyzzy',
+ src_suffix = ['.in', '.input'])
+ </programlisting>
+
+ <para>
+
+ Both an external command and an internal function may be specified,
+ in which case the function will be called to build the object first,
+ followed by the command line.
+
+ </para>
+
+ <!--
+ NEED AN EXAMPLE HERE.
+ -->
+
+ <para>
+
+ User-defined &Builder; objects can be used like the default &Builder;
+ objects to initialize &consenvs;.
+
+ </para>
+
+ <programlisting>
+ WebPage = Builder(command = 'htmlgen $HTMLGENFLAGS $sources > $target',
+ suffix = '.html',
+ src_suffix = '.in')
+ env = Environment(BUILDERS = ['WebPage'])
+ env.WebPage(target = 'foo.html', source = 'foo.in')
+ # Builds 'bar.html' on UNIX, 'bar.htm' on Windows NT:
+ env.WebPage(target = 'bar', source = 'bar.in')
+ </programlisting>
+
+ <para>
+
+ The command-line specification can interpolate variables from the
+ &consenv;; see "Variable substitution," above.
+
+ </para>
+
+ <para>
+
+ A &Builder; object may optionally be initialized with a list of:
+
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+
+ the prefix of the target file (e.g., 'lib' for libraries)
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ the suffix of the target file (e.g., '.a' for libraries)
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ the expected suffixes of the input files
+ (e.g., '.o' for object files)
+
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+
+ These arguments are used in automatic
+ dependency analysis and to generate output file names that don't
+ have suffixes supplied explicitly.
+
+ </para>
+ </section>
+
+ <section>
+ <title>Copying &Builder; Objects</title>
+
+ <para>
+
+ A &Copy; method exists to return a copy of an existing &Builder;
+ object, with any overridden values specified as keyword arguments to
+ the method:
+
+ </para>
+
+ <programlisting>
+ build = Builder(function = my_build)
+ build_out = build.Copy(suffix = '.out')
+ </programlisting>
+
+ <para>
+
+ Typically, &Builder; objects will be supplied by a tool-master or
+ administrator through a shared &consenv;.
+
+ </para>
+ </section>
+
+ <section>
+ <title>Special-purpose build rules</title>
+
+ <para>
+
+ A pre-defined &Command; builder exists to associate a target file with
+ a specific command or list of commands for building the file:
+
+ </para>
+
+ <programlisting>
+ env.Command(target = 'foo.out', source =
+ command = 'foo.in', "foo.process $sources > $target")
+
+ commands = [ "bar.process -o .tmpfile $sources",
+ "mv .tmpfile $target" ]
+ env.Command(target = 'bar.out', source = 'bar.in', command = commands)
+ </programlisting>
+
+ <para>
+ This is useful when it's too cumbersome to create a &Builder;
+ object just to build a single file in a special way.
+
+ </para>
+ </section>
+
+ <section>
+ <title>The &MakeBuilder; &Builder;</title>
+
+ <para>
+
+ A pre-defined &Builder; object named &MakeBuilder; exists to make
+ simple builds as easy as possible for users, at the expense of
+ sacrificing some build portability.
+
+ </para>
+
+ <para>
+
+ The following minimal example builds the 'hello' program from the
+ 'hello.c' source file:
+
+ </para>
+
+ <programlisting>
+ Environment().Make('hello', 'hello.c')
+ </programlisting>
+
+ <para>
+
+ Users of the &MakeBuilder; &Builder; object are not required to
+ understand intermediate steps involved in generating a file--for
+ example, the distinction between compiling source code into an object
+ file, and then linking object files into an executable. The details
+ of intermediate steps are handled by the invoked method. Users that
+ need to, however, can specify intermediate steps explicitly:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Make(target = 'hello.o', source = 'hello.c')
+ env.Make(target = 'hello', source = 'hello.o')
+ </programlisting>
+
+ <para>
+
+ The &MakeBuilder; method understands the file suffixes specified and
+ "does the right thing" to generate the target object and program
+ files, respectively. It does this by examining the specified output
+ suffixes for the &Builder; objects bound to the environment.
+
+ </para>
+
+ <para>
+
+ Because file name suffixes in the target and source file names
+ must be specified, the &MakeBuilder; method can't be used
+ portably across operating systems. In other words, for the
+ example above, the &MakeBuilder; builder will not generate
+ <filename>hello.exe</filename> on Windows NT.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>&Builder; maps</title>
+
+<!--
+Do we even need this anymore?
+Now that the individual builders
+have specified <literal>suffix</literal>
+and <literal>src_suffix</literal> values,
+all of the information we need to support
+the &MakeBuilder; builder is right there in the environment.
+I think this is a holdover from before I
+added the <literal>suffix</literal> arguments.
+If you want &MakeBuilder; to do something different,
+you set it up with another environment...
+-->
+
+ <para>
+
+ The <function>env.Make</function> method "does the right thing" to
+ build different file types because it uses a dictionary from the
+ &consenv; that maps file suffixes to the appropriate &Builder; object.
+ This &BUILDERMAP; can be initialized at instantiation:
+
+ </para>
+
+ <programlisting>
+ env = Environment(BUILDERMAP = {
+ '.o' : Object,
+ '.a' : Library,
+ '.html' : WebPage,
+ '' : Program,
+ })
+ </programlisting>
+
+ <para>
+
+ With the &BUILDERMAP; properly initialized, the
+ <function>env.Make</function> method can be used to build additional
+ file types:
+
+ </para>
+
+ <programlisting>
+ env.Make(target = 'index.html', source = 'index.input')
+ </programlisting>
+
+ <para>
+
+ &Builder; objects referenced in the &BUILDERMAP; do not need to be
+ listed separately in the &BUILDERS; variable. The &consenv; will
+ bind the union of the &Builder; objects listed in both variables.
+
+ </para>
+
+ <!--
+
+ YYY support scanners which detect files which haven't been generated yet
+
+ -->
+
+ </section>
+
+</section>
+
+
+
+<section id="sect-deps">
+ <title>Dependencies</title>
+
+ <section>
+ <title>Automatic dependencies</title>
+
+ <para>
+
+ By default, &SCons; assumes that a target file has <literal>automatic
+ dependencies</literal> on the:
+
+ </para>
+
+ <blockquote>
+ <simplelist>
+
+ <member>tool used to build the target file</member>
+
+ <member>contents of the input files</member>
+
+ <member>command line used to build the target file</member>
+
+ </simplelist>
+ </blockquote>
+
+ <para>
+
+ If any of these changes, the target file will be rebuilt.
+
+ </para>
+ </section>
+
+ <section>
+ <title>Implicit dependencies</title>
+
+ <para>
+
+ Additionally, &SCons; can scan the contents of files for
+ <literal>implicit dependencies</literal> on other files. For
+ example, &SCons; will scan the contents of a <filename>.c</filename>
+ file and determine that any object created from it is
+ dependent on any <filename>.h</filename> files specified via
+ <literal>#include</literal>. &SCons;, therefore, "does the right
+ thing" without needing to have these dependencies listed explicitly:
+
+ </para>
+
+ <programlisting>
+ % cat Construct
+ env = Environment()
+ env.Program('hello', 'hello.c')
+ % cat hello.c
+ #include "hello_string.h"
+ main()
+ {
+ printf("%s\n", STRING);
+ }
+ % cat > hello_string.h
+ #define STRING "Hello, world!\n"
+ % scons .
+ gcc -c hello.c -o hello.o
+ gcc -o hello hello.c
+ % ./hello
+ Hello, world!
+ % cat > hello_string.h
+ #define STRING "Hello, world, hello!\n"
+ % scons .
+ gcc -c hello.c -o hello.o
+ gcc -o hello hello.c
+ % ./hello
+ Hello, world, hello!
+ %
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Ignoring dependencies</title>
+
+ <para>
+
+ Undesirable <literal>automatic dependencies</literal> or
+ <literal>implicit dependencies</literal> may be ignored:
+
+ </para>
+
+ <programlisting>
+ env.Program(target = 'bar', source = 'bar.c')
+ env.Ignore('bar', '/usr/bin/gcc', 'version.h')
+ </programlisting>
+
+ <para>
+
+ In the above example, the <filename>bar</filename> program will not
+ be rebuilt if the <filename>/usr/bin/gcc</filename> compiler or the
+ <filename>version.h</filename> file change.
+
+ </para>
+ </section>
+
+ <section>
+ <title>Explicit dependencies</title>
+
+ <para>
+
+ Dependencies that are unknown to &SCons; may be specified explicitly
+ in an &SCons; configuration file:
+
+ </para>
+
+ <programlisting>
+ env.Dependency(target = 'output1', dependency = 'input_1 input_2')
+ env.Dependency(target = 'output2', dependency = ['input_1', 'input_2'])
+ env.Dependency(target = 'output3', dependency = ['white space input'])
+
+ env.Dependency(target = 'output_a output_b', dependency = 'input_3')
+ env.Dependency(target = ['output_c', 'output_d'], dependency = 'input_4')
+ env.Dependency(target = ['white space output'], dependency = 'input_5')
+ </programlisting>
+
+ <para>
+
+ Just like the <literal>target</literal> keyword argument, the
+ <literal>dependency</literal> keyword argument may be specified as a
+ string of white-space separated file names, or as an array.
+
+ </para>
+
+ <para>
+
+ A dependency on an &SCons; configuration file itself may be specified
+ explicitly to force a rebuild whenever the configuration file changes:
+
+ </para>
+
+ <programlisting>
+ env.Dependency(target = 'archive.tar.gz', dependency = 'SConstruct')
+ </programlisting>
+
+ </section>
+
+</section>
+
+
+
+<section id="sect-scanners">
+ <title>&Scanner; Objects</title>
+
+ <para>
+
+ Analagous to the previously-described &Builder; objects, &SCons;
+ supplies (and uses) &Scanner; objects to search the contents of
+ a file for implicit dependency files:
+
+ </para>
+
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+
+ <row>
+ <entry>CScan</entry>
+ <entry>scan .{c,C,cc,cxx,cpp} files for #include dependencies</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>
+
+ A &consenv; can be explicitly initialized with
+ associated &Scanner; objects:
+
+ </para>
+
+ <programlisting>
+ env = Environment(SCANNERS = ['CScan', 'M4Scan'])
+ </programlisting>
+
+ <para>
+
+ &Scanner; objects bound to a &consenv; can be
+ associated directly with specified files:
+
+ </para>
+
+ <programlisting>
+ env.CScan('foo.c', 'bar.c')
+ env.M4Scan('input.m4')
+ </programlisting>
+
+ <section>
+ <title>User-defined &Scanner; objects</title>
+
+ <para>
+
+ A user may define a &Scanner; object to scan a type of file for
+ implicit dependencies:
+
+ </para>
+
+ <programlisting>
+ def scanner1(file_contents):
+ # search for dependencies
+ return dependency_list
+
+ FirstScan = Scanner(function = scanner1)
+ </programlisting>
+
+ <para>
+
+ The scanner function must return a list of dependencies that its finds
+ based on analyzing the file contents it is passed as an argument.
+
+ </para>
+
+ <para>
+
+ The scanner function, when invoked, will be passed the calling
+ environment. The scanner function can use &consenvs; from the passed
+ environment to affect how it performs its dependency scan--the
+ canonical example being to use some sort of search-path construction
+ variable to look for dependency files in other directories:
+
+ </para>
+
+ <programlisting>
+ def scanner2(file_contents, env):
+ path = env.{'SCANNERPATH'} # XXX
+ # search for dependencies using 'path'
+ return dependency_list
+
+ SecondScan = Scanner(function = scanner2)
+ </programlisting>
+
+ <para>
+
+ The user may specify an additional argument when the &Scanner; object
+ is created. When the scanner is invoked, the additional argument
+ will be passed to the scanner funciton, which can be used in any way
+ the scanner function sees fit:
+
+ </para>
+
+ <programlisting>
+ def scanner3(file_contents, env, arg):
+ # skip 'arg' lines, then search for dependencies
+ return dependency_list
+
+ Skip_3_Lines_Scan = Scanner(function = scanner2, argument = 3)
+ Skip_6_Lines_Scan = Scanner(function = scanner2, argument = 6)
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Copying &Scanner; Objects</title>
+
+ <para>
+
+ A method exists to return a copy of an existing &Scanner; object,
+ with any overridden values specified as keyword arguments to the
+ method:
+
+ </para>
+
+ <programlisting>
+ scan = Scanner(function = my_scan)
+ scan_path = scan.Copy(path = '%SCANNERPATH')
+ </programlisting>
+
+ <para>
+
+ Typically, &Scanner; objects will be supplied by a tool-master or
+ administrator through a shared &consenv;.
+
+ </para>
+ </section>
+
+ <section>
+ <title>&Scanner; maps</title>
+
+<!--
+If the &BUILDERMAP; proves unnecessary,
+we could/should get rid of this one, too,
+by adding a parallel <literal>src_suffix</literal>
+argument to the &Scanner; factory...
+Comments?
+-->
+
+ <para>
+
+ Each &consenv; has a &SCANNERMAP;, a dictionary that associates
+ different file suffixes with a scanner object that can be used to
+ generate a list of dependencies from the contents of that file. This
+ &SCANNERMAP; can be initialized at instantiation:
+
+ </para>
+
+ <programlisting>
+ env = Environment(SCANNERMAP = {
+ '.c' : CScan,
+ '.cc' : CScan,
+ '.m4' : M4Scan,
+ })
+ </programlisting>
+
+ <para>
+
+ &Scanner; objects referenced in the &SCANNERMAP; do not need to
+ be listed separately in the &SCANNERS; variable. The &consenv;
+ will bind the union of the &Scanner; objects listed
+ in both variables.
+
+ </para>
+
+ </section>
+
+</section>
+
+
+
+<section id="sect-targets">
+ <title>Targets</title>
+
+ <para>
+
+ The methods in the build engine API described so far merely
+ establish associations that describe file dependencies, how a
+ file should be scanned, etc. Since the real point is to actually
+ <emphasis>build</emphasis> files, &SCons; also has methods that
+ actually direct the build engine to build, or otherwise manipulate,
+ target files.
+
+ </para>
+
+ <section>
+ <title>Building targets</title>
+ <para>
+
+ One or more targets may be built as follows:
+
+ </para>
+
+ <programlisting>
+ env.Build(target = ['foo', 'bar'])
+ </programlisting>
+
+ <para>
+
+ Note that specifying a directory (or other collective object) will
+ cause all subsidiary/dependent objects to be built as well:
+
+ </para>
+
+ <programlisting>
+ env.Build(target = '.')
+
+ env.Build(target = 'builddir')
+ </programlisting>
+
+ <para>
+
+ By default, &SCons; explicitly removes a target file before
+ invoking the underlying function or command(s) to build it.
+
+ </para>
+ </section>
+
+ <section>
+ <title>Removing targets</title>
+
+ <para>
+
+ A "cleanup" operation of removing generated (target) files is
+ performed as follows:
+
+ </para>
+
+ <programlisting>
+ env.Clean(target = ['foo', 'bar'])
+ </programlisting>
+
+ <para>
+
+ Like the &Build; method, the &Clean; method may be passed a
+ directory or other collective object, in which case the subsidiary
+ target objects under the directory will be removed:
+
+ </para>
+
+ <programlisting>
+ env.Clean(target = '.')
+
+ env.Clean(target = 'builddir')
+ </programlisting>
+
+ <para>
+
+ (The directories themselves are not removed.)
+
+ </para>
+ </section>
+
+ <section>
+ <title>Suppressing cleanup removal of build-targets</title>
+
+ <para>
+
+ By default, &SCons; explicitly removes all build-targets
+ when invoked to perform "cleanup". Files that should not be
+ removed during "cleanup" can be specified via the
+ &NoClean; method:
+
+ </para>
+
+ <programlisting>
+ env.Library(target = 'libfoo.a', source = ['aaa.c', 'bbb.c', 'ccc.c'])
+ env.NoClean('libfoo.a')
+ </programlisting>
+
+ <para>
+
+ The NoClean operation has precedence over the Clean operation.
+ A target that is specified as both Clean and NoClean, will not
+ be removed during a clean.
+
+ In the following example, target 'foo' will not be removed
+ during "cleanup":
+
+ <programlisting>
+ env.Clean(target = 'foo')
+ env.NoClean('foo')
+ </programlisting>
+
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Suppressing build-target removal</title>
+
+ <para>
+
+ As mentioned, by default, &SCons; explicitly removes a target
+ file before invoking the underlying function or command(s) to build
+ it. Files that should not be removed before rebuilding can be
+ specified via the &Precious; method:
+
+ </para>
+
+ <programlisting>
+ env.Library(target = 'libfoo.a', source = ['aaa.c', 'bbb.c', 'ccc.c'])
+ env.Precious('libfoo.a')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Default targets</title>
+
+ <para>
+
+ The user may specify default targets that will be built if there are no
+ targets supplied on the command line:
+
+ </para>
+
+ <programlisting>
+ env.Default('install', 'src')
+ </programlisting>
+
+ <para>
+
+ Multiple calls to the &Default; method (typically one per &SConscript;
+ file) append their arguments to the list of default targets.
+
+ </para>
+ </section>
+
+ <section>
+ <title>File installation</title>
+
+ <para>
+
+ Files may be installed in a destination directory:
+
+ </para>
+
+ <programlisting>
+ env.Install('/usr/bin', 'program1', 'program2')
+ </programlisting>
+
+ <para>
+
+ Files may be renamed on installation:
+
+ </para>
+
+ <programlisting>
+ env.InstallAs('/usr/bin/xyzzy', 'xyzzy.in')
+ </programlisting>
+
+ <para>
+
+ Multiple files may be renamed on installation by specifying
+ equal-length lists of target and source files:
+
+ </para>
+
+ <programlisting>
+ env.InstallAs(['/usr/bin/foo', '/usr/bin/bar'],
+ ['foo.in', 'bar.in'])
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Target aliases</title>
+
+ <para>
+
+ In order to provide convenient "shortcut" target names that expand to
+ a specified list of targets, aliases may be established:
+
+ </para>
+
+ <programlisting>
+ env.Alias(alias = 'install',
+ targets = ['/sbin', '/usr/lib', '/usr/share/man'])
+ </programlisting>
+
+ <para>
+
+ In this example, specifying a target of <literal>install</literal>
+ will cause all the files in the associated directories to be built
+ (that is, installed).
+
+ </para>
+
+ <para>
+
+ An &Alias; may include one or more other &Aliases; in its list:
+
+ </para>
+
+ <programlisting>
+ env.Alias(alias = 'libraries', targets = ['lib'])
+ env.Alias(alias = 'programs', targets = ['libraries', 'src'])
+ </programlisting>
+
+ </section>
+
+</section>
+
+
+
+<section id="sect-custom">
+ <title>Customizing output</title>
+
+<!--
+Take this whole section with a grain of salt.
+I whipped it up without a great deal of thought
+to try to add a "competitive advantage"
+for the second round of the Software Carpentry contest.
+In particular, hard-coding the
+analysis points and the keywords that specify them
+feels inflexible,
+but I can't think of another way it would be
+done effectively.
+I dunno, maybe this is fine as it is...
+-->
+
+ <para>
+
+ The &SCons; API supports the ability to customize, redirect, or
+ suppress its printed output through user-defined functions.
+ &SCons; has several pre-defined points in its build process at
+ which it calls a function to (potentially) print output. User-defined
+ functions can be specified for these call-back points when &Build;
+ or &Clean;is invoked:
+
+ </para>
+
+ <programlisting>
+ env.Build(target = '.',
+ on_analysis = dump_dependency,
+ pre_update = my_print_command,
+ post_update = my_error_handler)
+ on_error = my_error_handler)
+ </programlisting>
+
+ <para>
+
+ The specific call-back points are:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><literal>on_analysis</literal></term>
+ <listitem>
+ <para>
+
+ Called for every object, immediately after the object has been
+ analyzed to see if it's out-of-date. Typically used to print a
+ trace of considered objects for debugging of unexpected dependencies.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>pre_update</literal></term>
+ <listitem>
+ <para>
+
+ Called for every object that has been determined to be out-of-date
+ before its update function or command is executed. Typically used
+ to print the command being called to update a target.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>post_update</literal></term>
+ <listitem>
+ <para>
+
+ Called for every object after its update function or command has
+ been executed. Typically used to report that a top-level specified
+ target is up-to-date or was not remade.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>on_error</literal></term>
+ <listitem>
+ <para>
+
+ Called for every error returned by an update function or command.
+ Typically used to report errors with some string that will be
+ identifiable to build-analysis tools.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ Functions for each of these call-back points all take the same
+ arguments:
+
+ </para>
+
+ <programlisting>
+ my_dump_dependency(target, level, status, update, dependencies)
+ </programlisting>
+
+ <para>
+
+ where the arguments are:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><literal>target</literal></term>
+ <listitem>
+ <para>
+
+ The target object being considered.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>level</literal></term>
+ <listitem>
+ <para>
+
+ Specifies how many levels the dependency analysis has
+ recursed in order to consider the <literal>target</literal>.
+ A value of <literal>0</literal> specifies a top-level
+ <literal>target</literal> (that is, one passed to the
+ &Build; or &Clean; method). Objects which a top-level
+ <literal>target</literal> is directly dependent upon have a
+ <literal>level</literal> of <1>, their direct dependencies have a
+ <literal>level</literal> of <2>, etc. Typically used to indent
+ output to reflect the recursive levels.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>status</literal></term>
+ <listitem>
+ <para>
+
+ A string specifying the current status of the target
+ (<literal>"unknown"</literal>, <literal>"built"</literal>,
+ <literal>"error"</literal>, <literal>"analyzed"</literal>, etc.). A
+ complete list will be enumerated and described during implementation.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>update</literal></term>
+ <listitem>
+ <para>
+
+ The command line or function name that will be (or has been) executed
+ to update the <literal>target</literal>.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>dependencies</literal></term>
+ <listitem>
+ <para>
+
+ A list of direct dependencies of the target.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+</section>
+
+
+
+<section id="separate">
+ <title>Separate source and build trees</title>
+
+<!--
+I've never liked Cons' use of the name <literal>Link</literal>
+for this functionality,
+mainly because the term is overloaded
+with linking object files into an executable.
+Yet I've never come up with anything better.
+Any suggestions?
+-->
+
+<!--
+Also, I made this an &Environment; method because
+it logically belongs in the API reference
+(the build engine needs to know about it),
+and I thought it was clean to have
+everything in the build-engine API
+be called through an &Environment; object.
+But <literal>&Link</literal> isn't really
+associated with a specific environment
+(the &Cons; classic implementation just
+leaves it as a bare function call),
+so maybe we should just follow that example
+and not call it through an environment...
+-->
+
+ <para>
+
+ &SCons; allows target files to be built completely separately from
+ the source files by "linking" a build directory to an underlying
+ source directory:
+
+ </para>
+
+ <programlisting>
+ env.Link('build', 'src')
+
+ SConscript('build/SConscript')
+ </programlisting>
+
+ <para>
+
+ &SCons; will copy (or hard link) necessary files (including the
+ &SConscript; file) into the build directory hierarchy. This allows the
+ source directory to remain uncluttered by derived files.
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-variant">
+ <title>Variant builds</title>
+
+ <para>
+
+ The &Link; method may be used in conjunction with multiple
+ &consenvs; to support variant builds. The following
+ &SConstruct; and &SConscript; files would build separate debug and
+ production versions of the same program side-by-side:
+
+ </para>
+
+ <programlisting>
+ % cat SConstruct
+ env = Environment()
+ env.Link('build/debug', 'src')
+ env.Link('build/production', 'src')
+ flags = '-g'
+ SConscript('build/debug/SConscript', Export(env))
+ flags = '-O'
+ SConscript('build/production/SConscript', Export(env))
+ % cat src/SConscript
+ env = Environment(CCFLAGS = flags)
+ env.Program('hello', 'hello.c')
+ </programlisting>
+
+ <para>
+
+ The following example would build the appropriate program for the current
+ compilation platform, without having to clean any directories of object
+ or executable files for other architectures:
+
+ </para>
+
+ <programlisting>
+ % cat SConstruct
+ build_platform = os.path.join('build', sys.platform)
+ Link(build_platform, 'src')
+ SConscript(os.path.join(build_platform, 'SConscript'))
+ % cat src/SConscript
+ env = Environment
+ env.Program('hello', 'hello.c')
+ </programlisting>
+
+</section>
+
+
+
+<section id="sect-repositories">
+ <title>Code repositories</title>
+
+<!--
+Like &Link;, &Repository; and &Local; are part of the
+API reference, but not really tied to any specific environment.
+Is it better to be consistent about calling
+everything in the API through an environment,
+or to leave these independent so as
+not to complicate their calling interface?
+-->
+
+ <para>
+
+ &SCons; may use files from one or more shared code repositories in order
+ to build local copies of changed target files. A repository would
+ typically be a central directory tree, maintained by an integrator,
+ with known good libraries and executables.
+
+ </para>
+
+ <programlisting>
+ Repository('/home/source/1.1', '/home/source/1.0')
+ </programlisting>
+
+ <para>
+
+ Specified repositories will be searched in-order for any file
+ (configuration file, input file, target file) that does not exist
+ in the local directory tree. When building a local target file,
+ &SCons; will rewrite path names in the build command to use the
+ necessary repository files. This includes modifying lists of
+ <option>-I</option> or <option>-L</option> flags to specify an
+ appropriate set of include paths for dependency analysis.
+
+ </para>
+ <para>
+
+ &SCons; will modify the Python <varname>sys.path</varname> variable to
+ reflect the addition of repositories to the search path, so that any
+ imported modules or packages necessary for the build can be found in a
+ repository, as well.
+
+ </para>
+ <para>
+
+ If an up-to-date target file is found in a code repository, the file
+ will not be rebuilt or copied locally. Files that must exist locally
+ (for example, to run tests) may be specified:
+
+ </para>
+
+ <programlisting>
+ Local('program', 'libfoo.a')
+ </programlisting>
+
+ <para>
+
+ in which case &SCons; will copy or link an up-to-date copy of the
+ file from the appropriate repository.
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-caching">
+ <title>Derived-file caching</title>
+
+<!--
+There should be extensions to this part of the API for
+auxiliary functions like cleaning the cache.
+-->
+
+ <para>
+
+ &SCons; can maintain a cache directory of target files which may be
+ shared among multiple builds. This reduces build times by allowing
+ developers working on a project together to share common target
+ files:
+
+ </para>
+
+ <programlisting>
+ Cache('/var/tmp/build.cache/i386')
+ </programlisting>
+
+ <para>
+
+ When a target file is generated, a copy is added to the cache.
+ When generating a target file, if &SCons; determines that a file
+ that has been built with the exact same dependencies already exists
+ in the specified cache, &SCons; will copy the cached file rather
+ than re-building the target.
+
+ </para>
+ <para>
+
+ Command-line options exist to modify the &SCons; caching behavior
+ for a specific build, including disabling caching, building
+ dependencies in random order, and displaying commands as if cached
+ files were built.
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-jobs">
+ <title>Job management</title>
+
+<!--
+This has been completely superseded by
+the more sophisticated &Task; manager
+that Anthony Roach has contributed.
+I need to write that up...
+-->
+
+ <para>
+
+ A simple API exists to inform the Build Engine how many jobs may
+ be run simultaneously:
+
+ </para>
+
+ <programlisting>
+ Jobs(limit = 4)
+ </programlisting>
+
+</section>
diff --git a/doc/design/goals.xml b/doc/design/goals.xml
new file mode 100644
index 0000000..2a7b69b
--- /dev/null
+++ b/doc/design/goals.xml
@@ -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.
+
+-->
+
+ <para>
+
+ As a next-generation build tool,
+ &SCons should fundamentally
+ improve on its predecessors.
+ Rather than simply being driven by trying to
+ <emphasis>not</emphasis> be like previous tools,
+ &SCons; aims to satisfy the following goals:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><literal>Practicality</literal></term>
+ <listitem>
+ <para>
+
+ The &SCons; design emphasizes
+ an implementable feature set
+ that lets users get practical, useful work done.
+ &SCons; is helped in this regard by its roots in &Cons;,
+ which has had its feature set honed by
+ several years of input
+ from a dedicated band of users.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Portability</literal></term>
+ <listitem>
+ <para>
+
+ &SCons; is intended as a portable build tool,
+ able to handle software construction tasks
+ on a variety of operating systems.
+ It should be possible (although not mandatory)
+ to use &SCons; so that the same configuration file
+ builds the same software correctly on,
+ for example, both Linux and Windows NT.
+ Consequently, &SCons; should hide from users
+ operating-system-dependent details
+ such as filename extensions
+ (for example, <filename>.o</filename>
+ vs. <filename>.obj</filename>).
+
+ <!--
+ XXX: enable writing portable builds without forcing it
+ -->
+
+ <!--
+ XXX: still write non-portably for quick-and-dirty
+ -->
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Usability</literal></term>
+ <listitem>
+ <para>
+
+ Novice users should be able to grasp quickly
+ the rudiments of using &SCons; to build their software.
+ This extends to installing &SCons;, too.
+ Installation should be painless,
+ and the installed &SCons;
+ should work "out of the box"
+ to build most software.
+
+ </para>
+
+ <para>
+
+ This goal should be kept in mind during implementation,
+ when there is always a tendency to try to optimize too early.
+ Speed is nice, but not as important as clarity
+ and ease of use.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Utility</literal></term>
+ <listitem>
+ <para>
+
+ &SCons; should also provide a rich enough set of features
+ to accommodate building more complicated software projects.
+ However, the features required for
+ building complicated software projects
+ should not get in the way of novice users.
+ (See the previous goal.)
+ In other words, complexity should be available
+ when it's needed
+ but not required to get work done.
+ Practically, this implies that &SCons;
+ shouldn't be dumbed down to the point it
+ excludes complicated software builds.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Sharability</literal></term>
+ <listitem>
+ <para>
+
+ As a key element in balancing the conflicting
+ needs of <literal>Usability</literal> and <literal>Utility</literal>,
+ &SCons; should provide mechanisms to
+ allow &SCons; users to share build rules,
+ dependency scanners, and other objects and recipes
+ for constructing software.
+ A good sharing mechanism should support
+ the model wherein most developers on a project
+ use rules and templates
+ that are created
+ and maintained by a local integrator or build-master,
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Extensibility</literal></term>
+ <listitem>
+ <para>
+
+ &SCons; should provide mechanisms for
+ easily extending its capabilities,
+ including building new types of files,
+ adding new types of dependency scanning,
+ being able to accomodate dependencies
+ between objects other than files,
+ etc.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Flexibility</literal></term>
+ <listitem>
+ <para>
+
+ In addition to providing a useful command-line interface,
+ &SCons; should provide the right architectural
+ framework for embedding its dependency management
+ in other interfaces.
+ &SCons; would help strengthen other GUIs or IDEs
+ and the additional requirements of the
+ other interfaces would help broaden and solidify
+ the core &SCons; dependency management.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+<section id="sect-fix-make">
+ <title>Fixing &Make;'s problems</title>
+
+ <para>
+
+<!--
+To be written.
+-->
+
+ </para>
+
+</section>
+
+<section id="sect-fix-cons">
+ <title>Fixing &Cons;'s problems</title>
+
+ <para>
+
+<!--
+To be written.
+-->
+
+ </para>
+
+</section>
diff --git a/doc/design/install.xml b/doc/design/install.xml
new file mode 100644
index 0000000..e670e83
--- /dev/null
+++ b/doc/design/install.xml
@@ -0,0 +1,28 @@
+<!--
+
+ 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.
+
+-->
+
+<!--
+THIS CHAPTER NEEDS TO BE DISCUSSED AND WRITTEN.
+-->
diff --git a/doc/design/intro.xml b/doc/design/intro.xml
new file mode 100644
index 0000000..561baa4
--- /dev/null
+++ b/doc/design/intro.xml
@@ -0,0 +1,111 @@
+<!--
+
+ 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>
+
+ The &SCons; tool provides an easy-to-use, feature-rich interface
+ for constructing software. Architecturally, &SCons; separates
+ its dependency analysis and external object management into an
+ interface-independent Build Engine that could be embedded in any
+ software system that can run Python.
+
+ </para>
+
+ <para>
+
+ At the command line, &SCons; presents an easily-grasped tool
+ where configuration files are Python scripts, reducing the need
+ to learn new build-tool syntax. Inexperienced users can use
+ intelligent methods that ``do the right thing'' to build software
+ with a minimum of fuss. Sophisticated users can use a rich set
+ of underlying features for finer control of the build process,
+ including mechanisms for easily extending the build process to new
+ file types.
+
+ </para>
+
+ <para>
+
+ Dependencies are tracked using digital signatures,
+ which provide more robust dependency analysis than file time
+ stamps. Implicit dependencies are determined automatically by
+ scanning the contents of source files, avoiding the need for
+ laborious and fragile maintenance of static lists of dependencies in
+ configuration files.
+
+ </para>
+
+ <para>
+
+ The &SCons; tool supports use of files from one or more central code
+ repositories, a mechanism for caching derived files, and parallel
+ builds. The tool also includes a framework for sharing build
+ environments, which allows system administrators or integrators to
+ define appropriate build parameters for use by other users.
+
+ </para>
+
+<section id="sect-document">
+ <title>About This Document</title>
+
+ <para>
+
+ This document is an ongoing work-in-progress to write down the ideas
+ and tradeoffs that have gone, and will go into, the &SCons; design.
+ As such, this is intended primarily for use by developers and others
+ working on &SCons;, although it is also intended to serve as a
+ detailed overview of &SCons; for other interested parties. It will
+ be continually updated and evolve, and will likely overlap with other
+ documentation produced by the project. Sections of this document
+ that deal with syntax, for example, may move or be copied into a user
+ guide or reference manual.
+
+ </para>
+
+ <para>
+
+ So please don't assume that everything mentioned here has been
+ decided and carved in stone. If you have ideas for improvements, or
+ questions about things that don't seem to make any sense, please help
+ improve the design by speaking up about them.
+
+ </para>
+
+<!--
+Sections marked like this
+(prefixed with <literal>RATIONALE:</literal> in the HTML,
+surrounded by <literal>BEGIN RATIONALE:</literal>
+and <literal>END RATIONALE:</literal>
+in the printed documentatio)
+are DocBook REMARKs,
+comments about the document
+rather than actual document.
+I've used these to mark sections that need work,
+but also to cite some open design issues.
+If you have input on any of these marked issues,
+I'm especially eager to hear it.
+-->
+
+</section>
diff --git a/doc/design/issues.xml b/doc/design/issues.xml
new file mode 100644
index 0000000..1f9a78c
--- /dev/null
+++ b/doc/design/issues.xml
@@ -0,0 +1,195 @@
+<!--
+
+ 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>
+
+ No build tools is perfect.
+ Here are some &SCons; issues that
+ do not yet have solutions.
+
+ </para>
+
+ <section>
+ <title>Interaction with SC-config</title>
+
+ <para>
+
+ The SC-config tool will be used in the &SCons; installation
+ process to generate an appropriate default construction environment
+ so that building most software works "out of the box" on the
+ installed platform. The SC-config tool will find reasonable default
+ compilers (C, C++, Fortran), linkers/loaders, library archive tools,
+ etc. for specification in the default &SCons; construction
+ environment.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Interaction with test infrastructures</title>
+
+ <para>
+
+ &SCons; can be configured to use SC-test (or some other test tool)
+ to provide controlled, automated testing of software. The &Link;
+ method could link a <filename>test</filename> subdirectory to a build
+ subdirectory:
+
+ </para>
+
+ <programlisting>
+ Link('test', 'build')
+ SConscript('test/SConscript')</programlisting>
+
+ <para>
+
+ Any test cases checked in with the source code will be linked
+ into the <filename>test</filename> subdirectory and executed. If
+ &SConscript; files and test cases are written with this in mind, then
+ invoking:
+
+ </para>
+
+ <programlisting>
+ % sccons test</programlisting>
+
+ <para>
+
+ Would run all the automated test cases that depend on any changed
+ software.
+
+ </para>
+
+
+ <!--
+
+ YYY integrate with SC-test to provide sanity check on new tools
+ "discovery testing" of new tools
+ results recorded in a central database
+ central database can be somewhere else on web
+
+ -->
+
+ </section>
+
+ <section>
+ <title>Java dependencies</title>
+
+ <para>
+
+ Java dependencies are difficult for an external dependency-based
+ construction tool to accomodate. Determining Java class dependencies
+ is more complicated than the simple pattern-matching of C or C++
+ <literal>#include</literal> files. From the point of view of an
+ external build tool, the Java compiler behaves "unpredictably"
+ because it may create or update multiple output class files and
+ directories as a result of its internal class dependencies.
+
+ </para>
+
+ <para>
+
+ An obvious &SCons; implementation would be to have the &Scanner;
+ object parse output from <command>Java -depend -verbose</command> to
+ calculate dependencies, but this has the distinct disadvantage of
+ requiring two separate compiler invocations, thereby slowing down
+ builds.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Limitations of digital signature calculation</title>
+
+ <para>
+
+ In practice, calculating digital signatures of a file's contents is a
+ more robust mechanism than time stamps for determining what needs
+ building. However:
+
+ </para>
+
+ <orderedlist numeration="arabic">
+
+ <listitem>
+ <para>
+
+ Developers used to the time stamp model of &Make; can initially
+ find digital signatures counter-intuitive. The assumption that:
+
+ <programlisting>
+ % touch file.c</programlisting>
+
+ will cause a rebuild of <filename>file</filename> is strong...
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ Abstracting dependency calculation into a single digital signature
+ loses a little information: It is no longer possible to tell
+ (without laborious additional calculation) which input file dependency
+ caused a rebuild of a given target file. A feature that could
+ report, "I'm rebuilding file X because it's out-of-date with respect
+ to file Y," would be good, but an digital-signature implementation of
+ such a feature is non-obvious.
+
+ </para>
+ </listitem>
+
+ </orderedlist>
+
+ </section>
+
+ <section>
+ <title>Remote execution</title>
+
+ <para>
+
+ The ability to use multiple build systems through remote execution
+ of tools would be good. This should be implementable through the
+ &Job; class. Construction environments would need modification
+ to specify build systems.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Conditional builds</title>
+
+ <para>
+
+ The ability to check run-time conditions as suggested on the
+ sc-discuss mailing list ("build X only if: the machine is idle /
+ the file system has Y megabytes free space") would also be good,
+ but is not part of the current design.
+
+ </para>
+
+ </section>
diff --git a/doc/design/main.xml b/doc/design/main.xml
new file mode 100644
index 0000000..e991b36
--- /dev/null
+++ b/doc/design/main.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0"?>
+
+<!--
+
+ Copyright (c) 2001, 2002, 2003 Steven Knight
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+
+ <!--
+ We haven't updated the design document in ages.
+ Rather than fool people into thinking that it's
+ actually up-to-date and reflects the current design,
+ hard-code the version from back when we last updated it.
+ <!ENTITY % version SYSTEM "../version.xml">
+ %version;
+ -->
+ <!ENTITY builddate "2001/12/13 20:55:46">
+ <!ENTITY buildversion "0.91">
+ <!ENTITY buildrevision "0.01.D177">
+
+ <!--
+ Also freeze the scons.mod DTD extensions
+ to what they were way back when.
+ <!ENTITY % scons SYSTEM "../scons.mod">
+ -->
+ <!ENTITY % scons SYSTEM "scons.mod">
+ %scons;
+
+ <!ENTITY acks SYSTEM "acks.xml">
+ <!ENTITY bground SYSTEM "bground.xml">
+ <!ENTITY copyright SYSTEM "copyright.xml">
+ <!ENTITY engine SYSTEM "engine.xml">
+ <!ENTITY goals SYSTEM "goals.xml">
+ <!ENTITY install SYSTEM "install.xml">
+ <!ENTITY intro SYSTEM "intro.xml">
+ <!ENTITY issues SYSTEM "issues.xml">
+ <!ENTITY native SYSTEM "native.xml">
+ <!ENTITY overview SYSTEM "overview.xml">
+
+]>
+
+<book>
+ <bookinfo>
+ <title>SCons Design version &buildversion;</title>
+
+ <author>
+ <firstname>Steven</firstname>
+ <surname>Knight</surname>
+ </author>
+
+ <edition>Revision &buildrevision; (&builddate;)</edition>
+
+ <pubdate>2001</pubdate>
+
+ <copyright>
+ <year>2001</year>
+ <holder>Steven Knight</holder>
+ </copyright>
+
+ <legalnotice>
+ &copyright;
+ </legalnotice>
+
+ <releaseinfo>version &buildversion;</releaseinfo>
+
+ </bookinfo>
+
+ <chapter id="chap-intro">
+ <title>Introduction</title>
+ &intro;
+ </chapter>
+
+ <chapter id="chap-goals">
+ <title>Goals</title>
+ &goals;
+ </chapter>
+
+ <chapter id="chap-overview">
+ <title>Overview</title>
+ &overview;
+ </chapter>
+
+ <chapter id="chap-engine">
+ <title>Build Engine API</title>
+ &engine;
+ </chapter>
+
+ <chapter id="chap-native">
+ <title>Native Python Interface</title>
+ &native;
+ </chapter>
+
+ <!--
+
+ <chapter id="chap-install">
+ <title>Installation</title>
+ &install;
+ </chapter>
+
+ -->
+
+ <chapter id="chap-issues">
+ <title>Other Issues</title>
+ &issues;
+ </chapter>
+
+ <chapter id="chap-background">
+ <title>Background</title>
+ &bground;
+ </chapter>
+
+ <chapter id="chap-summary">
+ <title>Summary</title>
+ <para>
+
+ &SCons; offers a robust and feature-rich design for an SC-build
+ tool. With a Build Engine based on the proven design of
+ the &Cons; utility, it offers increased simplification of the
+ user interface for unsophisticated users with the addition
+ of the "do-the-right-thing" <function>env.Make</function>
+ method, increased flexibility for sophisticated users with the
+ addition of &Builder; and &Scanner; objects, a mechanism to
+ allow tool-masters (and users) to share working construction
+ environments, and embeddability to provide reliable dependency
+ management in a variety of environments and interfaces.
+
+ </para>
+ </chapter>
+
+ <chapter id="chap-acks">
+ <title>Acknowledgements</title>
+ &acks;
+ </chapter>
+
+</book>
diff --git a/doc/design/native.xml b/doc/design/native.xml
new file mode 100644
index 0000000..8cdd867
--- /dev/null
+++ b/doc/design/native.xml
@@ -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.
+
+-->
+
+<para>
+
+ The "Native Python" interface is the interface
+ that the actual &SCons; utility will present to users.
+ Because it exposes the Python Build Engine API,
+ &SCons; users will have direct access to the complete
+ functionality of the Build Engine.
+ In contrast, a different user interface such as a GUI
+ may choose to only use, and present to the end-user,
+ a subset of the Build Engine functionality.
+
+</para>
+
+<section id="sect-config">
+ <title>Configuration files</title>
+
+ <para>
+
+ &SCons; configuration files are simply Python scripts that invoke
+ methods to specify target files to be built, rules for building the
+ target files, and dependencies. Common build rules are available by
+ default and need not be explicitly specified in the configuration
+ files.
+
+ </para>
+
+ <para>
+
+ By default, the &SCons; utility searches for a file named
+ &SConstruct;, &Sconstruct; or &sconstruct (in that order) in the
+ current directory, and reads its configuration from the first file
+ found. A <option>-f</option> command-line option exists to read a
+ different file name.
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-syntax">
+ <title>Python syntax</title>
+
+ <para>
+
+ Because &SCons; configuration files are Python scripts, normal Python
+ syntax can be used to generate or manipulate lists of targets or
+ dependencies:
+
+ </para>
+
+ <programlisting>
+ sources = ['aaa.c', 'bbb.c', 'ccc.c']
+ env.Make('bar', sources)
+ </programlisting>
+
+ <para>
+
+ Python flow-control can be used to iterate through invocations of
+ build rules:
+
+ </para>
+
+ <programlisting>
+ objects = ['aaa.o', 'bbb.o', 'ccc.o']
+ for obj in objects:
+ src = replace(obj, '.o', '.c')
+ env.Make(obj, src)
+ </programlisting>
+
+ <para>
+
+ or to handle more complicated conditional invocations:
+
+ </para>
+
+ <programlisting>
+ # only build 'foo' on Linux systems
+ if sys.platform == 'linux1':
+ env.Make('foo', 'foo.c')
+ </programlisting>
+
+ <para>
+
+ Because &SCons; configuration files are Python scripts, syntax errors
+ will be caught by the Python parser. Target-building does not begin
+ until after all configuration files are read, so a syntax error will
+ not cause a build to fail half-way.
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-subsidiary">
+ <title>Subsidiary configuration Files</title>
+
+ <para>
+
+ A configuration file can instruct &SCons; to read up subsidiary
+ configuration files. Subsidiary files are specified explicitly in a
+ configuration file via the &SConscript; method. As usual, multiple
+ file names may be specified with white space separation, or in an
+ array:
+
+ </para>
+
+ <programlisting>
+ SConscript('other_file')
+ SConscript('file1 file2')
+ SConscript(['file3', 'file4'])
+ SConscript(['file name with white space'])
+ </programlisting>
+
+ <para>
+
+ An explicit <literal>sconscript</literal> keyword may be used:
+
+ </para>
+
+ <programlisting>
+ SConscript(sconscript = 'other_file')
+ </programlisting>
+
+ <para>
+
+ Including subsidiary configuration files is recursive: a configuration
+ file included via &SConscript; may in turn &SConscript; other
+ configuration files.
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-scoping">
+ <title>Variable scoping in subsidiary files</title>
+
+ <para>
+
+ When a subsidiary configuration file is read, it is given its own
+ namespace; it does not have automatic access to variables from the parent
+ configuration file.
+
+ </para>
+
+ <para>
+
+ Any variables (not just &SCons; objects) that are to be shared between configuration files must be
+ explicitly passed in the &SConscript; call
+ using the &Export method:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ debug = Environment(CCFLAGS = '-g')
+ installdir = '/usr/bin'
+ SConscript('src/SConscript', Export(env=env, debug=debug, installdir=installdir))
+ </programlisting>
+
+<!--
+The <literal>env=env</literal> stuff bugs me
+because it imposes extra work on the normal
+case where you <emphasis>don't</emphasis> rename
+the variables.
+Can we simplify the &Export; method
+so that a string
+without a keyword assignment
+is split into variables that are passed
+through transparently?
+Equivalent to the above example:
+<literal>SConscript('src/SConscript', Export('env debug installdir'))</literal>
+-->
+
+ <para>
+
+ Which may be specified explicitly using a keyword argument:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ debug = Environment(CCFLAGS = '-g')
+ installdir = '/usr/bin'
+ SConscript(sconscript = 'src/SConscript',
+ export = Export(env=env, debug=debug, installdir=installdir))
+ </programlisting>
+
+ <para>
+
+ Explicit variable-passing provides control over exactly what is available
+ to a subsidiary file, and avoids unintended side effects of changes in
+ one configuration file affecting other far-removed configuration files
+ (a very hard-to-debug class of build problem).
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-hierarchy">
+ <title>Hierarchical builds</title>
+
+ <para>
+
+ The &SConscript; method is so named because, by convention, subsidiary
+ configuration files in subdirectories are named &SConscript;:
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript')
+ SConscript('lib/build_me')
+ </programlisting>
+
+ <para>
+
+ When a subsidiary configuration file is read from a subdirectory, all
+ of that configuration file's targets and build rules are interpreted
+ relative to that directory (as if &SCons; had changed its working
+ directory to that subdirectory). This allows for easy support of
+ hierarchical builds of directory trees for large projects.
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-sharing">
+ <title>Sharing &consenvs;</title>
+
+ <para>
+
+ &SCons; will allow users to share &consenvs, as well as other &SCons;
+ objects and Python variables, by importing them from a central, shared
+ repository using normal Python syntax:
+
+ </para>
+
+ <programlisting>
+ from LocalEnvironments import optimized, debug
+
+ optimized.Make('foo', 'foo.c')
+ debug.Make('foo-d', 'foo.c')
+ </programlisting>
+
+ <para>
+
+ The expectation is that some local tool-master, integrator or
+ administrator will be responsible for assembling environments (creating
+ the &Builder; objects that specify the tools, options, etc.) and make
+ these available for sharing by all users.
+
+ </para>
+
+ <para>
+
+ The modules containing shared &consenvs;
+ (<literal>LocalEnvironments</literal> in the above example) can be
+ checked in and controlled with the rest of the source files. This
+ allows a project to track the combinations of tools and command-line
+ options that work on different platforms, at different times, and with
+ different tool versions, by using already-familiar revision control
+ tools.
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-help">
+ <title>Help</title>
+
+ <para>
+
+ The &SCons; utility provides a &Help; function to allow the writer
+ of a &SConstruct; file to provide help text that is specific to
+ the local build tree:
+
+ </para>
+
+ <programlisting>
+ Help("""
+ Type:
+ scons . build and test everything
+ scons test build the software
+ scons src run the tests
+ scons web build the web pages
+ """)
+ </programlisting>
+
+ <para>
+
+ This help text is displayed in response to the <option>-h</option>
+ command-line option. Calling the &Help; function more than once is an
+ error.
+
+ </para>
+
+</section>
+
+
+
+<section id="sect-debug">
+ <title>Debug</title>
+
+ <para>
+
+ &SCons; supports several command-line options for printing extra
+ information with which to debug build problems.
+
+ </para>
+
+<!--
+These need to be specified and explained
+beyond what the man page will have.
+-->
+
+ <!-- BEGIN HTML -->
+
+ <para>
+
+ See the -d, -p, -pa, and -pw options
+ in the <!--<A HREF="#sccons_Man_page">man page</A>-->, below.
+ All of these options make use of call-back functions to
+ <!--<A HREF="reference.html#Customizing_output">control the output</A>-->
+ printed by the Build Engine.
+
+ </para>
+
+ <!-- END HTML -->
+
+</section>
diff --git a/doc/design/overview.xml b/doc/design/overview.xml
new file mode 100644
index 0000000..38e4258
--- /dev/null
+++ b/doc/design/overview.xml
@@ -0,0 +1,498 @@
+<!--
+
+ 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.
+
+-->
+
+<section id="sect-architecture">
+ <title>Architecture</title>
+
+ <para>
+
+ The heart of &SCons; is its <emphasis>Build Engine</emphasis>.
+ The &SCons; Build Engine is a Python module
+ that manages dependencies between
+ external objects
+ such as files or database records.
+ The Build Engine is designed to
+ be interface-neutral
+ and easily embeddable in any
+ software system that needs dependency
+ analysis between updatable objects.
+
+ </para>
+
+ <para>
+
+ The key parts of the Build Engine architecture
+ are captured in the following quasi-UML diagram:
+
+ </para>
+
+<!--
+Including this figure makes our PDF build blow up.
+The figure, however,
+is left over from the Software Carpentry contest
+and is therefore old, out-of-date, and needs to be redone anyway.
+This is where it will go, anyway...
+-->
+
+ <!--
+ YARG! THIS MAKES THE PDF BUILD BLOW UP. HELP!
+ <figure>
+ <title>&SCons; Architecture</title>
+ <graphic fileref="engine.jpg">
+ </figure>
+ -->
+
+ <para>
+
+ The point of &SCons; is to manage
+ dependencies between arbitrary external objects.
+ Consequently, the Build Engine does not restrict or specify
+ the nature of the external objects it manages,
+ but instead relies on subclass of the &Node;
+ class to interact with the external system or systems
+ (file systems, database management systems)
+ that maintain the objects being examined or updated.
+
+ </para>
+
+ <para>
+
+ The Build Engine presents to the software system in
+ which it is embedded
+ a Python API for specifying source (input) and target (output) objects,
+ rules for building/updating objects,
+ rules for scanning objects for dependencies, etc.
+ Above its Python API,
+ the Build Engine is completely
+ interface-independent,
+ and can be encapsulated by any other software
+ that supports embedded Python.
+
+ </para>
+
+ <para>
+
+ Software that chooses to use the Build Engine
+ for dependency management
+ interacts with it
+ through <emphasis>Construction Environments</emphasis>.
+ A Construction Environment consists
+ of a dictionary of environment variables,
+ and one or more associated
+ &Scanner; objects
+ and &Builder; objects.
+ The Python API is used to
+ form these associations.
+
+ </para>
+
+ <para>
+
+ A &Scanner; object specifies
+ how to examine a type of source object
+ (C source file, database record)
+ for dependency information.
+ A &Scanner; object may use
+ variables from the associated
+ Construction Environment
+ to modify how it scans an object:
+ specifying a search path for included files,
+ which field in a database record to consult,
+ etc.
+
+ </para>
+
+ <para>
+
+ A &Builder; object specifies
+ how to update a type of target object:
+ executable program, object file, database field, etc.
+ Like a &Scanner; object,
+ a &Builder; object may use
+ variables from the associated
+ Construction Environment
+ to modify how it builds an object:
+ specifying flags to a compiler,
+ using a different update function,
+ etc.
+
+ </para>
+
+ <para>
+
+ &Scanner; and &Builder; objects will return one or more
+ &Node; objects that represent external objects.
+ &Node; objects are the means by which the
+ Build Engine tracks dependencies:
+ A &Node; may represent a source (input) object that
+ should already exist,
+ or a target (output) object which may be built,
+ or both.
+ The &Node; class is sub-classed to
+ represent external objects of specific type:
+ files, directories, database fields or records, etc.
+ Because dependency information, however,
+ is tracked by the top-level &Node; methods and attributes,
+ dependencies can exist
+ between nodes representing different external object types.
+ For example,
+ building a file could be made
+ dependent on the value of a given
+ field in a database record,
+ or a database table could depend
+ on the contents of an external file.
+
+ </para>
+
+ <para>
+
+ The Build Engine uses a &Job; class (not displayed)
+ to manage the actual work of updating external target objects:
+ spawning commands to build files,
+ submitting the necessary commands to update a database record,
+ etc.
+ The &Job; class has sub-classes
+ to handle differences between spawning
+ jobs in parallel and serially.
+
+ </para>
+
+ <para>
+
+ The Build Engine also uses a
+ &Signature; class (not displayed)
+ to maintain information about whether
+ an external object is up-to-date.
+ Target objects with out-of-date signatures
+ are updated using the appropriate
+ &Builder; object.
+
+ </para>
+
+ <!-- BEGIN HTML -->
+
+ <!--
+ Details on the composition, methods,
+ and attributes of these classes
+ are available in the A HREF="internals.html" Internals /A page.
+ -->
+
+ <!-- END HTML -->
+
+</section>
+
+
+
+<section id="sect-engine">
+ <title>Build Engine</title>
+
+ <para>
+
+ More detailed discussion of some of the
+ Build Engine's characteristics:
+
+ </para>
+
+ <section>
+ <title>Python API</title>
+
+ <para>
+
+ The Build Engine can be embedded in any other software
+ that supports embedding Python:
+ in a GUI,
+ in a wrapper script that
+ interprets classic <filename>Makefile</filename> syntax,
+ or in any other software that
+ can translate its dependency representation
+ into the appropriate calls to the Build Engine API.
+ <!--<xref linkend="chap-native">--> describes in detail
+ the specification for a "Native Python" interface
+ that will drive the &SCons; implementation effort.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Single-image execution</title>
+
+ <para>
+
+ When building/updating the objects,
+ the Build Engine operates as a single executable
+ with a complete Directed Acyclic Graph (DAG)
+ of the dependencies in the entire build tree.
+ This is in stark contrast to the
+ commonplace recursive use of Make
+ to handle hierarchical directory-tree builds.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Dependency analysis</title>
+
+ <para>
+
+ Dependency analysis is carried out via digital signatures
+ (a.k.a. "fingerprints").
+ Contents of object are examined and reduced
+ to a number that can be stored and compared to
+ see if the object has changed.
+ Additionally, &SCons; uses the same
+ signature technique on the command-lines that
+ are executed to update an object.
+ If the command-line has changed since the last time,
+ then the object must be rebuilt.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Customized output</title>
+
+ <para>
+
+ The output of Build Engine is customizable
+ through user-defined functions.
+ This could be used to print additional desired
+ information about what &SCons; is doing,
+ or tailor output to a specific build analyzer,
+ GUI, or IDE.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Build failures</title>
+
+ <para>
+
+ &SCons; detects build failures via the exit status from the tools
+ used to build the target files. By default, a failed exit status
+ (non-zero on UNIX systems) terminates the build with an appropriate
+ error message. An appropriate class from the Python library will
+ interpret build-tool failures via an OS-independent API.
+
+ </para>
+
+ <para>
+
+ If multiple tasks are executing in a parallel build, and one tool
+ returns failure, &SCons; will not initiate any further build tasks,
+ but allow the other build tasks to complete before terminating.
+
+ </para>
+
+ <para>
+
+ A <option>-k</option> command-line option may be used to ignore
+ errors and continue building other targets. In no case will a target
+ that depends on a failed build be rebuilt.
+
+ </para>
+
+ </section>
+
+</section>
+
+
+
+<section id="sect-interfaces">
+ <title>Interfaces</title>
+
+ <para>
+
+ As previously described,
+ the &SCons; Build Engine
+ is interface-independent above its Python API,
+ and can be embedded in any software system
+ that can translate its dependency requirements
+ into the necessary Python calls.
+
+ </para>
+
+ <para>
+
+ The "main" &SCons; interface
+ for implementation purposes,
+ uses Python scripts as configuration files.
+ Because this exposes the Build Engine's Python API to the user,
+ it is current called the "Native Python" interface.
+
+ </para>
+
+ <para>
+
+ This section will also discuss
+ how &SCons; will function in the context
+ of two other interfaces:
+ the &Makefile; interface of the classic &Make; utility,
+ and a hypothetical graphical user interface (GUI).
+
+ </para>
+
+ <section>
+ <title>Native Python interface</title>
+
+ <para>
+
+ The Native Python interface is intended to be the primary interface
+ by which users will know &SCons;--that is,
+ it is the interface they will use
+ if they actually type &SCons; at a command-line prompt.
+
+ </para>
+
+ <para>
+
+ In the Native Python interface, &SCons; configuration files are simply
+ Python scripts that directly invoke methods from the Build Engine's
+ Python API to specify target files to be built, rules for building
+ the target files, and dependencies. Additional methods, specific to
+ this interface, are added to handle functionality that is specific to
+ the Native Python interface: reading a subsidiary configuration file;
+ copying target files to an installation directory; etc.
+
+ </para>
+
+ <para>
+
+ Because configuration files are Python scripts, Python flow control
+ can be used to provide very flexible manipulation of objects and
+ dependencies. For example, a function could be used to invoke a common
+ set of methods on a file, and called iteratively over an array of
+ files.
+
+ </para>
+
+ <para>
+
+ As an additional advantage, syntax errors in &SCons; Native Python
+ configuration files will be caught by the Python parser. Target-building
+ does not begin until after all configuration files are read, so a syntax
+ error will not cause a build to fail half-way.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Makefile interface</title>
+
+ <para>
+
+ An alternate &SCons; interface would provide backwards
+ compatibility with the classic &Make utility.
+ This would be done by embedding the &SCons; Build Engine
+ in a Python script that can translate existing
+ &Makefile;s into the underlying calls to the
+ Build Engine's Python API
+ for building and tracking dependencies.
+ Here are approaches to solving some of the issues
+ that arise from marrying these two pieces:
+
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <para>
+ &Makefile; suffix rules can be translated
+ into an appropriate &Builder; object
+ with suffix maps from the Construction Environment.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Long lists of static dependences
+ appended to a &Makefile; by
+ various <command>"make depend"</command> schemes
+ can be preserved
+ but supplemented by
+ the more accurate dependency information
+ provided by &Scanner; objects.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Recursive invocations of &Make;
+ can be avoided by reading up
+ the subsidiary &Makefile; instead.
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+
+ Lest this seem like too outlandish an undertaking,
+ there is a working example of this approach:
+ Gary Holt's &Makepp; utility
+ is a Perl script that provides
+ admirably complete parsing of complicated &Makefile;s
+ around an internal build engine inspired,
+ in part, by the classic <application>Cons</application> utility.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Graphical interfaces</title>
+
+ <para>
+
+ The &SCons; Build Engine
+ is designed from the ground up to be embedded
+ into multiple interfaces.
+ Consequently, embedding the dependency capabilities
+ of &SCons; into graphical interface
+ would be a matter of mapping the
+ GUI's dependency representation
+ (either implicit or explicit)
+ into corresponding calls to the Python API
+ of the &SCons; Build Engine.
+
+ </para>
+
+ <para>
+
+ Note, however, that this proposal leaves the problem of
+ designed a good graphical interface
+ for representing software build dependencies
+ to people with actual GUI design experience...
+
+ </para>
+
+ </section>
+
+</section>
diff --git a/doc/design/scons.mod b/doc/design/scons.mod
new file mode 100644
index 0000000..d805210
--- /dev/null
+++ b/doc/design/scons.mod
@@ -0,0 +1,429 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ An SCons-specific DTD module, for use with SCons DocBook
+ documentation, that contains names, phrases, acronyms, etc. used
+ throughout the SCons documentation.
+
+-->
+
+
+
+<!--
+
+ Other applications that we reference.
+
+-->
+
+<!ENTITY Aegis "<application>Aegis</application>">
+<!ENTITY Ant "<application>Ant</application>">
+<!ENTITY Autoconf "<application>Autoconf</application>">
+<!ENTITY Automake "<application>Automake</application>">
+<!ENTITY cc "<application>cc</application>">
+<!ENTITY Cons "<application>Cons</application>">
+<!ENTITY cp "<application>cp</application>">
+<!ENTITY csh "<application>csh</application>">
+<!ENTITY gcc "<application>gcc</application>">
+<!ENTITY Jam "<application>Jam</application>">
+<!ENTITY jar "<application>jar</application>">
+<!ENTITY javac "<application>javac</application>">
+<!ENTITY javah "<application>javah</application>">
+<!ENTITY Make "<application>Make</application>">
+<!ENTITY Makepp "<application>Make++</application>">
+<!ENTITY Python "<application>Python</application>">
+<!ENTITY ranlib "<application>ranlib</application>">
+<!ENTITY rmic "<application>rmic</application>">
+<!ENTITY SCons "<application>SCons</application>">
+<!ENTITY scons "<application>scons</application>">
+<!ENTITY ScCons "<application>ScCons</application>">
+<!ENTITY tar "<application>tar</application>">
+<!ENTITY touch "<application>touch</application>">
+<!ENTITY zip "<application>zip</application>">
+
+
+<!--
+
+ Classes.
+
+-->
+
+<!ENTITY Action "<classname>Action</classname>">
+<!ENTITY ActionBase "<classname>ActionBase</classname>">
+<!ENTITY CommandAction "<classname>CommandAction</classname>">
+<!ENTITY FunctionAction "<classname>FunctionAction</classname>">
+<!ENTITY ListAction "<classname>ListAction</classname>">
+<!ENTITY Builder "<classname>Builder</classname>">
+<!ENTITY BuilderBase "<classname>BuilderBase</classname>">
+<!ENTITY CompositeBuilder "<classname>CompositeBuilder</classname>">
+<!ENTITY MultiStepBuilder "<classname>MultiStepBuilder</classname>">
+<!ENTITY Job "<classname>Job</classname>">
+<!ENTITY Jobs "<classname>Jobs</classname>">
+<!ENTITY Serial "<classname>Serial</classname>">
+<!ENTITY Parallel "<classname>Parallel</classname>">
+<!ENTITY Node "<classname>Node</classname>">
+<!ENTITY Node_FS "<classname>Node.FS</classname>">
+<!ENTITY Scanner "<classname>Scanner</classname>">
+<!ENTITY Sig "<classname>Sig</classname>">
+<!ENTITY Signature "<classname>Signature</classname>">
+<!ENTITY Taskmaster "<classname>Taskmaster</classname>">
+<!ENTITY TimeStamp "<classname>TimeStamp</classname>">
+<!ENTITY Walker "<classname>Walker</classname>">
+<!ENTITY Wrapper "<classname>Wrapper</classname>">
+
+
+
+<!--
+
+ Options, command-line.
+
+-->
+
+<!ENTITY debug-explain "<literal>--debug=explain</literal>">
+<!ENTITY implicit-cache "<literal>--implicit-cache</literal>">
+<!ENTITY implicit-deps-changed "<literal>--implicit-deps-changed</literal>">
+<!ENTITY implicit-deps-unchanged "<literal>--implicit-deps-unchanged</literal>">
+<!ENTITY Q "<literal>-Q</literal>">
+
+<!--
+
+ Options, SConscript-settable.
+
+-->
+
+<!ENTITY implicit_cache "<literal>implicit_cache</literal>">
+<!ENTITY implicit_deps_changed "<literal>implicit_deps_changed</literal>">
+<!ENTITY implicit_deps_unchanged "<literal>implicit_deps_unchanged</literal>">
+
+
+
+<!--
+
+ File and directory names.
+
+-->
+
+<!ENTITY build "<filename>build</filename>">
+<!ENTITY Makefile "<filename>Makefile</filename>">
+<!ENTITY Makefiles "<filename>Makefiles</filename>">
+<!ENTITY SConscript "<filename>SConscript</filename>">
+<!ENTITY SConstruct "<filename>SConstruct</filename>">
+<!ENTITY Sconstruct "<filename>Sconstruct</filename>">
+<!ENTITY sconstruct "<filename>sconstruct</filename>">
+<!ENTITY sconsign "<filename>.sconsign</filename>">
+<!ENTITY src "<filename>src</filename>">
+
+
+
+<!--
+
+ Methods and functions. This includes functions from both
+ the Build Engine and the Native Python Interface.
+
+-->
+
+<!ENTITY Add "<function>Add</function>">
+<!ENTITY AddOptions "<function>AddOptions</function>">
+<!ENTITY Alias "<function>Alias</function>">
+<!ENTITY Aliases "<function>Aliases</function>">
+<!ENTITY Append "<function>Append</function>">
+<!ENTITY BoolOption "<function>BoolOption</function>">
+<!ENTITY Build "<function>Build</function>">
+<!ENTITY CacheDir "<function>CacheDir</function>">
+<!ENTITY Clean "<function>Clean</function>">
+<!ENTITY Clone "<function>Clone</function>">
+<!ENTITY Command "<function>Command</function>">
+<!ENTITY Configure "<function>Configure</function>">
+<!ENTITY Copy "<function>Copy</function>">
+<!ENTITY Default "<function>Default</function>">
+<!ENTITY DefaultRules "<function>DefaultRules</function>">
+<!ENTITY Depends "<function>Depends</function>">
+<!ENTITY Dir "<function>Dir</function>">
+<!ENTITY Entry "<function>Entry</function>">
+<!ENTITY EnumOption "<function>EnumOption</function>">
+<!ENTITY Environment "<function>Environment</function>">
+<!ENTITY Export "<function>Export</function>">
+<!ENTITY File "<function>File</function>">
+<!ENTITY Finish "<function>Finish</function>">
+<!ENTITY GenerateHelpText "<function>GenerateHelpText</function>">
+<!ENTITY Help "<function>Help</function>">
+<!ENTITY Ignore "<function>Ignore</function>">
+<!ENTITY Import "<function>Import</function>">
+<!ENTITY Install "<function>Install</function>">
+<!ENTITY InstallAs "<function>InstallAs</function>">
+<!ENTITY Link "<function>Link</function>">
+<!ENTITY ListOption "<function>ListOption</function>">
+<!ENTITY Local "<function>Local</function>">
+<!ENTITY Module "<function>Module</function>">
+<!ENTITY NoClean "<function>NoClean</function>">
+<!ENTITY Objects "<function>Objects</function>">
+<!ENTITY Options "<function>Options</function>">
+<!ENTITY PackageOption "<function>PackageOption</function>">
+<!ENTITY PathOption "<function>PathOption</function>">
+<!ENTITY Precious "<function>Precious</function>">
+<!ENTITY Prepend "<function>Prepend</function>">
+<!ENTITY Replace "<function>Replace</function>">
+<!ENTITY Repository "<function>Repository</function>">
+<!ENTITY Return "<function>Return</function>">
+<!ENTITY RuleSet "<function>RuleSet</function>">
+<!ENTITY Salt "<function>Salt</function>">
+<!ENTITY SetBuildSignatureType "<function>SetBuildSignatureType</function>">
+<!ENTITY SetContentSignatureType "<function>SetContentSignatureType</function>">
+<!ENTITY SourceSignature "<function>SourceSignature</function>">
+<!ENTITY SourceSignatures "<function>SourceSignatures</function>">
+<!ENTITY Split "<function>Split</function>">
+<!ENTITY TargetSignatures "<function>TargetSignatures</function>">
+<!ENTITY Task "<function>Task</function>">
+
+<!-- Environment methods -->
+<!ENTITY subst "<function>subst</function>">
+
+<!-- Configure context functions -->
+<!ENTITY Message "<function>Message</function>">
+<!ENTITY Result "<function>Result</function>">
+<!ENTITY CheckCHeader "<function>CheckCHeader</function>">
+<!ENTITY CheckCXXHeader "<function>CheckCXXHeader</function>">
+<!ENTITY CheckFunc "<function>CheckFunc</function>">
+<!ENTITY CheckHeader "<function>CheckHeader</function>">
+<!ENTITY CheckLib "<function>CheckLib</function>">
+<!ENTITY CheckLibWithHeader "<function>CheckLibWithHeader</function>">
+<!ENTITY CheckType "<function>CheckType</function>">
+<!ENTITY TryAction "<function>TryAction</function>">
+<!ENTITY TryBuild "<function>TryBuild</function>">
+<!ENTITY TryCompile "<function>TryCompile</function>">
+<!ENTITY TryLink "<function>TryLink</function>">
+<!ENTITY TryRun "<function>TryRun</function>">
+
+<!-- Python functions -->
+<!ENTITY str "<function>str</function>">
+<!ENTITY zipfile "<function>zipfile</function>">
+
+<!-- Obsolete, but referenced in old documents. -->
+<!ENTITY Cache "<function>Cache</function>">
+
+
+
+<!--
+
+ Global variables.
+
+-->
+
+<!ENTITY ARGUMENTS "<varname>ARGUMENTS</varname>">
+<!ENTITY BUILD_TARGETS "<varname>BUILD_TARGETS</varname>">
+<!ENTITY COMMAND_LINE_TARGETS "<varname>COMMAND_LINE_TARGETS</varname>">
+<!ENTITY DEFAULT_TARGETS "<varname>DEFAULT_TARGETS</varname>">
+
+
+
+<!--
+
+ Construction variables.
+
+-->
+
+<!ENTITY BUILDERMAP "<varname>BUILDERMAP</varname>">
+<!ENTITY BUILDERS "<varname>BUILDERS</varname>">
+<!ENTITY CC "<varname>CC</varname>">
+<!ENTITY CCFLAGS "<varname>CCFLAGS</varname>">
+<!ENTITY CCCOM "<varname>CCCOM</varname>">
+<!ENTITY COLOR "<varname>COLOR</varname>">
+<!ENTITY COLORS "<varname>COLORS</varname>">
+<!ENTITY CONFIG "<varname>CONFIG</varname>">
+<!ENTITY CPPDEFINES "<varname>CPPDEFINES</varname>">
+<!ENTITY ENV "<varname>ENV</varname>">
+<!ENTITY JAVACLASSDIR "<varname>JAVACLASSDIR</varname>">
+<!ENTITY LIBDIRPREFIX "<varname>LIBDIRPREFIX</varname>">
+<!ENTITY LIBDIRSUFFIX "<varname>LIBDIRSUFFIX</varname>">
+<!ENTITY LIBLINKPREFIX "<varname>LIBLINKPREFIX</varname>">
+<!ENTITY LIBLINKSUFFIX "<varname>LIBLINKSUFFIX</varname>">
+<!ENTITY LIBPATH "<varname>LIBPATH</varname>">
+<!ENTITY LIBS "<varname>LIBS</varname>">
+<!ENTITY LINK "<varname>LINK</varname>">
+<!ENTITY LINKCOM "<varname>LINKCOM</varname>">
+<!ENTITY LINKFLAGS "<varname>LINKFLAGS</varname>">
+<!ENTITY RELEASE "<varname>RELEASE</varname>">
+<!ENTITY RELEASE_BUILD "<varname>RELEASE_BUILD</varname>">
+<!ENTITY SCANNERMAP "<varname>SCANNERMAP</varname>">
+<!ENTITY SCANNERS "<varname>SCANNERS</varname>">
+<!ENTITY TARFLAGS "<varname>TARFLAGS</varname>">
+<!ENTITY TARSUFFIX "<varname>TARSUFFIX</varname>">
+
+
+
+<!--
+
+ Environment variables.
+
+-->
+
+<!ENTITY PATH "<varname>PATH</varname>">
+<!ENTITY PYTHONPATH "<varname>PYTHONPATH</varname>">
+<!ENTITY SCONSFLAGS "<varname>SCONSFLAGS</varname>">
+
+
+
+<!--
+
+ Function and method arguments.
+
+-->
+
+<!ENTITY allowed_values "<varname>allowed_values</varname>">
+<!ENTITY build_dir "<varname>build_dir</varname>">
+<!ENTITY map "<varname>map</varname>">
+<!ENTITY ignorecase "<varname>ignorecase</varname>">
+<!ENTITY options "<varname>options</varname>">
+<!ENTITY exports "<varname>exports</varname>">
+<!ENTITY source "<varname>source</varname>">
+<!ENTITY target "<varname>target</varname>">
+
+
+
+<!--
+
+ Values of function and method arguments.
+
+-->
+
+<!ENTITY all "<literal>all</literal>">
+<!ENTITY none "<literal>none</literal>">
+
+
+
+<!--
+
+ Builder and Scanner objects.
+
+-->
+
+<!ENTITY BuildDir "<function>BuildDir</function>">
+<!ENTITY CFile "<function>CFile</function>">
+<!ENTITY CXXFile "<function>CXXFile</function>">
+<!ENTITY DVI "<function>DVI</function>">
+<!ENTITY Jar "<function>Jar</function>">
+<!ENTITY Java "<function>Java</function>">
+<!ENTITY JavaH "<function>JavaH</function>">
+<!ENTITY Library "<function>Library</function>">
+<!ENTITY Object "<function>Object</function>">
+<!ENTITY PCH "<function>PCH</function>">
+<!ENTITY PDF "<function>PDF</function>">
+<!ENTITY PostScript "<function>PostScript</function>">
+<!ENTITY Program "<function>Program</function>">
+<!ENTITY RES "<function>RES</function>">
+<!ENTITY RMIC "<function>RMIC</function>">
+<!ENTITY SharedLibrary "<function>SharedLibrary</function>">
+<!ENTITY SharedObject "<function>SharedObject</function>">
+<!ENTITY StaticLibrary "<function>StaticLibrary</function>">
+<!ENTITY StaticObject "<function>StaticObject</function>">
+<!ENTITY Tar "<function>Tar</function>">
+<!ENTITY Zip "<function>Zip</function>">
+
+<!-- Obsolete, but referenced in old documents. -->
+<!ENTITY MakeBuilder "<function>Make</function>">
+
+
+
+<!--
+
+ Terms. Define both singular and plural forms in various
+ case-sensitive combinations for use in titles, in-line, etc.
+
+-->
+
+<!ENTITY buildfunc "<literal>builder function</literal>">
+<!ENTITY builder_method "<literal>builder method</literal>">
+
+<!ENTITY Configure_Contexts "<literal>Configure Contexts</literal>">
+<!ENTITY configure_context "<literal>configure context</literal>">
+
+<!ENTITY ConsEnv "<literal>Construction Environment</literal>">
+<!ENTITY ConsEnvs "<literal>Construction Environments</literal>">
+<!ENTITY Consenv "<literal>Construction environment</literal>">
+<!ENTITY Consenvs "<literal>Construction environments</literal>">
+<!ENTITY consenv "<literal>construction environment</literal>">
+<!ENTITY consenvs "<literal>construction environments</literal>">
+
+<!ENTITY ConsVar "<literal>Construction Variable</literal>">
+<!ENTITY ConsVars "<literal>Construction Variables</literal>">
+<!ENTITY Consvar "<literal>Construction variable</literal>">
+<!ENTITY Consvars "<literal>Construction variables</literal>">
+<!ENTITY consvar "<literal>construction variable</literal>">
+<!ENTITY consvars "<literal>construction variables</literal>">
+
+<!ENTITY CPPPATH "<literal>CPPPATH</literal>">
+
+<!ENTITY Dictionary "<literal>Dictionary</literal>">
+
+<!ENTITY Emitter "<literal>Emitter</literal>">
+<!ENTITY emitter "<literal>emitter</literal>">
+<!ENTITY Generator "<literal>Generator</literal>">
+<!ENTITY generator "<literal>generator</literal>">
+
+<!ENTITY Nodes "<literal>Nodes</literal>">
+
+<!ENTITY signature "<literal>signature</literal>">
+<!ENTITY buildsignature "<literal>build signature</literal>">
+
+<!ENTITY true "<literal>true</literal>">
+<!ENTITY false "<literal>false</literal>">
+
+<!ENTITY typedef "<literal>typedef</literal>">
+
+<!--
+
+ File and program names used in examples.
+
+-->
+
+<!ENTITY bar "<application>bar</application>">
+<!ENTITY common1_c "<filename>common1.c</filename>">
+<!ENTITY common2_c "<filename>common2.c</filename>">
+<!ENTITY custom_py "<filename>custom.py</filename>">
+<!ENTITY goodbye "<application>goodbye</application>">
+<!ENTITY goodbye_o "<filename>goodbye.o</filename>">
+<!ENTITY goodbye_obj "<filename>goodbye.obj</filename>">
+<!ENTITY file_dll "<filename>file.dll</filename>">
+<!ENTITY file_in "<filename>file.in</filename>">
+<!ENTITY file_lib "<filename>file.lib</filename>">
+<!ENTITY file_o "<filename>file.o</filename>">
+<!ENTITY file_obj "<filename>file.obj</filename>">
+<!ENTITY file_out "<filename>file.out</filename>">
+<!ENTITY foo "<application>foo</application>">
+<!ENTITY foo_o "<filename>foo.o</filename>">
+<!ENTITY foo_obj "<filename>foo.obj</filename>">
+<!ENTITY hello "<application>hello</application>">
+<!ENTITY hello_c "<filename>hello.c</filename>">
+<!ENTITY hello_exe "<filename>hello.exe</filename>">
+<!ENTITY hello_h "<filename>hello.h</filename>">
+<!ENTITY hello_o "<filename>hello.o</filename>">
+<!ENTITY hello_obj "<filename>hello.obj</filename>">
+<!ENTITY libfile_a "<filename>libfile_a</filename>">
+<!ENTITY libfile_so "<filename>libfile_so</filename>">
+<!ENTITY new_hello "<application>new_hello</application>">
+<!ENTITY new_hello_exe "<application>new_hello.exe</application>">
+<!ENTITY prog "<filename>prog</filename>">
+<!ENTITY prog1 "<filename>prog1</filename>">
+<!ENTITY prog2 "<filename>prog2</filename>">
+<!ENTITY prog_c "<filename>prog.c</filename>">
+<!ENTITY prog_exe "<filename>prog.exe</filename>">
+<!ENTITY stdio_h "<filename>stdio.h</filename>">
+
+<!--
+
+ Punctuation.
+
+-->
+
+<!ENTITY plus "<literal>+</literal>">
+<!ENTITY hash "<literal>#</literal>">
+
+<!--
+
+ Mailing lists
+
+-->
+
+<!ENTITY scons-announce "<literal>announce@scons.tigris.org</literal>">
+<!ENTITY scons-devel "<literal>dev@scons.tigris.org</literal>">
+<!ENTITY scons-users "<literal>users@scons.tigris.org</literal>">
diff --git a/doc/developer/MANIFEST b/doc/developer/MANIFEST
new file mode 100644
index 0000000..eece338
--- /dev/null
+++ b/doc/developer/MANIFEST
@@ -0,0 +1,9 @@
+architecture.xml
+branches.xml
+copyright.xml
+cycle.xml
+main.xml
+packaging.xml
+preface.xml
+sourcetree.xml
+testing.xml
diff --git a/doc/developer/architecture.xml b/doc/developer/architecture.xml
new file mode 100644
index 0000000..3a6e18c
--- /dev/null
+++ b/doc/developer/architecture.xml
@@ -0,0 +1,40 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>Architecture</title>
+
+ <para>
+
+ XXX
+ </para>
+
+ </section>
diff --git a/doc/developer/branches.xml b/doc/developer/branches.xml
new file mode 100644
index 0000000..e46b616
--- /dev/null
+++ b/doc/developer/branches.xml
@@ -0,0 +1,40 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>&SCons; Branches</title>
+
+ <para>
+
+ XXX
+ </para>
+
+ </section>
diff --git a/doc/developer/copyright.xml b/doc/developer/copyright.xml
new file mode 100644
index 0000000..7a37cb9
--- /dev/null
+++ b/doc/developer/copyright.xml
@@ -0,0 +1,32 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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 Developer's Guide Copyright (c) 2007 Steven Knight
+
+ </para>
+</blockquote>
diff --git a/doc/developer/cycle.xml b/doc/developer/cycle.xml
new file mode 100644
index 0000000..b56edd2
--- /dev/null
+++ b/doc/developer/cycle.xml
@@ -0,0 +1,40 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>Development Cycle</title>
+
+ <para>
+
+ XXX
+ </para>
+
+ </section>
diff --git a/doc/developer/main.xml b/doc/developer/main.xml
new file mode 100644
index 0000000..0ebed33
--- /dev/null
+++ b/doc/developer/main.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+
+ <!ENTITY % version SYSTEM "../version.xml">
+ %version;
+
+ <!ENTITY % scons SYSTEM "../scons.mod">
+ %scons;
+
+ <!ENTITY architecture SYSTEM "architecture.xml">
+ <!ENTITY branches SYSTEM "branches.xml">
+ <!ENTITY copyright SYSTEM "copyright.xml">
+ <!ENTITY cycle SYSTEM "cycle.xml">
+ <!ENTITY packaging SYSTEM "packaging.xml">
+ <!ENTITY preface SYSTEM "preface.xml">
+ <!ENTITY sourcetree SYSTEM "sourcetree.xml">
+ <!ENTITY testing SYSTEM "testing.xml">
+
+]>
+
+<book>
+ <bookinfo>
+ <title>SCons Developer's Guide &buildversion;</title>
+
+ <author>
+ <firstname>Steven</firstname>
+ <surname>Knight</surname>
+ </author>
+
+ <edition>Revision &buildrevision; (&builddate;)</edition>
+
+ <pubdate>2007</pubdate>
+
+ <copyright>
+ <year>2007</year>
+ <holder>Steven Knight</holder>
+ </copyright>
+
+ <legalnotice>
+ &copyright;
+ </legalnotice>
+
+ <releaseinfo>version &buildversion;</releaseinfo>
+
+ </bookinfo>
+
+ <preface id="chap-preface">
+ <title>Preface</title>
+ &preface;
+ </preface>
+
+ <chapter id="chap-development-cycle">
+ <title>Development Cycle</title>
+ &cycle;
+ </chapter>
+
+ <chapter id="chap-source-tree">
+ <title>Source Tree</title>
+ &sourcetree;
+ </chapter>
+
+ <chapter id="chap-testing">
+ <title>Testing</title>
+ &testing;
+ </chapter>
+
+ <chapter id="chap-branches">
+ <title>Branches</title>
+ &branches;
+ </chapter>
+
+ <chapter id="chap-packaging">
+ <title>Packaging</title>
+ &packaging;
+ </chapter>
+
+ <chapter id="chap-architecture">
+ <title>Architecture</title>
+ &architecture;
+ </chapter>
+
+</book>
diff --git a/doc/developer/packaging.xml b/doc/developer/packaging.xml
new file mode 100644
index 0000000..92b6a31
--- /dev/null
+++ b/doc/developer/packaging.xml
@@ -0,0 +1,40 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>Packaging</title>
+
+ <para>
+
+ XXX
+ </para>
+
+ </section>
diff --git a/doc/developer/preface.xml b/doc/developer/preface.xml
new file mode 100644
index 0000000..ece9cdc
--- /dev/null
+++ b/doc/developer/preface.xml
@@ -0,0 +1,175 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ This document assumes that you already know how &SCons;
+ and that you want to learn how to work on the code.
+
+ </para>
+
+ <section>
+ <title>&SCons; Principles</title>
+
+ <para>
+
+ There are a few overriding principles
+ we try to live up to in designing and implementing &SCons:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>Correctness</term>
+
+ <listitem>
+ <para>
+
+ First and foremost,
+ by default, &SCons; guarantees a correct build
+ even if it means sacrificing performance a little.
+ We strive to guarantee the build is correct
+ regardless of how the software being built is structured,
+ how it may have been written,
+ or how unusual the tools are that build it.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Performance</term>
+
+ <listitem>
+ <para>
+
+ Given that the build is correct,
+ we try to make &SCons; build software
+ as quickly as possible.
+ In particular, wherever we may have needed to slow
+ down the default &SCons; behavior to guarantee a correct build,
+ we also try to make it easy to speed up &SCons;
+ through optimization options that let you trade off
+ guaranteed correctness in all end cases for
+ a speedier build in the usual cases.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Convenience</term>
+
+ <listitem>
+ <para>
+
+ &SCons; tries to do as much for you out of the box as reasonable,
+ including detecting the right tools on your system
+ and using them correctly to build the software.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ In a nutshell, we try hard to make &SCons; just
+ "do the right thing" and build software correctly,
+ with a minimum of hassles.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>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>
+
+ 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>
diff --git a/doc/developer/sourcetree.xml b/doc/developer/sourcetree.xml
new file mode 100644
index 0000000..97bfee0
--- /dev/null
+++ b/doc/developer/sourcetree.xml
@@ -0,0 +1,40 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>Source Tree</title>
+
+ <para>
+
+ XXX
+ </para>
+
+ </section>
diff --git a/doc/developer/testing.xml b/doc/developer/testing.xml
new file mode 100644
index 0000000..a41c61b
--- /dev/null
+++ b/doc/developer/testing.xml
@@ -0,0 +1,40 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>Testing</title>
+
+ <para>
+
+ XXX
+ </para>
+
+ </section>
diff --git a/doc/man/MANIFEST b/doc/man/MANIFEST
new file mode 100644
index 0000000..8e69d1c
--- /dev/null
+++ b/doc/man/MANIFEST
@@ -0,0 +1,2 @@
+scons.1
+sconsign.1
diff --git a/doc/man/scons-time.1 b/doc/man/scons-time.1
new file mode 100644
index 0000000..8231c9d
--- /dev/null
+++ b/doc/man/scons-time.1
@@ -0,0 +1,1017 @@
+.\" Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+.\"
+.\" 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.
+.\"
+.\" doc/man/scons-time.1 4577 2009/12/27 19:44:43 scons
+.\"
+.\" ES - Example Start - indents and turns off line fill
+.de ES
+.RS
+.nf
+..
+.\" EE - Example End - ends indent and turns line fill back on
+.de EE
+.RE
+.fi
+..
+'\"==========================================================================
+.de SF
+.B scons-time func
+[\fB-h\fR]
+[\fB--chdir=\fIDIR\fR]
+[\fB-f \fIFILE\fR]
+[\fB--fmt=\fIFORMAT\fR]
+[\fB--func=\fINAME\fR]
+[\fB-p \fISTRING\fR]
+[\fB-t \fINUMBER\fR]
+[\fB--title= TITLE\fR]
+[\fIARGUMENTS\fR]
+..
+'\"--------------------------------------------------------------------------
+.de SY
+.B scons-time mem
+[\fB-h\fR]
+[\fB--chdir=\fIDIR\fR]
+[\fB-f \fIFILE\fR]
+[\fB--fmt=\fIFORMAT\fR]
+[\fB-p \fISTRING\fR]
+[\fB--stage=\fISTAGE\fR]
+[\fB-t \fINUMBER\fR]
+[\fB--title=\fITITLE\fR]
+[\fIARGUMENTS\fR]
+..
+'\"--------------------------------------------------------------------------
+.de SO
+.B scons-time obj
+[\fB-h\fR]
+[\fB--chdir=\fIDIR\fR]
+[\fB-f \fIFILE\fR]
+[\fB--fmt=\fIFORMAT\fR]
+[\fB-p \fISTRING\fR]
+[\fB--stage=\fISTAGE\fR]
+[\fB-t \fINUMBER\fR]
+[\fB--title=\fITITLE\fR]
+[\fIARGUMENTS\fR]
+..
+'\"--------------------------------------------------------------------------
+.de SR
+.B scons-time run
+[\fB-hnqv\fR]
+[\fB--aegis=\fIPROJECT\fR]
+[\fB-f \fIFILE\fR]
+[\fB--number=\fINUMBER\fR]
+[\fB--outdir=\fIOUTDIR\fR]
+[\fB-p \fISTRING\fR]
+[\fB--python=\fIPYTHON\fR]
+[\fB-s \fIDIR\fR]
+[\fB--scons=\fISCONS\fR]
+[\fB--svn=\fIURL\fR]
+[\fIARGUMENTS\fR]
+..
+'\"--------------------------------------------------------------------------
+.de ST
+.B scons-time time
+[\fB-h\fR]
+[\fB--chdir=\fIDIR\fR]
+[\fB-f \fIFILE\fR]
+[\fB--fmt=\fIFORMAT\fR]
+[\fB-p \fISTRING\fR]
+[\fB-t \fINUMBER\fR]
+[\fB--title=\fITITLE\fR]
+[\fB--which=\fIWHICH\fR]
+[\fIARGUMENTS\fR]
+..
+.TH SCONS-TIME 1 "December 2009"
+.SH NAME
+scons-time \- generate and display SCons timing information
+'\"==========================================================================
+.SH SYNOPSIS
+.B scons-time
+.IR subcommand
+[
+.IR options ...
+]
+[
+.IR arguments ...
+]
+'\"--------------------------------------------------------------------------
+.SS "Generating Timing Information"
+.SR
+'\"--------------------------------------------------------------------------
+.SS "Extracting Function Timings"
+.SF
+'\"--------------------------------------------------------------------------
+.SS "Extracting Memory Statistics"
+.SY
+'\"--------------------------------------------------------------------------
+.SS "Extracting Object Counts"
+.SO
+'\"--------------------------------------------------------------------------
+.SS "Extracting Execution Times"
+.ST
+'\"--------------------------------------------------------------------------
+.SS "Help Text"
+.B scons-time help
+.I SUBCOMMAND
+[...]
+'\"==========================================================================
+.SH DESCRIPTION
+The
+.B scons-time
+command runs an SCons configuration
+through a standard set of profiled timings
+and can extract and graph information from the
+resulting profiles and log files of those timings.
+The action to be performed by the
+.B scons-time
+script is specified
+by a subcommand, the first argument on the command line.
+See the
+.B SUBCOMMANDS
+section below for information about the operation
+of specific subcommands.
+.P
+The basic way to use
+.B scons-time
+is to run the
+.B scons-time run
+subcommand
+(possibly multiple times)
+to generate profile and log file output,
+and then use one of the other
+subcommands to display the results
+captured in the profiles and log files
+for a particular kind of information:
+function timings
+(the
+.B scons-time func
+subcommand),
+total memory used
+(the
+.B scons-time mem
+subcommand),
+object counts
+(the
+.B scons-time obj
+subcommand)
+and overall execution time
+(the
+.B scons-time time
+subcommand).
+Options exist to place and find the
+profiles and log files in separate directories,
+to generate the output in a format suitable
+for graphing with the
+.BR gnuplot (1)
+program,
+and so on.
+.P
+There are two basic ways the
+.B scons-time run
+subcommand
+is intended to be used
+to gather timing statistics
+for a configuration.
+One is to use the
+.B --svn=
+option to test a configuration against
+a list of revisions from the SCons Subversion repository.
+This will generate a profile and timing log file
+for every revision listed with the
+.B --number=
+option,
+and can be used to look at the
+impact of commited changes to the
+SCons code base on a particular
+configuration over time.
+.P
+The other way is to profile incremental changes to a
+local SCons code base during a development cycle--that is,
+to look at the performance impact of changes
+you're making in the local tree.
+In this mode,
+you run the
+.B scons-time run
+subcommand
+.I without
+the
+.B --svn=
+option,
+in which case it simply looks in the profile/log file output directory
+(the current directory by default)
+and automatically figures out the
+.I next
+run number for the output profile and log file.
+Used in this way,
+the development cycle goes something like:
+make a change to SCons;
+run
+.B scons-time run
+to profile it against a specific configuration;
+make another change to SCons;
+run
+.B scons-time run
+again to profile it;
+etc.
+'\"==========================================================================
+.SH OPTIONS
+The
+.B scons-time
+command only supports a few global options:
+.TP
+-h, --help
+Displays the global help text and exits,
+identical to the
+.B scons-time help
+subcommand.
+.TP
+-V, --version
+Displays the
+.B scons-time
+version and exits.
+.P
+Most functionality is controlled by options
+to the individual subcommands.
+See the next section for information
+about individual subcommand options.
+'\"==========================================================================
+.SH SUBCOMMANDS
+The
+.B scons-time
+command supports the following
+individual subcommands.
+'\"--------------------------------------------------------------------------
+.SS "The func Subcommand"
+.SF
+.P
+The
+.B scons-time func
+subcommand displays timing information
+for a specific Python function within SCons.
+By default, it extracts information about the
+.BR _main ()
+function,
+which includes the Python profiler timing
+for all of SCons.
+.P
+The
+.B scons-time func
+subcommand extracts function timing information
+from all the specified file arguments,
+which should be Python profiler output files.
+(Normally, these would be
+.B *.prof
+files generated by the
+.B scons-time run
+subcommand,
+but they can actually be generated
+by any Python profiler invocation.)
+All file name arguments will be
+globbed for on-disk files.
+.P
+If no arguments are specified,
+then function timing information
+will be extracted from all
+.B *.prof
+files,
+or the subset of them
+with a prefix specified by the
+.B -p
+option.
+.P
+Options include:
+.TP
+-C DIRECTORY, --chdir=DIRECTORY
+Changes to the specified
+.I DIRECTORY
+before looking for the specified files
+(or files that match the specified patterns).
+.TP
+-f FILE, --file=FILE
+Reads configuration information from the specified
+.IR FILE .
+.TP
+-fmt=FORMAT, --format=FORMAT
+Reports the output in the specified
+.IR FORMAT .
+The formats currently supported are
+.B ascii
+(the default)
+and
+.BR gnuplot .
+.TP
+--func=NAME
+Extracts timings for the specified function
+.IR NAME .
+The default is to report cumulative timings for the
+.BR _main ()
+function,
+which contains the entire SCons run.
+.TP
+-h, --help
+Displays help text for the
+.B scons-time func
+subcommand.
+.TP
+-p STRING, --prefix=STRING
+Specifies the prefix string for profiles
+from which to extract function timing information.
+This will be used to search for profiles
+if no arguments are specified on the command line.
+.TP
+-t NUMBER, --tail=NUMBER
+Only extracts function timings from the last
+.I NUMBER
+files.
+'\"--------------------------------------------------------------------------
+.SS "The help Subcommand"
+.B scons-time help
+.I SUBCOMMAND
+[...]
+The
+.B help
+subcommand prints help text for any
+other subcommands listed as later arguments on the command line.
+'\"--------------------------------------------------------------------------
+.SS "The mem Subcommand"
+.SY
+.P
+The
+.B scons-time mem
+subcommand displays how much memory SCons uses.
+.P
+The
+.B scons-time mem
+subcommand extracts memory use information
+from all the specified file arguments,
+which should be files containing output from
+running SCons with the
+.B --debug=memory
+option.
+(Normally, these would be
+.B *.log
+files generated by the
+.B scons-time run
+subcommand.)
+All file name arguments will be
+globbed for on-disk files.
+.P
+If no arguments are specified,
+then memory information
+will be extracted from all
+.B *.log
+files,
+or the subset of them
+with a prefix specified by the
+.B -p
+option.
+.P
+.TP
+-C DIR, --chdir=DIR
+Changes to the specified
+.I DIRECTORY
+before looking for the specified files
+(or files that match the specified patterns).
+.TP
+-f FILE, --file=FILE
+Reads configuration information from the specified
+.IR FILE .
+.TP
+-fmt=FORMAT, --format=FORMAT
+Reports the output in the specified
+.IR FORMAT .
+The formats currently supported are
+.B ascii
+(the default)
+and
+.BR gnuplot .
+.TP
+-h, --help
+Displays help text for the
+.B scons-time mem
+subcommand.
+.TP
+-p STRING, --prefix=STRING
+Specifies the prefix string for log files
+from which to extract memory usage information.
+This will be used to search for log files
+if no arguments are specified on the command line.
+.TP
+--stage=STAGE
+Prints the memory used at the end of the specified
+.IR STAGE :
+.B pre-read
+(before the SConscript files are read),
+.B post-read ,
+(after the SConscript files are read),
+.B pre-build
+(before any targets are built)
+or
+.B post-build
+(after any targets are built).
+If no
+.B --stage
+option is specified,
+the default behavior is
+.BR post-build ,
+which reports the final amount of memory
+used by SCons during each run.
+.TP
+-t NUMBER, --tail=NUMBER
+Only reports memory statistics from the last
+.I NUMBER
+files.
+'\"--------------------------------------------------------------------------
+.SS "The obj Subcommand"
+.SO
+.P
+The
+.B scons-time obj
+subcommand displays how many objects of a specific named type
+are created by SCons.
+.P
+The
+.B scons-time obj
+subcommand extracts object counts
+from all the specified file arguments,
+which should be files containing output from
+running SCons with the
+.B --debug=count
+option.
+(Normally, these would be
+.B *.log
+files generated by the
+.B scons-time run
+subcommand.)
+All file name arguments will be
+globbed for on-disk files.
+.P
+If no arguments are specified,
+then object counts
+will be extracted from all
+.B *.log
+files,
+or the subset of them
+with a prefix specified by the
+.B -p
+option.
+.TP
+-C DIR, --chdir=DIR
+Changes to the specified
+.I DIRECTORY
+before looking for the specified files
+(or files that match the specified patterns).
+.TP
+-f FILE, --file=FILE
+Reads configuration information from the specified
+.IR FILE .
+.TP
+-fmt=FORMAT, --format=FORMAT
+Reports the output in the specified
+.IR FORMAT .
+The formats currently supported are
+.B ascii
+(the default)
+and
+.BR gnuplot .
+.TP
+-h, --help
+Displays help text for the
+.B scons-time obj
+subcommand.
+.TP
+-p STRING, --prefix=STRING
+Specifies the prefix string for log files
+from which to extract object counts.
+This will be used to search for log files
+if no arguments are specified on the command line.
+.TP
+--stage=STAGE
+Prints the object count at the end of the specified
+.IR STAGE :
+.B pre-read
+(before the SConscript files are read),
+.B post-read ,
+(after the SConscript files are read),
+.B pre-build
+(before any targets are built)
+or
+.B post-build
+(after any targets are built).
+If no
+.B --stage
+option is specified,
+the default behavior is
+.BR post-build ,
+which reports the final object count during each run.
+.TP
+-t NUMBER, --tail=NUMBER
+Only reports object counts from the last
+.I NUMBER
+files.
+'\"--------------------------------------------------------------------------
+.SS "The run Subcommand"
+.SR
+The
+.B scons-time run
+subcommand is the basic subcommand
+for profiling a specific configuration
+against a version of SCons.
+.P
+The configuration to be tested
+is specified as a list of files
+or directories that will be unpacked or copied
+into a temporary directory
+in which SCons will be invoked.
+The
+.B scons-time run
+subcommand understands file suffixes like
+.BR .tar ,
+.BR .tar.gz ,
+.BR .tgz
+and
+.BR .zip
+and will unpack their contents into a temporary directory.
+If more than one argument is specified,
+each one will be unpacked or copied
+into the temporary directory "on top of"
+the previous archives or directories,
+so the expectation is that multiple
+specified archives share the same directory layout.
+.P
+Once the file or directory arguments are unpacked or
+copied to the temporary directory,
+the
+.B scons-time run
+subcommand runs the
+requested version of SCons
+against the configuration
+three times:
+.TP
+Startup
+SCons is run with the
+.B --help
+option so that just the SConscript files are read,
+and then the default help text is printed.
+This profiles just the perceived "overhead" of starting up SCons
+and processing the SConscript files.
+.TP
+Full build
+SCons is run to build everything specified in the configuration.
+Specific targets to be passed in on the command l ine
+may be specified by the
+.B targets
+keyword in a configuration file; see below for details.
+.TP
+Rebuild
+SCons is run again on the same just-built directory.
+If the dependencies in the SCons configuration are correct,
+this should be an up-to-date, "do nothing" rebuild.
+.P
+Each invocation captures the output log file and a profile.
+.P
+The
+.B scons-time run
+subcommand supports the following options:
+.TP
+--aegis=PROJECT
+Specifies the Aegis
+.I PROJECT
+from which the
+version(s) of
+.B scons
+being timed will be extracted.
+When
+.B --aegis
+is specified, the
+.BI --number= NUMBER
+option specifies delta numbers
+that will be tested.
+Output from each invocation run will be placed in file
+names that match the Aegis delta numbers.
+If the
+.B --number=
+option is not specified,
+then the default behavior is to time the
+tip of the specified
+.IR PROJECT .
+.TP
+-f FILE, --file=FILE
+Reads configuration information from the specified
+.IR FILE .
+This often provides a more convenient way to specify and
+collect parameters associated with a specific timing configuration
+than specifying them on the command line.
+See the
+.B CONFIGURATION FILE
+section below
+for information about the configuration file parameters.
+.TP
+-h, --help
+Displays help text for the
+.B scons-time run
+subcommand.
+.TP
+-n, --no-exec
+Do not execute commands,
+just printing the command-line equivalents of what would be executed.
+Note that the
+.B scons-time
+script actually executes its actions in Python,
+where possible,
+for portability.
+The commands displayed are UNIX
+.I equivalents
+of what it's doing.
+.TP
+--number=NUMBER
+Specifies the run number to be used in the names of
+the log files and profile outputs generated by this run.
+.IP
+When used in conjuction with the
+.BI --aegis= PROJECT
+option,
+.I NUMBER
+specifies one or more comma-separated Aegis delta numbers
+that will be retrieved automatically from the specified Aegis
+.IR PROJECT .
+.IP
+When used in conjuction with the
+.BI --svn= URL
+option,
+.I NUMBER
+specifies one or more comma-separated Subversion revision numbers
+that will be retrieved automatically from the Subversion
+repository at the specified
+.IR URL .
+Ranges of delta or revision numbers
+may be specified be separating two numbers
+with a hyphen
+.RB ( \- ).
+.P
+Example:
+.ES
+% scons-time run --svn=http://scons.tigris.org/svn/trunk --num=1247,1249-1252 .
+.EE
+.TP
+-p STRING, --prefix=STRING
+Specifies the prefix string to be used for all of the log files
+and profiles generated by this run.
+The default is derived from the first
+specified argument:
+if the first argument is a directory,
+the default prefix is the name of the directory;
+if the first argument is an archive
+(tar or zip file),
+the default prefix is the the base name of the archive,
+that is, what remains after stripping the archive suffix
+.RB ( .tgz ", " .tar.gz " or " .zip ).
+.TP
+--python=PYTHON
+Specifies a path to the Python executable to be used
+for the timing runs.
+The default is to use the same Python executable that
+is running the
+.B scons-time
+command itself.
+.TP
+-q, --quiet
+Suppresses display of the command lines being executed.
+.TP
+-s DIR, --subdir=DIR
+Specifies the name of directory or subdirectory
+from which the commands should be executed.
+The default is XXX
+.TP
+--scons=SCONS
+Specifies a path to the SCons script to be used
+for the timing runs.
+The default is XXX
+.TP
+--svn=URL, --subversion=URL
+Specifies the
+.I URL
+of the Subversion repository from which the
+version(s) of
+.B scons
+being timed will be extracted.
+When
+.B --svn
+is specified, the
+.BI --number= NUMBER
+option specifies revision numbers
+that will be tested.
+Output from each invocation run will be placed in file
+names that match the Subversion revision numbers.
+If the
+.B --number=
+option is not specified,
+then the default behavior is to time the
+.B HEAD
+of the specified
+.IR URL .
+.TP
+-v, --verbose
+Displays the output from individual commands to the screen
+(in addition to capturing the output in log files).
+'\"--------------------------------------------------------------------------
+.SS "The time Subcommand"
+.ST
+.P
+The
+.B scons-time time
+subcommand displays SCons execution times
+as reported by the
+.B scons --debug=time
+option.
+.P
+The
+.B scons-time time
+subcommand extracts SCons timing
+from all the specified file arguments,
+which should be files containing output from
+running SCons with the
+.B --debug=time
+option.
+(Normally, these would be
+.B *.log
+files generated by the
+.B scons-time run
+subcommand.)
+All file name arguments will be
+globbed for on-disk files.
+.P
+If no arguments are specified,
+then execution timings
+will be extracted from all
+.B *.log
+files,
+or the subset of them
+with a prefix specified by the
+.B -p
+option.
+.TP
+-C DIR, --chdir=DIR
+Changes to the specified
+.I DIRECTORY
+before looking for the specified files
+(or files that match the specified patterns).
+.TP
+-f FILE, --file=FILE
+Reads configuration information from the specified
+.IR FILE .
+.TP
+-fmt=FORMAT, --format=FORMAT
+Reports the output in the specified
+.IR FORMAT .
+The formats currently supported are
+.B ascii
+(the default)
+and
+.BR gnuplot .
+.TP
+-h, --help
+Displays help text for the
+.B scons-time time
+subcommand.
+.TP
+-p STRING, --prefix=STRING
+Specifies the prefix string for log files
+from which to extract execution timings.
+This will be used to search for log files
+if no arguments are specified on the command line.
+.TP
+-t NUMBER, --tail=NUMBER
+Only reports object counts from the last
+.I NUMBER
+files.
+.TP
+--which=WHICH
+Prints the execution time for the specified
+.IR WHICH
+value:
+.B total
+(the total execution time),
+.B SConscripts
+(total execution time for the SConscript files themselves),
+.B SCons
+(exectuion time in SCons code itself)
+or
+.B commands
+(execution time of the commands and other actions
+used to build targets).
+If no
+.B --which
+option is specified,
+the default behavior is
+.BR total ,
+which reports the total execution time for each run.
+'\"==========================================================================
+.SH CONFIGURATION FILE
+Various
+.B scons-time
+subcommands can read information from a specified
+configuration file when passed the
+.B \-f
+or
+.B \--file
+options.
+The configuration file is actually executed as a Python script.
+Setting Python variables in the configuration file
+controls the behavior of the
+.B scons-time
+script more conveniently than having to specify
+command-line options or arguments for every run,
+and provides a handy way to "shrink-wrap"
+the necessary information for producing (and reporting)
+consistent timing runs for a given configuration.
+.TP
+.B aegis
+The Aegis executable for extracting deltas.
+The default is simply
+.BR aegis .
+.TP
+.B aegis_project
+The Aegis project from which deltas should be extracted.
+The default is whatever is specified
+with the
+.B --aegis=
+command-line option.
+.TP
+.B archive_list
+A list of archives (files or directories)
+that will be copied to the temporary directory
+in which SCons will be invoked.
+.BR .tar ,
+.BR .tar.gz ,
+.BR .tgz
+and
+.BR .zip
+files will have their contents unpacked in
+the temporary directory.
+Directory trees and files will be copied as-is.
+.TP
+.B initial_commands
+A list of commands that will be executed
+before the actual timed
+.B scons
+runs.
+This can be used for commands that are necessary
+to prepare the source tree\-for example,
+creating a configuration file
+that should not be part of the timed run.
+.TP
+.B key_location
+The location of the key on Gnuplot graphing information
+generated with the
+.BR --format=gnuplot
+option.
+The default is
+.BR "bottom left" .
+.TP
+.B prefix
+The file name prefix to be used when
+running or extracting timing for this configuration.
+.TP
+.B python
+The path name of the Python executable
+to be used when running or extracting information
+for this configuration.
+The default is the same version of Python
+used to run the SCons
+.TP
+.B scons
+The path name of the SCons script to be used
+when running or extracting information
+for this configuration.
+The default is simply
+.BR scons .
+.TP
+.B scons_flags
+The
+.B scons
+flags used when running SCons to collect timing information.
+The default value is
+.BR "--debug=count --debug=memory --debug=time --debug=memoizer" .
+.TP
+.B scons_lib_dir
+.TP
+.B scons_wrapper
+.TP
+.B startup_targets
+.TP
+.B subdir
+The subdirectory of the project into which the
+.B scons-time
+script should change
+before executing the SCons commands to time.
+.TP
+.B subversion_url
+The Subversion URL from
+.TP
+.B svn
+The subversion executable used to
+check out revisions of SCons to be timed.
+The default is simple
+.BR svn .
+.TP
+.B svn_co_flag
+.TP
+.B tar
+.TP
+.B targets
+A string containing the targets that should be added to
+the command line of every timed
+.B scons
+run.
+This can be used to restrict what's being timed to a
+subset of the full build for the configuration.
+.TP
+.B targets0
+.TP
+.B targets1
+.TP
+.B targets2
+.TP
+.B title
+.TP
+.B unzip
+.TP
+.B verbose
+.TP
+.B vertical_bars
+'\"--------------------------------------------------------------------------
+.SS Example
+Here is an example
+.B scons-time
+configuration file
+for a hypothetical sample project:
+.P
+.ES
+# The project doesn't use SCons natively (yet), so we're
+# timing a separate set of SConscript files that we lay
+# on top of the vanilla unpacked project tarball.
+arguments = ['project-1.2.tgz', 'project-SConscripts.tar']
+
+# The subdirectory name contains the project version number,
+# so tell scons-time to chdir there before building.
+subdir = 'project-1.2'
+
+# Set the prefix so output log files and profiles are named:
+# project-000-[012].{log,prof}
+# project-001-[012].{log,prof}
+# etc.
+prefix = 'project'
+
+# The SConscript files being tested don't do any SConf
+# configuration, so run their normal ./configure script
+# before we invoke SCons.
+initial_commands = [
+ './configure',
+]
+
+# Only time building the bin/project executable.
+targets = 'bin/project'
+
+# Time against SCons revisions of the branches/core branch
+subversion_url = 'http://scons.tigris.org/svn/scons/branches/core'
+.EE
+'\"==========================================================================
+.SH ENVIRONMENT
+The
+.B scons-time
+script uses the following environment variables:
+.TP
+.B PRESERVE
+If this value is set,
+the
+.B scons-time
+script will
+.I not
+remove the temporary directory or directories
+in which it builds the specified configuration
+or downloads a specific version of SCons.
+'\"==========================================================================
+.SH "SEE ALSO"
+.BR gnuplot (1),
+.BR scons (1)
+
+.SH AUTHORS
+Steven Knight <knight at baldmt dot com>
diff --git a/doc/man/scons.1 b/doc/man/scons.1
new file mode 100644
index 0000000..f57169b
--- /dev/null
+++ b/doc/man/scons.1
@@ -0,0 +1,10149 @@
+.\" Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+.\"
+.\" 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.
+.\"
+.\" doc/man/scons.1 4577 2009/12/27 19:44:43 scons
+.\"
+.TH SCONS 1 "December 2009"
+.\" ES - Example Start - indents and turns off line fill
+.rm ES
+.de ES
+.RS
+.nf
+..
+.\" EE - Example End - ends indent and turns line fill back on
+.rm EE
+.de EE
+.fi
+.RE
+..
+.SH NAME
+scons \- a software construction tool
+.SH SYNOPSIS
+.B scons
+[
+.IR options ...
+]
+[
+.IR name = val ...
+]
+[
+.IR targets ...
+]
+.SH DESCRIPTION
+
+The
+.B scons
+utility builds software (or other files) by determining which
+component pieces must be rebuilt and executing the necessary commands to
+rebuild them.
+
+By default,
+.B scons
+searches for a file named
+.IR SConstruct ,
+.IR Sconstruct ,
+or
+.I sconstruct
+(in that order) in the current directory and reads its
+configuration from the first file found.
+An alternate file name may be
+specified via the
+.B -f
+option.
+
+The
+.I SConstruct
+file can specify subsidiary
+configuration files using the
+.B SConscript()
+function.
+By convention,
+these subsidiary files are named
+.IR SConscript ,
+although any name may be used.
+(Because of this naming convention,
+the term "SConscript files"
+is sometimes used to refer
+generically to all
+.B scons
+configuration files,
+regardless of actual file name.)
+
+The configuration files
+specify the target files to be built, and
+(optionally) the rules to build those targets. Reasonable default
+rules exist for building common software components (executable
+programs, object files, libraries), so that for most software
+projects, only the target and input files need be specified.
+
+Before reading the
+.I SConstruct
+file,
+.B scons
+looks for a directory named
+.I site_scons
+in the directory containing the
+.I SConstruct
+file; if it exists,
+.I site_scons
+is added to sys.path,
+the file
+.IR site_scons/site_init.py ,
+is evaluated if it exists,
+and the directory
+.I site_scons/site_tools
+is added to the default toolpath if it exist.
+See the
+.I --no-site-dir
+and
+.I --site-dir
+options for more details.
+
+.B scons
+reads and executes the SConscript files as Python scripts,
+so you may use normal Python scripting capabilities
+(such as flow control, data manipulation, and imported Python libraries)
+to handle complicated build situations.
+.BR scons ,
+however, reads and executes all of the SConscript files
+.I before
+it begins building any targets.
+To make this obvious,
+.B scons
+prints the following messages about what it is doing:
+
+.ES
+$ scons foo.out
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+cp foo.in foo.out
+scons: done building targets.
+$
+.EE
+
+The status messages
+(everything except the line that reads "cp foo.in foo.out")
+may be suppressed using the
+.B -Q
+option.
+
+.B scons
+does not automatically propagate
+the external environment used to execute
+.B scons
+to the commands used to build target files.
+This is so that builds will be guaranteed
+repeatable regardless of the environment
+variables set at the time
+.B scons
+is invoked.
+This also means that if the compiler or other commands
+that you want to use to build your target files
+are not in standard system locations,
+.B scons
+will not find them unless
+you explicitly set the PATH
+to include those locations.
+Whenever you create an
+.B scons
+construction environment,
+you can propagate the value of PATH
+from your external environment as follows:
+
+.ES
+import os
+env = Environment(ENV = {'PATH' : os.environ['PATH']})
+.EE
+
+Similarly, if the commands use external environment variables
+like $PATH, $HOME, $JAVA_HOME, $LANG, $SHELL, $TERM, etc.,
+these variables can also be explicitly propagated:
+
+.ES
+import os
+env = Environment(ENV = {'PATH' : os.environ['PATH'],
+ 'HOME' : os.environ['HOME']})
+.EE
+
+Or you may explicitly propagate the invoking user's
+complete external environment:
+
+.ES
+import os
+env = Environment(ENV = os.environ)
+.EE
+
+This comes at the expense of making your build
+dependent on the user's environment being set correctly,
+but it may be more convenient for many configurations.
+
+.B scons
+can scan known input files automatically for dependency
+information (for example, #include statements
+in C or C++ files) and will rebuild dependent files appropriately
+whenever any "included" input file changes.
+.B scons
+supports the
+ability to define new scanners for unknown input file types.
+
+.B scons
+knows how to fetch files automatically from
+SCCS or RCS subdirectories
+using SCCS, RCS or BitKeeper.
+
+.B scons
+is normally executed in a top-level directory containing a
+.I SConstruct
+file, optionally specifying
+as command-line arguments
+the target file or files to be built.
+
+By default, the command
+
+.ES
+scons
+.EE
+
+will build all target files in or below the current directory.
+Explicit default targets
+(to be built when no targets are specified on the command line)
+may be defined the SConscript file(s)
+using the
+.B Default()
+function, described below.
+
+Even when
+.B Default()
+targets are specified in the SConscript file(s),
+all target files in or below the current directory
+may be built by explicitly specifying
+the current directory (.)
+as a command-line target:
+
+.ES
+scons .
+.EE
+
+Building all target files,
+including any files outside of the current directory,
+may be specified by supplying a command-line target
+of the root directory (on POSIX systems):
+
+.ES
+scons /
+.EE
+
+or the path name(s) of the volume(s) in which all the targets
+should be built (on Windows systems):
+
+.ES
+scons C:\\ D:\\
+.EE
+
+To build only specific targets,
+supply them as command-line arguments:
+
+.ES
+scons foo bar
+.EE
+
+in which case only the specified targets will be built
+(along with any derived files on which they depend).
+
+Specifying "cleanup" targets in SConscript files is not usually necessary.
+The
+.B -c
+flag removes all files
+necessary to build the specified target:
+
+.ES
+scons -c .
+.EE
+
+to remove all target files, or:
+
+.ES
+scons -c build export
+.EE
+
+to remove target files under build and export.
+Additional files or directories to remove can be specified using the
+.BR Clean()
+function.
+Conversely, targets that would normally be removed by the
+.B -c
+invocation
+can be prevented from being removed by using the
+.BR NoClean ()
+function.
+
+A subset of a hierarchical tree may be built by
+remaining at the top-level directory (where the
+.I SConstruct
+file lives) and specifying the subdirectory as the target to be
+built:
+
+.ES
+scons src/subdir
+.EE
+
+or by changing directory and invoking scons with the
+.B -u
+option, which traverses up the directory
+hierarchy until it finds the
+.I SConstruct
+file, and then builds
+targets relatively to the current subdirectory:
+
+.ES
+cd src/subdir
+scons -u .
+.EE
+
+.B scons
+supports building multiple targets in parallel via a
+.B -j
+option that takes, as its argument, the number
+of simultaneous tasks that may be spawned:
+
+.ES
+scons -j 4
+.EE
+
+builds four targets in parallel, for example.
+
+.B scons
+can maintain a cache of target (derived) files that can
+be shared between multiple builds. When caching is enabled in a
+SConscript file, any target files built by
+.B scons
+will be copied
+to the cache. If an up-to-date target file is found in the cache, it
+will be retrieved from the cache instead of being rebuilt locally.
+Caching behavior may be disabled and controlled in other ways by the
+.BR --cache-force ,
+.BR --cache-disable ,
+and
+.B --cache-show
+command-line options. The
+.B --random
+option is useful to prevent multiple builds
+from trying to update the cache simultaneously.
+
+Values of variables to be passed to the SConscript file(s)
+may be specified on the command line:
+
+.ES
+scons debug=1 .
+.EE
+
+These variables are available in SConscript files
+through the ARGUMENTS dictionary,
+and can be used in the SConscript file(s) to modify
+the build in any way:
+
+.ES
+if ARGUMENTS.get('debug', 0):
+ env = Environment(CCFLAGS = '-g')
+else:
+ env = Environment()
+.EE
+
+The command-line variable arguments are also available
+in the ARGLIST list,
+indexed by their order on the command line.
+This allows you to process them in order rather than by name,
+if necessary.
+ARGLIST[0] returns a tuple
+containing (argname, argvalue).
+A Python exception is thrown if you
+try to access a list member that
+does not exist.
+
+.B scons
+requires Python version 1.5.2 or later.
+There should be no other dependencies or requirements to run
+.B scons.
+
+.\" The following paragraph reflects the default tool search orders
+.\" currently in SCons/Tool/__init__.py. If any of those search orders
+.\" change, this documentation should change, too.
+By default,
+.B scons
+knows how to search for available programming tools
+on various systems.
+On Windows systems,
+.B scons
+searches in order for the
+Microsoft Visual C++ tools,
+the MinGW tool chain,
+the Intel compiler tools,
+and the PharLap ETS compiler.
+On OS/2 systems,
+.B scons
+searches in order for the
+OS/2 compiler,
+the GCC tool chain,
+and the Microsoft Visual C++ tools,
+On SGI IRIX, IBM AIX, Hewlett Packard HP-UX, and Sun Solaris systems,
+.B scons
+searches for the native compiler tools
+(MIPSpro, Visual Age, aCC, and Forte tools respectively)
+and the GCC tool chain.
+On all other platforms,
+including POSIX (Linux and UNIX) platforms,
+.B scons
+searches in order
+for the GCC tool chain,
+the Microsoft Visual C++ tools,
+and the Intel compiler tools.
+You may, of course, override these default values
+by appropriate configuration of
+Environment construction variables.
+
+.SH OPTIONS
+In general,
+.B scons
+supports the same command-line options as GNU
+.BR make ,
+and many of those supported by
+.BR cons .
+
+.TP
+-b
+Ignored for compatibility with non-GNU versions of
+.BR make.
+
+.TP
+-c, --clean, --remove
+Clean up by removing all target files for which a construction
+command is specified.
+Also remove any files or directories associated to the construction command
+using the
+.BR Clean ()
+function.
+Will not remove any targets specified by the
+.BR NoClean ()
+function.
+
+.TP
+.RI --cache-debug= file
+Print debug information about the
+.BR CacheDir ()
+derived-file caching
+to the specified
+.IR file .
+If
+.I file
+is
+.B \-
+(a hyphen),
+the debug information are printed to the standard output.
+The printed messages describe what signature file names are
+being looked for in, retrieved from, or written to the
+.BR CacheDir ()
+directory tree.
+
+.TP
+--cache-disable, --no-cache
+Disable the derived-file caching specified by
+.BR CacheDir ().
+.B scons
+will neither retrieve files from the cache
+nor copy files to the cache.
+
+.TP
+--cache-force, --cache-populate
+When using
+.BR CacheDir (),
+populate a cache by copying any already-existing, up-to-date
+derived files to the cache,
+in addition to files built by this invocation.
+This is useful to populate a new cache with
+all the current derived files,
+or to add to the cache any derived files
+recently built with caching disabled via the
+.B --cache-disable
+option.
+
+.TP
+--cache-show
+When using
+.BR CacheDir ()
+and retrieving a derived file from the cache,
+show the command
+that would have been executed to build the file,
+instead of the usual report,
+"Retrieved `file' from cache."
+This will produce consistent output for build logs,
+regardless of whether a target
+file was rebuilt or retrieved from the cache.
+
+.TP
+.RI --config= mode
+This specifies how the
+.B Configure
+call should use or generate the
+results of configuration tests.
+The option should be specified from
+among the following choices:
+
+.TP
+--config=auto
+scons will use its normal dependency mechanisms
+to decide if a test must be rebuilt or not.
+This saves time by not running the same configuration tests
+every time you invoke scons,
+but will overlook changes in system header files
+or external commands (such as compilers)
+if you don't specify those dependecies explicitly.
+This is the default behavior.
+
+.TP
+--config=force
+If this option is specified,
+all configuration tests will be re-run
+regardless of whether the
+cached results are out of date.
+This can be used to explicitly
+force the configuration tests to be updated
+in response to an otherwise unconfigured change
+in a system header file or compiler.
+
+.TP
+--config=cache
+If this option is specified,
+no configuration tests will be rerun
+and all results will be taken from cache.
+Note that scons will still consider it an error
+if --config=cache is specified
+and a necessary test does not
+yet have any results in the cache.
+
+.TP
+.RI "-C" " directory" ", --directory=" directory
+Change to the specified
+.I directory
+before searching for the
+.IR SConstruct ,
+.IR Sconstruct ,
+or
+.I sconstruct
+file, or doing anything
+else. Multiple
+.B -C
+options are interpreted
+relative to the previous one, and the right-most
+.B -C
+option wins. (This option is nearly
+equivalent to
+.BR "-f directory/SConstruct" ,
+except that it will search for
+.IR SConstruct ,
+.IR Sconstruct ,
+or
+.I sconstruct
+in the specified directory.)
+
+.\" .TP
+.\" -d
+.\" Display dependencies while building target files. Useful for
+.\" figuring out why a specific file is being rebuilt, as well as
+.\" general debugging of the build process.
+
+.TP
+-D
+Works exactly the same way as the
+.B -u
+option except for the way default targets are handled.
+When this option is used and no targets are specified on the command line,
+all default targets are built, whether or not they are below the current
+directory.
+
+.TP
+.RI --debug= type
+Debug the build process.
+.I type
+specifies what type of debugging:
+
+.TP
+--debug=count
+Print how many objects are created
+of the various classes used internally by SCons
+before and after reading the SConscript files
+and before and after building targets.
+This is not supported when run under Python versions earlier than 2.1,
+when SCons is executed with the Python
+.B -O
+(optimized) option,
+or when the SCons modules
+have been compiled with optimization
+(that is, when executing from
+.B *.pyo
+files).
+
+.TP
+--debug=dtree
+A synonym for the newer
+.B --tree=derived
+option.
+This will be deprecated in some future release
+and ultimately removed.
+
+.TP
+--debug=explain
+Print an explanation of precisely why
+.B scons
+is deciding to (re-)build any targets.
+(Note: this does not print anything
+for targets that are
+.I not
+rebuilt.)
+
+.TP
+--debug=findlibs
+Instruct the scanner that searches for libraries
+to print a message about each potential library
+name it is searching for,
+and about the actual libraries it finds.
+
+.TP
+--debug=includes
+Print the include tree after each top-level target is built.
+This is generally used to find out what files are included by the sources
+of a given derived file:
+
+.ES
+$ scons --debug=includes foo.o
+.EE
+
+.TP
+--debug=memoizer
+Prints a summary of hits and misses using the Memoizer,
+an internal subsystem that counts
+how often SCons uses cached values in memory
+instead of recomputing them each time they're needed.
+Only available when using Python 2.2 or later.
+
+.TP
+--debug=memory
+Prints how much memory SCons uses
+before and after reading the SConscript files
+and before and after building targets.
+
+.TP
+--debug=nomemoizer
+A deprecated option preserved for backwards compatibility.
+
+.TP
+--debug=objects
+Prints a list of the various objects
+of the various classes used internally by SCons.
+This only works when run under Python 2.1 or later.
+
+.TP
+--debug=pdb
+Re-run SCons under the control of the
+.RI pdb
+Python debugger.
+
+.TP
+--debug=presub
+Print the raw command line used to build each target
+before the construction environment variables are substituted.
+Also shows which targets are being built by this command.
+Output looks something like this:
+.ES
+$ scons --debug=presub
+Building myprog.o with action(s):
+ $SHCC $SHCFLAGS $SHCCFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES
+\&...
+.EE
+
+.TP
+--debug=stacktrace
+Prints an internal Python stack trace
+when encountering an otherwise unexplained error.
+
+.TP
+--debug=stree
+A synonym for the newer
+.B --tree=all,status
+option.
+This will be deprecated in some future release
+and ultimately removed.
+
+.TP
+--debug=time
+Prints various time profiling information:
+the time spent executing each individual build command;
+the total build time (time SCons ran from beginning to end);
+the total time spent reading and executing SConscript files;
+the total time spent SCons itself spend running
+(that is, not counting reading and executing SConscript files);
+and both the total time spent executing all build commands
+and the elapsed wall-clock time spent executing those build commands.
+(When
+.B scons
+is executed without the
+.B -j
+option,
+the elapsed wall-clock time will typically
+be slightly longer than the total time spent
+executing all the build commands,
+due to the SCons processing that takes place
+in between executing each command.
+When
+.B scons
+is executed
+.I with
+the
+.B -j
+option,
+and your build configuration allows good parallelization,
+the elapsed wall-clock time should
+be significantly smaller than the
+total time spent executing all the build commands,
+since multiple build commands and
+intervening SCons processing
+should take place in parallel.)
+
+.TP
+--debug=tree
+A synonym for the newer
+.B --tree=all
+option.
+This will be deprecated in some future release
+and ultimately removed.
+
+.TP
+.RI --diskcheck= types
+Enable specific checks for
+whether or not there is a file on disk
+where the SCons configuration expects a directory
+(or vice versa),
+and whether or not RCS or SCCS sources exist
+when searching for source and include files.
+The
+.I types
+argument can be set to:
+.BR all ,
+to enable all checks explicitly
+(the default behavior);
+.BR none ,
+to disable all such checks;
+.BR match ,
+to check that files and directories on disk
+match SCons' expected configuration;
+.BR rcs ,
+to check for the existence of an RCS source
+for any missing source or include files;
+.BR sccs ,
+to check for the existence of an SCCS source
+for any missing source or include files.
+Multiple checks can be specified separated by commas;
+for example,
+.B --diskcheck=sccs,rcs
+would still check for SCCS and RCS sources,
+but disable the check for on-disk matches of files and directories.
+Disabling some or all of these checks
+can provide a performance boost for large configurations,
+or when the configuration will check for files and/or directories
+across networked or shared file systems,
+at the slight increased risk of an incorrect build
+or of not handling errors gracefully
+(if include files really should be
+found in SCCS or RCS, for example,
+or if a file really does exist
+where the SCons configuration expects a directory).
+
+.TP
+.RI --duplicate= ORDER
+There are three ways to duplicate files in a build tree: hard links,
+soft (symbolic) links and copies. The default behaviour of SCons is to
+prefer hard links to soft links to copies. You can specify different
+behaviours with this option.
+.IR ORDER
+must be one of
+.IR hard-soft-copy
+(the default),
+.IR soft-hard-copy ,
+.IR hard-copy ,
+.IR soft-copy
+or
+.IR copy .
+SCons will attempt to duplicate files using
+the mechanisms in the specified order.
+
+.\" .TP
+.\" -e, --environment-overrides
+.\" Variables from the execution environment override construction
+.\" variables from the SConscript files.
+
+.TP
+.RI -f " file" ", --file=" file ", --makefile=" file ", --sconstruct=" file
+Use
+.I file
+as the initial SConscript file.
+Multiple
+.B -f
+options may be specified,
+in which case
+.B scons
+will read all of the specified files.
+
+.TP
+-h, --help
+Print a local help message for this build, if one is defined in
+the SConscript file(s), plus a line that describes the
+.B -H
+option for command-line option help. If no local help message
+is defined, prints the standard help message about command-line
+options. Exits after displaying the appropriate message.
+
+.TP
+-H, --help-options
+Print the standard help message about command-line options and
+exit.
+
+.TP
+-i, --ignore-errors
+Ignore all errors from commands executed to rebuild files.
+
+.TP
+.RI -I " directory" ", --include-dir=" directory
+Specifies a
+.I directory
+to search for
+imported Python modules. If several
+.B -I
+options
+are used, the directories are searched in the order specified.
+
+.TP
+--implicit-cache
+Cache implicit dependencies.
+This causes
+.B scons
+to use the implicit (scanned) dependencies
+from the last time it was run
+instead of scanning the files for implicit dependencies.
+This can significantly speed up SCons,
+but with the following limitations:
+.IP
+.B scons
+will not detect changes to implicit dependency search paths
+(e.g.
+.BR CPPPATH ", " LIBPATH )
+that would ordinarily
+cause different versions of same-named files to be used.
+.IP
+.B scons
+will miss changes in the implicit dependencies
+in cases where a new implicit
+dependency is added earlier in the implicit dependency search path
+(e.g.
+.BR CPPPATH ", " LIBPATH )
+than a current implicit dependency with the same name.
+
+.TP
+--implicit-deps-changed
+Forces SCons to ignore the cached implicit dependencies. This causes the
+implicit dependencies to be rescanned and recached. This implies
+.BR --implicit-cache .
+
+.TP
+--implicit-deps-unchanged
+Force SCons to ignore changes in the implicit dependencies.
+This causes cached implicit dependencies to always be used.
+This implies
+.BR --implicit-cache .
+
+.TP
+--interactive
+Starts SCons in interactive mode.
+The SConscript files are read once and a
+.B "scons>>>"
+prompt is printed.
+Targets may now be rebuilt by typing commands at interactive prompt
+without having to re-read the SConscript files
+and re-initialize the dependency graph from scratch.
+
+SCons interactive mode supports the following commands:
+
+.RS 10
+.TP 6
+.BI build "[OPTIONS] [TARGETS] ..."
+Builds the specified
+.I TARGETS
+(and their dependencies)
+with the specified
+SCons command-line
+.IR OPTIONS .
+.B b
+and
+.B scons
+are synonyms.
+
+The following SCons command-line options affect the
+.B build
+command:
+
+.ES
+--cache-debug=FILE
+--cache-disable, --no-cache
+--cache-force, --cache-populate
+--cache-show
+--debug=TYPE
+-i, --ignore-errors
+-j N, --jobs=N
+-k, --keep-going
+-n, --no-exec, --just-print, --dry-run, --recon
+-Q
+-s, --silent, --quiet
+--taskmastertrace=FILE
+--tree=OPTIONS
+.EE
+
+.IP "" 6
+Any other SCons command-line options that are specified
+do not cause errors
+but have no effect on the
+.B build
+command
+(mainly because they affect how the SConscript files are read,
+which only happens once at the beginning of interactive mode).
+
+.TP 6
+.BI clean "[OPTIONS] [TARGETS] ..."
+Cleans the specified
+.I TARGETS
+(and their dependencies)
+with the specified options.
+.B c
+is a synonym.
+This command is itself a synonym for
+.B "build --clean"
+
+.TP 6
+.BI exit
+Exits SCons interactive mode.
+You can also exit by terminating input
+(CTRL+D on UNIX or Linux systems,
+CTRL+Z on Windows systems).
+
+.TP 6
+.BI help "[COMMAND]"
+Provides a help message about
+the commands available in SCons interactive mode.
+If
+.I COMMAND
+is specified,
+.B h
+and
+.B ?
+are synonyms.
+
+.TP 6
+.BI shell "[COMMANDLINE]"
+Executes the specified
+.I COMMANDLINE
+in a subshell.
+If no
+.I COMMANDLINE
+is specified,
+executes the interactive command interpreter
+specified in the
+.B SHELL
+environment variable
+(on UNIX and Linux systems)
+or the
+.B COMSPEC
+environment variable
+(on Windows systems).
+.B sh
+and
+.B !
+are synonyms.
+
+.TP 6
+.B version
+Prints SCons version information.
+.RE
+
+.IP
+An empty line repeats the last typed command.
+Command-line editing can be used if the
+.B readline
+module is available.
+
+.ES
+$ scons --interactive
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons>>> build -n prog
+scons>>> exit
+.EE
+
+.TP
+.RI -j " N" ", --jobs=" N
+Specifies the number of jobs (commands) to run simultaneously.
+If there is more than one
+.B -j
+option, the last one is effective.
+.\" ??? If the
+.\" .B -j
+.\" option
+.\" is specified without an argument,
+.\" .B scons
+.\" will not limit the number of
+.\" simultaneous jobs.
+
+.TP
+-k, --keep-going
+Continue as much as possible after an error. The target that
+failed and those that depend on it will not be remade, but other
+targets specified on the command line will still be processed.
+
+.\" .TP
+.\" .RI -l " N" ", --load-average=" N ", --max-load=" N
+.\" No new jobs (commands) will be started if
+.\" there are other jobs running and the system load
+.\" average is at least
+.\" .I N
+.\" (a floating-point number).
+
+.\"
+.\" .TP
+.\" --list-derived
+.\" List derived files (targets, dependencies) that would be built,
+.\" but do not build them.
+.\" [XXX This can probably go away with the right
+.\" combination of other options. Revisit this issue.]
+.\"
+.\" .TP
+.\" --list-actions
+.\" List derived files that would be built, with the actions
+.\" (commands) that build them. Does not build the files.
+.\" [XXX This can probably go away with the right
+.\" combination of other options. Revisit this issue.]
+.\"
+.\" .TP
+.\" --list-where
+.\" List derived files that would be built, plus where the file is
+.\" defined (file name and line number). Does not build the files.
+.\" [XXX This can probably go away with the right
+.\" combination of other options. Revisit this issue.]
+
+.TP
+-m
+Ignored for compatibility with non-GNU versions of
+.BR make .
+
+.TP
+.RI --max-drift= SECONDS
+Set the maximum expected drift in the modification time of files to
+.IR SECONDS .
+This value determines how long a file must be unmodified
+before its cached content signature
+will be used instead of
+calculating a new content signature (MD5 checksum)
+of the file's contents.
+The default value is 2 days, which means a file must have a
+modification time of at least two days ago in order to have its
+cached content signature used.
+A negative value means to never cache the content
+signature and to ignore the cached value if there already is one. A value
+of 0 means to always use the cached signature,
+no matter how old the file is.
+
+.TP
+.RI --md5-chunksize= KILOBYTES
+Set the block size used to compute MD5 signatures to
+.IR KILOBYTES .
+This value determines the size of the chunks which are read in at once when
+computing MD5 signatures. Files below that size are fully stored in memory
+before performing the signature computation while bigger files are read in
+block-by-block. A huge block-size leads to high memory consumption while a very
+small block-size slows down the build considerably.
+
+The default value is to use a chunk size of 64 kilobytes, which should
+be appropriate for most uses.
+
+.TP
+-n, --just-print, --dry-run, --recon
+No execute. Print the commands that would be executed to build
+any out-of-date target files, but do not execute the commands.
+
+.TP
+.RI --no-site-dir
+Prevents the automatic addition of the standard
+.I site_scons
+dir to
+.IR sys.path .
+Also prevents loading the
+.I site_scons/site_init.py
+module if it exists, and prevents adding
+.I site_scons/site_tools
+to the toolpath.
+
+.\" .TP
+.\" .RI -o " file" ", --old-file=" file ", --assume-old=" file
+.\" Do not rebuild
+.\" .IR file ,
+.\" and do
+.\" not rebuild anything due to changes in the contents of
+.\" .IR file .
+.\" .TP
+.\" .RI --override " file"
+.\" Read values to override specific build environment variables
+.\" from the specified
+.\" .IR file .
+.\" .TP
+.\" -p
+.\" Print the data base (construction environments,
+.\" Builder and Scanner objects) that are defined
+.\" after reading the SConscript files.
+.\" After printing, a normal build is performed
+.\" as usual, as specified by other command-line options.
+.\" This also prints version information
+.\" printed by the
+.\" .B -v
+.\" option.
+.\"
+.\" To print the database without performing a build do:
+.\"
+.\" .ES
+.\" scons -p -q
+.\" .EE
+
+.TP
+.RI --profile= file
+Run SCons under the Python profiler
+and save the results in the specified
+.IR file .
+The results may be analyzed using the Python
+pstats module.
+
+.TP
+-q, --question
+Do not run any commands, or print anything. Just return an exit
+status that is zero if the specified targets are already up to
+date, non-zero otherwise.
+.TP
+-Q
+Quiets SCons status messages about
+reading SConscript files,
+building targets
+and entering directories.
+Commands that are executed
+to rebuild target files are still printed.
+
+.\" .TP
+.\" -r, -R, --no-builtin-rules, --no-builtin-variables
+.\" Clear the default construction variables. Construction
+.\" environments that are created will be completely empty.
+
+.TP
+--random
+Build dependencies in a random order. This is useful when
+building multiple trees simultaneously with caching enabled,
+to prevent multiple builds from simultaneously trying to build
+or retrieve the same target files.
+
+.TP
+-s, --silent, --quiet
+Silent. Do not print commands that are executed to rebuild
+target files.
+Also suppresses SCons status messages.
+
+.TP
+-S, --no-keep-going, --stop
+Ignored for compatibility with GNU
+.BR make .
+
+.TP
+.RI --site-dir= dir
+Uses the named dir as the site dir rather than the default
+.I site_scons
+dir. This dir will get prepended to
+.IR sys.path ,
+the module
+.IR dir /site_init.py
+will get loaded if it exists, and
+.IR dir /site_tools
+will get added to the default toolpath.
+
+.TP
+.RI --stack-size= KILOBYTES
+Set the size stack used to run threads to
+.IR KILOBYTES .
+This value determines the stack size of the threads used to run jobs.
+These are the threads that execute the actions of the builders for the
+nodes that are out-of-date.
+Note that this option has no effect unless the
+.B num_jobs
+option, which corresponds to -j and --jobs, is larger than one. Using
+a stack size that is too small may cause stack overflow errors. This
+usually shows up as segmentation faults that cause scons to abort
+before building anything. Using a stack size that is too large will
+cause scons to use more memory than required and may slow down the entire
+build process.
+
+The default value is to use a stack size of 256 kilobytes, which should
+be appropriate for most uses. You should not need to increase this value
+unless you encounter stack overflow errors.
+
+.TP
+-t, --touch
+Ignored for compatibility with GNU
+.BR make .
+(Touching a file to make it
+appear up-to-date is unnecessary when using
+.BR scons .)
+
+.TP
+.RI --taskmastertrace= file
+Prints trace information to the specified
+.I file
+about how the internal Taskmaster object
+evaluates and controls the order in which Nodes are built.
+A file name of
+.B -
+may be used to specify the standard output.
+
+.TP
+.RI -tree= options
+Prints a tree of the dependencies
+after each top-level target is built.
+This prints out some or all of the tree,
+in various formats,
+depending on the
+.I options
+specified:
+
+.TP
+--tree=all
+Print the entire dependency tree
+after each top-level target is built.
+This prints out the complete dependency tree,
+including implicit dependencies and ignored dependencies.
+
+.TP
+--tree=derived
+Restricts the tree output to only derived (target) files,
+not source files.
+
+.TP
+--tree=status
+Prints status information for each displayed node.
+
+.TP
+--tree=prune
+Prunes the tree to avoid repeating dependency information
+for nodes that have already been displayed.
+Any node that has already been displayed
+will have its name printed in
+.BR "[square brackets]" ,
+as an indication that the dependencies
+for that node can be found by searching
+for the relevant output higher up in the tree.
+
+.IP
+Multiple options may be specified,
+separated by commas:
+
+.ES
+# Prints only derived files, with status information:
+scons --tree=derived,status
+
+# Prints all dependencies of target, with status information
+# and pruning dependencies of already-visited Nodes:
+scons --tree=all,prune,status target
+.EE
+
+.TP
+-u, --up, --search-up
+Walks up the directory structure until an
+.I SConstruct ,
+.I Sconstruct
+or
+.I sconstruct
+file is found, and uses that
+as the top of the directory tree.
+If no targets are specified on the command line,
+only targets at or below the
+current directory will be built.
+
+.TP
+-U
+Works exactly the same way as the
+.B -u
+option except for the way default targets are handled.
+When this option is used and no targets are specified on the command line,
+all default targets that are defined in the SConscript(s) in the current
+directory are built, regardless of what directory the resultant targets end
+up in.
+
+.TP
+-v, --version
+Print the
+.B scons
+version, copyright information,
+list of authors, and any other relevant information.
+Then exit.
+
+.TP
+-w, --print-directory
+Print a message containing the working directory before and
+after other processing.
+
+.TP
+--no-print-directory
+Turn off -w, even if it was turned on implicitly.
+
+.TP
+.RI --warn= type ", --warn=no-" type
+Enable or disable warnings.
+.I type
+specifies the type of warnings to be enabled or disabled:
+
+.TP
+--warn=all, --warn=no-all
+Enables or disables all warnings.
+
+.TP
+--warn=cache-write-error, --warn=no-cache-write-error
+Enables or disables warnings about errors trying to
+write a copy of a built file to a specified
+.BR CacheDir ().
+These warnings are disabled by default.
+
+.TP
+--warn=corrupt-sconsign, --warn=no-corrupt-sconsign
+Enables or disables warnings about unfamiliar signature data in
+.B .sconsign
+files.
+These warnings are enabled by default.
+
+.TP
+--warn=dependency, --warn=no-dependency
+Enables or disables warnings about dependencies.
+These warnings are disabled by default.
+
+.TP
+--warn=deprecated, --warn=no-deprecated
+Enables or disables all warnings about use of
+currently deprecated features.
+These warnings are enabled by default.
+Note that the
+.B --warn=no-deprecated
+option does not disable warnings about absolutely all deprecated features.
+Warnings for some deprecated features that have already been through
+several releases with deprecation warnings
+may be mandatory for a release or two
+before they are officially no longer supported by SCons.
+Warnings for some specific deprecated features
+may be enabled or disabled individually;
+see below.
+
+.RS
+.TP
+--warn=deprecated-copy, --warn=no-deprecated-copy
+Enables or disables warnings about use of the deprecated
+.B env.Copy()
+method.
+
+.TP
+--warn=deprecated-source-signatures, --warn=no-deprecated-source-signatures
+Enables or disables warnings about use of the deprecated
+.B SourceSignatures()
+function or
+.B env.SourceSignatures()
+method.
+
+.TP
+--warn=deprecated-target-signatures, --warn=no-deprecated-target-signatures
+Enables or disables warnings about use of the deprecated
+.B TargetSignatures()
+function or
+.B env.TargetSignatures()
+method.
+.RE
+
+.TP
+--warn=duplicate-environment, --warn=no-duplicate-environment
+Enables or disables warnings about attempts to specify a build
+of a target with two different construction environments
+that use the same action.
+These warnings are enabled by default.
+
+.TP
+--warn=fortran-cxx-mix, --warn=no-fortran-cxx-mix
+Enables or disables the specific warning about linking
+Fortran and C++ object files in a single executable,
+which can yield unpredictable behavior with some compilers.
+
+.TP
+--warn=future-deprecated, --warn=no-future-deprecated
+Enables or disables warnings about features
+that will be deprecated in the future.
+These warnings are disabled by default.
+Enabling this warning is especially
+recommended for projects that redistribute
+SCons configurations for other users to build,
+so that the project can be warned as soon as possible
+about to-be-deprecated features
+that may require changes to the configuration.
+
+.TP
+--warn=link, --warn=no-link
+Enables or disables warnings about link steps.
+
+.TP
+--warn=misleading-keywords, --warn=no-misleading-keywords
+Enables or disables warnings about use of the misspelled keywords
+.B targets
+and
+.B sources
+when calling Builders.
+(Note the last
+.B s
+characters, the correct spellings are
+.B target
+and
+.B source.)
+These warnings are enabled by default.
+
+.TP
+--warn=missing-sconscript, --warn=no-missing-sconscript
+Enables or disables warnings about missing SConscript files.
+These warnings are enabled by default.
+
+.TP
+--warn=no-md5-module, --warn=no-no-md5-module
+Enables or disables warnings about the version of Python
+not having an MD5 checksum module available.
+These warnings are enabled by default.
+
+.TP
+--warn=no-metaclass-support, --warn=no-no-metaclass-support
+Enables or disables warnings about the version of Python
+not supporting metaclasses when the
+.B --debug=memoizer
+option is used.
+These warnings are enabled by default.
+
+.TP
+--warn=no-object-count, --warn=no-no-object-count
+Enables or disables warnings about the
+.B --debug=object
+feature not working when
+.B scons
+is run with the python
+.B \-O
+option or from optimized Python (.pyo) modules.
+
+.TP
+--warn=no-parallel-support, --warn=no-no-parallel-support
+Enables or disables warnings about the version of Python
+not being able to support parallel builds when the
+.B -j
+option is used.
+These warnings are enabled by default.
+
+.TP
+--warn=python-version, --warn=no-python-version
+Enables or disables the warning about running
+SCons with a deprecated version of Python.
+These warnings are enabled by default.
+
+.TP
+--warn=reserved-variable, --warn=no-reserved-variable
+Enables or disables warnings about attempts to set the
+reserved construction variable names
+.BR CHANGED_SOURCES ,
+.BR CHANGED_TARGETS ,
+.BR TARGET ,
+.BR TARGETS ,
+.BR SOURCE ,
+.BR SOURCES ,
+.BR UNCHANGED_SOURCES
+or
+.BR UNCHANGED_TARGETS .
+These warnings are disabled by default.
+
+.TP
+--warn=stack-size, --warn=no-stack-size
+Enables or disables warnings about requests to set the stack size
+that could not be honored.
+These warnings are enabled by default.
+
+.\" .TP
+.\" .RI --write-filenames= file
+.\" Write all filenames considered into
+.\" .IR file .
+.\"
+.\" .TP
+.\" .RI -W " file" ", --what-if=" file ", --new-file=" file ", --assume-new=" file
+.\" Pretend that the target
+.\" .I file
+.\" has been
+.\" modified. When used with the
+.\" .B -n
+.\" option, this
+.\" show you what would be rebuilt if you were to modify that file.
+.\" Without
+.\" .B -n
+.\" ... what? XXX
+.\"
+.\" .TP
+.\" --warn-undefined-variables
+.\" Warn when an undefined variable is referenced.
+
+.TP
+.RI -Y " repository" ", --repository=" repository ", --srcdir=" repository
+Search the specified repository for any input and target
+files not found in the local directory hierarchy. Multiple
+.B -Y
+options may be specified, in which case the
+repositories are searched in the order specified.
+
+.SH CONFIGURATION FILE REFERENCE
+.\" .SS Python Basics
+.\" XXX Adding this in the future would be a help.
+.SS Construction Environments
+A construction environment is the basic means by which the SConscript
+files communicate build information to
+.BR scons .
+A new construction environment is created using the
+.B Environment
+function:
+
+.ES
+env = Environment()
+.EE
+
+Variables, called
+.I construction
+.IR variables ,
+may be set in a construction environment
+either by specifying them as keywords when the object is created
+or by assigning them a value after the object is created:
+
+.ES
+env = Environment(FOO = 'foo')
+env['BAR'] = 'bar'
+.EE
+
+As a convenience,
+construction variables may also be set or modified by the
+.I parse_flags
+keyword argument, which applies the
+.B ParseFlags
+method (described below) to the argument value
+after all other processing is completed.
+This is useful either if the exact content of the flags is unknown
+(for example, read from a control file)
+or if the flags are distributed to a number of construction variables.
+
+.ES
+env = Environment(parse_flags = '-Iinclude -DEBUG -lm')
+.EE
+
+This example adds 'include' to
+.BR CPPPATH ,
+\&'EBUG' to
+.BR CPPDEFINES ,
+and 'm' to
+.BR LIBS .
+
+By default, a new construction environment is
+initialized with a set of builder methods
+and construction variables that are appropriate
+for the current platform.
+An optional platform keyword argument may be
+used to specify that an environment should
+be initialized for a different platform:
+
+.ES
+env = Environment(platform = 'cygwin')
+env = Environment(platform = 'os2')
+env = Environment(platform = 'posix')
+env = Environment(platform = 'win32')
+.EE
+
+Specifying a platform initializes the appropriate
+construction variables in the environment
+to use and generate file names with prefixes
+and suffixes appropriate for the platform.
+
+Note that the
+.B win32
+platform adds the
+.B SystemDrive
+and
+.B SystemRoot
+variables from the user's external environment
+to the construction environment's
+.B ENV
+dictionary.
+This is so that any executed commands
+that use sockets to connect with other systems
+(such as fetching source files from
+external CVS repository specifications like
+.BR :pserver:anonymous@cvs.sourceforge.net:/cvsroot/scons )
+will work on Windows systems.
+
+The platform argument may be function or callable object,
+in which case the Environment() method
+will call the specified argument to update
+the new construction environment:
+
+.ES
+def my_platform(env):
+ env['VAR'] = 'xyzzy'
+
+env = Environment(platform = my_platform)
+.EE
+
+Additionally, a specific set of tools
+with which to initialize the environment
+may be specified as an optional keyword argument:
+
+.ES
+env = Environment(tools = ['msvc', 'lex'])
+.EE
+
+Non-built-in tools may be specified using the toolpath argument:
+
+.ES
+env = Environment(tools = ['default', 'foo'], toolpath = ['tools'])
+.EE
+
+This looks for a tool specification in tools/foo.py (as well as
+using the ordinary default tools for the platform). foo.py should
+have two functions: generate(env, **kw) and exists(env).
+The
+.B generate()
+function
+modifies the passed-in environment
+to set up variables so that the tool
+can be executed;
+it may use any keyword arguments
+that the user supplies (see below)
+to vary its initialization.
+The
+.B exists()
+function should return a true
+value if the tool is available.
+Tools in the toolpath are used before
+any of the built-in ones. For example, adding gcc.py to the toolpath
+would override the built-in gcc tool.
+Also note that the toolpath is
+stored in the environment for use
+by later calls to
+.BR Clone ()
+and
+.BR Tool ()
+methods:
+
+.ES
+base = Environment(toolpath=['custom_path'])
+derived = base.Clone(tools=['custom_tool'])
+derived.CustomBuilder()
+.EE
+
+The elements of the tools list may also
+be functions or callable objects,
+in which case the Environment() method
+will call the specified elements
+to update the new construction environment:
+
+.ES
+def my_tool(env):
+ env['XYZZY'] = 'xyzzy'
+
+env = Environment(tools = [my_tool])
+.EE
+
+The individual elements of the tools list
+may also themselves be two-element lists of the form
+.RI ( toolname ", " kw_dict ).
+SCons searches for the
+.I toolname
+specification file as described above, and
+passes
+.IR kw_dict ,
+which must be a dictionary, as keyword arguments to the tool's
+.B generate
+function.
+The
+.B generate
+function can use the arguments to modify the tool's behavior
+by setting up the environment in different ways
+or otherwise changing its initialization.
+
+.ES
+# in tools/my_tool.py:
+def generate(env, **kw):
+ # Sets MY_TOOL to the value of keyword argument 'arg1' or 1.
+ env['MY_TOOL'] = kw.get('arg1', '1')
+def exists(env):
+ return 1
+
+# in SConstruct:
+env = Environment(tools = ['default', ('my_tool', {'arg1': 'abc'})],
+ toolpath=['tools'])
+.EE
+
+The tool definition (i.e. my_tool()) can use the PLATFORM variable from
+the environment it receives to customize the tool for different platforms.
+
+If no tool list is specified, then SCons will auto-detect the installed
+tools using the PATH variable in the ENV construction variable and the
+platform name when the Environment is constructed. Changing the PATH
+variable after the Environment is constructed will not cause the tools to
+be redetected.
+
+SCons supports the following tool specifications out of the box:
+
+.ES
+386asm
+aixc++
+aixcc
+aixf77
+aixlink
+ar
+as
+bcc32
+c++
+cc
+cvf
+dmd
+dvipdf
+dvips
+f77
+f90
+f95
+fortran
+g++
+g77
+gas
+gcc
+gfortran
+gnulink
+gs
+hpc++
+hpcc
+hplink
+icc
+icl
+ifl
+ifort
+ilink
+ilink32
+intelc
+jar
+javac
+javah
+latex
+lex
+link
+linkloc
+m4
+masm
+midl
+mingw
+mslib
+mslink
+mssdk
+msvc
+msvs
+mwcc
+mwld
+nasm
+pdflatex
+pdftex
+qt
+rmic
+rpcgen
+sgiar
+sgic++
+sgicc
+sgilink
+sunar
+sunc++
+suncc
+sunf77
+sunf90
+sunf95
+sunlink
+swig
+tar
+tex
+textfile
+tlib
+yacc
+zip
+.EE
+
+Additionally, there is a "tool" named
+.B default
+which configures the
+environment with a default set of tools for the current platform.
+
+On posix and cygwin platforms
+the GNU tools (e.g. gcc) are preferred by SCons,
+on Windows the Microsoft tools (e.g. msvc)
+followed by MinGW are preferred by SCons,
+and in OS/2 the IBM tools (e.g. icc) are preferred by SCons.
+
+.SS Builder Methods
+
+Build rules are specified by calling a construction
+environment's builder methods.
+The arguments to the builder methods are
+.B target
+(a list of targets to be built,
+usually file names)
+and
+.B source
+(a list of sources to be built,
+usually file names).
+
+Because long lists of file names
+can lead to a lot of quoting,
+.B scons
+supplies a
+.B Split()
+global function
+and a same-named environment method
+that split a single string
+into a list, separated on
+strings of white-space characters.
+(These are similar to the
+string.split() method
+from the standard Python library,
+but work even if the input isn't a string.)
+
+Like all Python arguments,
+the target and source arguments to a builder method
+can be specified either with or without
+the "target" and "source" keywords.
+When the keywords are omitted,
+the target is first,
+followed by the source.
+The following are equivalent examples of calling the Program builder method:
+
+.ES
+env.Program('bar', ['bar.c', 'foo.c'])
+env.Program('bar', Split('bar.c foo.c'))
+env.Program('bar', env.Split('bar.c foo.c'))
+env.Program(source = ['bar.c', 'foo.c'], target = 'bar')
+env.Program(target = 'bar', Split('bar.c foo.c'))
+env.Program(target = 'bar', env.Split('bar.c foo.c'))
+env.Program('bar', source = string.split('bar.c foo.c'))
+.EE
+
+Target and source file names
+that are not absolute path names
+(that is, do not begin with
+.B /
+on POSIX systems
+or
+.B \\
+on Windows systems,
+with or without
+an optional drive letter)
+are interpreted relative to the directory containing the
+.B SConscript
+file being read.
+An initial
+.B #
+(hash mark)
+on a path name means that the rest of the file name
+is interpreted relative to
+the directory containing
+the top-level
+.B SConstruct
+file,
+even if the
+.B #
+is followed by a directory separator character
+(slash or backslash).
+
+Examples:
+
+.ES
+# The comments describing the targets that will be built
+# assume these calls are in a SConscript file in the
+# a subdirectory named "subdir".
+
+# Builds the program "subdir/foo" from "subdir/foo.c":
+env.Program('foo', 'foo.c')
+
+# Builds the program "/tmp/bar" from "subdir/bar.c":
+env.Program('/tmp/bar', 'bar.c')
+
+# An initial '#' or '#/' are equivalent; the following
+# calls build the programs "foo" and "bar" (in the
+# top-level SConstruct directory) from "subdir/foo.c" and
+# "subdir/bar.c", respectively:
+env.Program('#foo', 'foo.c')
+env.Program('#/bar', 'bar.c')
+
+# Builds the program "other/foo" (relative to the top-level
+# SConstruct directory) from "subdir/foo.c":
+env.Program('#other/foo', 'foo.c')
+.EE
+
+When the target shares the same base name
+as the source and only the suffix varies,
+and if the builder method has a suffix defined for the target file type,
+then the target argument may be omitted completely,
+and
+.B scons
+will deduce the target file name from
+the source file name.
+The following examples all build the
+executable program
+.B bar
+(on POSIX systems)
+or
+.B bar.exe
+(on Windows systems)
+from the bar.c source file:
+
+.ES
+env.Program(target = 'bar', source = 'bar.c')
+env.Program('bar', source = 'bar.c')
+env.Program(source = 'bar.c')
+env.Program('bar.c')
+.EE
+
+As a convenience, a
+.B srcdir
+keyword argument may be specified
+when calling a Builder.
+When specified,
+all source file strings that are not absolute paths
+will be interpreted relative to the specified
+.BR srcdir .
+The following example will build the
+.B build/prog
+(or
+.B build/prog.exe
+on Windows)
+program from the files
+.B src/f1.c
+and
+.BR src/f2.c :
+
+.ES
+env.Program('build/prog', ['f1.c', 'f2.c'], srcdir='src')
+.EE
+
+It is possible to override or add construction variables when calling a
+builder method by passing additional keyword arguments.
+These overridden or added
+variables will only be in effect when building the target, so they will not
+affect other parts of the build. For example, if you want to add additional
+libraries for just one program:
+
+.ES
+env.Program('hello', 'hello.c', LIBS=['gl', 'glut'])
+.EE
+
+or generate a shared library with a non-standard suffix:
+
+.ES
+env.SharedLibrary('word', 'word.cpp',
+ SHLIBSUFFIX='.ocx',
+ LIBSUFFIXES=['.ocx'])
+.EE
+
+(Note that both the $SHLIBSUFFIX and $LIBSUFFIXES variables must be set
+if you want SCons to search automatically
+for dependencies on the non-standard library names;
+see the descriptions of these variables, below, for more information.)
+
+It is also possible to use the
+.I parse_flags
+keyword argument in an override:
+
+.ES
+env = Program('hello', 'hello.c', parse_flags = '-Iinclude -DEBUG -lm')
+.EE
+
+This example adds 'include' to
+.BR CPPPATH ,
+\&'EBUG' to
+.BR CPPDEFINES ,
+and 'm' to
+.BR LIBS .
+
+Although the builder methods defined by
+.B scons
+are, in fact,
+methods of a construction environment object,
+they may also be called without an explicit environment:
+
+.ES
+Program('hello', 'hello.c')
+SharedLibrary('word', 'word.cpp')
+.EE
+
+In this case,
+the methods are called internally using a default construction
+environment that consists of the tools and values that
+.B scons
+has determined are appropriate for the local system.
+
+Builder methods that can be called without an explicit
+environment may be called from custom Python modules that you
+import into an SConscript file by adding the following
+to the Python module:
+
+.ES
+from SCons.Script import *
+.EE
+
+All builder methods return a list-like object
+containing Nodes that
+represent the target or targets that will be built.
+A
+.I Node
+is an internal SCons object
+which represents
+build targets or sources.
+
+The returned Node-list object
+can be passed to other builder methods as source(s)
+or passed to any SCons function or method
+where a filename would normally be accepted.
+For example, if it were necessary
+to add a specific
+.B -D
+flag when compiling one specific object file:
+
+.ES
+bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR')
+env.Program(source = ['foo.c', bar_obj_list, 'main.c'])
+.EE
+
+Using a Node in this way
+makes for a more portable build
+by avoiding having to specify
+a platform-specific object suffix
+when calling the Program() builder method.
+
+Note that Builder calls will automatically "flatten"
+the source and target file lists,
+so it's all right to have the bar_obj list
+return by the StaticObject() call
+in the middle of the source file list.
+If you need to manipulate a list of lists returned by Builders
+directly using Python,
+you can either build the list by hand:
+
+.ES
+foo = Object('foo.c')
+bar = Object('bar.c')
+objects = ['begin.o'] + foo + ['middle.o'] + bar + ['end.o']
+for object in objects:
+ print str(object)
+.EE
+
+Or you can use the
+.BR Flatten ()
+function supplied by scons
+to create a list containing just the Nodes,
+which may be more convenient:
+
+.ES
+foo = Object('foo.c')
+bar = Object('bar.c')
+objects = Flatten(['begin.o', foo, 'middle.o', bar, 'end.o'])
+for object in objects:
+ print str(object)
+.EE
+
+Note also that because Builder calls return
+a list-like object, not an actual Python list,
+you should
+.I not
+use the Python
+.B +=
+operator to append Builder results to a Python list.
+Because the list and the object are different types,
+Python will not update the original list in place,
+but will instead create a new Node-list object
+containing the concatenation of the list
+elements and the Builder results.
+This will cause problems for any other Python variables
+in your SCons configuration
+that still hold on to a reference to the original list.
+Instead, use the Python
+.B .extend()
+method to make sure the list is updated in-place.
+Example:
+
+.ES
+object_files = []
+
+# Do NOT use += as follows:
+#
+# object_files += Object('bar.c')
+#
+# It will not update the object_files list in place.
+#
+# Instead, use the .extend() method:
+object_files.extend(Object('bar.c'))
+
+.EE
+
+The path name for a Node's file may be used
+by passing the Node to the Python-builtin
+.B str()
+function:
+
+.ES
+bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR')
+print "The path to bar_obj is:", str(bar_obj_list[0])
+.EE
+
+Note again that because the Builder call returns a list,
+we have to access the first element in the list
+.B (bar_obj_list[0])
+to get at the Node that actually represents
+the object file.
+
+Builder calls support a
+.B chdir
+keyword argument that
+specifies that the Builder's action(s)
+should be executed
+after changing directory.
+If the
+.B chdir
+argument is
+a string or a directory Node,
+scons will change to the specified directory.
+If the
+.B chdir
+is not a string or Node
+and is non-zero,
+then scons will change to the
+target file's directory.
+
+.ES
+# scons will change to the "sub" subdirectory
+# before executing the "cp" command.
+env.Command('sub/dir/foo.out', 'sub/dir/foo.in',
+ "cp dir/foo.in dir/foo.out",
+ chdir='sub')
+
+# Because chdir is not a string, scons will change to the
+# target's directory ("sub/dir") before executing the
+# "cp" command.
+env.Command('sub/dir/foo.out', 'sub/dir/foo.in',
+ "cp foo.in foo.out",
+ chdir=1)
+.EE
+
+Note that scons will
+.I not
+automatically modify
+its expansion of
+construction variables like
+.B $TARGET
+and
+.B $SOURCE
+when using the chdir
+keyword argument--that is,
+the expanded file names
+will still be relative to
+the top-level SConstruct directory,
+and consequently incorrect
+relative to the chdir directory.
+If you use the chdir keyword argument,
+you will typically need to supply a different
+command line using
+expansions like
+.B ${TARGET.file}
+and
+.B ${SOURCE.file}
+to use just the filename portion of the
+targets and source.
+
+.B scons
+provides the following builder methods:
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+'\" BEGIN GENERATED BUILDER DESCRIPTIONS
+'\"
+'\" The descriptions below of the various SCons Builders are generated
+'\" from the .xml files that live next to the various Python modules in
+'\" the build enginer library. If you're reading this [gnt]roff file
+'\" with an eye towards patching this man page, you can still submit
+'\" a diff against this text, but it will have to be translated to a
+'\" diff against the underlying .xml file before the patch is actually
+'\" accepted. If you do that yourself, it will make it easier to
+'\" integrate the patch.
+'\"
+'\" BEGIN GENERATED BUILDER DESCRIPTIONS
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.so builders.man
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+'\" END GENERATED BUILDER DESCRIPTIONS
+'\"
+'\" The descriptions above of the various SCons Builders are generated
+'\" from the .xml files that live next to the various Python modules in
+'\" the build enginer library. If you're reading this [gnt]roff file
+'\" with an eye towards patching this man page, you can still submit
+'\" a diff against this text, but it will have to be translated to a
+'\" diff against the underlying .xml file before the patch is actually
+'\" accepted. If you do that yourself, it will make it easier to
+'\" integrate the patch.
+'\"
+'\" END GENERATED BUILDER DESCRIPTIONS
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+.P
+All
+targets of builder methods automatically depend on their sources.
+An explicit dependency can
+be specified using the
+.B Depends
+method of a construction environment (see below).
+
+In addition,
+.B scons
+automatically scans
+source files for various programming languages,
+so the dependencies do not need to be specified explicitly.
+By default, SCons can
+C source files,
+C++ source files,
+Fortran source files with
+.B .F
+(POSIX systems only),
+.B .fpp,
+or
+.B .FPP
+file extensions,
+and assembly language files with
+.B .S
+(POSIX systems only),
+.B .spp,
+or
+.B .SPP
+files extensions
+for C preprocessor dependencies.
+SCons also has default support
+for scanning D source files,
+You can also write your own Scanners
+to add support for additional source file types.
+These can be added to the default
+Scanner object used by the
+.BR Object (),
+.BR StaticObject (),
+and
+.BR SharedObject ()
+Builders by adding them
+to the
+.B SourceFileScanner
+object as follows:
+
+See the section "Scanner Objects,"
+below, for a more information about
+defining your own Scanner objects.
+
+.SS Methods and Functions to Do Things
+In addition to Builder methods,
+.B scons
+provides a number of other construction environment methods
+and global functions to
+manipulate the build configuration.
+
+Usually, a construction environment method
+and global function with the same name both exist
+so that you don't have to remember whether
+to a specific bit of functionality
+must be called with or without a construction environment.
+In the following list,
+if you call something as a global function
+it looks like:
+.ES
+.RI Function( arguments )
+.EE
+and if you call something through a construction
+environment it looks like:
+.ES
+.RI env.Function( arguments )
+.EE
+If you can call the functionality in both ways,
+then both forms are listed.
+
+Global functions may be called from custom Python modules that you
+import into an SConscript file by adding the following
+to the Python module:
+
+.ES
+from SCons.Script import *
+.EE
+
+Except where otherwise noted,
+the same-named
+construction environment method
+and global function
+provide the exact same functionality.
+The only difference is that,
+where appropriate,
+calling the functionality through a construction environment will
+substitute construction variables into
+any supplied strings.
+For example:
+
+.ES
+env = Environment(FOO = 'foo')
+Default('$FOO')
+env.Default('$FOO')
+.EE
+
+In the above example,
+the first call to the global
+.B Default()
+function will actually add a target named
+.B $FOO
+to the list of default targets,
+while the second call to the
+.B env.Default()
+construction environment method
+will expand the value
+and add a target named
+.B foo
+to the list of default targets.
+For more on construction variable expansion,
+see the next section on
+construction variables.
+
+Construction environment methods
+and global functions supported by
+.B scons
+include:
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Action( action ", [" cmd/str/fun ", [" var ", ...]] [" option = value ", ...])"
+.TP
+.IR env .Action( action ", [" cmd/str/fun ", [" var ", ...]] [" option = value ", ...])"
+Creates an Action object for
+the specified
+.IR action .
+See the section "Action Objects,"
+below, for a complete explanation of the arguments and behavior.
+
+Note that the
+.BR env.Action ()
+form of the invocation will expand
+construction variables in any argument strings,
+including the
+.I action
+argument, at the time it is called
+using the construction variables in the
+.I env
+construction environment through which
+.BR env.Action ()
+was called.
+The
+.BR Action ()
+form delays all variable expansion
+until the Action object is actually used.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI AddMethod( object, function ", [" name ])
+.TP
+.RI env.AddMethod( function ", [" name ])
+When called with the
+.BR AddMethod ()
+form,
+adds the specified
+.I function
+to the specified
+.I object
+as the specified method
+.IR name .
+When called with the
+.BR env.AddMethod ()
+form,
+adds the specified
+.I function
+to the construction environment
+.I env
+as the specified method
+.IR name .
+In both cases, if
+.I name
+is omitted or
+.BR None ,
+the name of the
+specified
+.I function
+itself is used for the method name.
+
+Examples:
+
+.ES
+# Note that the first argument to the function to
+# be attached as a method must be the object through
+# which the method will be called; the Python
+# convention is to call it 'self'.
+def my_method(self, arg):
+ print "my_method() got", arg
+
+# Use the global AddMethod() function to add a method
+# to the Environment class. This
+AddMethod(Environment, my_method)
+env = Environment()
+env.my_method('arg')
+
+# Add the function as a method, using the function
+# name for the method call.
+env = Environment()
+env.AddMethod(my_method, 'other_method_name')
+env.other_method_name('another arg')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI AddOption( arguments )
+This function adds a new command-line option to be recognized.
+The specified
+.I arguments
+are the same as supported by the standard Python
+.BR optparse.add_option ()
+method (with a few additional capabilities noted below);
+see the documentation for
+.B optparse
+for a thorough discussion of its option-processing capabities.
+(Note that although the
+.B optparse
+module was not a standard module until Python 2.3,
+.B scons
+contains a compatible version of the module
+that is used to provide identical functionality
+when run by earlier Python versions.)
+
+In addition to the arguments and values supported by the
+.B optparse.add_option ()
+method,
+the SCons
+.BR AddOption ()
+function allows you to set the
+.B nargs
+keyword value to
+.B '?'
+(a string with just the question mark)
+to indicate that the specified long option(s) take(s) an
+.I optional
+argument.
+When
+.B "nargs = '?'"
+is passed to the
+.BR AddOption ()
+function, the
+.B const
+keyword argument
+may be used to supply the "default"
+value that should be used when the
+option is specified on the command line
+without an explicit argument.
+
+If no
+.B default=
+keyword argument is supplied when calling
+.BR AddOption (),
+the option will have a default value of
+.BR None .
+
+Once a new command-line option has been added with
+.BR AddOption (),
+the option value may be accessed using
+.BR GetOption ()
+or
+.BR env.GetOption ().
+\" NOTE: in SCons 1.x or 2.0, user options will be settable, but not yet.
+\" Uncomment this when that works. See tigris issue 2105.
+\" The value may also be set, using
+\" .BR SetOption ()
+\" or
+\" .BR env.SetOption (),
+\" if conditions in a
+\" .B SConscript
+\" require overriding any default value.
+\" Note, however, that a
+\" value specified on the command line will
+\" .I always
+\" override a value set by any SConscript file.
+
+Any specified
+.B help=
+strings for the new option(s)
+will be displayed by the
+.B -H
+or
+.B -h
+options
+(the latter only if no other help text is
+specified in the SConscript files).
+The help text for the local options specified by
+.BR AddOption ()
+will appear below the SCons options themselves,
+under a separate
+.B "Local Options"
+heading.
+The options will appear in the help text
+in the order in which the
+.BR AddOption ()
+calls occur.
+
+Example:
+
+.ES
+AddOption('--prefix',
+ dest='prefix',
+ nargs=1, type='string',
+ action='store',
+ metavar='DIR',
+ help='installation prefix')
+env = Environment(PREFIX = GetOption('prefix'))
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI AddPostAction( target ", " action )
+.TP
+.RI env.AddPostAction( target ", " action )
+Arranges for the specified
+.I action
+to be performed
+after the specified
+.I target
+has been built.
+The specified action(s) may be
+an Action object, or anything that
+can be converted into an Action object
+(see below).
+
+When multiple targets are supplied,
+the action may be called multiple times,
+once after each action that generates
+one or more targets in the list.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI AddPreAction( target ", " action )
+.TP
+.RI env.AddPreAction( target ", " action )
+Arranges for the specified
+.I action
+to be performed
+before the specified
+.I target
+is built.
+The specified action(s) may be
+an Action object, or anything that
+can be converted into an Action object
+(see below).
+
+When multiple targets are specified,
+the action(s) may be called multiple times,
+once before each action that generates
+one or more targets in the list.
+
+Note that if any of the targets are built in multiple steps,
+the action will be invoked just
+before the "final" action that specifically
+generates the specified target(s).
+For example, when building an executable program
+from a specified source
+.B .c
+file via an intermediate object file:
+
+.ES
+foo = Program('foo.c')
+AddPreAction(foo, 'pre_action')
+.EE
+
+The specified
+.B pre_action
+would be executed before
+.B scons
+calls the link command that actually
+generates the executable program binary
+.BR foo ,
+not before compiling the
+.B foo.c
+file into an object file.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Alias( alias ", [" targets ", [" action ]])
+.TP
+.RI env.Alias( alias ", [" targets ", [" action ]])
+Creates one or more phony targets that
+expand to one or more other targets.
+An optional
+.I action
+(command)
+or list of actions
+can be specified that will be executed
+whenever the any of the alias targets are out-of-date.
+Returns the Node object representing the alias,
+which exists outside of any file system.
+This Node object, or the alias name,
+may be used as a dependency of any other target,
+including another alias.
+.B Alias
+can be called multiple times for the same
+alias to add additional targets to the alias,
+or additional actions to the list for this alias.
+
+Examples:
+
+.ES
+Alias('install')
+Alias('install', '/usr/bin')
+Alias(['install', 'install-lib'], '/usr/local/lib')
+
+env.Alias('install', ['/usr/local/bin', '/usr/local/lib'])
+env.Alias('install', ['/usr/local/man'])
+
+env.Alias('update', ['file1', 'file2'], "update_database $SOURCES")
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI AllowSubstExceptions([ exception ", ...])"
+Specifies the exceptions that will be allowed
+when expanding construction variables.
+By default,
+any construction variable expansions that generate a
+.B NameError
+or
+.BR IndexError
+exception will expand to a
+.B ''
+(a null string) and not cause scons to fail.
+All exceptions not in the specified list
+will generate an error message
+and terminate processing.
+
+If
+.B AllowSubstExceptions
+is called multiple times,
+each call completely overwrites the previous list
+of allowed exceptions.
+
+Example:
+
+.ES
+# Requires that all construction variable names exist.
+# (You may wish to do this if you want to enforce strictly
+# that all construction variables must be defined before use.)
+AllowSubstExceptions()
+
+# Also allow a string containing a zero-division expansion
+# like '${1 / 0}' to evalute to ''.
+AllowSubstExceptions(IndexError, NameError, ZeroDivisionError)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI AlwaysBuild( target ", ...)"
+.TP
+.RI env.AlwaysBuild( target ", ...)"
+Marks each given
+.I target
+so that it is always assumed to be out of date,
+and will always be rebuilt if needed.
+Note, however, that
+.BR AlwaysBuild ()
+does not add its target(s) to the default target list,
+so the targets will only be built
+if they are specified on the command line,
+or are a dependent of a target specified on the command line--but
+they will
+.I always
+be built if so specified.
+Multiple targets can be passed in to a single call to
+.BR AlwaysBuild ().
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.Append( key = val ", [...])"
+Appends the specified keyword arguments
+to the end of construction variables in the environment.
+If the Environment does not have
+the specified construction variable,
+it is simply added to the environment.
+If the values of the construction variable
+and the keyword argument are the same type,
+then the two values will be simply added together.
+Otherwise, the construction variable
+and the value of the keyword argument
+are both coerced to lists,
+and the lists are added together.
+(See also the Prepend method, below.)
+
+Example:
+
+.ES
+env.Append(CCFLAGS = ' -g', FOO = ['foo.yyy'])
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.AppendENVPath( name ", " newpath ", [" envname ", " sep ", " delete_existing ])
+This appends new path elements to the given path in the
+specified external environment
+.RB ( ENV
+by default).
+This will only add
+any particular path once (leaving the last one it encounters and
+ignoring the rest, to preserve path order),
+and to help assure this,
+will normalize all paths (using
+.B os.path.normpath
+and
+.BR os.path.normcase ).
+This can also handle the
+case where the given old path variable is a list instead of a
+string, in which case a list will be returned instead of a string.
+
+If
+.I delete_existing
+is 0, then adding a path that already exists
+will not move it to the end; it will stay where it is in the list.
+
+Example:
+
+.ES
+print 'before:',env['ENV']['INCLUDE']
+include_path = '/foo/bar:/foo'
+env.AppendENVPath('INCLUDE', include_path)
+print 'after:',env['ENV']['INCLUDE']
+
+yields:
+before: /foo:/biz
+after: /biz:/foo/bar:/foo
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.AppendUnique( key = val ", [...], delete_existing=0)"
+Appends the specified keyword arguments
+to the end of construction variables in the environment.
+If the Environment does not have
+the specified construction variable,
+it is simply added to the environment.
+If the construction variable being appended to is a list,
+then any value(s) that already exist in the
+construction variable will
+.I not
+be added again to the list.
+However, if delete_existing is 1,
+existing matching values are removed first, so
+existing values in the arg list move to the end of the list.
+
+Example:
+
+.ES
+env.AppendUnique(CCFLAGS = '-g', FOO = ['foo.yyy'])
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+env.BitKeeper()
+A factory function that
+returns a Builder object
+to be used to fetch source files
+using BitKeeper.
+The returned Builder
+is intended to be passed to the
+.B SourceCode
+function.
+
+Example:
+
+.ES
+env.SourceCode('.', env.BitKeeper())
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI BuildDir( build_dir ", " src_dir ", [" duplicate ])
+.TP
+.RI env.BuildDir( build_dir ", " src_dir ", [" duplicate ])
+Deprecated synonyms for
+.BR VariantDir ()
+and
+.BR env.VariantDir ().
+The
+.I build_dir
+argument becomes the
+.I variant_dir
+argument of
+.BR VariantDir ()
+or
+.BR env.VariantDir ().
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Builder( action ", [" arguments ])
+.TP
+.RI env.Builder( action ", [" arguments ])
+Creates a Builder object for
+the specified
+.IR action .
+See the section "Builder Objects,"
+below, for a complete explanation of the arguments and behavior.
+
+Note that the
+.BR env.Builder ()
+form of the invocation will expand
+construction variables in any arguments strings,
+including the
+.I action
+argument,
+at the time it is called
+using the construction variables in the
+.B env
+construction environment through which
+.BR env.Builder ()
+was called.
+The
+.BR Builder ()
+form delays all variable expansion
+until after the Builder object is actually called.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI CacheDir( cache_dir )
+.TP
+.RI env.CacheDir( cache_dir )
+Specifies that
+.B scons
+will maintain a cache of derived files in
+.I cache_dir .
+The derived files in the cache will be shared
+among all the builds using the same
+.BR CacheDir ()
+call.
+Specifying a
+.I cache_dir
+of
+.B None
+disables derived file caching.
+
+Calling
+.BR env.CacheDir ()
+will only affect targets built
+through the specified construction environment.
+Calling
+.BR CacheDir ()
+sets a global default
+that will be used by all targets built
+through construction environments
+that do
+.I not
+have an
+.BR env.CacheDir ()
+specified.
+
+When a
+.BR CacheDir ()
+is being used and
+.B scons
+finds a derived file that needs to be rebuilt,
+it will first look in the cache to see if a
+derived file has already been built
+from identical input files and an identical build action
+(as incorporated into the MD5 build signature).
+If so,
+.B scons
+will retrieve the file from the cache.
+If the derived file is not present in the cache,
+.B scons
+will rebuild it and
+then place a copy of the built file in the cache
+(identified by its MD5 build signature),
+so that it may be retrieved by other
+builds that need to build the same derived file
+from identical inputs.
+
+Use of a specified
+.BR CacheDir()
+may be disabled for any invocation
+by using the
+.B --cache-disable
+option.
+
+If the
+.B --cache-force
+option is used,
+.B scons
+will place a copy of
+.I all
+derived files in the cache,
+even if they already existed
+and were not built by this invocation.
+This is useful to populate a cache
+the first time
+.BR CacheDir ()
+is added to a build,
+or after using the
+.B --cache-disable
+option.
+
+When using
+.BR CacheDir (),
+.B scons
+will report,
+"Retrieved `file' from cache,"
+unless the
+.B --cache-show
+option is being used.
+When the
+.B --cache-show
+option is used,
+.B scons
+will print the action that
+.I would
+have been used to build the file,
+without any indication that
+the file was actually retrieved from the cache.
+This is useful to generate build logs
+that are equivalent regardless of whether
+a given derived file has been built in-place
+or retrieved from the cache.
+
+The
+.BR NoCache ()
+method can be used to disable caching of specific files. This can be
+useful if inputs and/or outputs of some tool are impossible to
+predict or prohibitively large.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Clean( targets ", " files_or_dirs )
+.TP
+.RI env.Clean( targets ", " files_or_dirs )
+This specifies a list of files or directories which should be removed
+whenever the targets are specified with the
+.B -c
+command line option.
+The specified targets may be a list
+or an individual target.
+Multiple calls to
+.BR Clean ()
+are legal,
+and create new targets or add files and directories to the
+clean list for the specified targets.
+
+Multiple files or directories should be specified
+either as separate arguments to the
+.BR Clean ()
+method, or as a list.
+.BR Clean ()
+will also accept the return value of any of the construction environment
+Builder methods.
+Examples:
+
+The related
+.BR NoClean ()
+function overrides calling
+.BR Clean ()
+for the same target,
+and any targets passed to both functions will
+.I not
+be removed by the
+.B -c
+option.
+
+Examples:
+
+.ES
+Clean('foo', ['bar', 'baz'])
+Clean('dist', env.Program('hello', 'hello.c'))
+Clean(['foo', 'bar'], 'something_else_to_clean')
+.EE
+
+In this example,
+installing the project creates a subdirectory for the documentation.
+This statement causes the subdirectory to be removed
+if the project is deinstalled.
+.ES
+Clean(docdir, os.path.join(docdir, projectname))
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Command( target ", " source ", " action ", [" key = val ", ...])"
+.TP
+.RI env.Command( target ", " source ", " action ", [" key = val ", ...])"
+Executes a specific action
+(or list of actions)
+to build a target file or files.
+This is more convenient
+than defining a separate Builder object
+for a single special-case build.
+
+As a special case, the
+.B source_scanner
+keyword argument can
+be used to specify
+a Scanner object
+that will be used to scan the sources.
+(The global
+.B DirScanner
+object can be used
+if any of the sources will be directories
+that must be scanned on-disk for
+changes to files that aren't
+already specified in other Builder of function calls.)
+
+Any other keyword arguments specified override any
+same-named existing construction variables.
+
+An action can be an external command,
+specified as a string,
+or a callable Python object;
+see "Action Objects," below,
+for more complete information.
+Also note that a string specifying an external command
+may be preceded by an
+.B @
+(at-sign)
+to suppress printing the command in question,
+or by a
+.B \-
+(hyphen)
+to ignore the exit status of the external command.
+
+Examples:
+
+.ES
+env.Command('foo.out', 'foo.in',
+ "$FOO_BUILD < $SOURCES > $TARGET")
+
+env.Command('bar.out', 'bar.in',
+ ["rm -f $TARGET",
+ "$BAR_BUILD < $SOURCES > $TARGET"],
+ ENV = {'PATH' : '/usr/local/bin/'})
+
+def rename(env, target, source):
+ import os
+ os.rename('.tmp', str(target[0]))
+
+env.Command('baz.out', 'baz.in',
+ ["$BAZ_BUILD < $SOURCES > .tmp",
+ rename ])
+.EE
+
+.IP
+Note that the
+.BR Command ()
+function will usually assume, by default,
+that the specified targets and/or sources are Files,
+if no other part of the configuration
+identifies what type of entry it is.
+If necessary, you can explicitly specify
+that targets or source nodes should
+be treated as directoriese
+by using the
+.BR Dir ()
+or
+.BR env.Dir ()
+functions.
+
+Examples:
+
+.ES
+env.Command('ddd.list', Dir('ddd'), 'ls -l $SOURCE > $TARGET')
+
+env['DISTDIR'] = 'destination/directory'
+env.Command(env.Dir('$DISTDIR')), None, make_distdir)
+.EE
+
+.IP
+(Also note that SCons will usually
+automatically create any directory necessary to hold a target file,
+so you normally don't need to create directories by hand.)
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Configure( env ", [" custom_tests ", " conf_dir ", " log_file ", " config_h ])
+.TP
+.RI env.Configure([ custom_tests ", " conf_dir ", " log_file ", " config_h ])
+Creates a Configure object for integrated
+functionality similar to GNU autoconf.
+See the section "Configure Contexts,"
+below, for a complete explanation of the arguments and behavior.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.Clone([ key = val ", ...])"
+Return a separate copy of a construction environment.
+If there are any keyword arguments specified,
+they are added to the returned copy,
+overwriting any existing values
+for the keywords.
+
+Example:
+
+.ES
+env2 = env.Clone()
+env3 = env.Clone(CCFLAGS = '-g')
+.EE
+.IP
+Additionally, a list of tools and a toolpath may be specified, as in
+the Environment constructor:
+
+.ES
+def MyTool(env): env['FOO'] = 'bar'
+env4 = env.Clone(tools = ['msvc', MyTool])
+.EE
+
+The
+.I parse_flags
+keyword argument is also recognized:
+
+.ES
+# create an environment for compiling programs that use wxWidgets
+wx_env = env.Clone(parse_flags = '!wx-config --cflags --cxxflags')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.Copy([ key = val ", ...])"
+A now-deprecated synonym for
+.BR env.Clone() .
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.CVS( repository ", " module )
+A factory function that
+returns a Builder object
+to be used to fetch source files
+from the specified
+CVS
+.IR repository .
+The returned Builder
+is intended to be passed to the
+.B SourceCode
+function.
+
+The optional specified
+.I module
+will be added to the beginning
+of all repository path names;
+this can be used, in essence,
+to strip initial directory names
+from the repository path names,
+so that you only have to
+replicate part of the repository
+directory hierarchy in your
+local build directory.
+
+Examples:
+
+.ES
+# Will fetch foo/bar/src.c
+# from /usr/local/CVSROOT/foo/bar/src.c.
+env.SourceCode('.', env.CVS('/usr/local/CVSROOT'))
+
+# Will fetch bar/src.c
+# from /usr/local/CVSROOT/foo/bar/src.c.
+env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo'))
+
+# Will fetch src.c
+# from /usr/local/CVSROOT/foo/bar/src.c.
+env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo/bar'))
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Decider( function )
+.TP
+.RI env.Decider( function )
+Specifies that all up-to-date decisions for
+targets built through this construction environment
+will be handled by the specified
+.IR function .
+The
+.I function
+can be one of the following strings
+that specify the type of decision function
+to be performed:
+
+.RS 10
+.HP 6
+.B timestamp-newer
+Specifies that a target shall be considered out of date and rebuilt
+if the dependency's timestamp is newer than the target file's timestamp.
+This is the behavior of the classic Make utility,
+and
+.B make
+can be used a synonym for
+.BR timestamp-newer .
+
+.HP 6
+.B timestamp-match
+Specifies that a target shall be considered out of date and rebuilt
+if the dependency's timestamp is different than the
+timestamp recorded the last time the target was built.
+This provides behavior very similar to the classic Make utility
+(in particular, files are not opened up so that their
+contents can be checksummed)
+except that the target will also be rebuilt if a
+dependency file has been restored to a version with an
+.I earlier
+timestamp, such as can happen when restoring files from backup archives.
+
+.HP 6
+.B MD5
+Specifies that a target shall be considered out of date and rebuilt
+if the dependency's content has changed sine the last time
+the target was built,
+as determined be performing an MD5 checksum
+on the dependency's contents
+and comparing it to the checksum recorded the
+last time the target was built.
+.B content
+can be used as a synonym for
+.BR MD5 .
+
+.HP 6
+.B MD5-timestamp
+Specifies that a target shall be considered out of date and rebuilt
+if the dependency's content has changed sine the last time
+the target was built,
+except that dependencies with a timestamp that matches
+the last time the target was rebuilt will be
+assumed to be up-to-date and
+.I not
+rebuilt.
+This provides behavior very similar
+to the
+.B MD5
+behavior of always checksumming file contents,
+with an optimization of not checking
+the contents of files whose timestamps haven't changed.
+The drawback is that SCons will
+.I not
+detect if a file's content has changed
+but its timestamp is the same,
+as might happen in an automated script
+that runs a build,
+updates a file,
+and runs the build again,
+all within a single second.
+.RE
+
+.IP
+Examples:
+
+.ES
+# Use exact timestamp matches by default.
+Decider('timestamp-match')
+
+# Use MD5 content signatures for any targets built
+# with the attached construction environment.
+env.Decider('content')
+.EE
+
+.IP
+In addition to the above already-available functions,
+the
+.I function
+argument may be an actual Python function
+that takes the following three arguments:
+
+.RS 10
+.IP dependency
+The Node (file) which
+should cause the
+.I target
+to be rebuilt
+if it has "changed" since the last tme
+.I target was built.
+
+.IP target
+The Node (file) being built.
+In the normal case,
+this is what should get rebuilt
+if the
+.I dependency
+has "changed."
+
+.IP prev_ni
+Stored information about the state of the
+.I dependency
+the last time the
+.I target
+was built.
+This can be consulted to match various
+file characteristics
+such as the timestamp,
+size, or content signature.
+.RE
+
+.IP
+The
+.I function
+should return a
+.B True
+(non-zero)
+value if the
+.I dependency
+has "changed" since the last time
+the
+.I target
+was built
+(indicating that the target
+.I should
+be rebuilt),
+and
+.B False
+(zero)
+otherwise
+(indicating that the target should
+.I not
+be rebuilt).
+Note that the decision can be made
+using whatever criteria are appopriate.
+Ignoring some or all of the function arguments
+is perfectly normal.
+
+Example:
+
+.ES
+def my_decider(dependency, target, prev_ni):
+ return not os.path.exists(str(target))
+
+env.Decider(my_decider)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Default( targets )
+.TP
+.RI env.Default( targets )
+This specifies a list of default targets,
+which will be built by
+.B scons
+if no explicit targets are given on the command line.
+Multiple calls to
+.BR Default ()
+are legal,
+and add to the list of default targets.
+
+Multiple targets should be specified as
+separate arguments to the
+.BR Default ()
+method, or as a list.
+.BR Default ()
+will also accept the Node returned by any
+of a construction environment's
+builder methods.
+
+Examples:
+
+.ES
+Default('foo', 'bar', 'baz')
+env.Default(['a', 'b', 'c'])
+hello = env.Program('hello', 'hello.c')
+env.Default(hello)
+.EE
+.IP
+An argument to
+.BR Default ()
+of
+.B None
+will clear all default targets.
+Later calls to
+.BR Default ()
+will add to the (now empty) default-target list
+like normal.
+
+The current list of targets added using the
+.BR Default ()
+function or method is available in the
+.B DEFAULT_TARGETS
+list;
+see below.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI DefaultEnvironment([ args ])
+Creates and returns a default construction environment object.
+This construction environment is used internally by SCons
+in order to execute many of the global functions in this list,
+and to fetch source files transparently
+from source code management systems.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Depends( target ", " dependency )
+.TP
+.RI env.Depends( target ", " dependency )
+Specifies an explicit dependency;
+the
+.I target
+will be rebuilt
+whenever the
+.I dependency
+has changed.
+Both the specified
+.I target
+and
+.I dependency
+can be a string
+(usually the path name of a file or directory)
+or Node objects,
+or a list of strings or Node objects
+(such as returned by a Builder call).
+This should only be necessary
+for cases where the dependency
+is not caught by a Scanner
+for the file.
+
+Example:
+
+.ES
+env.Depends('foo', 'other-input-file-for-foo')
+
+mylib = env.Library('mylib.c')
+installed_lib = env.Install('lib', mylib)
+bar = env.Program('bar.c')
+
+# Arrange for the library to be copied into the installation
+# directory before trying to build the "bar" program.
+# (Note that this is for example only. A "real" library
+# dependency would normally be configured through the $LIBS
+# and $LIBPATH variables, not using an env.Depends() call.)
+
+env.Depends(bar, installed_lib)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.Dictionary([ vars ])
+Returns a dictionary object
+containing copies of all of the
+construction variables in the environment.
+If there are any variable names specified,
+only the specified construction
+variables are returned in the dictionary.
+
+Example:
+
+.ES
+dict = env.Dictionary()
+cc_dict = env.Dictionary('CC', 'CCFLAGS', 'CCCOM')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Dir( name ", [" directory ])
+.TP
+.RI env.Dir( name ", [" directory ])
+This returns a Directory Node,
+an object that represents the specified directory
+.IR name .
+.I name
+can be a relative or absolute path.
+.I directory
+is an optional directory that will be used as the parent directory.
+If no
+.I directory
+is specified, the current script's directory is used as the parent.
+
+If
+.I name
+is a list, SCons returns a list of Dir nodes.
+Construction variables are expanded in
+.IR name .
+
+Directory Nodes can be used anywhere you
+would supply a string as a directory name
+to a Builder method or function.
+Directory Nodes have attributes and methods
+that are useful in many situations;
+see "File and Directory Nodes," below.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.Dump([ key ])
+Returns a pretty printable representation of the environment.
+.IR key ,
+if not
+.IR None ,
+should be a string containing the name of the variable of interest.
+
+This SConstruct:
+.ES
+env=Environment()
+print env.Dump('CCCOM')
+.EE
+.IP
+will print:
+.ES
+\&'$CC -c -o $TARGET $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $SOURCES'
+.EE
+
+.ES
+env=Environment()
+print env.Dump()
+.EE
+.IP
+will print:
+.ES
+{ 'AR': 'ar',
+ 'ARCOM': '$AR $ARFLAGS $TARGET $SOURCES\n$RANLIB $RANLIBFLAGS $TARGET',
+ 'ARFLAGS': ['r'],
+ 'AS': 'as',
+ 'ASCOM': '$AS $ASFLAGS -o $TARGET $SOURCES',
+ 'ASFLAGS': [],
+ ...
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI EnsurePythonVersion( major ", " minor )
+.TP
+.RI env.EnsurePythonVersion( major ", " minor )
+Ensure that the Python version is at least
+.IR major . minor .
+This function will
+print out an error message and exit SCons with a non-zero exit code if the
+actual Python version is not late enough.
+
+Example:
+
+.ES
+EnsurePythonVersion(2,2)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI EnsureSConsVersion( major ", " minor ", [" revision ])
+.TP
+.RI env.EnsureSConsVersion( major ", " minor ", [" revision ])
+Ensure that the SCons version is at least
+.IR major.minor ,
+or
+.IR major.minor.revision .
+if
+.I revision
+is specified.
+This function will
+print out an error message and exit SCons with a non-zero exit code if the
+actual SCons version is not late enough.
+
+Examples:
+
+.ES
+EnsureSConsVersion(0,14)
+
+EnsureSConsVersion(0,96,90)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Environment([ key = value ", ...])"
+.TP
+.RI env.Environment([ key = value ", ...])"
+Return a new construction environment
+initialized with the specified
+.IR key = value
+pairs.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Execute( action ", [" strfunction ", " varlist ])
+.TP
+.RI env.Execute( action ", [" strfunction ", " varlist ])
+Executes an Action object.
+The specified
+.IR action
+may be an Action object
+(see the section "Action Objects,"
+below, for a complete explanation of the arguments and behavior),
+or it may be a command-line string,
+list of commands,
+or executable Python function,
+each of which will be converted
+into an Action object
+and then executed.
+The exit value of the command
+or return value of the Python function
+will be returned.
+
+Note that
+.B scons
+will print an error message if the executed
+.I action
+fails--that is,
+exits with or returns a non-zero value.
+.B scons
+will
+.I not ,
+however,
+automatically terminate the build
+if the specified
+.I action
+fails.
+If you want the build to stop in response to a failed
+.BR Execute ()
+call,
+you must explicitly check for a non-zero return value:
+
+.ES
+Execute(Copy('file.out', 'file.in'))
+
+if Execute("mkdir sub/dir/ectory"):
+ # The mkdir failed, don't try to build.
+ Exit(1)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Exit([ value ])
+.TP
+.RI env.Exit([ value ])
+This tells
+.B scons
+to exit immediately
+with the specified
+.IR value .
+A default exit value of
+.B 0
+(zero)
+is used if no value is specified.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Export( vars )
+.TP
+.RI env.Export( vars )
+This tells
+.B scons
+to export a list of variables from the current
+SConscript file to all other SConscript files.
+The exported variables are kept in a global collection,
+so subsequent calls to
+.BR Export ()
+will over-write previous exports that have the same name.
+Multiple variable names can be passed to
+.BR Export ()
+as separate arguments or as a list.
+Keyword arguments can be used to provide names and their values.
+A dictionary can be used to map variables to a different name when exported.
+Both local variables and global variables can be exported.
+
+Examples:
+
+.ES
+env = Environment()
+# Make env available for all SConscript files to Import().
+Export("env")
+
+package = 'my_name'
+# Make env and package available for all SConscript files:.
+Export("env", "package")
+
+# Make env and package available for all SConscript files:
+Export(["env", "package"])
+
+# Make env available using the name debug:
+Export(debug = env)
+
+# Make env available using the name debug:
+Export({"debug":env})
+.EE
+
+.IP
+Note that the
+.BR SConscript ()
+function supports an
+.I exports
+argument that makes it easier to to export a variable or
+set of variables to a single SConscript file.
+See the description of the
+.BR SConscript ()
+function, below.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI File( name ", [" directory ])
+.TP
+.RI env.File( name ", [" directory ])
+This returns a
+File Node,
+an object that represents the specified file
+.IR name .
+.I name
+can be a relative or absolute path.
+.I directory
+is an optional directory that will be used as the parent directory.
+
+If
+.I name
+is a list, SCons returns a list of File nodes.
+Construction variables are expanded in
+.IR name .
+
+File Nodes can be used anywhere you
+would supply a string as a file name
+to a Builder method or function.
+File Nodes have attributes and methods
+that are useful in many situations;
+see "File and Directory Nodes," below.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI FindFile( file ", " dirs )
+.TP
+.RI env.FindFile( file ", " dirs )
+Search for
+.I file
+in the path specified by
+.IR dirs .
+.I dirs
+may be a list of directory names or a single directory name.
+In addition to searching for files that exist in the filesytem,
+this function also searches for derived files
+that have not yet been built.
+
+Example:
+
+.ES
+foo = env.FindFile('foo', ['dir1', 'dir2'])
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI FindInstalledFiles( )
+.TP
+.RI env.FindInstalledFiles( )
+Returns the list of targets set up by the
+.B Install()
+or
+.B InstallAs()
+builders.
+
+This function serves as a convenient method to select the contents of
+a binary package.
+
+Example:
+
+.ES
+Install( '/bin', [ 'executable_a', 'executable_b' ] )
+
+# will return the file node list
+# [ '/bin/executable_a', '/bin/executable_b' ]
+FindInstalledFiles()
+
+Install( '/lib', [ 'some_library' ] )
+
+# will return the file node list
+# [ '/bin/executable_a', '/bin/executable_b', '/lib/some_library' ]
+FindInstalledFiles()
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI FindSourceFiles( node = '"."' )
+.TP
+.RI env.FindSourceFiles( node = '"."' )
+
+Returns the list of nodes which serve as the source of the built files.
+It does so by inspecting the dependency tree starting at the optional
+argument
+.B node
+which defaults to the '"."'-node. It will then return all leaves of
+.B node.
+These are all children which have no further children.
+
+This function is a convenient method to select the contents of a Source
+Package.
+
+Example:
+
+.ES
+Program( 'src/main_a.c' )
+Program( 'src/main_b.c' )
+Program( 'main_c.c' )
+
+# returns ['main_c.c', 'src/main_a.c', 'SConstruct', 'src/main_b.c']
+FindSourceFiles()
+
+# returns ['src/main_b.c', 'src/main_a.c' ]
+FindSourceFiles( 'src' )
+.EE
+
+.IP
+As you can see build support files (SConstruct in the above example)
+will also be returned by this function.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI FindPathDirs( variable )
+Returns a function
+(actually a callable Python object)
+intended to be used as the
+.B path_function
+of a Scanner object.
+The returned object will look up the specified
+.I variable
+in a construction environment
+and treat the construction variable's value as a list of
+directory paths that should be searched
+(like
+.BR CPPPATH ,
+.BR LIBPATH ,
+etc.).
+
+Note that use of
+.BR FindPathDirs ()
+is generally preferable to
+writing your own
+.B path_function
+for the following reasons:
+1) The returned list will contain all appropriate directories
+found in source trees
+(when
+.BR VariantDir ()
+is used)
+or in code repositories
+(when
+.BR Repository ()
+or the
+.B \-Y
+option are used).
+2) scons will identify expansions of
+.I variable
+that evaluate to the same list of directories as,
+in fact, the same list,
+and avoid re-scanning the directories for files,
+when possible.
+
+Example:
+
+.ES
+def my_scan(node, env, path, arg):
+ # Code to scan file contents goes here...
+ return include_files
+
+scanner = Scanner(name = 'myscanner',
+ function = my_scan,
+ path_function = FindPathDirs('MYPATH'))
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Flatten( sequence )
+.TP
+.RI env.Flatten( sequence )
+Takes a sequence (that is, a Python list or tuple)
+that may contain nested sequences
+and returns a flattened list containing
+all of the individual elements in any sequence.
+This can be helpful for collecting
+the lists returned by calls to Builders;
+other Builders will automatically
+flatten lists specified as input,
+but direct Python manipulation of
+these lists does not.
+
+Examples:
+
+.ES
+foo = Object('foo.c')
+bar = Object('bar.c')
+
+# Because `foo' and `bar' are lists returned by the Object() Builder,
+# `objects' will be a list containing nested lists:
+objects = ['f1.o', foo, 'f2.o', bar, 'f3.o']
+
+# Passing such a list to another Builder is all right because
+# the Builder will flatten the list automatically:
+Program(source = objects)
+
+# If you need to manipulate the list directly using Python, you need to
+# call Flatten() yourself, or otherwise handle nested lists:
+for object in Flatten(objects):
+ print str(object)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI GetBuildFailures()
+Returns a list of exceptions for the
+actions that failed while
+attempting to build targets.
+Each element in the returned list is a
+.B BuildError
+object
+with the following attributes
+that record various aspects
+of the build failure:
+
+.B .node
+The node that was being built
+when the build failure occurred.
+
+.B .status
+The numeric exit status
+returned by the command or Python function
+that failed when trying to build the
+specified Node.
+
+.B .errstr
+The SCons error string
+describing the build failure.
+(This is often a generic
+message like "Error 2"
+to indicate that an executed
+command exited with a status of 2.)
+
+.B .filename
+The name of the file or
+directory that actually caused the failure.
+This may be different from the
+.B .node
+attribute.
+For example,
+if an attempt to build a target named
+.B sub/dir/target
+fails because the
+.B sub/dir
+directory could not be created,
+then the
+.B .node
+attribute will be
+.B sub/dir/target
+but the
+.B .filename
+attribute will be
+.BR sub/dir .
+
+.B .executor
+The SCons Executor object
+for the target Node
+being built.
+This can be used to retrieve
+the construction environment used
+for the failed action.
+
+.B .action
+The actual SCons Action object that failed.
+This will be one specific action
+out of the possible list of
+actions that would have been
+executed to build the target.
+
+.B .command
+The actual expanded command that was executed and failed,
+after expansion of
+.BR $TARGET ,
+.BR $SOURCE ,
+and other construction variables.
+
+Note that the
+.BR GetBuildFailures ()
+function
+will always return an empty list
+until any build failure has occurred,
+which means that
+.BR GetBuildFailures ()
+will always return an empty list
+while the
+.B SConscript
+files are being read.
+Its primary intended use is
+for functions that will be
+executed before SCons exits
+by passing them to the
+standard Python
+.BR atexit.register ()
+function.
+Example:
+
+.ES
+import atexit
+
+def print_build_failures():
+ from SCons.Script import GetBuildFailures
+ for bf in GetBuildFailures():
+ print "%s failed: %s" % (bf.node, bf.errstr)
+
+atexit.register(print_build_failures)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI GetBuildPath( file ", [" ... ])
+.TP
+.RI env.GetBuildPath( file ", [" ... ])
+Returns the
+.B scons
+path name (or names) for the specified
+.I file
+(or files).
+The specified
+.I file
+or files
+may be
+.B scons
+Nodes or strings representing path names.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI GetLaunchDir()
+.TP
+.RI env.GetLaunchDir()
+Returns the absolute path name of the directory from which
+.B scons
+was initially invoked.
+This can be useful when using the
+.BR \-u ,
+.BR \-U
+or
+.BR \-D
+options, which internally
+change to the directory in which the
+.B SConstruct
+file is found.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI GetOption( name )
+.TP
+.RI env.GetOption( name )
+This function provides a way to query the value of
+SCons options set on scons command line
+(or set using the
+.IR SetOption ()
+function).
+The options supported are:
+
+.RS 10
+.TP 6
+.B cache_debug
+which corresponds to --cache-debug;
+.TP 6
+.B cache_disable
+which corresponds to --cache-disable;
+.TP 6
+.B cache_force
+which corresponds to --cache-force;
+.TP 6
+.B cache_show
+which corresponds to --cache-show;
+.TP 6
+.B clean
+which corresponds to -c, --clean and --remove;
+.TP 6
+.B config
+which corresponds to --config;
+.TP 6
+.B directory
+which corresponds to -C and --directory;
+.TP 6
+.B diskcheck
+which corresponds to --diskcheck
+.TP 6
+.B duplicate
+which corresponds to --duplicate;
+.TP 6
+.B file
+which corresponds to -f, --file, --makefile and --sconstruct;
+.TP 6
+.B help
+which corresponds to -h and --help;
+.TP 6
+.B ignore_errors
+which corresponds to --ignore-errors;
+.TP 6
+.B implicit_cache
+which corresponds to --implicit-cache;
+.TP 6
+.B implicit_deps_changed
+which corresponds to --implicit-deps-changed;
+.TP 6
+.B implicit_deps_unchanged
+which corresponds to --implicit-deps-unchanged;
+.TP 6
+.B interactive
+which corresponds to --interact and --interactive;
+.TP 6
+.B keep_going
+which corresponds to -k and --keep-going;
+.TP 6
+.B max_drift
+which corresponds to --max-drift;
+.TP 6
+.B no_exec
+which corresponds to -n, --no-exec, --just-print, --dry-run and --recon;
+.TP 6
+.B no_site_dir
+which corresponds to --no-site-dir;
+.TP 6
+.B num_jobs
+which corresponds to -j and --jobs;
+.TP 6
+.B profile_file
+which corresponds to --profile;
+.TP 6
+.B question
+which corresponds to -q and --question;
+.TP 6
+.B random
+which corresponds to --random;
+.TP 6
+.B repository
+which corresponds to -Y, --repository and --srcdir;
+.TP 6
+.B silent
+which corresponds to -s, --silent and --quiet;
+.TP 6
+.B site_dir
+which corresponds to --site-dir;
+.TP 6
+.B stack_size
+which corresponds to --stack-size;
+.TP 6
+.B taskmastertrace_file
+which corresponds to --taskmastertrace; and
+.TP 6
+.B warn
+which corresponds to --warn and --warning.
+.RE
+
+.IP
+See the documentation for the
+corresponding command line object for information about each specific
+option.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Glob( pattern ", [" ondisk ", " source ", " strings ])
+.TP
+.RI env.Glob( pattern ", [" ondisk ", " source ", " strings ])
+Returns Nodes (or strings) that match the specified
+.IR pattern ,
+relative to the directory of the current
+.B SConscript
+file.
+The
+.BR env.Glob ()
+form performs string substition on
+.I pattern
+and returns whatever matches
+the resulting expanded pattern.
+
+The specified
+.I pattern
+uses Unix shell style metacharacters for matching:
+
+.ES
+ * matches everything
+ ? matches any single character
+ [seq] matches any character in seq
+ [!seq] matches any char not in seq
+.EE
+
+.IP
+If the first character of a filename is a dot,
+it must be matched explicitly.
+Character matches do
+.I not
+span directory separators.
+
+The
+.BR Glob ()
+knows about
+repositories
+(see the
+.BR Repository ()
+function)
+and source directories
+(see the
+.BR VariantDir ()
+function)
+and
+returns a Node (or string, if so configured)
+in the local (SConscript) directory
+if matching Node is found
+anywhere in a corresponding
+repository or source directory.
+
+The
+.B ondisk
+argument may be set to
+.B False
+(or any other non-true value)
+to disable the search for matches on disk,
+thereby only returning matches among
+already-configured File or Dir Nodes.
+The default behavior is to
+return corresponding Nodes
+for any on-disk matches found.
+
+The
+.B source
+argument may be set to
+.B True
+(or any equivalent value)
+to specify that,
+when the local directory is a
+.BR VariantDir (),
+the returned Nodes should be from the
+corresponding source directory,
+not the local directory.
+
+The
+.B strings
+argument may be set to
+.B True
+(or any equivalent value)
+to have the
+.BR Glob ()
+function return strings, not Nodes,
+that represent the matched files or directories.
+The returned strings will be relative to
+the local (SConscript) directory.
+(Note that This may make it easier to perform
+arbitrary manipulation of file names,
+but if the returned strings are
+passed to a different
+.B SConscript
+file,
+any Node translation will be relative
+to the other
+.B SConscript
+directory,
+not the original
+.B SConscript
+directory.)
+
+Examples:
+
+.ES
+Program('foo', Glob('*.c'))
+Zip('/tmp/everything', Glob('.??*') + Glob('*'))
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+'\".TP
+'\".RI GlobalBuilders( flag )
+'\"When
+'\".B flag
+'\"is non-zero,
+'\"adds the names of the default builders
+'\"(Program, Library, etc.)
+'\"to the global name space
+'\"so they can be called without an explicit construction environment.
+'\"(This is the default.)
+'\"When
+'\".B
+'\"flag is zero,
+'\"the names of the default builders are removed
+'\"from the global name space
+'\"so that an explicit construction environment is required
+'\"to call all builders.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Help( text )
+.TP
+.RI env.Help( text )
+This specifies help text to be printed if the
+.B -h
+argument is given to
+.BR scons .
+If
+.BR Help
+is called multiple times, the text is appended together in the order
+that
+.BR Help
+is called.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Ignore( target ", " dependency )
+.TP
+.RI env.Ignore( target ", " dependency )
+The specified dependency file(s)
+will be ignored when deciding if
+the target file(s) need to be rebuilt.
+
+You can also use
+.BR Ignore()
+to remove a target from the default build.
+In order to do this you must specify the directory the target will
+be built in as the target, and the file you want to skip building
+as the dependency.
+
+Note that this will only remove the dependencies listed from
+the files built by default. It will still be built if that
+dependency is needed by another object being built.
+See the third and forth examples below.
+
+Examples:
+
+.ES
+env.Ignore('foo', 'foo.c')
+env.Ignore('bar', ['bar1.h', 'bar2.h'])
+env.Ignore('.','foobar.obj')
+env.Ignore('bar','bar/foobar.obj')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Import( vars )
+.TP
+.RI env.Import( vars )
+This tells
+.B scons
+to import a list of variables into the current SConscript file. This
+will import variables that were exported with
+.BR Export ()
+or in the
+.I exports
+argument to
+.BR SConscript ().
+Variables exported by
+.BR SConscript ()
+have precedence.
+Multiple variable names can be passed to
+.BR Import ()
+as separate arguments or as a list. The variable "*" can be used
+to import all variables.
+
+Examples:
+
+.ES
+Import("env")
+Import("env", "variable")
+Import(["env", "variable"])
+Import("*")
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Literal( string )
+.TP
+.RI env.Literal( string )
+The specified
+.I string
+will be preserved as-is
+and not have construction variables expanded.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Local( targets )
+.TP
+.RI env.Local( targets )
+The specified
+.I targets
+will have copies made in the local tree,
+even if an already up-to-date copy
+exists in a repository.
+Returns a list of the target Node or Nodes.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+\" .TP
+\" .RI env.MergeShellPaths( arg ", [" prepend ])
+\" Merges the elements of the specified
+\" .IR arg ,
+\" which must be a dictionary, to the construction
+\" environment's copy of the shell environment
+\" in env['ENV'].
+\" (This is the environment which is passed
+\" to subshells spawned by SCons.)
+\" Note that
+\" .I arg
+\" must be a single value,
+\" so multiple strings must
+\" be passed in as a list,
+\" not as separate arguments to
+\" .BR env.MergeShellPaths ().
+
+\" New values are prepended to the environment variable by default,
+\" unless prepend=0 is specified.
+\" Duplicate values are always eliminated,
+\" since this function calls
+\" .B AppendENVPath
+\" or
+\" .B PrependENVPath
+\" depending on the
+\" .I prepend
+\" argument. See those functions for more details.
+
+\" Examples:
+
+\" .ES
+\" # Prepend a path to the shell PATH.
+\" env.MergeShellPaths({'PATH':'/usr/local/bin'} )
+\" # Append two dirs to the shell INCLUDE.
+\" env.MergeShellPaths({'INCLUDE':['c:/inc1', 'c:/inc2']}, prepend=0 )
+
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.MergeFlags( arg ", [" unique ])
+Merges the specified
+.I arg
+values to the construction environment's construction variables.
+If the
+.I arg
+argument is not a dictionary,
+it is converted to one by calling
+.B env.ParseFlags()
+on the argument
+before the values are merged.
+Note that
+.I arg
+must be a single value,
+so multiple strings must
+be passed in as a list,
+not as separate arguments to
+.BR env.MergeFlags ().
+
+By default,
+duplicate values are eliminated;
+you can, however, specify
+.B unique=0
+to allow duplicate
+values to be added.
+When eliminating duplicate values,
+any construction variables that end with
+the string
+.B PATH
+keep the left-most unique value.
+All other construction variables keep
+the right-most unique value.
+
+Examples:
+
+.ES
+# Add an optimization flag to $CCFLAGS.
+env.MergeFlags('-O3')
+
+# Combine the flags returned from running pkg-config with an optimization
+# flag and merge the result into the construction variables.
+env.MergeFlags(['!pkg-config gtk+-2.0 --cflags', '-O3'])
+
+# Combine an optimization flag with the flags returned from running pkg-config
+# twice and merge the result into the construction variables.
+env.MergeFlags(['-O3',
+ '!pkg-config gtk+-2.0 --cflags --libs',
+ '!pkg-config libpng12 --cflags --libs'])
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI NoCache( target ", ...)"
+.TP
+.RI env.NoCache( target ", ...)"
+Specifies a list of files which should
+.I not
+be cached whenever the
+.BR CacheDir ()
+method has been activated.
+The specified targets may be a list
+or an individual target.
+
+Multiple files should be specified
+either as separate arguments to the
+.BR NoCache ()
+method, or as a list.
+.BR NoCache ()
+will also accept the return value of any of the construction environment
+Builder methods.
+
+Calling
+.BR NoCache ()
+on directories and other non-File Node types has no effect because
+only File Nodes are cached.
+
+Examples:
+
+.ES
+NoCache('foo.elf')
+NoCache(env.Program('hello', 'hello.c'))
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI NoClean( target ", ...)"
+.TP
+.RI env.NoClean( target ", ...)"
+Specifies a list of files or directories which should
+.I not
+be removed whenever the targets (or their dependencies)
+are specified with the
+.B -c
+command line option.
+The specified targets may be a list
+or an individual target.
+Multiple calls to
+.BR NoClean ()
+are legal,
+and prevent each specified target
+from being removed by calls to the
+.B -c
+option.
+
+Multiple files or directories should be specified
+either as separate arguments to the
+.BR NoClean ()
+method, or as a list.
+.BR NoClean ()
+will also accept the return value of any of the construction environment
+Builder methods.
+
+Calling
+.BR NoClean ()
+for a target overrides calling
+.BR Clean ()
+for the same target,
+and any targets passed to both functions will
+.I not
+be removed by the
+.B -c
+option.
+
+Examples:
+
+.ES
+NoClean('foo.elf')
+NoClean(env.Program('hello', 'hello.c'))
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.ParseConfig( command ", [" function ", " unique ])
+Calls the specified
+.I function
+to modify the environment as specified by the output of
+.I command .
+The default
+.I function
+is
+.BR env.MergeFlags (),
+which expects the output of a typical
+.I *-config command
+(for example,
+.BR gtk-config )
+and adds the options
+to the appropriate construction variables.
+By default,
+duplicate values are not
+added to any construction variables;
+you can specify
+.B unique=0
+to allow duplicate
+values to be added.
+
+Interpreted options
+and the construction variables they affect
+are as specified for the
+.BR env.ParseFlags ()
+method (which this method calls).
+See that method's description, below,
+for a table of options and construction variables.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI ParseDepends( filename ", [" must_exist ", " only_one ])
+.TP
+.RI env.ParseDepends( filename ", [" must_exist ", " only_one ])
+Parses the contents of the specified
+.I filename
+as a list of dependencies in the style of
+.BR Make
+or
+.BR mkdep ,
+and explicitly establishes all of the listed dependencies.
+
+By default,
+it is not an error
+if the specified
+.I filename
+does not exist.
+The optional
+.I must_exist
+argument may be set to a non-zero
+value to have
+scons
+throw an exception and
+generate an error if the file does not exist,
+or is otherwise inaccessible.
+
+The optional
+.I only_one
+argument may be set to a non-zero
+value to have
+scons
+thrown an exception and
+generate an error
+if the file contains dependency
+information for more than one target.
+This can provide a small sanity check
+for files intended to be generated
+by, for example, the
+.B gcc -M
+flag,
+which should typically only
+write dependency information for
+one output file into a corresponding
+.B .d
+file.
+
+The
+.I filename
+and all of the files listed therein
+will be interpreted relative to
+the directory of the
+.I SConscript
+file which calls the
+.B ParseDepends
+function.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.ParseFlags( flags ", ...)"
+Parses one or more strings containing
+typical command-line flags for GCC tool chains
+and returns a dictionary with the flag values
+separated into the appropriate SCons construction variables.
+This is intended as a companion to the
+.BR env.MergeFlags ()
+method, but allows for the values in the returned dictionary
+to be modified, if necessary,
+before merging them into the construction environment.
+(Note that
+.BR env.MergeFlags ()
+will call this method if its argument is not a dictionary,
+so it is usually not necessary to call
+.BR env.ParseFlags ()
+directly unless you want to manipulate the values.)
+
+If the first character in any string is
+an exclamation mark (!),
+the rest of the string is executed as a command,
+and the output from the command is
+parsed as GCC tool chain command-line flags
+and added to the resulting dictionary.
+
+Flag values are translated accordig to the prefix found,
+and added to the following construction variables:
+
+.ES
+-arch CCFLAGS, LINKFLAGS
+-D CPPDEFINES
+-framework FRAMEWORKS
+-frameworkdir= FRAMEWORKPATH
+-include CCFLAGS
+-isysroot CCFLAGS, LINKFLAGS
+-I CPPPATH
+-l LIBS
+-L LIBPATH
+-mno-cygwin CCFLAGS, LINKFLAGS
+-mwindows LINKFLAGS
+-pthread CCFLAGS, LINKFLAGS
+-std= CFLAGS
+-Wa, ASFLAGS, CCFLAGS
+-Wl,-rpath= RPATH
+-Wl,-R, RPATH
+-Wl,-R RPATH
+-Wl, LINKFLAGS
+-Wp, CPPFLAGS
+- CCFLAGS
++ CCFLAGS, LINKFLAGS
+.EE
+
+.IP
+Any other strings not associated with options
+are assumed to be the names of libraries
+and added to the
+.B LIBS
+construction variable.
+
+Examples (all of which produce the same result):
+
+.ES
+dict = env.ParseFlags('-O2 -Dfoo -Dbar=1')
+dict = env.ParseFlags('-O2', '-Dfoo', '-Dbar=1')
+dict = env.ParseFlags(['-O2', '-Dfoo -Dbar=1'])
+dict = env.ParseFlags('-O2', '!echo -Dfoo -Dbar=1')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+env.Perforce()
+A factory function that
+returns a Builder object
+to be used to fetch source files
+from the Perforce source code management system.
+The returned Builder
+is intended to be passed to the
+.B SourceCode
+function.
+
+Example:
+
+.ES
+env.SourceCode('.', env.Perforce())
+.EE
+.IP
+Perforce uses a number of external
+environment variables for its operation.
+Consequently, this function adds the
+following variables from the user's external environment
+to the construction environment's
+ENV dictionary:
+P4CHARSET,
+P4CLIENT,
+P4LANGUAGE,
+P4PASSWD,
+P4PORT,
+P4USER,
+SystemRoot,
+USER,
+and
+USERNAME.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Platform( string )
+Returns a callable object
+that can be used to initialize
+a construction environment using the
+platform keyword of the Environment() method.
+
+Example:
+
+.ES
+env = Environment(platform = Platform('win32'))
+.EE
+.TP
+.RI env.Platform( string )
+Applies the callable object for the specified platform
+.I string
+to the environment through which the method was called.
+
+.ES
+env.Platform('posix')
+.EE
+.IP
+Note that the
+.B win32
+platform adds the
+.B SystemDrive
+and
+.B SystemRoot
+variables from the user's external environment
+to the construction environment's
+.B ENV
+dictionary.
+This is so that any executed commands
+that use sockets to connect with other systems
+(such as fetching source files from
+external CVS repository specifications like
+.BR :pserver:anonymous@cvs.sourceforge.net:/cvsroot/scons )
+will work on Windows systems.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Progress( callable ", [" interval ])
+.TP
+.RI Progress( string ", [" interval ", " file ", " overwrite ])
+.TP
+.RI Progress( list_of_strings ", [" interval ", " file ", " overwrite ])
+Allows SCons to show progress made during the build
+by displaying a string or calling a function while
+evaluating Nodes (e.g. files).
+
+If the first specified argument is a Python callable
+(a function or an object that has a
+.BR __call__ ()
+method),
+the function will be called
+once every
+.I interval
+times a Node is evaluated.
+The callable will be passed the evaluated Node
+as its only argument.
+(For future compatibility,
+it's a good idea to also add
+.B *args
+and
+.B **kw
+as arguments to your function or method.
+This will prevent the code from breaking
+if SCons ever changes the interface
+to call the function with additional arguments in the future.)
+
+An example of a simple custom progress function
+that prints a string containing the Node name
+every 10 Nodes:
+
+.ES
+def my_progress_function(node, *args, **kw):
+ print 'Evaluating node %s!' % node
+Progress(my_progress_function, interval=10)
+.EE
+.IP
+A more complicated example of a custom progress display object
+that prints a string containing a count
+every 100 evaluated Nodes.
+Note the use of
+.B \\\\r
+(a carriage return)
+at the end so that the string
+will overwrite itself on a display:
+
+.ES
+import sys
+class ProgressCounter:
+ count = 0
+ def __call__(self, node, *args, **kw):
+ self.count += 100
+ sys.stderr.write('Evaluated %s nodes\\r' % self.count)
+Progress(ProgressCounter(), interval=100)
+.EE
+.IP
+If the first argument
+.BR Progress ()
+is a string,
+the string will be displayed
+every
+.I interval
+evaluated Nodes.
+The default is to print the string on standard output;
+an alternate output stream
+may be specified with the
+.B file=
+argument.
+The following will print a series of dots
+on the error output,
+one dot for every 100 evaluated Nodes:
+
+.ES
+import sys
+Progress('.', interval=100, file=sys.stderr)
+.EE
+.IP
+If the string contains the verbatim substring
+.B $TARGET,
+it will be replaced with the Node.
+Note that, for performance reasons, this is
+.I not
+a regular SCons variable substition,
+so you can not use other variables
+or use curly braces.
+The following example will print the name of
+every evaluated Node,
+using a
+.B \\\\r
+(carriage return) to cause each line to overwritten by the next line,
+and the
+.B overwrite=
+keyword argument to make sure the previously-printed
+file name is overwritten with blank spaces:
+
+.ES
+import sys
+Progress('$TARGET\\r', overwrite=True)
+.EE
+.IP
+If the first argument to
+.BR Progress ()
+is a list of strings,
+then each string in the list will be displayed
+in rotating fashion every
+.I interval
+evaluated Nodes.
+This can be used to implement a "spinner"
+on the user's screen as follows:
+
+.ES
+Progress(['-\\r', '\\\\\\r', '|\\r', '/\\r'], interval=5)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Precious( target ", ...)"
+.TP
+.RI env.Precious( target ", ...)"
+Marks each given
+.I target
+as precious so it is not deleted before it is rebuilt. Normally
+.B scons
+deletes a target before building it.
+Multiple targets can be passed in to a single call to
+.BR Precious ().
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.Prepend( key = val ", [...])"
+Appends the specified keyword arguments
+to the beginning of construction variables in the environment.
+If the Environment does not have
+the specified construction variable,
+it is simply added to the environment.
+If the values of the construction variable
+and the keyword argument are the same type,
+then the two values will be simply added together.
+Otherwise, the construction variable
+and the value of the keyword argument
+are both coerced to lists,
+and the lists are added together.
+(See also the Append method, above.)
+
+Example:
+
+.ES
+env.Prepend(CCFLAGS = '-g ', FOO = ['foo.yyy'])
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.PrependENVPath( name ", " newpath ", [" envname ", " sep ", " delete_existing ])
+This appends new path elements to the given path in the
+specified external environment
+.RB ( ENV
+by default).
+This will only add
+any particular path once (leaving the first one it encounters and
+ignoring the rest, to preserve path order),
+and to help assure this,
+will normalize all paths (using
+.B os.path.normpath
+and
+.BR os.path.normcase ).
+This can also handle the
+case where the given old path variable is a list instead of a
+string, in which case a list will be returned instead of a string.
+
+If
+.I delete_existing
+is 0, then adding a path that already exists
+will not move it to the beginning;
+it will stay where it is in the list.
+
+Example:
+
+.ES
+print 'before:',env['ENV']['INCLUDE']
+include_path = '/foo/bar:/foo'
+env.PrependENVPath('INCLUDE', include_path)
+print 'after:',env['ENV']['INCLUDE']
+.EE
+
+The above exmaple will print:
+
+.ES
+before: /biz:/foo
+after: /foo/bar:/foo:/biz
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.PrependUnique( key = val ", delete_existing=0, [...])"
+Appends the specified keyword arguments
+to the beginning of construction variables in the environment.
+If the Environment does not have
+the specified construction variable,
+it is simply added to the environment.
+If the construction variable being appended to is a list,
+then any value(s) that already exist in the
+construction variable will
+.I not
+be added again to the list.
+However, if delete_existing is 1,
+existing matching values are removed first, so
+existing values in the arg list move to the front of the list.
+
+Example:
+
+.ES
+env.PrependUnique(CCFLAGS = '-g', FOO = ['foo.yyy'])
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+env.RCS()
+A factory function that
+returns a Builder object
+to be used to fetch source files
+from RCS.
+The returned Builder
+is intended to be passed to the
+.B SourceCode
+function:
+
+Examples:
+
+.ES
+env.SourceCode('.', env.RCS())
+.EE
+.IP
+Note that
+.B scons
+will fetch source files
+from RCS subdirectories automatically,
+so configuring RCS
+as demonstrated in the above example
+should only be necessary if
+you are fetching from
+RCS,v
+files in the same
+directory as the source files,
+or if you need to explicitly specify RCS
+for a specific subdirectory.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.Replace( key = val ", [...])"
+Replaces construction variables in the Environment
+with the specified keyword arguments.
+
+Example:
+
+.ES
+env.Replace(CCFLAGS = '-g', FOO = 'foo.xxx')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Repository( directory )
+.TP
+.RI env.Repository( directory )
+Specifies that
+.I directory
+is a repository to be searched for files.
+Multiple calls to
+.BR Repository ()
+are legal,
+and each one adds to the list of
+repositories that will be searched.
+
+To
+.BR scons ,
+a repository is a copy of the source tree,
+from the top-level directory on down,
+which may contain
+both source files and derived files
+that can be used to build targets in
+the local source tree.
+The canonical example would be an
+official source tree maintained by an integrator.
+If the repository contains derived files,
+then the derived files should have been built using
+.BR scons ,
+so that the repository contains the necessary
+signature information to allow
+.B scons
+to figure out when it is appropriate to
+use the repository copy of a derived file,
+instead of building one locally.
+
+Note that if an up-to-date derived file
+already exists in a repository,
+.B scons
+will
+.I not
+make a copy in the local directory tree.
+In order to guarantee that a local copy
+will be made,
+use the
+.B Local()
+method.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Requires( target ", " prerequisite )
+.TP
+.RI env.Requires( target ", " prerequisite )
+Specifies an order-only relationship
+between the specified target file(s)
+and the specified prerequisite file(s).
+The prerequisite file(s)
+will be (re)built, if necessary,
+.I before
+the target file(s),
+but the target file(s) do not actually
+depend on the prerequisites
+and will not be rebuilt simply because
+the prerequisite file(s) change.
+
+Example:
+
+.ES
+env.Requires('foo', 'file-that-must-be-built-before-foo')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Return([ vars "... , " stop= ])
+By default,
+this stops processing the current SConscript
+file and returns to the calling SConscript file
+the values of the variables named in the
+.I vars
+string arguments.
+Multiple strings contaning variable names may be passed to
+.BR Return ().
+Any strings that contain white space
+
+The optional
+.B stop=
+keyword argument may be set to a false value
+to continue processing the rest of the SConscript
+file after the
+.BR Return ()
+call.
+This was the default behavior prior to SCons 0.98.
+However, the values returned
+are still the values of the variables in the named
+.I vars
+at the point
+.BR Return ()
+is called.
+
+Examples:
+
+.ES
+# Returns without returning a value.
+Return()
+
+# Returns the value of the 'foo' Python variable.
+Return("foo")
+
+# Returns the values of the Python variables 'foo' and 'bar'.
+Return("foo", "bar")
+
+# Returns the values of Python variables 'val1' and 'val2'.
+Return('val1 val2')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Scanner( function ", [" argument ", " keys ", " path_function ", " node_class ", " node_factory ", " scan_check ", " recursive ])
+.TP
+.RI env.Scanner( function ", [" argument ", " keys ", " path_function ", " node_class ", " node_factory ", " scan_check ", " recursive ])
+Creates a Scanner object for
+the specified
+.IR function .
+See the section "Scanner Objects,"
+below, for a complete explanation of the arguments and behavior.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+env.SCCS()
+A factory function that
+returns a Builder object
+to be used to fetch source files
+from SCCS.
+The returned Builder
+is intended to be passed to the
+.B SourceCode
+function.
+
+Example:
+
+.ES
+env.SourceCode('.', env.SCCS())
+.EE
+.IP
+Note that
+.B scons
+will fetch source files
+from SCCS subdirectories automatically,
+so configuring SCCS
+as demonstrated in the above example
+should only be necessary if
+you are fetching from
+.I s.SCCS
+files in the same
+directory as the source files,
+or if you need to explicitly specify SCCS
+for a specific subdirectory.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI SConscript( scripts ", [" exports ", " variant_dir ", " duplicate ])
+'\" .RI SConscript( scripts ", [" exports ", " variant_dir ", " src_dir ", " duplicate ])
+.TP
+.RI env.SConscript( scripts ", [" exports ", " variant_dir ", " duplicate ])
+'\" .RI env.SConscript( scripts ", [" exports ", " variant_dir ", " src_dir ", " duplicate ])
+.TP
+.RI SConscript(dirs= subdirs ", [name=" script ", " exports ", " variant_dir ", " duplicate ])
+'\" .RI SConscript(dirs= subdirs ", [name=" script ", " exports ", " variant_dir ", " src_dir ", " duplicate ])
+.TP
+.RI env.SConscript(dirs= subdirs ", [name=" script ", " exports ", " variant_dir ", " duplicate ])
+'\" .RI env.SConscript(dirs= subdirs ", [name=" script ", " exports ", " variant_dir ", " src_dir ", " duplicate ])
+This tells
+.B scons
+to execute
+one or more subsidiary SConscript (configuration) files.
+Any variables returned by a called script using
+.BR Return ()
+will be returned by the call to
+.BR SConscript ().
+There are two ways to call the
+.BR SConscript ()
+function.
+
+The first way you can call
+.BR SConscript ()
+is to explicitly specify one or more
+.I scripts
+as the first argument.
+A single script may be specified as a string;
+multiple scripts must be specified as a list
+(either explicitly or as created by
+a function like
+.BR Split ()).
+Examples:
+.ES
+SConscript('SConscript') # run SConscript in the current directory
+SConscript('src/SConscript') # run SConscript in the src directory
+SConscript(['src/SConscript', 'doc/SConscript'])
+config = SConscript('MyConfig.py')
+.EE
+
+The second way you can call
+.BR SConscript ()
+is to specify a list of (sub)directory names
+as a
+.RI dirs= subdirs
+keyword argument.
+In this case,
+.B scons
+will, by default,
+execute a subsidiary configuration file named
+.B SConscript
+in each of the specified directories.
+You may specify a name other than
+.B SConscript
+by supplying an optional
+.RI name= script
+keyword argument.
+The first three examples below have the same effect
+as the first three examples above:
+.ES
+SConscript(dirs='.') # run SConscript in the current directory
+SConscript(dirs='src') # run SConscript in the src directory
+SConscript(dirs=['src', 'doc'])
+SConscript(dirs=['sub1', 'sub2'], name='MySConscript')
+.EE
+
+The optional
+.I exports
+argument provides a list of variable names or a dictionary of
+named values to export to the
+.IR script(s) .
+These variables are locally exported only to the specified
+.IR script(s) ,
+and do not affect the global pool of variables used by the
+.BR Export ()
+function.
+'\"If multiple dirs are provided, each script gets a fresh export.
+The subsidiary
+.I script(s)
+must use the
+.BR Import ()
+function to import the variables.
+Examples:
+.ES
+foo = SConscript('sub/SConscript', exports='env')
+SConscript('dir/SConscript', exports=['env', 'variable'])
+SConscript(dirs='subdir', exports='env variable')
+SConscript(dirs=['one', 'two', 'three'], exports='shared_info')
+.EE
+
+If the optional
+.I variant_dir
+argument is present, it causes an effect equivalent to the
+.BR VariantDir ()
+method described below.
+(If
+.I variant_dir
+is not present, the
+'\" .IR src_dir and
+.I duplicate
+'\" arguments are ignored.)
+argument is ignored.)
+The
+.I variant_dir
+'\" and
+'\" .I src_dir
+'\" arguments are interpreted relative to the directory of the calling
+argument is interpreted relative to the directory of the calling
+.BR SConscript file.
+See the description of the
+.BR VariantDir ()
+function below for additional details and restrictions.
+
+If
+'\" .IR variant_dir " is present, but"
+'\" .IR src_dir " is not,"
+.IR variant_dir " is present,"
+the source directory is relative to the called
+.BR SConscript " file."
+.ES
+SConscript('src/SConscript', variant_dir = 'build')
+.EE
+is equivalent to
+.ES
+VariantDir('build', 'src')
+SConscript('build/SConscript')
+.EE
+This later paradigm is often used when the sources are
+in the same directory as the
+.BR SConstruct file:
+.ES
+SConscript('SConscript', variant_dir = 'build')
+.EE
+is equivalent to
+.ES
+VariantDir('build', '.')
+SConscript('build/SConscript')
+.EE
+
+'\" If
+'\" .IR variant_dir " and"
+'\" .IR src_dir " are both present,"
+'\" xxxxx everything is in a state of confusion.
+'\" .ES
+'\" SConscript(dirs = 'src', variant_dir = 'build', src_dir = '.')
+'\" runs src/SConscript in build/src, but
+'\" SConscript(dirs = 'lib', variant_dir = 'build', src_dir = 'src')
+'\" runs lib/SConscript (in lib!). However,
+'\" SConscript(dirs = 'src', variant_dir = 'build', src_dir = 'src')
+'\" runs src/SConscript in build. Moreover,
+'\" SConscript(dirs = 'src/lib', variant_dir = 'build', src_dir = 'src')
+'\" runs src/lib/SConscript in build/lib. Moreover,
+'\" SConscript(dirs = 'build/src/lib', variant_dir = 'build', src_dir = 'src')
+'\" can't find build/src/lib/SConscript, even though it ought to exist.
+'\" .EE
+'\" is equivalent to
+'\" .ES
+'\" ????????????????
+'\" .EE
+'\" and what about this alternative?
+'\"TODO??? SConscript('build/SConscript', src_dir='src')
+
+Here are some composite examples:
+
+.ES
+# collect the configuration information and use it to build src and doc
+shared_info = SConscript('MyConfig.py')
+SConscript('src/SConscript', exports='shared_info')
+SConscript('doc/SConscript', exports='shared_info')
+.EE
+
+.ES
+# build debugging and production versions. SConscript
+# can use Dir('.').path to determine variant.
+SConscript('SConscript', variant_dir='debug', duplicate=0)
+SConscript('SConscript', variant_dir='prod', duplicate=0)
+.EE
+
+.ES
+# build debugging and production versions. SConscript
+# is passed flags to use.
+opts = { 'CPPDEFINES' : ['DEBUG'], 'CCFLAGS' : '-pgdb' }
+SConscript('SConscript', variant_dir='debug', duplicate=0, exports=opts)
+opts = { 'CPPDEFINES' : ['NODEBUG'], 'CCFLAGS' : '-O' }
+SConscript('SConscript', variant_dir='prod', duplicate=0, exports=opts)
+.EE
+
+.ES
+# build common documentation and compile for different architectures
+SConscript('doc/SConscript', variant_dir='build/doc', duplicate=0)
+SConscript('src/SConscript', variant_dir='build/x86', duplicate=0)
+SConscript('src/SConscript', variant_dir='build/ppc', duplicate=0)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI SConscriptChdir( value )
+.TP
+.RI env.SConscriptChdir( value )
+By default,
+.B scons
+changes its working directory
+to the directory in which each
+subsidiary SConscript file lives.
+This behavior may be disabled
+by specifying either:
+
+.ES
+SConscriptChdir(0)
+env.SConscriptChdir(0)
+.EE
+.IP
+in which case
+.B scons
+will stay in the top-level directory
+while reading all SConscript files.
+(This may be necessary when building from repositories,
+when all the directories in which SConscript files may be found
+don't necessarily exist locally.)
+You may enable and disable
+this ability by calling
+SConscriptChdir()
+multiple times.
+
+Example:
+
+.ES
+env = Environment()
+SConscriptChdir(0)
+SConscript('foo/SConscript') # will not chdir to foo
+env.SConscriptChdir(1)
+SConscript('bar/SConscript') # will chdir to bar
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI SConsignFile([ file , dbm_module ])
+.TP
+.RI env.SConsignFile([ file , dbm_module ])
+This tells
+.B scons
+to store all file signatures
+in the specified database
+.IR file .
+If the
+.I file
+name is omitted,
+.B .sconsign
+is used by default.
+(The actual file name(s) stored on disk
+may have an appropriated suffix appended
+by the
+.IR dbm_module .)
+If
+.I file
+is not an absolute path name,
+the file is placed in the same directory as the top-level
+.B SConstruct
+file.
+
+If
+.I file
+is
+.BR None ,
+then
+.B scons
+will store file signatures
+in a separate
+.B .sconsign
+file in each directory,
+not in one global database file.
+(This was the default behavior
+prior to SCons 0.96.91 and 0.97.)
+
+The optional
+.I dbm_module
+argument can be used to specify
+which Python database module
+The default is to use a custom
+.B SCons.dblite
+module that uses pickled
+Python data structures,
+and which works on all Python versions from 1.5.2 on.
+
+Examples:
+
+.ES
+# Explicitly stores signatures in ".sconsign.dblite"
+# in the top-level SConstruct directory (the
+# default behavior).
+SConsignFile()
+
+# Stores signatures in the file "etc/scons-signatures"
+# relative to the top-level SConstruct directory.
+SConsignFile("etc/scons-signatures")
+
+# Stores signatures in the specified absolute file name.
+SConsignFile("/home/me/SCons/signatures")
+
+# Stores signatures in a separate .sconsign file
+# in each directory.
+SConsignFile(None)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.SetDefault(key = val ", [...])"
+Sets construction variables to default values specified with the keyword
+arguments if (and only if) the variables are not already set.
+The following statements are equivalent:
+
+.ES
+env.SetDefault(FOO = 'foo')
+
+if not env.has_key('FOO'): env['FOO'] = 'foo'
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI SetOption( name ", " value )
+.TP
+.RI env.SetOption( name ", " value )
+This function provides a way to set a select subset of the scons command
+line options from a SConscript file. The options supported are:
+
+.RS 10
+.TP 6
+.B clean
+which corresponds to -c, --clean and --remove;
+.TP 6
+.B duplicate
+which corresponds to --duplicate;
+.TP 6
+.B help
+which corresponds to -h and --help;
+.TP 6
+.B implicit_cache
+which corresponds to --implicit-cache;
+.TP 6
+.B max_drift
+which corresponds to --max-drift;
+.TP 6
+.B no_exec
+which corresponds to -n, --no-exec, --just-print, --dry-run and --recon;
+.TP 6
+.B num_jobs
+which corresponds to -j and --jobs;
+.TP 6
+.B random
+which corresponds to --random; and
+.TP 6
+.B stack_size
+which corresponds to --stack-size.
+.RE
+
+.IP
+See the documentation for the
+corresponding command line object for information about each specific
+option.
+
+Example:
+
+.ES
+SetOption('max_drift', 1)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI SideEffect( side_effect ", " target )
+.TP
+.RI env.SideEffect( side_effect ", " target )
+Declares
+.I side_effect
+as a side effect of building
+.IR target .
+Both
+.I side_effect
+and
+.I target
+can be a list, a file name, or a node.
+A side effect is a target file that is created or updated
+as a side effect of building other targets.
+For example, a Windows PDB
+file is created as a side effect of building the .obj
+files for a static library,
+and various log files are created updated
+as side effects of various TeX commands.
+If a target is a side effect of multiple build commands,
+.B scons
+will ensure that only one set of commands
+is executed at a time.
+Consequently, you only need to use this method
+for side-effect targets that are built as a result of
+multiple build commands.
+
+Because multiple build commands may update
+the same side effect file,
+by default the
+.I side_effect
+target is
+.I not
+automatically removed
+when the
+.I target
+is removed by the
+.B -c
+option.
+(Note, however, that the
+.I side_effect
+might be removed as part of
+cleaning the directory in which it lives.)
+If you want to make sure the
+.I side_effect
+is cleaned whenever a specific
+.I target
+is cleaned,
+you must specify this explicitly
+with the
+.BR Clean ()
+or
+.BR env.Clean ()
+function.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI SourceCode( entries ", " builder )
+.TP
+.RI env.SourceCode( entries ", " builder )
+Arrange for non-existent source files to
+be fetched from a source code management system
+using the specified
+.IR builder .
+The specified
+.I entries
+may be a Node, string or list of both,
+and may represent either individual
+source files or directories in which
+source files can be found.
+
+For any non-existent source files,
+.B scons
+will search up the directory tree
+and use the first
+.B SourceCode
+builder it finds.
+The specified
+.I builder
+may be
+.BR None ,
+in which case
+.B scons
+will not use a builder to fetch
+source files for the specified
+.IR entries ,
+even if a
+.B SourceCode
+builder has been specified
+for a directory higher up the tree.
+
+.B scons
+will, by default,
+fetch files from SCCS or RCS subdirectories
+without explicit configuration.
+This takes some extra processing time
+to search for the necessary
+source code management files on disk.
+You can avoid these extra searches
+and speed up your build a little
+by disabling these searches as follows:
+
+.ES
+env.SourceCode('.', None)
+.EE
+
+.IP
+Note that if the specified
+.I builder
+is one you create by hand,
+it must have an associated
+construction environment to use
+when fetching a source file.
+
+.B scons
+provides a set of canned factory
+functions that return appropriate
+Builders for various popular
+source code management systems.
+Canonical examples of invocation include:
+
+.ES
+env.SourceCode('.', env.BitKeeper('/usr/local/BKsources'))
+env.SourceCode('src', env.CVS('/usr/local/CVSROOT'))
+env.SourceCode('/', env.RCS())
+env.SourceCode(['f1.c', 'f2.c'], env.SCCS())
+env.SourceCode('no_source.c', None)
+.EE
+'\"env.SourceCode('.', env.Subversion('file:///usr/local/Subversion'))
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.subst( input ", [" raw ", " target ", " source ", " conv ])
+Performs construction variable interpolation
+on the specified string or sequence argument
+.IR input .
+
+By default,
+leading or trailing white space will
+be removed from the result.
+and all sequences of white space
+will be compressed to a single space character.
+Additionally, any
+.B $(
+and
+.B $)
+character sequences will be stripped from the returned string,
+The optional
+.I raw
+argument may be set to
+.B 1
+if you want to preserve white space and
+.BR $( - $)
+sequences.
+The
+.I raw
+argument may be set to
+.B 2
+if you want to strip
+all characters between
+any
+.B $(
+and
+.B $)
+pairs
+(as is done for signature calculation).
+
+If the input is a sequence
+(list or tuple),
+the individual elements of
+the sequence will be expanded,
+and the results will be returned as a list.
+
+The optional
+.I target
+and
+.I source
+keyword arguments
+must be set to lists of
+target and source nodes, respectively,
+if you want the
+.BR $TARGET ,
+.BR $TARGETS ,
+.BR $SOURCE
+and
+.BR $SOURCES
+to be available for expansion.
+This is usually necessary if you are
+calling
+.BR env.subst ()
+from within a Python function used
+as an SCons action.
+
+Returned string values or sequence elements
+are converted to their string representation by default.
+The optional
+.I conv
+argument
+may specify a conversion function
+that will be used in place of
+the default.
+For example, if you want Python objects
+(including SCons Nodes)
+to be returned as Python objects,
+you can use the Python
+.B lambda
+idiom to pass in an unnamed function
+that simply returns its unconverted argument.
+
+Example:
+
+.ES
+print env.subst("The C compiler is: $CC")
+
+def compile(target, source, env):
+ sourceDir = env.subst("${SOURCE.srcdir}",
+ target=target,
+ source=source)
+
+source_nodes = env.subst('$EXPAND_TO_NODELIST',
+ conv=lambda x: x)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+'\".TP
+'\".RI Subversion( repository ", " module )
+'\"A factory function that
+'\"returns a Builder object
+'\"to be used to fetch source files
+'\"from the specified Subversion
+'\".IR repository .
+'\"The returned Builder
+'\"is intended to be passed to the
+'\".B SourceCode
+'\"function.
+'\"
+'\"The optional specified
+'\".I module
+'\"will be added to the beginning
+'\"of all repository path names;
+'\"this can be used, in essence,
+'\"to strip initial directory names
+'\"from the repository path names,
+'\"so that you only have to
+'\"replicate part of the repository
+'\"directory hierarchy in your
+'\"local build directory.
+'\"
+'\"Example:
+'\"
+'\".ES
+'\"# Will fetch foo/bar/src.c
+'\"# from /usr/local/Subversion/foo/bar/src.c.
+'\"env.SourceCode('.', env.Subversion('file:///usr/local/Subversion'))
+'\"
+'\"# Will fetch bar/src.c
+'\"# from /usr/local/Subversion/foo/bar/src.c.
+'\"env.SourceCode('.', env.Subversion('file:///usr/local/Subversion', 'foo'))
+'\"
+'\"# Will fetch src.c
+'\"# from /usr/local/Subversion/foo/bar/src.c.
+'\"env.SourceCode('.', env.Subversion('file:///usr/local/Subversion', 'foo/bar'))
+'\".EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI SourceSignatures( type )
+.TP
+.RI env.SourceSignatures( type )
+Note: Although it is not yet officially deprecated,
+use of this function is discouraged.
+See the
+.BR Decider ()
+function for a more flexible and straightforward way
+to configure SCons' decision-making.
+
+The
+.BR SourceSignatures ()
+function tells
+.B scons
+how to decide if a source file
+(a file that is not built from any other files)
+has changed since the last time it
+was used to build a particular target file.
+Legal values are
+.B "MD5"
+or
+.BR "timestamp" .
+
+If the environment method is used,
+the specified type of source signature
+is only used when deciding whether targets
+built with that environment are up-to-date or must be rebuilt.
+If the global function is used,
+the specified type of source signature becomes the default
+used for all decisions
+about whether targets are up-to-date.
+
+.B "MD5"
+means
+.B scons
+decides that a source file has changed
+if the MD5 checksum of its contents has changed since
+the last time it was used to rebuild a particular target file.
+
+.B "timestamp"
+means
+.B scons
+decides that a source file has changed
+if its timestamp (modification time) has changed since
+the last time it was used to rebuild a particular target file.
+(Note that although this is similar to the behavior of Make,
+by default it will also rebuild if the dependency is
+.I older
+than the last time it was used to rebuild the target file.)
+
+There is no different between the two behaviors
+for Python
+.BR Value ()
+node objects.
+
+.B "MD5"
+signatures take longer to compute,
+but are more accurate than
+.B "timestamp"
+signatures.
+The default value is
+.BR "MD5" .
+
+Note that the default
+.BR TargetSignatures ()
+setting (see below)
+is to use this
+.BR SourceSignatures ()
+setting for any target files that are used
+to build other target files.
+Consequently, changing the value of
+.BR SourceSignatures ()
+will, by default,
+affect the up-to-date decision for all files in the build
+(or all files built with a specific construction environment
+when
+.BR env.SourceSignatures ()
+is used).
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Split( arg )
+.TP
+.RI env.Split( arg )
+Returns a list of file names or other objects.
+If arg is a string,
+it will be split on strings of white-space characters
+within the string,
+making it easier to write long lists of file names.
+If arg is already a list,
+the list will be returned untouched.
+If arg is any other type of object,
+it will be returned as a list
+containing just the object.
+
+Example:
+
+.ES
+files = Split("f1.c f2.c f3.c")
+files = env.Split("f4.c f5.c f6.c")
+files = Split("""
+ f7.c
+ f8.c
+ f9.c
+""")
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Tag( node ", " tags )
+Annotates file or directory Nodes with
+information about how the
+.BR Package ()
+Builder should package those files or directories.
+All tags are optional.
+
+Examples:
+
+.ES
+# makes sure the built library will be installed with 0644 file
+# access mode
+Tag( Library( 'lib.c' ), UNIX_ATTR="0644" )
+
+# marks file2.txt to be a documentation file
+Tag( 'file2.txt', DOC )
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI TargetSignatures( type )
+.TP
+.RI env.TargetSignatures( type )
+Note: Although it is not yet officially deprecated,
+use of this function is discouraged.
+See the
+.BR Decider ()
+function for a more flexible and straightforward way
+to configure SCons' decision-making.
+
+The
+.BR TargetSignatures ()
+function tells
+.B scons
+how to decide if a target file
+(a file that
+.I is
+built from any other files)
+has changed since the last time it
+was used to build some other target file.
+Legal values are
+.BR "build" ;
+.BR "content"
+(or its synonym
+.BR "MD5" );
+.BR "timestamp" ;
+or
+.BR "source" .
+
+If the environment method is used,
+the specified type of target signature is only used
+for targets built with that environment.
+If the global function is used,
+the specified type of signature becomes the default
+used for all target files that
+don't have an explicit target signature type
+specified for their environments.
+
+.B "content"
+(or its synonym
+.BR "MD5" )
+means
+.B scons
+decides that a target file has changed
+if the MD5 checksum of its contents has changed since
+the last time it was used to rebuild some other target file.
+This means
+.B scons
+will open up
+MD5 sum the contents
+of target files after they're built,
+and may decide that it does not need to rebuild
+"downstream" target files if a file was
+rebuilt with exactly the same contents as the last time.
+
+.B "timestamp"
+means
+.B scons
+decides that a target file has changed
+if its timestamp (modification time) has changed since
+the last time it was used to rebuild some other target file.
+(Note that although this is similar to the behavior of Make,
+by default it will also rebuild if the dependency is
+.I older
+than the last time it was used to rebuild the target file.)
+
+.B "source"
+means
+.B scons
+decides that a target file has changed
+as specified by the corresponding
+.BR SourceSignatures ()
+setting
+.BR "" ( "MD5"
+or
+.BR "timestamp" ).
+This means that
+.B scons
+will treat all input files to a target the same way,
+regardless of whether they are source files
+or have been built from other files.
+
+.B "build"
+means
+.B scons
+decides that a target file has changed
+if it has been rebuilt in this invocation
+or if its content or timestamp have changed
+as specified by the corresponding
+.BR SourceSignatures ()
+setting.
+This "propagates" the status of a rebuilt file
+so that other "downstream" target files
+will always be rebuilt,
+even if the contents or the timestamp
+have not changed.
+
+.B "build"
+signatures are fastest because
+.B "content"
+(or
+.BR "MD5" )
+signatures take longer to compute,
+but are more accurate than
+.B "timestamp"
+signatures,
+and can prevent unnecessary "downstream" rebuilds
+when a target file is rebuilt to the exact same contents
+as the previous build.
+The
+.B "source"
+setting provides the most consistent behavior
+when other target files may be rebuilt from
+both source and target input files.
+The default value is
+.BR "source" .
+
+Because the default setting is
+.BR "source" ,
+using
+.BR SourceSignatures ()
+is generally preferable to
+.BR TargetSignatures () ,
+so that the up-to-date decision
+will be consistent for all files
+(or all files built with a specific construction environment).
+Use of
+.BR TargetSignatures ()
+provides specific control for how built target files
+affect their "downstream" dependencies.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Tool( string [, toolpath ", " **kw ])
+Returns a callable object
+that can be used to initialize
+a construction environment using the
+tools keyword of the Environment() method.
+The object may be called with a construction
+environment as an argument,
+in which case the object will
+add the necessary variables
+to the construction environment
+and the name of the tool will be added to the
+.B $TOOLS
+construction variable.
+
+Additional keyword arguments are passed to the tool's
+.B generate()
+method.
+
+Examples:
+
+.ES
+env = Environment(tools = [ Tool('msvc') ])
+
+env = Environment()
+t = Tool('msvc')
+t(env) # adds 'msvc' to the TOOLS variable
+u = Tool('opengl', toolpath = ['tools'])
+u(env) # adds 'opengl' to the TOOLS variable
+.EE
+.TP
+.RI env.Tool( string [, toolpath ", " **kw ])
+Applies the callable object for the specified tool
+.I string
+to the environment through which the method was called.
+
+Additional keyword arguments are passed to the tool's
+.B generate()
+method.
+
+.ES
+env.Tool('gcc')
+env.Tool('opengl', toolpath = ['build/tools'])
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI Value( value ", [" built_value ])
+.TP
+.RI env.Value( value ", [" built_value ])
+Returns a Node object representing the specified Python value. Value
+Nodes can be used as dependencies of targets. If the result of
+calling
+.BR str( value )
+changes between SCons runs, any targets depending on
+.BR Value( value )
+will be rebuilt.
+(This is true even when using timestamps to decide if
+files are up-to-date.)
+When using timestamp source signatures, Value Nodes'
+timestamps are equal to the system time when the Node is created.
+
+The returned Value Node object has a
+.BR write ()
+method that can be used to "build" a Value Node
+by setting a new value.
+The optional
+.I built_value
+argument can be specified
+when the Value Node is created
+to indicate the Node should already be considered
+"built."
+There is a corresponding
+.BR read ()
+method that will return the built value of the Node.
+
+Examples:
+
+.ES
+env = Environment()
+
+def create(target, source, env):
+ # A function that will write a 'prefix=$SOURCE'
+ # string into the file name specified as the
+ # $TARGET.
+ f = open(str(target[0]), 'wb')
+ f.write('prefix=' + source[0].get_contents())
+
+# Fetch the prefix= argument, if any, from the command
+# line, and use /usr/local as the default.
+prefix = ARGUMENTS.get('prefix', '/usr/local')
+
+# Attach a .Config() builder for the above function action
+# to the construction environment.
+env['BUILDERS']['Config'] = Builder(action = create)
+env.Config(target = 'package-config', source = Value(prefix))
+
+def build_value(target, source, env):
+ # A function that "builds" a Python Value by updating
+ # the the Python value with the contents of the file
+ # specified as the source of the Builder call ($SOURCE).
+ target[0].write(source[0].get_contents())
+
+output = env.Value('before')
+input = env.Value('after')
+
+# Attach a .UpdateValue() builder for the above function
+# action to the construction environment.
+env['BUILDERS']['UpdateValue'] = Builder(action = build_value)
+env.UpdateValue(target = Value(output), source = Value(input))
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI VariantDir( variant_dir ", " src_dir ", [" duplicate ])
+.TP
+.RI env.VariantDir( variant_dir ", " src_dir ", [" duplicate ])
+Use the
+.BR VariantDir ()
+function to create a copy of your sources in another location:
+if a name under
+.IR variant_dir
+is not found but exists under
+.IR src_dir ,
+the file or directory is copied to
+.IR variant_dir .
+Target files can be built in a different directory
+than the original sources by simply refering to the sources (and targets)
+within the variant tree.
+
+.BR VariantDir ()
+can be called multiple times with the same
+.I src_dir
+to set up multiple builds with different options
+.RI ( variants ).
+The
+.I src_dir
+location must be in or underneath the SConstruct file's directory, and
+.I variant_dir
+may not be underneath
+.IR src_dir .
+'\"TODO: Can the above restrictions be clarified or relaxed?
+'\"TODO: The latter restriction is clearly not completely right;
+'\"TODO: src_dir = '.' works fine with a build dir under it.
+
+The default behavior is for
+.B scons
+to physically duplicate the source files in the variant tree.
+Thus, a build performed in the variant tree is guaranteed to be identical
+to a build performed in the source tree even if
+intermediate source files are generated during the build,
+or preprocessors or other scanners search for included files
+relative to the source file,
+or individual compilers or other invoked tools are hard-coded
+to put derived files in the same directory as source files.
+
+If possible on the platform,
+the duplication is performed by linking rather than copying;
+see also the
+.IR --duplicate
+command-line option.
+Moreover, only the files needed for the build are duplicated;
+files and directories that are not used are not present in
+.IR variant_dir .
+
+Duplicating the source tree may be disabled by setting the
+.I duplicate
+argument to 0 (zero).
+This will cause
+.B scons
+to invoke Builders using the path names of source files in
+.I src_dir
+and the path names of derived files within
+.IR variant_dir .
+This is always more efficient than
+.IR duplicate =1,
+and is usually safe for most builds
+(but see above for cases that may cause problems).
+
+Note that
+.BR VariantDir ()
+works most naturally with a subsidiary SConscript file.
+However, you would then call the subsidiary SConscript file
+not in the source directory, but in the
+.I variant_dir ,
+regardless of the value of
+.IR duplicate .
+This is how you tell
+.B scons
+which variant of a source tree to build:
+
+.ES
+# run src/SConscript in two variant directories
+VariantDir('build/variant1', 'src')
+SConscript('build/variant1/SConscript')
+VariantDir('build/variant2', 'src')
+SConscript('build/variant2/SConscript')
+.EE
+
+.IP
+See also the
+.BR SConscript ()
+function, described above,
+for another way to specify a variant directory
+in conjunction with calling a subsidiary SConscript file.
+
+Examples:
+
+.ES
+# use names in the build directory, not the source directory
+VariantDir('build', 'src', duplicate=0)
+Program('build/prog', 'build/source.c')
+.EE
+
+.ES
+# this builds both the source and docs in a separate subtree
+VariantDir('build', '.', duplicate=0)
+SConscript(dirs=['build/src','build/doc'])
+.EE
+
+.ES
+# same as previous example, but only uses SConscript
+SConscript(dirs='src', variant_dir='build/src', duplicate=0)
+SConscript(dirs='doc', variant_dir='build/doc', duplicate=0)
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI WhereIs( program ", [" path ", " pathext ", " reject ])
+.TP
+.RI env.WhereIs( program ", [" path ", " pathext ", " reject ])
+
+Searches for the specified executable
+.I program,
+returning the full path name to the program
+if it is found,
+and returning None if not.
+Searches the specified
+.I path,
+the value of the calling environment's PATH
+(env['ENV']['PATH']),
+or the user's current external PATH
+(os.environ['PATH'])
+by default.
+On Windows systems, searches for executable
+programs with any of the file extensions
+listed in the specified
+.I pathext,
+the calling environment's PATHEXT
+(env['ENV']['PATHEXT'])
+or the user's current PATHEXT
+(os.environ['PATHEXT'])
+by default.
+Will not select any
+path name or names
+in the specified
+.I reject
+list, if any.
+
+.SS SConscript Variables
+In addition to the global functions and methods,
+.B scons
+supports a number of Python variables
+that can be used in SConscript files
+to affect how you want the build to be performed.
+These variables may be accessed from custom Python modules that you
+import into an SConscript file by adding the following
+to the Python module:
+
+.ES
+from SCons.Script import *
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+ARGLIST
+A list
+.IR keyword = value
+arguments specified on the command line.
+Each element in the list is a tuple
+containing the
+.RI ( keyword , value )
+of the argument.
+The separate
+.I keyword
+and
+.I value
+elements of the tuple
+can be accessed by
+subscripting for element
+.B [0]
+and
+.B [1]
+of the tuple, respectively.
+
+Example:
+
+.ES
+print "first keyword, value =", ARGLIST[0][0], ARGLIST[0][1]
+print "second keyword, value =", ARGLIST[1][0], ARGLIST[1][1]
+third_tuple = ARGLIST[2]
+print "third keyword, value =", third_tuple[0], third_tuple[1]
+for key, value in ARGLIST:
+ # process key and value
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+ARGUMENTS
+A dictionary of all the
+.IR keyword = value
+arguments specified on the command line.
+The dictionary is not in order,
+and if a given keyword has
+more than one value assigned to it
+on the command line,
+the last (right-most) value is
+the one in the
+.B ARGUMENTS
+dictionary.
+
+Example:
+
+.ES
+if ARGUMENTS.get('debug', 0):
+ env = Environment(CCFLAGS = '-g')
+else:
+ env = Environment()
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+BUILD_TARGETS
+A list of the targets which
+.B scons
+will actually try to build,
+regardless of whether they were specified on
+the command line or via the
+.BR Default ()
+function or method.
+The elements of this list may be strings
+.I or
+nodes, so you should run the list through the Python
+.B str
+function to make sure any Node path names
+are converted to strings.
+
+Because this list may be taken from the
+list of targets specified using the
+.BR Default ()
+function or method,
+the contents of the list may change
+on each successive call to
+.BR Default ().
+See the
+.B DEFAULT_TARGETS
+list, below,
+for additional information.
+
+Example:
+
+.ES
+if 'foo' in BUILD_TARGETS:
+ print "Don't forget to test the `foo' program!"
+if 'special/program' in BUILD_TARGETS:
+ SConscript('special')
+.EE
+.IP
+Note that the
+.B BUILD_TARGETS
+list only contains targets expected listed
+on the command line or via calls to the
+.BR Default ()
+function or method.
+It does
+.I not
+contain all dependent targets that will be built as
+a result of making the sure the explicitly-specified
+targets are up to date.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+COMMAND_LINE_TARGETS
+A list of the targets explicitly specified on
+the command line.
+If there are no targets specified on the command line,
+the list is empty.
+This can be used, for example,
+to take specific actions only
+when a certain target or targets
+is explicitly being built.
+
+Example:
+
+.ES
+if 'foo' in COMMAND_LINE_TARGETS:
+ print "Don't forget to test the `foo' program!"
+if 'special/program' in COMMAND_LINE_TARGETS:
+ SConscript('special')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+DEFAULT_TARGETS
+A list of the target
+.I nodes
+that have been specified using the
+.BR Default ()
+function or method.
+The elements of the list are nodes,
+so you need to run them through the Python
+.B str
+function to get at the path name for each Node.
+
+Example:
+
+.ES
+print str(DEFAULT_TARGETS[0])
+if 'foo' in map(str, DEFAULT_TARGETS):
+ print "Don't forget to test the `foo' program!"
+.EE
+.IP
+The contents of the
+.B DEFAULT_TARGETS
+list change on on each successive call to the
+.BR Default ()
+function:
+
+.ES
+print map(str, DEFAULT_TARGETS) # originally []
+Default('foo')
+print map(str, DEFAULT_TARGETS) # now a node ['foo']
+Default('bar')
+print map(str, DEFAULT_TARGETS) # now a node ['foo', 'bar']
+Default(None)
+print map(str, DEFAULT_TARGETS) # back to []
+.EE
+.IP
+Consequently, be sure to use
+.B DEFAULT_TARGETS
+only after you've made all of your
+.BR Default ()
+calls,
+or else simply be careful of the order
+of these statements in your SConscript files
+so that you don't look for a specific
+default target before it's actually been added to the list.
+
+.SS Construction Variables
+.\" XXX From Gary Ruben, 23 April 2002:
+.\" I think it would be good to have an example with each construction
+.\" variable description in the documentation.
+.\" eg.
+.\" CC The C compiler
+.\" Example: env["CC"] = "c68x"
+.\" Default: env["CC"] = "cc"
+.\"
+.\" CCCOM The command line ...
+.\" Example:
+.\" To generate the compiler line c68x -ps -qq -mr -o $TARGET $SOURCES
+.\" env["CC"] = "c68x"
+.\" env["CFLAGS"] = "-ps -qq -mr"
+.\" env["CCCOM"] = "$CC $CFLAGS -o $TARGET $SOURCES
+.\" Default:
+.\" (I dunno what this is ;-)
+A construction environment has an associated dictionary of
+.I construction variables
+that are used by built-in or user-supplied build rules.
+Construction variables must follow the same rules for
+Python identifiers:
+the initial character must be an underscore or letter,
+followed by any number of underscores, letters, or digits.
+
+A number of useful construction variables are automatically defined by
+scons for each supported platform, and additional construction variables
+can be defined by the user. The following is a list of the automatically
+defined construction variables:
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+'\" BEGIN GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS
+'\"
+'\" The descriptions below of the various SCons construction variables
+'\" are generated from the .xml files that live next to the various
+'\" Python modules in the build enginer library. If you're reading
+'\" this [gnt]roff file with an eye towards patching this man page,
+'\" you can still submit a diff against this text, but it will have to
+'\" be translated to a diff against the underlying .xml file before the
+'\" patch is actually accepted. If you do that yourself, it will make
+'\" it easier to integrate the patch.
+'\"
+'\" BEGIN GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.so variables.man
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+'\" END GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS
+'\"
+'\" The descriptions above of the various SCons construction variables
+'\" are generated from the .xml files that live next to the various
+'\" Python modules in the build enginer library. If you're reading
+'\" this [gnt]roff file with an eye towards patching this man page,
+'\" you can still submit a diff against this text, but it will have to
+'\" be translated to a diff against the underlying .xml file before the
+'\" patch is actually accepted. If you do that yourself, it will make
+'\" it easier to integrate the patch.
+'\"
+'\" END GENERATED CONSTRUCTION VARIABLE DESCRIPTIONS
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+.LP
+Construction variables can be retrieved and set using the
+.B Dictionary
+method of the construction environment:
+
+.ES
+dict = env.Dictionary()
+dict["CC"] = "cc"
+.EE
+
+or using the [] operator:
+
+.ES
+env["CC"] = "cc"
+.EE
+
+Construction variables can also be passed to the construction environment
+constructor:
+
+.ES
+env = Environment(CC="cc")
+.EE
+
+or when copying a construction environment using the
+.B Clone
+method:
+
+.ES
+env2 = env.Clone(CC="cl.exe")
+.EE
+
+.SS Configure Contexts
+
+.B scons
+supports
+.I configure contexts,
+an integrated mechanism similar to the
+various AC_CHECK macros in GNU autoconf
+for testing for the existence of C header
+files, libraries, etc.
+In contrast to autoconf,
+.B scons
+does not maintain an explicit cache of the tested values,
+but uses its normal dependency tracking to keep the checked values
+up to date. However, users may override this behaviour with the
+.B --config
+command line option.
+
+The following methods can be used to perform checks:
+
+.TP
+.RI Configure( env ", [" custom_tests ", " conf_dir ", " log_file ", " config_h ", " clean ", " help])
+.TP
+.RI env.Configure([ custom_tests ", " conf_dir ", " log_file ", " config_h ", " clean ", " help])
+This creates a configure context, which can be used to perform checks.
+.I env
+specifies the environment for building the tests.
+This environment may be modified when performing checks.
+.I custom_tests
+is a dictionary containing custom tests.
+See also the section about custom tests below.
+By default, no custom tests are added to the configure context.
+.I conf_dir
+specifies a directory where the test cases are built.
+Note that this directory is not used for building
+normal targets.
+The default value is the directory
+#/.sconf_temp.
+.I log_file
+specifies a file which collects the output from commands
+that are executed to check for the existence of header files, libraries, etc.
+The default is the file #/config.log.
+If you are using the
+.BR VariantDir ()
+method,
+you may want to specify a subdirectory under your variant directory.
+.I config_h
+specifies a C header file where the results of tests
+will be written, e.g. #define HAVE_STDIO_H, #define HAVE_LIBM, etc.
+The default is to not write a
+.B config.h
+file.
+You can specify the same
+.B config.h
+file in multiple calls to Configure,
+in which case
+.B scons
+will concatenate all results in the specified file.
+Note that SCons
+uses its normal dependency checking
+to decide if it's necessary to rebuild
+the specified
+.I config_h
+file.
+This means that the file is not necessarily re-built each
+time scons is run,
+but is only rebuilt if its contents will have changed
+and some target that depends on the
+.I config_h
+file is being built.
+
+The optional
+.B clean
+and
+.B help
+arguments can be used to suppress execution of the configuration
+tests when the
+.B -c/--clean
+or
+.B -H/-h/--help
+options are used, respectively.
+The default behavior is always to execute
+configure context tests,
+since the results of the tests may
+affect the list of targets to be cleaned
+or the help text.
+If the configure tests do not affect these,
+then you may add the
+.B clean=False
+or
+.B help=False
+arguments
+(or both)
+to avoid unnecessary test execution.
+
+.EE
+A created
+.B Configure
+instance has the following associated methods:
+
+.TP
+.RI SConf.Finish( context )
+.TP
+.IR sconf .Finish()
+This method should be called after configuration is done.
+It returns the environment as modified
+by the configuration checks performed.
+After this method is called, no further checks can be performed
+with this configuration context.
+However, you can create a new
+.RI Configure
+context to perform additional checks.
+Only one context should be active at a time.
+
+The following Checks are predefined.
+(This list will likely grow larger as time
+goes by and developers contribute new useful tests.)
+
+.TP
+.RI SConf.CheckHeader( context ", " header ", [" include_quotes ", " language ])
+.TP
+.IR sconf .CheckHeader( header ", [" include_quotes ", " language ])
+Checks if
+.I header
+is usable in the specified language.
+.I header
+may be a list,
+in which case the last item in the list
+is the header file to be checked,
+and the previous list items are
+header files whose
+.B #include
+lines should precede the
+header line being checked for.
+The optional argument
+.I include_quotes
+must be
+a two character string, where the first character denotes the opening
+quote and the second character denotes the closing quote.
+By default, both characters are " (double quote).
+The optional argument
+.I language
+should be either
+.B C
+or
+.B C++
+and selects the compiler to be used for the check.
+Returns 1 on success and 0 on failure.
+
+.TP
+.RI SConf.CheckCHeader( context ", " header ", [" include_quotes ])
+.TP
+.IR sconf .CheckCHeader( header ", [" include_quotes ])
+This is a wrapper around
+.B SConf.CheckHeader
+which checks if
+.I header
+is usable in the C language.
+.I header
+may be a list,
+in which case the last item in the list
+is the header file to be checked,
+and the previous list items are
+header files whose
+.B #include
+lines should precede the
+header line being checked for.
+The optional argument
+.I include_quotes
+must be
+a two character string, where the first character denotes the opening
+quote and the second character denotes the closing quote (both default
+to \N'34').
+Returns 1 on success and 0 on failure.
+
+.TP
+.RI SConf.CheckCXXHeader( context ", " header ", [" include_quotes ])
+.TP
+.IR sconf .CheckCXXHeader( header ", [" include_quotes ])
+This is a wrapper around
+.B SConf.CheckHeader
+which checks if
+.I header
+is usable in the C++ language.
+.I header
+may be a list,
+in which case the last item in the list
+is the header file to be checked,
+and the previous list items are
+header files whose
+.B #include
+lines should precede the
+header line being checked for.
+The optional argument
+.I include_quotes
+must be
+a two character string, where the first character denotes the opening
+quote and the second character denotes the closing quote (both default
+to \N'34').
+Returns 1 on success and 0 on failure.
+
+.TP
+.RI SConf.CheckFunc( context, ", " function_name ", [" header ", " language ])
+.TP
+.IR sconf .CheckFunc( function_name ", [" header ", " language ])
+Checks if the specified
+C or C++ function is available.
+.I function_name
+is the name of the function to check for.
+The optional
+.I header
+argument is a string
+that will be
+placed at the top
+of the test file
+that will be compiled
+to check if the function exists;
+the default is:
+.ES
+#ifdef __cplusplus
+extern "C"
+#endif
+char function_name();
+.EE
+The optional
+.I language
+argument should be
+.B C
+or
+.B C++
+and selects the compiler to be used for the check;
+the default is "C".
+
+.TP
+.RI SConf.CheckLib( context ", [" library ", " symbol ", " header ", " language ", " autoadd=1 ])
+.TP
+.IR sconf .CheckLib([ library ", " symbol ", " header ", " language ", " autoadd=1 ])
+Checks if
+.I library
+provides
+.IR symbol .
+If the value of
+.I autoadd
+is 1 and the library provides the specified
+.IR symbol ,
+appends the library to the LIBS construction environment variable.
+.I library
+may also be None (the default),
+in which case
+.I symbol
+is checked with the current LIBS variable,
+or a list of library names,
+in which case each library in the list
+will be checked for
+.IR symbol .
+If
+.I symbol
+is not set or is
+.BR None ,
+then
+.BR SConf.CheckLib ()
+just checks if
+you can link against the specified
+.IR library .
+The optional
+.I language
+argument should be
+.B C
+or
+.B C++
+and selects the compiler to be used for the check;
+the default is "C".
+The default value for
+.I autoadd
+is 1.
+This method returns 1 on success and 0 on error.
+
+.TP
+.RI SConf.CheckLibWithHeader( context ", " library ", " header ", " language ", [" call ", " autoadd ])
+.TP
+.IR sconf .CheckLibWithHeader( library ", " header ", " language ", [" call ", " autoadd ])
+
+In contrast to the
+.RI SConf.CheckLib
+call, this call provides a more sophisticated way to check against libraries.
+Again,
+.I library
+specifies the library or a list of libraries to check.
+.I header
+specifies a header to check for.
+.I header
+may be a list,
+in which case the last item in the list
+is the header file to be checked,
+and the previous list items are
+header files whose
+.B #include
+lines should precede the
+header line being checked for.
+.I language
+may be one of 'C','c','CXX','cxx','C++' and 'c++'.
+.I call
+can be any valid expression (with a trailing ';').
+If
+.I call
+is not set,
+the default simply checks that you
+can link against the specified
+.IR library .
+.I autoadd
+specifies whether to add the library to the environment (only if the check
+succeeds). This method returns 1 on success and 0 on error.
+
+.TP
+.RI SConf.CheckType( context ", " type_name ", [" includes ", " language ])
+.TP
+.IR sconf .CheckType( type_name ", [" includes ", " language ])
+Checks for the existence of a type defined by
+.BR typedef .
+.I type_name
+specifies the typedef name to check for.
+.I includes
+is a string containing one or more
+.B #include
+lines that will be inserted into the program
+that will be run to test for the existence of the type.
+The optional
+.I language
+argument should be
+.B C
+or
+.B C++
+and selects the compiler to be used for the check;
+the default is "C".
+Example:
+.ES
+sconf.CheckType('foo_type', '#include "my_types.h"', 'C++')
+.EE
+
+.TP
+.RI Configure.CheckCC( self )
+Checks whether the C compiler (as defined by the CC construction variable) works
+by trying to compile a small source file.
+
+By default, SCons only detects if there is a program with the correct name, not
+if it is a functioning compiler.
+
+This uses the exact same command than the one used by the object builder for C
+source file, so it can be used to detect if a particular compiler flag works or
+not.
+
+.TP
+.RI Configure.CheckCXX( self )
+Checks whether the C++ compiler (as defined by the CXX construction variable)
+works by trying to compile a small source file. By default, SCons only detects
+if there is a program with the correct name, not if it is a functioning compiler.
+
+This uses the exact same command than the one used by the object builder for
+CXX source files, so it can be used to detect if a particular compiler flag
+works or not.
+
+.TP
+.RI Configure.CheckSHCC( self )
+Checks whether the C compiler (as defined by the SHCC construction variable) works
+by trying to compile a small source file. By default, SCons only detects if
+there is a program with the correct name, not if it is a functioning compiler.
+
+This uses the exact same command than the one used by the object builder for C
+source file, so it can be used to detect if a particular compiler flag works or
+not. This does not check whether the object code can be used to build a shared
+library, only that the compilation (not link) succeeds.
+
+.TP
+.RI Configure.CheckSHCXX( self )
+Checks whether the C++ compiler (as defined by the SHCXX construction variable)
+works by trying to compile a small source file. By default, SCons only detects
+if there is a program with the correct name, not if it is a functioning compiler.
+
+This uses the exact same command than the one used by the object builder for
+CXX source files, so it can be used to detect if a particular compiler flag
+works or not. This does not check whether the object code can be used to build
+a shared library, only that the compilation (not link) succeeds.
+
+.EE
+Example of a typical Configure usage:
+
+.ES
+env = Environment()
+conf = Configure( env )
+if not conf.CheckCHeader( 'math.h' ):
+ print 'We really need math.h!'
+ Exit(1)
+if conf.CheckLibWithHeader( 'qt', 'qapp.h', 'c++',
+ 'QApplication qapp(0,0);' ):
+ # do stuff for qt - usage, e.g.
+ conf.env.Append( CPPFLAGS = '-DWITH_QT' )
+env = conf.Finish()
+.EE
+
+.TP
+.RI SConf.CheckTypeSize( context ", " type_name ", [" header ", " language ", " expect ])
+.TP
+.IR sconf .CheckTypeSize( type_name ", [" header ", " language ", " expect ])
+Checks for the size of a type defined by
+.BR typedef .
+.I type_name
+specifies the typedef name to check for.
+The optional
+.I header
+argument is a string
+that will be
+placed at the top
+of the test file
+that will be compiled
+to check if the function exists;
+the default is empty.
+The optional
+.I language
+argument should be
+.B C
+or
+.B C++
+and selects the compiler to be used for the check;
+the default is "C".
+The optional
+.I expect
+argument should be an integer.
+If this argument is used,
+the function will only check whether the type
+given in type_name has the expected size (in bytes).
+For example,
+.B "CheckTypeSize('short', expect = 2)"
+will return success only if short is two bytes.
+
+.ES
+.EE
+
+.TP
+.RI SConf.CheckDeclaration( context ", " symbol ", [" includes ", " language ])
+.TP
+.IR sconf .CheckDeclaration( symbol ", [" includes ", " language ])
+Checks if the specified
+.I symbol
+is declared.
+.I includes
+is a string containing one or more
+.B #include
+lines that will be inserted into the program
+that will be run to test for the existence of the type.
+The optional
+.I language
+argument should be
+.B C
+or
+.B C++
+and selects the compiler to be used for the check;
+the default is "C".
+
+.TP
+.RI SConf.Define( context ", " symbol ", [" value ", " comment ])
+.TP
+.IR sconf .Define( symbol ", [" value ", " comment ])
+This function does not check for anything, but defines a
+preprocessor symbol that will be added to the configuration header file.
+It is the equivalent of AC_DEFINE,
+and defines the symbol
+.I name
+with the optional
+.B value
+and the optional comment
+.BR comment .
+
+.IP
+Examples:
+
+.ES
+env = Environment()
+conf = Configure( env )
+
+# Puts the following line in the config header file:
+# #define A_SYMBOL
+conf.Define('A_SYMBOL')
+
+# Puts the following line in the config header file:
+# #define A_SYMBOL 1
+conf.Define('A_SYMBOL', 1)
+.EE
+
+.IP
+Be careful about quoting string values, though:
+
+.ES
+env = Environment()
+conf = Configure( env )
+
+# Puts the following line in the config header file:
+# #define A_SYMBOL YA
+conf.Define('A_SYMBOL', "YA")
+
+# Puts the following line in the config header file:
+# #define A_SYMBOL "YA"
+conf.Define('A_SYMBOL', '"YA"')
+.EE
+
+.IP
+For comment:
+
+.ES
+env = Environment()
+conf = Configure( env )
+
+# Puts the following lines in the config header file:
+# /* Set to 1 if you have a symbol */
+# #define A_SYMBOL 1
+conf.Define('A_SYMBOL', 1, 'Set to 1 if you have a symbol')
+.EE
+
+.EE
+You can define your own custom checks.
+in addition to the predefined checks.
+These are passed in a dictionary to the Configure function.
+This dictionary maps the names of the checks
+to user defined Python callables
+(either Python functions or class instances implementing the
+.I __call__
+method).
+The first argument of the call is always a
+.I CheckContext
+instance followed by the arguments,
+which must be supplied by the user of the check.
+These CheckContext instances define the following methods:
+
+.TP
+.RI CheckContext.Message( self ", " text )
+
+Usually called before the check is started.
+.I text
+will be displayed to the user, e.g. 'Checking for library X...'
+
+.TP
+.RI CheckContext.Result( self, ", " res )
+
+Usually called after the check is done.
+.I res
+can be either an integer or a string. In the former case, 'yes' (res != 0)
+or 'no' (res == 0) is displayed to the user, in the latter case the
+given string is displayed.
+
+.TP
+.RI CheckContext.TryCompile( self ", " text ", " extension )
+Checks if a file with the specified
+.I extension
+(e.g. '.c') containing
+.I text
+can be compiled using the environment's
+.B Object
+builder. Returns 1 on success and 0 on failure.
+
+.TP
+.RI CheckContext.TryLink( self ", " text ", " extension )
+Checks, if a file with the specified
+.I extension
+(e.g. '.c') containing
+.I text
+can be compiled using the environment's
+.B Program
+builder. Returns 1 on success and 0 on failure.
+
+.TP
+.RI CheckContext.TryRun( self ", " text ", " extension )
+Checks, if a file with the specified
+.I extension
+(e.g. '.c') containing
+.I text
+can be compiled using the environment's
+.B Program
+builder. On success, the program is run. If the program
+executes successfully
+(that is, its return status is 0),
+a tuple
+.I (1, outputStr)
+is returned, where
+.I outputStr
+is the standard output of the
+program.
+If the program fails execution
+(its return status is non-zero),
+then (0, '') is returned.
+
+.TP
+.RI CheckContext.TryAction( self ", " action ", [" text ", " extension ])
+Checks if the specified
+.I action
+with an optional source file (contents
+.I text
+, extension
+.I extension
+= ''
+) can be executed.
+.I action
+may be anything which can be converted to a
+.B scons
+.RI Action.
+On success,
+.I (1, outputStr)
+is returned, where
+.I outputStr
+is the content of the target file.
+On failure
+.I (0, '')
+is returned.
+
+.TP
+.RI CheckContext.TryBuild( self ", " builder ", [" text ", " extension ])
+Low level implementation for testing specific builds;
+the methods above are based on this method.
+Given the Builder instance
+.I builder
+and the optional
+.I text
+of a source file with optional
+.IR extension ,
+this method returns 1 on success and 0 on failure. In addition,
+.I self.lastTarget
+is set to the build target node, if the build was successful.
+
+.EE
+Example for implementing and using custom tests:
+
+.ES
+def CheckQt(context, qtdir):
+ context.Message( 'Checking for qt ...' )
+ lastLIBS = context.env['LIBS']
+ lastLIBPATH = context.env['LIBPATH']
+ lastCPPPATH= context.env['CPPPATH']
+ context.env.Append(LIBS = 'qt', LIBPATH = qtdir + '/lib', CPPPATH = qtdir + '/include' )
+ ret = context.TryLink("""
+#include <qapp.h>
+int main(int argc, char **argv) {
+ QApplication qapp(argc, argv);
+ return 0;
+}
+""")
+ if not ret:
+ context.env.Replace(LIBS = lastLIBS, LIBPATH=lastLIBPATH, CPPPATH=lastCPPPATH)
+ context.Result( ret )
+ return ret
+
+env = Environment()
+conf = Configure( env, custom_tests = { 'CheckQt' : CheckQt } )
+if not conf.CheckQt('/usr/lib/qt'):
+ print 'We really need qt!'
+ Exit(1)
+env = conf.Finish()
+.EE
+
+.SS Command-Line Construction Variables
+
+Often when building software,
+some variables must be specified at build time.
+For example, libraries needed for the build may be in non-standard
+locations, or site-specific compiler options may need to be passed to the
+compiler.
+.B scons
+provides a
+.B Variables
+object to support overriding construction variables
+on the command line:
+.ES
+$ scons VARIABLE=foo
+.EE
+The variable values can also be specified in a text-based SConscript file.
+To create a Variables object, call the Variables() function:
+
+.TP
+.RI Variables([ files "], [" args ])
+This creates a Variables object that will read construction variables from
+the file or list of filenames specified in
+.IR files .
+If no files are specified,
+or the
+.I files
+argument is
+.BR None ,
+then no files will be read.
+The optional argument
+.I args
+is a dictionary of
+values that will override anything read from the specified files;
+it is primarily intended to be passed the
+.B ARGUMENTS
+dictionary that holds variables
+specified on the command line.
+Example:
+
+.ES
+vars = Variables('custom.py')
+vars = Variables('overrides.py', ARGUMENTS)
+vars = Variables(None, {FOO:'expansion', BAR:7})
+.EE
+
+Variables objects have the following methods:
+
+.TP
+.RI Add( key ", [" help ", " default ", " validator ", " converter ])
+This adds a customizable construction variable to the Variables object.
+.I key
+is the name of the variable.
+.I help
+is the help text for the variable.
+.I default
+is the default value of the variable;
+if the default value is
+.B None
+and there is no explicit value specified,
+the construction variable will
+.I not
+be added to the construction environment.
+.I validator
+is called to validate the value of the variable, and should take three
+arguments: key, value, and environment.
+The recommended way to handle an invalid value is
+to raise an exception (see example below).
+.I converter
+is called to convert the value before putting it in the environment, and
+should take either a value, or the value and environment, as parameters.
+The
+.I converter
+must return a value,
+which will be converted into a string
+before being validated by the
+.I validator
+(if any)
+and then added to the environment.
+
+Examples:
+
+.ES
+vars.Add('CC', 'The C compiler')
+
+def validate_color(key, val, env):
+ if not val in ['red', 'blue', 'yellow']:
+ raise "Invalid color value '%s'" % val
+vars.Add('COLOR', validator=valid_color)
+.EE
+
+.TP
+.RI AddVariables( list )
+A wrapper script that adds
+multiple customizable construction variables
+to a Variables object.
+.I list
+is a list of tuple or list objects
+that contain the arguments
+for an individual call to the
+.B Add
+method.
+
+.ES
+opt.AddVariables(
+ ('debug', '', 0),
+ ('CC', 'The C compiler'),
+ ('VALIDATE', 'An option for testing validation',
+ 'notset', validator, None),
+ )
+.EE
+
+.TP
+.RI Update( env ", [" args ])
+This updates a construction environment
+.I env
+with the customized construction variables.
+Any specified variables that are
+.I not
+configured for the Variables object
+will be saved and may be
+retrieved with the
+.BR UnknownVariables ()
+method, below.
+
+Normally this method is not called directly,
+but is called indirectly by passing the Variables object to
+the Environment() function:
+
+.ES
+env = Environment(variables=vars)
+.EE
+
+.IP
+The text file(s) that were specified
+when the Variables object was created
+are executed as Python scripts,
+and the values of (global) Python variables set in the file
+are added to the construction environment.
+
+Example:
+
+.ES
+CC = 'my_cc'
+.EE
+
+.TP
+.RI UnknownVariables( )
+Returns a dictionary containing any
+variables that were specified
+either in the files or the dictionary
+with which the Variables object was initialized,
+but for which the Variables object was
+not configured.
+
+.ES
+env = Environment(variables=vars)
+for key, value in vars.UnknownVariables():
+ print "unknown variable: %s=%s" % (key, value)
+.EE
+
+.TP
+.RI Save( filename ", " env )
+This saves the currently set variables into a script file named
+.I filename
+that can be used on the next invocation to automatically load the current
+settings. This method combined with the Variables method can be used to
+support caching of variables between runs.
+
+.ES
+env = Environment()
+vars = Variables(['variables.cache', 'custom.py'])
+vars.Add(...)
+vars.Update(env)
+vars.Save('variables.cache', env)
+.EE
+
+.TP
+.RI GenerateHelpText( env ", [" sort ])
+This generates help text documenting the customizable construction
+variables suitable to passing in to the Help() function.
+.I env
+is the construction environment that will be used to get the actual values
+of customizable variables. Calling with
+an optional
+.I sort
+function
+will cause the output to be sorted
+by the specified argument.
+The specific
+.I sort
+function
+should take two arguments
+and return
+-1, 0 or 1
+(like the standard Python
+.I cmp
+function).
+
+.ES
+Help(vars.GenerateHelpText(env))
+Help(vars.GenerateHelpText(env, sort=cmp))
+.EE
+
+.TP
+.RI FormatVariableHelpText( env ", " opt ", " help ", " default ", " actual )
+This method returns a formatted string
+containing the printable help text
+for one option.
+It is normally not called directly,
+but is called by the
+.IR GenerateHelpText ()
+method to create the returned help text.
+It may be overridden with your own
+function that takes the arguments specified above
+and returns a string of help text formatted to your liking.
+Note that the
+.IR GenerateHelpText ()
+will not put any blank lines or extra
+characters in between the entries,
+so you must add those characters to the returned
+string if you want the entries separated.
+
+.ES
+def my_format(env, opt, help, default, actual):
+ fmt = "\n%s: default=%s actual=%s (%s)\n"
+ return fmt % (opt, default. actual, help)
+vars.FormatVariableHelpText = my_format
+.EE
+
+To make it more convenient to work with customizable Variables,
+.B scons
+provides a number of functions
+that make it easy to set up
+various types of Variables:
+
+.TP
+.RI BoolVariable( key ", " help ", " default )
+Return a tuple of arguments
+to set up a Boolean option.
+The option will use
+the specified name
+.IR key ,
+have a default value of
+.IR default ,
+and display the specified
+.I help
+text.
+The option will interpret the values
+.BR y ,
+.BR yes ,
+.BR t ,
+.BR true ,
+.BR 1 ,
+.B on
+and
+.B all
+as true,
+and the values
+.BR n ,
+.BR no ,
+.BR f ,
+.BR false ,
+.BR 0 ,
+.B off
+and
+.B none
+as false.
+
+.TP
+.RI EnumVariable( key ", " help ", " default ", " allowed_values ", [" map ", " ignorecase ])
+Return a tuple of arguments
+to set up an option
+whose value may be one
+of a specified list of legal enumerated values.
+The option will use
+the specified name
+.IR key ,
+have a default value of
+.IR default ,
+and display the specified
+.I help
+text.
+The option will only support those
+values in the
+.I allowed_values
+list.
+The optional
+.I map
+argument is a dictionary
+that can be used to convert
+input values into specific legal values
+in the
+.I allowed_values
+list.
+If the value of
+.I ignore_case
+is
+.B 0
+(the default),
+then the values are case-sensitive.
+If the value of
+.I ignore_case
+is
+.BR 1 ,
+then values will be matched
+case-insensitive.
+If the value of
+.I ignore_case
+is
+.BR 1 ,
+then values will be matched
+case-insensitive,
+and all input values will be
+converted to lower case.
+
+.TP
+.RI ListVariable( key ", " help ", " default ", " names ", [", map ])
+Return a tuple of arguments
+to set up an option
+whose value may be one or more
+of a specified list of legal enumerated values.
+The option will use
+the specified name
+.IR key ,
+have a default value of
+.IR default ,
+and display the specified
+.I help
+text.
+The option will only support the values
+.BR all ,
+.BR none ,
+or the values in the
+.I names
+list.
+More than one value may be specified,
+with all values separated by commas.
+The default may be a string of
+comma-separated default values,
+or a list of the default values.
+The optional
+.I map
+argument is a dictionary
+that can be used to convert
+input values into specific legal values
+in the
+.I names
+list.
+
+.TP
+.RI PackageVariable( key ", " help ", " default )
+Return a tuple of arguments
+to set up an option
+whose value is a path name
+of a package that may be
+enabled, disabled or
+given an explicit path name.
+The option will use
+the specified name
+.IR key ,
+have a default value of
+.IR default ,
+and display the specified
+.I help
+text.
+The option will support the values
+.BR yes ,
+.BR true ,
+.BR on ,
+.BR enable
+or
+.BR search ,
+in which case the specified
+.I default
+will be used,
+or the option may be set to an
+arbitrary string
+(typically the path name to a package
+that is being enabled).
+The option will also support the values
+.BR no ,
+.BR false ,
+.BR off
+or
+.BR disable
+to disable use of the specified option.
+
+.TP
+.RI PathVariable( key ", " help ", " default ", [" validator ])
+Return a tuple of arguments
+to set up an option
+whose value is expected to be a path name.
+The option will use
+the specified name
+.IR key ,
+have a default value of
+.IR default ,
+and display the specified
+.I help
+text.
+An additional
+.I validator
+may be specified
+that will be called to
+verify that the specified path
+is acceptable.
+SCons supplies the
+following ready-made validators:
+.BR PathVariable.PathExists
+(the default),
+which verifies that the specified path exists;
+.BR PathVariable.PathIsFile ,
+which verifies that the specified path is an existing file;
+.BR PathVariable.PathIsDir ,
+which verifies that the specified path is an existing directory;
+.BR PathVariable.PathIsDirCreate ,
+which verifies that the specified path is a directory
+and will create the specified directory if the path does not exist;
+and
+.BR PathVariable.PathAccept ,
+which simply accepts the specific path name argument without validation,
+and which is suitable if you want your users
+to be able to specify a directory path that will be
+created as part of the build process, for example.
+You may supply your own
+.I validator
+function,
+which must take three arguments
+.RI ( key ,
+the name of the variable to be set;
+.IR val ,
+the specified value being checked;
+and
+.IR env ,
+the construction environment)
+and should raise an exception
+if the specified value is not acceptable.
+
+.RE
+These functions make it
+convenient to create a number
+of variables with consistent behavior
+in a single call to the
+.B AddVariables
+method:
+
+.ES
+vars.AddVariables(
+ BoolVariable('warnings', 'compilation with -Wall and similiar', 1),
+ EnumVariable('debug', 'debug output and symbols', 'no'
+ allowed_values=('yes', 'no', 'full'),
+ map={}, ignorecase=0), # case sensitive
+ ListVariable('shared',
+ 'libraries to build as shared libraries',
+ 'all',
+ names = list_of_libs),
+ PackageVariable('x11',
+ 'use X11 installed here (yes = search some places)',
+ 'yes'),
+ PathVariable('qtdir', 'where the root of Qt is installed', qtdir),
+ PathVariable('foopath', 'where the foo library is installed', foopath,
+ PathVariable.PathIsDir),
+
+)
+.EE
+
+.SS File and Directory Nodes
+
+The
+.IR File ()
+and
+.IR Dir ()
+functions return
+.I File
+and
+.I Dir
+Nodes, respectively.
+python objects, respectively.
+Those objects have several user-visible attributes
+and methods that are often useful:
+
+.IP path
+The build path
+of the given
+file or directory.
+This path is relative to the top-level directory
+(where the
+.B SConstruct
+file is found).
+The build path is the same as the source path if
+.I variant_dir
+is not being used.
+
+.IP abspath
+The absolute build path of the given file or directory.
+
+.IP srcnode()
+The
+.IR srcnode ()
+method
+returns another
+.I File
+or
+.I Dir
+object representing the
+.I source
+path of the given
+.I File
+or
+.IR Dir .
+The
+
+.ES
+# Get the current build dir's path, relative to top.
+Dir('.').path
+# Current dir's absolute path
+Dir('.').abspath
+# Next line is always '.', because it is the top dir's path relative to itself.
+Dir('#.').path
+File('foo.c').srcnode().path # source path of the given source file.
+
+# Builders also return File objects:
+foo = env.Program('foo.c')
+print "foo will be built in %s"%foo.path
+.EE
+
+A
+.I Dir
+Node or
+.I File
+Node can also be used to create
+file and subdirectory Nodes relative to the generating Node.
+A
+.I Dir
+Node will place the new Nodes within the directory it represents.
+A
+.I File
+node will place the new Nodes within its parent directory
+(that is, "beside" the file in question).
+If
+.I d
+is a
+.I Dir
+(directory) Node and
+.I f
+is a
+.I File
+(file) Node,
+then these methods are available:
+
+.TP
+.IR d .Dir( name )
+Returns a directory Node for a subdirectory of
+.I d
+named
+.IR name .
+
+.TP
+.IR d .File( name )
+Returns a file Node for a file within
+.I d
+named
+.IR name .
+
+.TP
+.IR d .Entry( name )
+Returns an unresolved Node within
+.I d
+named
+.IR name .
+
+.TP
+.IR f .Dir( name )
+Returns a directory named
+.I name
+within the parent directory of
+.IR f .
+
+.TP
+.IR f .File( name )
+Returns a file named
+.I name
+within the parent directory of
+.IR f .
+
+.TP
+.IR f .Entry( name )
+Returns an unresolved Node named
+.I name
+within the parent directory of
+.IR f .
+
+.RE
+For example:
+
+.ES
+# Get a Node for a file within a directory
+incl = Dir('include')
+f = incl.File('header.h')
+
+# Get a Node for a subdirectory within a directory
+dist = Dir('project-3.2.1)
+src = dist.Dir('src')
+
+# Get a Node for a file in the same directory
+cfile = File('sample.c')
+hfile = cfile.File('sample.h')
+
+# Combined example
+docs = Dir('docs')
+html = docs.Dir('html')
+index = html.File('index.html')
+css = index.File('app.css')
+.EE
+
+.SH EXTENDING SCONS
+.SS Builder Objects
+.B scons
+can be extended to build different types of targets
+by adding new Builder objects
+to a construction environment.
+.IR "In general" ,
+you should only need to add a new Builder object
+when you want to build a new type of file or other external target.
+If you just want to invoke a different compiler or other tool
+to build a Program, Object, Library, or any other
+type of output file for which
+.B scons
+already has an existing Builder,
+it is generally much easier to
+use those existing Builders
+in a construction environment
+that sets the appropriate construction variables
+(CC, LINK, etc.).
+
+Builder objects are created
+using the
+.B Builder
+function.
+The
+.B Builder
+function accepts the following arguments:
+
+.IP action
+The command line string used to build the target from the source.
+.B action
+can also be:
+a list of strings representing the command
+to be executed and its arguments
+(suitable for enclosing white space in an argument),
+a dictionary
+mapping source file name suffixes to
+any combination of command line strings
+(if the builder should accept multiple source file extensions),
+a Python function;
+an Action object
+(see the next section);
+or a list of any of the above.
+
+An action function
+takes three arguments:
+.I source
+- a list of source nodes,
+.I target
+- a list of target nodes,
+.I env
+- the construction environment.
+
+.IP prefix
+The prefix that will be prepended to the target file name.
+This may be specified as a:
+
+.RS 10
+.HP 6
+*
+.IR string ,
+
+.HP 6
+*
+.I callable object
+- a function or other callable that takes
+two arguments (a construction environment and a list of sources)
+and returns a prefix,
+
+.HP 6
+*
+.I dictionary
+- specifies a mapping from a specific source suffix (of the first
+source specified) to a corresponding target prefix. Both the source
+suffix and target prefix specifications may use environment variable
+substitution, and the target prefix (the 'value' entries in the
+dictionary) may also be a callable object. The default target prefix
+may be indicated by a dictionary entry with a key value of None.
+.RE
+.P
+
+.ES
+b = Builder("build_it < $SOURCE > $TARGET"
+ prefix = "file-")
+
+def gen_prefix(env, sources):
+ return "file-" + env['PLATFORM'] + '-'
+b = Builder("build_it < $SOURCE > $TARGET",
+ prefix = gen_prefix)
+
+b = Builder("build_it < $SOURCE > $TARGET",
+ suffix = { None: "file-",
+ "$SRC_SFX_A": gen_prefix })
+.EE
+
+.IP suffix
+The suffix that will be appended to the target file name.
+This may be specified in the same manner as the prefix above.
+If the suffix is a string, then
+.B scons
+will append a '.' to the beginning of the suffix if it's not already
+there. The string returned by callable object (or obtained from the
+dictionary) is untouched and must append its own '.' to the beginning
+if one is desired.
+
+.ES
+b = Builder("build_it < $SOURCE > $TARGET"
+ suffix = "-file")
+
+def gen_suffix(env, sources):
+ return "." + env['PLATFORM'] + "-file"
+b = Builder("build_it < $SOURCE > $TARGET",
+ suffix = gen_suffix)
+
+b = Builder("build_it < $SOURCE > $TARGET",
+ suffix = { None: ".sfx1",
+ "$SRC_SFX_A": gen_suffix })
+.EE
+
+.IP ensure_suffix
+When set to any true value, causes
+.B scons
+to add the target suffix specified by the
+.I suffix
+keyword to any target strings
+that have a different suffix.
+(The default behavior is to leave untouched
+any target file name that looks like it already has any suffix.)
+
+.ES
+b1 = Builder("build_it < $SOURCE > $TARGET"
+ suffix = ".out")
+b2 = Builder("build_it < $SOURCE > $TARGET"
+ suffix = ".out",
+ ensure_suffix)
+env = Environment()
+env['BUILDERS']['B1'] = b1
+env['BUILDERS']['B2'] = b2
+
+# Builds "foo.txt" because ensure_suffix is not set.
+env.B1('foo.txt', 'foo.in')
+
+# Builds "bar.txt.out" because ensure_suffix is set.
+env.B2('bar.txt', 'bar.in')
+.EE
+
+.IP src_suffix
+The expected source file name suffix. This may be a string or a list
+of strings.
+
+.IP target_scanner
+A Scanner object that
+will be invoked to find
+implicit dependencies for this target file.
+This keyword argument should be used
+for Scanner objects that find
+implicit dependencies
+based only on the target file
+and the construction environment,
+.I not
+for implicit
+(See the section "Scanner Objects," below,
+for information about creating Scanner objects.)
+
+.IP source_scanner
+A Scanner object that
+will be invoked to
+find implicit dependences in
+any source files
+used to build this target file.
+This is where you would
+specify a scanner to
+find things like
+.B #include
+lines in source files.
+The pre-built
+.B DirScanner
+Scanner object may be used to
+indicate that this Builder
+should scan directory trees
+for on-disk changes to files
+that
+.B scons
+does not know about from other Builder or function calls.
+(See the section "Scanner Objects," below,
+for information about creating your own Scanner objects.)
+
+.IP target_factory
+A factory function that the Builder will use
+to turn any targets specified as strings into SCons Nodes.
+By default,
+SCons assumes that all targets are files.
+Other useful target_factory
+values include
+.BR Dir ,
+for when a Builder creates a directory target,
+and
+.BR Entry ,
+for when a Builder can create either a file
+or directory target.
+
+Example:
+
+.ES
+MakeDirectoryBuilder = Builder(action=my_mkdir, target_factory=Dir)
+env = Environment()
+env.Append(BUILDERS = {'MakeDirectory':MakeDirectoryBuilder})
+env.MakeDirectory('new_directory', [])
+.EE
+
+.IP
+Note that the call to the MakeDirectory Builder
+needs to specify an empty source list
+to make the string represent the builder's target;
+without that, it would assume the argument is the source,
+and would try to deduce the target name from it,
+which in the absence of an automatically-added prefix or suffix
+would lead to a matching target and source name
+and a circular dependency.
+
+.IP source_factory
+A factory function that the Builder will use
+to turn any sources specified as strings into SCons Nodes.
+By default,
+SCons assumes that all source are files.
+Other useful source_factory
+values include
+.BR Dir ,
+for when a Builder uses a directory as a source,
+and
+.BR Entry ,
+for when a Builder can use files
+or directories (or both) as sources.
+
+Example:
+
+.ES
+CollectBuilder = Builder(action=my_mkdir, source_factory=Entry)
+env = Environment()
+env.Append(BUILDERS = {'Collect':CollectBuilder})
+env.Collect('archive', ['directory_name', 'file_name'])
+.EE
+
+.IP emitter
+A function or list of functions to manipulate the target and source
+lists before dependencies are established
+and the target(s) are actually built.
+.B emitter
+can also be a string containing a construction variable to expand
+to an emitter function or list of functions,
+or a dictionary mapping source file suffixes
+to emitter functions.
+(Only the suffix of the first source file
+is used to select the actual emitter function
+from an emitter dictionary.)
+
+An emitter function
+takes three arguments:
+.I source
+- a list of source nodes,
+.I target
+- a list of target nodes,
+.I env
+- the construction environment.
+An emitter must return a tuple containing two lists,
+the list of targets to be built by this builder,
+and the list of sources for this builder.
+
+Example:
+
+.ES
+def e(target, source, env):
+ return (target + ['foo.foo'], source + ['foo.src'])
+
+# Simple association of an emitter function with a Builder.
+b = Builder("my_build < $TARGET > $SOURCE",
+ emitter = e)
+
+def e2(target, source, env):
+ return (target + ['bar.foo'], source + ['bar.src'])
+
+# Simple association of a list of emitter functions with a Builder.
+b = Builder("my_build < $TARGET > $SOURCE",
+ emitter = [e, e2])
+
+# Calling an emitter function through a construction variable.
+env = Environment(MY_EMITTER = e)
+b = Builder("my_build < $TARGET > $SOURCE",
+ emitter = '$MY_EMITTER')
+
+# Calling a list of emitter functions through a construction variable.
+env = Environment(EMITTER_LIST = [e, e2])
+b = Builder("my_build < $TARGET > $SOURCE",
+ emitter = '$EMITTER_LIST')
+
+# Associating multiple emitters with different file
+# suffixes using a dictionary.
+def e_suf1(target, source, env):
+ return (target + ['another_target_file'], source)
+def e_suf2(target, source, env):
+ return (target, source + ['another_source_file'])
+b = Builder("my_build < $TARGET > $SOURCE",
+ emitter = {'.suf1' : e_suf1,
+ '.suf2' : e_suf2})
+.EE
+
+.IP multi
+Specifies whether this builder is allowed to be called multiple times for
+the same target file(s). The default is 0, which means the builder
+can not be called multiple times for the same target file(s). Calling a
+builder multiple times for the same target simply adds additional source
+files to the target; it is not allowed to change the environment associated
+with the target, specify addition environment overrides, or associate a different
+builder with the target.
+
+.IP env
+A construction environment that can be used
+to fetch source code using this Builder.
+(Note that this environment is
+.I not
+used for normal builds of normal target files,
+which use the environment that was
+used to call the Builder for the target file.)
+
+.IP generator
+A function that returns a list of actions that will be executed to build
+the target(s) from the source(s).
+The returned action(s) may be
+an Action object, or anything that
+can be converted into an Action object
+(see the next section).
+
+The generator function
+takes four arguments:
+.I source
+- a list of source nodes,
+.I target
+- a list of target nodes,
+.I env
+- the construction environment,
+.I for_signature
+- a Boolean value that specifies
+whether the generator is being called
+for generating a build signature
+(as opposed to actually executing the command).
+Example:
+
+.ES
+def g(source, target, env, for_signature):
+ return [["gcc", "-c", "-o"] + target + source]
+
+b = Builder(generator=g)
+.EE
+
+.IP
+The
+.I generator
+and
+.I action
+arguments must not both be used for the same Builder.
+
+.IP src_builder
+Specifies a builder to use when a source file name suffix does not match
+any of the suffixes of the builder. Using this argument produces a
+multi-stage builder.
+
+.IP single_source
+Specifies that this builder expects exactly one source file per call. Giving
+more than one source files without target files results in implicitely calling
+the builder multiple times (once for each source given). Giving multiple
+source files together with target files results in a UserError exception.
+
+.RE
+.IP
+The
+.I generator
+and
+.I action
+arguments must not both be used for the same Builder.
+
+.IP source_ext_match
+When the specified
+.I action
+argument is a dictionary,
+the default behavior when a builder is passed
+multiple source files is to make sure that the
+extensions of all the source files match.
+If it is legal for this builder to be
+called with a list of source files with different extensions,
+this check can be suppressed by setting
+.B source_ext_match
+to
+.B None
+or some other non-true value.
+When
+.B source_ext_match
+is disable,
+.B scons
+will use the suffix of the first specified
+source file to select the appropriate action from the
+.I action
+dictionary.
+
+In the following example,
+the setting of
+.B source_ext_match
+prevents
+.B scons
+from exiting with an error
+due to the mismatched suffixes of
+.B foo.in
+and
+.BR foo.extra .
+
+.ES
+b = Builder(action={'.in' : 'build $SOURCES > $TARGET'},
+ source_ext_match = None)
+
+env = Environment(BUILDERS = {'MyBuild':b})
+env.MyBuild('foo.out', ['foo.in', 'foo.extra'])
+.EE
+
+.IP env
+A construction environment that can be used
+to fetch source code using this Builder.
+(Note that this environment is
+.I not
+used for normal builds of normal target files,
+which use the environment that was
+used to call the Builder for the target file.)
+
+.ES
+b = Builder(action="build < $SOURCE > $TARGET")
+env = Environment(BUILDERS = {'MyBuild' : b})
+env.MyBuild('foo.out', 'foo.in', my_arg = 'xyzzy')
+.EE
+
+.IP chdir
+A directory from which scons
+will execute the
+action(s) specified
+for this Builder.
+If the
+.B chdir
+argument is
+a string or a directory Node,
+scons will change to the specified directory.
+If the
+.B chdir
+is not a string or Node
+and is non-zero,
+then scons will change to the
+target file's directory.
+
+Note that scons will
+.I not
+automatically modify
+its expansion of
+construction variables like
+.B $TARGET
+and
+.B $SOURCE
+when using the chdir
+keyword argument--that is,
+the expanded file names
+will still be relative to
+the top-level SConstruct directory,
+and consequently incorrect
+relative to the chdir directory.
+Builders created using chdir keyword argument,
+will need to use construction variable
+expansions like
+.B ${TARGET.file}
+and
+.B ${SOURCE.file}
+to use just the filename portion of the
+targets and source.
+
+.ES
+b = Builder(action="build < ${SOURCE.file} > ${TARGET.file}",
+ chdir=1)
+env = Environment(BUILDERS = {'MyBuild' : b})
+env.MyBuild('sub/dir/foo.out', 'sub/dir/foo.in')
+.EE
+
+.B WARNING:
+Python only keeps one current directory
+location for all of the threads.
+This means that use of the
+.B chdir
+argument
+will
+.I not
+work with the SCons
+.B -j
+option,
+because individual worker threads spawned
+by SCons interfere with each other
+when they start changing directory.
+
+.RE
+Any additional keyword arguments supplied
+when a Builder object is created
+(that is, when the Builder() function is called)
+will be set in the executing construction
+environment when the Builder object is called.
+The canonical example here would be
+to set a construction variable to
+the repository of a source code system.
+
+Any additional keyword arguments supplied
+when a Builder
+.I object
+is called
+will only be associated with the target
+created by that particular Builder call
+(and any other files built as a
+result of the call).
+
+These extra keyword arguments are passed to the
+following functions:
+command generator functions,
+function Actions,
+and emitter functions.
+
+.SS Action Objects
+
+The
+.BR Builder ()
+function will turn its
+.B action
+keyword argument into an appropriate
+internal Action object.
+You can also explicity create Action objects
+using the
+.BR Action ()
+global function,
+which can then be passed to the
+.BR Builder ()
+function.
+This can be used to configure
+an Action object more flexibly,
+or it may simply be more efficient
+than letting each separate Builder object
+create a separate Action
+when multiple
+Builder objects need to do the same thing.
+
+The
+.BR Action ()
+global function
+returns an appropriate object for the action
+represented by the type of the first argument:
+
+.IP Action
+If the first argument is already an Action object,
+the object is simply returned.
+
+.IP String
+If the first argument is a string,
+a command-line Action is returned.
+Note that the command-line string
+may be preceded by an
+.B @
+(at-sign)
+to suppress printing of the specified command line,
+or by a
+.B \-
+(hyphen)
+to ignore the exit status from the specified command:
+
+.ES
+Action('$CC -c -o $TARGET $SOURCES')
+
+# Doesn't print the line being executed.
+Action('@build $TARGET $SOURCES')
+
+# Ignores return value
+Action('-build $TARGET $SOURCES')
+.EE
+.\" XXX From Gary Ruben, 23 April 2002:
+.\" What would be useful is a discussion of how you execute command
+.\" shell commands ie. what is the process used to spawn the shell, pass
+.\" environment variables to it etc., whether there is one shell per
+.\" environment or one per command etc. It might help to look at the Gnu
+.\" make documentation to see what they think is important to discuss about
+.\" a build system. I'm sure you can do a better job of organising the
+.\" documentation than they have :-)
+
+.IP List
+If the first argument is a list,
+then a list of Action objects is returned.
+An Action object is created as necessary
+for each element in the list.
+If an element
+.I within
+the list is itself a list,
+the internal list is the
+command and arguments to be executed via
+the command line.
+This allows white space to be enclosed
+in an argument by defining
+a command in a list within a list:
+
+.ES
+Action([['cc', '-c', '-DWHITE SPACE', '-o', '$TARGET', '$SOURCES']])
+.EE
+
+.IP Function
+If the first argument is a Python function,
+a function Action is returned.
+The Python function must take three keyword arguments,
+.B target
+(a Node object representing the target file),
+.B source
+(a Node object representing the source file)
+and
+.B env
+(the construction environment
+used for building the target file).
+The
+.B target
+and
+.B source
+arguments may be lists of Node objects if there is
+more than one target file or source file.
+The actual target and source file name(s) may
+be retrieved from their Node objects
+via the built-in Python str() function:
+
+.ES
+target_file_name = str(target)
+source_file_names = map(lambda x: str(x), source)
+.EE
+.IP
+The function should return
+.B 0
+or
+.B None
+to indicate a successful build of the target file(s).
+The function may raise an exception
+or return a non-zero exit status
+to indicate an unsuccessful build.
+
+.ES
+def build_it(target = None, source = None, env = None):
+ # build the target from the source
+ return 0
+
+a = Action(build_it)
+.EE
+
+If the action argument is not one of the above,
+None is returned.
+.PP
+
+The second argument is optional and is used to define the output
+which is printed when the Action is actually performed.
+In the absence of this parameter,
+or if it's an empty string,
+a default output depending on the type of the action is used.
+For example, a command-line action will print the executed command.
+The argument must be either a Python function or a string.
+
+In the first case,
+it's a function that returns a string to be printed
+to describe the action being executed.
+The function may also be specified by the
+.IR strfunction =
+keyword argument.
+Like a function to build a file,
+this function must take three keyword arguments:
+.B target
+(a Node object representing the target file),
+.B source
+(a Node object representing the source file)
+and
+.BR env
+(a construction environment).
+The
+.B target
+and
+.B source
+arguments may be lists of Node objects if there is
+more than one target file or source file.
+
+In the second case, you provide the string itself.
+The string may also be specified by the
+.IR cmdstr =
+keyword argument.
+The string typically contains variables, notably
+$TARGET(S) and $SOURCE(S), or consists of just a single
+variable, which is optionally defined somewhere else.
+SCons itself heavily uses the latter variant.
+
+Examples:
+
+.ES
+def build_it(target, source, env):
+ # build the target from the source
+ return 0
+
+def string_it(target, source, env):
+ return "building '%s' from '%s'" % (target[0], source[0])
+
+# Use a positional argument.
+f = Action(build_it, string_it)
+s = Action(build_it, "building '$TARGET' from '$SOURCE'")
+
+# Alternatively, use a keyword argument.
+f = Action(build_it, strfunction=string_it)
+s = Action(build_it, cmdstr="building '$TARGET' from '$SOURCE'")
+
+# You can provide a configurable variable.
+l = Action(build_it, '$STRINGIT')
+.EE
+
+The third and succeeding arguments, if present,
+may either be a construction variable or a list of construction variables
+whose values will be included in the signature of the Action
+when deciding whether a target should be rebuilt because the action changed.
+The variables may also be specified by a
+.IR varlist =
+keyword parameter;
+if both are present, they are combined.
+This is necessary whenever you want a target to be rebuilt
+when a specific construction variable changes.
+This is not often needed for a string action,
+as the expanded variables will normally be part of the command line,
+but may be needed if a Python function action uses
+the value of a construction variable when generating the command line.
+
+.ES
+def build_it(target, source, env):
+ # build the target from the 'XXX' construction variable
+ open(target[0], 'w').write(env['XXX'])
+ return 0
+
+# Use positional arguments.
+a = Action(build_it, '$STRINGIT', ['XXX'])
+
+# Alternatively, use a keyword argument.
+a = Action(build_it, varlist=['XXX'])
+.EE
+
+The
+.BR Action ()
+global function
+can be passed the following
+optional keyword arguments
+to modify the Action object's behavior:
+
+.IP
+.B chdir
+The
+.B chdir
+keyword argument specifies that
+scons will execute the action
+after changing to the specified directory.
+If the
+.B chdir
+argument is
+a string or a directory Node,
+scons will change to the specified directory.
+If the
+.B chdir
+argument
+is not a string or Node
+and is non-zero,
+then scons will change to the
+target file's directory.
+
+Note that scons will
+.I not
+automatically modify
+its expansion of
+construction variables like
+.B $TARGET
+and
+.B $SOURCE
+when using the chdir
+keyword argument--that is,
+the expanded file names
+will still be relative to
+the top-level SConstruct directory,
+and consequently incorrect
+relative to the chdir directory.
+Builders created using chdir keyword argument,
+will need to use construction variable
+expansions like
+.B ${TARGET.file}
+and
+.B ${SOURCE.file}
+to use just the filename portion of the
+targets and source.
+
+.ES
+a = Action("build < ${SOURCE.file} > ${TARGET.file}",
+ chdir=1)
+.EE
+
+.IP
+.B exitstatfunc
+The
+.BR Action ()
+global function
+also takes an
+.B exitstatfunc
+keyword argument
+which specifies a function
+that is passed the exit status
+(or return value)
+from the specified action
+and can return an arbitrary
+or modified value.
+This can be used, for example,
+to specify that an Action object's
+return value should be ignored
+under special conditions
+and SCons should, therefore,
+consider that the action always suceeds:
+
+.ES
+def always_succeed(s):
+ # Always return 0, which indicates success.
+ return 0
+a = Action("build < ${SOURCE.file} > ${TARGET.file}",
+ exitstatfunc=always_succeed)
+.EE
+
+.IP
+.B batch_key
+The
+.B batch_key
+keyword argument can be used
+to specify that the Action can create multiple target files
+by processing multiple independent source files simultaneously.
+(The canonical example is "batch compilation"
+of multiple object files
+by passing multiple source files
+to a single invocation of a compiler
+such as Microsoft's Visual C / C++ compiler.)
+If the
+.B batch_key
+argument is any non-False, non-callable Python value,
+the configured Action object will cause
+.B scons
+to collect all targets built with the Action object
+and configured with the same construction environment
+into single invocations of the Action object's
+command line or function.
+Command lines will typically want to use the
+.BR CHANGED_SOURCES
+construction variable
+(and possibly
+.BR CHANGED_TARGETS
+as well)
+to only pass to the command line those sources that
+have actually changed since their targets were built.
+
+Example:
+
+.ES
+a = Action('build $CHANGED_SOURCES', batch_key=True)
+.EE
+
+The
+.B batch_key
+argument may also be
+a callable function
+that returns a key that
+will be used to identify different
+"batches" of target files to be collected
+for batch building.
+A
+.B batch_key
+function must take the following arguments:
+
+.IP action
+The action object.
+
+.IP env
+The construction environment
+configured for the target.
+
+.IP target
+The list of targets for a particular configured action.
+
+.IP source
+The list of source for a particular configured action.
+
+The returned key should typically
+be a tuple of values derived from the arguments,
+using any appropriate logic to decide
+how multiple invocations should be batched.
+For example, a
+.B batch_key
+function may decide to return
+the value of a specific construction
+variable from the
+.B env
+argument
+which will cause
+.B scons
+to batch-build targets
+with matching values of that variable,
+or perhaps return the
+.BR id ()
+of the entire construction environment,
+in which case
+.B scons
+will batch-build
+all targets configured with the same construction environment.
+Returning
+.B None
+indicates that
+the particular target should
+.I not
+be part of any batched build,
+but instead will be built
+by a separate invocation of action's
+command or function.
+Example:
+
+.ES
+def batch_key(action, env, target, source):
+ tdir = target[0].dir
+ if tdir.name == 'special':
+ # Don't batch-build any target
+ # in the special/ subdirectory.
+ return None
+ return (id(action), id(env), tdir)
+a = Action('build $CHANGED_SOURCES', batch_key=batch_key)
+.EE
+
+.SS Miscellaneous Action Functions
+
+.B scons
+supplies a number of functions
+that arrange for various common
+file and directory manipulations
+to be performed.
+These are similar in concept to "tasks" in the
+Ant build tool,
+although the implementation is slightly different.
+These functions do not actually
+perform the specified action
+at the time the function is called,
+but instead return an Action object
+that can be executed at the
+appropriate time.
+(In Object-Oriented terminology,
+these are actually
+Action
+.I Factory
+functions
+that return Action objects.)
+
+In practice,
+there are two natural ways
+that these
+Action Functions
+are intended to be used.
+
+First,
+if you need
+to perform the action
+at the time the SConscript
+file is being read,
+you can use the
+.B Execute
+global function to do so:
+.ES
+Execute(Touch('file'))
+.EE
+
+Second,
+you can use these functions
+to supply Actions in a list
+for use by the
+.B Command
+method.
+This can allow you to
+perform more complicated
+sequences of file manipulation
+without relying
+on platform-specific
+external commands:
+that
+.ES
+env = Environment(TMPBUILD = '/tmp/builddir')
+env.Command('foo.out', 'foo.in',
+ [Mkdir('$TMPBUILD'),
+ Copy('$TMPBUILD', '${SOURCE.dir}'),
+ "cd $TMPBUILD && make",
+ Delete('$TMPBUILD')])
+.EE
+
+.TP
+.RI Chmod( dest ", " mode )
+Returns an Action object that
+changes the permissions on the specified
+.I dest
+file or directory to the specified
+.IR mode .
+Examples:
+
+.ES
+Execute(Chmod('file', 0755))
+
+env.Command('foo.out', 'foo.in',
+ [Copy('$TARGET', '$SOURCE'),
+ Chmod('$TARGET', 0755)])
+.EE
+
+.TP
+.RI Copy( dest ", " src )
+Returns an Action object
+that will copy the
+.I src
+source file or directory to the
+.I dest
+destination file or directory.
+Examples:
+
+.ES
+Execute(Copy('foo.output', 'foo.input'))
+
+env.Command('bar.out', 'bar.in',
+ Copy('$TARGET', '$SOURCE'))
+.EE
+
+.TP
+.RI Delete( entry ", [" must_exist ])
+Returns an Action that
+deletes the specified
+.IR entry ,
+which may be a file or a directory tree.
+If a directory is specified,
+the entire directory tree
+will be removed.
+If the
+.I must_exist
+flag is set,
+then a Python error will be thrown
+if the specified entry does not exist;
+the default is
+.BR must_exist=0 ,
+that is, the Action will silently do nothing
+if the entry does not exist.
+Examples:
+
+.ES
+Execute(Delete('/tmp/buildroot'))
+
+env.Command('foo.out', 'foo.in',
+ [Delete('${TARGET.dir}'),
+ MyBuildAction])
+
+Execute(Delete('file_that_must_exist', must_exist=1))
+.EE
+
+.TP
+.RI Mkdir( dir )
+Returns an Action
+that creates the specified
+directory
+.I dir .
+Examples:
+
+.ES
+Execute(Mkdir('/tmp/outputdir'))
+
+env.Command('foo.out', 'foo.in',
+ [Mkdir('/tmp/builddir'),
+ Copy('/tmp/builddir/foo.in', '$SOURCE'),
+ "cd /tmp/builddir && make",
+ Copy('$TARGET', '/tmp/builddir/foo.out')])
+.EE
+
+.TP
+.RI Move( dest ", " src )
+Returns an Action
+that moves the specified
+.I src
+file or directory to
+the specified
+.I dest
+file or directory.
+Examples:
+
+.ES
+Execute(Move('file.destination', 'file.source'))
+
+env.Command('output_file', 'input_file',
+ [MyBuildAction,
+ Move('$TARGET', 'file_created_by_MyBuildAction')])
+.EE
+
+.TP
+.RI Touch( file )
+Returns an Action
+that updates the modification time
+on the specified
+.IR file .
+Examples:
+
+.ES
+Execute(Touch('file_to_be_touched'))
+
+env.Command('marker', 'input_file',
+ [MyBuildAction,
+ Touch('$TARGET')])
+.EE
+
+.SS Variable Substitution
+
+Before executing a command,
+.B scons
+performs construction variable interpolation on the strings that make up
+the command line of builders.
+Variables are introduced by a
+.B $
+prefix.
+Besides construction variables, scons provides the following
+variables for each command execution:
+
+.IP CHANGED_SOURCES
+The file names of all sources of the build command
+that have changed since the target was last built.
+
+.IP CHANGED_TARGETS
+The file names of all targets that would be built
+from sources that have changed since the target was last built.
+
+.IP SOURCE
+The file name of the source of the build command,
+or the file name of the first source
+if multiple sources are being built.
+
+.IP SOURCES
+The file names of the sources of the build command.
+
+.IP TARGET
+The file name of the target being built,
+or the file name of the first target
+if multiple targets are being built.
+
+.IP TARGETS
+The file names of all targets being built.
+
+.IP UNCHANGED_SOURCES
+The file names of all sources of the build command
+that have
+.I not
+changed since the target was last built.
+
+.IP UNCHANGED_TARGETS
+The file names of all targets that would be built
+from sources that have
+.I not
+changed since the target was last built.
+
+(Note that the above variables are reserved
+and may not be set in a construction environment.)
+
+.LP
+For example, given the construction variable CC='cc', targets=['foo'], and
+sources=['foo.c', 'bar.c']:
+
+.ES
+action='$CC -c -o $TARGET $SOURCES'
+.EE
+
+would produce the command line:
+
+.ES
+cc -c -o foo foo.c bar.c
+.EE
+
+Variable names may be surrounded by curly braces ({})
+to separate the name from the trailing characters.
+Within the curly braces, a variable name may have
+a Python slice subscript appended to select one
+or more items from a list.
+In the previous example, the string:
+
+.ES
+${SOURCES[1]}
+.EE
+
+would produce:
+
+.ES
+bar.c
+.EE
+
+Additionally, a variable name may
+have the following special
+modifiers appended within the enclosing curly braces
+to modify the interpolated string:
+
+.IP base
+The base path of the file name,
+including the directory path
+but excluding any suffix.
+
+.IP dir
+The name of the directory in which the file exists.
+
+.IP file
+The file name,
+minus any directory portion.
+
+.IP filebase
+Just the basename of the file,
+minus any suffix
+and minus the directory.
+
+.IP suffix
+Just the file suffix.
+
+.IP abspath
+The absolute path name of the file.
+
+.IP posix
+The POSIX form of the path,
+with directories separated by
+.B /
+(forward slashes)
+not backslashes.
+This is sometimes necessary on Windows systems
+when a path references a file on other (POSIX) systems.
+
+.IP srcpath
+The directory and file name to the source file linked to this file through
+.BR VariantDir ().
+If this file isn't linked,
+it just returns the directory and filename unchanged.
+
+.IP srcdir
+The directory containing the source file linked to this file through
+.BR VariantDir ().
+If this file isn't linked,
+it just returns the directory part of the filename.
+
+.IP rsrcpath
+The directory and file name to the source file linked to this file through
+.BR VariantDir ().
+If the file does not exist locally but exists in a Repository,
+the path in the Repository is returned.
+If this file isn't linked, it just returns the
+directory and filename unchanged.
+
+.IP rsrcdir
+The Repository directory containing the source file linked to this file through
+.BR VariantDir ().
+If this file isn't linked,
+it just returns the directory part of the filename.
+
+.LP
+For example, the specified target will
+expand as follows for the corresponding modifiers:
+
+.ES
+$TARGET => sub/dir/file.x
+${TARGET.base} => sub/dir/file
+${TARGET.dir} => sub/dir
+${TARGET.file} => file.x
+${TARGET.filebase} => file
+${TARGET.suffix} => .x
+${TARGET.abspath} => /top/dir/sub/dir/file.x
+
+SConscript('src/SConscript', variant_dir='sub/dir')
+$SOURCE => sub/dir/file.x
+${SOURCE.srcpath} => src/file.x
+${SOURCE.srcdir} => src
+
+Repository('/usr/repository')
+$SOURCE => sub/dir/file.x
+${SOURCE.rsrcpath} => /usr/repository/src/file.x
+${SOURCE.rsrcdir} => /usr/repository/src
+.EE
+
+Note that curly braces braces may also be used
+to enclose arbitrary Python code to be evaluated.
+(In fact, this is how the above modifiers are substituted,
+they are simply attributes of the Python objects
+that represent TARGET, SOURCES, etc.)
+See the section "Python Code Substitution," below,
+for more thorough examples of
+how this can be used.
+
+Lastly, a variable name
+may be a callable Python function
+associated with a
+construction variable in the environment.
+The function should
+take four arguments:
+.I target
+- a list of target nodes,
+.I source
+- a list of source nodes,
+.I env
+- the construction environment,
+.I for_signature
+- a Boolean value that specifies
+whether the function is being called
+for generating a build signature.
+SCons will insert whatever
+the called function returns
+into the expanded string:
+
+.ES
+def foo(target, source, env, for_signature):
+ return "bar"
+
+# Will expand $BAR to "bar baz"
+env=Environment(FOO=foo, BAR="$FOO baz")
+.EE
+
+You can use this feature to pass arguments to a
+Python function by creating a callable class
+that stores one or more arguments in an object,
+and then uses them when the
+.B __call__()
+method is called.
+Note that in this case,
+the entire variable expansion must
+be enclosed by curly braces
+so that the arguments will
+be associated with the
+instantiation of the class:
+
+.ES
+class foo:
+ def __init__(self, arg):
+ self.arg = arg
+
+ def __call__(self, target, source, env, for_signature):
+ return self.arg + " bar"
+
+# Will expand $BAR to "my argument bar baz"
+env=Environment(FOO=foo, BAR="${FOO('my argument')} baz")
+.EE
+
+.LP
+The special pseudo-variables
+.B "$("
+and
+.B "$)"
+may be used to surround parts of a command line
+that may change
+.I without
+causing a rebuild--that is,
+which are not included in the signature
+of target files built with this command.
+All text between
+.B "$("
+and
+.B "$)"
+will be removed from the command line
+before it is added to file signatures,
+and the
+.B "$("
+and
+.B "$)"
+will be removed before the command is executed.
+For example, the command line:
+
+.ES
+echo Last build occurred $( $TODAY $). > $TARGET
+.EE
+
+.LP
+would execute the command:
+
+.ES
+echo Last build occurred $TODAY. > $TARGET
+.EE
+
+.LP
+but the command signature added to any target files would be:
+
+.ES
+echo Last build occurred . > $TARGET
+.EE
+
+.SS Python Code Substitution
+
+Any python code within
+.BR "${" - "}"
+pairs gets evaluated by python 'eval', with the python globals set to
+the current environment's set of construction variables.
+So in the following case:
+.ES
+env['COND'] = 0
+env.Command('foo.out', 'foo.in',
+ '''echo ${COND==1 and 'FOO' or 'BAR'} > $TARGET''')
+.EE
+the command executed will be either
+.ES
+echo FOO > foo.out
+.EE
+or
+.ES
+echo BAR > foo.out
+.EE
+according to the current value of env['COND'] when the command is
+executed. The evaluation occurs when the target is being
+built, not when the SConscript is being read. So if env['COND'] is changed
+later in the SConscript, the final value will be used.
+
+Here's a more interesting example. Note that all of COND, FOO, and
+BAR are environment variables, and their values are substituted into
+the final command. FOO is a list, so its elements are interpolated
+separated by spaces.
+
+.ES
+env=Environment()
+env['COND'] = 0
+env['FOO'] = ['foo1', 'foo2']
+env['BAR'] = 'barbar'
+env.Command('foo.out', 'foo.in',
+ 'echo ${COND==1 and FOO or BAR} > $TARGET')
+
+# Will execute this:
+# echo foo1 foo2 > foo.out
+.EE
+
+SCons uses the following rules when converting construction variables into
+command lines:
+
+.IP String
+When the value is a string it is interpreted as a space delimited list of
+command line arguments.
+
+.IP List
+When the value is a list it is interpreted as a list of command line
+arguments. Each element of the list is converted to a string.
+
+.IP Other
+Anything that is not a list or string is converted to a string and
+interpreted as a single command line argument.
+
+.IP Newline
+Newline characters (\\n) delimit lines. The newline parsing is done after
+all other parsing, so it is not possible for arguments (e.g. file names) to
+contain embedded newline characters. This limitation will likely go away in
+a future version of SCons.
+
+.SS Scanner Objects
+
+You can use the
+.B Scanner
+function to define
+objects to scan
+new file types for implicit dependencies.
+Scanner accepts the following arguments:
+
+.IP function
+This can be either:
+1) a Python function that will process
+the Node (file)
+and return a list of strings (file names)
+representing the implicit
+dependencies found in the contents;
+or:
+2) a dictionary that maps keys
+(typically the file suffix, but see below for more discussion)
+to other Scanners that should be called.
+
+If the argument is actually a Python function,
+the function must take three or four arguments:
+
+ def scanner_function(node, env, path):
+
+ def scanner_function(node, env, path, arg=None):
+
+The
+.B node
+argument is the internal
+SCons node representing the file.
+Use
+.B str(node)
+to fetch the name of the file, and
+.B node.get_contents()
+to fetch contents of the file.
+Note that the file is
+.I not
+guaranteed to exist before the scanner is called,
+so the scanner function should check that
+if there's any chance that the scanned file
+might not exist
+(for example, if it's built from other files).
+
+The
+.B env
+argument is the construction environment for the scan.
+Fetch values from it using the
+.B env.Dictionary()
+method.
+
+The
+.B path
+argument is a tuple (or list)
+of directories that can be searched
+for files.
+This will usually be the tuple returned by the
+.B path_function
+argument (see below).
+
+The
+.B arg
+argument is the argument supplied
+when the scanner was created, if any.
+
+.IP name
+The name of the Scanner.
+This is mainly used
+to identify the Scanner internally.
+
+.IP argument
+An optional argument that, if specified,
+will be passed to the scanner function
+(described above)
+and the path function
+(specified below).
+
+.IP skeys
+An optional list that can be used to
+determine which scanner should be used for
+a given Node.
+In the usual case of scanning for file names,
+this argument will be a list of suffixes
+for the different file types that this
+Scanner knows how to scan.
+If the argument is a string,
+then it will be expanded
+into a list by the current environment.
+
+.IP path_function
+A Python function that takes four or five arguments:
+a construction environment,
+a Node for the directory containing
+the SConscript file in which
+the first target was defined,
+a list of target nodes,
+a list of source nodes,
+and an optional argument supplied
+when the scanner was created.
+The
+.B path_function
+returns a tuple of directories
+that can be searched for files to be returned
+by this Scanner object.
+(Note that the
+.BR FindPathDirs ()
+function can be used to return a ready-made
+.B path_function
+for a given construction variable name,
+instead of having to write your own function from scratch.)
+
+.IP node_class
+The class of Node that should be returned
+by this Scanner object.
+Any strings or other objects returned
+by the scanner function
+that are not of this class
+will be run through the
+.B node_factory
+function.
+
+.IP node_factory
+A Python function that will take a string
+or other object
+and turn it into the appropriate class of Node
+to be returned by this Scanner object.
+
+.IP scan_check
+An optional Python function that takes two arguments,
+a Node (file) and a construction environment,
+and returns whether the
+Node should, in fact,
+be scanned for dependencies.
+This check can be used to eliminate unnecessary
+calls to the scanner function when,
+for example, the underlying file
+represented by a Node does not yet exist.
+
+.IP recursive
+An optional flag that
+specifies whether this scanner should be re-invoked
+on the dependency files returned by the scanner.
+When this flag is not set,
+the Node subsystem will
+only invoke the scanner on the file being scanned,
+and not (for example) also on the files
+specified by the #include lines
+in the file being scanned.
+.I recursive
+may be a callable function,
+in which case it will be called with a list of
+Nodes found and
+should return a list of Nodes
+that should be scanned recursively;
+this can be used to select a specific subset of
+Nodes for additional scanning.
+
+Note that
+.B scons
+has a global
+.B SourceFileScanner
+object that is used by
+the
+.BR Object (),
+.BR SharedObject (),
+and
+.BR StaticObject ()
+builders to decide
+which scanner should be used
+for different file extensions.
+You can using the
+.BR SourceFileScanner.add_scanner ()
+method to add your own Scanner object
+to the
+.B scons
+infrastructure
+that builds target programs or
+libraries from a list of
+source files of different types:
+
+.ES
+def xyz_scan(node, env, path):
+ contents = node.get_text_contents()
+ # Scan the contents and return the included files.
+
+XYZScanner = Scanner(xyz_scan)
+
+SourceFileScanner.add_scanner('.xyx', XYZScanner)
+
+env.Program('my_prog', ['file1.c', 'file2.f', 'file3.xyz'])
+.EE
+
+.SH SYSTEM-SPECIFIC BEHAVIOR
+SCons and its configuration files are very portable,
+due largely to its implementation in Python.
+There are, however, a few portability
+issues waiting to trap the unwary.
+.SS .C file suffix
+SCons handles the upper-case
+.B .C
+file suffix differently,
+depending on the capabilities of
+the underlying system.
+On a case-sensitive system
+such as Linux or UNIX,
+SCons treats a file with a
+.B .C
+suffix as a C++ source file.
+On a case-insensitive system
+such as Windows,
+SCons treats a file with a
+.B .C
+suffix as a C source file.
+.SS .F file suffix
+SCons handles the upper-case
+.B .F
+file suffix differently,
+depending on the capabilities of
+the underlying system.
+On a case-sensitive system
+such as Linux or UNIX,
+SCons treats a file with a
+.B .F
+suffix as a Fortran source file
+that is to be first run through
+the standard C preprocessor.
+On a case-insensitive system
+such as Windows,
+SCons treats a file with a
+.B .F
+suffix as a Fortran source file that should
+.I not
+be run through the C preprocessor.
+.SS Windows: Cygwin Tools and Cygwin Python vs. Windows Pythons
+Cygwin supplies a set of tools and utilities
+that let users work on a
+Windows system using a more POSIX-like environment.
+The Cygwin tools, including Cygwin Python,
+do this, in part,
+by sharing an ability to interpret UNIX-like path names.
+For example, the Cygwin tools
+will internally translate a Cygwin path name
+like /cygdrive/c/mydir
+to an equivalent Windows pathname
+of C:/mydir (equivalent to C:\\mydir).
+
+Versions of Python
+that are built for native Windows execution,
+such as the python.org and ActiveState versions,
+do not have the Cygwin path name semantics.
+This means that using a native Windows version of Python
+to build compiled programs using Cygwin tools
+(such as gcc, bison, and flex)
+may yield unpredictable results.
+"Mixing and matching" in this way
+can be made to work,
+but it requires careful attention to the use of path names
+in your SConscript files.
+
+In practice, users can sidestep
+the issue by adopting the following rules:
+When using gcc,
+use the Cygwin-supplied Python interpreter
+to run SCons;
+when using Microsoft Visual C/C++
+(or some other Windows compiler)
+use the python.org or ActiveState version of Python
+to run SCons.
+.SS Windows: scons.bat file
+On Windows systems,
+SCons is executed via a wrapper
+.B scons.bat
+file.
+This has (at least) two ramifications:
+
+First, Windows command-line users
+that want to use variable assignment
+on the command line
+may have to put double quotes
+around the assignments:
+
+.ES
+scons "FOO=BAR" "BAZ=BLEH"
+.EE
+
+Second, the Cygwin shell does not
+recognize this file as being the same
+as an
+.B scons
+command issued at the command-line prompt.
+You can work around this either by
+executing
+.B scons.bat
+from the Cygwin command line,
+or by creating a wrapper shell
+script named
+.B scons .
+
+.SS MinGW
+
+The MinGW bin directory must be in your PATH environment variable or the
+PATH variable under the ENV construction variable for SCons
+to detect and use the MinGW tools. When running under the native Windows
+Python interpreter, SCons will prefer the MinGW tools over the Cygwin
+tools, if they are both installed, regardless of the order of the bin
+directories in the PATH variable. If you have both MSVC and MinGW
+installed and you want to use MinGW instead of MSVC,
+then you must explictly tell SCons to use MinGW by passing
+
+.ES
+tools=['mingw']
+.EE
+
+to the Environment() function, because SCons will prefer the MSVC tools
+over the MinGW tools.
+
+.SH EXAMPLES
+
+To help you get started using SCons,
+this section contains a brief overview of some common tasks.
+
+.SS Basic Compilation From a Single Source File
+
+.ES
+env = Environment()
+env.Program(target = 'foo', source = 'foo.c')
+.EE
+
+Note: Build the file by specifying
+the target as an argument
+("scons foo" or "scons foo.exe").
+or by specifying a dot ("scons .").
+
+.SS Basic Compilation From Multiple Source Files
+
+.ES
+env = Environment()
+env.Program(target = 'foo', source = Split('f1.c f2.c f3.c'))
+.EE
+
+.SS Setting a Compilation Flag
+
+.ES
+env = Environment(CCFLAGS = '-g')
+env.Program(target = 'foo', source = 'foo.c')
+.EE
+
+.SS Search The Local Directory For .h Files
+
+Note: You do
+.I not
+need to set CCFLAGS to specify -I options by hand.
+SCons will construct the right -I options from CPPPATH.
+
+.ES
+env = Environment(CPPPATH = ['.'])
+env.Program(target = 'foo', source = 'foo.c')
+.EE
+
+.SS Search Multiple Directories For .h Files
+
+.ES
+env = Environment(CPPPATH = ['include1', 'include2'])
+env.Program(target = 'foo', source = 'foo.c')
+.EE
+
+.SS Building a Static Library
+
+.ES
+env = Environment()
+env.StaticLibrary(target = 'foo', source = Split('l1.c l2.c'))
+env.StaticLibrary(target = 'bar', source = ['l3.c', 'l4.c'])
+.EE
+
+.SS Building a Shared Library
+
+.ES
+env = Environment()
+env.SharedLibrary(target = 'foo', source = ['l5.c', 'l6.c'])
+env.SharedLibrary(target = 'bar', source = Split('l7.c l8.c'))
+.EE
+
+.SS Linking a Local Library Into a Program
+
+.ES
+env = Environment(LIBS = 'mylib', LIBPATH = ['.'])
+env.Library(target = 'mylib', source = Split('l1.c l2.c'))
+env.Program(target = 'prog', source = ['p1.c', 'p2.c'])
+.EE
+
+.SS Defining Your Own Builder Object
+
+Notice that when you invoke the Builder,
+you can leave off the target file suffix,
+and SCons will add it automatically.
+
+.ES
+bld = Builder(action = 'pdftex < $SOURCES > $TARGET'
+ suffix = '.pdf',
+ src_suffix = '.tex')
+env = Environment(BUILDERS = {'PDFBuilder' : bld})
+env.PDFBuilder(target = 'foo.pdf', source = 'foo.tex')
+
+# The following creates "bar.pdf" from "bar.tex"
+env.PDFBuilder(target = 'bar', source = 'bar')
+.EE
+
+Note also that the above initialization
+overwrites the default Builder objects,
+so the Environment created above
+can not be used call Builders like env.Program(),
+env.Object(), env.StaticLibrary(), etc.
+
+.SS Adding Your Own Builder Object to an Environment
+
+.ES
+bld = Builder(action = 'pdftex < $SOURCES > $TARGET'
+ suffix = '.pdf',
+ src_suffix = '.tex')
+env = Environment()
+env.Append(BUILDERS = {'PDFBuilder' : bld})
+env.PDFBuilder(target = 'foo.pdf', source = 'foo.tex')
+env.Program(target = 'bar', source = 'bar.c')
+.EE
+
+You also can use other Pythonic techniques to add
+to the BUILDERS construction variable, such as:
+
+.ES
+env = Environment()
+env['BUILDERS]['PDFBuilder'] = bld
+.EE
+
+.SS Defining Your Own Scanner Object
+
+The following example shows an extremely simple scanner (the
+.BR kfile_scan ()
+function)
+that doesn't use a search path at all
+and simply returns the
+file names present on any
+.B include
+lines in the scanned file.
+This would implicitly assume that all included
+files live in the top-level directory:
+
+.ES
+import re
+
+'\" Note: the \\ in the following are for the benefit of nroff/troff,
+'\" not inappropriate doubled escape characters within the r'' raw string.
+include_re = re.compile(r'^include\\s+(\\S+)$', re.M)
+
+def kfile_scan(node, env, path, arg):
+ contents = node.get_text_contents()
+ includes = include_re.findall(contents)
+ return includes
+
+kscan = Scanner(name = 'kfile',
+ function = kfile_scan,
+ argument = None,
+ skeys = ['.k'])
+scanners = Environment().Dictionary('SCANNERS')
+env = Environment(SCANNERS = scanners + [kscan])
+
+env.Command('foo', 'foo.k', 'kprocess < $SOURCES > $TARGET')
+
+bar_in = File('bar.in')
+env.Command('bar', bar_in, 'kprocess $SOURCES > $TARGET')
+bar_in.target_scanner = kscan
+.EE
+
+Here is a similar but more complete example that searches
+a path of directories
+(specified as the
+.B MYPATH
+construction variable)
+for files that actually exist:
+
+.ES
+include_re = re.compile(r'^include\\s+(\\S+)$', re.M)
+
+def my_scan(node, env, path, arg):
+ contents = node.get_text_contents()
+ includes = include_re.findall(contents)
+ if includes == []:
+ return []
+ results = []
+ for inc in includes:
+ for dir in path:
+ file = dir + os.sep + inc
+ if os.path.exists(file):
+ results.append(file)
+ break
+ return results
+
+scanner = Scanner(name = 'myscanner',
+ function = my_scan,
+ argument = None,
+ skeys = ['.x'],
+ path_function = FindPathDirs('MYPATH'),
+ )
+scanners = Environment().Dictionary('SCANNERS')
+env = Environment(SCANNERS = scanners + [scanner])
+.EE
+
+The
+.BR FindPathDirs ()
+function used in the previous example returns a function
+(actually a callable Python object)
+that will return a list of directories
+specified in the
+.B $MYPATH
+construction variable.
+If you need to customize how the search path is derived,
+you would provide your own
+.B path_function
+argument when creating the Scanner object,
+as follows:
+
+.ES
+# MYPATH is a list of directories to search for files in
+def pf(env, dir, target, source, arg):
+ top_dir = Dir('#').abspath
+ results = []
+ if env.has_key('MYPATH'):
+ for p in env['MYPATH']:
+ results.append(top_dir + os.sep + p)
+ return results
+
+scanner = Scanner(name = 'myscanner',
+ function = my_scan,
+ argument = None,
+ skeys = ['.x'],
+ path_function = pf,
+ )
+.EE
+
+.SS Creating a Hierarchical Build
+
+Notice that the file names specified in a subdirectory's
+SConscript
+file are relative to that subdirectory.
+
+.ES
+SConstruct:
+
+ env = Environment()
+ env.Program(target = 'foo', source = 'foo.c')
+
+ SConscript('sub/SConscript')
+
+sub/SConscript:
+
+ env = Environment()
+ # Builds sub/foo from sub/foo.c
+ env.Program(target = 'foo', source = 'foo.c')
+
+ SConscript('dir/SConscript')
+
+sub/dir/SConscript:
+
+ env = Environment()
+ # Builds sub/dir/foo from sub/dir/foo.c
+ env.Program(target = 'foo', source = 'foo.c')
+.EE
+
+.SS Sharing Variables Between SConscript Files
+
+You must explicitly Export() and Import() variables that
+you want to share between SConscript files.
+
+.ES
+SConstruct:
+
+ env = Environment()
+ env.Program(target = 'foo', source = 'foo.c')
+
+ Export("env")
+ SConscript('subdirectory/SConscript')
+
+subdirectory/SConscript:
+
+ Import("env")
+ env.Program(target = 'foo', source = 'foo.c')
+.EE
+
+.SS Building Multiple Variants From the Same Source
+
+Use the variant_dir keyword argument to
+the SConscript function to establish
+one or more separate variant build directory trees
+for a given source directory:
+
+.ES
+SConstruct:
+
+ cppdefines = ['FOO']
+ Export("cppdefines")
+ SConscript('src/SConscript', variant_dir='foo')
+
+ cppdefines = ['BAR']
+ Export("cppdefines")
+ SConscript('src/SConscript', variant_dir='bar')
+
+src/SConscript:
+
+ Import("cppdefines")
+ env = Environment(CPPDEFINES = cppdefines)
+ env.Program(target = 'src', source = 'src.c')
+.EE
+
+Note the use of the Export() method
+to set the "cppdefines" variable to a different
+value each time we call the SConscript function.
+
+.SS Hierarchical Build of Two Libraries Linked With a Program
+
+.ES
+SConstruct:
+
+ env = Environment(LIBPATH = ['#libA', '#libB'])
+ Export('env')
+ SConscript('libA/SConscript')
+ SConscript('libB/SConscript')
+ SConscript('Main/SConscript')
+
+libA/SConscript:
+
+ Import('env')
+ env.Library('a', Split('a1.c a2.c a3.c'))
+
+libB/SConscript:
+
+ Import('env')
+ env.Library('b', Split('b1.c b2.c b3.c'))
+
+Main/SConscript:
+
+ Import('env')
+ e = env.Copy(LIBS = ['a', 'b'])
+ e.Program('foo', Split('m1.c m2.c m3.c'))
+.EE
+
+The '#' in the LIBPATH directories specify that they're relative to the
+top-level directory, so they don't turn into "Main/libA" when they're
+used in Main/SConscript.
+
+Specifying only 'a' and 'b' for the library names
+allows SCons to append the appropriate library
+prefix and suffix for the current platform
+(for example, 'liba.a' on POSIX systems,
+\&'a.lib' on Windows).
+
+.SS Customizing construction variables from the command line.
+
+The following would allow the C compiler to be specified on the command
+line or in the file custom.py.
+
+.ES
+vars = Variables('custom.py')
+vars.Add('CC', 'The C compiler.')
+env = Environment(variables=vars)
+Help(vars.GenerateHelpText(env))
+.EE
+
+The user could specify the C compiler on the command line:
+
+.ES
+scons "CC=my_cc"
+.EE
+
+or in the custom.py file:
+
+.ES
+CC = 'my_cc'
+.EE
+
+or get documentation on the options:
+
+.ES
+$ scons -h
+
+CC: The C compiler.
+ default: None
+ actual: cc
+
+.EE
+
+.SS Using Microsoft Visual C++ precompiled headers
+
+Since windows.h includes everything and the kitchen sink, it can take quite
+some time to compile it over and over again for a bunch of object files, so
+Microsoft provides a mechanism to compile a set of headers once and then
+include the previously compiled headers in any object file. This
+technology is called precompiled headers. The general recipe is to create a
+file named "StdAfx.cpp" that includes a single header named "StdAfx.h", and
+then include every header you want to precompile in "StdAfx.h", and finally
+include "StdAfx.h" as the first header in all the source files you are
+compiling to object files. For example:
+
+StdAfx.h:
+.ES
+#include <windows.h>
+#include <my_big_header.h>
+.EE
+
+StdAfx.cpp:
+.ES
+#include <StdAfx.h>
+.EE
+
+Foo.cpp:
+.ES
+#include <StdAfx.h>
+
+/* do some stuff */
+.EE
+
+Bar.cpp:
+.ES
+#include <StdAfx.h>
+
+/* do some other stuff */
+.EE
+
+SConstruct:
+.ES
+env=Environment()
+env['PCHSTOP'] = 'StdAfx.h'
+env['PCH'] = env.PCH('StdAfx.cpp')[0]
+env.Program('MyApp', ['Foo.cpp', 'Bar.cpp'])
+.EE
+
+For more information see the document for the PCH builder, and the PCH and
+PCHSTOP construction variables. To learn about the details of precompiled
+headers consult the MSDN documention for /Yc, /Yu, and /Yp.
+
+.SS Using Microsoft Visual C++ external debugging information
+
+Since including debugging information in programs and shared libraries can
+cause their size to increase significantly, Microsoft provides a mechanism
+for including the debugging information in an external file called a PDB
+file. SCons supports PDB files through the PDB construction
+variable.
+
+SConstruct:
+.ES
+env=Environment()
+env['PDB'] = 'MyApp.pdb'
+env.Program('MyApp', ['Foo.cpp', 'Bar.cpp'])
+.EE
+
+For more information see the document for the PDB construction variable.
+
+.SH ENVIRONMENT
+
+.IP SCONS_LIB_DIR
+Specifies the directory that contains the SCons Python module directory
+(e.g. /home/aroach/scons-src-0.01/src/engine).
+
+.IP SCONSFLAGS
+A string of options that will be used by scons in addition to those passed
+on the command line.
+
+.SH "SEE ALSO"
+.B scons
+User Manual,
+.B scons
+Design Document,
+.B scons
+source code.
+
+.SH AUTHORS
+Steven Knight <knight@baldmt.com>
+.br
+Anthony Roach <aroach@electriceyeball.com>
+
diff --git a/doc/man/sconsign.1 b/doc/man/sconsign.1
new file mode 100644
index 0000000..6694784
--- /dev/null
+++ b/doc/man/sconsign.1
@@ -0,0 +1,208 @@
+.\" Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+.\"
+.\" 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.
+.\"
+.\" doc/man/sconsign.1 4577 2009/12/27 19:44:43 scons
+.\"
+.\" ES - Example Start - indents and turns off line fill
+.de ES
+.RS
+.nf
+..
+.\" EE - Example End - ends indent and turns line fill back on
+.de EE
+.RE
+.fi
+..
+.TH SCONSIGN 1 "December 2009"
+.SH NAME
+sconsign \- print SCons .sconsign file information
+.SH SYNOPSIS
+.B sconsign
+[
+.IR options ...
+]
+.IR file
+[ ... ]
+.SH DESCRIPTION
+
+The
+.B sconsign
+command
+displays the contents of one or more
+.B .sconsign
+files specified by the user.
+
+By default,
+.B sconsign
+dumps the entire contents of the
+specified file(s).
+Each entry is printed in the following format:
+
+ file: signature timestamp length
+ implicit_dependency_1: signature timestamp length
+ implicit_dependency_2: signature timestamp length
+ action_signature [action string]
+
+.B None
+is printed
+in place of any missing timestamp, bsig, or csig
+values for
+any entry
+or any of its dependencies.
+If the entry has no implicit dependencies,
+or no build action,
+the lines are simply omitted.
+
+By default,
+.B sconsign
+assumes that any
+.I file
+arguments that end with a
+.B .dbm
+suffix contains
+signature entries for
+more than one directory
+(that is,
+was specified by the
+.B SConsignFile ()
+function).
+Any
+.I file
+argument that does not end in
+.B .dbm
+is assumed to be a traditional
+.B .sconsign
+file containing the signature entries
+for a single directory.
+An explicit format
+may be specified using the
+.B -f
+or
+.B --file=
+options.
+
+.SH OPTIONS
+
+Various options control what information is printed
+and the format:
+
+.TP
+-a, --act, --action
+Prints the build action information
+for all entries or the specified entries.
+
+.TP
+-c, --csig
+Prints the content signature (csig) information
+for all entries or the specified entries.
+
+.TP
+-d DIRECTORY, --dir=DIRECTORY
+When the signatures are being
+read from a
+.B .dbm
+file, or the
+.B -f dbm
+or
+.B --format=dbm
+options are used,
+prints information about
+only the signatures
+for entries in the specified
+.IR DIRECTORY .
+
+.TP
+-e ENTRY, --entry=ENTRY
+Prints information about only the specified
+.IR ENTRY .
+Multiple -e options may be used,
+in which case information about each
+.I ENTRY
+is printed in the order in which the
+options are specified on the command line.
+
+.TP
+-f FORMAT, --format=FORMAT
+The file(s) to be printed
+are in the specified
+.IR FORMAT .
+Legal values are
+.B dbm
+(the DBM format used
+when the
+.BR SConsignFile ()
+function is used)
+or
+.B sconsign
+(the default format
+used for an individual
+.B .sconsign
+file in each directory).
+
+.TP
+-h, --help
+Prints a help message and exits.
+
+.TP
+-i, --implicit
+Prints the list of cached implicit dependencies
+for all entries or the the specified entries.
+
+.TP
+--raw
+Prints a pretty-printed representation
+of the raw Python dictionary that holds
+build information about individual entry
+(both the entry itself or its implicit dependencies).
+An entry's build action is still printed in its usual format.
+
+.TP
+-r, --readable
+Prints timestamps in a human-readable string,
+enclosed in single quotes.
+
+.TP
+-t, --timestamp
+Prints the timestamp information
+for all entries or the specified entries.
+
+.TP
+-v, --verbose
+Prints labels identifying each field being printed.
+
+.SH ENVIRONMENT
+
+.IP SCONS_LIB_DIR
+Specifies the directory that contains the SCons Python module directory
+(e.g. /home/aroach/scons-src-0.01/src/engine).
+on the command line.
+
+.SH "SEE ALSO"
+.BR scons ,
+.B scons
+User Manual,
+.B scons
+Design Document,
+.B scons
+source code.
+
+.SH AUTHORS
+Steven Knight <knight at baldmt dot com>
diff --git a/doc/python10/MANIFEST b/doc/python10/MANIFEST
new file mode 100644
index 0000000..c9484d8
--- /dev/null
+++ b/doc/python10/MANIFEST
@@ -0,0 +1,16 @@
+abstract.xml
+acks.xml
+arch.fig
+builder.fig
+copyright.xml
+design.xml
+future.xml
+install.xml
+intro.xml
+job-task.fig
+main.xml
+node.fig
+process.xml
+scanner.fig
+scons.mod
+sig.fig
diff --git a/doc/python10/abstract.xml b/doc/python10/abstract.xml
new file mode 100644
index 0000000..294180b
--- /dev/null
+++ b/doc/python10/abstract.xml
@@ -0,0 +1,32 @@
+<para>
+
+ &SCons; is a software construction tool (build tool, or make tool)
+ implemented in Python, which uses Python scripts as "configuration
+ files" for software builds. Based on the design which won the
+ Software Carpentry build tool competition, &SCons solves a number of
+ problems associated with other build tools, especially including the
+ classic and ubiquitous &Make; itself.
+
+</para>
+
+<para>
+
+ Distinctive features of &SCons; include: a modular design that
+ lends itself to being embedded in other applications; a global
+ view of all dependencies in the source tree; an improved model for
+ parallel (<option>-j</option>) builds; automatic scanning of files for
+ dependencies; use of MD5 signatures for deciding whether a file
+ is up-to-date; use of traditional file timestamps instead of
+ MD5 signatures available as an option;
+ use of Python functions or objects to build target files; easy user
+ extensibility.
+
+</para>
+
+<para>
+
+ This paper discusses the goals of the &SCons; project, gives an overview
+ of the design of &SCons; itself, describes the development process used,
+ and discusses future plans and directions for the tool.
+
+</para>
diff --git a/doc/python10/acks.xml b/doc/python10/acks.xml
new file mode 100644
index 0000000..895bad7
--- /dev/null
+++ b/doc/python10/acks.xml
@@ -0,0 +1,27 @@
+<para>
+
+ First, many thanks to the great group of developers who dove in right
+ from the beginning and have contributed the code and ideas to make
+ &SCons; a success: Chad Austin, Charles Crain, Steve Leblanc, and
+ Anthony Roach. Thanks also to those on the scons-devel mailing list
+ who have contributed greatly to the discussion, notably including
+ David Abrahams, Trent Mick, and Steven Shaw.
+
+</para>
+
+<para>
+
+ &SCons; would not exist today without the pioneering work of Bob
+ Sidebotham on the original &Cons; tool, and without Greg Wilson's
+ having started the Software Carpentry contest.
+
+</para>
+
+<para>
+
+ Thanks also to Peter Miller for: Aegis; the testing discipline that it
+ enforces, without which creating a stable but flexible tool would be
+ impossible; the "Recursive Make Considered Harmful" paper which led me
+ to experiment with &Cons; in the first place.
+
+</para>
diff --git a/doc/python10/arch.eps b/doc/python10/arch.eps
new file mode 100644
index 0000000..1fdd51f
--- /dev/null
+++ b/doc/python10/arch.eps
@@ -0,0 +1,134 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: build/doc/python10/arch.fig
+%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d
+%%CreationDate: Sun Jan 2 01:21:05 2005
+%%For: knight@casablanca.home.baldmt.com (Steven Knight)
+%%BoundingBox: 0 0 218 182
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 182 moveto 0 0 lineto 218 0 lineto 218 182 lineto closepath clip newpath
+-215.3 324.7 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%
+% Fig objects follow
+%
+/Courier-Bold ff 300.00 scf sf
+3825 2925 m
+gs 1 -1 sc (scons) col0 sh gr
+/Times-Roman ff 300.00 scf sf
+3825 3225 m
+gs 1 -1 sc (Script) col0 sh gr
+/Times-Roman ff 300.00 scf sf
+5100 4875 m
+gs 1 -1 sc (Build Engine) col0 sh gr
+/Courier-Bold ff 300.00 scf sf
+4200 4875 m
+gs 1 -1 sc (SCons) col0 sh gr
+% Polyline
+7.500 slw
+n 3600 4200 m 7200 4200 l 7200 5400 l 3600 5400 l
+ cp gs col0 s gr
+/Courier-Bold ff 300.00 scf sf
+4725 4050 m
+gs 1 -1 sc (SCons) col0 sh gr
+/Times-Roman ff 300.00 scf sf
+5625 4050 m
+gs 1 -1 sc (API) col0 sh gr
+% Polyline
+n 3600 2400 m 3600 2400 l 3600 2400 l 3600 2400 l
+ cp gs col0 s gr
+% Polyline
+n 3600 2400 m 4800 2400 l 4800 3600 l 3600 3600 l
+ cp gs col0 s gr
+% Polyline
+n 3600 3600 m 7200 3600 l 7200 4200 l 3600 4200 l
+ cp gs col0 s gr
+% Polyline
+ [60] 0 sd
+n 6000 3600 m 7200 3600 l 7200 2400 l 6000 2400 l
+ cp gs col0 s gr [] 0 sd
+/Times-Italic ff 300.00 scf sf
+6300 2925 m
+gs 1 -1 sc (other) col0 sh gr
+/Times-Italic ff 300.00 scf sf
+6150 3225 m
+gs 1 -1 sc (interface) col0 sh gr
+$F2psEnd
+rs
diff --git a/doc/python10/arch.fig b/doc/python10/arch.fig
new file mode 100644
index 0000000..ae20bd4
--- /dev/null
+++ b/doc/python10/arch.fig
@@ -0,0 +1,35 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 3825 2775 4650 3300
+4 0 0 50 0 14 20 0.0000 4 135 825 3825 2925 scons\001
+4 0 0 50 0 0 20 0.0000 4 255 690 3825 3225 Script\001
+-6
+6 3600 4200 7200 5400
+6 4200 4650 6675 4950
+4 0 0 50 0 0 20 0.0000 4 255 1515 5100 4875 Build Engine\001
+4 0 0 50 0 14 20 0.0000 4 165 825 4200 4875 SCons\001
+-6
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3600 4200 7200 4200 7200 5400 3600 5400 3600 4200
+-6
+6 4725 3825 6150 4050
+4 0 0 50 0 14 20 0.0000 4 165 825 4725 4050 SCons\001
+4 0 0 50 0 0 20 0.0000 4 195 465 5625 4050 API\001
+-6
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3600 2400 3600 2400 3600 2400 3600 2400 3600 2400
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3600 2400 4800 2400 4800 3600 3600 3600 3600 2400
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3600 3600 7200 3600 7200 4200 3600 4200 3600 3600
+2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5
+ 6000 3600 7200 3600 7200 2400 6000 2400 6000 3600
+4 0 0 50 0 1 20 0.0000 4 210 570 6300 2925 other\001
+4 0 0 50 0 1 20 0.0000 4 270 975 6150 3225 interface\001
diff --git a/doc/python10/arch.jpg b/doc/python10/arch.jpg
new file mode 100644
index 0000000..4e69437
--- /dev/null
+++ b/doc/python10/arch.jpg
Binary files differ
diff --git a/doc/python10/builder.eps b/doc/python10/builder.eps
new file mode 100644
index 0000000..db87afc
--- /dev/null
+++ b/doc/python10/builder.eps
@@ -0,0 +1,325 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: build/doc/python10/builder.fig
+%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d
+%%CreationDate: Sun Jan 2 01:21:05 2005
+%%For: knight@casablanca.home.baldmt.com (Steven Knight)
+%%BoundingBox: 0 0 668 290
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 290 moveto 0 0 lineto 668 0 lineto 668 290 lineto closepath clip newpath
+-53.3 342.7 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/reencdict 12 dict def /ReEncode { reencdict begin
+/newcodesandnames exch def /newfontname exch def /basefontname exch def
+/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def
+basefontdict { exch dup /FID ne { dup /Encoding eq
+{ exch dup length array copy newfont 3 1 roll put }
+{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall
+newfont /FontName newfontname put newcodesandnames aload pop
+128 1 255 { newfont /Encoding get exch /.notdef put } for
+newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat
+newfontname newfont definefont pop end } def
+/isovec [
+8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde
+8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis
+8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron
+8#220 /dotlessi 8#230 /oe 8#231 /OE
+8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling
+8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis
+8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot
+8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus
+8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph
+8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine
+8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf
+8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute
+8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring
+8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute
+8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute
+8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve
+8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply
+8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex
+8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave
+8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring
+8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute
+8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute
+8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve
+8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide
+8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex
+8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def
+/Times-Roman /Times-Roman-iso isovec ReEncode
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%
+% Fig objects follow
+%
+% Polyline
+7.500 slw
+n 2700 1200 m 4500 1200 l 4500 1800 l 2700 1800 l
+ cp gs col0 s gr
+/Times-Roman-iso ff 240.00 scf sf
+2925 1575 m
+gs 1 -1 sc (Environment) col0 sh gr
+% Polyline
+n 2700 2400 m 4500 2400 l 4500 3000 l 2700 3000 l
+ cp gs col0 s gr
+/Times-Roman-iso ff 240.00 scf sf
+3600 2775 m
+gs 1 -1 sc (BuilderWrapper) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 2700 3600 m 4500 3600 l 4500 4200 l 2700 4200 l
+ cp gs col0 s gr
+/Times-Roman-iso ff 240.00 scf sf
+3600 3975 m
+gs 1 -1 sc (BuilderBase) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 8400 3600 m 9900 3600 l 9900 4200 l 8400 4200 l
+ cp gs col0 s gr
+/Times-Roman-iso ff 240.00 scf sf
+9150 3975 m
+gs 1 -1 sc (ActionBase) dup sw pop 2 div neg 0 rm col0 sh gr
+/Times-Roman-iso ff 240.00 scf sf
+4650 5175 m
+gs 1 -1 sc (MultiStep-) dup sw pop 2 div neg 0 rm col0 sh gr
+/Times-Roman-iso ff 240.00 scf sf
+4650 5460 m
+gs 1 -1 sc (Builder) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 3900 4800 m 5400 4800 l 5400 5700 l 3900 5700 l
+ cp gs col0 s gr
+/Times-Roman-iso ff 240.00 scf sf
+2550 5175 m
+gs 1 -1 sc (Composite-) dup sw pop 2 div neg 0 rm col0 sh gr
+/Times-Roman-iso ff 240.00 scf sf
+2550 5460 m
+gs 1 -1 sc (Builder) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 1800 4800 m 3300 4800 l 3300 5700 l 1800 5700 l
+ cp gs col0 s gr
+/Times-Roman-iso ff 240.00 scf sf
+7050 5175 m
+gs 1 -1 sc (Command) dup sw pop 2 div neg 0 rm col0 sh gr
+/Times-Roman-iso ff 240.00 scf sf
+7050 5460 m
+gs 1 -1 sc (Action) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 6300 4800 m 7800 4800 l 7800 5700 l 6300 5700 l
+ cp gs col0 s gr
+/Times-Roman-iso ff 240.00 scf sf
+9150 5460 m
+gs 1 -1 sc (Action) dup sw pop 2 div neg 0 rm col0 sh gr
+/Times-Roman-iso ff 240.00 scf sf
+9150 5175 m
+gs 1 -1 sc (Function) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 8400 4800 m 9900 4800 l 9900 5700 l 8400 5700 l
+ cp gs col0 s gr
+/Times-Roman-iso ff 240.00 scf sf
+11250 5175 m
+gs 1 -1 sc (List) dup sw pop 2 div neg 0 rm col0 sh gr
+/Times-Roman-iso ff 240.00 scf sf
+11250 5460 m
+gs 1 -1 sc (Action) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 10500 4800 m 12000 4800 l 12000 5700 l 10500 5700 l
+ cp gs col0 s gr
+% Polyline
+n 900 2400 m 2100 2400 l 2100 3000 l 900 3000 l
+ cp gs col0 s gr
+/Times-Roman-iso ff 240.00 scf sf
+1500 2775 m
+gs 1 -1 sc (Node) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 3600 4200 m 3525 4350 l 3675 4350 l
+ cp gs col0 s gr
+% Polyline
+n 3150 4800 m 3150 4500 l 4050 4500 l
+ 4050 4800 l gs col0 s gr
+% Polyline
+n 3600 4350 m
+ 3600 4500 l gs col0 s gr
+% Polyline
+n 9150 4200 m 9075 4350 l 9225 4350 l
+ cp gs col0 s gr
+% Polyline
+n 7050 4800 m 7050 4500 l 10950 4500 l
+ 10950 4800 l gs col0 s gr
+% Polyline
+n 9150 4350 m
+ 9150 4800 l gs col0 s gr
+% Polyline
+gs clippath
+9885 3870 m 9885 3930 l 10036 3930 l 9916 3900 l 10036 3870 l cp
+eoclip
+n 11550 4650 m 11550 3900 l
+ 9900 3900 l gs col0 s gr gr
+
+% arrowhead
+n 10036 3870 m 9916 3900 l 10036 3930 l 10036 3870 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+8415 3930 m 8415 3870 l 8264 3870 l 8384 3900 l 8264 3930 l cp
+eoclip
+n 4650 3900 m
+ 8400 3900 l gs col0 s gr gr
+
+% arrowhead
+n 8264 3930 m 8384 3900 l 8264 3870 l 8264 3930 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+3930 1785 m 3870 1785 l 3870 1936 l 3900 1816 l 3930 1936 l cp
+eoclip
+n 3900 2250 m
+ 3900 1800 l gs col0 s gr gr
+
+% arrowhead
+n 3930 1936 m 3900 1816 l 3870 1936 l 3930 1936 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+3270 2415 m 3330 2415 l 3330 2264 l 3300 2384 l 3270 2264 l cp
+eoclip
+n 3300 1950 m
+ 3300 2400 l gs col0 s gr gr
+
+% arrowhead
+n 3270 2264 m 3300 2384 l 3330 2264 l 3270 2264 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+3570 3615 m 3630 3615 l 3630 3464 l 3600 3584 l 3570 3464 l cp
+eoclip
+n 3600 3150 m
+ 3600 3600 l gs col0 s gr gr
+
+% arrowhead
+n 3570 3464 m 3600 3584 l 3630 3464 l 3570 3464 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+4380 4185 m 4320 4185 l 4320 4336 l 4350 4216 l 4380 4336 l cp
+eoclip
+n 4350 4650 m
+ 4350 4200 l gs col0 s gr gr
+
+% arrowhead
+n 4380 4336 m 4350 4216 l 4320 4336 l 4380 4336 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+2880 4185 m 2820 4185 l 2820 4336 l 2850 4216 l 2880 4336 l cp
+eoclip
+n 2850 4650 m
+ 2850 4200 l gs col0 s gr gr
+
+% arrowhead
+n 2880 4336 m 2850 4216 l 2820 4336 l 2880 4336 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+2715 3930 m 2715 3870 l 2564 3870 l 2684 3900 l 2564 3930 l cp
+eoclip
+n 1500 3150 m 1500 3900 l
+ 2700 3900 l gs col0 s gr gr
+
+% arrowhead
+n 2564 3930 m 2684 3900 l 2564 3870 l 2564 3930 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+n 4650 3900 m 4575 3860 l 4500 3900 l 4575 3940 l
+ cp gs col0 s gr
+% Polyline
+n 1500 3000 m 1460 3075 l 1500 3150 l 1540 3075 l
+ cp gs col0 s gr
+% Polyline
+n 3600 3000 m 3560 3075 l 3600 3150 l 3640 3075 l
+ cp gs col0 s gr
+% Polyline
+n 3300 1800 m 3260 1875 l 3300 1950 l 3340 1875 l
+ cp gs col0 s gr
+% Polyline
+n 3900 2250 m 3860 2325 l 3900 2400 l 3940 2325 l
+ cp gs col0 s gr
+% Polyline
+n 4350 4650 m 4310 4725 l 4350 4800 l 4390 4725 l
+ cp gs col0 s gr
+% Polyline
+n 2850 4650 m 2810 4725 l 2850 4800 l 2890 4725 l
+ cp gs col0 s gr
+% Polyline
+n 11550 4650 m 11510 4725 l 11550 4800 l 11590 4725 l
+ cp gs col0 s gr
+% Polyline
+ [60] 0 sd
+n 3600 1200 m
+ 3600 900 l gs col0 s gr [] 0 sd
+$F2psEnd
+rs
diff --git a/doc/python10/builder.fig b/doc/python10/builder.fig
new file mode 100644
index 0000000..75e5ec0
--- /dev/null
+++ b/doc/python10/builder.fig
@@ -0,0 +1,128 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 2700 1200 4500 1800
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2700 1200 4500 1200 4500 1800 2700 1800 2700 1200
+4 0 0 50 0 0 16 0.0000 4 165 1290 2925 1575 Environment\001
+-6
+6 2700 2400 4500 3000
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2700 2400 4500 2400 4500 3000 2700 3000 2700 2400
+4 1 0 50 0 0 16 0.0000 4 225 1620 3600 2775 BuilderWrapper\001
+-6
+6 2700 3600 4500 4200
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2700 3600 4500 3600 4500 4200 2700 4200 2700 3600
+4 1 0 50 0 0 16 0.0000 4 165 1215 3600 3975 BuilderBase\001
+-6
+6 8400 3600 9900 4200
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 8400 3600 9900 3600 9900 4200 8400 4200 8400 3600
+4 1 0 50 0 0 16 0.0000 4 165 1140 9150 3975 ActionBase\001
+-6
+6 3900 4800 5400 5700
+6 4050 4950 5250 5475
+4 1 0 50 0 0 16 0.0000 4 225 1140 4650 5175 MultiStep-\001
+4 1 0 50 0 0 16 0.0000 4 165 750 4650 5460 Builder\001
+-6
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3900 4800 5400 4800 5400 5700 3900 5700 3900 4800
+-6
+6 1800 4800 3300 5700
+6 1950 4950 3150 5475
+4 1 0 50 0 0 16 0.0000 4 225 1200 2550 5175 Composite-\001
+4 1 0 50 0 0 16 0.0000 4 165 750 2550 5460 Builder\001
+-6
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 1800 4800 3300 4800 3300 5700 1800 5700 1800 4800
+-6
+6 6300 4800 7800 5700
+6 6525 4950 7575 5475
+4 1 0 50 0 0 16 0.0000 4 165 1020 7050 5175 Command\001
+4 1 0 50 0 0 16 0.0000 4 165 675 7050 5460 Action\001
+-6
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 6300 4800 7800 4800 7800 5700 6300 5700 6300 4800
+-6
+6 8400 4800 9900 5700
+6 8700 4950 9600 5475
+4 1 0 50 0 0 16 0.0000 4 165 675 9150 5460 Action\001
+4 1 0 50 0 0 16 0.0000 4 165 870 9150 5175 Function\001
+-6
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 8400 4800 9900 4800 9900 5700 8400 5700 8400 4800
+-6
+6 10500 4800 12000 5700
+6 10875 4950 11625 5475
+4 1 0 50 0 0 16 0.0000 4 165 390 11250 5175 List\001
+4 1 0 50 0 0 16 0.0000 4 165 675 11250 5460 Action\001
+-6
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 10500 4800 12000 4800 12000 5700 10500 5700 10500 4800
+-6
+6 900 2400 2100 3000
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 900 2400 2100 2400 2100 3000 900 3000 900 2400
+4 1 0 50 0 0 16 0.0000 4 165 525 1500 2775 Node\001
+-6
+2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 3600 4200 3525 4350 3675 4350 3600 4200
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 3150 4800 3150 4500 4050 4500 4050 4800
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
+ 3600 4350 3600 4500
+2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 9150 4200 9075 4350 9225 4350 9150 4200
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 7050 4800 7050 4500 10950 4500 10950 4800
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
+ 9150 4350 9150 4800
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3
+ 1 1 1.00 60.00 120.00
+ 11550 4650 11550 3900 9900 3900
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 4650 3900 8400 3900
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 3900 2250 3900 1800
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 3300 1950 3300 2400
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 3600 3150 3600 3600
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 4350 4650 4350 4200
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 2850 4650 2850 4200
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3
+ 1 1 1.00 60.00 120.00
+ 1500 3150 1500 3900 2700 3900
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 4650 3900 4575 3860 4500 3900 4575 3940 4650 3900
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 1500 3000 1460 3075 1500 3150 1540 3075 1500 3000
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 3600 3000 3560 3075 3600 3150 3640 3075 3600 3000
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 3300 1800 3260 1875 3300 1950 3340 1875 3300 1800
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 3900 2250 3860 2325 3900 2400 3940 2325 3900 2250
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 4350 4650 4310 4725 4350 4800 4390 4725 4350 4650
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 2850 4650 2810 4725 2850 4800 2890 4725 2850 4650
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 11550 4650 11510 4725 11550 4800 11590 4725 11550 4650
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 3600 1200 3600 900
diff --git a/doc/python10/builder.jpg b/doc/python10/builder.jpg
new file mode 100644
index 0000000..e9085e8
--- /dev/null
+++ b/doc/python10/builder.jpg
Binary files differ
diff --git a/doc/python10/copyright.xml b/doc/python10/copyright.xml
new file mode 100644
index 0000000..d141fc6
--- /dev/null
+++ b/doc/python10/copyright.xml
@@ -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>
+
+ Copyright (c) 2001, 2002 Steven Knight
+
+ </para>
+</blockquote>
diff --git a/doc/python10/design.xml b/doc/python10/design.xml
new file mode 100644
index 0000000..cb58af9
--- /dev/null
+++ b/doc/python10/design.xml
@@ -0,0 +1,898 @@
+<para>
+
+ The &SCons; architecture consists of three layers:
+
+</para>
+
+<mediaobject>
+ <imageobject>
+ <imagedata fileref="arch" format="eps" align="center">
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="arch.jpg" format="jpg" align="center">
+ </imageobject>
+ <!-- PDF files?
+ <imageobject>
+ <imagedata fileref="arch.pdf" align="center">
+ </imageobject>
+ -->
+</mediaobject>
+
+<itemizedlist>
+
+ <listitem>
+ <para>
+
+ The &SCons; <emphasis>Build Engine</emphasis>, a package of Python
+ modules that handle dependency management and updating out-of-date
+ objects.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ The &SCons; <emphasis>API</emphasis> (applications programming
+ interface) between the Build Engine
+ and the user interface.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ The &scons; <emphasis>script</emphasis> itself (note lower case
+ <emphasis>sc</emphasis>), which is the pre-provided interface to
+ the Build Engine.
+
+ </para>
+ </listitem>
+
+</itemizedlist>
+
+<para>
+
+ Notice that this architecture separates the internal workings of
+ &SCons; (the Build Engine) from the
+ external user interface. The benefit is that the &SCons; Build Engine
+ can be imported into any other software package written in Python
+ to support a variety of user interfaces&mdash;or, to look at it
+ in reverse, other software interfaces can use the &SCons; Build
+ Engine to manage dependencies between their objects.
+
+</para>
+
+<para>
+
+ Because the
+ &SCons; package itself is modular, only those parts of the package
+ relevant to the embedding interface need be imported; for example,
+ a utility that wants to use only file timestamps for checking
+ whether a file is up-to-date
+ need not import the MD5 signature module.
+
+</para>
+
+<section>
+ <title>The &SCons; Build Engine</title>
+
+ <para>
+
+ The Build Engine is a package of Python modules that
+ form the heart of &SCons;.
+
+ The Build Engine can be broadly divided into five
+ architectural subsystems, each responsible
+ for a crucial part of &SCons; functionality:
+
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <para>
+
+ A <emphasis>node</emphasis> subsystem, responsible for managing
+ the files (or other objects) to be built, and the dependency
+ relationships between them.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ A <emphasis>scanner</emphasis> subsystem, responsible for
+ scanning various file types for implicit dependencies.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ A <emphasis>signature</emphasis> subsystem, responsible for
+ deciding whether a given file (or other object) requires
+ rebuilding.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ A <emphasis>builder</emphasis> subsystem, responsible for
+ actually executing the necessary command or function to
+ build a file (or other object).
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ A <emphasis>job/task</emphasis> subsystem, responsible for
+ handling parallelization of builds.
+
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+
+ The rest of this section will provide a high-level overview of the
+ class structure of each of these Build Engine subsystems.
+
+ </para>
+
+ <section>
+ <title>Node Subsystem</title>
+
+ <para>
+
+ The node subsystem of the Build Engine is
+ responsible for managing the knowledge in &SCons; of
+ the relationships among the external objects
+ (files) it is responsible for updating.
+ The most important of these relationships is
+ the dependency relationship between various &Node; objects,
+ which &SCons; uses to determine the order
+ in which builds should be performed.
+
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="node" format="eps" align="center">
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="node.jpg" format="jpg" align="center">
+ </imageobject>
+ <!-- PDF files?
+ <imageobject>
+ <imagedata fileref="node.pdf" align="center">
+ </imageobject>
+ -->
+ </mediaobject>
+
+ <para>
+
+ The &scons; script (or other
+ user interface)
+ tells the Build Engine
+ about dependencies
+ through its &consenv; API.
+ The Build Engine also discovers
+ dependencies automatically through the use of &Scanner; objects.
+
+ </para>
+
+ <para>
+
+ Subclasses of the &Node; class maintain additional
+ relationships that reflect the real-world
+ existence of these objects.
+ For example, the &Node_FS; subclass
+ is responsible for managing a
+ representation of the directory hierarchy
+ of a file system.
+
+ </para>
+
+ <para>
+
+ A &Walker; class is used by other subsystems
+ to walk the dependency tree maintained by the &Node; class.
+ The &Walker; class maintains a stack of &Node; objects
+ visited during its depth-first traversal of the
+ dependency tree,
+ and uses an intermediate node &Wrapper; class
+ to maintain state information about a
+ &Node; object's dependencies.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Scanner Subsystem</title>
+
+ <para>
+
+ The scanner subsystem is responsible for maintaining
+ objects that can scan the contents of a &Node;'s
+ for implicit dependencies.
+
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="scanner" format="eps" align="center">
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="scanner.jpg" format="jpg" align="center">
+ </imageobject>
+ <!-- PDF files?
+ <imageobject>
+ <imagedata fileref="scanner.pdf" align="center">
+ </imageobject>
+ -->
+ </mediaobject>
+
+ <para>
+
+ In practice, a given &Scanner; subclass object
+ functions as a prototype,
+ returning clones of itself
+ depending on the &consenv;
+ values governing how the &Node;
+ should be scanned.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Signature Subsystem</title>
+
+ <para>
+
+ The signature subsystem is responsible for computing
+ signature information for &Node; objects.
+ The signature subsystem in &SCons;
+ supports multiple ways to
+ determine whether a &Node is up-to-date
+ by using an abstract &Sig; class
+ as a strategy wrapper:
+
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="sig" format="eps" align="center">
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="sig.jpg" format="jpg" align="center">
+ </imageobject>
+ <!-- PDF files?
+ <imageobject>
+ <imagedata fileref="sig.pdf" align="center">
+ </imageobject>
+ -->
+ </mediaobject>
+
+ <para>
+
+ By default, &SCons; tracks dependencies by computing and
+ maintaining MD5 signatures for the contents of each source file
+ (or other object). The signature of a <emphasis>derived</emphasis>
+ file consists of the aggregate of the signatures of all the source
+ files <emphasis>plus</emphasis> the command-line string used to
+ build the file. These signatures are stored in a &sconsign; file
+ in each directory.
+
+ </para>
+
+ <para>
+
+ If the contents of any of the source files changes, the change to its
+ MD5 signature is propogated to the signature of the derived file(s). The
+ simple fact that the new signature does not match the stored signature
+ indicates that the derived file is not up to date and must be rebuilt.
+
+ </para>
+
+ <para>
+
+ A separate &TimeStamp; subclass of the &Sig; class supports
+ the use of traditional file timestamps for
+ deciding whether files are up-to-date.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Builder Subsystem</title>
+
+ <para>
+
+ The &SCons; Build Engine records how out-of-date files
+ (or other objects) should be rebuilt in &Builder; objects,
+ maintained by the builder subsystem:
+
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="builder" format="eps" align="center">
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="builder.jpg" format="jpg" align="center">
+ </imageobject>
+ <!-- PDF files?
+ <imageobject>
+ <imagedata fileref="builder.pdf" align="center">
+ </imageobject>
+ -->
+ </mediaobject>
+
+ <para>
+
+ The actual underlying class name is &BuilderBase;,
+ and there are subclasses that can encapsulate
+ multiple &Builder; objects for special purposes.
+ One subclass
+ (&CompositeBuilder;)
+ selects an appropriate encapsulated &Builder;
+ based on the file suffix of the target object.
+ The other
+ (&MultiStepBuilder;).
+ can chain together multiple
+ &Builder; objects,
+ for example,
+ to build an executable program from a source file
+ through an implicit intermediate object file.
+
+ </para>
+
+ <para>
+
+ A &BuilderBase; object has an associated
+ &ActionBase; object
+ responsible for actually executing
+ the appropriate steps
+ to update the target file.
+ There are three subclasses,
+ one for externally executable commands
+ (&CommandAction;),
+ one for Python functions
+ (&FunctionAction;),
+ and one for lists of
+ multiple &Action; objects
+ (&ListAction;).
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Job/Task Subsystem</title>
+
+ <para>
+
+ &SCons; supports parallel builds with a thread-based tasking
+ model, managed by the job/task subsystem.
+
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="job-task" format="eps" align="center">
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="job-task.jpg" format="jpg" align="center">
+ </imageobject>
+ <!-- PDF files?
+ <imageobject>
+ <imagedata fileref="job-task.pdf" align="center">
+ </imageobject>
+ -->
+ </mediaobject>
+
+ <para>
+
+ Instead of performing an outer-loop recursive descent
+ of the dependency tree and then forking a task when it finds a
+ file that needs updating, &SCons; starts as many threads as are
+ requested, each thread managed by the &Jobs; class.
+ As a performance optimization,
+ the &Jobs; class maintains an internal
+ distinction between
+ &Serial; and &Parallel;
+ build jobs,
+ so that serial builds
+ don't pay any performance penalty
+ by using a multi-threaded implementation
+ written for &Parallel; builds.
+
+ </para>
+
+ <para>
+
+ Each &Jobs; object, running in its own thread,
+ then requests a &Task; from a central &Taskmaster;,
+ which is responsible
+ for handing out available &Task; objects for (re-)building
+ out-of-date nodes. A condition variable
+ makes sure that the &Jobs; objects
+ query the &Taskmaster; one at a time.
+
+ </para>
+
+ <para>
+
+ The &Taskmaster uses the node subsystem's
+ &Walker; class to walk the dependency tree,
+ and the &Sig; class to use the
+ appropriate method
+ of deciding if a &Node; is up-to-date.
+
+ </para>
+
+ <para>
+
+ This scheme has many advantages over the standard &Make;
+ implementation of <option>-j</option>.
+ Effective use of <option>-j</option> is difficult
+ with the usual recursive use of Make,
+ because the number of jobs started by <option>-j</option> multiply
+ at each level of the source tree.
+ This makes the actual number of jobs
+ executed at any moment very dependent on the size and layout of
+ the tree. &SCons;, in contrast, starts only as many jobs as are
+ requested, and keeps them constantly busy (excepting jobs that
+ block waiting for their dependency files to finish building).
+
+ </para>
+
+ </section>
+
+</section>
+
+<section>
+ <title>The &SCons; API</title>
+
+ <para>
+
+ This section provides an overview of the &SCons; interface. The
+ complete interface specification is both more detailed and flexible
+ than this overview.
+
+ </para>
+
+ <section>
+ <title>&ConsVars;</title>
+
+ <para>
+
+ In &SCons;, a &consenv; is an object through which an external
+ interface (such as the &scons; script) communicates dependency
+ information to the &SCons; Build Engine.
+
+ </para>
+
+ <para>
+
+ A construction environment is implemented as a dictionary
+ containing:
+
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <para>
+
+ construction variables, string values that are substituted
+ into command lines or used by builder functions;
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ one or more &Builder; objects that can be invoked to update a
+ file or other object;
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ one or more &Scanner; objects that can be used to
+ scan a file automatically for dependencies (such as
+ files specified on <literal>#include</literal> lines).
+
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+
+ &Consenvs; are instantiated as follows:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env_debug = Environment(CCFLAGS = '-g')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>&Builder; Objects</title>
+
+ <para>
+
+ An &SCons; &Builder; object encapsulates information about how to
+ build a specific type of file: an executable program, an object
+ file, a library, etc. A &Builder; object is associated with a
+ file through an associated &consenv; method and later invoked to
+ actually build the file. The &Builder; object will typically use
+ construction variables (such as &CCFLAGS;, &LIBPATH;) to influence
+ the specific build execution.
+
+ </para>
+
+ <para>
+
+ &Builder; objects are instantiated as follows:
+
+ </para>
+
+ <programlisting>
+ bld = Builder(name = 'Program', action = "$CC -o $TARGET $SOURCES")
+ </programlisting>
+
+ <para>
+
+ In the above example, the <literal>action</literal> is a
+ command-line string in which the Build Engine will
+ interpolate the values of construction
+ variables before execution. The actual
+ <literal>action</literal> specified, though,
+ may be a function:
+
+ </para>
+
+ <programlisting>
+ def update(dest):
+ # [code to update the object]
+ return 0
+
+ bld = Builder(name = 'Program', function = update)
+ </programlisting>
+
+ <para>
+
+ Or a callable Python object (or class):
+
+ </para>
+
+ <programlisting>
+ class class_a:
+ def __call__(self, kw):
+ # build the desired object
+ return 0
+
+ builder = SCons.Builder.Builder(action = class_a())
+ </programlisting>
+
+ <para>
+
+ A &Builder; object may have the <literal>prefix</literal> and
+ <literal>suffix</literal> of its target file type specified
+ as keyword arguments at instantiation. Additionally, the
+ suffix of the <emphasis>source files</emphasis> used by this
+ &Builder; to build its target files may be specified using the
+ <literal>src_suffix</literal> keyword argument:
+
+ </para>
+
+ <programlisting>
+ bld_lib = Builder(name = 'Library', action = "$AR r $TARGET $SOURCES",
+ prefix = 'lib', suffix = '.a', src_suffix = '.o')
+ </programlisting>
+
+ <para>
+
+ The specified <literal>prefix</literal> and
+ <literal>suffix</literal> will be appended to the name of any
+ target file built by this &Builder; object, if they are not
+ already part of the file name. The <literal>src_suffix</literal>
+ is used by the &SCons; Build Engine to chain together
+ multiple &Builder; objects to create,
+ for example, a library from the original source
+ files without having to specify the
+ intermediate <literal>.o</literal> files.
+
+ </para>
+
+ <para>
+
+ &Builder; objects are associated with a &consenv; through a
+ &consvar; named &BUILDERS;, a list of the &Builder objects that
+ will be available for execution through the &consenv:
+
+ </para>
+
+ <programlisting>
+ env = Environment(BUILDERS = [ Object, Library, WebPage, Program ])
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>&Scanner; Objects</title>
+
+ <para>
+
+ &Scanner; objects perform automatic checking for dependencies
+ by scanning the contents of files. The canonical
+ example is scanning a C source file or header file for
+ files specified on <literal>#include</literal> lines.
+
+ </para>
+
+ <para>
+
+ A &Scanner; object is instantiated as follows:
+
+ </para>
+
+ <programlisting>
+ def c_scan(contents):
+ # scan contents of file
+ return # list of files found
+
+ c_scanner = Scanner(name = 'CScan', function = c_scan,
+ argument = None,
+ skeys = ['.c', '.C', '.h', '.H')
+ </programlisting>
+
+ <para>
+
+ The <literal>skeys</literal> argument specifies a list of file
+ suffixes for file types that this &Scanner; knows how to scan.
+
+ </para>
+
+ <para>
+
+ &Scanner; objects are associated with a &consenv; through a
+ &consvar; named &SCANNERS;, a list of the &Scanner; objects that
+ will be available through the &consenv:
+
+ </para>
+
+ <programlisting>
+ env = Environment(SCANNERS = [ CScan, M4Scan ])
+ </programlisting>
+
+ <para>
+
+ For utilities that will build files with a variety of file
+ suffixes, or which require unusual scanning rules, a &Scanner;
+ object may be associated explicitly with a &Builder; object as
+ follows:
+
+ </para>
+
+ <programlisting>
+ def tool_scan(contents):
+ # scan contents of file
+ return # list of files found
+
+ tool_scanner = Scanner(name = 'TScan', function = tool_scan)
+
+ bld = Builder(name = 'Tool', scanner = tool_scanner)
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>&BuildDir;</title>
+
+ <para>
+
+ &SCons; supports a flexible mechanism for building target
+ files in a separate build directory from the source files.
+ The &BuildDir; syntax is straightforward:
+
+ </para>
+
+ <programlisting>
+ BuildDir(source = 'src', build = 'bld')
+ </programlisting>
+
+ <para>
+
+ By
+ default, source files are linked or copied into the build
+ directory, because exactly replicating the source directory
+ is sometimes necessary for certain combinations of use of
+ <literal>#include "..."</literal> and <option>-I</option> search
+ paths.
+
+ An option exists to specify that only output files should be placed in
+ the build directory:
+
+ </para>
+
+ <programlisting>
+ BuildDir(source = 'src', build = 'bld', no_sources = 1)
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>&Repository;</title>
+
+ <para>
+
+ &SCons; supports the ability to search a list of code repositories
+ for source files and derived files. This works much like
+ &Make;'s <varname>VPATH</varname> feature, as implemented in
+ recent versions of GNU &Make;.
+ (The POSIX standard for &Make; specifies slightly
+ different behavior for <varname>VPATH</varname>.)
+ The syntax is:
+
+ </para>
+
+ <programlisting>
+ Repository('/home/source/1.1', '/home/source/1.0')
+ </programlisting>
+
+ <para>
+
+ A command-line <option>-Y</option> option exists to allow
+ repositories to be specified on the command line, or in the
+ &SCONSFLAGS; environment variable (not construction variable!).
+ This avoids a chicken-and-egg situation and allows the top-level
+ &SConstruct; file to be found in a repository as well.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>&Cache;</title>
+
+ <para>
+
+ &SCons; supports a way for developers to share derived files. Again, the
+ syntax is straightforward:
+
+ </para>
+
+ <programlisting>
+ Cache('/var/build.cache/i386')
+ </programlisting>
+
+ <para>
+
+ Copies of any derived files built will be placed in the specified
+ directory with their MD5 signature. If another build results in an
+ out-of-date derived file with the same signature, the derived file
+ will be copied from the cache instead of being rebuilt.
+
+ </para>
+
+ </section>
+
+</section>
+
+<section>
+ <title>The &scons; Script</title>
+
+ <para>
+
+ The &scons; script provides an interface
+ that looks roughly equivalent to the
+ classic &Make; utility&mdash;that is, execution from the command
+ line, and dependency information read from configuration files.
+
+ </para>
+
+ <para>
+
+ The most noticeable difference between &scons; and &Make;, or most
+ other build tools, is that the configuration files are actually
+ Python scripts, generically called "SConscripts" (although the
+ top-level "Makefile" is named &SConstruct). Users do not have to
+ learn a new language syntax, but instead configure dependency
+ information by making direct calls to the Python API of the
+ &SCons; Build Engine. Here is an example &SConstruct file which
+ builds a program in side-by-side normal and debug versions:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ debug = env.Copy(CCFLAGS = '-g')
+
+ source_files = ['f1.c', 'f2.c', 'f3.c']
+
+ env.Program(target = 'foo', sources = source_files)
+ debug.Program(target = 'foo-debug', sources = source_files)
+ </programlisting>
+
+ <para>
+
+ Notice the fact that this file is a Python script, which allows us
+ to define and re-use an array that lists the source files.
+
+ </para>
+
+ <para>
+
+ Because quoting individul strings in long
+ lists of files can get tedious and error-prone, the &SCons;
+ methods support a short-cut of listing multiple files in a single
+ string, separated by white space.
+ This would change
+ the assignment in the above example to a more easily-readable:
+
+ </para>
+
+ <programlisting>
+ source_files = 'f1.c f2.c f3.c'
+ </programlisting>
+
+ <para>
+
+ The mechanism to establish hierarchical builds is to "include" any
+ subsidiary configuration files in the build by listing them explicitly
+ in a call to the &SConscript; function:
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript', 'lib/SConscript')
+ </programlisting>
+
+ <para>
+
+ By convention, configuration files in subdirectories are named
+ &SConscript;.
+
+ </para>
+
+ <para>
+
+ The &scons; script has intentionally been made to look, from
+ the outside, as much like &Make; as is practical. To this
+ end, the &scons; script supports all of the same command-line
+ options supported by GNU &Make;: <option>-f</option> FILE,
+ <option>-j</option>, <option>-k</option>, <option>-s</option>,
+ etc. For compatibility, &scons; ignores those GNU &Make; options
+ that don't make sense for the &SCons; architecture, such as
+ <option>-b</option>, <option>-m</option>, <option>-S</option>,
+ and <option>-t</option>. The
+ intention is that, given an equivalent &SConstruct; file for a
+ &Makefile;, a user could use &SCons; as a drop-in replacement for
+ &Make;. Additional command-line options are, where possible, taken
+ from the Perl &Cons; utility on which the &SCons; design is based.
+
+ </para>
+
+</section>
diff --git a/doc/python10/future.xml b/doc/python10/future.xml
new file mode 100644
index 0000000..272d508
--- /dev/null
+++ b/doc/python10/future.xml
@@ -0,0 +1,170 @@
+<para>
+
+ There are a number of things we would like to do to continue to
+ improve &SCons; in the future.
+
+</para>
+
+<section>
+ <title>Distutils Cooperation</title>
+
+ <para>
+
+ There is a certain amount of overlap between what &SCons; does
+ to search out and make use of various compilers on a system, and
+ the impressively complete job that the Distutils do of describing
+ much the same thing. Collaborating to provide some sort of common
+ interface between the two tools would benefit both tools.
+
+ </para>
+
+</section>
+
+<section>
+ <title>Additional Builder Support</title>
+
+ <para>
+
+ Adding additional builders would broaden the
+ potential user base. In rough order of importance:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>Java</term>
+ <listitem>
+ <para>
+
+ Given the popularity of Java, support for it would greatly
+ increase the appeal of &SCons; in the large community of Java
+ users.
+
+ </para>
+
+ <para>
+
+ Good support for Java is, however, a tricky
+ proposition. Because the Java compiler can make decisions
+ about compiling other files based on what classes it finds
+ in a file, it behaves "unpredictably" from the point of
+ view of an outside build tool like &SCons; or &Make;. Some
+ sort of sophisticated scanning of Java source code to
+ identify what other classes are likely to be compiled
+ would be an obvious first step, but notice that here
+ &SCons; would be scanning the file to find additional
+ targets to be built. This is the inverse of the sort of
+ <literal>#include</literal> scanning performed
+ for C files, in which &SCons; is looking for additional
+ <emphasis>dependencies</emphasis>.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Documentation toolchains</term>
+ <listitem>
+ <para>
+
+ A number of early adopters
+ are using &SCons; to
+ build documents
+ from TeX or DocBook source files.
+ Built-in support for
+ various documentation toolchains
+ would be an obvious boon
+ for many people.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>C#</term>
+ <listitem>
+ <para>
+
+ The reality is that anything that Microsoft does will doubtless
+ have a wide audience. Turning &SCons;' back on that would be
+ cutting off its nose to spite its face.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Fortran</term>
+ <listitem>
+ <para>
+
+ Despite the fact that &SCons; is no longer directly
+ associated with Software Carpentry, it still shares the
+ same goal: to make programming easier for more than just
+ programmers. To that end, good Fortran support would
+ help a great many physical scientists and other computer
+ <emphasis>users</emphasis> out there who still rely on Fortran
+ for a great deal of their work.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+</section>
+
+<section>
+ <title>Database Interface</title>
+
+ <para>
+
+ The Nodes in an &SCons; dependency graph aren't only restricted to
+ files. Creating an interface to mSQL or MySQL databases would allow
+ the possibility of updating external files in response to changes in
+ database fields, or vice versa. This could be handy, for example,
+ for generating a cache of static web pages from a database that only
+ need re-generating when the appropriate database objects change.
+
+ </para>
+
+</section>
+
+<section>
+ <title>Tool Integration</title>
+
+ <para>
+
+ &SCons; should work well with as many popular Integrated Development
+ Environments (IDEs) and tool chains as possible: Komodo, Microsoft
+ Visual Studio, ClearCase, etc. Suggestions for additional tools are
+ welcome.
+
+ </para>
+
+</section>
+
+<section>
+ <title>Makefile Interface</title>
+
+ <para>
+
+ Because the &SCons; Build Engine can be embedded in any Python
+ interface, there isn't any technical reason why a &Makefile;
+ interpreter couldn't be written in Python and use the &SCons; Build
+ Engine for its dependency analysis.
+
+ </para>
+
+ <para>
+
+ Proof-of-concept for the idea already exists. Gary Holt's
+ <literal>make++</literal> (also known as <literal>makepp</literal>)
+ is a Perl implementation of just such a &Makefile; interpreter. It
+ could possible serve as a model for a Python version, in much the
+ same way the &Cons; design served as the prototype for &SCons;.
+
+ </para>
+
+</section>
diff --git a/doc/python10/install.xml b/doc/python10/install.xml
new file mode 100644
index 0000000..d150beb
--- /dev/null
+++ b/doc/python10/install.xml
@@ -0,0 +1,179 @@
+<para>
+
+ Initial installation of a new utility provides the first, lasting
+ impression of how well the software is likely to perform. From the
+ start, &SCons; has made clean installation a priority.
+
+</para>
+
+<section>
+ <title>Version Control</title>
+
+ <para>
+
+ Distributing an application like &SCons; that depends
+ on a package normally found in a library poses a
+ problem. If the &scons; script and the &SCons; Build Engine
+ are installed separately, it could be easy
+ to introduce a version mismatch between the Build Engine
+ installed in
+ <filename>/usr/lib/python*/site-packages</filename>
+ and the &scons; script installed in
+ <filename>/usr/bin</filename>.
+ Such a mismatch
+ could possible mean exceptions that prevent builds, or even worse,
+ silently unreliable builds.
+
+ </para>
+
+ <para>
+
+ To reduce the possibility of a version mismatch,
+ the &scons; script looks first for its
+ imported modules in <filename>/usr/lib/scons-{version}/</filename>,
+ then in <filename>/usr/lib/scons/</filename>,
+ and then in the normal &PYTHONPATH; locations,
+ including <filename>/usr/lib/python*/site-packages</filename>).
+ Searching in a version-specific library directory first
+ makes it convenient to install and use multiple
+ side-by-side versions of &SCons;,
+ which is sometimes important
+ when verifying that a new version does not introduce any
+ errors into the local build process.
+ Searching next in an &SCons;-specific library directory
+ makes it convenient for other software to find
+ the &SCons; Build Engine without having to worry about
+ installing separate copies for
+ multiple versions of Python.
+
+ </para>
+
+</section>
+
+<section>
+ <title>Packages</title>
+
+ <para>
+
+ &SCons; is currently distributed in the following packages:
+
+ </para>
+
+ <table>
+ <title></title>
+ <tgroup cols="2">
+ <tbody>
+
+ <row valign="top">
+ <entry>
+ <literal>scons-</literal><emphasis>version</emphasis><literal>.tar.gz</literal>
+ </entry>
+ <entry><para>
+
+ The traditional <literal>.tar.gz</literal> file,
+ installable by running <filename>setup.py</filename>.
+
+ </para></entry>
+ </row>
+
+ <row valign="top">
+ <entry>
+ <literal>scons-</literal><emphasis>version</emphasis><literal>.noarch.rpm</literal>
+ </entry>
+ <entry><para>
+
+ An RPM file for typical installation.
+
+ </para></entry>
+ </row>
+
+ <row valign="top">
+ <entry>
+ <literal>scons-</literal><emphasis>version</emphasis><literal>_all.deb</literal>
+ </entry>
+ <entry><para>
+
+ A Debian package.
+
+ </para></entry>
+ </row>
+
+ <row valign="top">
+ <entry>
+ <literal>scons-</literal><emphasis>version</emphasis><literal>.win32.exe</literal>
+ </entry>
+ <entry><para>
+
+ A Windows installer.
+
+ </para></entry>
+ </row>
+
+ <row valign="top">
+ <entry>
+ <literal>scons-</literal><emphasis>version</emphasis><literal>.src.rpm</literal>
+ </entry>
+ <entry><para>
+
+ A source RPM file.
+
+ </para></entry>
+ </row>
+
+ <row valign="top">
+ <entry>
+ <literal>scons-src-</literal><emphasis>version</emphasis><literal>.tar.gz</literal>
+ </entry>
+ <entry><para>
+
+ A tarball of the &SCons; source tree,
+ including the full set of regression tests.
+
+ </para></entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+
+ Like other software written in Python, &SCons; benefits greatly from
+ the tremendous effort put into the <literal>distutils</literal> by
+ Greg Ward and others. These take care of 90% of the work by making
+ it almost trivial to generate the appropriate RPM files, Debian
+ packages, and Windows installer.
+
+ </para>
+
+</section>
+
+<section>
+ <title>Default Builder Objects</title>
+
+ <para>
+
+ As part of the installation process, &SCons; runs a set of scripts
+ that look for popular compilers and other tools and set up
+ appropriate default &Builder; objects for the tools found. These
+ &Builder; objects are then used to initialize the default &consenv;
+ values.
+
+ </para>
+
+</section>
+
+<section>
+ <title>Default Scanner Objects</title>
+
+ <para>
+
+ Additionally, &SCons; comes with a stock set of &Scanner; objects
+ for the various file types that it supports out of the box. Any
+ unusal &Scanner; objects required for a specific tool will be
+ detected at installation time and associated with the appropriate
+ &Builder; object for the tool.
+
+ </para>
+
+</section>
diff --git a/doc/python10/intro.xml b/doc/python10/intro.xml
new file mode 100644
index 0000000..d3057be
--- /dev/null
+++ b/doc/python10/intro.xml
@@ -0,0 +1,212 @@
+<para>
+
+ More than twenty years after its creation, the classic UNIX &Make;
+ utility and its descendants are still the dominant way in which
+ software is built. &Make; has maintained this position despite the
+ fact that the intervening years have revealed many
+ shortcomings of the &Make; model for building software:
+
+</para>
+
+<itemizedlist>
+
+ <listitem>
+ <para>
+
+ The use of timestamps to decide when a file has been updated is
+ imprecise and prone to error, especially across distributed file
+ systems such as NFS.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ Builds of typical large software systems still take hours, if not
+ days, despite the tremendous advances in CPU and disk speeds over
+ recent years.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ &Make; maintains static definitions of dependencies in its
+ &Makefiles;. Much effort has been put into
+ utilities (<application>mkdepend</application>, <application>gcc
+ -M</application>) and schemes (<filename>Makefile.d</filename>
+ files) to try to keep &Makefile; dependencies up-to-date,
+ but these only confirm that &Make;'s static dependencies are
+ inherently fragile.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ The standard recursive use of &Make; for build hierarchies leads
+ to incomplete dependency graphs, which must be overcome by
+ manually changing the order in which directories are built, or
+ through the use of multiple build passes.
+
+ </para>
+ </listitem>
+
+</itemizedlist>
+
+<para>
+
+ One need only look at the plethora of helper and wrapper utilities
+ (automake, easymake, imake, jmake, makeLib, maketool, mkmed, shake,
+ SMake, TMAKE) and complete alternatives to &Make; (Ant, bake, bau,
+ bras, Cake, Cons, Cook, Jam, jmk, jus, makeme, mash, MK, nmake, Odin,
+ VMake) that have been created over the years to realize that vanilla
+ &Make; is not satisfying everyone's build requirements. So why Yet
+ Another build tool?
+
+</para>
+
+<section>
+ <title>Enter Software Carpentry</title>
+
+ <para>
+
+ Most of the build tools just mentioned
+ were written by programmers and for
+ programmers. The fact that most programmer-friendly
+ utilities do a poor job of fulfilling the needs
+ of non-programmers prompted Greg Wilson to
+ organize the Software Carpentry competition in January 2000.
+ Software Carpentry was an
+ open design contest with the express goal of producing a set of
+ next-generation utilities, including a build tool, that would be
+ accessible
+ not only to
+ programmers
+ but also to computer <emphasis>users</emphasis>
+ such as physical scientists.
+
+ </para>
+
+ <para>
+
+ The key to this usability would be that all of
+ these utilities, including the build tool, would be
+ written in Python.
+ This provided the catalyst for actually
+ pursuing an idea
+ that had been floating around one of the more
+ intriguing &Make; alternatives,
+ a Perl utility called &Cons;.
+ What if the friendlier syntax of Python
+ could be married to the
+ architectural advantages of &Cons;?
+
+ </para>
+
+ <para>
+
+ The resulting merged design, at that time named &ScCons;,
+ won the Software Carpentry build tool competition. CodeSourcery (by
+ then the administrators of the competition) ultimately decided not to
+ fund development of the build tool, but the seed had been planted and the
+ design had taken root.
+
+ </para>
+
+</section>
+
+<section>
+ <title>Cons</title>
+
+ <para>
+
+ It helps to know something about &Cons;.
+ &Cons; was first released in 1996 by Bob Sidebotham,
+ then an employee of Fore Systems,
+ and it has a number of
+ distinctive features that set it apart from most &Make;-alikes:
+
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <para>
+
+ &Cons; "configuration files" are not Yet Another
+ invented mini-language, but are actually <emphasis>Perl
+ scripts</emphasis>, which means the full power and flexibility of
+ a real scripting language can be applied to build problems.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ &Cons; builds everything from a single process at the top of the
+ source tree, with a global view of the dependencies.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ &Cons; scans files automatically for dependencies such as
+ files specified on <literal>#include</literal> lines.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ &Cons; decides if a file was out-of-date by using MD5 checksums of
+ the contents of files, not timestamps.
+
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+
+ Despite all of these intriguing architectural features, the great
+ strength of &Cons;&mdash;being written in Perl&mdash;was also one of
+ its weaknesses, turning away many potential users due to the
+ (real or perceived) steep learning curve of Perl.
+
+ </para>
+
+</section>
+
+<section>
+ <title>&SCons;</title>
+
+ <para>
+
+ Through the &ScCons; contest entry,
+ &SCons; is the direct descendant of the &Cons; architecture,
+ and is currently
+ under active, supported development with a growing body of
+ users. Its first release was 13 December 2001, under the simple and
+ non-restrictive MIT license, and from the outset, the goal of the
+ members of the &SCons; project has been to deliver a stable, reliable
+ tool that can be used for industrial-strength software builds.
+
+ </para>
+
+ <para>
+
+ The rest of this paper will give an overview of the &SCons; design
+ (including its architecture and interface), describe the development
+ methodology used, and discuss future directions for &SCons;.
+
+ </para>
+
+</section>
diff --git a/doc/python10/job-task.eps b/doc/python10/job-task.eps
new file mode 100644
index 0000000..b3eeaff
--- /dev/null
+++ b/doc/python10/job-task.eps
@@ -0,0 +1,238 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: build/doc/python10/job-task.fig
+%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d
+%%CreationDate: Sun Jan 2 01:21:05 2005
+%%For: knight@casablanca.home.baldmt.com (Steven Knight)
+%%BoundingBox: 0 0 416 236
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 236 moveto 0 0 lineto 416 0 lineto 416 236 lineto closepath clip newpath
+-35.3 342.7 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%
+% Fig objects follow
+%
+% Polyline
+7.500 slw
+n 4200 3900 m 5100 3900 l 5100 4500 l 4200 4500 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+4650 4275 m
+gs 1 -1 sc (Task) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 4200 5100 m 5100 5100 l 5100 5700 l 4200 5700 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+4650 5475 m
+gs 1 -1 sc (Node) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 6300 2100 m 7200 2100 l 7200 2700 l 6300 2700 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+6750 2475 m
+gs 1 -1 sc (Sig) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 6300 3300 m 7500 3300 l 7500 3900 l 6300 3900 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+6900 3675 m
+gs 1 -1 sc (Walker) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 4200 2100 m 5700 2100 l 5700 2700 l 4200 2700 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+4950 2475 m
+gs 1 -1 sc (TaskMaster) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 2400 3300 m 3600 3300 l 3600 3900 l 2400 3900 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+3000 3675 m
+gs 1 -1 sc (Parallel) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 600 3300 m 1800 3300 l 1800 3900 l 600 3900 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+1200 3675 m
+gs 1 -1 sc (Serial) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 1200 2100 m 3000 2100 l 3000 2700 l 1200 2700 l
+ cp gs col0 s gr
+/Times-Roman ff 255.00 scf sf
+2099 2475 m
+gs 1 -1 sc (Jobs) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 2700 2700 m 2660 2775 l 2700 2850 l 2740 2775 l
+ cp gs col0 s gr
+% Polyline
+n 5700 2400 m 5775 2440 l 5850 2400 l 5775 2360 l
+ cp gs col0 s gr
+% Polyline
+n 5400 2700 m 5360 2775 l 5400 2850 l 5440 2775 l
+ cp gs col0 s gr
+% Polyline
+n 4650 2700 m 4610 2775 l 4650 2850 l 4690 2775 l
+ cp gs col0 s gr
+% Polyline
+n 1500 2700 m 1460 2775 l 1500 2850 l 1540 2775 l
+ cp gs col0 s gr
+% Polyline
+n 4650 4500 m 4610 4575 l 4650 4650 l 4690 4575 l
+ cp gs col0 s gr
+% Polyline
+gs clippath
+1470 3315 m 1530 3315 l 1530 3164 l 1500 3284 l 1470 3164 l cp
+eoclip
+n 1500 2850 m
+ 1500 3300 l gs col0 s gr gr
+
+% arrowhead
+n 1470 3164 m 1500 3284 l 1530 3164 l 1470 3164 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+2670 3315 m 2730 3315 l 2730 3164 l 2700 3284 l 2670 3164 l cp
+eoclip
+n 2700 2850 m
+ 2700 3300 l gs col0 s gr gr
+
+% arrowhead
+n 2670 3164 m 2700 3284 l 2730 3164 l 2670 3164 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+4620 3915 m 4680 3915 l 4680 3764 l 4650 3884 l 4620 3764 l cp
+eoclip
+n 4650 2850 m
+ 4650 3900 l gs col0 s gr gr
+
+% arrowhead
+n 4620 3764 m 4650 3884 l 4680 3764 l 4620 3764 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+4620 5115 m 4680 5115 l 4680 4964 l 4650 5084 l 4620 4964 l cp
+eoclip
+n 4650 4650 m
+ 4650 5100 l gs col0 s gr gr
+
+% arrowhead
+n 4620 4964 m 4650 5084 l 4680 4964 l 4620 4964 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+6315 3630 m 6315 3570 l 6164 3570 l 6284 3600 l 6164 3630 l cp
+eoclip
+n 5400 2850 m 5400 3600 l
+ 6300 3600 l gs col0 s gr gr
+
+% arrowhead
+n 6164 3630 m 6284 3600 l 6164 3570 l 6164 3630 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+6315 2430 m 6315 2370 l 6164 2370 l 6284 2400 l 6164 2430 l cp
+eoclip
+n 5850 2400 m
+ 6300 2400 l gs col0 s gr gr
+
+% arrowhead
+n 6164 2430 m 6284 2400 l 6164 2370 l 6164 2430 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+n 3000 2400 m 3075 2440 l 3150 2400 l 3075 2360 l
+ cp gs col0 s gr
+% Polyline
+gs clippath
+4215 2430 m 4215 2370 l 4064 2370 l 4184 2400 l 4064 2430 l cp
+eoclip
+n 3150 2400 m
+ 4200 2400 l gs col0 s gr gr
+
+% arrowhead
+n 4064 2430 m 4184 2400 l 4064 2370 l 4064 2430 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+ [60] 0 sd
+n 2100 2100 m
+ 2100 1800 l gs col0 s gr [] 0 sd
+% Polyline
+ [60] 0 sd
+n 4950 2100 m
+ 4950 1800 l gs col0 s gr [] 0 sd
+% Polyline
+ [60] 0 sd
+n 6750 2100 m
+ 6750 1800 l gs col0 s gr [] 0 sd
+$F2psEnd
+rs
diff --git a/doc/python10/job-task.fig b/doc/python10/job-task.fig
new file mode 100644
index 0000000..6febd97
--- /dev/null
+++ b/doc/python10/job-task.fig
@@ -0,0 +1,90 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 4200 3900 5100 4500
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 4200 3900 5100 3900 5100 4500 4200 4500 4200 3900
+4 1 0 50 0 0 16 0.0000 4 165 465 4650 4275 Task\001
+-6
+6 4200 5100 5100 5700
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 4200 5100 5100 5100 5100 5700 4200 5700 4200 5100
+4 1 0 50 0 0 16 0.0000 4 165 525 4650 5475 Node\001
+-6
+6 6300 2100 7200 2700
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 6300 2100 7200 2100 7200 2700 6300 2700 6300 2100
+4 1 0 50 0 0 16 0.0000 4 225 330 6750 2475 Sig\001
+-6
+6 6300 3300 7500 3900
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 6300 3300 7500 3300 7500 3900 6300 3900 6300 3300
+4 1 0 50 0 0 16 0.0000 4 165 735 6900 3675 Walker\001
+-6
+6 4200 2100 5700 2700
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 4200 2100 5700 2100 5700 2700 4200 2700 4200 2100
+4 1 0 50 0 0 16 0.0000 4 165 1155 4950 2475 TaskMaster\001
+-6
+6 2400 3300 3600 3900
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2400 3300 3600 3300 3600 3900 2400 3900 2400 3300
+4 1 0 50 0 0 16 0.0000 4 165 765 3000 3675 Parallel\001
+-6
+6 600 3300 1800 3900
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 600 3300 1800 3300 1800 3900 600 3900 600 3300
+4 1 0 50 0 0 16 0.0000 4 165 585 1200 3675 Serial\001
+-6
+6 1200 2100 3000 2700
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 1200 2100 3000 2100 3000 2700 1200 2700 1200 2100
+4 1 0 50 0 0 17 0.0000 4 165 420 2099 2475 Jobs\001
+-6
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 2700 2700 2660 2775 2700 2850 2740 2775 2700 2700
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 5700 2400 5775 2440 5850 2400 5775 2360 5700 2400
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 5400 2700 5360 2775 5400 2850 5440 2775 5400 2700
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 4650 2700 4610 2775 4650 2850 4690 2775 4650 2700
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 1500 2700 1460 2775 1500 2850 1540 2775 1500 2700
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 4650 4500 4610 4575 4650 4650 4690 4575 4650 4500
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 1500 2850 1500 3300
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 2700 2850 2700 3300
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 4650 2850 4650 3900
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 4650 4650 4650 5100
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3
+ 1 1 1.00 60.00 120.00
+ 5400 2850 5400 3600 6300 3600
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 5850 2400 6300 2400
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 3000 2400 3075 2440 3150 2400 3075 2360 3000 2400
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 3150 2400 4200 2400
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 2100 2100 2100 1800
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 4950 2100 4950 1800
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 6750 2100 6750 1800
diff --git a/doc/python10/job-task.jpg b/doc/python10/job-task.jpg
new file mode 100644
index 0000000..ff3ded0
--- /dev/null
+++ b/doc/python10/job-task.jpg
Binary files differ
diff --git a/doc/python10/main.xml b/doc/python10/main.xml
new file mode 100644
index 0000000..42bc4af
--- /dev/null
+++ b/doc/python10/main.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0"?>
+
+<!--
+
+ Copyright (c) 2001, 2002, 2003 Steven Knight
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+
+ <!ENTITY % scons SYSTEM "scons.mod">
+ %scons;
+
+ <!ENTITY abstract SYSTEM "abstract.xml">
+ <!ENTITY acks SYSTEM "acks.xml">
+ <!ENTITY copyright SYSTEM "copyright.xml">
+ <!ENTITY design SYSTEM "design.xml">
+ <!ENTITY future SYSTEM "future.xml">
+ <!ENTITY install SYSTEM "install.xml">
+ <!ENTITY intro SYSTEM "intro.xml">
+ <!ENTITY process SYSTEM "process.xml">
+
+]>
+
+<article>
+ <articleinfo>
+ <title>SCons Design and Implementation</title>
+
+ <author>
+ <firstname>Steven</firstname>
+ <surname>Knight</surname>
+ </author>
+
+ <copyright>
+ <year>2001</year>
+ <year>2002</year>
+ <holder>Steven Knight</holder>
+ </copyright>
+
+ <pubdate>2002</pubdate>
+
+ <confgroup>
+ <confdates>4-7 February 2002</confdates>
+ <conftitle>The Tenth International Python Conference</conftitle>
+ <address>Alexandria, Virginia</address>
+ </confgroup>
+
+ <revhistory>
+ <revision>
+ <revnumber>0.2</revnumber>
+ <date>16 December 2001</date>
+ <revremark>Internal re-review.</revremark>
+ </revision>
+ <revision>
+ <revnumber>0.1</revnumber>
+ <date>8 October 2001</date>
+ <revremark>Submitted for Python10 conference.</revremark>
+ </revision>
+ </revhistory>
+
+ </articleinfo>
+
+ <abstract>
+ &abstract;
+ </abstract>
+
+ <section id="sect-intro">
+ <title>Introduction</title>
+ &intro;
+ </section>
+
+ <section id="sect-design">
+ <title>Architecture</title>
+ &design;
+ </section>
+
+ <section id="sect-install">
+ <title>Installation</title>
+ &install;
+ </section>
+
+ <section id="sect-process">
+ <title>Development Process</title>
+ &process;
+ </section>
+
+ <section id="sect-future">
+ <title>Future Directions</title>
+ &future;
+ </section>
+
+ <section id="sect-summary">
+ <title>Summary</title>
+ <para>
+
+ This paper has introduced &SCons;, a next-generation build tool
+ with a modular, embeddable architecture and a direct Python
+ interface. &SCons; has a global view of the dependencies in a source
+ tree, uses MD5 signatures to decide if derived files are out of date,
+ and automatically scans files for dependencies, all of which make &SCons;
+ builds exceptionally reliable. The &SCons; development methodology has
+ been described, notable for its emphasis on automated regression
+ testing to ensure a robust and reliable tool from day one. Several
+ future directions for &SCons; have also been discussed.
+
+ </para>
+ </section>
+
+ <section id="sect-acks">
+ <title>Acknowledgements</title>
+ &acks;
+ </section>
+
+ <!--
+ <section id="sect-refs">
+ <title>References</title>
+ <para>
+ </para>
+ </section>
+ -->
+
+ <bibliography id="sect-refs">
+ <title>References</title>
+
+ <biblioentry>
+ <abbrev>1</abbrev>
+ <authorgroup>
+ <author><firstname>Stuart I.</firstname><surname>Feldman</surname></author>
+ </authorgroup>
+ <copyright>
+ <year>Aug 1978</year>
+ </copyright>
+ <publisher>
+ <publishername>Bell Laboratories</publishername>
+ </publisher>
+ <title>Make - A Program for Maintaining Computer Programs</title>
+ </biblioentry>
+
+ <biblioentry>
+ <abbrev>2</abbrev>
+ <authorgroup>
+ <author><firstname>Peter</firstname><surname>Miller</surname></author>
+ </authorgroup>
+ <copyright>
+ <year>1997</year>
+ <holder>Peter Miller</holder>
+ </copyright>
+ <title>Recursive Make Considered Harmful</title>
+ <!--http://www.pcug.org.au/~millerp/rmch/recu-make-cons-harm.html-->
+ </biblioentry>
+
+ <biblioentry>
+ <abbrev>3</abbrev>
+ <authorgroup>
+ <author><firstname>Andrew</firstname><surname>Oram</surname></author>
+ <author><firstname>Steve</firstname><surname>Talbott</surname></author>
+ </authorgroup>
+ <copyright>
+ <year>1986</year>
+ <year>1991</year>
+ <holder>O'Reilly &amp; Associates, Inc.</holder>
+ </copyright>
+ <publisher>
+ <publishername>O'Reilly & Associates, Inc.</publishername>
+ </publisher>
+ <title>Managing Projects with Make, 2nd Ed.</title>
+ </biblioentry>
+
+ <biblioentry>
+ <abbrev>4</abbrev>
+ <authorgroup>
+ <author><firstname>Richard M.</firstname><surname>Stallman</surname></author>
+ <author><firstname>Roland</firstname><surname>McGrath</surname></author>
+ </authorgroup>
+ <copyright>
+ <year>1988</year>
+ <year>'89</year>
+ <year>'90</year>
+ <year>'91</year>
+ <year>'92</year>
+ <year>'93</year>
+ <year>'94</year>
+ <year>'95</year>
+ <year>'96</year>
+ <year>'97</year>
+ <year>'98</year>
+ <year>'99</year>
+ <year>2000</year>
+ <holder>Free Software Foundation, Inc.</holder>
+ </copyright>
+ <publisher>
+ <publishername>Free Software Foundation, Inc.</publishername>
+ </publisher>
+ <title>GNU Make</title>
+ <subtitle>A Program for Directing Recompilation</subtitle>
+ </biblioentry>
+
+ </bibliography>
+
+</article>
diff --git a/doc/python10/node.eps b/doc/python10/node.eps
new file mode 100644
index 0000000..995235d
--- /dev/null
+++ b/doc/python10/node.eps
@@ -0,0 +1,351 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: build/doc/python10/node.fig
+%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d
+%%CreationDate: Sun Jan 2 01:21:05 2005
+%%For: knight@casablanca.home.baldmt.com (Steven Knight)
+%%BoundingBox: 0 0 452 362
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 362 moveto 0 0 lineto 452 0 lineto 452 362 lineto closepath clip newpath
+0.7 414.7 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%
+% Fig objects follow
+%
+% Polyline
+7.500 slw
+n 2700 1200 m 4500 1200 l 4500 1800 l 2700 1800 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+2925 1575 m
+gs 1 -1 sc (Environment) col0 sh gr
+% Polyline
+n 2700 3600 m 4500 3600 l 4500 4200 l 2700 4200 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+3375 3975 m
+gs 1 -1 sc (Node) col0 sh gr
+% Polyline
+n 5700 1800 m 6900 1800 l 6900 2400 l 5700 2400 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+5925 2175 m
+gs 1 -1 sc (Walker) col0 sh gr
+% Polyline
+n 2100 2400 m 3300 2400 l 3300 3000 l 2100 3000 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+2325 2775 m
+gs 1 -1 sc (Builder) col0 sh gr
+% Polyline
+n 3900 2400 m 5100 2400 l 5100 3000 l 3900 3000 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+4125 2775 m
+gs 1 -1 sc (Scanner) col0 sh gr
+% Polyline
+n 2400 6300 m 3300 6300 l 3300 6900 l 2400 6900 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+2700 6675 m
+gs 1 -1 sc (Dir) col0 sh gr
+% Polyline
+n 0 6300 m 900 6300 l 900 6900 l 0 6900 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+150 6675 m
+gs 1 -1 sc (Entry) col0 sh gr
+% Polyline
+n 1200 6300 m 2100 6300 l 2100 6900 l 1200 6900 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+1425 6675 m
+gs 1 -1 sc (File) col0 sh gr
+% Polyline
+n 1050 5100 m 2250 5100 l 2250 5700 l 1050 5700 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+1200 5475 m
+gs 1 -1 sc (Node.FS) col0 sh gr
+% Polyline
+n 1650 5700 m 1575 5850 l 1725 5850 l
+ cp gs col0 s gr
+% Polyline
+n 450 6300 m 450 6000 l 2700 6000 l
+ 2700 6300 l gs col0 s gr
+% Polyline
+n 1650 6300 m
+ 1650 5850 l gs col0 s gr
+% Polyline
+ [60] 0 sd
+n 5100 6300 m 6300 6300 l 6300 6900 l 5100 6900 l
+ cp gs col0 s gr [] 0 sd
+/Times-Roman ff 240.00 scf sf
+5325 6675 m
+gs 1 -1 sc (Record) col0 sh gr
+% Polyline
+ [60] 0 sd
+n 6600 6300 m 7500 6300 l 7500 6900 l 6600 6900 l
+ cp gs col0 s gr [] 0 sd
+/Times-Roman ff 240.00 scf sf
+6750 6675 m
+gs 1 -1 sc (Field) col0 sh gr
+% Polyline
+ [60] 0 sd
+n 4950 5100 m 6150 5100 l 6150 5700 l 4950 5700 l
+ cp gs col0 s gr [] 0 sd
+/Times-Roman ff 240.00 scf sf
+5100 5475 m
+gs 1 -1 sc (Node.DB) col0 sh gr
+% Polyline
+n 5550 5700 m 5475 5850 l 5625 5850 l
+ cp gs col0 s gr
+% Polyline
+ [60] 0 sd
+n 4350 6300 m 4350 6000 l 7050 6000 l
+ 7050 6300 l gs col0 s gr [] 0 sd
+% Polyline
+ [60] 0 sd
+n 5550 5850 m
+ 5550 6300 l gs col0 s gr [] 0 sd
+% Polyline
+ [60] 0 sd
+n 3900 6300 m 4800 6300 l 4800 6900 l 3900 6900 l
+ cp gs col0 s gr [] 0 sd
+/Times-Roman ff 240.00 scf sf
+4050 6675 m
+gs 1 -1 sc (Table) col0 sh gr
+% Polyline
+n 5700 3000 m 6900 3000 l 6900 3600 l 5700 3600 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+5850 3375 m
+gs 1 -1 sc (Wrapper) col0 sh gr
+% Polyline
+n 900 1200 m 1800 1200 l 1800 1800 l 900 1800 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+1200 1575 m
+gs 1 -1 sc (FS) col0 sh gr
+% Polyline
+n 3600 4200 m 3525 4350 l 3675 4350 l
+ cp gs col0 s gr
+% Polyline
+n 1800 5100 m 1800 4800 l 5550 4800 l
+ 5550 5100 l gs col0 s gr
+% Polyline
+n 3600 4800 m
+ 3600 4350 l gs col0 s gr
+% Polyline
+n 4200 1800 m 4160 1875 l 4200 1950 l 4240 1875 l
+ cp gs col0 s gr
+% Polyline
+n 3000 6150 m 2960 6225 l 3000 6300 l 3040 6225 l
+ cp gs col0 s gr
+% Polyline
+n 6300 3600 m 6260 3675 l 6300 3750 l 6340 3675 l
+ cp gs col0 s gr
+% Polyline
+n 6300 2400 m 6260 2475 l 6300 2550 l 6340 2475 l
+ cp gs col0 s gr
+% Polyline
+n 3000 4200 m 2960 4275 l 3000 4350 l 3040 4275 l
+ cp gs col0 s gr
+% Polyline
+n 4200 3450 m 4160 3525 l 4200 3600 l 4240 3525 l
+ cp gs col0 s gr
+% Polyline
+n 3000 3450 m 2960 3525 l 3000 3600 l 3040 3525 l
+ cp gs col0 s gr
+% Polyline
+gs clippath
+2235 5370 m 2235 5430 l 2386 5430 l 2266 5400 l 2386 5370 l cp
+eoclip
+n 3000 6150 m 3000 5400 l
+ 2250 5400 l gs col0 s gr gr
+
+% arrowhead
+n 2386 5370 m 2266 5400 l 2386 5430 l 2386 5370 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+2715 3930 m 2715 3870 l 2564 3870 l 2684 3900 l 2564 3930 l cp
+eoclip
+n 3000 4350 m 3000 4500 l 1800 4500 l 1800 3900 l
+ 2700 3900 l gs col0 s gr gr
+
+% arrowhead
+n 2564 3930 m 2684 3900 l 2564 3870 l 2564 3930 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+4485 3870 m 4485 3930 l 4636 3930 l 4516 3900 l 4636 3870 l cp
+eoclip
+n 6300 3750 m 6300 3900 l
+ 4500 3900 l gs col0 s gr gr
+
+% arrowhead
+n 4636 3870 m 4516 3900 l 4636 3930 l 4636 3870 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+4230 2985 m 4170 2985 l 4170 3136 l 4200 3016 l 4230 3136 l cp
+eoclip
+n 4200 3450 m
+ 4200 3000 l gs col0 s gr gr
+
+% arrowhead
+n 4230 3136 m 4200 3016 l 4170 3136 l 4230 3136 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+3030 2985 m 2970 2985 l 2970 3136 l 3000 3016 l 3030 3136 l cp
+eoclip
+n 3000 3450 m
+ 3000 3000 l gs col0 s gr gr
+
+% arrowhead
+n 3030 3136 m 3000 3016 l 2970 3136 l 3030 3136 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+n 3000 1800 m 2960 1875 l 3000 1950 l 3040 1875 l
+ cp gs col0 s gr
+% Polyline
+gs clippath
+2970 2415 m 3030 2415 l 3030 2264 l 3000 2384 l 2970 2264 l cp
+eoclip
+n 3000 1950 m
+ 3000 2400 l gs col0 s gr gr
+
+% arrowhead
+n 2970 2264 m 3000 2384 l 3030 2264 l 2970 2264 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+4170 2415 m 4230 2415 l 4230 2264 l 4200 2384 l 4170 2264 l cp
+eoclip
+n 4200 1950 m
+ 4200 2400 l gs col0 s gr gr
+
+% arrowhead
+n 4170 2264 m 4200 2384 l 4230 2264 l 4170 2264 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+6270 3015 m 6330 3015 l 6330 2864 l 6300 2984 l 6270 2864 l cp
+eoclip
+n 6300 2550 m
+ 6300 3000 l gs col0 s gr gr
+
+% arrowhead
+n 6270 2864 m 6300 2984 l 6330 2864 l 6270 2864 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+4785 6570 m 4785 6630 l 4936 6630 l 4816 6600 l 4936 6570 l cp
+eoclip
+n 5100 6600 m
+ 4800 6600 l gs col0 s gr gr
+
+% arrowhead
+n 4936 6570 m 4816 6600 l 4936 6630 l 4936 6570 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+6285 6570 m 6285 6630 l 6436 6630 l 6316 6600 l 6436 6570 l cp
+eoclip
+n 6600 6600 m
+ 6300 6600 l gs col0 s gr gr
+
+% arrowhead
+n 6436 6570 m 6316 6600 l 6436 6630 l 6436 6570 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+n 1350 1800 m 1310 1875 l 1350 1950 l 1390 1875 l
+ cp gs col0 s gr
+% Polyline
+gs clippath
+1320 5115 m 1380 5115 l 1380 4964 l 1350 5084 l 1320 4964 l cp
+eoclip
+n 1350 1950 m
+ 1350 5100 l gs col0 s gr gr
+
+% arrowhead
+n 1320 4964 m 1350 5084 l 1380 4964 l 1320 4964 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+ [60] 0 sd
+n 1350 1200 m
+ 1350 900 l gs col0 s gr [] 0 sd
+% Polyline
+ [60] 0 sd
+n 3600 1200 m
+ 3600 900 l gs col0 s gr [] 0 sd
+$F2psEnd
+rs
diff --git a/doc/python10/node.fig b/doc/python10/node.fig
new file mode 100644
index 0000000..3c40f07
--- /dev/null
+++ b/doc/python10/node.fig
@@ -0,0 +1,165 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 2700 1200 4500 1800
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2700 1200 4500 1200 4500 1800 2700 1800 2700 1200
+4 0 0 50 0 0 16 0.0000 4 165 1290 2925 1575 Environment\001
+-6
+6 2700 3600 4500 4200
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2700 3600 4500 3600 4500 4200 2700 4200 2700 3600
+4 0 0 50 0 0 16 0.0000 4 165 525 3375 3975 Node\001
+-6
+6 5700 1800 6900 2400
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 5700 1800 6900 1800 6900 2400 5700 2400 5700 1800
+4 0 0 50 0 0 16 0.0000 4 165 735 5925 2175 Walker\001
+-6
+6 2100 2400 3300 3000
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2100 2400 3300 2400 3300 3000 2100 3000 2100 2400
+4 0 0 50 0 0 16 0.0000 4 165 750 2325 2775 Builder\001
+-6
+6 3900 2400 5100 3000
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3900 2400 5100 2400 5100 3000 3900 3000 3900 2400
+4 0 0 50 0 0 16 0.0000 4 165 780 4125 2775 Scanner\001
+-6
+6 0 5100 3300 6900
+6 2400 6300 3300 6900
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2400 6300 3300 6300 3300 6900 2400 6900 2400 6300
+4 0 0 50 0 0 16 0.0000 4 165 345 2700 6675 Dir\001
+-6
+6 0 6300 900 6900
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 0 6300 900 6300 900 6900 0 6900 0 6300
+4 0 0 50 0 0 16 0.0000 4 225 555 150 6675 Entry\001
+-6
+6 1200 6300 2100 6900
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 1200 6300 2100 6300 2100 6900 1200 6900 1200 6300
+4 0 0 50 0 0 16 0.0000 4 165 390 1425 6675 File\001
+-6
+6 1050 5100 2250 5700
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 1050 5100 2250 5100 2250 5700 1050 5700 1050 5100
+4 0 0 50 0 0 16 0.0000 4 165 855 1200 5475 Node.FS\001
+-6
+6 450 5700 2700 6300
+2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 1650 5700 1575 5850 1725 5850 1650 5700
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 450 6300 450 6000 2700 6000 2700 6300
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
+ 1650 6300 1650 5850
+-6
+-6
+6 3900 5100 7500 6900
+6 5100 6300 6300 6900
+2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5
+ 5100 6300 6300 6300 6300 6900 5100 6900 5100 6300
+4 0 0 50 0 0 16 0.0000 4 165 705 5325 6675 Record\001
+-6
+6 6600 6300 7500 6900
+2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5
+ 6600 6300 7500 6300 7500 6900 6600 6900 6600 6300
+4 0 0 50 0 0 16 0.0000 4 165 510 6750 6675 Field\001
+-6
+6 4950 5100 6150 5700
+2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5
+ 4950 5100 6150 5100 6150 5700 4950 5700 4950 5100
+4 0 0 50 0 0 16 0.0000 4 165 930 5100 5475 Node.DB\001
+-6
+6 4350 5700 7050 6300
+2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 5550 5700 5475 5850 5625 5850 5550 5700
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4
+ 4350 6300 4350 6000 7050 6000 7050 6300
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 5550 5850 5550 6300
+-6
+6 3900 6300 4800 6900
+2 2 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5
+ 3900 6300 4800 6300 4800 6900 3900 6900 3900 6300
+4 0 0 50 0 0 16 0.0000 4 165 555 4050 6675 Table\001
+-6
+-6
+6 5700 3000 6900 3600
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 5700 3000 6900 3000 6900 3600 5700 3600 5700 3000
+4 0 0 50 0 0 16 0.0000 4 225 870 5850 3375 Wrapper\001
+-6
+6 900 1200 1800 1800
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 900 1200 1800 1200 1800 1800 900 1800 900 1200
+4 0 0 50 0 0 16 0.0000 4 165 270 1200 1575 FS\001
+-6
+2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 3600 4200 3525 4350 3675 4350 3600 4200
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 1800 5100 1800 4800 5550 4800 5550 5100
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
+ 3600 4800 3600 4350
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 4200 1800 4160 1875 4200 1950 4240 1875 4200 1800
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 3000 6150 2960 6225 3000 6300 3040 6225 3000 6150
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 6300 3600 6260 3675 6300 3750 6340 3675 6300 3600
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 6300 2400 6260 2475 6300 2550 6340 2475 6300 2400
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 3000 4200 2960 4275 3000 4350 3040 4275 3000 4200
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 4200 3450 4160 3525 4200 3600 4240 3525 4200 3450
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 3000 3450 2960 3525 3000 3600 3040 3525 3000 3450
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3
+ 1 1 1.00 60.00 120.00
+ 3000 6150 3000 5400 2250 5400
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 5
+ 1 1 1.00 60.00 120.00
+ 3000 4350 3000 4500 1800 4500 1800 3900 2700 3900
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3
+ 1 1 1.00 60.00 120.00
+ 6300 3750 6300 3900 4500 3900
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2
+ 1 1 1.00 60.00 120.00
+ 4200 3450 4200 3000
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2
+ 1 1 1.00 60.00 120.00
+ 3000 3450 3000 3000
+2 3 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 5
+ 3000 1800 2960 1875 3000 1950 3040 1875 3000 1800
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2
+ 1 1 1.00 60.00 120.00
+ 3000 1950 3000 2400
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2
+ 1 1 1.00 60.00 120.00
+ 4200 1950 4200 2400
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2
+ 1 1 1.00 60.00 120.00
+ 6300 2550 6300 3000
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2
+ 1 1 1.00 60.00 120.00
+ 5100 6600 4800 6600
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2
+ 1 1 1.00 60.00 120.00
+ 6600 6600 6300 6600
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 1350 1800 1310 1875 1350 1950 1390 1875 1350 1800
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 2
+ 1 1 1.00 60.00 120.00
+ 1350 1950 1350 5100
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 1350 1200 1350 900
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 3600 1200 3600 900
diff --git a/doc/python10/node.jpg b/doc/python10/node.jpg
new file mode 100644
index 0000000..98ceb5e
--- /dev/null
+++ b/doc/python10/node.jpg
Binary files differ
diff --git a/doc/python10/process.xml b/doc/python10/process.xml
new file mode 100644
index 0000000..f1b2479
--- /dev/null
+++ b/doc/python10/process.xml
@@ -0,0 +1,353 @@
+<para>
+
+ The &SCons; project has paid particular attention from day one to the
+ development process. One of the first internal documents produced was
+ a set of Developer's Guidelines to provide a loose framework for what
+ we were trying to accomplish and how we would go about accomplishing
+ it. These Guidelines cover things like:
+
+</para>
+
+<itemizedlist>
+
+ <listitem>
+ <para>
+
+ &SCons; will be written to Python version 1.5.2 (to ensure
+ usability by a wide install base).
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ How &SCons; is be tested: which infrastructure modules to use,
+ what platforms to test on, etc.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ Expectations for developers (subscribe to the mailing list,
+ encouraged to register at SourceForge).
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ Brief outline of how to use the change management systems (Aegis and
+ CVS) for &SCons; development;.
+
+ </para>
+ </listitem>
+
+</itemizedlist>
+
+<para>
+
+ Establishing these guidelines up front had two purposes: 1)
+ Demonstrate the seriousness of the project to anyone wondering about
+ joining the effort; 2) Give potential developers an idea up front as
+ to whether their development style would mesh with the rest of the
+ project.
+
+</para>
+
+<section>
+ <title>Aegis</title>
+
+ <para>
+
+ One of the most important aspects of the &SCons; development process
+ is the use of Peter Miller's Aegis change management system. I
+ had been using Aegis for personal projects for several years, and
+ found its development methodology vastly improved the quality of my
+ programming. I was consequently committed to using it for &SCons;
+ development.
+
+ </para>
+
+ <para>
+
+ Aegis provides a number of things, including:
+
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <para>
+
+ A flexible source code control and branching model.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ A defined process with separate development, review and
+ integration steps.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ A distributed development model based on distribution of atomic
+ change sets.
+
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+
+ The single most important reason for using Aegis, however, is its
+ management of automated tests as part of the development process.
+
+ </para>
+
+</section>
+
+<section>
+ <title>Testing, Testing, Testing</title>
+
+ <para>
+
+ The &SCons; project has made extensive use of automated tests from day
+ one, taking inspiration mostly from Aegis, partly from the eXtreme
+ Programming model, and with a little home-brew scripting for glue.
+
+ </para>
+
+ <section>
+ <title>Testing Criteria</title>
+
+ <para>
+
+ The underlying criteria for testing changes to the &SCons; code
+ are taken from Aegis:
+
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <para>
+
+ Every change must have one or more new or modified tests
+ checked in along with the code.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ The new code being checked in must pass all of the new and/or
+ modified tests.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ The <emphasis>old</emphasis>, already checked-in code in must
+ <emphasis>fail</emphasis> all of the new and/or modified
+ tests.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ The new code being checked in must pass all unmodified,
+ already checked-in tests.
+
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+
+ In practice, these restrictions can be overridden as necessary­for
+ example, when changing comments or documentation.
+
+ </para>
+
+ <para>
+
+ The criterion that surprises many people is having the old code
+ fail the tests in the change. This makes sure that the new tests
+ or modified tests really do exercise the bug fix or feature being
+ added by the change.
+
+ </para>
+
+ <para>
+
+ Together, these criteria ensure that every newly checked-in
+ version &SCons; conforms to defined behavior, as defined by
+ the tests. Whenever a bug is found, its fix is checked in with
+ a new or modified test that guarantees the bug will not recur
+ in the future. We have already built up a regression test base
+ of almost 90 tests that cover the vast majority of &SCons;'
+ functionality.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Testing Infrastructure</title>
+
+ <para>
+
+ Testing standards are no good if they're too much of a burden for
+ developers, who will at best work around or ignore the testing
+ requirements, or at worst stop contributing code and go join a
+ project that's more fun. To this end, good testing infrastructure
+ that makes it easy to write tests is crucial.
+
+ </para>
+
+ <para>
+
+ &SCons; development uses two development methodologies, one for
+ the individual modules in the build engine, and the other for
+ end-to-end tests of the &SCons; script.
+
+ </para>
+
+ <para>
+
+ For the build engine modules, we use PyUnit. Every change to a
+ build engine module must have a change to its corresponding unit
+ tests, which live side-by-side in a separate file that imports
+ module. As we build up a large body of unit tests, this ensures
+ that the build engine will perform correctly whenever someone uses
+ it in some application other than the &SCons; script itself.
+
+ </para>
+
+ <para>
+
+ For end-to-end script tests, we have developed two modules to make
+ writing tests easy. The first, <filename>TestCmd.py</filename>,
+ is a generic module for
+ testing commands or scripts (in any language, not just Python).
+
+ The second module, <filename>TestScons.py</filename>,
+ is a subclass of the generic
+ <filename>TestCmd.py</filename> module.
+ <filename>TestScons.py</filename>
+ takes care of initialization and
+ displaying error conditions
+ specific to testing &SCons;.
+
+ </para>
+
+ <para>
+
+ In practice, simple tests only
+ need to initialize a test object, use the object to write some
+ input files, run &SCons;, and then check whatever criteria
+ determine whether the test passed or failed. A complete test of
+ the &Program; method, for example, looks like this:
+
+ </para>
+
+ <programlisting>
+ test = TestSCons.TestSCons()
+
+ test.write('SConstruct',
+ """env = Environment()
+ env.Program(target = 'foo', source = 'foo.c')
+ """)
+
+ test.write('foo.c',
+ """
+ int
+ main(int argc, char *argv[])
+ {
+ argv[argc++] = "-"; /* dummy use of args */
+ printf("foo.c successfully compiled\\n");
+ exit (0);
+ }
+ """)
+
+ test.run(arguments = 'foo') # runs SCons
+
+ test.run(program = test.workpath('foo'))
+
+ test.fail_test(test.stdout() != "foo.c successfully compiled\n")
+
+ test.pass_test()
+ </programlisting>
+
+ </section>
+
+</section>
+
+<section>
+ <title>SourceForge</title>
+
+ <para>
+
+ Registration of the &SCons; project was approved at SourceForge on
+ 29 June 2001. Within a week, the initial code base was checked in,
+ mailing lists were created, and the web site was set up. We started
+ making use of the task-list manager to track what we had to finish
+ for initial release.
+
+ </para>
+
+ <para>
+
+ The obvious complication was how to use
+ structured testing methodology of Aegis when SourceForge uses
+ CVS for source control. Not using the SourceForge CVS tree would
+ have had two significant disadvantages: one, missing out on the
+ archiving and central location in the event of disaster; two, people
+ coming to the SourceForge project page wouldn't be able to browse
+ the source. The latter was particularly important in
+ the early stages of development, in order to avoid any impression
+ that this was Yet Another Project that starts with a bang and then
+ dwindles as the initial enthusiasm starts to wear off.
+
+ </para>
+
+ <para>
+
+ The solution was to use the SourceForge CVS repository for read-only
+ access to the source. &SCons; developers are welcome to use CVS for
+ their development, but the changes are <emphasis>not</emphasis>
+ committed to the SourceForge repository. Instead, patches are sent
+ to the integrator for processing through Aegis. When the change
+ has been integrated into the Aegis repository, a home-brew
+ script translates the Aegis change into a virtual shell script
+ of commands that copy the necessary files from Aegis and check them
+ in to CVS at SourceForge.
+
+ </para>
+
+ <para>
+
+ (In practice, write access is not actually disabled for registered
+ developers, but if they do make any changes directly at SourceForge,
+ they can be overwritten at the next Aegis update.)
+
+ </para>
+
+</section>
diff --git a/doc/python10/scanner.eps b/doc/python10/scanner.eps
new file mode 100644
index 0000000..35614f8
--- /dev/null
+++ b/doc/python10/scanner.eps
@@ -0,0 +1,168 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: build/doc/python10/scanner.fig
+%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d
+%%CreationDate: Sun Jan 2 01:21:05 2005
+%%For: knight@casablanca.home.baldmt.com (Steven Knight)
+%%BoundingBox: 0 0 398 200
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 200 moveto 0 0 lineto 398 0 lineto 398 200 lineto closepath clip newpath
+-17.3 360.7 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%
+% Fig objects follow
+%
+% Polyline
+7.500 slw
+n 2700 5400 m 4500 5400 l 4500 6000 l 2700 6000 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+3000 5775 m
+gs 1 -1 sc (ProgScanner) col0 sh gr
+% Polyline
+n 2700 4200 m 4500 4200 l 4500 4800 l 2700 4800 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+3225 4575 m
+gs 1 -1 sc (Scanner) col0 sh gr
+% Polyline
+n 2700 3000 m 4500 3000 l 4500 3600 l 2700 3600 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+2925 3375 m
+gs 1 -1 sc (Environment) col0 sh gr
+% Polyline
+ [60] 0 sd
+n 5100 5400 m 6900 5400 l 6900 6000 l 5100 6000 l
+ cp gs col0 s gr [] 0 sd
+/Times-Roman ff 240.00 scf sf
+5400 5775 m
+gs 1 -1 sc (JavaScanner) col0 sh gr
+% Polyline
+n 300 5400 m 2100 5400 l 2100 6000 l 300 6000 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+750 5775 m
+gs 1 -1 sc (CScanner) col0 sh gr
+% Polyline
+n 600 3300 m 1500 3300 l 1500 3900 l 600 3900 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+825 3675 m
+gs 1 -1 sc (Node) col0 sh gr
+% Polyline
+n 1200 5400 m 1200 5100 l 6000 5100 l
+ 6000 5400 l gs col0 s gr
+% Polyline
+n 3600 4950 m
+ 3600 5400 l gs col0 s gr
+% Polyline
+n 3600 4800 m 3525 4950 l 3675 4950 l
+ cp gs col0 s gr
+% Polyline
+n 3600 3600 m 3560 3675 l 3600 3750 l 3640 3675 l
+ cp gs col0 s gr
+% Polyline
+n 1050 3900 m 1010 3975 l 1050 4050 l 1090 3975 l
+ cp gs col0 s gr
+% Polyline
+gs clippath
+2715 4530 m 2715 4470 l 2564 4470 l 2684 4500 l 2564 4530 l cp
+eoclip
+n 1050 4050 m 1050 4500 l
+ 2700 4500 l gs col0 s gr gr
+
+% arrowhead
+n 2564 4530 m 2684 4500 l 2564 4470 l 2564 4530 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+gs clippath
+3570 4215 m 3630 4215 l 3630 4064 l 3600 4184 l 3570 4064 l cp
+eoclip
+n 3600 3750 m
+ 3600 4200 l gs col0 s gr gr
+
+% arrowhead
+n 3570 4064 m 3600 4184 l 3630 4064 l 3570 4064 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+ [60] 0 sd
+n 3600 3000 m
+ 3600 2700 l gs col0 s gr [] 0 sd
+$F2psEnd
+rs
diff --git a/doc/python10/scanner.fig b/doc/python10/scanner.fig
new file mode 100644
index 0000000..01488e8
--- /dev/null
+++ b/doc/python10/scanner.fig
@@ -0,0 +1,57 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 2700 5400 4500 6000
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2700 5400 4500 5400 4500 6000 2700 6000 2700 5400
+4 0 0 50 0 0 16 0.0000 4 225 1245 3000 5775 ProgScanner\001
+-6
+6 2700 4200 4500 4800
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2700 4200 4500 4200 4500 4800 2700 4800 2700 4200
+4 0 0 50 0 0 16 0.0000 4 165 780 3225 4575 Scanner\001
+-6
+6 2700 3000 4500 3600
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2700 3000 4500 3000 4500 3600 2700 3600 2700 3000
+4 0 0 50 0 0 16 0.0000 4 165 1290 2925 3375 Environment\001
+-6
+6 5100 5400 6900 6000
+2 2 1 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 5100 5400 6900 5400 6900 6000 5100 6000 5100 5400
+4 0 0 50 0 0 16 0.0000 4 165 1200 5400 5775 JavaScanner\001
+-6
+6 300 5400 2100 6000
+2 2 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 300 5400 2100 5400 2100 6000 300 6000 300 5400
+4 0 0 50 0 0 16 0.0000 4 165 945 750 5775 CScanner\001
+-6
+6 600 3300 1500 3900
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 600 3300 1500 3300 1500 3900 600 3900 600 3300
+4 0 0 50 0 0 16 0.0000 4 165 525 825 3675 Node\001
+-6
+2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4
+ 1200 5400 1200 5100 6000 5100 6000 5400
+2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 3600 4950 3600 5400
+2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 3600 4800 3525 4950 3675 4950 3600 4800
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 3600 3600 3560 3675 3600 3750 3640 3675 3600 3600
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 1050 3900 1010 3975 1050 4050 1090 3975 1050 3900
+2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 3
+ 1 1 1.00 60.00 120.00
+ 1050 4050 1050 4500 2700 4500
+2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 3600 3750 3600 4200
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 3600 3000 3600 2700
diff --git a/doc/python10/scanner.jpg b/doc/python10/scanner.jpg
new file mode 100644
index 0000000..08e5dcb
--- /dev/null
+++ b/doc/python10/scanner.jpg
Binary files differ
diff --git a/doc/python10/scons.mod b/doc/python10/scons.mod
new file mode 100644
index 0000000..8df6d2c
--- /dev/null
+++ b/doc/python10/scons.mod
@@ -0,0 +1,428 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ An SCons-specific DTD module, for use with SCons DocBook
+ documentation, that contains names, phrases, acronyms, etc. used
+ throughout the SCons documentation.
+
+-->
+
+
+
+<!--
+
+ Other applications that we reference.
+
+-->
+
+<!ENTITY Aegis "<application>Aegis</application>">
+<!ENTITY Ant "<application>Ant</application>">
+<!ENTITY Autoconf "<application>Autoconf</application>">
+<!ENTITY Automake "<application>Automake</application>">
+<!ENTITY cc "<application>cc</application>">
+<!ENTITY Cons "<application>Cons</application>">
+<!ENTITY cp "<application>cp</application>">
+<!ENTITY csh "<application>csh</application>">
+<!ENTITY gcc "<application>gcc</application>">
+<!ENTITY Jam "<application>Jam</application>">
+<!ENTITY jar "<application>jar</application>">
+<!ENTITY javac "<application>javac</application>">
+<!ENTITY javah "<application>javah</application>">
+<!ENTITY Make "<application>Make</application>">
+<!ENTITY Makepp "<application>Make++</application>">
+<!ENTITY Python "<application>Python</application>">
+<!ENTITY ranlib "<application>ranlib</application>">
+<!ENTITY rmic "<application>rmic</application>">
+<!ENTITY SCons "<application>SCons</application>">
+<!ENTITY scons "<application>scons</application>">
+<!ENTITY ScCons "<application>ScCons</application>">
+<!ENTITY tar "<application>tar</application>">
+<!ENTITY touch "<application>touch</application>">
+<!ENTITY zip "<application>zip</application>">
+
+
+<!--
+
+ Classes.
+
+-->
+
+<!ENTITY Action "<classname>Action</classname>">
+<!ENTITY ActionBase "<classname>ActionBase</classname>">
+<!ENTITY CommandAction "<classname>CommandAction</classname>">
+<!ENTITY FunctionAction "<classname>FunctionAction</classname>">
+<!ENTITY ListAction "<classname>ListAction</classname>">
+<!ENTITY Builder "<classname>Builder</classname>">
+<!ENTITY BuilderBase "<classname>BuilderBase</classname>">
+<!ENTITY CompositeBuilder "<classname>CompositeBuilder</classname>">
+<!ENTITY MultiStepBuilder "<classname>MultiStepBuilder</classname>">
+<!ENTITY Job "<classname>Job</classname>">
+<!ENTITY Jobs "<classname>Jobs</classname>">
+<!ENTITY Serial "<classname>Serial</classname>">
+<!ENTITY Parallel "<classname>Parallel</classname>">
+<!ENTITY Node "<classname>Node</classname>">
+<!ENTITY Node_FS "<classname>Node.FS</classname>">
+<!ENTITY Scanner "<classname>Scanner</classname>">
+<!ENTITY Sig "<classname>Sig</classname>">
+<!ENTITY Signature "<classname>Signature</classname>">
+<!ENTITY Taskmaster "<classname>Taskmaster</classname>">
+<!ENTITY TimeStamp "<classname>TimeStamp</classname>">
+<!ENTITY Walker "<classname>Walker</classname>">
+<!ENTITY Wrapper "<classname>Wrapper</classname>">
+
+
+
+<!--
+
+ Options, command-line.
+
+-->
+
+<!ENTITY debug-explain "<literal>--debug=explain</literal>">
+<!ENTITY implicit-cache "<literal>--implicit-cache</literal>">
+<!ENTITY implicit-deps-changed "<literal>--implicit-deps-changed</literal>">
+<!ENTITY implicit-deps-unchanged "<literal>--implicit-deps-unchanged</literal>">
+<!ENTITY Q "<literal>-Q</literal>">
+
+<!--
+
+ Options, SConscript-settable.
+
+-->
+
+<!ENTITY implicit_cache "<literal>implicit_cache</literal>">
+<!ENTITY implicit_deps_changed "<literal>implicit_deps_changed</literal>">
+<!ENTITY implicit_deps_unchanged "<literal>implicit_deps_unchanged</literal>">
+
+
+
+<!--
+
+ File and directory names.
+
+-->
+
+<!ENTITY build "<filename>build</filename>">
+<!ENTITY Makefile "<filename>Makefile</filename>">
+<!ENTITY Makefiles "<filename>Makefiles</filename>">
+<!ENTITY SConscript "<filename>SConscript</filename>">
+<!ENTITY SConstruct "<filename>SConstruct</filename>">
+<!ENTITY Sconstruct "<filename>Sconstruct</filename>">
+<!ENTITY sconstruct "<filename>sconstruct</filename>">
+<!ENTITY sconsign "<filename>.sconsign</filename>">
+<!ENTITY src "<filename>src</filename>">
+
+
+
+<!--
+
+ Methods and functions. This includes functions from both
+ the Build Engine and the Native Python Interface.
+
+-->
+
+<!ENTITY Add "<function>Add</function>">
+<!ENTITY AddOptions "<function>AddOptions</function>">
+<!ENTITY Alias "<function>Alias</function>">
+<!ENTITY Aliases "<function>Aliases</function>">
+<!ENTITY Append "<function>Append</function>">
+<!ENTITY BoolOption "<function>BoolOption</function>">
+<!ENTITY Build "<function>Build</function>">
+<!ENTITY CacheDir "<function>CacheDir</function>">
+<!ENTITY Clean "<function>Clean</function>">
+<!ENTITY Clone "<function>Clone</function>">
+<!ENTITY Command "<function>Command</function>">
+<!ENTITY Configure "<function>Configure</function>">
+<!ENTITY Copy "<function>Copy</function>">
+<!ENTITY Default "<function>Default</function>">
+<!ENTITY DefaultRules "<function>DefaultRules</function>">
+<!ENTITY Depends "<function>Depends</function>">
+<!ENTITY Dir "<function>Dir</function>">
+<!ENTITY Entry "<function>Entry</function>">
+<!ENTITY EnumOption "<function>EnumOption</function>">
+<!ENTITY Environment "<function>Environment</function>">
+<!ENTITY Export "<function>Export</function>">
+<!ENTITY File "<function>File</function>">
+<!ENTITY Finish "<function>Finish</function>">
+<!ENTITY GenerateHelpText "<function>GenerateHelpText</function>">
+<!ENTITY Help "<function>Help</function>">
+<!ENTITY Ignore "<function>Ignore</function>">
+<!ENTITY Import "<function>Import</function>">
+<!ENTITY Install "<function>Install</function>">
+<!ENTITY InstallAs "<function>InstallAs</function>">
+<!ENTITY Link "<function>Link</function>">
+<!ENTITY ListOption "<function>ListOption</function>">
+<!ENTITY Local "<function>Local</function>">
+<!ENTITY Module "<function>Module</function>">
+<!ENTITY Objects "<function>Objects</function>">
+<!ENTITY Options "<function>Options</function>">
+<!ENTITY PackageOption "<function>PackageOption</function>">
+<!ENTITY PathOption "<function>PathOption</function>">
+<!ENTITY Precious "<function>Precious</function>">
+<!ENTITY Prepend "<function>Prepend</function>">
+<!ENTITY Replace "<function>Replace</function>">
+<!ENTITY Repository "<function>Repository</function>">
+<!ENTITY Return "<function>Return</function>">
+<!ENTITY RuleSet "<function>RuleSet</function>">
+<!ENTITY Salt "<function>Salt</function>">
+<!ENTITY SetBuildSignatureType "<function>SetBuildSignatureType</function>">
+<!ENTITY SetContentSignatureType "<function>SetContentSignatureType</function>">
+<!ENTITY SourceSignature "<function>SourceSignature</function>">
+<!ENTITY SourceSignatures "<function>SourceSignatures</function>">
+<!ENTITY Split "<function>Split</function>">
+<!ENTITY TargetSignatures "<function>TargetSignatures</function>">
+<!ENTITY Task "<function>Task</function>">
+
+<!-- Environment methods -->
+<!ENTITY subst "<function>subst</function>">
+
+<!-- Configure context functions -->
+<!ENTITY Message "<function>Message</function>">
+<!ENTITY Result "<function>Result</function>">
+<!ENTITY CheckCHeader "<function>CheckCHeader</function>">
+<!ENTITY CheckCXXHeader "<function>CheckCXXHeader</function>">
+<!ENTITY CheckFunc "<function>CheckFunc</function>">
+<!ENTITY CheckHeader "<function>CheckHeader</function>">
+<!ENTITY CheckLib "<function>CheckLib</function>">
+<!ENTITY CheckLibWithHeader "<function>CheckLibWithHeader</function>">
+<!ENTITY CheckType "<function>CheckType</function>">
+<!ENTITY TryAction "<function>TryAction</function>">
+<!ENTITY TryBuild "<function>TryBuild</function>">
+<!ENTITY TryCompile "<function>TryCompile</function>">
+<!ENTITY TryLink "<function>TryLink</function>">
+<!ENTITY TryRun "<function>TryRun</function>">
+
+<!-- Python functions -->
+<!ENTITY str "<function>str</function>">
+<!ENTITY zipfile "<function>zipfile</function>">
+
+<!-- Obsolete, but referenced in old documents. -->
+<!ENTITY Cache "<function>Cache</function>">
+
+
+
+<!--
+
+ Global variables.
+
+-->
+
+<!ENTITY ARGUMENTS "<varname>ARGUMENTS</varname>">
+<!ENTITY BUILD_TARGETS "<varname>BUILD_TARGETS</varname>">
+<!ENTITY COMMAND_LINE_TARGETS "<varname>COMMAND_LINE_TARGETS</varname>">
+<!ENTITY DEFAULT_TARGETS "<varname>DEFAULT_TARGETS</varname>">
+
+
+
+<!--
+
+ Construction variables.
+
+-->
+
+<!ENTITY BUILDERMAP "<varname>BUILDERMAP</varname>">
+<!ENTITY BUILDERS "<varname>BUILDERS</varname>">
+<!ENTITY CC "<varname>CC</varname>">
+<!ENTITY CCFLAGS "<varname>CCFLAGS</varname>">
+<!ENTITY CCCOM "<varname>CCCOM</varname>">
+<!ENTITY COLOR "<varname>COLOR</varname>">
+<!ENTITY COLORS "<varname>COLORS</varname>">
+<!ENTITY CONFIG "<varname>CONFIG</varname>">
+<!ENTITY CPPDEFINES "<varname>CPPDEFINES</varname>">
+<!ENTITY ENV "<varname>ENV</varname>">
+<!ENTITY JAVACLASSDIR "<varname>JAVACLASSDIR</varname>">
+<!ENTITY LIBDIRPREFIX "<varname>LIBDIRPREFIX</varname>">
+<!ENTITY LIBDIRSUFFIX "<varname>LIBDIRSUFFIX</varname>">
+<!ENTITY LIBLINKPREFIX "<varname>LIBLINKPREFIX</varname>">
+<!ENTITY LIBLINKSUFFIX "<varname>LIBLINKSUFFIX</varname>">
+<!ENTITY LIBPATH "<varname>LIBPATH</varname>">
+<!ENTITY LIBS "<varname>LIBS</varname>">
+<!ENTITY LINK "<varname>LINK</varname>">
+<!ENTITY LINKCOM "<varname>LINKCOM</varname>">
+<!ENTITY LINKFLAGS "<varname>LINKFLAGS</varname>">
+<!ENTITY RELEASE "<varname>RELEASE</varname>">
+<!ENTITY RELEASE_BUILD "<varname>RELEASE_BUILD</varname>">
+<!ENTITY SCANNERMAP "<varname>SCANNERMAP</varname>">
+<!ENTITY SCANNERS "<varname>SCANNERS</varname>">
+<!ENTITY TARFLAGS "<varname>TARFLAGS</varname>">
+<!ENTITY TARSUFFIX "<varname>TARSUFFIX</varname>">
+
+
+
+<!--
+
+ Environment variables.
+
+-->
+
+<!ENTITY PATH "<varname>PATH</varname>">
+<!ENTITY PYTHONPATH "<varname>PYTHONPATH</varname>">
+<!ENTITY SCONSFLAGS "<varname>SCONSFLAGS</varname>">
+
+
+
+<!--
+
+ Function and method arguments.
+
+-->
+
+<!ENTITY allowed_values "<varname>allowed_values</varname>">
+<!ENTITY build_dir "<varname>build_dir</varname>">
+<!ENTITY map "<varname>map</varname>">
+<!ENTITY ignorecase "<varname>ignorecase</varname>">
+<!ENTITY options "<varname>options</varname>">
+<!ENTITY exports "<varname>exports</varname>">
+<!ENTITY source "<varname>source</varname>">
+<!ENTITY target "<varname>target</varname>">
+
+
+
+<!--
+
+ Values of function and method arguments.
+
+-->
+
+<!ENTITY all "<literal>all</literal>">
+<!ENTITY none "<literal>none</literal>">
+
+
+
+<!--
+
+ Builder and Scanner objects.
+
+-->
+
+<!ENTITY BuildDir "<function>BuildDir</function>">
+<!ENTITY CFile "<function>CFile</function>">
+<!ENTITY CXXFile "<function>CXXFile</function>">
+<!ENTITY DVI "<function>DVI</function>">
+<!ENTITY Jar "<function>Jar</function>">
+<!ENTITY Java "<function>Java</function>">
+<!ENTITY JavaH "<function>JavaH</function>">
+<!ENTITY Library "<function>Library</function>">
+<!ENTITY Object "<function>Object</function>">
+<!ENTITY PCH "<function>PCH</function>">
+<!ENTITY PDF "<function>PDF</function>">
+<!ENTITY PostScript "<function>PostScript</function>">
+<!ENTITY Program "<function>Program</function>">
+<!ENTITY RES "<function>RES</function>">
+<!ENTITY RMIC "<function>RMIC</function>">
+<!ENTITY SharedLibrary "<function>SharedLibrary</function>">
+<!ENTITY SharedObject "<function>SharedObject</function>">
+<!ENTITY StaticLibrary "<function>StaticLibrary</function>">
+<!ENTITY StaticObject "<function>StaticObject</function>">
+<!ENTITY Tar "<function>Tar</function>">
+<!ENTITY Zip "<function>Zip</function>">
+
+<!-- Obsolete, but referenced in old documents. -->
+<!ENTITY MakeBuilder "<function>Make</function>">
+
+
+
+<!--
+
+ Terms. Define both singular and plural forms in various
+ case-sensitive combinations for use in titles, in-line, etc.
+
+-->
+
+<!ENTITY buildfunc "<literal>builder function</literal>">
+<!ENTITY builder_method "<literal>builder method</literal>">
+
+<!ENTITY Configure_Contexts "<literal>Configure Contexts</literal>">
+<!ENTITY configure_context "<literal>configure context</literal>">
+
+<!ENTITY ConsEnv "<literal>Construction Environment</literal>">
+<!ENTITY ConsEnvs "<literal>Construction Environments</literal>">
+<!ENTITY Consenv "<literal>Construction environment</literal>">
+<!ENTITY Consenvs "<literal>Construction environments</literal>">
+<!ENTITY consenv "<literal>construction environment</literal>">
+<!ENTITY consenvs "<literal>construction environments</literal>">
+
+<!ENTITY ConsVar "<literal>Construction Variable</literal>">
+<!ENTITY ConsVars "<literal>Construction Variables</literal>">
+<!ENTITY Consvar "<literal>Construction variable</literal>">
+<!ENTITY Consvars "<literal>Construction variables</literal>">
+<!ENTITY consvar "<literal>construction variable</literal>">
+<!ENTITY consvars "<literal>construction variables</literal>">
+
+<!ENTITY CPPPATH "<literal>CPPPATH</literal>">
+
+<!ENTITY Dictionary "<literal>Dictionary</literal>">
+
+<!ENTITY Emitter "<literal>Emitter</literal>">
+<!ENTITY emitter "<literal>emitter</literal>">
+<!ENTITY Generator "<literal>Generator</literal>">
+<!ENTITY generator "<literal>generator</literal>">
+
+<!ENTITY Nodes "<literal>Nodes</literal>">
+
+<!ENTITY signature "<literal>signature</literal>">
+<!ENTITY buildsignature "<literal>build signature</literal>">
+
+<!ENTITY true "<literal>true</literal>">
+<!ENTITY false "<literal>false</literal>">
+
+<!ENTITY typedef "<literal>typedef</literal>">
+
+<!--
+
+ File and program names used in examples.
+
+-->
+
+<!ENTITY bar "<application>bar</application>">
+<!ENTITY common1_c "<filename>common1.c</filename>">
+<!ENTITY common2_c "<filename>common2.c</filename>">
+<!ENTITY custom_py "<filename>custom.py</filename>">
+<!ENTITY goodbye "<application>goodbye</application>">
+<!ENTITY goodbye_o "<filename>goodbye.o</filename>">
+<!ENTITY goodbye_obj "<filename>goodbye.obj</filename>">
+<!ENTITY file_dll "<filename>file.dll</filename>">
+<!ENTITY file_in "<filename>file.in</filename>">
+<!ENTITY file_lib "<filename>file.lib</filename>">
+<!ENTITY file_o "<filename>file.o</filename>">
+<!ENTITY file_obj "<filename>file.obj</filename>">
+<!ENTITY file_out "<filename>file.out</filename>">
+<!ENTITY foo "<application>foo</application>">
+<!ENTITY foo_o "<filename>foo.o</filename>">
+<!ENTITY foo_obj "<filename>foo.obj</filename>">
+<!ENTITY hello "<application>hello</application>">
+<!ENTITY hello_c "<filename>hello.c</filename>">
+<!ENTITY hello_exe "<filename>hello.exe</filename>">
+<!ENTITY hello_h "<filename>hello.h</filename>">
+<!ENTITY hello_o "<filename>hello.o</filename>">
+<!ENTITY hello_obj "<filename>hello.obj</filename>">
+<!ENTITY libfile_a "<filename>libfile_a</filename>">
+<!ENTITY libfile_so "<filename>libfile_so</filename>">
+<!ENTITY new_hello "<application>new_hello</application>">
+<!ENTITY new_hello_exe "<application>new_hello.exe</application>">
+<!ENTITY prog "<filename>prog</filename>">
+<!ENTITY prog1 "<filename>prog1</filename>">
+<!ENTITY prog2 "<filename>prog2</filename>">
+<!ENTITY prog_c "<filename>prog.c</filename>">
+<!ENTITY prog_exe "<filename>prog.exe</filename>">
+<!ENTITY stdio_h "<filename>stdio.h</filename>">
+
+<!--
+
+ Punctuation.
+
+-->
+
+<!ENTITY plus "<literal>+</literal>">
+<!ENTITY hash "<literal>#</literal>">
+
+<!--
+
+ Mailing lists
+
+-->
+
+<!ENTITY scons-announce "<literal>announce@scons.tigris.org</literal>">
+<!ENTITY scons-devel "<literal>dev@scons.tigris.org</literal>">
+<!ENTITY scons-users "<literal>users@scons.tigris.org</literal>">
diff --git a/doc/python10/sig.eps b/doc/python10/sig.eps
new file mode 100644
index 0000000..26aabaa
--- /dev/null
+++ b/doc/python10/sig.eps
@@ -0,0 +1,147 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: build/doc/python10/sig.fig
+%%Creator: /usr/bin/fig2dev Version 3.2 Patchlevel 3d
+%%CreationDate: Sun Jan 2 01:21:05 2005
+%%For: knight@casablanca.home.baldmt.com (Steven Knight)
+%%BoundingBox: 0 0 308 128
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 128 moveto 0 0 lineto 308 0 lineto 308 128 lineto closepath clip newpath
+-71.3 288.7 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%
+% Fig objects follow
+%
+% Polyline
+7.500 slw
+n 1200 3000 m 2700 3000 l 2700 3600 l 1200 3600 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+1950 3375 m
+gs 1 -1 sc (Taskmaster) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 3300 4200 m 4500 4200 l 4500 4800 l 3300 4800 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+3900 4575 m
+gs 1 -1 sc (MD5) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 5100 4200 m 6300 4200 l 6300 4800 l 5100 4800 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+5700 4575 m
+gs 1 -1 sc (TStamp) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 4200 3000 m 5400 3000 l 5400 3600 l 4200 3600 l
+ cp gs col0 s gr
+/Times-Roman ff 240.00 scf sf
+4800 3375 m
+gs 1 -1 sc (Sig) dup sw pop 2 div neg 0 rm col0 sh gr
+% Polyline
+n 2700 3300 m 2775 3340 l 2850 3300 l 2775 3260 l
+ cp gs col0 s gr
+% Polyline
+n 4800 3600 m 4725 3750 l 4875 3750 l
+ cp gs col0 s gr
+% Polyline
+n 3900 4200 m 3900 3900 l 5700 3900 l
+ 5700 4200 l gs col0 s gr
+% Polyline
+n 4800 3750 m
+ 4800 3900 l gs col0 s gr
+% Polyline
+gs clippath
+4215 3330 m 4215 3270 l 4064 3270 l 4184 3300 l 4064 3330 l cp
+eoclip
+n 2850 3300 m
+ 4200 3300 l gs col0 s gr gr
+
+% arrowhead
+n 4064 3330 m 4184 3300 l 4064 3270 l 4064 3330 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+ [60] 0 sd
+n 1950 3000 m
+ 1950 2700 l gs col0 s gr [] 0 sd
+% Polyline
+ [60] 0 sd
+n 4800 3000 m
+ 4800 2700 l gs col0 s gr [] 0 sd
+$F2psEnd
+rs
diff --git a/doc/python10/sig.fig b/doc/python10/sig.fig
new file mode 100644
index 0000000..823d59e
--- /dev/null
+++ b/doc/python10/sig.fig
@@ -0,0 +1,44 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 1200 3000 2700 3600
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 1200 3000 2700 3000 2700 3600 1200 3600 1200 3000
+4 1 0 50 0 0 16 0.0000 4 165 1125 1950 3375 Taskmaster\001
+-6
+6 3300 4200 4500 4800
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3300 4200 4500 4200 4500 4800 3300 4800 3300 4200
+4 1 0 50 0 0 16 0.0000 4 165 525 3900 4575 MD5\001
+-6
+6 5100 4200 6300 4800
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 5100 4200 6300 4200 6300 4800 5100 4800 5100 4200
+4 1 0 50 0 0 16 0.0000 4 225 780 5700 4575 TStamp\001
+-6
+6 4200 3000 5400 3600
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 4200 3000 5400 3000 5400 3600 4200 3600 4200 3000
+4 1 0 50 0 0 16 0.0000 4 225 330 4800 3375 Sig\001
+-6
+2 3 0 1 0 7 50 0 -1 4.000 0 0 7 0 0 5
+ 2700 3300 2775 3340 2850 3300 2775 3260 2700 3300
+2 3 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 4800 3600 4725 3750 4875 3750 4800 3600
+2 1 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 4
+ 3900 4200 3900 3900 5700 3900 5700 4200
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
+ 4800 3750 4800 3900
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 1.00 60.00 120.00
+ 2850 3300 4200 3300
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 1950 3000 1950 2700
+2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
+ 4800 3000 4800 2700
diff --git a/doc/python10/sig.jpg b/doc/python10/sig.jpg
new file mode 100644
index 0000000..0c7e0df
--- /dev/null
+++ b/doc/python10/sig.jpg
Binary files differ
diff --git a/doc/reference/Alias.xml b/doc/reference/Alias.xml
new file mode 100644
index 0000000..b87967d
--- /dev/null
+++ b/doc/reference/Alias.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &Alias; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/CFile.xml b/doc/reference/CFile.xml
new file mode 100644
index 0000000..f76c390
--- /dev/null
+++ b/doc/reference/CFile.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &CFile; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/CXXFile.xml b/doc/reference/CXXFile.xml
new file mode 100644
index 0000000..c1c038e
--- /dev/null
+++ b/doc/reference/CXXFile.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &CXXFile; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/Command.xml b/doc/reference/Command.xml
new file mode 100644
index 0000000..abb3a58
--- /dev/null
+++ b/doc/reference/Command.xml
@@ -0,0 +1,73 @@
+<!--
+
+ 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 a catchall method which can be used to arrange for
+any build action to be executed to update the target. For this command, a
+target file and list of inputs is provided. In addition, a build action
+is specified as the last argument. The build action is typically a
+command line or lines, but may also contain Perl code to be executed;
+see the section above on build actions for details.
+
+The C<Command> method is called as follows:
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &Command; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/Install.xml b/doc/reference/Install.xml
new file mode 100644
index 0000000..2d06e3b
--- /dev/null
+++ b/doc/reference/Install.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &Install; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/InstallAs.xml b/doc/reference/InstallAs.xml
new file mode 100644
index 0000000..ed8cb78
--- /dev/null
+++ b/doc/reference/InstallAs.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &InstallAs; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/Library.xml b/doc/reference/Library.xml
new file mode 100644
index 0000000..19a3e96
--- /dev/null
+++ b/doc/reference/Library.xml
@@ -0,0 +1,152 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003 Steven Knight
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head2 The C<Library> method
+
+The C<Library> method arranges to create the specified library from the
+specified object files. It is invoked as follows:
+
+ Library $env <library name>, <source or object files>;
+
+The library name will have the value of the C<SUFLIB> construction
+variable appended (by default, C<.lib> on Win32 systems, C<.a> on Unix
+systems) if the suffix is not already present.
+
+Source files may be specified in place of objects files-,-the C<Objects>
+method will be invoked to arrange the conversion of all the files into
+object files, and hence all the observations about the C<Objects> method,
+above, apply to this method also.
+
+The actual creation of the library will be handled by an external
+command which results from expanding the C<ARCOM> construction variable,
+with C<%E<lt>> set to the library members (in the order presented),
+and C<%E<gt>> to the library to be created. (See the section above
+on construction variable expansion for details.) The user may set
+variables in the construction environment which will affect the
+operation of the command. These include C<AR>, the archive program
+to use, C<ARFLAGS>, which can be used to modify the flags given to
+the program specified by C<AR>, and C<RANLIB>, the name of a archive
+index generation program, if needed (if the particular need does not
+require the latter functionality, then C<ARCOM> must be redefined to not
+reference C<RANLIB>).
+
+The C<Library> method allows the same library to be specified in multiple
+method invocations. All of the contributing objects from all the invocations
+(which may be from different directories) are combined and generated by a
+single archive command. Note, however, that if you prune a build so that
+only part of a library is specified, then only that part of the library will
+be generated (the rest will disappear!).
+
+-->
+
+ <section>
+ <title>Linking With a Library</title>
+
+ <programlisting>
+ env = Environment(CC = 'gcc',
+ LIBS = 'world')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -c world.c -o world.o
+ gcc -o hello hello.o -lworld
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Creating a Library</title>
+
+ <programlisting>
+ env = Environment(CC = 'gcc',
+ LIBS = 'world')
+ env.Program('hello.c')
+ env.Library('world.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -c world.c -o world.o
+ ar r libworld.a world.o
+ ar: creating libworld.a
+ ranlib libworld.a
+ gcc -o hello hello.o libworld.a
+ </literallayout>
+
+ </section>
+
+<!--
+
+A key simplification of Cons is the idea of a B<construction environment>. A
+construction environment is an B<object> characterized by a set of key/value
+pairs and a set of B<methods>. In order to tell Cons how to build something,
+you invoke the appropriate method via an appropriate construction
+environment. Consider the following example:
+
+
+
+ $env = new cons(
+ CC => 'gcc',
+ LIBS => 'libworld.a'
+ );
+
+ Program $env 'hello', 'hello.c';
+
+In this case, rather than using the default construction environment, as is,
+we have overridden the value of C<CC> so that the GNU C Compiler equivalent
+is used, instead. Since this version of B<Hello, World!> requires a library,
+F<libworld.a>, we have specified that any program linked in this environment
+should be linked with that library. If the library exists already, well and
+good, but if not, then we'll also have to include the statement:
+
+
+
+ Library $env 'libworld', 'world.c';
+
+Now if you type C<cons hello>, the library will be built before the program
+is linked, and, of course, C<gcc> will be used to compile both modules:
+
+
+
+ % cons hello
+
+-->
+
+ <section>
+ <title>The &Library; Builder</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/MANIFEST b/doc/reference/MANIFEST
new file mode 100644
index 0000000..438aada
--- /dev/null
+++ b/doc/reference/MANIFEST
@@ -0,0 +1,21 @@
+Alias.xml
+CFile.xml
+CXXFile.xml
+Command.xml
+Install.xml
+InstallAs.xml
+Library.xml
+Object.xml
+PCH.xml
+PDF.xml
+PostScript.xml
+Program.xml
+RES.xml
+SharedLibrary.xml
+SharedObject.xml
+StaticLibrary.xml
+StaticObject.xml
+copyright.xml
+errors.xml
+main.xml
+preface.xml
diff --git a/doc/reference/Object.xml b/doc/reference/Object.xml
new file mode 100644
index 0000000..9e887d8
--- /dev/null
+++ b/doc/reference/Object.xml
@@ -0,0 +1,71 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003 Steven Knight
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head2 The C<Objects> method
+
+The C<Objects> method arranges to create the object files that correspond to
+the specified source files. It is invoked as shown below:
+
+ @files = Objects $env <source or object files>;
+
+Under Unix, source files ending in F<.s> and F<.c> are currently
+supported, and will be compiled into a name of the same file ending
+in F<.o>. By default, all files are created by invoking the external
+command which results from expanding the C<CCCOM> construction variable,
+with C<%E<lt>> and C<%E<gt>> set to the source and object files,
+respectively. (See the section above on construction variable expansion
+for details). The variable C<CPPPATH> is also used when scanning source
+files for dependencies. This is a colon separated list of pathnames, and
+is also used to create the construction variable C<_IFLAGS,> which will
+contain the appropriate list of -C<I> options for the compilation. Any
+relative pathnames in C<CPPPATH> is interpreted relative to the
+directory in which the associated construction environment was created
+(absolute and top-relative names may also be used). This variable is
+used by C<CCCOM>. The behavior of this command can be modified by
+changing any of the variables which are interpolated into C<CCCOM>, such
+as C<CC>, C<CFLAGS>, and, indirectly, C<CPPPATH>. It's also possible
+to replace the value of C<CCCOM>, itself. As a convenience, this file
+returns the list of object filenames.
+
+-->
+
+ <para>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &Object; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/PCH.xml b/doc/reference/PCH.xml
new file mode 100644
index 0000000..b2a4d75
--- /dev/null
+++ b/doc/reference/PCH.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &PCH; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/PDF.xml b/doc/reference/PDF.xml
new file mode 100644
index 0000000..b3a25dc
--- /dev/null
+++ b/doc/reference/PDF.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &PDF; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/PostScript.xml b/doc/reference/PostScript.xml
new file mode 100644
index 0000000..f5a6579
--- /dev/null
+++ b/doc/reference/PostScript.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &PostScript; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/Program.xml b/doc/reference/Program.xml
new file mode 100644
index 0000000..30f90d2
--- /dev/null
+++ b/doc/reference/Program.xml
@@ -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.
+
+-->
+
+<!--
+
+=head2 The C<Program> method
+
+The C<Program> method arranges to link the specified program with the
+specified object files. It is invoked in the following manner:
+
+ Program $env <program name>, <source or object files>;
+
+The program name will have the value of the C<SUFEXE> construction
+variable appended (by default, C<.exe> on Win32 systems, nothing on Unix
+systems) if the suffix is not already present.
+
+Source files may be specified in place of objects files-,-the C<Objects>
+method will be invoked to arrange the conversion of all the files into
+object files, and hence all the observations about the C<Objects> method,
+above, apply to this method also.
+
+The actual linking of the program will be handled by an external command
+which results from expanding the C<LINKCOM> construction variable, with
+C<%E<lt>> set to the object files to be linked (in the order presented),
+and C<%E<gt>> set to the target. (See the section above on construction
+variable expansion for details.) The user may set additional variables
+in the construction environment, including C<LINK>, to define which
+program to use for linking, C<LIBPATH>, a colon-separated list of
+library search paths, for use with library specifications of the form
+I<-llib>, and C<LIBS>, specifying the list of libraries to link against
+(in either I<-llib> form or just as pathnames. Relative pathnames in
+both C<LIBPATH> and C<LIBS> are interpreted relative to the directory
+in which the associated construction environment is created (absolute
+and top-relative names may also be used). Cons automatically sets up
+dependencies on any libraries mentioned in C<LIBS>: those libraries will
+be built before the command is linked.
+
+-->
+
+ <para>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &Program; Builder</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/RES.xml b/doc/reference/RES.xml
new file mode 100644
index 0000000..15c0aea
--- /dev/null
+++ b/doc/reference/RES.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &RES; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/SharedLibrary.xml b/doc/reference/SharedLibrary.xml
new file mode 100644
index 0000000..603dab1
--- /dev/null
+++ b/doc/reference/SharedLibrary.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &SharedLibrary; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/SharedObject.xml b/doc/reference/SharedObject.xml
new file mode 100644
index 0000000..0860769
--- /dev/null
+++ b/doc/reference/SharedObject.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &SharedObject; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/StaticLibrary.xml b/doc/reference/StaticLibrary.xml
new file mode 100644
index 0000000..ea7ae5b
--- /dev/null
+++ b/doc/reference/StaticLibrary.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &StaticLibrary; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/StaticObject.xml b/doc/reference/StaticObject.xml
new file mode 100644
index 0000000..ff8dae8
--- /dev/null
+++ b/doc/reference/StaticObject.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &StaticObject; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/copyright.xml b/doc/reference/copyright.xml
new file mode 100644
index 0000000..7f6059c
--- /dev/null
+++ b/doc/reference/copyright.xml
@@ -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/reference/errors.xml b/doc/reference/errors.xml
new file mode 100644
index 0000000..448777f
--- /dev/null
+++ b/doc/reference/errors.xml
@@ -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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>X</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/reference/main.xml b/doc/reference/main.xml
new file mode 100644
index 0000000..ed122f6
--- /dev/null
+++ b/doc/reference/main.xml
@@ -0,0 +1,207 @@
+<?xml version="1.0"?>
+
+<!--
+
+ Copyright (c) 2001, 2002, 2003 Steven Knight
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+
+ <!ENTITY % version SYSTEM "../version.xml">
+ %version;
+
+ <!ENTITY % scons SYSTEM "../scons.mod">
+ %scons;
+
+ <!-- Builders -->
+ <!ENTITY Alias_file SYSTEM "Alias.xml">
+ <!ENTITY CFile_file SYSTEM "CFile.xml">
+ <!ENTITY CXXFile_file SYSTEM "CXXFile.xml">
+ <!ENTITY Command_file SYSTEM "Command.xml">
+ <!ENTITY Install_file SYSTEM "Install.xml">
+ <!ENTITY InstallAs_file SYSTEM "InstallAs.xml">
+ <!ENTITY Library_file SYSTEM "Library.xml">
+ <!ENTITY Object_file SYSTEM "Object.xml">
+ <!ENTITY PCH_file SYSTEM "PCH.xml">
+ <!ENTITY PDF_file SYSTEM "PDF.xml">
+ <!ENTITY PostScript_file SYSTEM "PostScript.xml">
+ <!ENTITY Program_file SYSTEM "Program.xml">
+ <!ENTITY RES_file SYSTEM "RES.xml">
+ <!ENTITY SharedLibrary_file SYSTEM "SharedLibrary.xml">
+ <!ENTITY SharedObject_file SYSTEM "SharedObject.xml">
+ <!ENTITY StaticLibrary_file SYSTEM "StaticLibrary.xml">
+ <!ENTITY StaticObject_file SYSTEM "StaticObject.xml">
+
+ <!-- Construction Variables -->
+
+ <!ENTITY copyright SYSTEM "copyright.xml">
+ <!ENTITY errors SYSTEM "errors.xml">
+ <!ENTITY preface SYSTEM "preface.xml">
+
+]>
+
+<book>
+ <bookinfo>
+ <title>SCons Reference Manual &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-builders">
+ <title>Builder Reference</title>
+
+ <section id="sect-Alias">
+ <title>The Alias Builder</title>
+ &Alias_file;
+ </section>
+
+ <section id="sect-CFile">
+ <title>The CFile Builder</title>
+ &CFile_file;
+ </section>
+
+ <section id="sect-Command">
+ <title>The Command Builder</title>
+ &Command_file;
+ </section>
+
+ <section id="sect-CXXFile">
+ <title>The CXXFile Builder</title>
+ &CXXFile_file;
+ </section>
+
+ <section id="sect-Install">
+ <title>The Install Builder</title>
+ &Install_file;
+ </section>
+
+ <section id="sect-InstallAs">
+ <title>The InstallAs Builder</title>
+ &InstallAs_file;
+ </section>
+
+ <section id="sect-Library">
+ <title>The Library Builder</title>
+ &Library_file;
+ </section>
+
+ <section id="sect-Object">
+ <title>The Object Builder</title>
+ &Object_file;
+ </section>
+
+ <section id="sect-PCH">
+ <title>The PCH Builder</title>
+ &PCH_file;
+ </section>
+
+ <section id="sect-PDF">
+ <title>The PDF Builder</title>
+ &PDF_file;
+ </section>
+
+ <section id="sect-PostScript">
+ <title>The PDF Builder</title>
+ &PostScript_file;
+ </section>
+
+ <section id="sect-Program">
+ <title>The Program Builder</title>
+ &Program_file;
+ </section>
+
+ <section id="sect-RES">
+ <title>The RES Builder</title>
+ &RES_file;
+ </section>
+
+ <section id="sect-SharedLibrary">
+ <title>The SharedLibrary Builder</title>
+ &SharedLibrary_file;
+ </section>
+
+ <section id="sect-SharedObject">
+ <title>The SharedObject Builder</title>
+ &SharedObject_file;
+ </section>
+
+ <section id="sect-StaticLibrary">
+ <title>The StaticLibrary Builder</title>
+ &StaticLibrary_file;
+ </section>
+
+ <section id="sect-StaticObject">
+ <title>The StaticObject Builder</title>
+ &StaticObject_file;
+ </section>
+
+ </chapter>
+
+ <chapter id="chap-variables">
+ <title>&ConsVar; Reference</title>
+
+ <section id="sect-AR">
+ <title>AR</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ </chapter>
+
+ <appendix id="chap-errors">
+ <title>Errors Generated by &SCons;</title>
+ &errors;
+ </appendix>
+
+</book>
diff --git a/doc/reference/preface.xml b/doc/reference/preface.xml
new file mode 100644
index 0000000..82ea44a
--- /dev/null
+++ b/doc/reference/preface.xml
@@ -0,0 +1,85 @@
+<!--
+
+ 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>Why &SCons;?</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>History</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Conventions</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Acknowledgements</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Contact</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
diff --git a/doc/scons.mod b/doc/scons.mod
new file mode 100644
index 0000000..8ac58ca
--- /dev/null
+++ b/doc/scons.mod
@@ -0,0 +1,521 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ An SCons-specific DTD module, for use with SCons DocBook
+ documentation, that contains names, phrases, acronyms, etc. used
+ throughout the SCons documentation.
+
+-->
+
+
+
+<!--
+
+ Other applications that we reference.
+
+-->
+
+<!ENTITY Aegis "<application>Aegis</application>">
+<!ENTITY Ant "<application>Ant</application>">
+<!ENTITY ar "<application>ar</application>">
+<!ENTITY as "<application>as</application>">
+<!ENTITY Autoconf "<application>Autoconf</application>">
+<!ENTITY Automake "<application>Automake</application>">
+<!ENTITY bison "<application>bison</application>">
+<!ENTITY cc "<application>cc</application>">
+<!ENTITY Cons "<application>Cons</application>">
+<!ENTITY cp "<application>cp</application>">
+<!ENTITY csh "<application>csh</application>">
+<!ENTITY f77 "<application>f77</application>">
+<!ENTITY f90 "<application>f90</application>">
+<!ENTITY f95 "<application>f95</application>">
+<!ENTITY gas "<application>gas</application>">
+<!ENTITY gcc "<application>gcc</application>">
+<!ENTITY g77 "<application>g77</application>">
+<!ENTITY gXX "<application>gXX</application>">
+<!ENTITY Jam "<application>Jam</application>">
+<!ENTITY jar "<application>jar</application>">
+<!ENTITY javac "<application>javac</application>">
+<!ENTITY javah "<application>javah</application>">
+<!ENTITY latex "<application>latex</application>">
+<!ENTITY lex "<application>lex</application>">
+<!ENTITY m4 "<application>m4</application>">
+<!ENTITY Make "<application>Make</application>">
+<!ENTITY Makepp "<application>Make++</application>">
+<!ENTITY pdflatex "<application>pdflatex</application>">
+<!ENTITY pdftex "<application>pdftex</application>">
+<!ENTITY Python "<application>Python</application>">
+<!ENTITY ranlib "<application>ranlib</application>">
+<!ENTITY rmic "<application>rmic</application>">
+<!ENTITY SCons "<application>SCons</application>">
+<!ENTITY ScCons "<application>ScCons</application>">
+<!ENTITY swig "<application>swig</application>">
+<!ENTITY tar "<application>tar</application>">
+<!ENTITY tex "<application>tex</application>">
+<!ENTITY touch "<application>touch</application>">
+<!ENTITY yacc "<application>yacc</application>">
+<!ENTITY zip "<application>zip</application>">
+
+
+<!--
+
+ Classes.
+
+-->
+
+<!ENTITY Action "<classname>Action</classname>">
+<!ENTITY ActionBase "<classname>ActionBase</classname>">
+<!ENTITY CommandAction "<classname>CommandAction</classname>">
+<!ENTITY FunctionAction "<classname>FunctionAction</classname>">
+<!ENTITY ListAction "<classname>ListAction</classname>">
+<!ENTITY Builder "<classname>Builder</classname>">
+<!ENTITY BuilderBase "<classname>BuilderBase</classname>">
+<!ENTITY CompositeBuilder "<classname>CompositeBuilder</classname>">
+<!ENTITY MultiStepBuilder "<classname>MultiStepBuilder</classname>">
+<!ENTITY Job "<classname>Job</classname>">
+<!ENTITY Jobs "<classname>Jobs</classname>">
+<!ENTITY Serial "<classname>Serial</classname>">
+<!ENTITY Parallel "<classname>Parallel</classname>">
+<!ENTITY Node "<classname>Node</classname>">
+<!ENTITY Node_FS "<classname>Node.FS</classname>">
+<!ENTITY Scanner "<classname>Scanner</classname>">
+<!ENTITY Sig "<classname>Sig</classname>">
+<!ENTITY Signature "<classname>Signature</classname>">
+<!ENTITY Taskmaster "<classname>Taskmaster</classname>">
+<!ENTITY TimeStamp "<classname>TimeStamp</classname>">
+<!ENTITY Walker "<classname>Walker</classname>">
+<!ENTITY Wrapper "<classname>Wrapper</classname>">
+
+
+
+<!--
+
+ Options, command-line.
+
+-->
+
+<!ENTITY config "<literal>--config</literal>">
+<!ENTITY debug-explain "<literal>--debug=explain</literal>">
+<!ENTITY debug-findlibs "<literal>--debug=findlibs</literal>">
+<!ENTITY debug-includes "<literal>--debug=includes</literal>">
+<!ENTITY debug-presub "<literal>--debug=presub</literal>">
+<!ENTITY debug-stacktrace "<literal>--debug=stacktrace</literal>">
+<!ENTITY implicit-cache "<literal>--implicit-cache</literal>">
+<!ENTITY implicit-deps-changed "<literal>--implicit-deps-changed</literal>">
+<!ENTITY implicit-deps-unchanged "<literal>--implicit-deps-unchanged</literal>">
+<!ENTITY profile "<literal>--profile</literal>">
+<!ENTITY taskmastertrace "<literal>--taskmastertrace</literal>">
+<!ENTITY tree "<literal>--tree</literal>">
+<!ENTITY Q "<literal>-Q</literal>">
+
+<!--
+
+ Options, SConscript-settable.
+
+-->
+
+<!ENTITY implicit_cache "<literal>implicit_cache</literal>">
+<!ENTITY implicit_deps_changed "<literal>implicit_deps_changed</literal>">
+<!ENTITY implicit_deps_unchanged "<literal>implicit_deps_unchanged</literal>">
+
+
+
+<!--
+
+ File and directory names.
+
+-->
+
+<!ENTITY build "<filename>build</filename>">
+<!ENTITY Makefile "<filename>Makefile</filename>">
+<!ENTITY Makefiles "<filename>Makefiles</filename>">
+<!ENTITY scons "<filename>scons</filename>">
+<!ENTITY SConscript "<filename>SConscript</filename>">
+<!ENTITY SConstruct "<filename>SConstruct</filename>">
+<!ENTITY Sconstruct "<filename>Sconstruct</filename>">
+<!ENTITY sconstruct "<filename>sconstruct</filename>">
+<!ENTITY sconsign "<filename>.sconsign</filename>">
+<!ENTITY src "<filename>src</filename>">
+
+
+
+<!--
+
+ Methods and functions. This includes functions from both
+ the Build Engine and the Native Python Interface.
+
+-->
+
+<!ENTITY Add "<function>Add</function>">
+<!ENTITY AddMethod "<function>AddMethod</function>">
+<!ENTITY AddPostAction "<function>AddPostAction</function>">
+<!ENTITY AddPreAction "<function>AddPreAction</function>">
+<!ENTITY AddOption "<function>AddOption</function>">
+<!ENTITY AddOptions "<function>AddOptions</function>">
+<!ENTITY AddVariables "<function>AddVariables</function>">
+<!ENTITY Alias "<function>Alias</function>">
+<!ENTITY Aliases "<function>Aliases</function>">
+<!ENTITY AlwaysBuild "<function>AlwaysBuild</function>">
+<!ENTITY Append "<function>Append</function>">
+<!ENTITY AppendENVPath "<function>AppendENVPath</function>">
+<!ENTITY AppendUnique "<function>AppendUnique</function>">
+<!ENTITY BoolOption "<function>BoolOption</function>">
+<!ENTITY BoolVariable "<function>BoolVariable</function>">
+<!ENTITY Build "<function>Build</function>">
+<!ENTITY CacheDir "<function>CacheDir</function>">
+<!ENTITY Chmod "<function>Chmod</function>">
+<!ENTITY Clean "<function>Clean</function>">
+<!ENTITY Clone "<function>Clone</function>">
+<!ENTITY Command "<function>Command</function>">
+<!ENTITY Configure "<function>Configure</function>">
+<!ENTITY Copy "<function>Copy</function>">
+<!ENTITY Decider "<function>Decider</function>">
+<!ENTITY Default "<function>Default</function>">
+<!ENTITY DefaultEnvironment "<function>DefaultEnvironment</function>">
+<!ENTITY DefaultRules "<function>DefaultRules</function>">
+<!ENTITY Delete "<function>Delete</function>">
+<!ENTITY Depends "<function>Depends</function>">
+<!ENTITY Dir "<function>Dir</function>">
+<!ENTITY Dump "<function>Dump</function>">
+<!ENTITY Entry "<function>Entry</function>">
+<!ENTITY EnumOption "<function>EnumOption</function>">
+<!ENTITY EnumVariable "<function>EnumVariable</function>">
+<!ENTITY EnsurePythonVersion "<function>EnsurePythonVersion</function>">
+<!ENTITY EnsureSConsVersion "<function>EnsureSConsVersion</function>">
+<!ENTITY Environment "<function>Environment</function>">
+<!ENTITY Execute "<function>Execute</function>">
+<!ENTITY Exit "<function>Exit</function>">
+<!ENTITY Export "<function>Export</function>">
+<!ENTITY File "<function>File</function>">
+<!ENTITY FindFile "<function>FindFile</function>">
+<!ENTITY FindInstalledFiles "<function>FindInstalledFiles</function>">
+<!ENTITY Finish "<function>Finish</function>">
+<!ENTITY Flatten "<function>Flatten</function>">
+<!ENTITY GenerateHelpText "<function>GenerateHelpText</function>">
+<!ENTITY GetBuildFailures "<function>GetBuildFailures</function>">
+<!ENTITY GetLaunchDir "<function>GetLaunchDir</function>">
+<!ENTITY GetOption "<function>GetOption</function>">
+<!ENTITY Glob "<function>Glob</function>">
+<!ENTITY Help "<function>Help</function>">
+<!ENTITY Ignore "<function>Ignore</function>">
+<!ENTITY Import "<function>Import</function>">
+<!ENTITY Install "<function>Install</function>">
+<!ENTITY InstallAs "<function>InstallAs</function>">
+<!ENTITY Link "<function>Link</function>">
+<!ENTITY ListOption "<function>ListOption</function>">
+<!ENTITY ListVariable "<function>ListVariable</function>">
+<!ENTITY Local "<function>Local</function>">
+<!ENTITY MergeFlags "<function>MergeFlags</function>">
+<!ENTITY Mkdir "<function>Mkdir</function>">
+<!ENTITY Module "<function>Module</function>">
+<!ENTITY Move "<function>Move</function>">
+<!ENTITY NoClean "<function>NoClean</function>">
+<!ENTITY NoCache "<function>NoCache</function>">
+<!ENTITY Objects "<function>Objects</function>">
+<!ENTITY Options "<function>Options</function>">
+<!ENTITY Variables "<function>Variables</function>">
+<!ENTITY PackageOption "<function>PackageOption</function>">
+<!ENTITY PackageVariable "<function>PackageVariable</function>">
+<!ENTITY ParseConfig "<function>ParseConfig</function>">
+<!ENTITY ParseDepends "<function>ParseDepends</function>">
+<!ENTITY ParseFlags "<function>ParseFlags</function>">
+<!ENTITY PathOption "<function>PathOption</function>">
+<!ENTITY PathOption_PathAccept "<function>PathOption.PathAccept</function>">
+<!ENTITY PathOption_PathExists "<function>PathOption.PathExists</function>">
+<!ENTITY PathOption_PathIsDir "<function>PathOption.PathIsDir</function>">
+<!ENTITY PathOption_PathIsDirCreate "<function>PathOption.PathIsDirCreate</function>">
+<!ENTITY PathOption_PathIsFile "<function>PathOption.PathIsFile</function>">
+<!ENTITY PathVariable "<function>PathVariable</function>">
+<!ENTITY PathVariable_PathAccept "<function>PathVariable.PathAccept</function>">
+<!ENTITY PathVariable_PathExists "<function>PathVariable.PathExists</function>">
+<!ENTITY PathVariable_PathIsDir "<function>PathVariable.PathIsDir</function>">
+<!ENTITY PathVariable_PathIsDirCreate "<function>PathVariable.PathIsDirCreate</function>">
+<!ENTITY PathVariable_PathIsFile "<function>PathVariable.PathIsFile</function>">
+<!ENTITY Precious "<function>Precious</function>">
+<!ENTITY Prepend "<function>Prepend</function>">
+<!ENTITY PrependENVPath "<function>PrependENVPath</function>">
+<!ENTITY PrependUnique "<function>PrependUnique</function>">
+<!ENTITY Progress "<function>Progress</function>">
+<!ENTITY Replace "<function>Replace</function>">
+<!ENTITY Repository "<function>Repository</function>">
+<!ENTITY Requires "<function>Requires</function>">
+<!ENTITY Return "<function>Return</function>">
+<!ENTITY RuleSet "<function>RuleSet</function>">
+<!ENTITY Salt "<function>Salt</function>">
+<!ENTITY SetBuildSignatureType "<function>SetBuildSignatureType</function>">
+<!ENTITY SetContentSignatureType "<function>SetContentSignatureType</function>">
+<!ENTITY SetDefault "<function>SetDefault</function>">
+<!ENTITY SetOption "<function>SetOption</function>">
+<!ENTITY SideEffect "<function>SideEffect</function>">
+<!ENTITY SourceSignature "<function>SourceSignature</function>">
+<!ENTITY SourceSignatures "<function>SourceSignatures</function>">
+<!ENTITY Split "<function>Split</function>">
+<!ENTITY Tag "<function>Tag</function>">
+<!ENTITY TargetSignatures "<function>TargetSignatures</function>">
+<!ENTITY Task "<function>Task</function>">
+<!ENTITY Touch "<function>Touch</function>">
+<!ENTITY UnknownOptions "<function>UnknownOptions</function>">
+<!ENTITY UnknownVariables "<function>UnknownVariables</function>">
+
+<!-- Environment methods -->
+<!ENTITY subst "<function>subst</function>">
+
+<!-- Configure context functions -->
+<!ENTITY Message "<function>Message</function>">
+<!ENTITY Result "<function>Result</function>">
+<!ENTITY CheckCHeader "<function>CheckCHeader</function>">
+<!ENTITY CheckCXXHeader "<function>CheckCXXHeader</function>">
+<!ENTITY CheckFunc "<function>CheckFunc</function>">
+<!ENTITY CheckHeader "<function>CheckHeader</function>">
+<!ENTITY CheckLib "<function>CheckLib</function>">
+<!ENTITY CheckLibWithHeader "<function>CheckLibWithHeader</function>">
+<!ENTITY CheckType "<function>CheckType</function>">
+<!ENTITY TryAction "<function>TryAction</function>">
+<!ENTITY TryBuild "<function>TryBuild</function>">
+<!ENTITY TryCompile "<function>TryCompile</function>">
+<!ENTITY TryLink "<function>TryLink</function>">
+<!ENTITY TryRun "<function>TryRun</function>">
+
+
+<!-- Python functions -->
+<!ENTITY str "<function>str</function>">
+<!ENTITY zipfile "<function>zipfile</function>">
+
+<!-- Obsolete, but referenced in old documents. -->
+<!ENTITY Cache "<function>Cache</function>">
+
+
+
+<!--
+
+ Global variables.
+
+-->
+
+<!ENTITY ARGLIST "<varname>ARGLIST</varname>">
+<!ENTITY ARGUMENTS "<varname>ARGUMENTS</varname>">
+<!ENTITY BUILD_TARGETS "<varname>BUILD_TARGETS</varname>">
+<!ENTITY COMMAND_LINE_TARGETS "<varname>COMMAND_LINE_TARGETS</varname>">
+<!ENTITY DEFAULT_TARGETS "<varname>DEFAULT_TARGETS</varname>">
+
+
+
+<!--
+
+ Construction variables.
+
+-->
+
+<!ENTITY BUILDERMAP "<varname>BUILDERMAP</varname>">
+<!ENTITY COLOR "<varname>COLOR</varname>">
+<!ENTITY COLORS "<varname>COLORS</varname>">
+<!ENTITY CONFIG "<varname>CONFIG</varname>">
+<!ENTITY CPPDEFINES "<varname>CPPDEFINES</varname>">
+<!ENTITY RELEASE "<varname>RELEASE</varname>">
+<!ENTITY RELEASE_BUILD "<varname>RELEASE_BUILD</varname>">
+<!ENTITY SCANNERMAP "<varname>SCANNERMAP</varname>">
+<!ENTITY TARFLAGS "<varname>TARFLAGS</varname>">
+<!ENTITY TARSUFFIX "<varname>TARSUFFIX</varname>">
+
+
+
+<!--
+
+ Environment variables.
+
+-->
+
+<!ENTITY PATH "<varname>PATH</varname>">
+<!ENTITY PYTHONPATH "<varname>PYTHONPATH</varname>">
+<!ENTITY SCONSFLAGS "<varname>SCONSFLAGS</varname>">
+
+
+
+<!--
+
+ Function and method arguments.
+
+-->
+
+<!ENTITY allowed_values "<varname>allowed_values</varname>">
+<!ENTITY build_dir "<varname>build_dir</varname>">
+<!ENTITY map "<varname>map</varname>">
+<!ENTITY ignorecase "<varname>ignorecase</varname>">
+<!ENTITY options "<varname>options</varname>">
+<!ENTITY exports "<varname>exports</varname>">
+<!ENTITY source "<varname>source</varname>">
+<!ENTITY target "<varname>target</varname>">
+<!ENTITY variables "<varname>variables</varname>">
+<!ENTITY variant_dir "<varname>variant_dir</varname>">
+
+
+
+<!--
+
+ Values of function and method arguments.
+
+-->
+
+<!ENTITY all "<literal>all</literal>">
+<!ENTITY none "<literal>none</literal>">
+
+
+
+<!--
+
+ Builder and Scanner objects.
+
+-->
+
+<!ENTITY BuildDir "<function>BuildDir</function>">
+<!ENTITY CFile "<function>CFile</function>">
+<!ENTITY CXXFile "<function>CXXFile</function>">
+<!ENTITY DVI "<function>DVI</function>">
+<!ENTITY Jar "<function>Jar</function>">
+<!ENTITY Java "<function>Java</function>">
+<!ENTITY JavaH "<function>JavaH</function>">
+<!ENTITY Library "<function>Library</function>">
+<!ENTITY Object "<function>Object</function>">
+<!ENTITY PCH "<function>PCH</function>">
+<!ENTITY PDF "<function>PDF</function>">
+<!ENTITY PostScript "<function>PostScript</function>">
+<!ENTITY Program "<function>Program</function>">
+<!ENTITY RES "<function>RES</function>">
+<!ENTITY RMIC "<function>RMIC</function>">
+<!ENTITY SharedLibrary "<function>SharedLibrary</function>">
+<!ENTITY SharedObject "<function>SharedObject</function>">
+<!ENTITY StaticLibrary "<function>StaticLibrary</function>">
+<!ENTITY StaticObject "<function>StaticObject</function>">
+<!ENTITY Substfile "<function>Substfile</function>">
+<!ENTITY Tar "<function>Tar</function>">
+<!ENTITY Textfile "<function>Textfile</function>">
+<!ENTITY VariantDir "<function>VariantDir</function>">
+<!ENTITY Zip "<function>Zip</function>">
+
+<!-- Obsolete, but referenced in old documents. -->
+<!ENTITY MakeBuilder "<function>Make</function>">
+
+
+
+<!--
+
+ Terms. Define both singular and plural forms in various
+ case-sensitive combinations for use in titles, in-line, etc.
+
+-->
+
+<!ENTITY buildfunc "<literal>builder function</literal>">
+<!ENTITY build_action "<literal>build action</literal>">
+<!ENTITY build_actions "<literal>build actions</literal>">
+<!ENTITY builder_method "<literal>builder method</literal>">
+
+<!ENTITY Configure_Contexts "<literal>Configure Contexts</literal>">
+<!ENTITY configure_context "<literal>configure context</literal>">
+
+<!ENTITY ConsEnv "<literal>Construction Environment</literal>">
+<!ENTITY ConsEnvs "<literal>Construction Environments</literal>">
+<!ENTITY Consenv "<literal>Construction environment</literal>">
+<!ENTITY Consenvs "<literal>Construction environments</literal>">
+<!ENTITY consenv "<literal>construction environment</literal>">
+<!ENTITY consenvs "<literal>construction environments</literal>">
+
+<!ENTITY ConsVar "<literal>Construction Variable</literal>">
+<!ENTITY ConsVars "<literal>Construction Variables</literal>">
+<!ENTITY Consvar "<literal>Construction variable</literal>">
+<!ENTITY Consvars "<literal>Construction variables</literal>">
+<!ENTITY consvar "<literal>construction variable</literal>">
+<!ENTITY consvars "<literal>construction variables</literal>">
+
+<!ENTITY CPPPATH "<literal>CPPPATH</literal>">
+
+<!ENTITY Dictionary "<literal>Dictionary</literal>">
+
+<!ENTITY Emitter "<literal>Emitter</literal>">
+<!ENTITY emitter "<literal>emitter</literal>">
+
+<!ENTITY factory "<literal>factory</literal>">
+
+<!ENTITY Generator "<literal>Generator</literal>">
+<!ENTITY generator "<literal>generator</literal>">
+
+<!ENTITY Nodes "<literal>Nodes</literal>">
+
+<!ENTITY signature "<literal>signature</literal>">
+<!ENTITY buildsignature "<literal>build signature</literal>">
+
+<!ENTITY true "<literal>true</literal>">
+<!ENTITY false "<literal>false</literal>">
+
+<!ENTITY typedef "<literal>typedef</literal>">
+
+<!--
+
+ Python keyword arguments
+
+-->
+
+<!ENTITY action "<literal>action=</literal>">
+<!ENTITY batch_key "<literal>batch_key=</literal>">
+<!ENTITY cmdstr "<literal>cmdstr=</literal>">
+<!ENTITY exitstatfunc "<literal>exitstatfunc=</literal>">
+<!ENTITY strfunction "<literal>strfunction=</literal>">
+<!ENTITY varlist "<literal>varlist=</literal>">
+
+<!--
+
+ File and program names used in examples.
+
+-->
+
+<!ENTITY bar "<filename>bar</filename>">
+<!ENTITY common1_c "<filename>common1.c</filename>">
+<!ENTITY common2_c "<filename>common2.c</filename>">
+<!ENTITY custom_py "<filename>custom.py</filename>">
+<!ENTITY goodbye "<filename>goodbye</filename>">
+<!ENTITY goodbye_o "<filename>goodbye.o</filename>">
+<!ENTITY goodbye_obj "<filename>goodbye.obj</filename>">
+<!ENTITY file_dll "<filename>file.dll</filename>">
+<!ENTITY file_in "<filename>file.in</filename>">
+<!ENTITY file_lib "<filename>file.lib</filename>">
+<!ENTITY file_o "<filename>file.o</filename>">
+<!ENTITY file_obj "<filename>file.obj</filename>">
+<!ENTITY file_out "<filename>file.out</filename>">
+<!ENTITY foo "<filename>foo</filename>">
+<!ENTITY foo_o "<filename>foo.o</filename>">
+<!ENTITY foo_obj "<filename>foo.obj</filename>">
+<!ENTITY hello "<filename>hello</filename>">
+<!ENTITY hello_c "<filename>hello.c</filename>">
+<!ENTITY hello_exe "<filename>hello.exe</filename>">
+<!ENTITY hello_h "<filename>hello.h</filename>">
+<!ENTITY hello_o "<filename>hello.o</filename>">
+<!ENTITY hello_obj "<filename>hello.obj</filename>">
+<!ENTITY libfile_a "<filename>libfile_a</filename>">
+<!ENTITY libfile_so "<filename>libfile_so</filename>">
+<!ENTITY new_hello "<filename>new_hello</filename>">
+<!ENTITY new_hello_exe "<filename>new_hello.exe</filename>">
+<!ENTITY prog "<filename>prog</filename>">
+<!ENTITY prog1 "<filename>prog1</filename>">
+<!ENTITY prog2 "<filename>prog2</filename>">
+<!ENTITY prog_c "<filename>prog.c</filename>">
+<!ENTITY prog_exe "<filename>prog.exe</filename>">
+<!ENTITY stdio_h "<filename>stdio.h</filename>">
+
+<!--
+
+ Punctuation.
+
+-->
+
+<!ENTITY plus "<literal>+</literal>">
+<!ENTITY hash "<literal>#</literal>">
+
+<!--
+
+ Mailing lists
+
+-->
+
+<!ENTITY scons-announce "<literal>announce@scons.tigris.org</literal>">
+<!ENTITY scons-devel "<literal>dev@scons.tigris.org</literal>">
+<!ENTITY scons-users "<literal>users@scons.tigris.org</literal>">
diff --git a/doc/user/MANIFEST b/doc/user/MANIFEST
new file mode 100644
index 0000000..ef273d3
--- /dev/null
+++ b/doc/user/MANIFEST
@@ -0,0 +1,50 @@
+actions.xml
+add-method.xml
+alias.xml
+ant.xml
+builders.xml
+builders-built-in.xml
+builders-commands.xml
+builders-writing.xml
+build-install.xml
+caching.xml
+command-line.xml
+cons.pl
+copyright.xml
+depends.xml
+environments.xml
+errors.xml
+example.xml
+factories.xml
+file-removal.xml
+hierarchy.xml
+install.xml
+java.xml
+libraries.xml
+less-simple.xml
+main.xml
+make.xml
+mergeflags.xml
+misc.xml
+nodes.xml
+output.xml
+parseconfig.xml
+parseflags.xml
+preface.xml
+python.xml
+repositories.xml
+run.xml
+scanners.xml
+sconf.xml
+separate.xml
+simple.xml
+sourcecode.xml
+tasks.xml
+tools.xml
+troubleshoot.xml
+variants.xml
+variables.xml
+SCons-win32-install-1.jpg
+SCons-win32-install-2.jpg
+SCons-win32-install-3.jpg
+SCons-win32-install-4.jpg
diff --git a/doc/user/README b/doc/user/README
new file mode 100644
index 0000000..aef479a
--- /dev/null
+++ b/doc/user/README
@@ -0,0 +1,21 @@
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+When adding a new file, add it to main.xml and MANIFEST.
+
+To build the .xml files from the .in files:
+ scons -D BUILDDOC=1 foo.xml
+To build the whole PDF doc from this dir, for testing:
+ scons -D ../../build/doc/PDF/scons-user.pdf
+
+Writing examples: here's a simple template.
+
+ <scons_example name="Foo">
+ <file name="SConstruct">
+ env = Environment()
+ print env.Dump("CC")
+ </file>
+ </scons_example>
+
+ <scons_output example="Foo">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
diff --git a/doc/user/SCons-win32-install-1.jpg b/doc/user/SCons-win32-install-1.jpg
new file mode 100644
index 0000000..ecc439d
--- /dev/null
+++ b/doc/user/SCons-win32-install-1.jpg
Binary files differ
diff --git a/doc/user/SCons-win32-install-2.jpg b/doc/user/SCons-win32-install-2.jpg
new file mode 100644
index 0000000..f468526
--- /dev/null
+++ b/doc/user/SCons-win32-install-2.jpg
Binary files differ
diff --git a/doc/user/SCons-win32-install-3.jpg b/doc/user/SCons-win32-install-3.jpg
new file mode 100644
index 0000000..90d2ed4
--- /dev/null
+++ b/doc/user/SCons-win32-install-3.jpg
Binary files differ
diff --git a/doc/user/SCons-win32-install-4.jpg b/doc/user/SCons-win32-install-4.jpg
new file mode 100644
index 0000000..d37973b
--- /dev/null
+++ b/doc/user/SCons-win32-install-4.jpg
Binary files differ
diff --git a/doc/user/actions.in b/doc/user/actions.in
new file mode 100644
index 0000000..1ea5c49
--- /dev/null
+++ b/doc/user/actions.in
@@ -0,0 +1,404 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Build actions
+
+Cons supports several types of B<build actions> that can be performed
+to construct one or more target files. Usually, a build action is
+a construction command, that is, a command-line string that invokes
+an external command. Cons can also execute Perl code embedded in a
+command-line string, and even supports an experimental ability to build
+a target file by executing a Perl code reference directly.
+
+A build action is usually specified as the value of a construction
+variable:
+
+ $env = new cons(
+ CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
+ LINKCOM => '[perl] &link_executable("%>", "%<")',
+ ARCOM => sub { my($env, $target, @sources) = @_;
+ # code to create an archive
+ }
+ );
+
+A build action may be associated directly with one or more target files
+via the C<Command> method; see below.
+
+=head2 Construction commands
+
+A construction command goes through expansion of construction variables
+and C<%-> pseudo-variables, as described above, to create the actual
+command line that Cons will execute to generate the target file or
+files.
+
+After substitution occurs, strings of white space are converted into
+single blanks, and leading and trailing white space is eliminated. It
+is therefore currently not possible to introduce variable length white
+space in strings passed into a command.
+
+If a multi-line command string is provided, the commands are executed
+sequentially. If any of the commands fails, then none of the rest are
+executed, and the target is not marked as updated, i.e. a new signature is
+not stored for the target.
+
+Normally, if all the commands succeed, and return a zero status (or whatever
+platform-specific indication of success is required), then a new signature
+is stored for the target. If a command erroneously reports success even
+after a failure, then Cons will assume that the target file created by that
+command is accurate and up-to-date.
+
+The first word of each command string, after expansion, is assumed to be an
+executable command looked up on the C<PATH> environment variable (which is,
+in turn, specified by the C<ENV> construction variable). If this command is
+found on the path, then the target will depend upon it: the command will
+therefore be automatically built, as necessary. It's possible to write
+multi-part commands to some shells, separated by semi-colons. Only the first
+command word will be depended upon, however, so if you write your command
+strings this way, you must either explicitly set up a dependency (with the
+C<Depends> method), or be sure that the command you are using is a system
+command which is expected to be available. If it isn't available, you will,
+of course, get an error.
+
+Cons normally prints a command before executing it. This behavior is
+suppressed if the first character of the command is C<@>. Note that
+you may need to separate the C<@> from the command name or escape it to
+prevent C<@cmd> from looking like an array to Perl quote operators that
+perform interpolation:
+
+ # The first command line is incorrect,
+ # because "@cp" looks like an array
+ # to the Perl qq// function.
+ # Use the second form instead.
+ Command $env 'foo', 'foo.in', qq(
+ @cp %< tempfile
+ @ cp tempfile %>
+ );
+
+If there are shell meta characters anywhere in the expanded command line,
+such as C<E<lt>>, C<E<gt>>, quotes, or semi-colon, then the command
+will actually be executed by invoking a shell. This means that a command
+such as:
+
+ cd foo
+
+alone will typically fail, since there is no command C<cd> on the path. But
+the command string:
+
+ cd $<:d; tar cf $>:f $<:f
+
+when expanded will still contain the shell meta character semi-colon, and a
+shell will be invoked to interpret the command. Since C<cd> is interpreted
+by this sub-shell, the command will execute as expected.
+
+=head2 Perl expressions
+
+If any command (even one within a multi-line command) begins with
+C<[perl]>, the remainder of that command line will be evaluated by the
+running Perl instead of being forked by the shell. If an error occurs
+in parsing the Perl code, or if the Perl expression returns 0 or undef,
+the command will be considered to have failed. For example, here is a
+simple command which creates a file C<foo> directly from Perl:
+
+ $env = new cons();
+ Command $env 'foo',
+ qq([perl] open(FOO,'>foo');print FOO "hi\\n"; close(FOO); 1);
+
+Note that when the command is executed, you are in the same package as
+when the F<Construct> or F<Conscript> file was read, so you can call
+Perl functions you've defined in the same F<Construct> or F<Conscript>
+file in which the C<Command> appears:
+
+ $env = new cons();
+ sub create_file {
+ my $file = shift;
+ open(FILE, ">$file");
+ print FILE "hi\n";
+ close(FILE);
+ return 1;
+ }
+ Command $env 'foo', "[perl] &create_file('%>')";
+
+The Perl string will be used to generate the signature for the derived
+file, so if you change the string, the file will be rebuilt. The contents
+of any subroutines you call, however, are not part of the signature,
+so if you modify a called subroutine such as C<create_file> above,
+the target will I<not> be rebuilt. Caveat user.
+
+=head2 Perl code references [EXPERIMENTAL]
+
+Cons supports the ability to create a derived file by directly executing
+a Perl code reference. This feature is considered EXPERIMENTAL and
+subject to change in the future.
+
+A code reference may either be a named subroutine referenced by the
+usual C<\&> syntax:
+
+ sub build_output {
+ my($env, $target, @sources) = @_;
+ print "build_output building $target\n";
+ open(OUT, ">$target");
+ foreach $src (@sources) {
+ if (! open(IN, "<$src")) {
+ print STDERR "cannot open '$src': $!\n";
+ return undef;
+ }
+ print OUT, <IN>;
+ }
+ close(OUT);
+ return 1;
+ }
+ Command $env 'output', \&build_output;
+
+or the code reference may be an anonymous subroutine:
+
+ Command $env 'output', sub {
+ my($env, $target, @sources) = @_;
+ print "building $target\n";
+ open(FILE, ">$target");
+ print FILE "hello\n";
+ close(FILE);
+ return 1;
+ };
+
+To build the target file, the referenced subroutine is passed, in order:
+the construction environment used to generate the target; the path
+name of the target itself; and the path names of all the source files
+necessary to build the target file.
+
+The code reference is expected to generate the target file, of course,
+but may manipulate the source and target files in any way it chooses.
+The code reference must return a false value (C<undef> or C<0>) if
+the build of the file failed. Any true value indicates a successful
+build of the target.
+
+Building target files using code references is considered EXPERIMENTAL
+due to the following current limitations:
+
+=over 4
+
+Cons does I<not> print anything to indicate the code reference is being
+called to build the file. The only way to give the user any indication
+is to have the code reference explicitly print some sort of "building"
+message, as in the above examples.
+
+Cons does not generate any signatures for code references, so if the
+code in the reference changes, the target will I<not> be rebuilt.
+
+Cons has no public method to allow a code reference to extract
+construction variables. This would be good to allow generalization of
+code references based on the current construction environment, but would
+also complicate the problem of generating meaningful signatures for code
+references.
+
+=back
+
+Support for building targets via code references has been released in
+this version to encourage experimentation and the seeking of possible
+solutions to the above limitations.
+
+-->
+
+ <para>
+
+ &SCons; supports several types of &build_actions;
+ that can be performed to build one or more target files.
+ Usually, a &build_action; is a command-line string
+ that invokes an external command.
+ A build action can also be an external command
+ specified as a list of arguments,
+ or even a Python function.
+
+ </para>
+
+ <para>
+
+ Build action objects are created by the &Action; function.
+ This function is, in fact, what &SCons; uses
+ to interpret the &action;
+ keyword argument when you call the &Builder; function.
+ So the following line that creates a simple Builder:
+
+ </para>
+
+ <sconstruct>
+ b = Builder(action = 'build < $SOURCE > $TARGET')
+ </sconstruct>
+
+ <para>
+
+ Is equivalent to:
+
+ </para>
+
+ <sconstruct>
+ b = Builder(action = Action('build < $SOURCE > $TARGET'))
+ </sconstruct>
+
+ <para>
+
+ The advantage of using the &Action; function directly
+ is that it can take a number of additional options
+ to modify the action's behavior in many useful ways.
+
+ </para>
+
+ <section>
+ <title>Command Strings as Actions</title>
+
+ <section>
+ <title>Suppressing Command-Line Printing</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Ignoring Exit Status</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Argument Lists as Actions</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Python Functions as Actions</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Modifying How an Action is Printed</title>
+
+ <section>
+ <title>XXX: the &strfunction; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>XXX: the &cmdstr; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Making an Action Depend on Variable Contents: the &varlist; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>chdir=1</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Batch Building of Multiple Targets from Separate Sources: the &batch_key; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Manipulating the Exit Status of an Action: the &exitstatfunc; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <!--
+
+ ???
+
+ <section>
+ <title>presub=</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/actions.xml b/doc/user/actions.xml
new file mode 100644
index 0000000..c3b8cf9
--- /dev/null
+++ b/doc/user/actions.xml
@@ -0,0 +1,404 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Build actions
+
+Cons supports several types of B<build actions> that can be performed
+to construct one or more target files. Usually, a build action is
+a construction command, that is, a command-line string that invokes
+an external command. Cons can also execute Perl code embedded in a
+command-line string, and even supports an experimental ability to build
+a target file by executing a Perl code reference directly.
+
+A build action is usually specified as the value of a construction
+variable:
+
+ $env = new cons(
+ CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
+ LINKCOM => '[perl] &link_executable("%>", "%<")',
+ ARCOM => sub { my($env, $target, @sources) = @_;
+ # code to create an archive
+ }
+ );
+
+A build action may be associated directly with one or more target files
+via the C<Command> method; see below.
+
+=head2 Construction commands
+
+A construction command goes through expansion of construction variables
+and C<%-> pseudo-variables, as described above, to create the actual
+command line that Cons will execute to generate the target file or
+files.
+
+After substitution occurs, strings of white space are converted into
+single blanks, and leading and trailing white space is eliminated. It
+is therefore currently not possible to introduce variable length white
+space in strings passed into a command.
+
+If a multi-line command string is provided, the commands are executed
+sequentially. If any of the commands fails, then none of the rest are
+executed, and the target is not marked as updated, i.e. a new signature is
+not stored for the target.
+
+Normally, if all the commands succeed, and return a zero status (or whatever
+platform-specific indication of success is required), then a new signature
+is stored for the target. If a command erroneously reports success even
+after a failure, then Cons will assume that the target file created by that
+command is accurate and up-to-date.
+
+The first word of each command string, after expansion, is assumed to be an
+executable command looked up on the C<PATH> environment variable (which is,
+in turn, specified by the C<ENV> construction variable). If this command is
+found on the path, then the target will depend upon it: the command will
+therefore be automatically built, as necessary. It's possible to write
+multi-part commands to some shells, separated by semi-colons. Only the first
+command word will be depended upon, however, so if you write your command
+strings this way, you must either explicitly set up a dependency (with the
+C<Depends> method), or be sure that the command you are using is a system
+command which is expected to be available. If it isn't available, you will,
+of course, get an error.
+
+Cons normally prints a command before executing it. This behavior is
+suppressed if the first character of the command is C<@>. Note that
+you may need to separate the C<@> from the command name or escape it to
+prevent C<@cmd> from looking like an array to Perl quote operators that
+perform interpolation:
+
+ # The first command line is incorrect,
+ # because "@cp" looks like an array
+ # to the Perl qq// function.
+ # Use the second form instead.
+ Command $env 'foo', 'foo.in', qq(
+ @cp %< tempfile
+ @ cp tempfile %>
+ );
+
+If there are shell meta characters anywhere in the expanded command line,
+such as C<E<lt>>, C<E<gt>>, quotes, or semi-colon, then the command
+will actually be executed by invoking a shell. This means that a command
+such as:
+
+ cd foo
+
+alone will typically fail, since there is no command C<cd> on the path. But
+the command string:
+
+ cd $<:d; tar cf $>:f $<:f
+
+when expanded will still contain the shell meta character semi-colon, and a
+shell will be invoked to interpret the command. Since C<cd> is interpreted
+by this sub-shell, the command will execute as expected.
+
+=head2 Perl expressions
+
+If any command (even one within a multi-line command) begins with
+C<[perl]>, the remainder of that command line will be evaluated by the
+running Perl instead of being forked by the shell. If an error occurs
+in parsing the Perl code, or if the Perl expression returns 0 or undef,
+the command will be considered to have failed. For example, here is a
+simple command which creates a file C<foo> directly from Perl:
+
+ $env = new cons();
+ Command $env 'foo',
+ qq([perl] open(FOO,'>foo');print FOO "hi\\n"; close(FOO); 1);
+
+Note that when the command is executed, you are in the same package as
+when the F<Construct> or F<Conscript> file was read, so you can call
+Perl functions you've defined in the same F<Construct> or F<Conscript>
+file in which the C<Command> appears:
+
+ $env = new cons();
+ sub create_file {
+ my $file = shift;
+ open(FILE, ">$file");
+ print FILE "hi\n";
+ close(FILE);
+ return 1;
+ }
+ Command $env 'foo', "[perl] &create_file('%>')";
+
+The Perl string will be used to generate the signature for the derived
+file, so if you change the string, the file will be rebuilt. The contents
+of any subroutines you call, however, are not part of the signature,
+so if you modify a called subroutine such as C<create_file> above,
+the target will I<not> be rebuilt. Caveat user.
+
+=head2 Perl code references [EXPERIMENTAL]
+
+Cons supports the ability to create a derived file by directly executing
+a Perl code reference. This feature is considered EXPERIMENTAL and
+subject to change in the future.
+
+A code reference may either be a named subroutine referenced by the
+usual C<\&> syntax:
+
+ sub build_output {
+ my($env, $target, @sources) = @_;
+ print "build_output building $target\n";
+ open(OUT, ">$target");
+ foreach $src (@sources) {
+ if (! open(IN, "<$src")) {
+ print STDERR "cannot open '$src': $!\n";
+ return undef;
+ }
+ print OUT, <IN>;
+ }
+ close(OUT);
+ return 1;
+ }
+ Command $env 'output', \&build_output;
+
+or the code reference may be an anonymous subroutine:
+
+ Command $env 'output', sub {
+ my($env, $target, @sources) = @_;
+ print "building $target\n";
+ open(FILE, ">$target");
+ print FILE "hello\n";
+ close(FILE);
+ return 1;
+ };
+
+To build the target file, the referenced subroutine is passed, in order:
+the construction environment used to generate the target; the path
+name of the target itself; and the path names of all the source files
+necessary to build the target file.
+
+The code reference is expected to generate the target file, of course,
+but may manipulate the source and target files in any way it chooses.
+The code reference must return a false value (C<undef> or C<0>) if
+the build of the file failed. Any true value indicates a successful
+build of the target.
+
+Building target files using code references is considered EXPERIMENTAL
+due to the following current limitations:
+
+=over 4
+
+Cons does I<not> print anything to indicate the code reference is being
+called to build the file. The only way to give the user any indication
+is to have the code reference explicitly print some sort of "building"
+message, as in the above examples.
+
+Cons does not generate any signatures for code references, so if the
+code in the reference changes, the target will I<not> be rebuilt.
+
+Cons has no public method to allow a code reference to extract
+construction variables. This would be good to allow generalization of
+code references based on the current construction environment, but would
+also complicate the problem of generating meaningful signatures for code
+references.
+
+=back
+
+Support for building targets via code references has been released in
+this version to encourage experimentation and the seeking of possible
+solutions to the above limitations.
+
+-->
+
+ <para>
+
+ &SCons; supports several types of &build_actions;
+ that can be performed to build one or more target files.
+ Usually, a &build_action; is a command-line string
+ that invokes an external command.
+ A build action can also be an external command
+ specified as a list of arguments,
+ or even a Python function.
+
+ </para>
+
+ <para>
+
+ Build action objects are created by the &Action; function.
+ This function is, in fact, what &SCons; uses
+ to interpret the &action;
+ keyword argument when you call the &Builder; function.
+ So the following line that creates a simple Builder:
+
+ </para>
+
+ <programlisting>
+ b = Builder(action = 'build < $SOURCE > $TARGET')
+ </programlisting>
+
+ <para>
+
+ Is equivalent to:
+
+ </para>
+
+ <programlisting>
+ b = Builder(action = Action('build < $SOURCE > $TARGET'))
+ </programlisting>
+
+ <para>
+
+ The advantage of using the &Action; function directly
+ is that it can take a number of additional options
+ to modify the action's behavior in many useful ways.
+
+ </para>
+
+ <section>
+ <title>Command Strings as Actions</title>
+
+ <section>
+ <title>Suppressing Command-Line Printing</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Ignoring Exit Status</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Argument Lists as Actions</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Python Functions as Actions</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Modifying How an Action is Printed</title>
+
+ <section>
+ <title>XXX: the &strfunction; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>XXX: the &cmdstr; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Making an Action Depend on Variable Contents: the &varlist; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>chdir=1</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Batch Building of Multiple Targets from Separate Sources: the &batch_key; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Manipulating the Exit Status of an Action: the &exitstatfunc; keyword argument</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <!--
+
+ ???
+
+ <section>
+ <title>presub=</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/add-method.in b/doc/user/add-method.in
new file mode 100644
index 0000000..61f13cc
--- /dev/null
+++ b/doc/user/add-method.in
@@ -0,0 +1,127 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ The &AddMethod; function is used to add a method
+ to an environment. It's typically used to add a "pseudo-builder,"
+ a function that looks like a &Builder; but
+ wraps up calls to multiple other &Builder;s
+ or otherwise processes its arguments
+ before calling one or more &Builder;s.
+ In the following example,
+ we want to install the program into the standard
+ <filename>/usr/bin</filename> directory hierarchy,
+ but also copy it into a local <filename>install/bin</filename>
+ directory from which a package might be built:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ def install_in_bin_dirs(env, source):
+ """Install source in both bin dirs"""
+ i1 = env.Install("$BIN", source)
+ i2 = env.Install("$LOCALBIN", source)
+ return [i1[0], i2[0]] # Return a list, like a normal builder
+ env = Environment(BIN='__ROOT__/usr/bin', LOCALBIN='#install/bin')
+ env.AddMethod(install_in_bin_dirs, "InstallInBinDirs")
+ env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+ This produces the following:
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q /</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ As mentioned, a psuedo-builder also provides more flexibility
+ in parsing arguments than you can get with a &Builder;.
+ The next example shows a pseudo-builder with a
+ named argument that modifies the filename, and a separate argument
+ for the resource file (rather than having the builder figure it out
+ by file extension). This example also demonstrates using the global
+ &AddMethod; function to add a method to the global Environment class,
+ so it will be used in all subsequently created environments.
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ def BuildTestProg(env, testfile, resourcefile, testdir="tests"):
+ """Build the test program;
+ prepends "test_" to src and target,
+ and puts target into testdir."""
+ srcfile = "test_%s.c" % testfile
+ target = "%s/test_%s" % (testdir, testfile)
+ if env['PLATFORM'] == 'win32':
+ resfile = env.RES(resourcefile)
+ p = env.Program(target, [srcfile, resfile])
+ else:
+ p = env.Program(target, srcfile)
+ return p
+ AddMethod(Environment, BuildTestProg)
+
+ env = Environment()
+ env.BuildTestProg('stuff', resourcefile='res.rc')
+ </file>
+ <file name="test_stuff.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="res.rc">
+ res.rc
+ </file>
+ </scons_example>
+
+ <para>
+ This produces the following on Linux:
+ </para>
+
+ <scons_output example="ex2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+ And the following on Windows:
+ </para>
+
+ <scons_output example="ex2" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+ Using &AddMethod; is better than just adding an instance method
+ to a &consenv; because it gets called as a proper method,
+ and because &AddMethod; provides for copying the method
+ to any clones of the &consenv; instance.
+ </para>
diff --git a/doc/user/add-method.xml b/doc/user/add-method.xml
new file mode 100644
index 0000000..761765f
--- /dev/null
+++ b/doc/user/add-method.xml
@@ -0,0 +1,135 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ The &AddMethod; function is used to add a method
+ to an environment. It's typically used to add a "pseudo-builder,"
+ a function that looks like a &Builder; but
+ wraps up calls to multiple other &Builder;s
+ or otherwise processes its arguments
+ before calling one or more &Builder;s.
+ In the following example,
+ we want to install the program into the standard
+ <filename>/usr/bin</filename> directory hierarchy,
+ but also copy it into a local <filename>install/bin</filename>
+ directory from which a package might be built:
+
+ </para>
+
+ <programlisting>
+ def install_in_bin_dirs(env, source):
+ """Install source in both bin dirs"""
+ i1 = env.Install("$BIN", source)
+ i2 = env.Install("$LOCALBIN", source)
+ return [i1[0], i2[0]] # Return a list, like a normal builder
+ env = Environment(BIN='/usr/bin', LOCALBIN='#install/bin')
+ env.AddMethod(install_in_bin_dirs, "InstallInBinDirs")
+ env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs
+ </programlisting>
+
+ <para>
+ This produces the following:
+ </para>
+
+ <screen>
+ % <userinput>scons -Q /</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ Install file: "hello" as "/usr/bin/hello"
+ Install file: "hello" as "install/bin/hello"
+ </screen>
+
+ <para>
+
+ As mentioned, a psuedo-builder also provides more flexibility
+ in parsing arguments than you can get with a &Builder;.
+ The next example shows a pseudo-builder with a
+ named argument that modifies the filename, and a separate argument
+ for the resource file (rather than having the builder figure it out
+ by file extension). This example also demonstrates using the global
+ &AddMethod; function to add a method to the global Environment class,
+ so it will be used in all subsequently created environments.
+
+ </para>
+
+ <programlisting>
+ def BuildTestProg(env, testfile, resourcefile, testdir="tests"):
+ """Build the test program;
+ prepends "test_" to src and target,
+ and puts target into testdir."""
+ srcfile = "test_%s.c" % testfile
+ target = "%s/test_%s" % (testdir, testfile)
+ if env['PLATFORM'] == 'win32':
+ resfile = env.RES(resourcefile)
+ p = env.Program(target, [srcfile, resfile])
+ else:
+ p = env.Program(target, srcfile)
+ return p
+ AddMethod(Environment, BuildTestProg)
+
+ env = Environment()
+ env.BuildTestProg('stuff', resourcefile='res.rc')
+ </programlisting>
+
+ <para>
+ This produces the following on Linux:
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o test_stuff.o -c test_stuff.c
+ cc -o tests/test_stuff test_stuff.o
+ </screen>
+
+ <para>
+ And the following on Windows:
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ rc /fores.res res.rc
+ cl /Fotest_stuff.obj /c test_stuff.c /nologo
+ link /nologo /OUT:tests\test_stuff.exe test_stuff.obj res.res
+ </screen>
+
+ <para>
+ Using &AddMethod; is better than just adding an instance method
+ to a &consenv; because it gets called as a proper method,
+ and because &AddMethod; provides for copying the method
+ to any clones of the &consenv; instance.
+ </para>
diff --git a/doc/user/alias.in b/doc/user/alias.in
new file mode 100644
index 0000000..45a1534
--- /dev/null
+++ b/doc/user/alias.in
@@ -0,0 +1,102 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ We've already seen how you can use the &Alias;
+ function to create a target named <literal>install</literal>:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('__ROOT__/usr/bin', hello)
+ env.Alias('install', '__ROOT__/usr/bin')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ You can then use this alias on the command line
+ to tell &SCons; more naturally that you want to install files:
+
+ </para>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons -Q install</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Like other &Builder; methods, though,
+ the &Alias; method returns an object
+ representing the alias being built.
+ You can then use this object as input to anothother &Builder;.
+ This is especially useful if you use such an object
+ as input to another call to the &Alias; &Builder;,
+ allowing you to create a hierarchy
+ of nested aliases:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ p = env.Program('foo.c')
+ l = env.Library('bar.c')
+ env.Install('__ROOT__/usr/bin', p)
+ env.Install('__ROOT__/usr/lib', l)
+ ib = env.Alias('install-bin', '__ROOT__/usr/bin')
+ il = env.Alias('install-lib', '__ROOT__/usr/lib')
+ env.Alias('install', [ib, il])
+ </file>
+ <file name="foo.c">
+ int main() { printf("foo.c\n"); }
+ </file>
+ <file name="bar.c">
+ void bar() { printf("bar.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ This example defines separate <literal>install</literal>,
+ <literal>install-bin</literal>,
+ and <literal>install-lib</literal> aliases,
+ allowing you finer control over what gets installed:
+
+ </para>
+
+ <scons_output example="ex2" os="posix">
+ <scons_output_command>scons -Q install-bin</scons_output_command>
+ <scons_output_command>scons -Q install-lib</scons_output_command>
+ <scons_output_command>scons -Q -c __ROOT__/</scons_output_command>
+ <scons_output_command>scons -Q install</scons_output_command>
+ </scons_output>
diff --git a/doc/user/alias.xml b/doc/user/alias.xml
new file mode 100644
index 0000000..04ebd5f
--- /dev/null
+++ b/doc/user/alias.xml
@@ -0,0 +1,112 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('/usr/bin', hello)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ You can then use this alias on the command line
+ to tell &SCons; more naturally that you want to install files:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q install</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ Install file: "hello" as "/usr/bin/hello"
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env = Environment()
+ p = env.Program('foo.c')
+ l = env.Library('bar.c')
+ env.Install('/usr/bin', p)
+ env.Install('/usr/lib', l)
+ ib = env.Alias('install-bin', '/usr/bin')
+ il = env.Alias('install-lib', '/usr/lib')
+ env.Alias('install', [ib, il])
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q install-bin</userinput>
+ cc -o foo.o -c foo.c
+ cc -o foo foo.o
+ Install file: "foo" as "/usr/bin/foo"
+ % <userinput>scons -Q install-lib</userinput>
+ cc -o bar.o -c bar.c
+ ar rc libbar.a bar.o
+ ranlib libbar.a
+ Install file: "libbar.a" as "/usr/lib/libbar.a"
+ % <userinput>scons -Q -c /</userinput>
+ Removed foo.o
+ Removed foo
+ Removed /usr/bin/foo
+ Removed bar.o
+ Removed libbar.a
+ Removed /usr/lib/libbar.a
+ % <userinput>scons -Q install</userinput>
+ cc -o foo.o -c foo.c
+ cc -o foo foo.o
+ Install file: "foo" as "/usr/bin/foo"
+ cc -o bar.o -c bar.c
+ ar rc libbar.a bar.o
+ ranlib libbar.a
+ Install file: "libbar.a" as "/usr/lib/libbar.a"
+ </screen>
diff --git a/doc/user/ant.in b/doc/user/ant.in
new file mode 100644
index 0000000..41b441d
--- /dev/null
+++ b/doc/user/ant.in
@@ -0,0 +1,52 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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/ant.xml b/doc/user/ant.xml
new file mode 100644
index 0000000..41b441d
--- /dev/null
+++ b/doc/user/ant.xml
@@ -0,0 +1,52 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <section>
+ <title>Differences Between &Ant; and &SCons;</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Advantages of &SCons; Over &Ant;</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
diff --git a/doc/user/build-install.in b/doc/user/build-install.in
new file mode 100644
index 0000000..ab289b1
--- /dev/null
+++ b/doc/user/build-install.in
@@ -0,0 +1,719 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ This chapter will take you through the basic steps
+ of installing &SCons; on your system,
+ and building &SCons; if you don't have a
+ pre-built package available
+ (or simply prefer the flexibility of building it yourself).
+ Before that, however, this chapter will also describe the basic steps
+ involved in installing Python on your system,
+ in case that is necessary.
+ Fortunately, both &SCons; and Python
+ are very easy to install on almost any system,
+ and Python already comes installed on many systems.
+
+ </para>
+
+ <!--
+
+ <para>
+
+ Lastly, this chapter also contains a section that
+ provides a brief overview of the Python programming language,
+ which is the language used to implement &SCons;,
+ and which forms the basis of the &SCons; configuration files.
+ Becoming familiar with some Python concepts will make it easier
+ to understand many of the examples in this User's Guide.
+ Nevertheless, it <emphasis>is</emphasis> possible
+ to configure simple &SCons; builds without knowing Python,
+ so you can skip this section if you
+ want to dive in and pick up things
+ by example- -or, of course, if you are
+ already familiar with Python.
+
+ </para>
+
+ -->
+
+ <section>
+ <title>Installing Python</title>
+
+ <para>
+
+ Because &SCons; is written in Python,
+ you must obviously have Python installed on your system
+ to use &SCons;.
+ Before you try to install Python,
+ you should check to see if Python is already
+ available on your system by typing
+ <userinput>python -V</userinput>
+ (capital 'V')
+ or
+ <userinput>python --version</userinput>
+ at your system's command-line prompt.
+
+ </para>
+
+ <screen>
+ $ <userinput>python -V</userinput>
+ Python 2.5.1
+ </screen>
+
+ <para>
+
+ And on a Windows system with Python installed:
+
+ </para>
+
+ <screen>
+ C:\><userinput>python -V</userinput>
+ Python 2.5.1
+ </screen>
+
+ <para>
+
+ If Python is not installed on your system,
+ you will see an error message
+ stating something like "command not found"
+ (on UNIX or Linux)
+ or "'python' is not recognized
+ as an internal or external command, operable progam or batch file"
+ (on Windows).
+ In that case, you need to install Python
+ before you can install &SCons;.
+
+ </para>
+
+ <para>
+
+ (Note that the <option>-V</option> option
+ was added to Python version 2.0,
+ so if your system only has an earlier version available
+ you may see an
+ <literal>"Unknown option: -V"</literal>
+ error message.)
+
+ </para>
+
+ <para>
+
+ The standard location for information
+ about downloading and installing Python is
+ <ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>.
+ See that page for information about
+ how to download and install Python on your system.
+
+ </para>
+
+ <para>
+
+ &SCons; will work with any version of Python from 1.5.2 or later.
+ If you need to install Python and have a choice,
+ we recommend using the most recent Python 2.5 version available.
+ Python 2.5 has significant improvements
+ that help speed up the performance of &SCons;.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; From Pre-Built Packages</title>
+
+ <para>
+
+ &SCons; comes pre-packaged for installation on a number of systems,
+ including Linux and Windows systems.
+ You do not need to read this entire section,
+ you should need to read only the section
+ appropriate to the type of system you're running on.
+
+ </para>
+
+ <section>
+ <title>Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems</title>
+
+ <para>
+
+ &SCons; comes in RPM (Red Hat Package Manager) format,
+ pre-built and ready to install on Red Hat Linux,
+ Fedora,
+ or any other Linux distribution that uses RPM.
+ Your distribution may
+ already have an &SCons; RPM built specifically for it;
+ many do, including SUSE, Mandrake and Fedora.
+ You can check for the availability of an &SCons; RPM
+ on your distribution's download servers,
+ or by consulting an RPM search site like
+ <ulink url="http://www.rpmfind.net/">http://www.rpmfind.net/</ulink> or
+ <ulink url="http://rpm.pbone.net/">http://rpm.pbone.net/</ulink>.
+
+ </para>
+
+ <para>
+
+ If your distribution supports installation via
+ <application>yum</application>,
+ you should be able to install &SCons; by running:
+
+ </para>
+
+ <screen>
+ # <userinput>yum install scons</userinput>
+ </screen>
+
+ <para>
+
+ If your Linux distribution does not already have
+ a specific &SCons; RPM file,
+ you can download and install from the
+ generic RPM provided by the &SCons; project.
+ This will install the
+ SCons script(s) in <filename>/usr/bin</filename>,
+ and the SCons library modules in
+ <filename>/usr/lib/scons</filename>.
+
+ </para>
+
+ <para>
+
+ To install from the command line, simply download the
+ appropriate <filename>.rpm</filename> file,
+ and then run:
+
+ </para>
+
+ <screen>
+ # <userinput>rpm -Uvh scons-1.2.0.d20091224-1.noarch.rpm</userinput>
+ </screen>
+
+ <para>
+
+ Or, you can use a graphical RPM package manager.
+ See your package manager application's documention
+ for specific instructions about
+ how to use it to install a downloaded RPM.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; on Debian Linux Systems</title>
+
+ <para>
+
+ Debian Linux systems use a different package management
+ format that also makes it very easy to install &SCons;.
+
+ </para>
+
+ <para>
+
+ If your system is connected to the Internet,
+ you can install the latest official Debian package
+ by running:
+
+ </para>
+
+ <screen>
+ # <userinput>apt-get install scons</userinput>
+ </screen>
+
+ <!--
+
+ <para>
+
+ Alternatively,
+ you can download the Debian package built
+ by the &SCons; project
+ and install it manually by running:
+
+ </para>
+
+ <screen>
+ # <userinput>db-XXX scons-*.deb</userinput>
+ </screen>
+
+ -->
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; on Windows Systems</title>
+
+ <para>
+
+ &SCons; provides a Windows installer
+ that makes installation extremely easy.
+ Download the <filename>scons-1.2.0.d20091224.win32.exe</filename>
+ file from the &SCons; download page at
+ <ulink url="http://www.scons.org/download.php">http://www.scons.org/download.php</ulink>.
+ Then all you need to do is execute the file
+ (usually by clicking on its icon in Windows Explorer).
+ These will take you through a small
+ sequence of windows that will install
+ &SCons; on your system.
+
+ <!--
+ Things are a little more complicated
+ if you are using the Cygwin version of Python.
+ This is because Cygwin
+ tries to make a Windows system look more
+ POSIX-like (or UNIX-like or Linux-like, if you prefer)
+ by having the Cygwin utilities,
+ including Cygwin Python,
+ interpret file name arguments on the command line
+ using the forward-slash (<filename>/</filename>)
+ as the directory separator,
+ instead of the normal Windows behavior of the
+ backslash (<filename>\</filename>) as the directory separator.
+ -->
+
+ </para>
+
+ <!--
+
+ <section>
+ <title>Installing &SCons; on Windows Systems Without Cygwin Python</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; on Windows Systems With Cygwin Python</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ -->
+
+ <!--
+
+ XXX - don't have the kinks worked out on how to
+ get these to display properly in all formats,
+ so comment them out for now.
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="SCons-win32-install-1.jpg" format="jpg" align="center">
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="SCons-win32-install-2.jpg" format="jpg" align="center">
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="SCons-win32-install-3.jpg" format="jpg" align="center">
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="SCons-win32-install-4.jpg" format="jpg" align="center">
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ -->
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Building and Installing &SCons; on Any System</title>
+
+ <para>
+
+ If a pre-built &SCons; package is not available for your system,
+ then you can still easily build and install &SCons; using the native
+ Python <filename>distutils</filename> package.
+
+ </para>
+
+ <para>
+
+ The first step is to download either the
+ <filename>scons-1.2.0.d20091224.tar.gz</filename>
+ or <filename>scons-1.2.0.d20091224.zip</filename>,
+ which are available from the SCons download page at
+ <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>.
+
+ </para>
+
+ <para>
+
+ Unpack the archive you downloaded,
+ using a utility like <application>tar</application>
+ on Linux or UNIX,
+ or <application>WinZip</application> on Windows.
+ This will create a directory called
+ <filename>scons-1.2.0.d20091224</filename>,
+ usually in your local directory.
+ Then change your working directory to that directory
+ and install &SCons; by executing the following commands:
+
+ </para>
+
+ <screen>
+ # <userinput>cd scons-1.2.0.d20091224</userinput>
+ # <userinput>python setup.py install</userinput>
+ </screen>
+
+ <para>
+
+ This will build &SCons;,
+ install the &scons; script
+ in the default system scripts directory
+ (<filename>/usr/local/bin</filename> or
+ <filename>C:\Python25\Scripts</filename>),
+ and will install the &SCons; build engine
+ in an appropriate stand-alone library directory
+ (<filename>/usr/local/lib/scons</filename> or
+ <filename>C:\Python25\scons</filename>).
+ Because these are system directories,
+ you may need root (on Linux or UNIX) or Administrator (on Windows)
+ privileges to install &SCons; like this.
+
+ </para>
+
+ <!--
+
+ <section>
+ <title>Building and Installing &SCons; in the Standard Python Library Directories</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>Building and Installing Multiple Versions of &SCons; Side-by-Side</title>
+
+ <para>
+
+ The &SCons; <filename>setup.py</filename> script
+ has some extensions that support
+ easy installation of multiple versions of &SCons;
+ in side-by-side locations.
+ This makes it easier to download and
+ experiment with different versions of &SCons;
+ before moving your official build process to a new version,
+ for example.
+
+ </para>
+
+ <para>
+
+ To install &SCons; in a version-specific location,
+ add the <option>--version-lib</option> option
+ when you call <filename>setup.py</filename>:
+
+ </para>
+
+ <screen>
+ # <userinput>python setup.py install --version-lib</userinput>
+ </screen>
+
+ <para>
+
+ This will install the &SCons; build engine
+ in the
+ <filename>/usr/lib/scons-1.2.0.d20091224</filename>
+ or
+ <filename>C:\Python25\scons-1.2.0.d20091224</filename>
+ directory, for example.
+
+ </para>
+
+ <para>
+
+ If you use the <option>--version-lib</option> option
+ the first time you install &SCons;,
+ you do not need to specify it each time you install
+ a new version.
+ The &SCons; <filename>setup.py</filename> script
+ will detect the version-specific directory name(s)
+ and assume you want to install all versions
+ in version-specific directories.
+ You can override that assumption in the future
+ by explicitly specifying the <option>--standalone-lib</option> option.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; in Other Locations</title>
+
+ <para>
+
+ You can install &SCons; in locations other than
+ the default by specifying the <option>--prefix=</option> option:
+
+ </para>
+
+ <screen>
+ # <userinput>python setup.py install --prefix=/opt/scons</userinput>
+ </screen>
+
+ <para>
+
+ This would
+ install the <application>scons</application> script in
+ <filename>/opt/scons/bin</filename>
+ and the build engine in
+ <filename>/opt/scons/lib/scons</filename>,
+
+ </para>
+
+ <para>
+
+ Note that you can specify both the <option>--prefix=</option>
+ and the <option>--version-lib</option> options
+ at the same type,
+ in which case <filename>setup.py</filename>
+ will install the build engine
+ in a version-specific directory
+ relative to the specified prefix.
+ Adding <option>--version-lib</option> to the
+ above example would install the build engine in
+ <filename>/opt/scons/lib/scons-1.2.0.d20091224</filename>.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building and Installing &SCons; Without Administrative Privileges</title>
+
+ <para>
+
+ If you don't have the right privileges to install &SCons;
+ in a system location,
+ simply use the <literal>--prefix=</literal> option
+ to install it in a location of your choosing.
+ For example,
+ to install &SCons; in appropriate locations
+ relative to the user's <literal>$HOME</literal> directory,
+ the &scons; script in
+ <filename>$HOME/bin</filename>
+ and the build engine in
+ <filename>$HOME/lib/scons</filename>,
+ simply type:
+
+ </para>
+
+ <screen>
+ $ <userinput>python setup.py install --prefix=$HOME</userinput>
+ </screen>
+
+ <para>
+
+ You may, of course, specify any other location you prefer,
+ and may use the <option>--version-lib</option> option
+ if you would like to install version-specific directories
+ relative to the specified prefix.
+
+ </para>
+
+ <para>
+
+ This can also be used to experiment with a newer
+ version of &SCons; than the one installed
+ in your system locations.
+ Of course, the location in which you install the
+ newer version of the &scons; script
+ (<filename>$HOME/bin</filename> in the above example)
+ must be configured in your &PATH; variable
+ before the directory containing
+ the system-installed version
+ of the &scons; script.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Python Basics</title>
+
+ <para>
+
+ This section will provide a brief overview of
+ the Python programming language.
+ Skip this section if you are already familiar with Python
+ (or you're really intent on diving into &SCons;
+ and just picking up things as you go).
+
+ </para>
+
+ <para>
+
+ Python has a lot of good
+ documentation freely available on-line
+ to help you get started.
+ The standard tutorial is available at XXX.
+
+
+ </para>
+
+ <para>
+
+ Python is very easy to pick up.
+
+ </para>
+
+ <para>
+
+ Python variables must be assigned to before they can be referenced.
+
+ </para>
+
+ <para>
+
+ Assignment is like most programming languages:
+
+ x = 1 + 2
+ z = 3 * x
+
+ </para>
+
+ <para>
+
+ Function calls look like most language function calls:
+
+ a = f(g)
+
+ </para>
+
+ <para>
+
+ Define functions like so:
+
+ def func(arg1, arg2):
+ return arg1 * arg 2
+
+ The number of parameters
+
+ </para>
+
+ <para>
+
+ Strings can be enclosed in single quotes or double quotes,
+ backslashes are used to escape characters,
+ triple-quote syntax lets you include quotes and newlines,
+ raw strings begin with 'r'.
+
+ </para>
+
+ <para>
+
+ Lists are enclosed in square brackets,
+ list items are separated by commas.
+ List references use square brackets and integer index values,
+ slice notation lets you select, delete or replace a range.
+
+ </para>
+
+ <para>
+
+ Dictionaries (hashes) are enclosed in curly brackets,
+ : separates keys from values,
+ , separates items.
+ Dictionary values are referenced using square brackets.
+
+ </para>
+
+ <para>
+
+ Access class attributes (including methods) using a '.'.
+
+ </para>
+
+ <para>
+
+ if: statements look like
+
+ elif: statements look like
+
+ else: statements look like
+
+ </para>
+
+ <para>
+
+ for: statements look like
+
+ while: statements look like
+
+ break statements look like
+
+ continue statements look like
+
+ </para>
+
+ <para>
+
+ pass
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/build-install.xml b/doc/user/build-install.xml
new file mode 100644
index 0000000..ab289b1
--- /dev/null
+++ b/doc/user/build-install.xml
@@ -0,0 +1,719 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ This chapter will take you through the basic steps
+ of installing &SCons; on your system,
+ and building &SCons; if you don't have a
+ pre-built package available
+ (or simply prefer the flexibility of building it yourself).
+ Before that, however, this chapter will also describe the basic steps
+ involved in installing Python on your system,
+ in case that is necessary.
+ Fortunately, both &SCons; and Python
+ are very easy to install on almost any system,
+ and Python already comes installed on many systems.
+
+ </para>
+
+ <!--
+
+ <para>
+
+ Lastly, this chapter also contains a section that
+ provides a brief overview of the Python programming language,
+ which is the language used to implement &SCons;,
+ and which forms the basis of the &SCons; configuration files.
+ Becoming familiar with some Python concepts will make it easier
+ to understand many of the examples in this User's Guide.
+ Nevertheless, it <emphasis>is</emphasis> possible
+ to configure simple &SCons; builds without knowing Python,
+ so you can skip this section if you
+ want to dive in and pick up things
+ by example- -or, of course, if you are
+ already familiar with Python.
+
+ </para>
+
+ -->
+
+ <section>
+ <title>Installing Python</title>
+
+ <para>
+
+ Because &SCons; is written in Python,
+ you must obviously have Python installed on your system
+ to use &SCons;.
+ Before you try to install Python,
+ you should check to see if Python is already
+ available on your system by typing
+ <userinput>python -V</userinput>
+ (capital 'V')
+ or
+ <userinput>python --version</userinput>
+ at your system's command-line prompt.
+
+ </para>
+
+ <screen>
+ $ <userinput>python -V</userinput>
+ Python 2.5.1
+ </screen>
+
+ <para>
+
+ And on a Windows system with Python installed:
+
+ </para>
+
+ <screen>
+ C:\><userinput>python -V</userinput>
+ Python 2.5.1
+ </screen>
+
+ <para>
+
+ If Python is not installed on your system,
+ you will see an error message
+ stating something like "command not found"
+ (on UNIX or Linux)
+ or "'python' is not recognized
+ as an internal or external command, operable progam or batch file"
+ (on Windows).
+ In that case, you need to install Python
+ before you can install &SCons;.
+
+ </para>
+
+ <para>
+
+ (Note that the <option>-V</option> option
+ was added to Python version 2.0,
+ so if your system only has an earlier version available
+ you may see an
+ <literal>"Unknown option: -V"</literal>
+ error message.)
+
+ </para>
+
+ <para>
+
+ The standard location for information
+ about downloading and installing Python is
+ <ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>.
+ See that page for information about
+ how to download and install Python on your system.
+
+ </para>
+
+ <para>
+
+ &SCons; will work with any version of Python from 1.5.2 or later.
+ If you need to install Python and have a choice,
+ we recommend using the most recent Python 2.5 version available.
+ Python 2.5 has significant improvements
+ that help speed up the performance of &SCons;.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; From Pre-Built Packages</title>
+
+ <para>
+
+ &SCons; comes pre-packaged for installation on a number of systems,
+ including Linux and Windows systems.
+ You do not need to read this entire section,
+ you should need to read only the section
+ appropriate to the type of system you're running on.
+
+ </para>
+
+ <section>
+ <title>Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems</title>
+
+ <para>
+
+ &SCons; comes in RPM (Red Hat Package Manager) format,
+ pre-built and ready to install on Red Hat Linux,
+ Fedora,
+ or any other Linux distribution that uses RPM.
+ Your distribution may
+ already have an &SCons; RPM built specifically for it;
+ many do, including SUSE, Mandrake and Fedora.
+ You can check for the availability of an &SCons; RPM
+ on your distribution's download servers,
+ or by consulting an RPM search site like
+ <ulink url="http://www.rpmfind.net/">http://www.rpmfind.net/</ulink> or
+ <ulink url="http://rpm.pbone.net/">http://rpm.pbone.net/</ulink>.
+
+ </para>
+
+ <para>
+
+ If your distribution supports installation via
+ <application>yum</application>,
+ you should be able to install &SCons; by running:
+
+ </para>
+
+ <screen>
+ # <userinput>yum install scons</userinput>
+ </screen>
+
+ <para>
+
+ If your Linux distribution does not already have
+ a specific &SCons; RPM file,
+ you can download and install from the
+ generic RPM provided by the &SCons; project.
+ This will install the
+ SCons script(s) in <filename>/usr/bin</filename>,
+ and the SCons library modules in
+ <filename>/usr/lib/scons</filename>.
+
+ </para>
+
+ <para>
+
+ To install from the command line, simply download the
+ appropriate <filename>.rpm</filename> file,
+ and then run:
+
+ </para>
+
+ <screen>
+ # <userinput>rpm -Uvh scons-1.2.0.d20091224-1.noarch.rpm</userinput>
+ </screen>
+
+ <para>
+
+ Or, you can use a graphical RPM package manager.
+ See your package manager application's documention
+ for specific instructions about
+ how to use it to install a downloaded RPM.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; on Debian Linux Systems</title>
+
+ <para>
+
+ Debian Linux systems use a different package management
+ format that also makes it very easy to install &SCons;.
+
+ </para>
+
+ <para>
+
+ If your system is connected to the Internet,
+ you can install the latest official Debian package
+ by running:
+
+ </para>
+
+ <screen>
+ # <userinput>apt-get install scons</userinput>
+ </screen>
+
+ <!--
+
+ <para>
+
+ Alternatively,
+ you can download the Debian package built
+ by the &SCons; project
+ and install it manually by running:
+
+ </para>
+
+ <screen>
+ # <userinput>db-XXX scons-*.deb</userinput>
+ </screen>
+
+ -->
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; on Windows Systems</title>
+
+ <para>
+
+ &SCons; provides a Windows installer
+ that makes installation extremely easy.
+ Download the <filename>scons-1.2.0.d20091224.win32.exe</filename>
+ file from the &SCons; download page at
+ <ulink url="http://www.scons.org/download.php">http://www.scons.org/download.php</ulink>.
+ Then all you need to do is execute the file
+ (usually by clicking on its icon in Windows Explorer).
+ These will take you through a small
+ sequence of windows that will install
+ &SCons; on your system.
+
+ <!--
+ Things are a little more complicated
+ if you are using the Cygwin version of Python.
+ This is because Cygwin
+ tries to make a Windows system look more
+ POSIX-like (or UNIX-like or Linux-like, if you prefer)
+ by having the Cygwin utilities,
+ including Cygwin Python,
+ interpret file name arguments on the command line
+ using the forward-slash (<filename>/</filename>)
+ as the directory separator,
+ instead of the normal Windows behavior of the
+ backslash (<filename>\</filename>) as the directory separator.
+ -->
+
+ </para>
+
+ <!--
+
+ <section>
+ <title>Installing &SCons; on Windows Systems Without Cygwin Python</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; on Windows Systems With Cygwin Python</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ -->
+
+ <!--
+
+ XXX - don't have the kinks worked out on how to
+ get these to display properly in all formats,
+ so comment them out for now.
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="SCons-win32-install-1.jpg" format="jpg" align="center">
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="SCons-win32-install-2.jpg" format="jpg" align="center">
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="SCons-win32-install-3.jpg" format="jpg" align="center">
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="SCons-win32-install-4.jpg" format="jpg" align="center">
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ -->
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Building and Installing &SCons; on Any System</title>
+
+ <para>
+
+ If a pre-built &SCons; package is not available for your system,
+ then you can still easily build and install &SCons; using the native
+ Python <filename>distutils</filename> package.
+
+ </para>
+
+ <para>
+
+ The first step is to download either the
+ <filename>scons-1.2.0.d20091224.tar.gz</filename>
+ or <filename>scons-1.2.0.d20091224.zip</filename>,
+ which are available from the SCons download page at
+ <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>.
+
+ </para>
+
+ <para>
+
+ Unpack the archive you downloaded,
+ using a utility like <application>tar</application>
+ on Linux or UNIX,
+ or <application>WinZip</application> on Windows.
+ This will create a directory called
+ <filename>scons-1.2.0.d20091224</filename>,
+ usually in your local directory.
+ Then change your working directory to that directory
+ and install &SCons; by executing the following commands:
+
+ </para>
+
+ <screen>
+ # <userinput>cd scons-1.2.0.d20091224</userinput>
+ # <userinput>python setup.py install</userinput>
+ </screen>
+
+ <para>
+
+ This will build &SCons;,
+ install the &scons; script
+ in the default system scripts directory
+ (<filename>/usr/local/bin</filename> or
+ <filename>C:\Python25\Scripts</filename>),
+ and will install the &SCons; build engine
+ in an appropriate stand-alone library directory
+ (<filename>/usr/local/lib/scons</filename> or
+ <filename>C:\Python25\scons</filename>).
+ Because these are system directories,
+ you may need root (on Linux or UNIX) or Administrator (on Windows)
+ privileges to install &SCons; like this.
+
+ </para>
+
+ <!--
+
+ <section>
+ <title>Building and Installing &SCons; in the Standard Python Library Directories</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>Building and Installing Multiple Versions of &SCons; Side-by-Side</title>
+
+ <para>
+
+ The &SCons; <filename>setup.py</filename> script
+ has some extensions that support
+ easy installation of multiple versions of &SCons;
+ in side-by-side locations.
+ This makes it easier to download and
+ experiment with different versions of &SCons;
+ before moving your official build process to a new version,
+ for example.
+
+ </para>
+
+ <para>
+
+ To install &SCons; in a version-specific location,
+ add the <option>--version-lib</option> option
+ when you call <filename>setup.py</filename>:
+
+ </para>
+
+ <screen>
+ # <userinput>python setup.py install --version-lib</userinput>
+ </screen>
+
+ <para>
+
+ This will install the &SCons; build engine
+ in the
+ <filename>/usr/lib/scons-1.2.0.d20091224</filename>
+ or
+ <filename>C:\Python25\scons-1.2.0.d20091224</filename>
+ directory, for example.
+
+ </para>
+
+ <para>
+
+ If you use the <option>--version-lib</option> option
+ the first time you install &SCons;,
+ you do not need to specify it each time you install
+ a new version.
+ The &SCons; <filename>setup.py</filename> script
+ will detect the version-specific directory name(s)
+ and assume you want to install all versions
+ in version-specific directories.
+ You can override that assumption in the future
+ by explicitly specifying the <option>--standalone-lib</option> option.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Installing &SCons; in Other Locations</title>
+
+ <para>
+
+ You can install &SCons; in locations other than
+ the default by specifying the <option>--prefix=</option> option:
+
+ </para>
+
+ <screen>
+ # <userinput>python setup.py install --prefix=/opt/scons</userinput>
+ </screen>
+
+ <para>
+
+ This would
+ install the <application>scons</application> script in
+ <filename>/opt/scons/bin</filename>
+ and the build engine in
+ <filename>/opt/scons/lib/scons</filename>,
+
+ </para>
+
+ <para>
+
+ Note that you can specify both the <option>--prefix=</option>
+ and the <option>--version-lib</option> options
+ at the same type,
+ in which case <filename>setup.py</filename>
+ will install the build engine
+ in a version-specific directory
+ relative to the specified prefix.
+ Adding <option>--version-lib</option> to the
+ above example would install the build engine in
+ <filename>/opt/scons/lib/scons-1.2.0.d20091224</filename>.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building and Installing &SCons; Without Administrative Privileges</title>
+
+ <para>
+
+ If you don't have the right privileges to install &SCons;
+ in a system location,
+ simply use the <literal>--prefix=</literal> option
+ to install it in a location of your choosing.
+ For example,
+ to install &SCons; in appropriate locations
+ relative to the user's <literal>$HOME</literal> directory,
+ the &scons; script in
+ <filename>$HOME/bin</filename>
+ and the build engine in
+ <filename>$HOME/lib/scons</filename>,
+ simply type:
+
+ </para>
+
+ <screen>
+ $ <userinput>python setup.py install --prefix=$HOME</userinput>
+ </screen>
+
+ <para>
+
+ You may, of course, specify any other location you prefer,
+ and may use the <option>--version-lib</option> option
+ if you would like to install version-specific directories
+ relative to the specified prefix.
+
+ </para>
+
+ <para>
+
+ This can also be used to experiment with a newer
+ version of &SCons; than the one installed
+ in your system locations.
+ Of course, the location in which you install the
+ newer version of the &scons; script
+ (<filename>$HOME/bin</filename> in the above example)
+ must be configured in your &PATH; variable
+ before the directory containing
+ the system-installed version
+ of the &scons; script.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Python Basics</title>
+
+ <para>
+
+ This section will provide a brief overview of
+ the Python programming language.
+ Skip this section if you are already familiar with Python
+ (or you're really intent on diving into &SCons;
+ and just picking up things as you go).
+
+ </para>
+
+ <para>
+
+ Python has a lot of good
+ documentation freely available on-line
+ to help you get started.
+ The standard tutorial is available at XXX.
+
+
+ </para>
+
+ <para>
+
+ Python is very easy to pick up.
+
+ </para>
+
+ <para>
+
+ Python variables must be assigned to before they can be referenced.
+
+ </para>
+
+ <para>
+
+ Assignment is like most programming languages:
+
+ x = 1 + 2
+ z = 3 * x
+
+ </para>
+
+ <para>
+
+ Function calls look like most language function calls:
+
+ a = f(g)
+
+ </para>
+
+ <para>
+
+ Define functions like so:
+
+ def func(arg1, arg2):
+ return arg1 * arg 2
+
+ The number of parameters
+
+ </para>
+
+ <para>
+
+ Strings can be enclosed in single quotes or double quotes,
+ backslashes are used to escape characters,
+ triple-quote syntax lets you include quotes and newlines,
+ raw strings begin with 'r'.
+
+ </para>
+
+ <para>
+
+ Lists are enclosed in square brackets,
+ list items are separated by commas.
+ List references use square brackets and integer index values,
+ slice notation lets you select, delete or replace a range.
+
+ </para>
+
+ <para>
+
+ Dictionaries (hashes) are enclosed in curly brackets,
+ : separates keys from values,
+ , separates items.
+ Dictionary values are referenced using square brackets.
+
+ </para>
+
+ <para>
+
+ Access class attributes (including methods) using a '.'.
+
+ </para>
+
+ <para>
+
+ if: statements look like
+
+ elif: statements look like
+
+ else: statements look like
+
+ </para>
+
+ <para>
+
+ for: statements look like
+
+ while: statements look like
+
+ break statements look like
+
+ continue statements look like
+
+ </para>
+
+ <para>
+
+ pass
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/builders-built-in.in b/doc/user/builders-built-in.in
new file mode 100644
index 0000000..245cb8c
--- /dev/null
+++ b/doc/user/builders-built-in.in
@@ -0,0 +1,963 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; provides the ability to build a lot of different
+ types of files right "out of the box."
+ So far, we've been using &SCons;' ability to build
+ programs, objects and libraries to
+ illustrate much of the underlying functionality of &SCons;
+ This section will describe all of the different
+ types of files that you can build with &SCons;,
+ and the built-in &Builder; objects used to build them.
+ By default, all of the &Builder; objects in this section
+ can be built either with or without an explicit
+ construction environment.
+
+ </para>
+
+ <section>
+ <title>Programs: the &Program; Builder</title>
+
+ <para>
+
+ As we've seen, the &b-link-Program; Builder
+ is used to build an executable program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the &target; argument is the
+ name of the executable program name to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ Program('prog', 'file1.o')
+ </programlisting>
+
+ <para>
+
+ Will create the &prog;
+ executable on a POSIX system,
+ the &prog_exe; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-PROGPREFIX;
+ and
+ &cv-link-PROGSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(PROGPREFIX='my', PROGSUFFIX='.xxx')
+ env.Program('prog', ['file1.o', 'file2.o'])
+ </programlisting>
+
+ <para>
+
+ Will create a program named
+ <filename>myprog.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ becomes the base of the target
+ program created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ Program(['hello.c', 'goodbye.c'])
+ </programlisting>
+
+ <para>
+
+ Will create the &hello;
+ executable on a POSIX system,
+ the &hello_exe; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ Two construction variables control what libraries
+ will be linked with the resulting program.
+ The &cv-link-LIBS; variable is a list of the names of
+ libraries that will be linked into any programs,
+ and the &cv-link-LIBPATH; variables is a list of
+ directories that will be searched for
+ the specified libraries.
+ &SCons; will construct the right command-line
+ options for the running system.
+ For example:
+
+ </para>
+
+ <scons_example name="libs">
+ <file name="SConstruct" printme="1">
+ env = Environment(LIBS = ['foo1', 'foo2'],
+ LIBPATH = ['/usr/dir1', 'dir2'])
+ env.Program(['hello.c', 'goodbye.c'])
+ </file>
+ <file name="hello.c">
+ int hello() { printf("Hello, world!\n"); }
+ </file>
+ <file name="goodbye.c">
+ int goodbye() { printf("Goodbye, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Will execute as follows on a POSIX system:
+
+ </para>
+
+ <scons_output example="libs" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And execute as follows on a Windows system:
+
+ </para>
+
+ <scons_output example="libs" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The &cv-LIBS; construction variable
+ is turned into command line options
+ by appending the &cv-link-LIBLINKPREFIX; and &cv-link-LIBLINKSUFFIX;
+ construction variables to the beginning and end,
+ respectively, of each specified library.
+
+ </para>
+
+ <para>
+
+ The &cv-LIBPATH; construction variable
+ is turned into command line options
+ by appending the &cv-link-LIBDIRPREFIX; and &cv-link-LIBDIRSUFFIX;
+ construction variables to the beginning and end,
+ respectively, of each specified library.
+
+ </para>
+
+ <para>
+
+ Other relevant construction variables
+ include those used by the &b-link-Object;
+ builders to affect how the
+ source files specified as input to the &t-Program;
+ builders are turned into object files;
+ see the next section.
+
+ </para>
+
+ <para>
+
+ The command line used to control how a program is linked
+ is specified by the &cv-link-LINKCOM; construction variable.
+ By default, it uses the
+ &cv-link-LINK; construction variable
+ and the &cv-link-LINKFLAGS; construction variable.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Object-File Builders</title>
+
+ <para>
+
+ &SCons; provides separate Builder objects
+ to create static and shared object files.
+ The distinction becomes especially important when
+ archiving object files into different types of libraries.
+
+ </para>
+
+ <section>
+ <title>The &StaticObject; Builder</title>
+
+ <para>
+
+ The &b-link-StaticObject; Builder
+ is used to build an object file
+ suitable for static linking into a program,
+ or for inclusion in a static library.
+ The &source; argument is a single source-code file,
+ and the &target; argument is the
+ name of the static object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ StaticObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create the &file_o;
+ object file on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-OBJPREFIX;
+ and
+ &cv-link-OBJSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(OBJPREFIX='my', OBJSUFFIX='.xxx')
+ env.StaticObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>myfile.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ beomces the base of the name
+ of the static object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ StaticObject('file.c')
+ </programlisting>
+
+ <para>
+
+ Will create the &file_o;
+ executable on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &SharedObject; Builder</title>
+
+ <para>
+
+ The &b-link-SharedObject; Builder
+ is used to build an object file
+ suitable for shared linking into a program,
+ or for inclusion in a shared library.
+ The &source; argument is a single source-code file,
+ and the &target; argument is the
+ name of the shared object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ SharedObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create the &file_o;
+ object file on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-SHOBJPREFIX;
+ and
+ &cv-link-SHOBJSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(SHOBJPREFIX='my', SHOBJSUFFIX='.xxx')
+ env.SharedObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>myfile.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ becomes the base of the name
+ of the shared object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ SharedObject('file.c')
+ </programlisting>
+
+ <para>
+
+ Will create the &file_o;
+ executable on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Object; Builder</title>
+
+ <para>
+
+ The &b-link-Object; Builder is a synonym for &b-link-StaticObject;
+ and is completely equivalent.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Library Builders</title>
+
+ <para>
+
+ &SCons; provides separate Builder objects
+ to create static and shared libraries.
+
+ </para>
+
+ <section>
+ <title>The &StaticLibrary; Builder</title>
+
+ <para>
+
+ The &b-link-StaticLibrary; Builder
+ is used to create a library
+ suitable for static linking into a program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the &target; argument is the
+ name of the static library to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ StaticLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-LIBPREFIX;
+ and
+ &cv-link-LIBSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(LIBPREFIX='my', LIBSUFFIX='.xxx')
+ env.StaticLibrary('lib', ['file1.o', 'file2.o'])
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>mylib.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <programlisting>
+ StaticLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ becomes the base of the name of the static object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ StaticLibrary(['file.c', 'another.c'])
+ </programlisting>
+
+ <para>
+
+ Will create the &libfile_a;
+ library on a POSIX system,
+ the &file_lib; library on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &SharedLibrary; Builder</title>
+
+ <para>
+
+ The &b-link-SharedLibrary; Builder
+ is used to create a shared library
+ suitable for linking with a program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the &target; argument is the
+ name of the shared library to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ SharedLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-SHLIBPREFIX;
+ and
+ &cv-link-SHLIBSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(SHLIBPREFIX='my', SHLIBSUFFIX='.xxx')
+ env.SharedLibrary('shared', ['file1.o', 'file2.o'])
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>myshared.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <programlisting>
+ SharedLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ becomes the base of the name of the shared library to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ SharedLibrary(['file.c', 'another.c'])
+ </programlisting>
+
+ <para>
+
+ Will create the &libfile_so;
+ library on a POSIX system,
+ the &file_dll; library on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Library; Builder</title>
+
+ <para>
+
+ The &b-link-Library; Builder is a synonym for &b-link-StaticLibrary;
+ and is completely equivalent.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Pre-Compiled Headers: the &PCH; Builder</title>
+
+ <para>
+
+ XXX PCH()
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Microsoft Visual C++ Resource Files: the &RES; Builder</title>
+
+ <para>
+
+ XXX RES()
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Source Files</title>
+
+ <para>
+
+ By default
+ &SCons; supports two Builder objects
+ that know how to build source files
+ from other input files.
+ These are typically invoked "internally"
+ to turn files that need preprocessing into other source files.
+
+ </para>
+
+ <section>
+ <title>The &CFile; Builder</title>
+
+ <para>
+
+ XXX CFile()
+
+ </para>
+
+ <programlisting>
+ XXX CFile() programlisting
+ </programlisting>
+
+ <screen>
+ XXX CFile() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &CXXFile; Builder</title>
+
+ <para>
+
+ XXX CXXFILE()
+
+ </para>
+
+ <programlisting>
+ XXX CXXFILE() programlisting
+ </programlisting>
+
+ <screen>
+ XXX CXXFILE() screen
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Documents</title>
+
+ <para>
+
+ &SCons; provides a number of Builder objects
+ for creating different types of documents.
+
+ </para>
+
+ <section>
+ <title>The &DVI; Builder</title>
+
+ <para>
+
+ XXX DVI() para
+
+ </para>
+
+ <programlisting>
+ XXX DVI() programlisting
+ </programlisting>
+
+ <screen>
+ XXX DVI() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &PDF; Builder</title>
+
+ <para>
+
+ XXX PDF() para
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &PostScript; Builder</title>
+
+ <para>
+
+ XXX PostScript() para
+
+ </para>
+
+ <programlisting>
+ XXX PostScript() programlisting
+ </programlisting>
+
+ <screen>
+ XXX PostScript() screen
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Archives</title>
+
+ <para>
+
+ &SCons; provides Builder objects
+ for creating two different types of archive files.
+
+ </para>
+
+ <section>
+ <title>The &Tar; Builder</title>
+
+ <para>
+
+ The &b-link-Tar; Builder object uses the &tar;
+ utility to create archives of files
+ and/or directory trees:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Tar('out1.tar', ['file1', 'file2'])
+ env.Tar('out2', 'directory')
+ </file>
+ <file name="file1">
+ file1
+ </file>
+ <file name="file2">
+ file2
+ </file>
+ <file name="directory/file3">
+ directory/file3
+ </file>
+ </scons_example>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons -Q .</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ One common requirement when creating a &tar; archive
+ is to create a compressed archive using the
+ <option>-z</option> option.
+ This is easily handled by specifying
+ the value of the &cv-link-TARFLAGS; variable
+ when you create the construction environment.
+ Note, however, that the <option>-c</option> used to
+ to instruct &tar; to create the archive
+ is part of the default value of &cv-TARFLAGS;,
+ so you need to set it both options:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ env = Environment(TARFLAGS = '-c -z')
+ env.Tar('out.tar.gz', 'directory')
+ </file>
+ <file name="directory/file">
+ directory/file
+ </file>
+ </scons_example>
+
+ <scons_output example="ex2" os="posix">
+ <scons_output_command>scons -Q .</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ you may also wish to set the value of the
+ &cv-link-TARSUFFIX; construction variable
+ to your desired suffix for compress &tar; archives,
+ so that &SCons; can append it to the target file name
+ without your having to specify it explicitly:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct" printme="1">
+ env = Environment(TARFLAGS = '-c -z',
+ TARSUFFIX = '.tgz')
+ env.Tar('out', 'directory')
+ </file>
+ <file name="directory/file">
+ directory/file
+ </file>
+ </scons_example>
+
+ <scons_output example="ex3" os="posix">
+ <scons_output_command>scons -Q .</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>The &Zip; Builder</title>
+
+ <para>
+
+ The &b-link-Zip; Builder object creates archives of files
+ and/or directory trees in the ZIP file format.
+ Python versions 1.6 or later
+ contain an internal &zipfile; module
+ that &SCons; will use.
+ In this case, given the following
+ &SConstruct; file:
+
+ </para>
+
+ <scons_example name="ex4">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Zip('out', ['file1', 'file2'])
+ </file>
+ <file name="file1">
+ file1
+ </file>
+ <file name="file2">
+ file2
+ </file>
+ </scons_example>
+
+ <para>
+
+ Your output will reflect the fact
+ that an internal Python function
+ is being used to create the output ZIP archive:
+
+ </para>
+
+ <scons_output example="ex4" os="posix">
+ <scons_output_command>scons -Q .</scons_output_command>
+ </scons_output>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ zip /home/my/project/zip.out file1 file2
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Java</title>
+
+ <para>
+
+ &SCons; provides Builder objects
+ for creating various types of Java output files.
+
+ </para>
+
+ <section>
+ <title>Building Class Files: the &Java; Builder</title>
+
+ <para>
+
+ The &b-link-Java; builder takes one or more input
+ <filename>.java</filename> files
+ and turns them into one or more
+ <filename>.class</filename> files
+ Unlike most builders, however,
+ the &Java; builder takes
+ target and source <emphasis>directories</emphasis>,
+ not files, as input.
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Java(target = 'classes', source = 'src')
+ </programlisting>
+
+ <para>
+
+ The &Java; builder will then
+ search the specified source directory
+ tree for all <filename>.java</filename> files,
+ and pass any out-of-date
+
+ </para>
+
+ <screen>
+ XXX Java() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &Jar; Builder</title>
+
+ <para>
+
+ XXX The &Jar; builder object
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Java(target = 'classes', source = 'src')
+ env.Jar(target = '', source = 'classes')
+ </programlisting>
+
+ <screen>
+ XXX Jar() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Building C header and stub files: the &JavaH; Builder</title>
+
+ <para>
+
+ XXX JavaH() para
+
+ </para>
+
+ <programlisting>
+ XXX JavaH() programlisting
+ </programlisting>
+
+ <screen>
+ XXX JavaH() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Building RMI stub and skeleton class files: the &RMIC; Builder</title>
+
+ <para>
+
+ XXX RMIC() para
+
+ </para>
+
+ <programlisting>
+ XXX RMIC() programlisting
+ </programlisting>
+
+ <screen>
+ XXX RMIC() screen
+ </screen>
+
+ </section>
+
+ </section>
diff --git a/doc/user/builders-built-in.xml b/doc/user/builders-built-in.xml
new file mode 100644
index 0000000..bee5b38
--- /dev/null
+++ b/doc/user/builders-built-in.xml
@@ -0,0 +1,949 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; provides the ability to build a lot of different
+ types of files right "out of the box."
+ So far, we've been using &SCons;' ability to build
+ programs, objects and libraries to
+ illustrate much of the underlying functionality of &SCons;
+ This section will describe all of the different
+ types of files that you can build with &SCons;,
+ and the built-in &Builder; objects used to build them.
+ By default, all of the &Builder; objects in this section
+ can be built either with or without an explicit
+ construction environment.
+
+ </para>
+
+ <section>
+ <title>Programs: the &Program; Builder</title>
+
+ <para>
+
+ As we've seen, the &b-link-Program; Builder
+ is used to build an executable program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the &target; argument is the
+ name of the executable program name to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ Program('prog', 'file1.o')
+ </programlisting>
+
+ <para>
+
+ Will create the &prog;
+ executable on a POSIX system,
+ the &prog_exe; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-PROGPREFIX;
+ and
+ &cv-link-PROGSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(PROGPREFIX='my', PROGSUFFIX='.xxx')
+ env.Program('prog', ['file1.o', 'file2.o'])
+ </programlisting>
+
+ <para>
+
+ Will create a program named
+ <filename>myprog.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ becomes the base of the target
+ program created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ Program(['hello.c', 'goodbye.c'])
+ </programlisting>
+
+ <para>
+
+ Will create the &hello;
+ executable on a POSIX system,
+ the &hello_exe; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ Two construction variables control what libraries
+ will be linked with the resulting program.
+ The &cv-link-LIBS; variable is a list of the names of
+ libraries that will be linked into any programs,
+ and the &cv-link-LIBPATH; variables is a list of
+ directories that will be searched for
+ the specified libraries.
+ &SCons; will construct the right command-line
+ options for the running system.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(LIBS = ['foo1', 'foo2'],
+ LIBPATH = ['/usr/dir1', 'dir2'])
+ env.Program(['hello.c', 'goodbye.c'])
+ </programlisting>
+
+ <para>
+
+ Will execute as follows on a POSIX system:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o goodbye.o -c goodbye.c
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o goodbye.o -L/usr/dir1 -Ldir2 -lfoo1 -lfoo2
+ </screen>
+
+ <para>
+
+ And execute as follows on a Windows system:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Fogoodbye.obj /c goodbye.c /nologo
+ cl /Fohello.obj /c hello.c /nologo
+ link /nologo /OUT:hello.exe /LIBPATH:\usr\dir1 /LIBPATH:dir2 foo1.lib foo2.lib hello.obj goodbye.obj
+ </screen>
+
+ <para>
+
+ The &cv-LIBS; construction variable
+ is turned into command line options
+ by appending the &cv-link-LIBLINKPREFIX; and &cv-link-LIBLINKSUFFIX;
+ construction variables to the beginning and end,
+ respectively, of each specified library.
+
+ </para>
+
+ <para>
+
+ The &cv-LIBPATH; construction variable
+ is turned into command line options
+ by appending the &cv-link-LIBDIRPREFIX; and &cv-link-LIBDIRSUFFIX;
+ construction variables to the beginning and end,
+ respectively, of each specified library.
+
+ </para>
+
+ <para>
+
+ Other relevant construction variables
+ include those used by the &b-link-Object;
+ builders to affect how the
+ source files specified as input to the &t-Program;
+ builders are turned into object files;
+ see the next section.
+
+ </para>
+
+ <para>
+
+ The command line used to control how a program is linked
+ is specified by the &cv-link-LINKCOM; construction variable.
+ By default, it uses the
+ &cv-link-LINK; construction variable
+ and the &cv-link-LINKFLAGS; construction variable.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Object-File Builders</title>
+
+ <para>
+
+ &SCons; provides separate Builder objects
+ to create static and shared object files.
+ The distinction becomes especially important when
+ archiving object files into different types of libraries.
+
+ </para>
+
+ <section>
+ <title>The &StaticObject; Builder</title>
+
+ <para>
+
+ The &b-link-StaticObject; Builder
+ is used to build an object file
+ suitable for static linking into a program,
+ or for inclusion in a static library.
+ The &source; argument is a single source-code file,
+ and the &target; argument is the
+ name of the static object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ StaticObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create the &file_o;
+ object file on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-OBJPREFIX;
+ and
+ &cv-link-OBJSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(OBJPREFIX='my', OBJSUFFIX='.xxx')
+ env.StaticObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>myfile.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ beomces the base of the name
+ of the static object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ StaticObject('file.c')
+ </programlisting>
+
+ <para>
+
+ Will create the &file_o;
+ executable on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &SharedObject; Builder</title>
+
+ <para>
+
+ The &b-link-SharedObject; Builder
+ is used to build an object file
+ suitable for shared linking into a program,
+ or for inclusion in a shared library.
+ The &source; argument is a single source-code file,
+ and the &target; argument is the
+ name of the shared object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ SharedObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create the &file_o;
+ object file on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-SHOBJPREFIX;
+ and
+ &cv-link-SHOBJSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(SHOBJPREFIX='my', SHOBJSUFFIX='.xxx')
+ env.SharedObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>myfile.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ becomes the base of the name
+ of the shared object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ SharedObject('file.c')
+ </programlisting>
+
+ <para>
+
+ Will create the &file_o;
+ executable on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Object; Builder</title>
+
+ <para>
+
+ The &b-link-Object; Builder is a synonym for &b-link-StaticObject;
+ and is completely equivalent.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Library Builders</title>
+
+ <para>
+
+ &SCons; provides separate Builder objects
+ to create static and shared libraries.
+
+ </para>
+
+ <section>
+ <title>The &StaticLibrary; Builder</title>
+
+ <para>
+
+ The &b-link-StaticLibrary; Builder
+ is used to create a library
+ suitable for static linking into a program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the &target; argument is the
+ name of the static library to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ StaticLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-LIBPREFIX;
+ and
+ &cv-link-LIBSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(LIBPREFIX='my', LIBSUFFIX='.xxx')
+ env.StaticLibrary('lib', ['file1.o', 'file2.o'])
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>mylib.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <programlisting>
+ StaticLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ becomes the base of the name of the static object file to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ StaticLibrary(['file.c', 'another.c'])
+ </programlisting>
+
+ <para>
+
+ Will create the &libfile_a;
+ library on a POSIX system,
+ the &file_lib; library on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &SharedLibrary; Builder</title>
+
+ <para>
+
+ The &b-link-SharedLibrary; Builder
+ is used to create a shared library
+ suitable for linking with a program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the &target; argument is the
+ name of the shared library to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ SharedLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ &cv-link-SHLIBPREFIX;
+ and
+ &cv-link-SHLIBSUFFIX;
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(SHLIBPREFIX='my', SHLIBSUFFIX='.xxx')
+ env.SharedLibrary('shared', ['file1.o', 'file2.o'])
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>myshared.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <programlisting>
+ SharedLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ If you omit the &target;,
+ the base of the first input
+ file name specified
+ becomes the base of the name of the shared library to be created.
+ For example:
+
+ </para>
+
+ <programlisting>
+ SharedLibrary(['file.c', 'another.c'])
+ </programlisting>
+
+ <para>
+
+ Will create the &libfile_so;
+ library on a POSIX system,
+ the &file_dll; library on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Library; Builder</title>
+
+ <para>
+
+ The &b-link-Library; Builder is a synonym for &b-link-StaticLibrary;
+ and is completely equivalent.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Pre-Compiled Headers: the &PCH; Builder</title>
+
+ <para>
+
+ XXX PCH()
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Microsoft Visual C++ Resource Files: the &RES; Builder</title>
+
+ <para>
+
+ XXX RES()
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Source Files</title>
+
+ <para>
+
+ By default
+ &SCons; supports two Builder objects
+ that know how to build source files
+ from other input files.
+ These are typically invoked "internally"
+ to turn files that need preprocessing into other source files.
+
+ </para>
+
+ <section>
+ <title>The &CFile; Builder</title>
+
+ <para>
+
+ XXX CFile()
+
+ </para>
+
+ <programlisting>
+ XXX CFile() programlisting
+ </programlisting>
+
+ <screen>
+ XXX CFile() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &CXXFile; Builder</title>
+
+ <para>
+
+ XXX CXXFILE()
+
+ </para>
+
+ <programlisting>
+ XXX CXXFILE() programlisting
+ </programlisting>
+
+ <screen>
+ XXX CXXFILE() screen
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Documents</title>
+
+ <para>
+
+ &SCons; provides a number of Builder objects
+ for creating different types of documents.
+
+ </para>
+
+ <section>
+ <title>The &DVI; Builder</title>
+
+ <para>
+
+ XXX DVI() para
+
+ </para>
+
+ <programlisting>
+ XXX DVI() programlisting
+ </programlisting>
+
+ <screen>
+ XXX DVI() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &PDF; Builder</title>
+
+ <para>
+
+ XXX PDF() para
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &PostScript; Builder</title>
+
+ <para>
+
+ XXX PostScript() para
+
+ </para>
+
+ <programlisting>
+ XXX PostScript() programlisting
+ </programlisting>
+
+ <screen>
+ XXX PostScript() screen
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Archives</title>
+
+ <para>
+
+ &SCons; provides Builder objects
+ for creating two different types of archive files.
+
+ </para>
+
+ <section>
+ <title>The &Tar; Builder</title>
+
+ <para>
+
+ The &b-link-Tar; Builder object uses the &tar;
+ utility to create archives of files
+ and/or directory trees:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Tar('out1.tar', ['file1', 'file2'])
+ env.Tar('out2', 'directory')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ tar -c -f out1.tar file1 file2
+ tar -c -f out2.tar directory
+ </screen>
+
+ <para>
+
+ One common requirement when creating a &tar; archive
+ is to create a compressed archive using the
+ <option>-z</option> option.
+ This is easily handled by specifying
+ the value of the &cv-link-TARFLAGS; variable
+ when you create the construction environment.
+ Note, however, that the <option>-c</option> used to
+ to instruct &tar; to create the archive
+ is part of the default value of &cv-TARFLAGS;,
+ so you need to set it both options:
+
+ </para>
+
+ <programlisting>
+ env = Environment(TARFLAGS = '-c -z')
+ env.Tar('out.tar.gz', 'directory')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ tar -c -z -f out.tar.gz directory
+ </screen>
+
+ <para>
+
+ you may also wish to set the value of the
+ &cv-link-TARSUFFIX; construction variable
+ to your desired suffix for compress &tar; archives,
+ so that &SCons; can append it to the target file name
+ without your having to specify it explicitly:
+
+ </para>
+
+ <programlisting>
+ env = Environment(TARFLAGS = '-c -z',
+ TARSUFFIX = '.tgz')
+ env.Tar('out', 'directory')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ tar -c -z -f out.tgz directory
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &Zip; Builder</title>
+
+ <para>
+
+ The &b-link-Zip; Builder object creates archives of files
+ and/or directory trees in the ZIP file format.
+ Python versions 1.6 or later
+ contain an internal &zipfile; module
+ that &SCons; will use.
+ In this case, given the following
+ &SConstruct; file:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Zip('out', ['file1', 'file2'])
+ </programlisting>
+
+ <para>
+
+ Your output will reflect the fact
+ that an internal Python function
+ is being used to create the output ZIP archive:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ zip(["out.zip"], ["file1", "file2"])
+ </screen>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ zip /home/my/project/zip.out file1 file2
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Java</title>
+
+ <para>
+
+ &SCons; provides Builder objects
+ for creating various types of Java output files.
+
+ </para>
+
+ <section>
+ <title>Building Class Files: the &Java; Builder</title>
+
+ <para>
+
+ The &b-link-Java; builder takes one or more input
+ <filename>.java</filename> files
+ and turns them into one or more
+ <filename>.class</filename> files
+ Unlike most builders, however,
+ the &Java; builder takes
+ target and source <emphasis>directories</emphasis>,
+ not files, as input.
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Java(target = 'classes', source = 'src')
+ </programlisting>
+
+ <para>
+
+ The &Java; builder will then
+ search the specified source directory
+ tree for all <filename>.java</filename> files,
+ and pass any out-of-date
+
+ </para>
+
+ <screen>
+ XXX Java() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &Jar; Builder</title>
+
+ <para>
+
+ XXX The &Jar; builder object
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Java(target = 'classes', source = 'src')
+ env.Jar(target = '', source = 'classes')
+ </programlisting>
+
+ <screen>
+ XXX Jar() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Building C header and stub files: the &JavaH; Builder</title>
+
+ <para>
+
+ XXX JavaH() para
+
+ </para>
+
+ <programlisting>
+ XXX JavaH() programlisting
+ </programlisting>
+
+ <screen>
+ XXX JavaH() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Building RMI stub and skeleton class files: the &RMIC; Builder</title>
+
+ <para>
+
+ XXX RMIC() para
+
+ </para>
+
+ <programlisting>
+ XXX RMIC() programlisting
+ </programlisting>
+
+ <screen>
+ XXX RMIC() screen
+ </screen>
+
+ </section>
+
+ </section>
diff --git a/doc/user/builders-commands.in b/doc/user/builders-commands.in
new file mode 100644
index 0000000..687d12d
--- /dev/null
+++ b/doc/user/builders-commands.in
@@ -0,0 +1,156 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <!--
+
+ =head2 The C<Command> method
+
+
+ The C<Command> method is called as follows:
+
+ Command $env <target>, <inputs>, <build action>;
+
+ The target is made dependent upon the list of input files specified, and the
+ inputs must be built successfully or Cons will not attempt to build the
+ target.
+
+ To specify a command with multiple targets, you can specify a reference to a
+ list of targets. In Perl, a list reference can be created by enclosing a
+ list in square brackets. Hence the following command:
+
+ Command $env ['foo.h', 'foo.c'], 'foo.template', q(
+ gen %1
+ );
+
+ could be used in a case where the command C<gen> creates two files, both
+ F<foo.h> and F<foo.c>.
+
+ -->
+
+ <para>
+
+ Creating a &Builder; and attaching it to a &consenv;
+ allows for a lot of flexibility when you
+ want to re-use actions
+ to build multiple files of the same type.
+ This can, however, be cumbersome
+ if you only need to execute one specific command
+ to build a single file (or group of files).
+ For these situations, &SCons; supports a
+ &Command; &Builder; that arranges
+ for a specific action to be executed
+ to build a specific file or files.
+ This looks a lot like the other builders
+ (like &b-link-Program;, &b-link-Object;, etc.),
+ but takes as an additional argument
+ the command to be executed to build the file:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET")
+ </file>
+ <file name="foo.in">
+ foo.in
+ </file>
+ </scons_example>
+
+ <para>
+
+ When executed,
+ &SCons; runs the specified command,
+ substituting &cv-link-SOURCE; and &cv-link-TARGET;
+ as expected:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ This is often more convenient than
+ creating a &Builder; object
+ and adding it to the &cv-link-BUILDERS; variable
+ of a &consenv;
+
+ </para>
+
+ <para>
+
+ Note that the action you specify to the
+ &Command; &Builder; can be any legal &SCons; &Action;,
+ such as a Python function:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ def build(target, source, env):
+ # Whatever it takes to build
+ return None
+ env.Command('foo.out', 'foo.in', build)
+ </file>
+ <file name="foo.in">
+ foo.in
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which executes as follows:
+
+ </para>
+
+ <scons_output example="ex2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that &cv-link-SOURCE; and &cv-link-TARGET; are expanded
+ in the source and target as well as of SCons 1.1,
+ so you can write:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct" printme="1">
+ env.Command('${SOURCE.basename}.out', 'foo.in', build)
+ </file>
+ </scons_example>
+
+
+ <para>
+
+ which does the same thing as the previous example, but allows you
+ to avoid repeating yourself.
+
+ </para>
+
diff --git a/doc/user/builders-commands.xml b/doc/user/builders-commands.xml
new file mode 100644
index 0000000..111b1d2
--- /dev/null
+++ b/doc/user/builders-commands.xml
@@ -0,0 +1,146 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <!--
+
+ =head2 The C<Command> method
+
+
+ The C<Command> method is called as follows:
+
+ Command $env <target>, <inputs>, <build action>;
+
+ The target is made dependent upon the list of input files specified, and the
+ inputs must be built successfully or Cons will not attempt to build the
+ target.
+
+ To specify a command with multiple targets, you can specify a reference to a
+ list of targets. In Perl, a list reference can be created by enclosing a
+ list in square brackets. Hence the following command:
+
+ Command $env ['foo.h', 'foo.c'], 'foo.template', q(
+ gen %1
+ );
+
+ could be used in a case where the command C<gen> creates two files, both
+ F<foo.h> and F<foo.c>.
+
+ -->
+
+ <para>
+
+ Creating a &Builder; and attaching it to a &consenv;
+ allows for a lot of flexibility when you
+ want to re-use actions
+ to build multiple files of the same type.
+ This can, however, be cumbersome
+ if you only need to execute one specific command
+ to build a single file (or group of files).
+ For these situations, &SCons; supports a
+ &Command; &Builder; that arranges
+ for a specific action to be executed
+ to build a specific file or files.
+ This looks a lot like the other builders
+ (like &b-link-Program;, &b-link-Object;, etc.),
+ but takes as an additional argument
+ the command to be executed to build the file:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Command('foo.out', 'foo.in', "sed 's/x/y/' &lt; $SOURCE &gt; $TARGET")
+ </programlisting>
+
+ <para>
+
+ When executed,
+ &SCons; runs the specified command,
+ substituting &cv-link-SOURCE; and &cv-link-TARGET;
+ as expected:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ sed 's/x/y/' &lt; foo.in &gt; foo.out
+ </screen>
+
+ <para>
+
+ This is often more convenient than
+ creating a &Builder; object
+ and adding it to the &cv-link-BUILDERS; variable
+ of a &consenv;
+
+ </para>
+
+ <para>
+
+ Note that the action you specify to the
+ &Command; &Builder; can be any legal &SCons; &Action;,
+ such as a Python function:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ def build(target, source, env):
+ # Whatever it takes to build
+ return None
+ env.Command('foo.out', 'foo.in', build)
+ </programlisting>
+
+ <para>
+
+ Which executes as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ build(["foo.out"], ["foo.in"])
+ </screen>
+
+ <para>
+
+ Note that &cv-link-SOURCE; and &cv-link-TARGET; are expanded
+ in the source and target as well as of SCons 1.1,
+ so you can write:
+
+ </para>
+
+ <programlisting>
+ env.Command('${SOURCE.basename}.out', 'foo.in', build)
+ </programlisting>
+
+
+ <para>
+
+ which does the same thing as the previous example, but allows you
+ to avoid repeating yourself.
+
+ </para>
+
diff --git a/doc/user/builders-writing.in b/doc/user/builders-writing.in
new file mode 100644
index 0000000..4f54d99
--- /dev/null
+++ b/doc/user/builders-writing.in
@@ -0,0 +1,1087 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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 &cv-link-BUILDERS;
+ &consvar; in an environment.
+ The &cv-BUILDERS; variable is a Python dictionary
+ that maps the names by which you want to call
+ various &Builder; objects to the objects themselves.
+ For example, if we want to call the
+ &Builder; we just defined by the name
+ <function>Foo</function>,
+ our &SConstruct; file might look like:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct">
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ env.Foo('file.foo', 'file.input')
+ </file>
+ <file name="file.input">
+ file.input
+ </file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
+ </scons_example>
+
+ <sconstruct>
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ </sconstruct>
+
+ <para>
+
+ With the &Builder; attached to our &consenv;
+ with the name <function>Foo</function>,
+ we can now actually call it like so:
+
+ </para>
+
+ <programlisting>
+ env.Foo('file.foo', 'file.input')
+ </programlisting>
+
+ <para>
+
+ Then when we run &SCons; it looks like:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note, however, that the default &cv-BUILDERS;
+ variable in a &consenv;
+ comes with a default set of &Builder; objects
+ already defined:
+ &b-link-Program;, &b-link-Library;, etc.
+ And when we explicitly set the &cv-BUILDERS; variable
+ when we create the &consenv;,
+ the default &Builder;s are no longer part of
+ the environment:
+
+ </para>
+
+ <!--
+ The ToolSurrogate stuff that's used to capture output initializes
+ SCons.Defaults.ConstructionEnvironment with its own list of TOOLS.
+ In this next example, we want to show the user that when they
+ set the BUILDERS explicitly, the call to env.Program() generates
+ an AttributeError. This won't happen with all of the default
+ ToolSurrogates in the default construction environment. To make the
+ AttributeError show up, we have to overwite the default construction
+ environment's TOOLS variable so Program() builder doesn't show up.
+
+ We do this by executing a slightly different SConstruct file than the
+ one we print in the guide, with two extra statements at the front
+ that overwrite the TOOLS variable as described. Note that we have
+ to jam those statements on to the first line to keep the line number
+ in the generated error consistent with what the user will see in the
+ User's Guide.
+ -->
+ <scons_example name="ex2">
+ <file name="SConstruct">
+ import SCons.Defaults; SCons.Defaults.ConstructionEnvironment['TOOLS'] = {}; bld = Builder(action = 'foobuild &lt; $SOURCE &gt; $TARGET')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </file>
+ <file name="SConstruct.printme" printme="1">
+ bld = Builder(action = 'foobuild &lt; $SOURCE &gt; $TARGET')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </file>
+ <file name="file.input">
+ file.input
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ </scons_example>
+
+ <scons_output example="ex2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ To be able to use both our own defined &Builder; objects
+ and the default &Builder; objects in the same &consenv;,
+ you can either add to the &cv-BUILDERS; variable
+ using the &Append; function:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct">
+ env = Environment()
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env.Append(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </file>
+ <file name="file.input">
+ file.input
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
+ </scons_example>
+
+ <sconstruct>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env.Append(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </sconstruct>
+
+ <para>
+
+ Or you can explicitly set the appropriately-named
+ key in the &cv-BUILDERS; dictionary:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env['BUILDERS']['Foo'] = bld
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </sconstruct>
+
+ <para>
+
+ Either way, the same &consenv;
+ can then use both the newly-defined
+ <function>Foo</function> &Builder;
+ and the default &b-link-Program; &Builder;:
+
+ </para>
+
+ <scons_output example="ex3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Letting &SCons; Handle The File Suffixes</title>
+
+ <para>
+
+ By supplying additional information
+ when you create a &Builder;,
+ you can let &SCons; add appropriate file
+ suffixes to the target and/or the source file.
+ For example, rather than having to specify
+ explicitly that you want the <literal>Foo</literal>
+ &Builder; to build the <literal>file.foo</literal>
+ target file from the <literal>file.input</literal> source file,
+ you can give the <literal>.foo</literal>
+ and <literal>.input</literal> suffixes to the &Builder;,
+ making for more compact and readable calls to
+ the <literal>Foo</literal> &Builder;:
+
+ </para>
+
+ <scons_example name="ex4">
+ <file name="SConstruct">
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ env.Foo('file1')
+ env.Foo('file2')
+ </file>
+ <file name="file1.input">
+ file1.input
+ </file>
+ <file name="file2.input">
+ file2.input
+ </file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
+ </scons_example>
+
+ <sconstruct>
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file1')
+ env.Foo('file2')
+ </sconstruct>
+
+ <scons_output example="ex4">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ You can also supply a <literal>prefix</literal> keyword argument
+ if it's appropriate to have &SCons; append a prefix
+ to the beginning of target file names.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Builders That Execute Python Functions</title>
+
+ <para>
+
+ In &SCons;, you don't have to call an external command
+ to build a file.
+ You can, instead, define a Python function
+ that a &Builder; object can invoke
+ to build your target file (or files).
+ Such a &buildfunc; definition looks like:
+
+ </para>
+
+ <programlisting>
+ def build_function(target, source, env):
+ # Code to build "target" from "source"
+ return None
+ </programlisting>
+
+ <para>
+
+ The arguments of a &buildfunc; are:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>target</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the target or targets to be
+ built by this builder function.
+ The file names of these target(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>source</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the sources to be
+ used by this builder function to build the targets.
+ The file names of these source(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The &consenv; used for building the target(s).
+ The builder function may use any of the
+ environment's construction variables
+ in any way to affect how it builds the targets.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ The builder function must
+ return a <literal>0</literal> or <literal>None</literal> value
+ if the target(s) are built successfully.
+ The builder function
+ may raise an exception
+ or return any non-zero value
+ to indicate that the build is unsuccessful,
+
+ </para>
+
+ <para>
+
+ Once you've defined the Python function
+ that will build your target file,
+ defining a &Builder; object for it is as
+ simple as specifying the name of the function,
+ instead of an external command,
+ as the &Builder;'s
+ <literal>action</literal>
+ argument:
+
+ </para>
+
+ <scons_example name="ex5">
+ <file name="SConstruct" printme="1">
+ def build_function(target, source, env):
+ # Code to build "target" from "source"
+ return None
+ bld = Builder(action = build_function,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </file>
+ <file name="file.input">
+ file.input
+ </file>
+ </scons_example>
+
+ <para>
+
+ And notice that the output changes slightly,
+ reflecting the fact that a Python function,
+ not an external command,
+ is now called to build the target file:
+
+ </para>
+
+ <scons_output example="ex5">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Builders That Create Actions Using a &Generator;</title>
+
+ <para>
+
+ &SCons; Builder objects can create an action "on the fly"
+ by using a function called a &generator;.
+ This provides a great deal of flexibility to
+ construct just the right list of commands
+ to build your target.
+ A &generator; looks like:
+
+ </para>
+
+ <programlisting>
+ def generate_actions(source, target, env, for_signature):
+ return 'foobuild < %s > %s' % (target[0], source[0])
+ </programlisting>
+
+ <para>
+
+ The arguments of a &generator; are:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>source</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the sources to be built
+ by the command or other action
+ generated by this function.
+ The file names of these source(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>target</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the target or targets to be built
+ by the command or other action
+ generated by this function.
+ The file names of these target(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The &consenv; used for building the target(s).
+ The generator may use any of the
+ environment's construction variables
+ in any way to determine what command
+ or other action to return.
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>for_signature</term>
+
+ <listitem>
+ <para>
+
+ A flag that specifies whether the
+ generator is being called to contribute to a build signature,
+ as opposed to actually executing the command.
+
+ <!-- XXX NEED MORE HERE, describe generators use in signatures -->
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ The &generator; must return a
+ command string or other action that will be used to
+ build the specified target(s) from the specified source(s).
+
+ </para>
+
+ <para>
+
+ Once you've defined a &generator;,
+ you create a &Builder; to use it
+ by specifying the generator keyword argument
+ instead of <literal>action</literal>.
+
+ </para>
+
+ <scons_example name="ex6">
+ <file name="SConstruct">
+ def generate_actions(source, target, env, for_signature):
+ return 'foobuild < %s > %s' % (source[0], target[0])
+ bld = Builder(generator = generate_actions,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ env.Foo('file')
+ </file>
+ <file name="file.input">
+ file.input
+ </file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
+ </scons_example>
+
+ <sconstruct>
+ def generate_actions(source, target, env, for_signature):
+ return 'foobuild < %s > %s' % (source[0], target[0])
+ bld = Builder(generator = generate_actions,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </sconstruct>
+
+ <scons_output example="ex6">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that it's illegal to specify both an
+ <literal>action</literal>
+ and a
+ <literal>generator</literal>
+ for a &Builder;.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Builders That Modify the Target or Source Lists Using an &Emitter;</title>
+
+ <para>
+
+ &SCons; supports the ability for a Builder to modify the
+ lists of target(s) from the specified source(s).
+ You do this by defining an &emitter; function
+ that takes as its arguments
+ the list of the targets passed to the builder,
+ the list of the sources passed to the builder,
+ and the construction environment.
+ The emitter function should return the modified
+ lists of targets that should be built
+ and sources from which the targets will be built.
+
+ </para>
+
+ <para>
+
+ For example, suppose you want to define a Builder
+ that always calls a <filename>foobuild</filename> program,
+ and you want to automatically add
+ a new target file named
+ <filename>new_target</filename>
+ and a new source file named
+ <filename>new_source</filename>
+ whenever it's called.
+ The &SConstruct; file might look like this:
+
+ </para>
+
+ <scons_example name="ex7">
+ <file name="SConstruct">
+ def modify_targets(target, source, env):
+ target.append('new_target')
+ source.append('new_source')
+ return target, source
+ bld = Builder(action = 'foobuild $TARGETS - $SOURCES',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = modify_targets)
+ env = Environment(BUILDERS = {'Foo' : bld})
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ env.Foo('file')
+ </file>
+ <file name="file.input">
+ file.input
+ </file>
+ <file name="new_source">
+ new_source
+ </file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
+ </scons_example>
+
+ <sconstruct>
+ def modify_targets(target, source, env):
+ target.append('new_target')
+ source.append('new_source')
+ return target, source
+ bld = Builder(action = 'foobuild $TARGETS - $SOURCES',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = modify_targets)
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </sconstruct>
+
+ <para>
+
+ And would yield the following output:
+
+ </para>
+
+ <scons_output example="ex7">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ One very flexible thing that you can do is
+ use a construction variable to specify
+ different emitter functions for different
+ construction variable.
+ To do this, specify a string
+ containing a construction variable
+ expansion as the emitter when you call
+ the &Builder; function,
+ and set that construction variable to
+ the desired emitter function
+ in different construction environments:
+
+ </para>
+
+ <scons_example name="MY_EMITTER">
+
+ <file name="SConstruct" printme="1">
+ bld = Builder(action = 'my_command $SOURCES > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = '$MY_EMITTER')
+ def modify1(target, source, env):
+ return target, source + ['modify1.in']
+ def modify2(target, source, env):
+ return target, source + ['modify2.in']
+ env1 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify1)
+ env2 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify2)
+ env1.Foo('file1')
+ env2.Foo('file2')
+ import os
+ env1['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd()
+ env2['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd()
+ </file>
+ <file name="file1.input">
+ file1.input
+ </file>
+ <file name="file2.input">
+ file2.input
+ </file>
+ <file name="modify1.in">
+ modify1.input
+ </file>
+ <file name="modify2.in">
+ modify2.input
+ </file>
+ <file name="my_command" chmod="0755">
+ cat
+ </file>
+ </file>
+
+ </scons_example>
+
+ <sconstruct>
+ bld = Builder(action = 'my_command $SOURCES > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = '$MY_EMITTER')
+ def modify1(target, source, env):
+ return target, source + ['modify1.in']
+ def modify2(target, source, env):
+ return target, source + ['modify2.in']
+ env1 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify1)
+ env2 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify2)
+ env1.Foo('file1')
+ env2.Foo('file2')
+ </file>
+ </sconstruct>
+
+ <para>
+
+ In this example, the <filename>modify1.in</filename>
+ and <filename>modify2.in</filename> files
+ get added to the source lists
+ of the different commands:
+
+ </para>
+
+ <scons_output example="MY_EMITTER">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>target_factor=, source_factory=</title>
+
+ </section>
+
+ <section>
+ <title>target_scanner=, source_scanner=</title>
+
+ </section>
+
+ <section>
+ <title>multi=</title>
+
+ </section>
+
+ <section>
+ <title>single_source=</title>
+
+ </section>
+
+ <section>
+ <title>src_builder=</title>
+
+ </section>
+
+ <section>
+ <title>ensure_suffix=</title>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>Where To Put Your Custom Builders and Tools</title>
+
+ <para>
+
+ The <filename>site_scons</filename> directory gives you a place to
+ put Python modules you can import into your SConscripts
+ (site_scons), add-on tools that can integrate into &SCons;
+ (site_scons/site_tools), and a site_scons/site_init.py file that
+ gets read before any &SConstruct; or &SConscript;, allowing you to
+ change &SCons;'s default behavior.
+
+ </para>
+
+ <para>
+
+ If you get a tool from somewhere (the &SCons; wiki or a third party,
+ for instance) and you'd like to use it in your project, the
+ <filename>site_scons</filename> dir is the simplest place to put it.
+ Tools come in two flavors; either a Python function that operates on
+ an &Environment; or a Python file containing two functions, exists()
+ and generate().
+
+ </para>
+
+ <para>
+
+ A single-function Tool can just be included in your
+ <filename>site_scons/site_init.py</filename> file where it will be
+ parsed and made available for use. For instance, you could have a
+ <filename>site_scons/site_init.py</filename> file like this:
+
+ </para>
+
+ <scons_example name="site1">
+ <file name="site_scons/site_init.py" printme=1>
+ def TOOL_ADD_HEADER(env):
+ """A Tool to add a header from $HEADER to the source file"""
+ add_header = Builder(action=['echo "$HEADER" > $TARGET',
+ 'cat $SOURCE >> $TARGET'])
+ env.Append(BUILDERS = {'AddHeader' : add_header})
+ env['HEADER'] = '' # set default value
+ </file>
+ <file name="SConstruct">
+ env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====")
+ env.AddHeader('tgt', 'src')
+ </file>
+ <file name="src">
+ hi there
+ </file>
+ </scons_example>
+
+ <para>
+
+ and a &SConstruct; like this:
+
+ </para>
+
+ <sconstruct>
+ # Use TOOL_ADD_HEADER from site_scons/site_init.py
+ env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====")
+ env.AddHeader('tgt', 'src')
+ </sconstruct>
+
+ <para>
+
+ The <function>TOOL_ADD_HEADER</function> tool method will be
+ called to add the <function>AddHeader</function> tool to the
+ environment.
+
+ </para>
+
+ <!--
+ <scons_output example="site1" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+ -->
+
+ <para>
+ Similarly, a more full-fledged tool with
+ <function>exists()</function> and <function>generate()</function>
+ methods can be installed in
+ <filename>site_scons/site_tools/toolname.py</filename>. Since
+ <filename>site_scons/site_tools</filename> is automatically added
+ to the head of the tool search path, any tool found there will be
+ available to all environments. Furthermore, a tool found there
+ will override a built-in tool of the same name, so if you need to
+ change the behavior of a built-in tool, site_scons gives you the
+ hook you need.
+ </para>
+
+ <para>
+ Many people have a library of utility Python functions they'd like
+ to include in &SConscript;s; just put that module in
+ <filename>site_scons/my_utils.py</filename> or any valid Python module name of your
+ choice. For instance you can do something like this in
+ <filename>site_scons/my_utils.py</filename> to add build_id and MakeWorkDir functions:
+ </para>
+
+ <scons_example name="site2">
+ <file name="site_scons/my_utils.py" printme=1>
+ from SCons.Script import * # for Execute and Mkdir
+ def build_id():
+ """Return a build ID (stub version)"""
+ return "100"
+ def MakeWorkDir(workdir):
+ """Create the specified dir immediately"""
+ Execute(Mkdir(workdir))
+ </file>
+ <file name="SConscript">
+ import my_utils
+ MakeWorkDir('/tmp/work')
+ print "build_id=" + my_utils.build_id()
+ </file>
+ </scons_example>
+
+ <para>
+
+ And then in your &SConscript; or any sub-&SConscript; anywhere in
+ your build, you can import <filename>my_utils</filename> and use it:
+
+ </para>
+
+ <sconstruct>
+ import my_utils
+ print "build_id=" + my_utils.build_id()
+ my_utils.MakeWorkDir('/tmp/work')
+ </sconstruct>
+
+ <para>
+ Note that although you can put this library in
+ <filename>site_scons/site_init.py</filename>,
+ it is no better there than <filename>site_scons/my_utils.py</filename>
+ since you still have to import that module into your &SConscript;.
+ Also note that in order to refer to objects in the SCons namespace
+ such as &Environment; or &Mkdir; or &Execute; in any file other
+ than a &SConstruct; or &SConscript; you always need to do
+ </para>
+ <sconstruct>
+ from SCons.Script import *
+ </sconstruct>
+
+ <para>
+ This is true in modules in <filename>site_scons</filename> such as
+ <filename>site_scons/site_init.py</filename> as well.
+ </para>
+
+ <para>
+
+ If you have a machine-wide site dir you'd like to use instead of
+ <filename>./site_scons</filename>, use the
+ <literal>--site-dir</literal> option to point to your dir.
+ <filename>site_init.py</filename> and
+ <filename>site_tools</filename> will be located under that dir.
+ To avoid using a <filename>site_scons</filename> dir at all, even
+ if it exists, use the <literal>--no-site-dir</literal> option.
+
+ </para>
+
+ </section>
+
+
+ <!--
+
+ <section>
+ <title>Builders That Use Other Builders</title>
+
+ <para>
+
+ XXX para
+
+ </para>
+
+ <scons_example name="ex8">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ #env.SourceCode('.', env.BitKeeper('my_command'))
+ env.Program('hello.c')
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ </scons_example>
+
+ <scons_output example="ex8">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ -->
diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml
new file mode 100644
index 0000000..b05cce6
--- /dev/null
+++ b/doc/user/builders-writing.xml
@@ -0,0 +1,953 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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 &cv-link-BUILDERS;
+ &consvar; in an environment.
+ The &cv-BUILDERS; variable is a Python dictionary
+ that maps the names by which you want to call
+ various &Builder; objects to the objects themselves.
+ For example, if we want to call the
+ &Builder; we just defined by the name
+ <function>Foo</function>,
+ our &SConstruct; file might look like:
+
+ </para>
+
+
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ </programlisting>
+
+ <para>
+
+ With the &Builder; attached to our &consenv;
+ with the name <function>Foo</function>,
+ we can now actually call it like so:
+
+ </para>
+
+ <programlisting>
+ env.Foo('file.foo', 'file.input')
+ </programlisting>
+
+ <para>
+
+ Then when we run &SCons; it looks like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild &lt; file.input &gt; file.foo
+ </screen>
+
+ <para>
+
+ Note, however, that the default &cv-BUILDERS;
+ variable in a &consenv;
+ comes with a default set of &Builder; objects
+ already defined:
+ &b-link-Program;, &b-link-Library;, etc.
+ And when we explicitly set the &cv-BUILDERS; variable
+ when we create the &consenv;,
+ the default &Builder;s are no longer part of
+ the environment:
+
+ </para>
+
+ <!--
+ The ToolSurrogate stuff that's used to capture output initializes
+ SCons.Defaults.ConstructionEnvironment with its own list of TOOLS.
+ In this next example, we want to show the user that when they
+ set the BUILDERS explicitly, the call to env.Program() generates
+ an AttributeError. This won't happen with all of the default
+ ToolSurrogates in the default construction environment. To make the
+ AttributeError show up, we have to overwite the default construction
+ environment's TOOLS variable so Program() builder doesn't show up.
+
+ We do this by executing a slightly different SConstruct file than the
+ one we print in the guide, with two extra statements at the front
+ that overwrite the TOOLS variable as described. Note that we have
+ to jam those statements on to the first line to keep the line number
+ in the generated error consistent with what the user will see in the
+ User's Guide.
+ -->
+ <programlisting>
+ bld = Builder(action = 'foobuild &lt; $SOURCE &gt; $TARGET')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ AttributeError: SConsEnvironment instance has no attribute 'Program':
+ File "/home/my/project/SConstruct", line 4:
+ env.Program('hello.c')
+ </screen>
+
+ <para>
+
+ To be able to use both our own defined &Builder; objects
+ and the default &Builder; objects in the same &consenv;,
+ you can either add to the &cv-BUILDERS; variable
+ using the &Append; function:
+
+ </para>
+
+
+
+ <programlisting>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env.Append(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ Or you can explicitly set the appropriately-named
+ key in the &cv-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 &b-link-Program; &Builder;:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild &lt; file.input &gt; file.foo
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Letting &SCons; Handle The File Suffixes</title>
+
+ <para>
+
+ By supplying additional information
+ when you create a &Builder;,
+ you can let &SCons; add appropriate file
+ suffixes to the target and/or the source file.
+ For example, rather than having to specify
+ explicitly that you want the <literal>Foo</literal>
+ &Builder; to build the <literal>file.foo</literal>
+ target file from the <literal>file.input</literal> source file,
+ you can give the <literal>.foo</literal>
+ and <literal>.input</literal> suffixes to the &Builder;,
+ making for more compact and readable calls to
+ the <literal>Foo</literal> &Builder;:
+
+ </para>
+
+
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file1')
+ env.Foo('file2')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild &lt; file1.input &gt; file1.foo
+ foobuild &lt; file2.input &gt; file2.foo
+ </screen>
+
+ <para>
+
+ You can also supply a <literal>prefix</literal> keyword argument
+ if it's appropriate to have &SCons; append a prefix
+ to the beginning of target file names.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Builders That Execute Python Functions</title>
+
+ <para>
+
+ In &SCons;, you don't have to call an external command
+ to build a file.
+ You can, instead, define a Python function
+ that a &Builder; object can invoke
+ to build your target file (or files).
+ Such a &buildfunc; definition looks like:
+
+ </para>
+
+ <programlisting>
+ def build_function(target, source, env):
+ # Code to build "target" from "source"
+ return None
+ </programlisting>
+
+ <para>
+
+ The arguments of a &buildfunc; are:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>target</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the target or targets to be
+ built by this builder function.
+ The file names of these target(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>source</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the sources to be
+ used by this builder function to build the targets.
+ The file names of these source(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The &consenv; used for building the target(s).
+ The builder function may use any of the
+ environment's construction variables
+ in any way to affect how it builds the targets.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ The builder function must
+ return a <literal>0</literal> or <literal>None</literal> value
+ if the target(s) are built successfully.
+ The builder function
+ may raise an exception
+ or return any non-zero value
+ to indicate that the build is unsuccessful,
+
+ </para>
+
+ <para>
+
+ Once you've defined the Python function
+ that will build your target file,
+ defining a &Builder; object for it is as
+ simple as specifying the name of the function,
+ instead of an external command,
+ as the &Builder;'s
+ <literal>action</literal>
+ argument:
+
+ </para>
+
+ <programlisting>
+ def build_function(target, source, env):
+ # Code to build "target" from "source"
+ return None
+ bld = Builder(action = build_function,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <para>
+
+ And notice that the output changes slightly,
+ reflecting the fact that a Python function,
+ not an external command,
+ is now called to build the target file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ build_function(["file.foo"], ["file.input"])
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Builders That Create Actions Using a &Generator;</title>
+
+ <para>
+
+ &SCons; Builder objects can create an action "on the fly"
+ by using a function called a &generator;.
+ This provides a great deal of flexibility to
+ construct just the right list of commands
+ to build your target.
+ A &generator; looks like:
+
+ </para>
+
+ <programlisting>
+ def generate_actions(source, target, env, for_signature):
+ return 'foobuild < %s > %s' % (target[0], source[0])
+ </programlisting>
+
+ <para>
+
+ The arguments of a &generator; are:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>source</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the sources to be built
+ by the command or other action
+ generated by this function.
+ The file names of these source(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>target</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the target or targets to be built
+ by the command or other action
+ generated by this function.
+ The file names of these target(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The &consenv; used for building the target(s).
+ The generator may use any of the
+ environment's construction variables
+ in any way to determine what command
+ or other action to return.
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>for_signature</term>
+
+ <listitem>
+ <para>
+
+ A flag that specifies whether the
+ generator is being called to contribute to a build signature,
+ as opposed to actually executing the command.
+
+ <!-- XXX NEED MORE HERE, describe generators use in signatures -->
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ The &generator; must return a
+ command string or other action that will be used to
+ build the specified target(s) from the specified source(s).
+
+ </para>
+
+ <para>
+
+ Once you've defined a &generator;,
+ you create a &Builder; to use it
+ by specifying the generator keyword argument
+ instead of <literal>action</literal>.
+
+ </para>
+
+
+
+ <programlisting>
+ def generate_actions(source, target, env, for_signature):
+ return 'foobuild < %s > %s' % (source[0], target[0])
+ bld = Builder(generator = generate_actions,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild &lt; file.input &gt; file.foo
+ </screen>
+
+ <para>
+
+ Note that it's illegal to specify both an
+ <literal>action</literal>
+ and a
+ <literal>generator</literal>
+ for a &Builder;.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Builders That Modify the Target or Source Lists Using an &Emitter;</title>
+
+ <para>
+
+ &SCons; supports the ability for a Builder to modify the
+ lists of target(s) from the specified source(s).
+ You do this by defining an &emitter; function
+ that takes as its arguments
+ the list of the targets passed to the builder,
+ the list of the sources passed to the builder,
+ and the construction environment.
+ The emitter function should return the modified
+ lists of targets that should be built
+ and sources from which the targets will be built.
+
+ </para>
+
+ <para>
+
+ For example, suppose you want to define a Builder
+ that always calls a <filename>foobuild</filename> program,
+ and you want to automatically add
+ a new target file named
+ <filename>new_target</filename>
+ and a new source file named
+ <filename>new_source</filename>
+ whenever it's called.
+ The &SConstruct; file might look like this:
+
+ </para>
+
+
+
+ <programlisting>
+ def modify_targets(target, source, env):
+ target.append('new_target')
+ source.append('new_source')
+ return target, source
+ bld = Builder(action = 'foobuild $TARGETS - $SOURCES',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = modify_targets)
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <para>
+
+ And would yield the following output:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild file.foo new_target - file.input new_source
+ </screen>
+
+ <para>
+
+ One very flexible thing that you can do is
+ use a construction variable to specify
+ different emitter functions for different
+ construction variable.
+ To do this, specify a string
+ containing a construction variable
+ expansion as the emitter when you call
+ the &Builder; function,
+ and set that construction variable to
+ the desired emitter function
+ in different construction environments:
+
+ </para>
+
+ <programlisting>
+ bld = Builder(action = 'my_command $SOURCES &gt; $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = '$MY_EMITTER')
+ def modify1(target, source, env):
+ return target, source + ['modify1.in']
+ def modify2(target, source, env):
+ return target, source + ['modify2.in']
+ env1 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify1)
+ env2 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify2)
+ env1.Foo('file1')
+ env2.Foo('file2')
+ import os
+ env1['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd()
+ env2['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd()
+
+
+ </programlisting>
+
+ <programlisting>
+ bld = Builder(action = 'my_command $SOURCES > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = '$MY_EMITTER')
+ def modify1(target, source, env):
+ return target, source + ['modify1.in']
+ def modify2(target, source, env):
+ return target, source + ['modify2.in']
+ env1 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify1)
+ env2 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify2)
+ env1.Foo('file1')
+ env2.Foo('file2')
+
+ </programlisting>
+
+ <para>
+
+ In this example, the <filename>modify1.in</filename>
+ and <filename>modify2.in</filename> files
+ get added to the source lists
+ of the different commands:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ my_command file1.input modify1.in &gt; file1.foo
+ my_command file2.input modify2.in &gt; file2.foo
+ </screen>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>target_factor=, source_factory=</title>
+
+ </section>
+
+ <section>
+ <title>target_scanner=, source_scanner=</title>
+
+ </section>
+
+ <section>
+ <title>multi=</title>
+
+ </section>
+
+ <section>
+ <title>single_source=</title>
+
+ </section>
+
+ <section>
+ <title>src_builder=</title>
+
+ </section>
+
+ <section>
+ <title>ensure_suffix=</title>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>Where To Put Your Custom Builders and Tools</title>
+
+ <para>
+
+ The <filename>site_scons</filename> directory gives you a place to
+ put Python modules you can import into your SConscripts
+ (site_scons), add-on tools that can integrate into &SCons;
+ (site_scons/site_tools), and a site_scons/site_init.py file that
+ gets read before any &SConstruct; or &SConscript;, allowing you to
+ change &SCons;'s default behavior.
+
+ </para>
+
+ <para>
+
+ If you get a tool from somewhere (the &SCons; wiki or a third party,
+ for instance) and you'd like to use it in your project, the
+ <filename>site_scons</filename> dir is the simplest place to put it.
+ Tools come in two flavors; either a Python function that operates on
+ an &Environment; or a Python file containing two functions, exists()
+ and generate().
+
+ </para>
+
+ <para>
+
+ A single-function Tool can just be included in your
+ <filename>site_scons/site_init.py</filename> file where it will be
+ parsed and made available for use. For instance, you could have a
+ <filename>site_scons/site_init.py</filename> file like this:
+
+ </para>
+
+ <programlisting>
+ def TOOL_ADD_HEADER(env):
+ """A Tool to add a header from $HEADER to the source file"""
+ add_header = Builder(action=['echo "$HEADER" &gt; $TARGET',
+ 'cat $SOURCE &gt;&gt; $TARGET'])
+ env.Append(BUILDERS = {'AddHeader' : add_header})
+ env['HEADER'] = '' # set default value
+ </programlisting>
+
+ <para>
+
+ and a &SConstruct; like this:
+
+ </para>
+
+ <programlisting>
+ # Use TOOL_ADD_HEADER from site_scons/site_init.py
+ env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====")
+ env.AddHeader('tgt', 'src')
+ </programlisting>
+
+ <para>
+
+ The <function>TOOL_ADD_HEADER</function> tool method will be
+ called to add the <function>AddHeader</function> tool to the
+ environment.
+
+ </para>
+
+ <!--
+ <scons_output example="site1" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+ -->
+
+ <para>
+ Similarly, a more full-fledged tool with
+ <function>exists()</function> and <function>generate()</function>
+ methods can be installed in
+ <filename>site_scons/site_tools/toolname.py</filename>. Since
+ <filename>site_scons/site_tools</filename> is automatically added
+ to the head of the tool search path, any tool found there will be
+ available to all environments. Furthermore, a tool found there
+ will override a built-in tool of the same name, so if you need to
+ change the behavior of a built-in tool, site_scons gives you the
+ hook you need.
+ </para>
+
+ <para>
+ Many people have a library of utility Python functions they'd like
+ to include in &SConscript;s; just put that module in
+ <filename>site_scons/my_utils.py</filename> or any valid Python module name of your
+ choice. For instance you can do something like this in
+ <filename>site_scons/my_utils.py</filename> to add build_id and MakeWorkDir functions:
+ </para>
+
+ <programlisting>
+ from SCons.Script import * # for Execute and Mkdir
+ def build_id():
+ """Return a build ID (stub version)"""
+ return "100"
+ def MakeWorkDir(workdir):
+ """Create the specified dir immediately"""
+ Execute(Mkdir(workdir))
+ </programlisting>
+
+ <para>
+
+ And then in your &SConscript; or any sub-&SConscript; anywhere in
+ your build, you can import <filename>my_utils</filename> and use it:
+
+ </para>
+
+ <programlisting>
+ import my_utils
+ print "build_id=" + my_utils.build_id()
+ my_utils.MakeWorkDir('/tmp/work')
+ </programlisting>
+
+ <para>
+ Note that although you can put this library in
+ <filename>site_scons/site_init.py</filename>,
+ it is no better there than <filename>site_scons/my_utils.py</filename>
+ since you still have to import that module into your &SConscript;.
+ Also note that in order to refer to objects in the SCons namespace
+ such as &Environment; or &Mkdir; or &Execute; in any file other
+ than a &SConstruct; or &SConscript; you always need to do
+ </para>
+ <programlisting>
+ from SCons.Script import *
+ </programlisting>
+
+ <para>
+ This is true in modules in <filename>site_scons</filename> such as
+ <filename>site_scons/site_init.py</filename> as well.
+ </para>
+
+ <para>
+
+ If you have a machine-wide site dir you'd like to use instead of
+ <filename>./site_scons</filename>, use the
+ <literal>--site-dir</literal> option to point to your dir.
+ <filename>site_init.py</filename> and
+ <filename>site_tools</filename> will be located under that dir.
+ To avoid using a <filename>site_scons</filename> dir at all, even
+ if it exists, use the <literal>--no-site-dir</literal> option.
+
+ </para>
+
+ </section>
+
+
+ <!--
+
+ <section>
+ <title>Builders That Use Other Builders</title>
+
+ <para>
+
+ XXX para
+
+ </para>
+
+ <scons_example name="ex8">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ #env.SourceCode('.', env.BitKeeper('my_command'))
+ env.Program('hello.c')
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ </scons_example>
+
+ <scons_output example="ex8">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ -->
diff --git a/doc/user/builders.in b/doc/user/builders.in
new file mode 100644
index 0000000..a2f94ce
--- /dev/null
+++ b/doc/user/builders.in
@@ -0,0 +1,57 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+
+<refentry id="Command">
+
+<refmeta>
+<refentrytitle>Command</refentrytitle>
+</refmeta>
+
+<methodsynopsis>
+ <methodname>env.Command</methodname>
+ <methodparam>foo</methodparam>
+ <methodparam>bar</methodparam>
+</methodsynopsis>
+
+</refentry>
+-->
+
+<para>
+
+This appendix contains descriptions of all of the
+Builders that are <emphasis>potentially</emphasis>
+available "out of the box" in this version of SCons.
+
+</para>
+
+<variablelist>
+
+&builders-gen;
+
+</variablelist>
diff --git a/doc/user/builders.xml b/doc/user/builders.xml
new file mode 100644
index 0000000..a2f94ce
--- /dev/null
+++ b/doc/user/builders.xml
@@ -0,0 +1,57 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+
+<refentry id="Command">
+
+<refmeta>
+<refentrytitle>Command</refentrytitle>
+</refmeta>
+
+<methodsynopsis>
+ <methodname>env.Command</methodname>
+ <methodparam>foo</methodparam>
+ <methodparam>bar</methodparam>
+</methodsynopsis>
+
+</refentry>
+-->
+
+<para>
+
+This appendix contains descriptions of all of the
+Builders that are <emphasis>potentially</emphasis>
+available "out of the box" in this version of SCons.
+
+</para>
+
+<variablelist>
+
+&builders-gen;
+
+</variablelist>
diff --git a/doc/user/caching.in b/doc/user/caching.in
new file mode 100644
index 0000000..31b1103
--- /dev/null
+++ b/doc/user/caching.in
@@ -0,0 +1,502 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ On multi-developer software projects,
+ you can sometimes speed up every developer's builds a lot by
+ allowing them to share the derived files that they build.
+ &SCons; makes this easy, as well as reliable.
+
+ </para>
+
+ <section>
+ <title>Specifying the Shared Cache Directory</title>
+
+ <para>
+
+ To enable sharing of derived files,
+ use the &CacheDir; function
+ in any &SConscript; file:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct">
+ env = Environment()
+ env.Program('hello.c')
+ CacheDir('cache')
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ <directory name="cache">
+ </directory>
+ <file name="not_used" printme="1">
+ CacheDir('/usr/local/build_cache')
+ </file>
+ </scons_example>
+
+ <para>
+
+ Note that the directory you specify must already exist
+ and be readable and writable by all developers
+ who will be sharing derived files.
+ It should also be in some central location
+ that all builds will be able to access.
+ In environments where developers are using separate systems
+ (like individual workstations) for builds,
+ this directory would typically be
+ on a shared or NFS-mounted file system.
+
+ </para>
+
+ <para>
+
+ Here's what happens:
+ When a build has a &CacheDir; specified,
+ every time a file is built,
+ it is stored in the shared cache directory
+ along with its MD5 build signature.
+ <footnote>
+ <para>
+ Actually, the MD5 signature is used as the name of the file
+ in the shared cache directory in which the contents are stored.
+ </para>
+ </footnote>
+ On subsequent builds,
+ before an action is invoked to build a file,
+ &SCons; will check the shared cache directory
+ to see if a file with the exact same build
+ signature already exists.
+ If so, the derived file will not be built locally,
+ but will be copied into the local build directory
+ from the shared cache directory,
+ like so:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that the &CacheDir; feature still calculates
+ MD5 build sigantures for the shared cache file names
+ even if you configure &SCons; to use timestamps
+ to decide if files are up to date.
+ (See the <xref linkend="chap-depends"></xref>
+ chapter for information about the &Decider; function.)
+ Consequently, using &CacheDir; may reduce or eliminate any
+ potential performance improvements
+ from using timestamps for up-to-date decisions.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Keeping Build Output Consistent</title>
+
+ <para>
+
+ One potential drawback to using a shared cache
+ is that the output printed by &SCons;
+ can be inconsistent from invocation to invocation,
+ because any given file may be rebuilt one time
+ and retrieved from the shared cache the next time.
+ This can make analyzing build output more difficult,
+ especially for automated scripts that
+ expect consistent output each time.
+
+ </para>
+
+ <para>
+
+ If, however, you use the <literal>--cache-show</literal> option,
+ &SCons; will print the command line that it
+ <emphasis>would</emphasis> have executed
+ to build the file,
+ even when it is retrieving the file from the shared cache.
+ This makes the build output consistent
+ every time the build is run:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q --cache-show</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The trade-off, of course, is that you no longer
+ know whether or not &SCons;
+ has retrieved a derived file from cache
+ or has rebuilt it locally.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Not Using the Shared Cache for Specific Files</title>
+
+ <para>
+
+ You may want to disable caching for certain
+ specific files in your configuration.
+ For example, if you only want to put
+ executable files in a central cache,
+ but not the intermediate object files,
+ you can use the &NoCache;
+ function to specify that the
+ object files should not be cached:
+
+ </para>
+
+ <scons_example name="ex-NoCache">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ obj = env.Object('hello.c')
+ env.Program('hello.c')
+ CacheDir('cache')
+ NoCache('hello.o')
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ <directory name="cache">
+ </directory>
+ </scons_example>
+
+ <para>
+
+ Then when you run &scons; after cleaning
+ the built targets,
+ it will recompile the object file locally
+ (since it doesn't exist in the shared cache directory),
+ but still realize that the shared cache directory
+ contains an up-to-date executable program
+ that can be retrieved instead of re-linking:
+
+ </para>
+
+ <!--
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ Retrieved `hello' from cache
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Disabling the Shared Cache</title>
+
+ <para>
+
+ Retrieving an already-built file
+ from the shared cache
+ is usually a significant time-savings
+ over rebuilding the file,
+ but how much of a savings
+ (or even whether it saves time at all)
+ can depend a great deal on your
+ system or network configuration.
+ For example, retrieving cached files
+ from a busy server over a busy network
+ might end up being slower than
+ rebuilding the files locally.
+
+ </para>
+
+ <para>
+
+ In these cases, you can specify
+ the <literal>--cache-disable</literal>
+ command-line option to tell &SCons;
+ to not retrieve already-built files from the
+ shared cache directory:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q --cache-disable</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Populating a Shared Cache With Already-Built Files</title>
+
+ <para>
+
+ Sometimes, you may have one or more derived files
+ already built in your local build tree
+ that you wish to make available to other people doing builds.
+ For example, you may find it more effective to perform
+ integration builds with the cache disabled
+ (per the previous section)
+ and only populate the shared cache directory
+ with the built files after the integration build
+ has completed successfully.
+ This way, the cache will only get filled up
+ with derived files that are part of a complete, successful build
+ not with files that might be later overwritten
+ while you debug integration problems.
+
+ </para>
+
+ <para>
+
+ In this case, you can use the
+ the <literal>--cache-force</literal> option
+ to tell &SCons; to put all derived files in the cache,
+ even if the files already exist in your local tree
+ from having been built by a previous invocation:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q --cache-disable</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q --cache-disable</scons_output_command>
+ <scons_output_command>scons -Q --cache-force</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice how the above sample run
+ demonstrates that the <literal>--cache-disable</literal>
+ option avoids putting the built
+ <filename>hello.o</filename>
+ and
+ <filename>hello</filename> files in the cache,
+ but after using the <literal>--cache-force</literal> option,
+ the files have been put in the cache
+ for the next invocation to retrieve.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Minimizing Cache Contention: the <literal>--random</literal> Option</title>
+
+ <para>
+
+ If you allow multiple builds to update the
+ shared cache directory simultaneously,
+ two builds that occur at the same time
+ can sometimes start "racing"
+ with one another to build the same files
+ in the same order.
+ If, for example,
+ you are linking multiple files into an executable program:
+
+ </para>
+
+ <scons_example name="ex-random">
+ <file name="SConstruct" printme="1">
+ Program('prog',
+ ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
+ </file>
+ <file name="f1.c">f1.c</file>
+ <file name="f2.c">f2.c</file>
+ <file name="f3.c">f3.c</file>
+ <file name="f4.c">f4.c</file>
+ <file name="f5.c">f5.c</file>
+ <file name="f6.c">f6.c</file>
+ </scons_example>
+
+ <para>
+
+ &SCons; will normally build the input object files
+ on which the program depends in their normal, sorted order:
+
+ </para>
+
+ <scons_output example="ex-random">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ But if two such builds take place simultaneously,
+ they may each look in the cache at nearly the same
+ time and both decide that <filename>f1.o</filename>
+ must be rebuilt and pushed into the shared cache directory,
+ then both decide that <filename>f2.o</filename>
+ must be rebuilt (and pushed into the shared cache directory),
+ then both decide that <filename>f3.o</filename>
+ must be rebuilt...
+ This won't cause any actual build problems--both
+ builds will succeed,
+ generate correct output files,
+ and populate the cache--but
+ it does represent wasted effort.
+
+ </para>
+
+ <para>
+
+ To alleviate such contention for the cache,
+ you can use the <literal>--random</literal> command-line option
+ to tell &SCons; to build dependencies
+ in a random order:
+
+ </para>
+
+ <!--
+
+ The following <screen> output was generated by this:
+
+ <scons_output example="ex-random">
+ <scons_output_command>scons -Q - -random</scons_output_command>
+ </scons_output>
+
+ We captured it directly here to guarantee a "random" order,
+ guarding against the potential for - -random to happen
+ to return things in the original sorted order.
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q --random</userinput>
+ cc -o f3.o -c f3.c
+ cc -o f1.o -c f1.c
+ cc -o f5.o -c f5.c
+ cc -o f2.o -c f2.c
+ cc -o f4.o -c f4.c
+ cc -o prog f1.o f2.o f3.o f4.o f5.o
+ </screen>
+
+ <para>
+
+ Multiple builds using the <literal>--random</literal> option
+ will usually build their dependencies in different,
+ random orders,
+ which minimizes the chances for a lot of
+ contention for same-named files
+ in the shared cache directory.
+ Multiple simultaneous builds might still race to try to build
+ the same target file on occasion,
+ but long sequences of inefficient contention
+ should be rare.
+
+ </para>
+
+ <para>
+
+ Note, of course,
+ the <literal>--random</literal> option
+ will cause the output that &SCons; prints
+ to be inconsistent from invocation to invocation,
+ which may be an issue when
+ trying to compare output from different build runs.
+
+ </para>
+
+ <para>
+
+ If you want to make sure dependencies will be built
+ in a random order without having to specify
+ the <literal>--random</literal> on very command line,
+ you can use the &SetOption; function to
+ set the <literal>random</literal> option
+ within any &SConscript; file:
+
+ </para>
+
+ <scons_example name="ex-random">
+ <file name="SConstruct" printme="1">
+ SetOption('random', 1)
+ Program('prog',
+ ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
+ </file>
+ <file name="f1.c">f1.c</file>
+ <file name="f2.c">f2.c</file>
+ <file name="f3.c">f3.c</file>
+ <file name="f4.c">f4.c</file>
+ <file name="f5.c">f5.c</file>
+ <file name="f6.c">f6.c</file>
+ </scons_example>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Troubleshooting Shared Caching: the &cache-debug; Option</title>
+
+ <para>
+
+ XXX describe the - - cache-debug option
+ XXX maybe point to the troubleshooting appendix?
+
+ </para>
+
+ </section>
+
+ -->
+
+ <!--
+
+ <section>
+
+ <para>
+
+ XXX describe CacheDir management: monitoring, deleting, etc.
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/caching.xml b/doc/user/caching.xml
new file mode 100644
index 0000000..073539c
--- /dev/null
+++ b/doc/user/caching.xml
@@ -0,0 +1,506 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>
+
+ <programlisting>
+ CacheDir('/usr/local/build_cache')
+ </programlisting>
+
+ <para>
+
+ Note that the directory you specify must already exist
+ and be readable and writable by all developers
+ who will be sharing derived files.
+ It should also be in some central location
+ that all builds will be able to access.
+ In environments where developers are using separate systems
+ (like individual workstations) for builds,
+ this directory would typically be
+ on a shared or NFS-mounted file system.
+
+ </para>
+
+ <para>
+
+ Here's what happens:
+ When a build has a &CacheDir; specified,
+ every time a file is built,
+ it is stored in the shared cache directory
+ along with its MD5 build signature.
+ <footnote>
+ <para>
+ Actually, the MD5 signature is used as the name of the file
+ in the shared cache directory in which the contents are stored.
+ </para>
+ </footnote>
+ On subsequent builds,
+ before an action is invoked to build a file,
+ &SCons; will check the shared cache directory
+ to see if a file with the exact same build
+ signature already exists.
+ If so, the derived file will not be built locally,
+ but will be copied into the local build directory
+ from the shared cache directory,
+ like so:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q</userinput>
+ Retrieved `hello.o' from cache
+ Retrieved `hello' from cache
+ </screen>
+
+ <para>
+
+ Note that the &CacheDir; feature still calculates
+ MD5 build sigantures for the shared cache file names
+ even if you configure &SCons; to use timestamps
+ to decide if files are up to date.
+ (See the <xref linkend="chap-depends"></xref>
+ chapter for information about the &Decider; function.)
+ Consequently, using &CacheDir; may reduce or eliminate any
+ potential performance improvements
+ from using timestamps for up-to-date decisions.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Keeping Build Output Consistent</title>
+
+ <para>
+
+ One potential drawback to using a shared cache
+ is that the output printed by &SCons;
+ can be inconsistent from invocation to invocation,
+ because any given file may be rebuilt one time
+ and retrieved from the shared cache the next time.
+ This can make analyzing build output more difficult,
+ especially for automated scripts that
+ expect consistent output each time.
+
+ </para>
+
+ <para>
+
+ If, however, you use the <literal>--cache-show</literal> option,
+ &SCons; will print the command line that it
+ <emphasis>would</emphasis> have executed
+ to build the file,
+ even when it is retrieving the file from the shared cache.
+ This makes the build output consistent
+ every time the build is run:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q --cache-show</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ The trade-off, of course, is that you no longer
+ know whether or not &SCons;
+ has retrieved a derived file from cache
+ or has rebuilt it locally.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Not Using the Shared Cache for Specific Files</title>
+
+ <para>
+
+ You may want to disable caching for certain
+ specific files in your configuration.
+ For example, if you only want to put
+ executable files in a central cache,
+ but not the intermediate object files,
+ you can use the &NoCache;
+ function to specify that the
+ object files should not be cached:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ obj = env.Object('hello.c')
+ env.Program('hello.c')
+ CacheDir('cache')
+ NoCache('hello.o')
+ </programlisting>
+
+ <para>
+
+ Then when you run &scons; after cleaning
+ the built targets,
+ it will recompile the object file locally
+ (since it doesn't exist in the shared cache directory),
+ but still realize that the shared cache directory
+ contains an up-to-date executable program
+ that can be retrieved instead of re-linking:
+
+ </para>
+
+ <!--
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ Retrieved `hello' from cache
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Disabling the Shared Cache</title>
+
+ <para>
+
+ Retrieving an already-built file
+ from the shared cache
+ is usually a significant time-savings
+ over rebuilding the file,
+ but how much of a savings
+ (or even whether it saves time at all)
+ can depend a great deal on your
+ system or network configuration.
+ For example, retrieving cached files
+ from a busy server over a busy network
+ might end up being slower than
+ rebuilding the files locally.
+
+ </para>
+
+ <para>
+
+ In these cases, you can specify
+ the <literal>--cache-disable</literal>
+ command-line option to tell &SCons;
+ to not retrieve already-built files from the
+ shared cache directory:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q</userinput>
+ Retrieved `hello.o' from cache
+ Retrieved `hello' from cache
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q --cache-disable</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Populating a Shared Cache With Already-Built Files</title>
+
+ <para>
+
+ Sometimes, you may have one or more derived files
+ already built in your local build tree
+ that you wish to make available to other people doing builds.
+ For example, you may find it more effective to perform
+ integration builds with the cache disabled
+ (per the previous section)
+ and only populate the shared cache directory
+ with the built files after the integration build
+ has completed successfully.
+ This way, the cache will only get filled up
+ with derived files that are part of a complete, successful build
+ not with files that might be later overwritten
+ while you debug integration problems.
+
+ </para>
+
+ <para>
+
+ In this case, you can use the
+ the <literal>--cache-force</literal> option
+ to tell &SCons; to put all derived files in the cache,
+ even if the files already exist in your local tree
+ from having been built by a previous invocation:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --cache-disable</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q --cache-disable</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q --cache-force</userinput>
+ scons: `.' is up to date.
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Notice how the above sample run
+ demonstrates that the <literal>--cache-disable</literal>
+ option avoids putting the built
+ <filename>hello.o</filename>
+ and
+ <filename>hello</filename> files in the cache,
+ but after using the <literal>--cache-force</literal> option,
+ the files have been put in the cache
+ for the next invocation to retrieve.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Minimizing Cache Contention: the <literal>--random</literal> Option</title>
+
+ <para>
+
+ If you allow multiple builds to update the
+ shared cache directory simultaneously,
+ two builds that occur at the same time
+ can sometimes start "racing"
+ with one another to build the same files
+ in the same order.
+ If, for example,
+ you are linking multiple files into an executable program:
+
+ </para>
+
+ <programlisting>
+ Program('prog',
+ ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
+ </programlisting>
+
+ <para>
+
+ &SCons; will normally build the input object files
+ on which the program depends in their normal, sorted order:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o f1.o -c f1.c
+ cc -o f2.o -c f2.c
+ cc -o f3.o -c f3.c
+ cc -o f4.o -c f4.c
+ cc -o f5.o -c f5.c
+ cc -o prog f1.o f2.o f3.o f4.o f5.o
+ </screen>
+
+ <para>
+
+ But if two such builds take place simultaneously,
+ they may each look in the cache at nearly the same
+ time and both decide that <filename>f1.o</filename>
+ must be rebuilt and pushed into the shared cache directory,
+ then both decide that <filename>f2.o</filename>
+ must be rebuilt (and pushed into the shared cache directory),
+ then both decide that <filename>f3.o</filename>
+ must be rebuilt...
+ This won't cause any actual build problems--both
+ builds will succeed,
+ generate correct output files,
+ and populate the cache--but
+ it does represent wasted effort.
+
+ </para>
+
+ <para>
+
+ To alleviate such contention for the cache,
+ you can use the <literal>--random</literal> command-line option
+ to tell &SCons; to build dependencies
+ in a random order:
+
+ </para>
+
+ <!--
+
+ The following <screen> output was generated by this:
+
+ <scons_output example="ex-random">
+ <scons_output_command>scons -Q - -random</scons_output_command>
+ </scons_output>
+
+ We captured it directly here to guarantee a "random" order,
+ guarding against the potential for - -random to happen
+ to return things in the original sorted order.
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q --random</userinput>
+ cc -o f3.o -c f3.c
+ cc -o f1.o -c f1.c
+ cc -o f5.o -c f5.c
+ cc -o f2.o -c f2.c
+ cc -o f4.o -c f4.c
+ cc -o prog f1.o f2.o f3.o f4.o f5.o
+ </screen>
+
+ <para>
+
+ Multiple builds using the <literal>--random</literal> option
+ will usually build their dependencies in different,
+ random orders,
+ which minimizes the chances for a lot of
+ contention for same-named files
+ in the shared cache directory.
+ Multiple simultaneous builds might still race to try to build
+ the same target file on occasion,
+ but long sequences of inefficient contention
+ should be rare.
+
+ </para>
+
+ <para>
+
+ Note, of course,
+ the <literal>--random</literal> option
+ will cause the output that &SCons; prints
+ to be inconsistent from invocation to invocation,
+ which may be an issue when
+ trying to compare output from different build runs.
+
+ </para>
+
+ <para>
+
+ If you want to make sure dependencies will be built
+ in a random order without having to specify
+ the <literal>--random</literal> on very command line,
+ you can use the &SetOption; function to
+ set the <literal>random</literal> option
+ within any &SConscript; file:
+
+ </para>
+
+ <programlisting>
+ Program('prog',
+ ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
+
+ SetOption('random', 1)
+ Program('prog',
+ ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
+ </programlisting>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Troubleshooting Shared Caching: the &cache-debug; Option</title>
+
+ <para>
+
+ XXX describe the - - cache-debug option
+ XXX maybe point to the troubleshooting appendix?
+
+ </para>
+
+ </section>
+
+ -->
+
+ <!--
+
+ <section>
+
+ <para>
+
+ XXX describe CacheDir management: monitoring, deleting, etc.
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/command-line.in b/doc/user/command-line.in
new file mode 100644
index 0000000..686146e
--- /dev/null
+++ b/doc/user/command-line.in
@@ -0,0 +1,2327 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; provides a number of ways
+ for the writer of the &SConscript; files
+ to give the users who will run &SCons;
+ a great deal of control over the build execution.
+ The arguments that the user can specify on
+ the command line are broken down into three types:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>Options</term>
+
+ <listitem>
+ <para>
+
+ Command-line options always begin with
+ one or two <literal>-</literal> (hyphen) characters.
+ &SCons; provides ways for you to examine
+ and set options values from within your &SConscript; files,
+ as well as the ability to define your own
+ custom options.
+ See <xref linkend="sect-command-line-options"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Variables</term>
+
+ <listitem>
+ <para>
+
+ Any command-line argument containing an <literal>=</literal>
+ (equal sign) is considered a variable setting with the form
+ <varname>variable</varname>=<varname>value</varname>
+ &SCons; provides direct access to
+ all of the command-line variable settings,
+ the ability to apply command-line variable settings
+ to construction environments,
+ and functions for configuring
+ specific types of variables
+ (Boolean values, path names, etc.)
+ with automatic validation of the user's specified values.
+ See <xref linkend="sect-command-line-variables"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Targets</term>
+
+ <listitem>
+ <para>
+
+ Any command-line argument that is not an option
+ or a variable setting
+ (does not begin with a hyphen
+ and does not contain an equal sign)
+ is considered a target that the user
+ (presumably) wants &SCons; to build.
+ A list of Node objects representing
+ the target or targets to build.
+ &SCons; provides access to the list of specified targets,
+ as well as ways to set the default list of targets
+ from within the &SConscript; files.
+ See <xref linkend="sect-command-line-targets"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <section id="sect-command-line-options">
+ <title>Command-Line Options</title>
+
+ <para>
+
+ &SCons; has many <emphasis>command-line options</emphasis>
+ that control its behavior.
+ A &SCons; <emphasis>command-line option</emphasis>
+ always begins with one or two <literal>-</literal> (hyphen)
+ characters.
+
+ </para>
+
+ <section>
+ <title>Not Having to Specify Command-Line Options Each Time: the &SCONSFLAGS; Environment Variable</title>
+
+ <para>
+
+ Users may find themselves supplying
+ the same command-line options every time
+ they run &SCons;.
+ For example, you might find it saves time
+ to specify a value of <literal>-j 2</literal>
+ to have &SCons; run up to two build commands in parallel.
+ To avoid having to type <literal>-j 2</literal> by hand
+ every time,
+ you can set the external environment variable
+ &SCONSFLAGS; to a string containing
+ command-line options that you want &SCons; to use.
+
+ </para>
+
+ <para>
+
+ If, for example,
+ you're using a POSIX shell that's
+ compatible with the Bourne shell,
+ and you always want &SCons; to use the
+ <literal>-Q</literal> option,
+ you can set the &SCONSFLAGS;
+ environment as follows:
+
+ </para>
+
+ <scons_example name="SCONSFLAGS">
+ <file name="SConstruct">
+ def b(target, source, env):
+ pass
+ def s(target, source, env):
+ return " ... [build output] ..."
+ a = Action(b, strfunction = s)
+ env = Environment(BUILDERS = {'A' : Builder(action=a)})
+ env.A('foo.out', 'foo.in')
+ </file>
+ <file name="foo.in">
+ foo.in
+ </file>
+ </scons_example>
+
+ <scons_output example="SCONSFLAGS">
+ <scons_output_command>scons</scons_output_command>
+ <scons_output_command>export SCONSFLAGS="-Q"</scons_output_command>
+ <scons_output_command environment="SCONSFLAGS=-Q">scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Users of &csh;-style shells on POSIX systems
+ can set the &SCONSFLAGS; environment as follows:
+
+ </para>
+
+ <screen>
+ $ <userinput>setenv SCONSFLAGS "-Q"</userinput>
+ </screen>
+
+ <para>
+
+ Windows users may typically want to set the
+ &SCONSFLAGS; in the appropriate tab of the
+ <literal>System Properties</literal> window.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Getting Values Set by Command-Line Options: the &GetOption; Function</title>
+
+ <para>
+
+ &SCons; provides the &GetOption; function
+ to get the values set by the various command-line options.
+ One common use of this is to check whether or not
+ the <literal>-h</literal> or <literal>--help</literal> option
+ has been specified.
+ Normally, &SCons; does not print its help text
+ until after it has read all of the &SConscript; files,
+ because it's possible that help text has been added
+ by some subsidiary &SConscript; file deep in the
+ source tree hierarchy.
+ Of course, reading all of the &SConscript; files
+ takes extra time.
+
+ </para>
+
+ <para>
+
+ If you know that your configuration does not define
+ any additional help text in subsidiary &SConscript; files,
+ you can speed up the command-line help available to users
+ by using the &GetOption; function to load the
+ subsidiary &SConscript; files only if the
+ the user has <emphasis>not</emphasis> specified
+ the <literal>-h</literal> or <literal>--help</literal> option,
+ like so:
+
+ </para>
+
+ <sconstruct)
+ if not GetOption('help'):
+ SConscript('src/SConscript', export='env')
+ </sconstruct>
+
+ <para>
+
+ In general, the string that you pass to the
+ &GetOption; function to fetch the value of a command-line
+ option setting is the same as the "most common" long option name
+ (beginning with two hyphen characters),
+ although there are some exceptions.
+ The list of &SCons; command-line options
+ and the &GetOption; strings for fetching them,
+ are available in the
+ <xref linkend="sect-command-line-option-strings"></xref> section,
+ below.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Setting Values of Command-Line Options: the &SetOption; Function</title>
+
+ <para>
+
+ You can also set the values of &SCons;
+ command-line options from within the &SConscript; files
+ by using the &SetOption; function.
+ The strings that you use to set the values of &SCons;
+ command-line options are available in the
+ <xref linkend="sect-command-line-option-strings"></xref> section,
+ below.
+
+ </para>
+
+ <para>
+
+ One use of the &SetOption; function is to
+ specify a value for the <literal>-j</literal>
+ or <literal>--jobs</literal> option,
+ so that users get the improved performance
+ of a parallel build without having to specify the option by hand.
+ A complicating factor is that a good value
+ for the <literal>-j</literal> option is
+ somewhat system-dependent.
+ One rough guideline is that the more processors
+ your system has,
+ the higher you want to set the
+ <literal>-j</literal> value,
+ in order to take advantage of the number of CPUs.
+
+ </para>
+
+ <para>
+
+ For example, suppose the administrators
+ of your development systems
+ have standardized on setting a
+ <varname>NUM_CPU</varname> environment variable
+ to the number of processors on each system.
+ A little bit of Python code
+ to access the environment variable
+ and the &SetOption; function
+ provide the right level of flexibility:
+
+ </para>
+
+ <scons_example name="SetOption">
+ <file name="SConstruct" printme="1">
+ import os
+ num_cpu = int(os.environ.get('NUM_CPU', 2))
+ SetOption('num_jobs', num_cpu)
+ print "running with -j", GetOption('num_jobs')
+ </file>
+ <file name="foo.in">
+ foo.in
+ </file>
+ </scons_example>
+
+ <para>
+
+ The above snippet of code
+ sets the value of the <literal>--jobs</literal> option
+ to the value specified in the
+ <varname>$NUM_CPU</varname> environment variable.
+ (This is one of the exception cases
+ where the string is spelled differently from
+ the from command-line option.
+ The string for fetching or setting the <literal>--jobs</literal>
+ value is <literal>num_jobs</literal>
+ for historical reasons.)
+ The code in this example prints the <literal>num_jobs</literal>
+ value for illustrative purposes.
+ It uses a default value of <literal>2</literal>
+ to provide some minimal parallelism even on
+ single-processor systems:
+
+ </para>
+
+ <scons_output example="SetOption">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ But if the <varname>$NUM_CPU</varname>
+ environment variable is set,
+ then we use that for the default number of jobs:
+
+ </para>
+
+ <scons_output example="SetOption">
+ <scons_output_command>export NUM_CPU="4"</scons_output_command>
+ <scons_output_command environment="NUM_CPU=4">scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ But any explicit
+ <literal>-j</literal> or <literal>--jobs</literal>
+ value the user specifies an the command line is used first,
+ regardless of whether or not
+ the <varname>$NUM_CPU</varname> environment
+ variable is set:
+
+ </para>
+
+ <scons_output example="SetOption">
+ <scons_output_command>scons -Q -j 7</scons_output_command>
+ <scons_output_command>export NUM_CPU="4"</scons_output_command>
+ <scons_output_command environment="NUM_CPU=4">scons -Q -j 3</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section id="sect-command-line-option-strings">
+ <title>Strings for Getting or Setting Values of &SCons; Command-Line Options</title>
+
+ <para>
+
+ The strings that you can pass to the &GetOption;
+ and &SetOption; functions usually correspond to the
+ first long-form option name
+ (beginning with two hyphen characters: <literal>--</literal>),
+ after replacing any remaining hyphen characters
+ with underscores.
+
+ </para>
+
+ <para>
+
+ The full list of strings and the variables they
+ correspond to is as follows:
+
+ </para>
+
+ <informaltable>
+ <tgroup cols="2" align="left">
+
+ <thead>
+
+ <row>
+ <entry>String for &GetOption; and &SetOption;</entry>
+ <entry>Command-Line Option(s)</entry>
+ </row>
+
+ </thead>
+
+ <tbody>
+
+ <row>
+ <entry><literal>cache_debug</literal></entry>
+ <entry><option>--cache-debug</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>cache_disable</literal></entry>
+ <entry><option>--cache-disable</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>cache_force</literal></entry>
+ <entry><option>--cache-force</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>cache_show</literal></entry>
+ <entry><option>--cache-show</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>clean</literal></entry>
+ <entry><option>-c</option>,
+ <option>--clean</option>,
+ <option>--remove</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>config</literal></entry>
+ <entry><option>--config</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>directory</literal></entry>
+ <entry><option>-C</option>,
+ <option>--directory</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>diskcheck</literal></entry>
+ <entry><option>--diskcheck</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>duplicate</literal></entry>
+ <entry><option>--duplicate</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>file</literal></entry>
+ <entry><option>-f</option>,
+ <option>--file</option>,
+ <option>--makefile </option>,
+ <option>--sconstruct</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>help</literal></entry>
+ <entry><option>-h</option>,
+ <option>--help</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>ignore_errors</literal></entry>
+ <entry><option>--ignore-errors</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>implicit_cache</literal></entry>
+ <entry><option>--implicit-cache</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>implicit_deps_changed</literal></entry>
+ <entry><option>--implicit-deps-changed</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>implicit_deps_unchanged</literal></entry>
+ <entry><option>--implicit-deps-unchanged</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>interactive</literal></entry>
+ <entry><option>--interact</option>,
+ <option>--interactive</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>keep_going</literal></entry>
+ <entry><option>-k</option>,
+ <option>--keep-going</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>max_drift</literal></entry>
+ <entry><option>--max-drift</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>no_exec</literal></entry>
+ <entry><option>-n</option>,
+ <option>--no-exec</option>,
+ <option>--just-print</option>,
+ <option>--dry-run</option>,
+ <option>--recon</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>no_site_dir</literal></entry>
+ <entry><option>--no-site-dir</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>num_jobs</literal></entry>
+ <entry><option>-j</option>,
+ <option>--jobs</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>profile_file</literal></entry>
+ <entry><option>--profile</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>question</literal></entry>
+ <entry><option>-q</option>,
+ <option>--question</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>random</literal></entry>
+ <entry><option>--random</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>repository</literal></entry>
+ <entry><option>-Y</option>,
+ <option>--repository</option>,
+ <option>--srcdir</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>silent</literal></entry>
+ <entry><option>-s</option>,
+ <option>--silent</option>,
+ <option>--quiet</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>site_dir</literal></entry>
+ <entry><option>--site-dir</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>stack_size</literal></entry>
+ <entry><option>--stack-size</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>taskmastertrace_file</literal></entry>
+ <entry><option>--taskmastertrace</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>warn</literal></entry>
+ <entry><option>--warn</option> <option>--warning</option></entry>
+ </row>
+
+ </tbody>
+
+ </tgroup>
+ </informaltable>
+
+ </section>
+
+ <section>
+ <title>Adding Custom Command-Line Options: the &AddOption; Function</title>
+
+ <para>
+
+ &SCons; also allows you to define your own
+ command-line options with the &AddOption; function.
+ The &AddOption; function takes the same arguments
+ as the <function>optparse.add_option</function> function
+ from the standard Python library.
+ <footnote>
+ <para>
+ The &AddOption; function is,
+ in fact, implemented using a subclass
+ of the <classname>optparse.OptionParser</classname>.
+ </para>
+ </footnote>
+ Once you have added a custom command-line option
+ with the &AddOption; function,
+ the value of the option (if any) is immediately available
+ using the standard &GetOption; function.
+ (The value can also be set using &SetOption;,
+ although that's not very useful in practice
+ because a default value can be specified in
+ directly in the &AddOption; call.)
+
+ </para>
+
+ <para>
+
+ One useful example of using this functionality
+ is to provide a <option>--prefix</option> for users:
+
+ </para>
+
+ <scons_example name="AddOption">
+ <file name="SConstruct" printme="1">
+ AddOption('--prefix',
+ dest='prefix',
+ type='string',
+ nargs=1,
+ action='store',
+ metavar='DIR',
+ help='installation prefix')
+
+ env = Environment(PREFIX = GetOption('prefix'))
+
+ installed_foo = env.Install('$PREFIX/usr/bin', 'foo.in')
+ Default(installed_foo)
+ </file>
+ <file name="foo.in">
+ foo.in
+ </file>
+ </scons_example>
+
+ <para>
+
+ The above code uses the &GetOption; function
+ to set the <varname>$PREFIX</varname>
+ construction variable to any
+ value that the user specifies with a command-line
+ option of <literal>--prefix</literal>.
+ Because <varname>$PREFIX</varname>
+ will expand to a null string if it's not initialized,
+ running &SCons; without the
+ option of <literal>--prefix</literal>
+ will install the file in the
+ <filename>/usr/bin/</filename> directory:
+
+ </para>
+
+ <scons_output example="AddOption">
+ <scons_output_command>scons -Q -n</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ But specifying <literal>--prefix=/tmp/install</literal>
+ on the command line causes the file to be installed in the
+ <filename>/tmp/install/usr/bin/</filename> directory:
+
+ </para>
+
+ <scons_output example="AddOption">
+ <scons_output_command>scons -Q -n --prefix=/tmp/install</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ </section>
+
+ <section id="sect-command-line-variables">
+ <title>Command-Line <varname>variable</varname>=<varname>value</varname> Build Variables</title>
+
+ <para>
+
+ You may want to control various aspects
+ of your build by allowing the user
+ to specify <varname>variable</varname>=<varname>value</varname>
+ values on the command line.
+ For example, suppose you
+ want users to be able to
+ build a debug version of a program
+ by running &SCons; as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q debug=1</userinput>
+ </screen>
+
+ <para>
+
+ &SCons; provides an &ARGUMENTS; dictionary
+ that stores all of the
+ <varname>variable</varname>=<varname>value</varname>
+ assignments from the command line.
+ This allows you to modify
+ aspects of your build in response
+ to specifications on the command line.
+ (Note that unless you want to require
+ that users <emphasis>always</emphasis>
+ specify a variable,
+ you probably want to use
+ the Python
+ <literal>ARGUMENTS.get()</literal> function,
+ which allows you to specify a default value
+ to be used if there is no specification
+ on the command line.)
+
+ </para>
+
+ <para>
+
+ The following code sets the &cv-link-CCFLAGS; construction
+ variable in response to the <varname>debug</varname>
+ flag being set in the &ARGUMENTS; dictionary:
+
+ </para>
+
+ <scons_example name="ARGUMENTS">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ debug = ARGUMENTS.get('debug', 0)
+ if int(debug):
+ env.Append(CCFLAGS = '-g')
+ env.Program('prog.c')
+ </file>
+ <file name="prog.c">
+ prog.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ This results in the <varname>-g</varname>
+ compiler option being used when
+ <literal>debug=1</literal>
+ is used on the command line:
+
+ </para>
+
+ <scons_output example="ARGUMENTS">
+ <scons_output_command>scons -Q debug=0</scons_output_command>
+ <scons_output_command>scons -Q debug=0</scons_output_command>
+ <scons_output_command>scons -Q debug=1</scons_output_command>
+ <scons_output_command>scons -Q debug=1</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice that &SCons; keeps track of
+ the last values used to build the object files,
+ and as a result correctly rebuilds
+ the object and executable files
+ only when the value of the <literal>debug</literal>
+ argument has changed.
+
+ </para>
+
+ <para>
+
+ The &ARGUMENTS; dictionary has two minor drawbacks.
+ First, because it is a dictionary,
+ it can only store one value for each specified keyword,
+ and thus only "remembers" the last setting
+ for each keyword on the command line.
+ This makes the &ARGUMENTS; dictionary
+ inappropriate if users should be able to
+ specify multiple values
+ on the command line for a given keyword.
+ Second, it does not preserve
+ the order in which the variable settings
+ were specified,
+ which is a problem if
+ you want the configuration to
+ behave differently in response
+ to the order in which the build
+ variable settings were specified on the command line.
+
+ </para>
+
+ <para>
+
+ To accomodate these requirements,
+ &SCons; provides an &ARGLIST; variable
+ that gives you direct access to
+ <varname>variable</varname>=<varname>value</varname>
+ settings on the command line,
+ in the exact order they were specified,
+ and without removing any duplicate settings.
+ Each element in the &ARGLIST; variable
+ is itself a two-element list
+ containing the keyword and the value
+ of the setting,
+ and you must loop through,
+ or otherwise select from,
+ the elements of &ARGLIST; to
+ process the specific settings you want
+ in whatever way is appropriate for your configuration.
+ For example,
+ the following code to let the user
+ add to the &CPPDEFINES; construction variable
+ by specifying multiple
+ <varname>define=</varname>
+ settings on the command line:
+
+ </para>
+
+ <scons_example name="ARGLIST">
+ <file name="SConstruct" printme="1">
+ cppdefines = []
+ for key, value in ARGLIST:
+ if key == 'define':
+ cppdefines.append(value)
+ env = Environment(CPPDEFINES = cppdefines)
+ env.Object('prog.c')
+ </file>
+ <file name="prog.c">
+ prog.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Yields the following output:
+
+ </para>
+
+ <scons_output example="ARGLIST">
+ <scons_output_command>scons -Q define=FOO</scons_output_command>
+ <scons_output_command>scons -Q define=FOO define=BAR</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that the &ARGLIST; and &ARGUMENTS;
+ variables do not interfere with each other,
+ but merely provide slightly different views
+ into how the user specified
+ <varname>variable</varname>=<varname>value</varname>
+ settings on the command line.
+ You can use both variables in the same
+ &SCons; configuration.
+ In general, the &ARGUMENTS; dictionary
+ is more convenient to use,
+ (since you can just fetch variable
+ settings through a dictionary access),
+ and the &ARGLIST; list
+ is more flexible
+ (since you can examine the
+ specific order in which
+ the user's command-line variabe settings).
+
+ </para>
+
+ <section>
+ <title>Controlling Command-Line Build Variables</title>
+
+ <para>
+
+ Being able to use a command-line build variable like
+ <literal>debug=1</literal> is handy,
+ but it can be a chore to write specific Python code
+ to recognize each such variable,
+ check for errors and provide appropriate messages,
+ and apply the values to a construction variable.
+ To help with this,
+ &SCons; supports a class to
+ define such build variables easily,
+ and a mechanism to apply the
+ build variables to a construction environment.
+ This allows you to control how the build variables affect
+ construction environments.
+
+ </para>
+
+ <para>
+
+ For example, suppose that you want users to set
+ a &RELEASE; construction variable on the
+ command line whenever the time comes to build
+ a program for release,
+ and that the value of this variable
+ should be added to the command line
+ with the appropriate <literal>-D</literal> option
+ (or other command line option)
+ to pass the value to the C compiler.
+ Here's how you might do that by setting
+ the appropriate value in a dictionary for the
+ &cv-link-CPPDEFINES; construction variable:
+
+ </para>
+
+ <scons_example name="Variables1">
+ <file name="SConstruct" printme="1">
+ vars = Variables()
+ vars.Add('RELEASE', 'Set to 1 to build for release', 0)
+ env = Environment(variables = vars,
+ CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
+ env.Program(['foo.c', 'bar.c'])
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="bar.c">
+ bar.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ This &SConstruct; file first creates a &Variables; object
+ (the <literal>vars = Variables()</literal> call),
+ and then uses the object's &Add;
+ method to indicate that the &RELEASE;
+ variable can be set on the command line,
+ and that its default value will be <literal>0</literal>
+ (the third argument to the &Add; method).
+ The second argument is a line of help text;
+ we'll learn how to use it in the next section.
+
+ </para>
+
+ <para>
+
+ We then pass the created &Variables;
+ object as a &variables; keyword argument
+ to the &Environment; call
+ used to create the construction environment.
+ This then allows a user to set the
+ &RELEASE; build variable on the command line
+ and have the variable show up in
+ the command line used to build each object from
+ a C source file:
+
+ </para>
+
+ <scons_output example="Variables1">
+ <scons_output_command>scons -Q RELEASE=1</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ NOTE: Before &SCons; release 0.98.1, these build variables
+ were known as "command-line build options."
+ The class was actually named the &Options; class,
+ and in the sections below,
+ the various functions were named
+ &BoolOption;, &EnumOption;, &ListOption;,
+ &PathOption;, &PackageOption; and &AddOptions;.
+ These older names still work,
+ and you may encounter them in older
+ &SConscript; fles,
+ but their use is discouraged
+ and will be officially deprecated some day.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Providing Help for Command-Line Build Variables</title>
+
+ <para>
+
+ To make command-line build variables most useful,
+ you ideally want to provide
+ some help text that will describe
+ the available variables
+ when the user runs <literal>scons -h</literal>.
+ You could write this text by hand,
+ but &SCons; provides an easier way.
+ &Variables; objects support a
+ &GenerateHelpText; method
+ that will, as its name suggests,
+ generate text that describes
+ the various variables that
+ have been added to it.
+ You then pass the output from this method to
+ the &Help; function:
+
+ </para>
+
+ <scons_example name="Variables_Help">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add('RELEASE', 'Set to 1 to build for release', 0)
+ env = Environment(variables = vars)
+ Help(vars.GenerateHelpText(env))
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; will now display some useful text
+ when the <literal>-h</literal> option is used:
+
+ </para>
+
+ <scons_output example="Variables_Help">
+ <scons_output_command>scons -Q -h</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice that the help output shows the default value,
+ and the current actual value of the build variable.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Reading Build Variables From a File</title>
+
+ <para>
+
+ Giving the user a way to specify the
+ value of a build variable on the command line
+ is useful,
+ but can still be tedious
+ if users must specify the variable
+ every time they run &SCons;.
+ We can let users provide customized build variable settings
+ in a local file by providing a
+ file name when we create the
+ &Variables; object:
+
+ </para>
+
+ <scons_example name="Variables_custom_py_1">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add('RELEASE', 'Set to 1 to build for release', 0)
+ env = Environment(variables = vars,
+ CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
+ env.Program(['foo.c', 'bar.c'])
+ Help(vars.GenerateHelpText(env))
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="bar.c">
+ bar.c
+ </file>
+ <file name="custom.py">
+ RELEASE = 1
+ </file>
+ </scons_example>
+
+ <para>
+
+ This then allows the user to control the &RELEASE;
+ variable by setting it in the &custom_py; file:
+
+ </para>
+
+ <scons_example_file example="Variables_custom_py_1" name="custom.py"></scons_example_file>
+
+ <para>
+
+ Note that this file is actually executed
+ like a Python script.
+ Now when we run &SCons;:
+
+ </para>
+
+ <scons_output example="Variables_custom_py_1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And if we change the contents of &custom_py; to:
+
+ </para>
+
+ <scons_example name="Variables_custom_py_2">
+ <file name="SConstruct">
+ vars = Variables('custom.py')
+ vars.Add('RELEASE', 'Set to 1 to build for release', 0)
+ env = Environment(variables = vars,
+ CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
+ env.Program(['foo.c', 'bar.c'])
+ Help(vars.GenerateHelpText(env))
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="bar.c">
+ bar.c
+ </file>
+ <file name="custom.py" printme="1">
+ RELEASE = 0
+ </file>
+ </scons_example>
+
+ <para>
+
+ The object files are rebuilt appropriately
+ with the new variable:
+
+ </para>
+
+ <scons_output example="Variables_custom_py_2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Pre-Defined Build Variable Functions</title>
+
+ <para>
+
+ &SCons; provides a number of functions
+ that provide ready-made behaviors
+ for various types of command-line build variables.
+
+ </para>
+
+ <section>
+ <title>True/False Values: the &BoolVariable; Build Variable Function</title>
+
+ <para>
+
+ It's often handy to be able to specify a
+ variable that controls a simple Boolean variable
+ with a &true; or &false; value.
+ It would be even more handy to accomodate
+ users who have different preferences for how to represent
+ &true; or &false; values.
+ The &BoolVariable; function
+ makes it easy to accomodate these
+ common representations of
+ &true; or &false;.
+
+ </para>
+
+ <para>
+
+ The &BoolVariable; function takes three arguments:
+ the name of the build variable,
+ the default value of the build variable,
+ and the help string for the variable.
+ It then returns appropriate information for
+ passing to the &Add; method of a &Variables; object, like so:
+
+ </para>
+
+ <scons_example name="BoolVariable">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(BoolVariable('RELEASE', 'Set to build for release', 0))
+ env = Environment(variables = vars,
+ CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ With this build variable,
+ the &RELEASE; variable can now be enabled by
+ setting it to the value <literal>yes</literal>
+ or <literal>t</literal>:
+
+ </para>
+
+ <scons_output example="BoolVariable">
+ <scons_output_command>scons -Q RELEASE=yes foo.o</scons_output_command>
+ </scons_output>
+
+ <scons_output example="BoolVariable">
+ <scons_output_command>scons -Q RELEASE=t foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Other values that equate to &true; include
+ <literal>y</literal>,
+ <literal>1</literal>,
+ <literal>on</literal>
+ and
+ <literal>all</literal>.
+
+ </para>
+
+ <para>
+
+ Conversely, &RELEASE; may now be given a &false;
+ value by setting it to
+ <literal>no</literal>
+ or
+ <literal>f</literal>:
+
+ </para>
+
+ <scons_output example="BoolVariable">
+ <scons_output_command>scons -Q RELEASE=no foo.o</scons_output_command>
+ </scons_output>
+
+ <scons_output example="BoolVariable">
+ <scons_output_command>scons -Q RELEASE=f foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Other values that equate to &false; include
+ <literal>n</literal>,
+ <literal>0</literal>,
+ <literal>off</literal>
+ and
+ <literal>none</literal>.
+
+ </para>
+
+ <para>
+
+ Lastly, if a user tries to specify
+ any other value,
+ &SCons; supplies an appropriate error message:
+
+ </para>
+
+ <scons_output example="BoolVariable">
+ <scons_output_command>scons -Q RELEASE=bad_value foo.o</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Single Value From a List: the &EnumVariable; Build Variable Function</title>
+
+ <para>
+
+ Suppose that we want a user to be able to
+ set a &COLOR; variable
+ that selects a background color to be
+ displayed by an application,
+ but that we want to restrict the
+ choices to a specific set of allowed colors.
+ This can be set up quite easily
+ using the &EnumVariable;,
+ which takes a list of &allowed_values
+ in addition to the variable name,
+ default value,
+ and help text arguments:
+
+ </para>
+
+ <scons_example name="EnumVariable">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(EnumVariable('COLOR', 'Set background color', 'red',
+ allowed_values=('red', 'green', 'blue')))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLOR' : '"${COLOR}"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ The user can now explicity set the &COLOR; build variable
+ to any of the specified allowed values:
+
+ </para>
+
+ <scons_output example="EnumVariable">
+ <scons_output_command>scons -Q COLOR=red foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLOR=blue foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLOR=green foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ But, almost more importantly,
+ an attempt to set &COLOR;
+ to a value that's not in the list
+ generates an error message:
+
+ </para>
+
+ <scons_output example="EnumVariable">
+ <scons_output_command>scons -Q COLOR=magenta foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The &EnumVariable; function also supports a way
+ to map alternate names to allowed values.
+ Suppose, for example,
+ that we want to allow the user
+ to use the word <literal>navy</literal> as a synonym for
+ <literal>blue</literal>.
+ We do this by adding a &map; dictionary
+ that will map its key values
+ to the desired legal value:
+
+ </para>
+
+ <scons_example name="EnumVariable_map">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(EnumVariable('COLOR', 'Set background color', 'red',
+ allowed_values=('red', 'green', 'blue'),
+ map={'navy':'blue'}))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLOR' : '"${COLOR}"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ As desired, the user can then use
+ <literal>navy</literal> on the command line,
+ and &SCons; will translate it into <literal>blue</literal>
+ when it comes time to use the &COLOR;
+ variable to build a target:
+
+ </para>
+
+ <scons_output example="EnumVariable_map">
+ <scons_output_command>scons -Q COLOR=navy foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ By default, when using the &EnumVariable; function,
+ arguments that differ
+ from the legal values
+ only in case
+ are treated as illegal values:
+
+ </para>
+
+ <scons_output example="EnumVariable">
+ <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLOR=BLUE foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The &EnumVariable; function can take an additional
+ &ignorecase; keyword argument that,
+ when set to <literal>1</literal>,
+ tells &SCons; to allow case differences
+ when the values are specified:
+
+ </para>
+
+ <scons_example name="EnumVariable_ic1">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(EnumVariable('COLOR', 'Set background color', 'red',
+ allowed_values=('red', 'green', 'blue'),
+ map={'navy':'blue'},
+ ignorecase=1))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLOR' : '"${COLOR}"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which yields the output:
+
+ </para>
+
+ <scons_output example="EnumVariable_ic1">
+ <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLOR=BLUE foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLOR=green foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice that an &ignorecase; value of <literal>1</literal>
+ preserves the case-spelling that the user supplied.
+ If you want &SCons; to translate the names
+ into lower-case,
+ regardless of the case used by the user,
+ specify an &ignorecase; value of <literal>2</literal>:
+
+ </para>
+
+ <scons_example name="EnumVariable_ic2">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(EnumVariable('COLOR', 'Set background color', 'red',
+ allowed_values=('red', 'green', 'blue'),
+ map={'navy':'blue'},
+ ignorecase=2))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLOR' : '"${COLOR}"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Now &SCons; will use values of
+ <literal>red</literal>,
+ <literal>green</literal> or
+ <literal>blue</literal>
+ regardless of how the user spells
+ those values on the command line:
+
+ </para>
+
+ <scons_output example="EnumVariable_ic2">
+ <scons_output_command>scons -Q COLOR=Red foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLOR=nAvY foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLOR=GREEN foo.o</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Multiple Values From a List: the &ListVariable; Build Variable Function</title>
+
+ <para>
+
+ Another way in which you might want to allow users
+ to control a build variable is to
+ specify a list of one or more legal values.
+ &SCons; supports this through the &ListVariable; function.
+ If, for example, we want a user to be able to set a
+ &COLORS; variable to one or more of the legal list of values:
+
+ </para>
+
+ <scons_example name="ListVariable">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(ListVariable('COLORS', 'List of colors', 0,
+ ['red', 'green', 'blue']))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLORS' : '"${COLORS}"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ A user can now specify a comma-separated list
+ of legal values,
+ which will get translated into a space-separated
+ list for passing to the any build commands:
+
+ </para>
+
+ <scons_output example="ListVariable">
+ <scons_output_command>scons -Q COLORS=red,blue foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLORS=blue,green,red foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In addition, the &ListVariable; function
+ allows the user to specify explicit keywords of
+ &all; or &none;
+ to select all of the legal values,
+ or none of them, respectively:
+
+ </para>
+
+ <scons_output example="ListVariable">
+ <scons_output_command>scons -Q COLORS=all foo.o</scons_output_command>
+ <scons_output_command>scons -Q COLORS=none foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And, of course, an illegal value
+ still generates an error message:
+
+ </para>
+
+ <scons_output example="ListVariable">
+ <scons_output_command>scons -Q COLORS=magenta foo.o</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Path Names: the &PathVariable; Build Variable Function</title>
+
+ <para>
+
+ &SCons; supports a &PathVariable; function
+ to make it easy to create a build variable
+ to control an expected path name.
+ If, for example, you need to
+ define a variable in the preprocessor
+ that controls the location of a
+ configuration file:
+
+ </para>
+
+ <scons_example name="PathVariable">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('CONFIG',
+ 'Path to configuration file',
+ '__ROOT__/etc/my_config'))
+ env = Environment(variables = vars,
+ CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="__ROOT__/etc/my_config">
+ /opt/location
+ </file>
+ <file name="__ROOT__/usr/local/etc/other_config">
+ /opt/location
+ </file>
+ </scons_example>
+
+ <para>
+
+ This then allows the user to
+ override the &CONFIG; build variable
+ on the command line as necessary:
+
+ </para>
+
+ <scons_output example="PathVariable">
+ <scons_output_command>scons -Q foo.o</scons_output_command>
+ <scons_output_command>scons -Q CONFIG=__ROOT__/usr/local/etc/other_config foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ By default, &PathVariable; checks to make sure
+ that the specified path exists and generates an error if it
+ doesn't:
+
+ </para>
+
+ <scons_output example="PathVariable">
+ <scons_output_command>scons -Q CONFIG=__ROOT__/does/not/exist foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ &PathVariable; provides a number of methods
+ that you can use to change this behavior.
+ If you want to ensure that any specified paths are,
+ in fact, files and not directories,
+ use the &PathVariable_PathIsFile; method:
+
+ </para>
+
+ <scons_example name="PathIsFile">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('CONFIG',
+ 'Path to configuration file',
+ '__ROOT__/etc/my_config',
+ PathVariable.PathIsFile))
+ env = Environment(variables = vars,
+ CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="__ROOT__/etc/my_config">
+ /opt/location
+ </file>
+ </scons_example>
+
+ <para>
+
+ Conversely, to ensure that any specified paths are
+ directories and not files,
+ use the &PathVariable_PathIsDir; method:
+
+ </para>
+
+ <scons_example name="PathIsDir">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('DBDIR',
+ 'Path to database directory',
+ '__ROOT__/var/my_dbdir',
+ PathVariable.PathIsDir))
+ env = Environment(variables = vars,
+ CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="__ROOT__/var/my_dbdir">
+ /opt/location
+ </file>
+ </scons_example>
+
+ <para>
+
+ If you want to make sure that any specified paths
+ are directories,
+ and you would like the directory created
+ if it doesn't already exist,
+ use the &PathVariable_PathIsDirCreate; method:
+
+ </para>
+
+ <scons_example name="PathIsDirCreate">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('DBDIR',
+ 'Path to database directory',
+ '__ROOT__/var/my_dbdir',
+ PathVariable.PathIsDirCreate))
+ env = Environment(variables = vars,
+ CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="__ROOT__/var/my_dbdir">
+ /opt/location
+ </file>
+ </scons_example>
+
+ <para>
+
+ Lastly, if you don't care whether the path exists,
+ is a file, or a directory,
+ use the &PathVariable_PathAccept; method
+ to accept any path that the user supplies:
+
+ </para>
+
+ <scons_example name="PathAccept">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('OUTPUT',
+ 'Path to output file or directory',
+ None,
+ PathVariable.PathAccept))
+ env = Environment(variables = vars,
+ CPPDEFINES={'OUTPUT' : '"$OUTPUT"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ </section>
+
+ <section>
+ <title>Enabled/Disabled Path Names: the &PackageVariable; Build Variable Function</title>
+
+ <para>
+
+ Sometimes you want to give users
+ even more control over a path name variable,
+ allowing them to explicitly enable or
+ disable the path name
+ by using <literal>yes</literal> or <literal>no</literal> keywords,
+ in addition to allow them
+ to supply an explicit path name.
+ &SCons; supports the &PackageVariable;
+ function to support this:
+
+ </para>
+
+ <scons_example name="PackageVariable">
+ <file name="SConstruct" printme="1">
+ vars = Variables('custom.py')
+ vars.Add(PackageVariable('PACKAGE',
+ 'Location package',
+ '__ROOT__/opt/location'))
+ env = Environment(variables = vars,
+ CPPDEFINES={'PACKAGE' : '"$PACKAGE"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="__ROOT__/opt/location">
+ /opt/location
+ </file>
+ <file name="__ROOT__/usr/local/location">
+ /opt/location
+ </file>
+ </scons_example>
+
+ <para>
+
+ When the &SConscript; file uses the &PackageVariable; funciton,
+ user can now still use the default
+ or supply an overriding path name,
+ but can now explicitly set the
+ specified variable to a value
+ that indicates the package should be enabled
+ (in which case the default should be used)
+ or disabled:
+
+ </para>
+
+ <scons_output example="PackageVariable">
+ <scons_output_command>scons -Q foo.o</scons_output_command>
+ <scons_output_command>scons -Q PACKAGE=__ROOT__/usr/local/location foo.o</scons_output_command>
+ <scons_output_command>scons -Q PACKAGE=yes foo.o</scons_output_command>
+ <scons_output_command>scons -Q PACKAGE=no foo.o</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Adding Multiple Command-Line Build Variables at Once</title>
+
+ <para>
+
+ Lastly, &SCons; provides a way to add
+ multiple build variables to a &Variables; object at once.
+ Instead of having to call the &Add; method
+ multiple times,
+ you can call the &AddVariables;
+ method with a list of build variables
+ to be added to the object.
+ Each build variable is specified
+ as either a tuple of arguments,
+ just like you'd pass to the &Add; method itself,
+ or as a call to one of the pre-defined
+ functions for pre-packaged command-line build variables.
+ in any order:
+
+ </para>
+
+ <scons_example name="AddVariables_1">
+ <file name="SConstruct" printme="1">
+ vars = Variables()
+ vars.AddVariables(
+ ('RELEASE', 'Set to 1 to build for release', 0),
+ ('CONFIG', 'Configuration file', '/etc/my_config'),
+ BoolVariable('warnings', 'compilation with -Wall and similiar', 1),
+ EnumVariable('debug', 'debug output and symbols', 'no',
+ allowed_values=('yes', 'no', 'full'),
+ map={}, ignorecase=0), # case sensitive
+ ListVariable('shared',
+ 'libraries to build as shared libraries',
+ 'all',
+ names = list_of_libs),
+ PackageVariable('x11',
+ 'use X11 installed here (yes = search some places)',
+ 'yes'),
+ PathVariable('qtdir', 'where the root of Qt is installed', qtdir),
+ )
+ </file>
+ </scons_example>
+
+ <para>
+ </para>
+
+ </section>
+
+ <section>
+ <title>Handling Unknown Command-Line Build Variables: the &UnknownVariables; Function</title>
+
+ <para>
+
+ Users may, of course,
+ occasionally misspell variable names in their command-line settings.
+ &SCons; does not generate an error or warning
+ for any unknown variables the users specifies on the command line.
+ (This is in no small part because you may be
+ processing the arguments directly using the &ARGUMENTS; dictionary,
+ and therefore &SCons; can't know in the general case
+ whether a given "misspelled" variable is
+ really unknown and a potential problem,
+ or something that your &SConscript; file
+ will handle directly with some Python code.)
+
+ </para>
+
+ <para>
+
+ If, however, you're using a &Variables; object to
+ define a specific set of command-line build variables
+ that you expect users to be able to set,
+ you may want to provide an error
+ message or warning of your own
+ if the user supplies a variable setting
+ that is <emphasis>not</emphasis> among
+ the defined list of variable names known to the &Variables; object.
+ You can do this by calling the &UnknownVariables;
+ method of the &Variables; object:
+
+ </para>
+
+ <scons_example name="UnknownVariables">
+ <file name="SConstruct" printme="1">
+ vars = Variables(None)
+ vars.Add('RELEASE', 'Set to 1 to build for release', 0)
+ env = Environment(variables = vars,
+ CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
+ unknown = vars.UnknownVariables()
+ if unknown:
+ print "Unknown variables:", unknown.keys()
+ Exit(1)
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ The &UnknownVariables; method returns a dictionary
+ containing the keywords and values
+ of any variables the user specified on the command line
+ that are <emphasis>not</emphasis>
+ among the variables known to the &Variables; object
+ (from having been specified using
+ the &Variables; object's&Add; method).
+ In the examble above,
+ we check for whether the dictionary
+ returned by the &UnknownVariables; is non-empty,
+ and if so print the Python list
+ containing the names of the unknwown variables
+ and then call the &Exit; function
+ to terminate &SCons;:
+
+ </para>
+
+ <scons_output example="UnknownVariables">
+ <scons_output_command>scons -Q NOT_KNOWN=foo</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Of course, you can process the items in the
+ dictionary returned by the &UnknownVariables; function
+ in any way appropriate to your build configuration,
+ including just printing a warning message
+ but not exiting,
+ logging an error somewhere,
+ etc.
+
+ </para>
+
+ <para>
+
+ Note that you must delay the call of &UnknownVariables;
+ until after you have applied the &Variables; object
+ to a construction environment
+ with the <literal>variables=</literal>
+ keyword argument of an &Environment; call.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="sect-command-line-targets">
+ <title>Command-Line Targets</title>
+
+ <section>
+ <title>Fetching Command-Line Targets: the &COMMAND_LINE_TARGETS; Variable</title>
+
+ <para>
+
+ &SCons; supports a &COMMAND_LINE_TARGETS; variable
+ that lets you fetch the list of targets that the
+ user specified on the command line.
+ You can use the targets to manipulate the
+ build in any way you wish.
+ As a simple example,
+ suppose that you want to print a reminder
+ to the user whenever a specific program is built.
+ You can do this by checking for the
+ target in the &COMMAND_LINE_TARGETS; list:
+
+ </para>
+
+ <scons_example name="COMMAND_LINE_TARGETS">
+ <file name="SConstruct" printme="1">
+ if 'bar' in COMMAND_LINE_TARGETS:
+ print "Don't forget to copy `bar' to the archive!"
+ Default(Program('foo.c'))
+ Program('bar.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="bar.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then, running &SCons; with the default target
+ works as it always does,
+ but explicity specifying the &bar; target
+ on the command line generates the warning message:
+
+ </para>
+
+ <scons_output example="COMMAND_LINE_TARGETS">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q bar</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Another practical use for the &COMMAND_LINE_TARGETS; variable
+ might be to speed up a build
+ by only reading certain subsidiary &SConscript;
+ files if a specific target is requested.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Controlling the Default Targets: the &Default; Function</title>
+
+ <para>
+
+ One of the most basic things you can control
+ is which targets &SCons; will build by default--that is,
+ when there are no targets specified on the command line.
+ As mentioned previously,
+ &SCons; will normally build every target
+ in or below the current directory
+ by default--that is, when you don't
+ explicitly specify one or more targets
+ on the command line.
+ Sometimes, however, you may want
+ to specify explicitly that only
+ certain programs, or programs in certain directories,
+ should be built by default.
+ You do this with the &Default; function:
+
+ </para>
+
+ <scons_example name="Default1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Program('goodbye.c')
+ Default(hello)
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ <file name="goodbye.c">
+ goodbye.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ This &SConstruct; file knows how to build two programs,
+ &hello; and &goodbye;,
+ but only builds the
+ &hello; program by default:
+
+ </para>
+
+ <scons_output example="Default1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q goodbye</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that, even when you use the &Default;
+ function in your &SConstruct; file,
+ you can still explicitly specify the current directory
+ (<literal>.</literal>) on the command line
+ to tell &SCons; to build
+ everything in (or below) the current directory:
+
+ </para>
+
+ <scons_output example="Default1">
+ <scons_output_command>scons -Q .</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ You can also call the &Default;
+ function more than once,
+ in which case each call
+ adds to the list of targets to be built by default:
+
+ </para>
+
+ <scons_example name="Default2">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ prog1 = env.Program('prog1.c')
+ Default(prog1)
+ prog2 = env.Program('prog2.c')
+ prog3 = env.Program('prog3.c')
+ Default(prog3)
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ <file name="prog2.c">
+ prog2.c
+ </file>
+ <file name="prog3.c">
+ prog3.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Or you can specify more than one target
+ in a single call to the &Default; function:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ prog1 = env.Program('prog1.c')
+ prog2 = env.Program('prog2.c')
+ prog3 = env.Program('prog3.c')
+ Default(prog1, prog3)
+ </programlisting>
+
+ <para>
+
+ Either of these last two examples
+ will build only the
+ <application>prog1</application>
+ and
+ <application>prog3</application>
+ programs by default:
+
+ </para>
+
+ <scons_output example="Default2">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q .</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ You can list a directory as
+ an argument to &Default;:
+
+ </para>
+
+ <scons_example name="Default3">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Program(['prog1/main.c', 'prog1/foo.c'])
+ env.Program(['prog2/main.c', 'prog2/bar.c'])
+ Default('prog1')
+ </file>
+ <directory name="prog1"></directory>
+ <directory name="prog2"></directory>
+ <file name="prog1/main.c">
+ int main() { printf("prog1/main.c\n"); }
+ </file>
+ <file name="prog1/foo.c">
+ int foo() { printf("prog1/foo.c\n"); }
+ </file>
+ <file name="prog2/main.c">
+ int main() { printf("prog2/main.c\n"); }
+ </file>
+ <file name="prog2/bar.c">
+ int bar() { printf("prog2/bar.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ In which case only the target(s) in that
+ directory will be built by default:
+
+ </para>
+
+ <scons_output example="Default3">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q .</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Lastly, if for some reason you don't want
+ any targets built by default,
+ you can use the Python <literal>None</literal>
+ variable:
+
+ </para>
+
+ <scons_example name="Default4">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ prog1 = env.Program('prog1.c')
+ prog2 = env.Program('prog2.c')
+ Default(None)
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ <file name="prog2.c">
+ prog2.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which would produce build output like:
+
+ </para>
+
+ <scons_output example="Default4">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q .</scons_output_command>
+ </scons_output>
+
+ <section>
+ <title>Fetching the List of Default Targets: the &DEFAULT_TARGETS; Variable</title>
+
+ <para>
+
+ &SCons; supports a &DEFAULT_TARGETS; variable
+ that lets you get at the current list of default targets.
+ The &DEFAULT_TARGETS variable has
+ two important differences from the &COMMAND_LINE_TARGETS; variable.
+ First, the &DEFAULT_TARGETS; variable is a list of
+ internal &SCons; nodes,
+ so you need to convert the list elements to strings
+ if you want to print them or look for a specific target name.
+ Fortunately, you can do this easily
+ by using the Python <function>map</function> function
+ to run the list through <function>str</function>:
+
+ </para>
+
+ <scons_example name="DEFAULT_TARGETS_1">
+ <file name="SConstruct" printme="1">
+ prog1 = Program('prog1.c')
+ Default(prog1)
+ print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS)
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ (Keep in mind that all of the manipulation of the
+ &DEFAULT_TARGETS; list takes place during the
+ first phase when &SCons; is reading up the &SConscript; files,
+ which is obvious if
+ we leave off the <literal>-Q</literal> flag when we run &SCons;:)
+
+ </para>
+
+ <scons_output example="DEFAULT_TARGETS_1">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Second,
+ the contents of the &DEFAULT_TARGETS; list change
+ in response to calls to the &Default: function,
+ as you can see from the following &SConstruct; file:
+
+ </para>
+
+ <scons_example name="DEFAULT_TARGETS_2">
+ <file name="SConstruct" printme="1">
+ prog1 = Program('prog1.c')
+ Default(prog1)
+ print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
+ prog2 = Program('prog2.c')
+ Default(prog2)
+ print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ <file name="prog2.c">
+ prog2.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which yields the output:
+
+ </para>
+
+ <scons_output example="DEFAULT_TARGETS_2">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In practice, this simply means that you
+ need to pay attention to the order in
+ which you call the &Default; function
+ and refer to the &DEFAULT_TARGETS; list,
+ to make sure that you don't examine the
+ list before you've added the default targets
+ you expect to find in it.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Fetching the List of Build Targets, Regardless of Origin: the &BUILD_TARGETS; Variable</title>
+
+ <para>
+
+ We've already been introduced to the
+ &COMMAND_LINE_TARGETS; variable,
+ which contains a list of targets specified on the command line,
+ and the &DEFAULT_TARGETS; variable,
+ which contains a list of targets specified
+ via calls to the &Default; method or function.
+ Sometimes, however,
+ you want a list of whatever targets
+ &SCons; will try to build,
+ regardless of whether the targets came from the
+ command line or a &Default; call.
+ You could code this up by hand, as follows:
+
+ </para>
+
+ <sconstruct>
+ if COMMAND_LINE_TARGETS:
+ targets = COMMAND_LINE_TARGETS
+ else:
+ targets = DEFAULT_TARGETS
+ </sconstruct>
+
+ <para>
+
+ &SCons;, however, provides a convenient
+ &BUILD_TARGETS; variable
+ that eliminates the need for this by-hand manipulation.
+ Essentially, the &BUILD_TARGETS; variable
+ contains a list of the command-line targets,
+ if any were specified,
+ and if no command-line targets were specified,
+ it contains a list of the targets specified
+ via the &Default; method or function.
+
+ </para>
+
+ <para>
+
+ Because &BUILD_TARGETS; may contain a list of &SCons; nodes,
+ you must convert the list elements to strings
+ if you want to print them or look for a specific target name,
+ just like the &DEFAULT_TARGETS; list:
+
+ </para>
+
+ <scons_example name="BUILD_TARGETS_1">
+ <file name="SConstruct" printme="1">
+ prog1 = Program('prog1.c')
+ Program('prog2.c')
+ Default(prog1)
+ print "BUILD_TARGETS is", map(str, BUILD_TARGETS)
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ <file name="prog2.c">
+ prog2.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Notice how the value of &BUILD_TARGETS;
+ changes depending on whether a target is
+ specified on the command line:
+
+ </para>
+
+ <scons_output example="BUILD_TARGETS_1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q prog2</scons_output_command>
+ <scons_output_command>scons -Q -c .</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ </section>
diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml
new file mode 100644
index 0000000..630a9b2
--- /dev/null
+++ b/doc/user/command-line.xml
@@ -0,0 +1,2243 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; provides a number of ways
+ for the writer of the &SConscript; files
+ to give the users who will run &SCons;
+ a great deal of control over the build execution.
+ The arguments that the user can specify on
+ the command line are broken down into three types:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>Options</term>
+
+ <listitem>
+ <para>
+
+ Command-line options always begin with
+ one or two <literal>-</literal> (hyphen) characters.
+ &SCons; provides ways for you to examine
+ and set options values from within your &SConscript; files,
+ as well as the ability to define your own
+ custom options.
+ See <xref linkend="sect-command-line-options"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Variables</term>
+
+ <listitem>
+ <para>
+
+ Any command-line argument containing an <literal>=</literal>
+ (equal sign) is considered a variable setting with the form
+ <varname>variable</varname>=<varname>value</varname>
+ &SCons; provides direct access to
+ all of the command-line variable settings,
+ the ability to apply command-line variable settings
+ to construction environments,
+ and functions for configuring
+ specific types of variables
+ (Boolean values, path names, etc.)
+ with automatic validation of the user's specified values.
+ See <xref linkend="sect-command-line-variables"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Targets</term>
+
+ <listitem>
+ <para>
+
+ Any command-line argument that is not an option
+ or a variable setting
+ (does not begin with a hyphen
+ and does not contain an equal sign)
+ is considered a target that the user
+ (presumably) wants &SCons; to build.
+ A list of Node objects representing
+ the target or targets to build.
+ &SCons; provides access to the list of specified targets,
+ as well as ways to set the default list of targets
+ from within the &SConscript; files.
+ See <xref linkend="sect-command-line-targets"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <section id="sect-command-line-options">
+ <title>Command-Line Options</title>
+
+ <para>
+
+ &SCons; has many <emphasis>command-line options</emphasis>
+ that control its behavior.
+ A &SCons; <emphasis>command-line option</emphasis>
+ always begins with one or two <literal>-</literal> (hyphen)
+ characters.
+
+ </para>
+
+ <section>
+ <title>Not Having to Specify Command-Line Options Each Time: the &SCONSFLAGS; Environment Variable</title>
+
+ <para>
+
+ Users may find themselves supplying
+ the same command-line options every time
+ they run &SCons;.
+ For example, you might find it saves time
+ to specify a value of <literal>-j 2</literal>
+ to have &SCons; run up to two build commands in parallel.
+ To avoid having to type <literal>-j 2</literal> by hand
+ every time,
+ you can set the external environment variable
+ &SCONSFLAGS; to a string containing
+ command-line options that you want &SCons; to use.
+
+ </para>
+
+ <para>
+
+ If, for example,
+ you're using a POSIX shell that's
+ compatible with the Bourne shell,
+ and you always want &SCons; to use the
+ <literal>-Q</literal> option,
+ you can set the &SCONSFLAGS;
+ environment as follows:
+
+ </para>
+
+
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ ... [build output] ...
+ scons: done building targets.
+ % <userinput>export SCONSFLAGS="-Q"</userinput>
+ % <userinput>scons</userinput>
+ ... [build output] ...
+ </screen>
+
+ <para>
+
+ Users of &csh;-style shells on POSIX systems
+ can set the &SCONSFLAGS; environment as follows:
+
+ </para>
+
+ <screen>
+ $ <userinput>setenv SCONSFLAGS "-Q"</userinput>
+ </screen>
+
+ <para>
+
+ Windows users may typically want to set the
+ &SCONSFLAGS; in the appropriate tab of the
+ <literal>System Properties</literal> window.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Getting Values Set by Command-Line Options: the &GetOption; Function</title>
+
+ <para>
+
+ &SCons; provides the &GetOption; function
+ to get the values set by the various command-line options.
+ One common use of this is to check whether or not
+ the <literal>-h</literal> or <literal>--help</literal> option
+ has been specified.
+ Normally, &SCons; does not print its help text
+ until after it has read all of the &SConscript; files,
+ because it's possible that help text has been added
+ by some subsidiary &SConscript; file deep in the
+ source tree hierarchy.
+ Of course, reading all of the &SConscript; files
+ takes extra time.
+
+ </para>
+
+ <para>
+
+ If you know that your configuration does not define
+ any additional help text in subsidiary &SConscript; files,
+ you can speed up the command-line help available to users
+ by using the &GetOption; function to load the
+ subsidiary &SConscript; files only if the
+ the user has <emphasis>not</emphasis> specified
+ the <literal>-h</literal> or <literal>--help</literal> option,
+ like so:
+
+ </para>
+
+ <programlisting></programlisting>
+
+ <para>
+
+ In general, the string that you pass to the
+ &GetOption; function to fetch the value of a command-line
+ option setting is the same as the "most common" long option name
+ (beginning with two hyphen characters),
+ although there are some exceptions.
+ The list of &SCons; command-line options
+ and the &GetOption; strings for fetching them,
+ are available in the
+ <xref linkend="sect-command-line-option-strings"></xref> section,
+ below.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Setting Values of Command-Line Options: the &SetOption; Function</title>
+
+ <para>
+
+ You can also set the values of &SCons;
+ command-line options from within the &SConscript; files
+ by using the &SetOption; function.
+ The strings that you use to set the values of &SCons;
+ command-line options are available in the
+ <xref linkend="sect-command-line-option-strings"></xref> section,
+ below.
+
+ </para>
+
+ <para>
+
+ One use of the &SetOption; function is to
+ specify a value for the <literal>-j</literal>
+ or <literal>--jobs</literal> option,
+ so that users get the improved performance
+ of a parallel build without having to specify the option by hand.
+ A complicating factor is that a good value
+ for the <literal>-j</literal> option is
+ somewhat system-dependent.
+ One rough guideline is that the more processors
+ your system has,
+ the higher you want to set the
+ <literal>-j</literal> value,
+ in order to take advantage of the number of CPUs.
+
+ </para>
+
+ <para>
+
+ For example, suppose the administrators
+ of your development systems
+ have standardized on setting a
+ <varname>NUM_CPU</varname> environment variable
+ to the number of processors on each system.
+ A little bit of Python code
+ to access the environment variable
+ and the &SetOption; function
+ provide the right level of flexibility:
+
+ </para>
+
+ <programlisting>
+ import os
+ num_cpu = int(os.environ.get('NUM_CPU', 2))
+ SetOption('num_jobs', num_cpu)
+ print "running with -j", GetOption('num_jobs')
+ </programlisting>
+
+ <para>
+
+ The above snippet of code
+ sets the value of the <literal>--jobs</literal> option
+ to the value specified in the
+ <varname>$NUM_CPU</varname> environment variable.
+ (This is one of the exception cases
+ where the string is spelled differently from
+ the from command-line option.
+ The string for fetching or setting the <literal>--jobs</literal>
+ value is <literal>num_jobs</literal>
+ for historical reasons.)
+ The code in this example prints the <literal>num_jobs</literal>
+ value for illustrative purposes.
+ It uses a default value of <literal>2</literal>
+ to provide some minimal parallelism even on
+ single-processor systems:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ running with -j 2
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ But if the <varname>$NUM_CPU</varname>
+ environment variable is set,
+ then we use that for the default number of jobs:
+
+ </para>
+
+ <screen>
+ % <userinput>export NUM_CPU="4"</userinput>
+ % <userinput>scons -Q</userinput>
+ running with -j 4
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ But any explicit
+ <literal>-j</literal> or <literal>--jobs</literal>
+ value the user specifies an the command line is used first,
+ regardless of whether or not
+ the <varname>$NUM_CPU</varname> environment
+ variable is set:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q -j 7</userinput>
+ running with -j 7
+ scons: `.' is up to date.
+ % <userinput>export NUM_CPU="4"</userinput>
+ % <userinput>scons -Q -j 3</userinput>
+ running with -j 3
+ scons: `.' is up to date.
+ </screen>
+
+ </section>
+
+ <section id="sect-command-line-option-strings">
+ <title>Strings for Getting or Setting Values of &SCons; Command-Line Options</title>
+
+ <para>
+
+ The strings that you can pass to the &GetOption;
+ and &SetOption; functions usually correspond to the
+ first long-form option name
+ (beginning with two hyphen characters: <literal>--</literal>),
+ after replacing any remaining hyphen characters
+ with underscores.
+
+ </para>
+
+ <para>
+
+ The full list of strings and the variables they
+ correspond to is as follows:
+
+ </para>
+
+ <informaltable>
+ <tgroup cols="2" align="left">
+
+ <thead>
+
+ <row>
+ <entry>String for &GetOption; and &SetOption;</entry>
+ <entry>Command-Line Option(s)</entry>
+ </row>
+
+ </thead>
+
+ <tbody>
+
+ <row>
+ <entry><literal>cache_debug</literal></entry>
+ <entry><option>--cache-debug</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>cache_disable</literal></entry>
+ <entry><option>--cache-disable</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>cache_force</literal></entry>
+ <entry><option>--cache-force</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>cache_show</literal></entry>
+ <entry><option>--cache-show</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>clean</literal></entry>
+ <entry><option>-c</option>,
+ <option>--clean</option>,
+ <option>--remove</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>config</literal></entry>
+ <entry><option>--config</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>directory</literal></entry>
+ <entry><option>-C</option>,
+ <option>--directory</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>diskcheck</literal></entry>
+ <entry><option>--diskcheck</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>duplicate</literal></entry>
+ <entry><option>--duplicate</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>file</literal></entry>
+ <entry><option>-f</option>,
+ <option>--file</option>,
+ <option>--makefile </option>,
+ <option>--sconstruct</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>help</literal></entry>
+ <entry><option>-h</option>,
+ <option>--help</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>ignore_errors</literal></entry>
+ <entry><option>--ignore-errors</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>implicit_cache</literal></entry>
+ <entry><option>--implicit-cache</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>implicit_deps_changed</literal></entry>
+ <entry><option>--implicit-deps-changed</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>implicit_deps_unchanged</literal></entry>
+ <entry><option>--implicit-deps-unchanged</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>interactive</literal></entry>
+ <entry><option>--interact</option>,
+ <option>--interactive</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>keep_going</literal></entry>
+ <entry><option>-k</option>,
+ <option>--keep-going</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>max_drift</literal></entry>
+ <entry><option>--max-drift</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>no_exec</literal></entry>
+ <entry><option>-n</option>,
+ <option>--no-exec</option>,
+ <option>--just-print</option>,
+ <option>--dry-run</option>,
+ <option>--recon</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>no_site_dir</literal></entry>
+ <entry><option>--no-site-dir</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>num_jobs</literal></entry>
+ <entry><option>-j</option>,
+ <option>--jobs</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>profile_file</literal></entry>
+ <entry><option>--profile</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>question</literal></entry>
+ <entry><option>-q</option>,
+ <option>--question</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>random</literal></entry>
+ <entry><option>--random</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>repository</literal></entry>
+ <entry><option>-Y</option>,
+ <option>--repository</option>,
+ <option>--srcdir</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>silent</literal></entry>
+ <entry><option>-s</option>,
+ <option>--silent</option>,
+ <option>--quiet</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>site_dir</literal></entry>
+ <entry><option>--site-dir</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>stack_size</literal></entry>
+ <entry><option>--stack-size</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>taskmastertrace_file</literal></entry>
+ <entry><option>--taskmastertrace</option></entry>
+ </row>
+
+ <row>
+ <entry><literal>warn</literal></entry>
+ <entry><option>--warn</option> <option>--warning</option></entry>
+ </row>
+
+ </tbody>
+
+ </tgroup>
+ </informaltable>
+
+ </section>
+
+ <section>
+ <title>Adding Custom Command-Line Options: the &AddOption; Function</title>
+
+ <para>
+
+ &SCons; also allows you to define your own
+ command-line options with the &AddOption; function.
+ The &AddOption; function takes the same arguments
+ as the <function>optparse.add_option</function> function
+ from the standard Python library.
+ <footnote>
+ <para>
+ The &AddOption; function is,
+ in fact, implemented using a subclass
+ of the <classname>optparse.OptionParser</classname>.
+ </para>
+ </footnote>
+ Once you have added a custom command-line option
+ with the &AddOption; function,
+ the value of the option (if any) is immediately available
+ using the standard &GetOption; function.
+ (The value can also be set using &SetOption;,
+ although that's not very useful in practice
+ because a default value can be specified in
+ directly in the &AddOption; call.)
+
+ </para>
+
+ <para>
+
+ One useful example of using this functionality
+ is to provide a <option>--prefix</option> for users:
+
+ </para>
+
+ <programlisting>
+ AddOption('--prefix',
+ dest='prefix',
+ type='string',
+ nargs=1,
+ action='store',
+ metavar='DIR',
+ help='installation prefix')
+
+ env = Environment(PREFIX = GetOption('prefix'))
+
+ installed_foo = env.Install('$PREFIX/usr/bin', 'foo.in')
+ Default(installed_foo)
+ </programlisting>
+
+ <para>
+
+ The above code uses the &GetOption; function
+ to set the <varname>$PREFIX</varname>
+ construction variable to any
+ value that the user specifies with a command-line
+ option of <literal>--prefix</literal>.
+ Because <varname>$PREFIX</varname>
+ will expand to a null string if it's not initialized,
+ running &SCons; without the
+ option of <literal>--prefix</literal>
+ will install the file in the
+ <filename>/usr/bin/</filename> directory:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q -n</userinput>
+ Install file: "foo.in" as "/usr/bin/foo.in"
+ </screen>
+
+ <para>
+
+ But specifying <literal>--prefix=/tmp/install</literal>
+ on the command line causes the file to be installed in the
+ <filename>/tmp/install/usr/bin/</filename> directory:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q -n --prefix=/tmp/install</userinput>
+ Install file: "foo.in" as "/tmp/install/usr/bin/foo.in"
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section id="sect-command-line-variables">
+ <title>Command-Line <varname>variable</varname>=<varname>value</varname> Build Variables</title>
+
+ <para>
+
+ You may want to control various aspects
+ of your build by allowing the user
+ to specify <varname>variable</varname>=<varname>value</varname>
+ values on the command line.
+ For example, suppose you
+ want users to be able to
+ build a debug version of a program
+ by running &SCons; as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q debug=1</userinput>
+ </screen>
+
+ <para>
+
+ &SCons; provides an &ARGUMENTS; dictionary
+ that stores all of the
+ <varname>variable</varname>=<varname>value</varname>
+ assignments from the command line.
+ This allows you to modify
+ aspects of your build in response
+ to specifications on the command line.
+ (Note that unless you want to require
+ that users <emphasis>always</emphasis>
+ specify a variable,
+ you probably want to use
+ the Python
+ <literal>ARGUMENTS.get()</literal> function,
+ which allows you to specify a default value
+ to be used if there is no specification
+ on the command line.)
+
+ </para>
+
+ <para>
+
+ The following code sets the &cv-link-CCFLAGS; construction
+ variable in response to the <varname>debug</varname>
+ flag being set in the &ARGUMENTS; dictionary:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ debug = ARGUMENTS.get('debug', 0)
+ if int(debug):
+ env.Append(CCFLAGS = '-g')
+ env.Program('prog.c')
+ </programlisting>
+
+ <para>
+
+ This results in the <varname>-g</varname>
+ compiler option being used when
+ <literal>debug=1</literal>
+ is used on the command line:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q debug=0</userinput>
+ cc -o prog.o -c prog.c
+ cc -o prog prog.o
+ % <userinput>scons -Q debug=0</userinput>
+ scons: `.' is up to date.
+ % <userinput>scons -Q debug=1</userinput>
+ scons: `.' is up to date.
+ % <userinput>scons -Q debug=1</userinput>
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Notice that &SCons; keeps track of
+ the last values used to build the object files,
+ and as a result correctly rebuilds
+ the object and executable files
+ only when the value of the <literal>debug</literal>
+ argument has changed.
+
+ </para>
+
+ <para>
+
+ The &ARGUMENTS; dictionary has two minor drawbacks.
+ First, because it is a dictionary,
+ it can only store one value for each specified keyword,
+ and thus only "remembers" the last setting
+ for each keyword on the command line.
+ This makes the &ARGUMENTS; dictionary
+ inappropriate if users should be able to
+ specify multiple values
+ on the command line for a given keyword.
+ Second, it does not preserve
+ the order in which the variable settings
+ were specified,
+ which is a problem if
+ you want the configuration to
+ behave differently in response
+ to the order in which the build
+ variable settings were specified on the command line.
+
+ </para>
+
+ <para>
+
+ To accomodate these requirements,
+ &SCons; provides an &ARGLIST; variable
+ that gives you direct access to
+ <varname>variable</varname>=<varname>value</varname>
+ settings on the command line,
+ in the exact order they were specified,
+ and without removing any duplicate settings.
+ Each element in the &ARGLIST; variable
+ is itself a two-element list
+ containing the keyword and the value
+ of the setting,
+ and you must loop through,
+ or otherwise select from,
+ the elements of &ARGLIST; to
+ process the specific settings you want
+ in whatever way is appropriate for your configuration.
+ For example,
+ the following code to let the user
+ add to the &CPPDEFINES; construction variable
+ by specifying multiple
+ <varname>define=</varname>
+ settings on the command line:
+
+ </para>
+
+ <programlisting>
+ cppdefines = []
+ for key, value in ARGLIST:
+ if key == 'define':
+ cppdefines.append(value)
+ env = Environment(CPPDEFINES = cppdefines)
+ env.Object('prog.c')
+ </programlisting>
+
+ <para>
+
+ Yields the following output:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q define=FOO</userinput>
+ cc -o prog.o -c -DFOO prog.c
+ % <userinput>scons -Q define=FOO define=BAR</userinput>
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Note that the &ARGLIST; and &ARGUMENTS;
+ variables do not interfere with each other,
+ but merely provide slightly different views
+ into how the user specified
+ <varname>variable</varname>=<varname>value</varname>
+ settings on the command line.
+ You can use both variables in the same
+ &SCons; configuration.
+ In general, the &ARGUMENTS; dictionary
+ is more convenient to use,
+ (since you can just fetch variable
+ settings through a dictionary access),
+ and the &ARGLIST; list
+ is more flexible
+ (since you can examine the
+ specific order in which
+ the user's command-line variabe settings).
+
+ </para>
+
+ <section>
+ <title>Controlling Command-Line Build Variables</title>
+
+ <para>
+
+ Being able to use a command-line build variable like
+ <literal>debug=1</literal> is handy,
+ but it can be a chore to write specific Python code
+ to recognize each such variable,
+ check for errors and provide appropriate messages,
+ and apply the values to a construction variable.
+ To help with this,
+ &SCons; supports a class to
+ define such build variables easily,
+ and a mechanism to apply the
+ build variables to a construction environment.
+ This allows you to control how the build variables affect
+ construction environments.
+
+ </para>
+
+ <para>
+
+ For example, suppose that you want users to set
+ a &RELEASE; construction variable on the
+ command line whenever the time comes to build
+ a program for release,
+ and that the value of this variable
+ should be added to the command line
+ with the appropriate <literal>-D</literal> option
+ (or other command line option)
+ to pass the value to the C compiler.
+ Here's how you might do that by setting
+ the appropriate value in a dictionary for the
+ &cv-link-CPPDEFINES; construction variable:
+
+ </para>
+
+ <programlisting>
+ vars = Variables()
+ vars.Add('RELEASE', 'Set to 1 to build for release', 0)
+ env = Environment(variables = vars,
+ CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
+ env.Program(['foo.c', 'bar.c'])
+ </programlisting>
+
+ <para>
+
+ This &SConstruct; file first creates a &Variables; object
+ (the <literal>vars = Variables()</literal> call),
+ and then uses the object's &Add;
+ method to indicate that the &RELEASE;
+ variable can be set on the command line,
+ and that its default value will be <literal>0</literal>
+ (the third argument to the &Add; method).
+ The second argument is a line of help text;
+ we'll learn how to use it in the next section.
+
+ </para>
+
+ <para>
+
+ We then pass the created &Variables;
+ object as a &variables; keyword argument
+ to the &Environment; call
+ used to create the construction environment.
+ This then allows a user to set the
+ &RELEASE; build variable on the command line
+ and have the variable show up in
+ the command line used to build each object from
+ a C source file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q RELEASE=1</userinput>
+ cc -o bar.o -c -DRELEASE_BUILD=1 bar.c
+ cc -o foo.o -c -DRELEASE_BUILD=1 foo.c
+ cc -o foo foo.o bar.o
+ </screen>
+
+ <para>
+
+ NOTE: Before &SCons; release 0.98.1, these build variables
+ were known as "command-line build options."
+ The class was actually named the &Options; class,
+ and in the sections below,
+ the various functions were named
+ &BoolOption;, &EnumOption;, &ListOption;,
+ &PathOption;, &PackageOption; and &AddOptions;.
+ These older names still work,
+ and you may encounter them in older
+ &SConscript; fles,
+ but their use is discouraged
+ and will be officially deprecated some day.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Providing Help for Command-Line Build Variables</title>
+
+ <para>
+
+ To make command-line build variables most useful,
+ you ideally want to provide
+ some help text that will describe
+ the available variables
+ when the user runs <literal>scons -h</literal>.
+ You could write this text by hand,
+ but &SCons; provides an easier way.
+ &Variables; objects support a
+ &GenerateHelpText; method
+ that will, as its name suggests,
+ generate text that describes
+ the various variables that
+ have been added to it.
+ You then pass the output from this method to
+ the &Help; function:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add('RELEASE', 'Set to 1 to build for release', 0)
+ env = Environment(variables = vars)
+ Help(vars.GenerateHelpText(env))
+ </programlisting>
+
+ <para>
+
+ &SCons; will now display some useful text
+ when the <literal>-h</literal> option is used:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q -h</userinput>
+
+ RELEASE: Set to 1 to build for release
+ default: 0
+ actual: 0
+
+ Use scons -H for help about command-line options.
+ </screen>
+
+ <para>
+
+ Notice that the help output shows the default value,
+ and the current actual value of the build variable.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Reading Build Variables From a File</title>
+
+ <para>
+
+ Giving the user a way to specify the
+ value of a build variable on the command line
+ is useful,
+ but can still be tedious
+ if users must specify the variable
+ every time they run &SCons;.
+ We can let users provide customized build variable settings
+ in a local file by providing a
+ file name when we create the
+ &Variables; object:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add('RELEASE', 'Set to 1 to build for release', 0)
+ env = Environment(variables = vars,
+ CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
+ env.Program(['foo.c', 'bar.c'])
+ Help(vars.GenerateHelpText(env))
+ </programlisting>
+
+ <para>
+
+ This then allows the user to control the &RELEASE;
+ variable by setting it in the &custom_py; file:
+
+ </para>
+
+ <programlisting>
+ RELEASE = 1
+ </programlisting>
+
+ <para>
+
+ Note that this file is actually executed
+ like a Python script.
+ Now when we run &SCons;:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o bar.o -c -DRELEASE_BUILD=1 bar.c
+ cc -o foo.o -c -DRELEASE_BUILD=1 foo.c
+ cc -o foo foo.o bar.o
+ </screen>
+
+ <para>
+
+ And if we change the contents of &custom_py; to:
+
+ </para>
+
+ <programlisting>
+ RELEASE = 0
+ </programlisting>
+
+ <para>
+
+ The object files are rebuilt appropriately
+ with the new variable:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o bar.o -c -DRELEASE_BUILD=0 bar.c
+ cc -o foo.o -c -DRELEASE_BUILD=0 foo.c
+ cc -o foo foo.o bar.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Pre-Defined Build Variable Functions</title>
+
+ <para>
+
+ &SCons; provides a number of functions
+ that provide ready-made behaviors
+ for various types of command-line build variables.
+
+ </para>
+
+ <section>
+ <title>True/False Values: the &BoolVariable; Build Variable Function</title>
+
+ <para>
+
+ It's often handy to be able to specify a
+ variable that controls a simple Boolean variable
+ with a &true; or &false; value.
+ It would be even more handy to accomodate
+ users who have different preferences for how to represent
+ &true; or &false; values.
+ The &BoolVariable; function
+ makes it easy to accomodate these
+ common representations of
+ &true; or &false;.
+
+ </para>
+
+ <para>
+
+ The &BoolVariable; function takes three arguments:
+ the name of the build variable,
+ the default value of the build variable,
+ and the help string for the variable.
+ It then returns appropriate information for
+ passing to the &Add; method of a &Variables; object, like so:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(BoolVariable('RELEASE', 'Set to build for release', 0))
+ env = Environment(variables = vars,
+ CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ With this build variable,
+ the &RELEASE; variable can now be enabled by
+ setting it to the value <literal>yes</literal>
+ or <literal>t</literal>:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q RELEASE=yes foo.o</userinput>
+ cc -o foo.o -c -DRELEASE_BUILD=True foo.c
+ </screen>
+
+ <screen>
+ % <userinput>scons -Q RELEASE=t foo.o</userinput>
+ cc -o foo.o -c -DRELEASE_BUILD=True foo.c
+ </screen>
+
+ <para>
+
+ Other values that equate to &true; include
+ <literal>y</literal>,
+ <literal>1</literal>,
+ <literal>on</literal>
+ and
+ <literal>all</literal>.
+
+ </para>
+
+ <para>
+
+ Conversely, &RELEASE; may now be given a &false;
+ value by setting it to
+ <literal>no</literal>
+ or
+ <literal>f</literal>:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q RELEASE=no foo.o</userinput>
+ cc -o foo.o -c -DRELEASE_BUILD=False foo.c
+ </screen>
+
+ <screen>
+ % <userinput>scons -Q RELEASE=f foo.o</userinput>
+ cc -o foo.o -c -DRELEASE_BUILD=False foo.c
+ </screen>
+
+ <para>
+
+ Other values that equate to &false; include
+ <literal>n</literal>,
+ <literal>0</literal>,
+ <literal>off</literal>
+ and
+ <literal>none</literal>.
+
+ </para>
+
+ <para>
+
+ Lastly, if a user tries to specify
+ any other value,
+ &SCons; supplies an appropriate error message:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q RELEASE=bad_value foo.o</userinput>
+
+ scons: *** Error converting option: RELEASE
+ Invalid value for boolean option: bad_value
+ File "/home/my/project/SConstruct", line 4, in ?
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Single Value From a List: the &EnumVariable; Build Variable Function</title>
+
+ <para>
+
+ Suppose that we want a user to be able to
+ set a &COLOR; variable
+ that selects a background color to be
+ displayed by an application,
+ but that we want to restrict the
+ choices to a specific set of allowed colors.
+ This can be set up quite easily
+ using the &EnumVariable;,
+ which takes a list of &allowed_values
+ in addition to the variable name,
+ default value,
+ and help text arguments:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(EnumVariable('COLOR', 'Set background color', 'red',
+ allowed_values=('red', 'green', 'blue')))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLOR' : '"${COLOR}"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ The user can now explicity set the &COLOR; build variable
+ to any of the specified allowed values:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q COLOR=red foo.o</userinput>
+ cc -o foo.o -c -DCOLOR="red" foo.c
+ % <userinput>scons -Q COLOR=blue foo.o</userinput>
+ scons: `foo.o' is up to date.
+ % <userinput>scons -Q COLOR=green foo.o</userinput>
+ scons: `foo.o' is up to date.
+ </screen>
+
+ <para>
+
+ But, almost more importantly,
+ an attempt to set &COLOR;
+ to a value that's not in the list
+ generates an error message:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q COLOR=magenta foo.o</userinput>
+
+ scons: *** Invalid value for option COLOR: magenta
+ File "/home/my/project/SConstruct", line 5, in ?
+ </screen>
+
+ <para>
+
+ The &EnumVariable; function also supports a way
+ to map alternate names to allowed values.
+ Suppose, for example,
+ that we want to allow the user
+ to use the word <literal>navy</literal> as a synonym for
+ <literal>blue</literal>.
+ We do this by adding a &map; dictionary
+ that will map its key values
+ to the desired legal value:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(EnumVariable('COLOR', 'Set background color', 'red',
+ allowed_values=('red', 'green', 'blue'),
+ map={'navy':'blue'}))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLOR' : '"${COLOR}"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ As desired, the user can then use
+ <literal>navy</literal> on the command line,
+ and &SCons; will translate it into <literal>blue</literal>
+ when it comes time to use the &COLOR;
+ variable to build a target:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q COLOR=navy foo.o</userinput>
+ cc -o foo.o -c -DCOLOR="blue" foo.c
+ </screen>
+
+ <para>
+
+ By default, when using the &EnumVariable; function,
+ arguments that differ
+ from the legal values
+ only in case
+ are treated as illegal values:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q COLOR=Red foo.o</userinput>
+
+ scons: *** Invalid value for option COLOR: Red
+ File "/home/my/project/SConstruct", line 5, in ?
+ % <userinput>scons -Q COLOR=BLUE foo.o</userinput>
+
+ scons: *** Invalid value for option COLOR: BLUE
+ File "/home/my/project/SConstruct", line 5, in ?
+ % <userinput>scons -Q COLOR=nAvY foo.o</userinput>
+
+ scons: *** Invalid value for option COLOR: nAvY
+ File "/home/my/project/SConstruct", line 5, in ?
+ </screen>
+
+ <para>
+
+ The &EnumVariable; function can take an additional
+ &ignorecase; keyword argument that,
+ when set to <literal>1</literal>,
+ tells &SCons; to allow case differences
+ when the values are specified:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(EnumVariable('COLOR', 'Set background color', 'red',
+ allowed_values=('red', 'green', 'blue'),
+ map={'navy':'blue'},
+ ignorecase=1))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLOR' : '"${COLOR}"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ Which yields the output:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q COLOR=Red foo.o</userinput>
+ cc -o foo.o -c -DCOLOR="Red" foo.c
+ % <userinput>scons -Q COLOR=BLUE foo.o</userinput>
+ scons: `foo.o' is up to date.
+ % <userinput>scons -Q COLOR=nAvY foo.o</userinput>
+ scons: `foo.o' is up to date.
+ % <userinput>scons -Q COLOR=green foo.o</userinput>
+ scons: `foo.o' is up to date.
+ </screen>
+
+ <para>
+
+ Notice that an &ignorecase; value of <literal>1</literal>
+ preserves the case-spelling that the user supplied.
+ If you want &SCons; to translate the names
+ into lower-case,
+ regardless of the case used by the user,
+ specify an &ignorecase; value of <literal>2</literal>:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(EnumVariable('COLOR', 'Set background color', 'red',
+ allowed_values=('red', 'green', 'blue'),
+ map={'navy':'blue'},
+ ignorecase=2))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLOR' : '"${COLOR}"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ Now &SCons; will use values of
+ <literal>red</literal>,
+ <literal>green</literal> or
+ <literal>blue</literal>
+ regardless of how the user spells
+ those values on the command line:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q COLOR=Red foo.o</userinput>
+ cc -o foo.o -c -DCOLOR="red" foo.c
+ % <userinput>scons -Q COLOR=nAvY foo.o</userinput>
+ scons: `foo.o' is up to date.
+ % <userinput>scons -Q COLOR=GREEN foo.o</userinput>
+ scons: `foo.o' is up to date.
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Multiple Values From a List: the &ListVariable; Build Variable Function</title>
+
+ <para>
+
+ Another way in which you might want to allow users
+ to control a build variable is to
+ specify a list of one or more legal values.
+ &SCons; supports this through the &ListVariable; function.
+ If, for example, we want a user to be able to set a
+ &COLORS; variable to one or more of the legal list of values:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(ListVariable('COLORS', 'List of colors', 0,
+ ['red', 'green', 'blue']))
+ env = Environment(variables = vars,
+ CPPDEFINES={'COLORS' : '"${COLORS}"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ A user can now specify a comma-separated list
+ of legal values,
+ which will get translated into a space-separated
+ list for passing to the any build commands:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q COLORS=red,blue foo.o</userinput>
+ cc -o foo.o -c -DCOLORS="red blue" foo.c
+ % <userinput>scons -Q COLORS=blue,green,red foo.o</userinput>
+ scons: `foo.o' is up to date.
+ </screen>
+
+ <para>
+
+ In addition, the &ListVariable; function
+ allows the user to specify explicit keywords of
+ &all; or &none;
+ to select all of the legal values,
+ or none of them, respectively:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q COLORS=all foo.o</userinput>
+ cc -o foo.o -c -DCOLORS="red green blue" foo.c
+ % <userinput>scons -Q COLORS=none foo.o</userinput>
+ scons: `foo.o' is up to date.
+ </screen>
+
+ <para>
+
+ And, of course, an illegal value
+ still generates an error message:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q COLORS=magenta foo.o</userinput>
+
+ scons: *** Error converting option: COLORS
+ Invalid value(s) for option: magenta
+ File "/home/my/project/SConstruct", line 5, in ?
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Path Names: the &PathVariable; Build Variable Function</title>
+
+ <para>
+
+ &SCons; supports a &PathVariable; function
+ to make it easy to create a build variable
+ to control an expected path name.
+ If, for example, you need to
+ define a variable in the preprocessor
+ that controls the location of a
+ configuration file:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('CONFIG',
+ 'Path to configuration file',
+ '/etc/my_config'))
+ env = Environment(variables = vars,
+ CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ This then allows the user to
+ override the &CONFIG; build variable
+ on the command line as necessary:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q foo.o</userinput>
+ cc -o foo.o -c -DCONFIG_FILE="/etc/my_config" foo.c
+ % <userinput>scons -Q CONFIG=/usr/local/etc/other_config foo.o</userinput>
+ scons: `foo.o' is up to date.
+ </screen>
+
+ <para>
+
+ By default, &PathVariable; checks to make sure
+ that the specified path exists and generates an error if it
+ doesn't:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q CONFIG=/does/not/exist foo.o</userinput>
+
+ scons: *** Path for option CONFIG does not exist: /does/not/exist
+ File "/home/my/project/SConstruct", line 6, in ?
+ </screen>
+
+ <para>
+
+ &PathVariable; provides a number of methods
+ that you can use to change this behavior.
+ If you want to ensure that any specified paths are,
+ in fact, files and not directories,
+ use the &PathVariable_PathIsFile; method:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('CONFIG',
+ 'Path to configuration file',
+ '/etc/my_config',
+ PathVariable.PathIsFile))
+ env = Environment(variables = vars,
+ CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ Conversely, to ensure that any specified paths are
+ directories and not files,
+ use the &PathVariable_PathIsDir; method:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('DBDIR',
+ 'Path to database directory',
+ '/var/my_dbdir',
+ PathVariable.PathIsDir))
+ env = Environment(variables = vars,
+ CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ If you want to make sure that any specified paths
+ are directories,
+ and you would like the directory created
+ if it doesn't already exist,
+ use the &PathVariable_PathIsDirCreate; method:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('DBDIR',
+ 'Path to database directory',
+ '/var/my_dbdir',
+ PathVariable.PathIsDirCreate))
+ env = Environment(variables = vars,
+ CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ Lastly, if you don't care whether the path exists,
+ is a file, or a directory,
+ use the &PathVariable_PathAccept; method
+ to accept any path that the user supplies:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(PathVariable('OUTPUT',
+ 'Path to output file or directory',
+ None,
+ PathVariable.PathAccept))
+ env = Environment(variables = vars,
+ CPPDEFINES={'OUTPUT' : '"$OUTPUT"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Enabled/Disabled Path Names: the &PackageVariable; Build Variable Function</title>
+
+ <para>
+
+ Sometimes you want to give users
+ even more control over a path name variable,
+ allowing them to explicitly enable or
+ disable the path name
+ by using <literal>yes</literal> or <literal>no</literal> keywords,
+ in addition to allow them
+ to supply an explicit path name.
+ &SCons; supports the &PackageVariable;
+ function to support this:
+
+ </para>
+
+ <programlisting>
+ vars = Variables('custom.py')
+ vars.Add(PackageVariable('PACKAGE',
+ 'Location package',
+ '/opt/location'))
+ env = Environment(variables = vars,
+ CPPDEFINES={'PACKAGE' : '"$PACKAGE"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ When the &SConscript; file uses the &PackageVariable; funciton,
+ user can now still use the default
+ or supply an overriding path name,
+ but can now explicitly set the
+ specified variable to a value
+ that indicates the package should be enabled
+ (in which case the default should be used)
+ or disabled:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q foo.o</userinput>
+ cc -o foo.o -c -DPACKAGE="/opt/location" foo.c
+ % <userinput>scons -Q PACKAGE=/usr/local/location foo.o</userinput>
+ scons: `foo.o' is up to date.
+ % <userinput>scons -Q PACKAGE=yes foo.o</userinput>
+ scons: `foo.o' is up to date.
+ % <userinput>scons -Q PACKAGE=no foo.o</userinput>
+ scons: `foo.o' is up to date.
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Adding Multiple Command-Line Build Variables at Once</title>
+
+ <para>
+
+ Lastly, &SCons; provides a way to add
+ multiple build variables to a &Variables; object at once.
+ Instead of having to call the &Add; method
+ multiple times,
+ you can call the &AddVariables;
+ method with a list of build variables
+ to be added to the object.
+ Each build variable is specified
+ as either a tuple of arguments,
+ just like you'd pass to the &Add; method itself,
+ or as a call to one of the pre-defined
+ functions for pre-packaged command-line build variables.
+ in any order:
+
+ </para>
+
+ <programlisting>
+ vars = Variables()
+ vars.AddVariables(
+ ('RELEASE', 'Set to 1 to build for release', 0),
+ ('CONFIG', 'Configuration file', '/etc/my_config'),
+ BoolVariable('warnings', 'compilation with -Wall and similiar', 1),
+ EnumVariable('debug', 'debug output and symbols', 'no',
+ allowed_values=('yes', 'no', 'full'),
+ map={}, ignorecase=0), # case sensitive
+ ListVariable('shared',
+ 'libraries to build as shared libraries',
+ 'all',
+ names = list_of_libs),
+ PackageVariable('x11',
+ 'use X11 installed here (yes = search some places)',
+ 'yes'),
+ PathVariable('qtdir', 'where the root of Qt is installed', qtdir),
+ )
+ </programlisting>
+
+ <para>
+ </para>
+
+ </section>
+
+ <section>
+ <title>Handling Unknown Command-Line Build Variables: the &UnknownVariables; Function</title>
+
+ <para>
+
+ Users may, of course,
+ occasionally misspell variable names in their command-line settings.
+ &SCons; does not generate an error or warning
+ for any unknown variables the users specifies on the command line.
+ (This is in no small part because you may be
+ processing the arguments directly using the &ARGUMENTS; dictionary,
+ and therefore &SCons; can't know in the general case
+ whether a given "misspelled" variable is
+ really unknown and a potential problem,
+ or something that your &SConscript; file
+ will handle directly with some Python code.)
+
+ </para>
+
+ <para>
+
+ If, however, you're using a &Variables; object to
+ define a specific set of command-line build variables
+ that you expect users to be able to set,
+ you may want to provide an error
+ message or warning of your own
+ if the user supplies a variable setting
+ that is <emphasis>not</emphasis> among
+ the defined list of variable names known to the &Variables; object.
+ You can do this by calling the &UnknownVariables;
+ method of the &Variables; object:
+
+ </para>
+
+ <programlisting>
+ vars = Variables(None)
+ vars.Add('RELEASE', 'Set to 1 to build for release', 0)
+ env = Environment(variables = vars,
+ CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
+ unknown = vars.UnknownVariables()
+ if unknown:
+ print "Unknown variables:", unknown.keys()
+ Exit(1)
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ The &UnknownVariables; method returns a dictionary
+ containing the keywords and values
+ of any variables the user specified on the command line
+ that are <emphasis>not</emphasis>
+ among the variables known to the &Variables; object
+ (from having been specified using
+ the &Variables; object's&Add; method).
+ In the examble above,
+ we check for whether the dictionary
+ returned by the &UnknownVariables; is non-empty,
+ and if so print the Python list
+ containing the names of the unknwown variables
+ and then call the &Exit; function
+ to terminate &SCons;:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q NOT_KNOWN=foo</userinput>
+ Unknown variables: ['NOT_KNOWN']
+ </screen>
+
+ <para>
+
+ Of course, you can process the items in the
+ dictionary returned by the &UnknownVariables; function
+ in any way appropriate to your build configuration,
+ including just printing a warning message
+ but not exiting,
+ logging an error somewhere,
+ etc.
+
+ </para>
+
+ <para>
+
+ Note that you must delay the call of &UnknownVariables;
+ until after you have applied the &Variables; object
+ to a construction environment
+ with the <literal>variables=</literal>
+ keyword argument of an &Environment; call.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="sect-command-line-targets">
+ <title>Command-Line Targets</title>
+
+ <section>
+ <title>Fetching Command-Line Targets: the &COMMAND_LINE_TARGETS; Variable</title>
+
+ <para>
+
+ &SCons; supports a &COMMAND_LINE_TARGETS; variable
+ that lets you fetch the list of targets that the
+ user specified on the command line.
+ You can use the targets to manipulate the
+ build in any way you wish.
+ As a simple example,
+ suppose that you want to print a reminder
+ to the user whenever a specific program is built.
+ You can do this by checking for the
+ target in the &COMMAND_LINE_TARGETS; list:
+
+ </para>
+
+ <programlisting>
+ if 'bar' in COMMAND_LINE_TARGETS:
+ print "Don't forget to copy `bar' to the archive!"
+ Default(Program('foo.c'))
+ Program('bar.c')
+ </programlisting>
+
+ <para>
+
+ Then, running &SCons; with the default target
+ works as it always does,
+ but explicity specifying the &bar; target
+ on the command line generates the warning message:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o foo.o -c foo.c
+ cc -o foo foo.o
+ % <userinput>scons -Q bar</userinput>
+ Don't forget to copy `bar' to the archive!
+ cc -o bar.o -c bar.c
+ cc -o bar bar.o
+ </screen>
+
+ <para>
+
+ Another practical use for the &COMMAND_LINE_TARGETS; variable
+ might be to speed up a build
+ by only reading certain subsidiary &SConscript;
+ files if a specific target is requested.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Controlling the Default Targets: the &Default; Function</title>
+
+ <para>
+
+ One of the most basic things you can control
+ is which targets &SCons; will build by default--that is,
+ when there are no targets specified on the command line.
+ As mentioned previously,
+ &SCons; will normally build every target
+ in or below the current directory
+ by default--that is, when you don't
+ explicitly specify one or more targets
+ on the command line.
+ Sometimes, however, you may want
+ to specify explicitly that only
+ certain programs, or programs in certain directories,
+ should be built by default.
+ You do this with the &Default; function:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Program('goodbye.c')
+ Default(hello)
+ </programlisting>
+
+ <para>
+
+ This &SConstruct; file knows how to build two programs,
+ &hello; and &goodbye;,
+ but only builds the
+ &hello; program by default:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q</userinput>
+ scons: `hello' is up to date.
+ % <userinput>scons -Q goodbye</userinput>
+ cc -o goodbye.o -c goodbye.c
+ cc -o goodbye goodbye.o
+ </screen>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ cc -o goodbye.o -c goodbye.c
+ cc -o goodbye goodbye.o
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env = Environment()
+ prog1 = env.Program('prog1.c')
+ Default(prog1)
+ prog2 = env.Program('prog2.c')
+ prog3 = env.Program('prog3.c')
+ Default(prog3)
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o prog1.o -c prog1.c
+ cc -o prog1 prog1.o
+ cc -o prog3.o -c prog3.c
+ cc -o prog3 prog3.o
+ % <userinput>scons -Q .</userinput>
+ cc -o prog2.o -c prog2.c
+ cc -o prog2 prog2.o
+ </screen>
+
+ <para>
+
+ You can list a directory as
+ an argument to &Default;:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Program(['prog1/main.c', 'prog1/foo.c'])
+ env.Program(['prog2/main.c', 'prog2/bar.c'])
+ Default('prog1')
+ </programlisting>
+
+ <para>
+
+ In which case only the target(s) in that
+ directory will be built by default:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o prog1/foo.o -c prog1/foo.c
+ cc -o prog1/main.o -c prog1/main.c
+ cc -o prog1/main prog1/main.o prog1/foo.o
+ % <userinput>scons -Q</userinput>
+ scons: `prog1' is up to date.
+ % <userinput>scons -Q .</userinput>
+ cc -o prog2/bar.o -c prog2/bar.c
+ cc -o prog2/main.o -c prog2/main.c
+ cc -o prog2/main prog2/main.o prog2/bar.o
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env = Environment()
+ prog1 = env.Program('prog1.c')
+ prog2 = env.Program('prog2.c')
+ Default(None)
+ </programlisting>
+
+ <para>
+
+ Which would produce build output like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ scons: *** No targets specified and no Default() targets found. Stop.
+ % <userinput>scons -Q .</userinput>
+ cc -o prog1.o -c prog1.c
+ cc -o prog1 prog1.o
+ cc -o prog2.o -c prog2.c
+ cc -o prog2 prog2.o
+ </screen>
+
+ <section>
+ <title>Fetching the List of Default Targets: the &DEFAULT_TARGETS; Variable</title>
+
+ <para>
+
+ &SCons; supports a &DEFAULT_TARGETS; variable
+ that lets you get at the current list of default targets.
+ The &DEFAULT_TARGETS variable has
+ two important differences from the &COMMAND_LINE_TARGETS; variable.
+ First, the &DEFAULT_TARGETS; variable is a list of
+ internal &SCons; nodes,
+ so you need to convert the list elements to strings
+ if you want to print them or look for a specific target name.
+ Fortunately, you can do this easily
+ by using the Python <function>map</function> function
+ to run the list through <function>str</function>:
+
+ </para>
+
+ <programlisting>
+ prog1 = Program('prog1.c')
+ Default(prog1)
+ print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS)
+ </programlisting>
+
+ <para>
+
+ (Keep in mind that all of the manipulation of the
+ &DEFAULT_TARGETS; list takes place during the
+ first phase when &SCons; is reading up the &SConscript; files,
+ which is obvious if
+ we leave off the <literal>-Q</literal> flag when we run &SCons;:)
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ DEFAULT_TARGETS is ['prog1']
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -o prog1.o -c prog1.c
+ cc -o prog1 prog1.o
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ Second,
+ the contents of the &DEFAULT_TARGETS; list change
+ in response to calls to the &Default;: function,
+ as you can see from the following &SConstruct; file:
+
+ </para>
+
+ <programlisting>
+ prog1 = Program('prog1.c')
+ Default(prog1)
+ print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
+ prog2 = Program('prog2.c')
+ Default(prog2)
+ print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
+ </programlisting>
+
+ <para>
+
+ Which yields the output:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ DEFAULT_TARGETS is now ['prog1']
+ DEFAULT_TARGETS is now ['prog1', 'prog2']
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -o prog1.o -c prog1.c
+ cc -o prog1 prog1.o
+ cc -o prog2.o -c prog2.c
+ cc -o prog2 prog2.o
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ In practice, this simply means that you
+ need to pay attention to the order in
+ which you call the &Default; function
+ and refer to the &DEFAULT_TARGETS; list,
+ to make sure that you don't examine the
+ list before you've added the default targets
+ you expect to find in it.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Fetching the List of Build Targets, Regardless of Origin: the &BUILD_TARGETS; Variable</title>
+
+ <para>
+
+ We've already been introduced to the
+ &COMMAND_LINE_TARGETS; variable,
+ which contains a list of targets specified on the command line,
+ and the &DEFAULT_TARGETS; variable,
+ which contains a list of targets specified
+ via calls to the &Default; method or function.
+ Sometimes, however,
+ you want a list of whatever targets
+ &SCons; will try to build,
+ regardless of whether the targets came from the
+ command line or a &Default; call.
+ You could code this up by hand, as follows:
+
+ </para>
+
+ <programlisting>
+ if COMMAND_LINE_TARGETS:
+ targets = COMMAND_LINE_TARGETS
+ else:
+ targets = DEFAULT_TARGETS
+ </programlisting>
+
+ <para>
+
+ &SCons;, however, provides a convenient
+ &BUILD_TARGETS; variable
+ that eliminates the need for this by-hand manipulation.
+ Essentially, the &BUILD_TARGETS; variable
+ contains a list of the command-line targets,
+ if any were specified,
+ and if no command-line targets were specified,
+ it contains a list of the targets specified
+ via the &Default; method or function.
+
+ </para>
+
+ <para>
+
+ Because &BUILD_TARGETS; may contain a list of &SCons; nodes,
+ you must convert the list elements to strings
+ if you want to print them or look for a specific target name,
+ just like the &DEFAULT_TARGETS; list:
+
+ </para>
+
+ <programlisting>
+ prog1 = Program('prog1.c')
+ Program('prog2.c')
+ Default(prog1)
+ print "BUILD_TARGETS is", map(str, BUILD_TARGETS)
+ </programlisting>
+
+ <para>
+
+ Notice how the value of &BUILD_TARGETS;
+ changes depending on whether a target is
+ specified on the command line:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ BUILD_TARGETS is ['prog1']
+ cc -o prog1.o -c prog1.c
+ cc -o prog1 prog1.o
+ % <userinput>scons -Q prog2</userinput>
+ BUILD_TARGETS is ['prog2']
+ cc -o prog2.o -c prog2.c
+ cc -o prog2 prog2.o
+ % <userinput>scons -Q -c .</userinput>
+ BUILD_TARGETS is ['.']
+ Removed prog1.o
+ Removed prog1
+ Removed prog2.o
+ Removed prog2
+ </screen>
+
+ </section>
+
+ </section>
diff --git a/doc/user/cons.pl b/doc/user/cons.pl
new file mode 100644
index 0000000..8afbfec
--- /dev/null
+++ b/doc/user/cons.pl
@@ -0,0 +1,720 @@
+=head1 Introduction
+
+B<Cons> is a system for constructing, primarily, software, but is quite
+different from previous software construction systems. Cons was designed
+from the ground up to deal easily with the construction of software spread
+over multiple source directories. Cons makes it easy to create build scripts
+that are simple, understandable and maintainable. Cons ensures that complex
+software is easily and accurately reproducible.
+
+Cons uses a number of techniques to accomplish all of this. Construction
+scripts are just Perl scripts, making them both easy to comprehend and very
+flexible. Global scoping of variables is replaced with an import/export
+mechanism for sharing information between scripts, significantly improving
+the readability and maintainability of each script. B<Construction
+environments> are introduced: these are Perl objects that capture the
+information required for controlling the build process. Multiple
+environments are used when different semantics are required for generating
+products in the build tree. Cons implements automatic dependency analysis
+and uses this to globally sequence the entire build. Variant builds are
+easily produced from a single source tree. Intelligent build subsetting is
+possible, when working on localized changes. Overrides can be setup to
+easily override build instructions without modifying any scripts. MD5
+cryptographic B<signatures> are associated with derived files, and are used
+to accurately determine whether a given file needs to be rebuilt.
+
+While offering all of the above, and more, Cons remains simple and easy to
+use. This will, hopefully, become clear as you read the remainder of this
+document.
+
+
+
+=head2 Automatic global build sequencing
+
+Because Cons does full and accurate dependency analysis, and does this
+globally, for the entire build, Cons is able to use this information to take
+full control of the B<sequencing> of the build. This sequencing is evident
+in the above examples, and is equivalent to what you would expect for make,
+given a full set of dependencies. With Cons, this extends trivially to
+larger, multi-directory builds. As a result, all of the complexity involved
+in making sure that a build is organized correctly--including multi-pass
+hierarchical builds--is eliminated. We'll discuss this further in the next
+sections.
+
+
+
+=head1 A Model for sharing files
+
+
+=head2 Some simple conventions
+
+In any complex software system, a method for sharing build products needs to
+be established. We propose a simple set of conventions which are trivial to
+implement with Cons, but very effective.
+
+The basic rule is to require that all build products which need to be shared
+between directories are shared via an intermediate directory. We have
+typically called this F<export>, and, in a C environment, provided
+conventional sub-directories of this directory, such as F<include>, F<lib>,
+F<bin>, etc.
+
+These directories are defined by the top-level F<Construct> file. A simple
+F<Construct> file for a B<Hello, World!> application, organized using
+multiple directories, might look like this:
+
+ # Construct file for Hello, World!
+
+ # Where to put all our shared products.
+ $EXPORT = '#export';
+
+ 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 qw(
+ hello/Conscript
+ world/Conscript
+ );
+
+The F<world> directory's F<Conscript> file looks like this:
+
+ # Conscript file for directory world
+ Import qw( CONS INCLUDE LIB );
+
+ # Install the products of this directory
+ Install $CONS $LIB, 'libworld.a';
+ Install $CONS $INCLUDE, 'world.h';
+
+ # Internal products
+ Library $CONS 'libworld.a', 'world.c';
+
+and the F<hello> directory's F<Conscript> file looks like this:
+
+ # Conscript file for directory hello
+ Import qw( CONS BIN );
+
+ # Exported products
+ Install $CONS $BIN, 'hello';
+
+ # Internal products
+ Program $CONS 'hello', 'hello.c';
+
+To construct a B<Hello, World!> program with this directory structure, go to
+the top-level directory, and invoke C<cons> with the appropriate
+arguments. In the following example, we tell Cons to build the directory
+F<export>. To build a directory, Cons recursively builds all known products
+within that directory (only if they need rebuilding, of course). If any of
+those products depend upon other products in other directories, then those
+will be built, too.
+
+ % cons export
+ Install world/world.h as export/include/world.h
+ cc -Iexport/include -c hello/hello.c -o hello/hello.o
+ cc -Iexport/include -c world/world.c -o world/world.o
+ ar r world/libworld.a world/world.o
+ ar: creating world/libworld.a
+ ranlib world/libworld.a
+ Install world/libworld.a as export/lib/libworld.a
+ cc -o hello/hello hello/hello.o -Lexport/lib -lworld
+ Install hello/hello as export/bin/hello
+
+
+=head2 Clean, understandable, location-independent scripts
+
+You'll note that the two F<Conscript> files are very clean and
+to-the-point. They simply specify products of the directory and how to build
+those products. The build instructions are minimal: they specify which
+construction environment to use, the name of the product, and the name of
+the inputs. Note also that the scripts are location-independent: if you wish
+to reorganize your source tree, you are free to do so: you only have to
+change the F<Construct> file (in this example), to specify the new locations
+of the F<Conscript> files. The use of an export tree makes this goal easy.
+
+Note, too, how Cons takes care of little details for you. All the F<export>
+directories, for example, were made automatically. And the installed files
+were really hard-linked into the respective export directories, to save
+space and time. This attention to detail saves considerable work, and makes
+it even easier to produce simple, maintainable scripts.
+
+
+
+=head1 Signatures
+
+Cons uses file B<signatures> to decide if a derived file is out-of-date
+and needs rebuilding. In essence, if the contents of a file change,
+or the manner in which the file is built changes, the file's signature
+changes as well. This allows Cons to decide with certainty when a file
+needs rebuilding, because Cons can detect, quickly and reliably, whether
+any of its dependency files have been changed.
+
+
+=head2 MD5 content and build signatures
+
+Cons uses the B<MD5> (B<Message Digest 5>) algorithm to compute file
+signatures. The MD5 algorithm computes a strong cryptographic checksum
+for any given input string. Cons can, based on configuration, use two
+different MD5 signatures for a given file:
+
+The B<content signature> of a file is an MD5 checksum of the file's
+contents. Consequently, when the contents of a file change, its content
+signature changes as well.
+
+The B<build signature> of a file is a combined MD5 checksum of:
+
+=over 4
+
+the signatures of all the input files used to build the file
+
+the signatures of all dependency files discovered by source scanners
+(for example, C<.h> files)
+
+the signatures of all dependency files specified explicitly via the
+C<Depends> method)
+
+the command-line string used to build the file
+
+=back
+
+The build signature is, in effect, a digest of all the dependency
+information for the specified file. Consequently, a file's build
+signature changes whenever any part of its dependency information
+changes: a new file is added, the contents of a file on which it depends
+change, there's a change to the command line used to build the file (or
+any of its dependency files), etc.
+
+For example, in the previous section, the build signature of the
+F<world.o> file will include:
+
+=over 4
+
+the signature of the F<world.c> file
+
+the signatures of any header files that Cons detects are included,
+directly or indirectly, by F<world.c>
+
+the text of the actual command line was used to generate F<world.o>
+
+=back
+
+Similarly, the build signature of the F<libworld.a> file will include
+all the signatures of its constituents (and hence, transitively, the
+signatures of B<their> constituents), as well as the command line that
+created the file.
+
+Note that there is no need for a derived file to depend upon any
+particular F<Construct> or F<Conscript> file. If changes to these files
+affect a file, then this will be automatically reflected in its build
+signature, since relevant parts of the command line are included in the
+signature. Unrelated F<Construct> or F<Conscript> changes will have no
+effect.
+
+
+=head2 Storing signatures in .consign files
+
+Before Cons exits, it stores the calculated signatures for all of the
+files it built or examined in F<.consign> files, one per directory.
+Cons uses this stored information on later invocations to decide if
+derived files need to be rebuilt.
+
+After the previous example was compiled, the F<.consign> file in the
+F<build/peach/world> directory looked like this:
+
+ world.h:985533370 - d181712f2fdc07c1f05d97b16bfad904
+ world.o:985533372 2a0f71e0766927c0532977b0d2158981
+ world.c:985533370 - c712f77189307907f4189b5a7ab62ff3
+ libworld.a:985533374 69e568fc5241d7d25be86d581e1fb6aa
+
+After the file name and colon, the first number is a timestamp of the
+file's modification time (on UNIX systems, this is typically the number
+of seconds since January 1st, 1970). The second value is the build
+signature of the file (or ``-'' in the case of files with no build
+signature--that is, source files). The third value, if any, is the
+content signature of the file.
+
+
+=head2 Using build signatures to decide when to rebuild files
+
+When Cons is deciding whether to build or rebuild a derived file, it
+first computes the file's current build signature. If the file doesn't
+exist, it must obviously be built.
+
+If, however, the file already exists, Cons next compares the
+modification timestamp of the file against the timestamp value in
+the F<.consign> file. If the timestamps match, Cons compares the
+newly-computed build signature against the build signature in the
+F<.consign> file. If the timestamps do not match or the build
+signatures do not match, the derived file is rebuilt.
+
+After the file is built or rebuilt, Cons arranges to store the
+newly-computed build signature in the F<.consign> file when it exits.
+
+
+=head2 Signature example
+
+The use of these signatures is an extremely simple, efficient, and
+effective method of improving--dramatically--the reproducibility of a
+system.
+
+We'll demonstrate this with a simple example:
+
+ # Simple "Hello, World!" Construct file
+ $CFLAGS = '-g' if $ARG{DEBUG} eq 'on';
+ $CONS = new cons(CFLAGS => $CFLAGS);
+ Program $CONS 'hello', 'hello.c';
+
+Notice how Cons recompiles at the appropriate times:
+
+ % cons hello
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % cons hello
+ cons: "hello" is up-to-date.
+ % cons DEBUG=on hello
+ cc -g -c hello.c -o hello.o
+ cc -o hello hello.o
+ % cons DEBUG=on hello
+ cons: "hello" is up-to-date.
+ % cons hello
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+
+
+=head2 Source-file signature configuration
+
+Cons provides a C<SourceSignature> method that allows you to configure
+how the signature should be calculated for any source file when its
+signature is being used to decide if a dependent file is up-to-date.
+The arguments to the C<SourceSignature> method consist of one or more
+pairs of strings:
+
+ SourceSignature 'auto/*.c' => 'content',
+ '*' => 'stored-content';
+
+The first string in each pair is a pattern to match against derived file
+path names. The pattern is a file-globbing pattern, not a Perl regular
+expression; the pattern <*.l> will match all Lex source files. The C<*>
+wildcard will match across directory separators; the pattern C<foo/*.c>
+would match all C source files in any subdirectory underneath the C<foo>
+subdirectory.
+
+The second string in each pair contains one of the following keywords to
+specify how signatures should be calculated for source files that match
+the pattern. The available keywords are:
+
+=over 4
+
+=item content
+
+Use the content signature of the source file when calculating signatures
+of files that depend on it. This guarantees correct calculation of the
+file's signature for all builds, by telling Cons to read the contents of
+a source file to calculate its content signature each time it is run.
+
+=item stored-content
+
+Use the source file's content signature as stored in the F<.consign>
+file, provided the file's timestamp matches the cached timestamp value
+in the F<.consign> file. This optimizes performance, with the slight
+risk of an incorrect build if a source file's contents have been changed
+so quickly after its previous update that the timestamp still matches
+the stored timestamp in the F<.consign> file even though the contents
+have changed.
+
+=back
+
+The Cons default behavior of always calculating a source file's
+signature from the file's contents is equivalent to specifying:
+
+ SourceSignature '*' => 'content';
+
+The C<*> will match all source files. The C<content> keyword
+specifies that Cons will read the contents of a source file to calculate
+its signature each time it is run.
+
+A useful global performance optimization is:
+
+ SourceSignature '*' => 'stored-content';
+
+This specifies that Cons will use pre-computed content signatures
+from F<.consign> files, when available, rather than re-calculating a
+signature from the the source file's contents each time Cons is run. In
+practice, this is safe for most build situations, and only a problem
+when source files are changed automatically (by scripts, for example).
+The Cons default, however, errs on the side of guaranteeing a correct
+build in all situations.
+
+Cons tries to match source file path names against the patterns in the
+order they are specified in the C<SourceSignature> arguments:
+
+ SourceSignature '/usr/repository/objects/*' => 'stored-content',
+ '/usr/repository/*' => 'content',
+ '*.y' => 'content',
+ '*' => 'stored-content';
+
+In this example, all source files under the F</usr/repository/objects>
+directory will use F<.consign> file content signatures, source files
+anywhere else underneath F</usr/repository> will not use F<.consign>
+signature values, all Yacc source files (C<*.y>) anywhere else will not
+use F<.consign> signature values, and any other source file will use
+F<.consign> signature values.
+
+
+=head2 Derived-file signature configuration
+
+Cons provides a C<SIGNATURE> construction variable that allows you to
+configure how signatures are calculated for any derived file when its
+signature is being used to decide if a dependent file is up-to-date.
+The value of the C<SIGNATURE> construction variable is a Perl array
+reference that holds one or more pairs of strings, like the arguments to
+the C<SourceSignature> method.
+
+The first string in each pair is a pattern to match against derived file
+path names. The pattern is a file-globbing pattern, not a Perl regular
+expression; the pattern `*.obj' will match all (Win32) object files.
+The C<*> wildcard will match across directory separators; the pattern
+`foo/*.a' would match all (UNIX) library archives in any subdirectory
+underneath the foo subdirectory.
+
+The second string in each pair contains one of the following keywords
+to specify how signatures should be calculated for derived files that
+match the pattern. The available keywords are the same as for the
+C<SourceSignature> method, with an additional keyword:
+
+=over 4
+
+=item build
+
+Use the build signature of the derived file when calculating signatures
+of files that depend on it. This guarantees correct builds by forcing
+Cons to rebuild any and all files that depend on the derived file.
+
+=item content
+
+Use the content signature of the derived file when calculating signatures
+of files that depend on it. This guarantees correct calculation of the
+file's signature for all builds, by telling Cons to read the contents of
+a derived file to calculate its content signature each time it is run.
+
+=item stored-content
+
+Use the derived file's content signature as stored in the F<.consign>
+file, provided the file's timestamp matches the cached timestamp value
+in the F<.consign> file. This optimizes performance, with the slight
+risk of an incorrect build if a derived file's contents have been
+changed so quickly after a Cons build that the file's timestamp still
+matches the stored timestamp in the F<.consign> file.
+
+=back
+
+The Cons default behavior (as previously described) for using
+derived-file signatures is equivalent to:
+
+ $env = new cons(SIGNATURE => ['*' => 'build']);
+
+The C<*> will match all derived files. The C<build> keyword specifies
+that all derived files' build signatures will be used when calculating
+whether a dependent file is up-to-date.
+
+A useful alternative default C<SIGNATURE> configuration for many sites:
+
+ $env = new cons(SIGNATURE => ['*' => 'content']);
+
+In this configuration, derived files have their signatures calculated
+from the file contents. This adds slightly to Cons' workload, but has
+the useful effect of "stopping" further rebuilds if a derived file is
+rebuilt to exactly the same file contents as before, which usually
+outweighs the additional computation Cons must perform.
+
+For example, changing a comment in a C file and recompiling should
+generate the exact same object file (assuming the compiler doesn't
+insert a timestamp in the object file's header). In that case,
+specifying C<content> or C<stored-content> for the signature calculation
+will cause Cons to recognize that the object file did not actually
+change as a result of being rebuilt, and libraries or programs that
+include the object file will not be rebuilt. When C<build> is
+specified, however, Cons will only "know" that the object file was
+rebuilt, and proceed to rebuild any additional files that include the
+object file.
+
+Note that Cons tries to match derived file path names against the
+patterns in the order they are specified in the C<SIGNATURE> array
+reference:
+
+ $env = new cons(SIGNATURE => ['foo/*.o' => 'build',
+ '*.o' => 'content',
+ '*.a' => 'stored-content',
+ '*' => 'content']);
+
+In this example, all object files underneath the F<foo> subdirectory
+will use build signatures, all other object files (including object
+files underneath other subdirectories!) will use F<.consign> file
+content signatures, libraries will use F<.consign> file build
+signatures, and all other derived files will use content signatures.
+
+
+=head2 Debugging signature calculation
+
+Cons provides a C<-S> option that can be used to specify what internal
+Perl package Cons should use to calculate signatures. The default Cons
+behavior is equivalent to specifying C<-S md5> on the command line.
+
+The only other package (currently) available is an C<md5::debug>
+package that prints out detailed information about the MD5 signature
+calculations performed by Cons:
+
+ % cons -S md5::debug hello
+ sig::md5::srcsig(hello.c)
+ => |52d891204c62fe93ecb95281e1571938|
+ sig::md5::collect(52d891204c62fe93ecb95281e1571938)
+ => |fb0660af4002c40461a2f01fbb5ffd03|
+ sig::md5::collect(52d891204c62fe93ecb95281e1571938,
+ fb0660af4002c40461a2f01fbb5ffd03,
+ cc -c %< -o %>)
+ => |f7128da6c3fe3c377dc22ade70647b39|
+ sig::md5::current(||
+ eq |f7128da6c3fe3c377dc22ade70647b39|)
+ cc -c hello.c -o hello.o
+ sig::md5::collect()
+ => |d41d8cd98f00b204e9800998ecf8427e|
+ sig::md5::collect(f7128da6c3fe3c377dc22ade70647b39,
+ d41d8cd98f00b204e9800998ecf8427e,
+ cc -o %> %< )
+ => |a0bdce7fd09e0350e7efbbdb043a00b0|
+ sig::md5::current(||
+ eq |a0bdce7fd09e0350e7efbbdb043a00b0|)
+ cc -o hello, hello.o
+
+
+
+
+
+
+
+=head1 Temporary overrides
+
+Cons provides a very simple mechanism for overriding aspects of a build. The
+essence is that you write an override file containing one or more
+C<Override> commands, and you specify this on the command line, when you run
+C<cons>:
+
+ % cons -o over export
+
+will build the F<export> directory, with all derived files subject to the
+overrides present in the F<over> file. If you leave out the C<-o> option,
+then everything necessary to remove all overrides will be rebuilt.
+
+
+=head2 Overriding environment variables
+
+The override file can contain two types of overrides. The first is incoming
+environment variables. These are normally accessible by the F<Construct>
+file from the C<%ENV> hash variable. These can trivially be overridden in
+the override file by setting the appropriate elements of C<%ENV> (these
+could also be overridden in the user's environment, of course).
+
+
+=head2 The Override command
+
+The second type of override is accomplished with the C<Override> command,
+which looks like this:
+
+ Override <regexp>, <var1> => <value1>, <var2> => <value2>, ...;
+
+The regular expression I<regexp> is matched against every derived file that
+is a candidate for the build. If the derived file matches, then the
+variable/value pairs are used to override the values in the construction
+environment associated with the derived file.
+
+Let's suppose that we have a construction environment like this:
+
+ $CONS = new cons(
+ COPT => '',
+ CDBG => '-g',
+ CFLAGS => '%COPT %CDBG',
+ );
+
+Then if we have an override file F<over> containing this command:
+
+ Override '\.o$', COPT => '-O', CDBG => '';
+
+then any C<cons> invocation with C<-o over> that creates F<.o> files via
+this environment will cause them to be compiled with C<-O >and no C<-g>. The
+override could, of course, be restricted to a single directory by the
+appropriate selection of a regular expression.
+
+Here's the original version of the Hello, World! program, built with this
+environment. Note that Cons rebuilds the appropriate pieces when the
+override is applied or removed:
+
+ % cons hello
+ cc -g -c hello.c -o hello.o
+ cc -o hello hello.o
+ % cons -o over hello
+ cc -O -c hello.c -o hello.o
+ cc -o hello hello.o
+ % cons -o over hello
+ cons: "hello" is up-to-date.
+ % cons hello
+ cc -g -c hello.c -o hello.o
+ cc -o hello hello.o
+
+It's important that the C<Override> command only be used for temporary,
+on-the-fly overrides necessary for development because the overrides are not
+platform independent and because they rely too much on intimate knowledge of
+the workings of the scripts. For temporary use, however, they are exactly
+what you want.
+
+Note that it is still useful to provide, say, the ability to create a fully
+optimized version of a system for production use--from the F<Construct> and
+F<Conscript> files. This way you can tailor the optimized system to the
+platform. Where optimizer trade-offs need to be made (particular files may
+not be compiled with full optimization, for example), then these can be
+recorded for posterity (and reproducibility) directly in the scripts.
+
+
+
+=head2 The C<Module> method
+
+The C<Module> method is a combination of the C<Program> and C<Command>
+methods. Rather than generating an executable program directly, this command
+allows you to specify your own command to actually generate a module. The
+method is invoked as follows:
+
+ Module $env <module name>, <source or object files>, <construction command>;
+
+This command is useful in instances where you wish to create, for example,
+dynamically loaded modules, or statically linked code libraries.
+
+
+
+
+=head2 The C<RuleSet> method
+
+The C<RuleSet> method returns the construction variables for building
+various components with one of the rule sets supported by Cons. The
+currently supported rule sets are:
+
+=over 4
+
+=item msvc
+
+Rules for the Microsoft Visual C++ compiler suite.
+
+=item unix
+
+Generic rules for most UNIX-like compiler suites.
+
+=back
+
+On systems with more than one available compiler suite, this allows you
+to easily create side-by-side environments for building software with
+multiple tools:
+
+ $msvcenv = new cons(RuleSet("msvc"));
+ $cygnusenv = new cons(RuleSet("unix"));
+
+In the future, this could also be extended to other platforms that
+have different default rule sets.
+
+
+=head2 The C<DefaultRules> method
+
+The C<DefaultRules> method sets the default construction variables that
+will be returned by the C<new> method to the specified arguments:
+
+ DefaultRules(CC => 'gcc',
+ CFLAGS => '',
+ CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>');
+ $env = new cons();
+ # $env now contains *only* the CC, CFLAGS,
+ # and CCCOM construction variables
+
+Combined with the C<RuleSet> method, this also provides an easy way
+to set explicitly the default build environment to use some supported
+toolset other than the Cons defaults:
+
+ # use a UNIX-like tool suite (like cygwin) on Win32
+ DefaultRules(RuleSet('unix'));
+ $env = new cons();
+
+Note that the C<DefaultRules> method completely replaces the default
+construction environment with the specified arguments, it does not
+simply override the existing defaults. To override one or more
+variables in a supported C<RuleSet>, append the variables and values:
+
+ DefaultRules(RuleSet('unix'), CFLAGS => '-O3');
+ $env1 = new cons();
+ $env2 = new cons();
+ # both $env1 and $env2 have 'unix' defaults
+ # with CFLAGS set to '-O3'
+
+
+
+
+
+
+
+
+=head2 The C<SourcePath> method
+
+The C<SourcePath> mathod returns the real source path name of a file,
+as opposed to the path name within a build directory. It is invoked
+as follows:
+
+ $path = SourcePath <buildpath>;
+
+
+=head2 The C<ConsPath> method
+
+The C<ConsPath> method returns true if the supplied path is a derivable
+file, and returns undef (false) otherwise.
+It is invoked as follows:
+
+ $result = ConsPath <path>;
+
+
+=head2 The C<SplitPath> method
+
+The C<SplitPath> method looks up multiple path names in a string separated
+by the default path separator for the operating system (':' on UNIX
+systems, ';' on Windows NT), and returns the fully-qualified names.
+It is invoked as follows:
+
+ @paths = SplitPath <pathlist>;
+
+The C<SplitPath> method will convert names prefixed '#' to the
+appropriate top-level build name (without the '#') and will convert
+relative names to top-level names.
+
+
+=head2 The C<DirPath> method
+
+The C<DirPath> method returns the build path name(s) of a directory or
+list of directories. It is invoked as follows:
+
+ $cwd = DirPath <paths>;
+
+The most common use for the C<DirPath> method is:
+
+ $cwd = DirPath '.';
+
+to fetch the path to the current directory of a subsidiary F<Conscript>
+file.
+
+
+=head2 The C<FilePath> method
+
+The C<FilePath> method returns the build path name(s) of a file or
+list of files. It is invoked as follows:
+
+ $file = FilePath <path>;
diff --git a/doc/user/copyright.in b/doc/user/copyright.in
new file mode 100644
index 0000000..341698d
--- /dev/null
+++ b/doc/user/copyright.in
@@ -0,0 +1,32 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<blockquote>
+ <para>
+
+ SCons User's Guide Copyright (c) 2004, 2005, 2006, 2007 Steven Knight
+
+ </para>
+</blockquote>
diff --git a/doc/user/copyright.xml b/doc/user/copyright.xml
new file mode 100644
index 0000000..341698d
--- /dev/null
+++ b/doc/user/copyright.xml
@@ -0,0 +1,32 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<blockquote>
+ <para>
+
+ SCons User's Guide Copyright (c) 2004, 2005, 2006, 2007 Steven Knight
+
+ </para>
+</blockquote>
diff --git a/doc/user/depends.in b/doc/user/depends.in
new file mode 100644
index 0000000..dfd52e3
--- /dev/null
+++ b/doc/user/depends.in
@@ -0,0 +1,1816 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ So far we've seen how &SCons; handles one-time builds.
+ But one of the main functions of a build tool like &SCons;
+ is to rebuild only what is necessary
+ when source files change--or, put another way,
+ &SCons; should <emphasis>not</emphasis>
+ waste time rebuilding things that don't need to be rebuilt.
+ You can see this at work simply by re-invoking &SCons;
+ after building our simple &hello; example:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct">
+ Program('hello.c')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The second time it is executed,
+ &SCons; realizes that the &hello; program
+ is up-to-date with respect to the current &hello_c; source file,
+ and avoids rebuilding it.
+ You can see this more clearly by naming
+ the &hello; program explicitly on the command line:
+
+ </para>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that &SCons; reports <literal>"...is up to date"</literal>
+ only for target files named explicitly on the command line,
+ to avoid cluttering the output.
+
+ </para>
+
+ <section>
+ <title>Deciding When an Input File Has Changed: the &Decider; Function</title>
+
+ <para>
+
+ Another aspect of avoiding unnecessary rebuilds
+ is the fundamental build tool behavior
+ of <emphasis>rebuilding</emphasis>
+ things when an input file changes,
+ so that the built software is up to date.
+ By default,
+ &SCons; keeps track of this through an
+ MD5 &signature;, or checksum, of the contents of each file,
+ although you can easily configure
+ &SCons; to use the
+ modification times (or time stamps)
+ instead.
+ You can even specify your own Python function
+ for deciding if an input file has changed.
+
+ </para>
+
+ <section>
+ <title>Using MD5 Signatures to Decide if a File Has Changed</title>
+
+ <para>
+
+ By default,
+ &SCons; keeps track of whether a file has changed
+ based on an MD5 checksum of the file's contents,
+ not the file's modification time.
+ This means that you may be surprised by the
+ default &SCons; behavior if you are used to the
+ &Make; convention of forcing
+ a rebuild by updating the file's modification time
+ (using the &touch; command, for example):
+
+ </para>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>touch hello.c</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Even though the file's modification time has changed,
+ &SCons; realizes that the contents of the
+ &hello_c; file have <emphasis>not</emphasis> changed,
+ and therefore that the &hello; program
+ need not be rebuilt.
+ This avoids unnecessary rebuilds when,
+ for example, someone rewrites the
+ contents of a file without making a change.
+ But if the contents of the file really do change,
+ then &SCons; detects the change
+ and rebuilds the program as required:
+
+ </para>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that you can, if you wish,
+ specify this default behavior
+ (MD5 signatures) explicitly
+ using the &Decider; function as follows:
+
+ </para>
+
+ <sconstruct>
+ Program('hello.c')
+ Decider('MD5')
+ </sconstruct>
+
+ <para>
+
+ You can also use the string <literal>'content'</literal>
+ as a synonym for <literal>'MD5'</literal>
+ when calling the &Decider; function.
+
+ </para>
+
+ <section>
+ <title>Ramifications of Using MD5 Signatures</title>
+
+ <para>
+
+ Using MD5 signatures to decide if an input file has changed
+ has one surprising benefit:
+ if a source file has been changed
+ in such a way that the contents of the
+ rebuilt target file(s)
+ will be exactly the same as the last time
+ the file was built,
+ then any "downstream" target files
+ that depend on the rebuilt-but-not-changed target
+ file actually need not be rebuilt.
+
+ </para>
+
+ <para>
+
+ So if, for example,
+ a user were to only change a comment in a &hello_c; file,
+ then the rebuilt &hello_o; file
+ would be exactly the same as the one previously built
+ (assuming the compiler doesn't put any build-specific
+ information in the object file).
+ &SCons; would then realize that it would not
+ need to rebuild the &hello; program as follows:
+
+ </para>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In essence, &SCons;
+ "short-circuits" any dependent builds
+ when it realizes that a target file
+ has been rebuilt to exactly the same file as the last build.
+ This does take some extra processing time
+ to read the contents of the target (&hello_o;) file,
+ but often saves time when the rebuild that was avoided
+ would have been time-consuming and expensive.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Using Time Stamps to Decide If a File Has Changed</title>
+
+ <para>
+
+ If you prefer, you can
+ configure &SCons; to use the modification time
+ of a file, not the file contents,
+ when deciding if a target needs to be rebuilt.
+ &SCons; gives you two ways to use time stamps
+ to decide if an input file has changed
+ since the last time a target has been built.
+
+ </para>
+
+ <para>
+
+ The most familiar way to use time stamps
+ is the way &Make; does:
+ that is, have &SCons; decide
+ that a target must be rebuilt
+ if a source file's modification time is
+ <emphasis>newer</emphasis>
+ than the target file.
+ To do this, call the &Decider;
+ function as follows:
+
+ </para>
+
+ <scons_example name="newer">
+ <file name="SConstruct" printme="1">
+ Program('hello.c')
+ Decider('timestamp-newer')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ This makes &SCons; act like &Make;
+ when a file's modification time is updated
+ (using the &touch; command, for example):
+
+ </para>
+
+ <scons_output example="newer" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>touch hello.c</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And, in fact, because this behavior is the same
+ as the behavior of &Make;,
+ you can also use the string <literal>'make'</literal>
+ as a synonym for <literal>'timestamp-newer'</literal>
+ when calling the &Decider; function:
+
+ </para>
+
+ <sconstruct>
+ Program('hello.c')
+ Decider('make')
+ </sconstruct>
+
+ <para>
+
+ One drawback to using times stamps exactly like &Make;
+ is that if an input file's modification time suddenly
+ becomes <emphasis>older</emphasis> than a target file,
+ the target file will not be rebuilt.
+ This can happen if an old copy of a source file is restored
+ from a backup archive, for example.
+ The contents of the restored file will likely be different
+ than they were the last time a dependent target was built,
+ but the target won't be rebuilt
+ because the modification time of the source file
+ is not newer than the target.
+
+ </para>
+
+ <para>
+
+ Because &SCons; actually stores information
+ about the source files' time stamps whenever a target is built,
+ it can handle this situation by checking for
+ an exact match of the source file time stamp,
+ instead of just whether or not the source file
+ is newer than the target file.
+ To do this, specify the argument
+ <literal>'timestamp-match'</literal>
+ when calling the &Decider; function:
+
+ </para>
+
+ <scons_example name="match">
+ <file name="SConstruct" printme="1">
+ Program('hello.c')
+ Decider('timestamp-match')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ When configured this way,
+ &SCons; will rebuild a target whenever
+ a source file's modification time has changed.
+ So if we use the <literal>touch -t</literal>
+ option to change the modification time of
+ &hello_c; to an old date (January 1, 1989),
+ &SCons; will still rebuild the target file:
+
+ </para>
+
+ <scons_output example="match" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>touch -t 198901010000 hello.c</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In general, the only reason to prefer
+ <literal>timestamp-newer</literal>
+ instead of
+ <literal>timestamp-match</literal>,
+ would be if you have some specific reason
+ to require this &Make;-like behavior of
+ not rebuilding a target when an otherwise-modified
+ source file is older.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title>
+
+ <para>
+
+ As a performance enhancement,
+ &SCons; provides a way to use
+ MD5 checksums of file contents
+ but to read those contents
+ only when the file's timestamp has changed.
+ To do this, call the &Decider;
+ function with <literal>'MD5-timestamp'</literal>
+ argument as follows:
+
+ </para>
+
+ <scons_example name="MD5-timestamp">
+ <file name="SConstruct" printme="1">
+ Program('hello.c')
+ Decider('MD5-timestamp')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ So configured, &SCons will still behave like
+ it does when using <literal>Decider('MD5')</literal>:
+
+ </para>
+
+ <!--
+
+ We want to generate the output as follows,
+ but our "surrogate" system for generating the
+ output seems to get this wrong.
+ Just in-line the output for now.
+
+ <scons_output example="MD5-timestamp" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>touch hello.c</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>touch hello.c</userinput>
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit hello.c</userinput>
+ [CHANGE THE CONTENTS OF hello.c]
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ However, the second call to &SCons; in the above output,
+ when the build is up-to-date,
+ will have been performed by simply looking at the
+ modification time of the &hello_c; file,
+ not by opening it and performing
+ an MD5 checksum calcuation on its contents.
+ This can significantly speed up many up-to-date builds.
+
+ </para>
+
+ <para>
+
+ The only drawback to using
+ <literal>Decider('MD5-timestamp')</literal>
+ is that &SCons; will <emphasis>not</emphasis>
+ rebuild a target file if a source file was modified
+ within one second of the last time &SCons; built the file.
+ While most developers are programming,
+ this isn't a problem in practice,
+ since it's unlikely that someone will have built
+ and then thought quickly enough to make a substantive
+ change to a source file within one second.
+ Certain build scripts or
+ continuous integration tools may, however,
+ rely on the ability to apply changes to files
+ automatically and then rebuild as quickly as possible,
+ in which case use of
+ <literal>Decider('MD5-timestamp')</literal>
+ may not be appropriate.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Writing Your Own Custom &Decider; Function</title>
+
+ <para>
+
+ The different string values that we've passed to
+ the &Decider; function are essentially used by &SCons;
+ to pick one of several specific internal functions
+ that implement various ways of deciding if a dependency
+ (usually a source file)
+ has changed since a target file has been built.
+ As it turns out,
+ you can also supply your own function
+ to decide if a dependency has changed.
+
+ </para>
+
+ <para>
+
+ For example, suppose we have an input file
+ that contains a lot of data,
+ in some specific regular format,
+ that is used to rebuild a lot of different target files,
+ but each target file really only depends on
+ one particular section of the input file.
+ We'd like to have each target file depend on
+ only its section of the input file.
+ However, since the input file may contain a lot of data,
+ we want to open the input file only if its timestamp has changed.
+ This could done with a custom
+ &Decider; function that might look something like this:
+
+ </para>
+
+ <scons_example name="function">
+ <file name="SConstruct" printme="1">
+ Program('hello.c')
+ def decide_if_changed(dependency, target, prev_ni):
+ if self.get_timestamp() != prev_ni.timestamp:
+ dep = str(dependency)
+ tgt = str(target)
+ if specific_part_of_file_has_changed(dep, tgt):
+ return True
+ return False
+ Decider(decide_if_changed)
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Note that in the function definition,
+ the <varname>dependency</varname>
+ (input file) is the first argument,
+ and then the &target;.
+ Both of these are passed to the functions as
+ SCons &Node; objects,
+ which we convert to strings using the Python
+ <function>str()</function>.
+
+ </para>
+
+ <para>
+
+ The third argument, <varname>prev_ni</varname>,
+ is an object that holds the
+ signature or timestamp information
+ that was recorded about the dependency
+ the last time the target was built.
+ A <varname>prev_ni</varname> object can hold
+ different information,
+ depending on the type of thing that the
+ <varname>dependency</varname> argument represents.
+ For normal files,
+ the <varname>prev_ni</varname> object
+ has the following attributes:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>.csig</term>
+
+ <listitem>
+ <para>
+ The <emphasis>content signature</emphasis>,
+ or MD5 checksum, of the contents of the
+ <varname>dependency</varname>
+ file the list time the &target; was built.
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>.size</term>
+
+ <listitem>
+ <para>
+ The size in bytes of the <varname>dependency</varname>
+ file the list time the target was built.
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>.timestamp</term>
+
+ <listitem>
+ <para>
+ The modification time of the <varname>dependency</varname>
+ file the list time the &target; was built.
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ Note that ignoring some of the arguments
+ in your custom &Decider; function
+ is a perfectly normal thing to do,
+ if they don't impact the way you want to
+ decide if the dependency file has changed.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Mixing Different Ways of Deciding If a File Has Changed</title>
+
+ <para>
+
+ The previous examples have all demonstrated calling
+ the global &Decider; function
+ to configure all dependency decisions that &SCons; makes.
+ Sometimes, however, you want to be able to configure
+ different decision-making for different targets.
+ When that's necessary, you can use the
+ <function>env.Decider</function>
+ method to affect only the configuration
+ decisions for targets built with a
+ specific construction environment.
+
+ </para>
+
+ <para>
+
+ For example, if we arbitrarily want to build
+ one program using MD5 checkums
+ and another using file modification times
+ from the same source
+ we might configure it this way:
+
+ </para>
+
+ <scons_example name="mixing">
+ <file name="SConstruct" printme="1">
+ env1 = Environment(CPPPATH = ['.'])
+ env2 = env1.Clone()
+ env2.Decider('timestamp-match')
+ env1.Program('prog-MD5', 'program1.c')
+ env2.Program('prog-timestamp', 'program2.c')
+ </file>
+ <file name="program1.c">
+ #include "inc.h"
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="program2.c">
+ #include "inc.h"
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="inc.h">
+ #define INC 1
+ </file>
+ </scons_example>
+
+ <para>
+
+ If both of the programs include the same
+ <filename>inc.h</filename> file,
+ then updating the modification time of
+ <filename>inc.h</filename>
+ (using the &touch; command)
+ will cause only <filename>prog-timestamp</filename>
+ to be rebuilt:
+
+ </para>
+
+ <scons_output example="mixing" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>touch inc.h</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Older Functions for Deciding When an Input File Has Changed</title>
+
+ <para>
+
+ &SCons; still supports two functions that used to be the
+ primary methods for configuring the
+ decision about whether or not an input file has changed.
+ Although they're not officially deprecated yet,
+ their use is discouraged,
+ mainly because they rely on a somewhat
+ confusing distinction between how
+ source files and target files are handled.
+ These functions are documented here mainly in case you
+ encounter them in existing &SConscript; files.
+
+ </para>
+
+ <section>
+ <title>The &SourceSignatures; Function</title>
+
+ <para>
+
+ The &SourceSignatures; function is fairly straightforward,
+ and supports two different argument values
+ to configure whether source file changes should be decided
+ using MD5 signatures:
+
+ </para>
+
+ <sconstruct>
+ Program('hello.c')
+ SourceSignatures('MD5')
+ </sconstruct>
+
+ <para>
+
+ Or using time stamps:
+
+ </para>
+
+ <sconstruct>
+ Program('hello.c')
+ SourceSignatures('timestamp')
+ </sconstruct>
+
+ <para>
+
+ These are roughly equivalent to specifying
+ <function>Decider('MD5')</function>
+ or
+ <function>Decider('timestamp-match')</function>,
+ respectively,
+ although it only affects how SCons makes
+ decisions about dependencies on
+ <emphasis>source</emphasis> files--that is,
+ files that are not built from any other files.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &TargetSignatures; Function</title>
+
+ <para>
+
+ The &TargetSignatures; function
+ specifies how &SCons; decides
+ when a target file has changed
+ <emphasis>when it is used as a
+ dependency of (input to) another target</emphasis>--that is,
+ the &TargetSignatures; function configures
+ how the signatures of "intermediate" target files
+ are used when deciding if a "downstream" target file
+ must be rebuilt.
+ <footnote><para>
+ This easily-overlooked distinction between
+ how &SCons; decides if the target itself must be rebuilt
+ and how the target is then used to decide if a different
+ target must be rebuilt is one of the confusing
+ things that has led to the &TargetSignatures;
+ and &SourceSignatures; functions being
+ replaced by the simpler &Decider; function.
+ </para></footnote>
+
+ </para>
+
+ <para>
+
+ The &TargetSignatures; function supports the same
+ <literal>'MD5'</literal> and <literal>'timestamp'</literal>
+ argument values that are supported by the &SourceSignatures;,
+ with the same meanings, but applied to target files.
+ That is, in the example:
+
+ </para>
+
+ <sconstruct>
+ Program('hello.c')
+ TargetSignatures('MD5')
+ </sconstruct>
+
+ <para>
+
+ The MD5 checksum of the &hello_o; target file
+ will be used to decide if it has changed since the last
+ time the "downstream" &hello; target file was built.
+ And in the example:
+
+ </para>
+
+ <sconstruct>
+ Program('hello.c')
+ TargetSignatures('timestamp')
+ </sconstruct>
+
+ <para>
+
+ The modification time of the &hello_o; target file
+ will be used to decide if it has changed since the last
+ time the "downstream" &hello; target file was built.
+
+ </para>
+
+ <para>
+
+ The &TargetSignatures; function supports
+ two additional argument values:
+ <literal>'source'</literal> and <literal>'build'</literal>.
+ The <literal>'source'</literal> argument
+ specifies that decisions involving
+ whether target files have changed
+ since a previous build
+ should use the same behavior
+ for the decisions configured for source files
+ (using the &SourceSignatures; function).
+ So in the example:
+
+ </para>
+
+ <sconstruct>
+ Program('hello.c')
+ TargetSignatures('source')
+ SourceSignatures('timestamp')
+ </sconstruct>
+
+ <para>
+
+ All files, both targets and sources,
+ will use modification times
+ when deciding if an input file
+ has changed since the last
+ time a target was built.
+
+ </para>
+
+ <para>
+
+ Lastly, the <literal>'build'</literal> argument
+ specifies that &SCons; should examine
+ the build status of a target file
+ and always rebuild a "downstream" target
+ if the target file was itself rebuilt,
+ without re-examining the contents or timestamp
+ of the newly-built target file.
+ If the target file was not rebuilt during
+ this &scons; invocation,
+ then the target file will be examined
+ the same way as configured by
+ the &SourceSignature; call
+ to decide if it has changed.
+
+ </para>
+
+ <para>
+
+ This mimics the behavior of
+ <literal>build signatures</literal>
+ in earlier versions of &SCons;.
+ A &buildsignature; re-combined
+ signatures of all the input files
+ that went into making the target file,
+ so that the target file itself
+ did not need to have its contents read
+ to compute an MD5 signature.
+ This can improve performance for some configurations,
+ but is generally not as effective as using
+ <literal>Decider('MD5-timestamp')</literal>.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title>
+
+ <para>
+
+ Now suppose that our "Hello, World!" program
+ actually has an <literal>#include</literal> line
+ to include the &hello_h; file in the compilation:
+
+ </para>
+
+ <scons_example name="include">
+ <file name="SConstruct">
+ Program('hello.c', CPPPATH = '.')
+ </file>
+ <file name="hello.c" printme="1">
+ #include &lt;hello.h&gt;
+ int
+ main()
+ {
+ printf("Hello, %s!\n", string);
+ }
+ </file>
+ <file name="hello.h">
+ #define string "world"
+ </file>
+ </scons_example>
+
+ <para>
+
+ And, for completeness, the &hello_h; file looks like this:
+
+ </para>
+
+ <scons_example_file example="include" name="hello.h">
+ </scons_example_file>
+
+ <para>
+
+ In this case, we want &SCons; to recognize that,
+ if the contents of the &hello_h; file change,
+ the &hello; program must be recompiled.
+ To do this, we need to modify the
+ &SConstruct; file like so:
+
+ </para>
+
+ <scons_example_file example="include" name="SConstruct">
+ </scons_example_file>
+
+ <para>
+
+ The &cv-link-CPPPATH; value
+ tells &SCons; to look in the current directory
+ (<literal>'.'</literal>)
+ for any files included by C source files
+ (<filename>.c</filename> or <filename>.h</filename> files).
+ With this assignment in the &SConstruct; file:
+
+ </para>
+
+ <scons_output example="include" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ First, notice that &SCons;
+ added the <literal>-I.</literal> argument
+ from the &cv-CPPPATH; variable
+ so that the compilation would find the
+ &hello_h; file in the local directory.
+
+ </para>
+
+ <para>
+
+ Second, realize that &SCons; knows that the &hello;
+ program must be rebuilt
+ because it scans the contents of
+ the &hello_c; file
+ for the <literal>#include</literal> lines that indicate
+ another file is being included in the compilation.
+ &SCons; records these as
+ <emphasis>implicit dependencies</emphasis>
+ of the target file,
+ Consequently,
+ when the &hello_h; file changes,
+ &SCons; realizes that the &hello_c; file includes it,
+ and rebuilds the resulting &hello; program
+ that depends on both the &hello_c; and &hello_h; files.
+
+ </para>
+
+ <para>
+
+ Like the &cv-link-LIBPATH; variable,
+ the &cv-CPPPATH; variable
+ may be a list of directories,
+ or a string separated by
+ the system-specific path separation character
+ (':' on POSIX/Linux, ';' on Windows).
+ Either way, &SCons; creates the
+ right command-line options
+ so that the following example:
+
+ </para>
+
+ <scons_example name="ex5">
+ <file name="SConstruct" printme="1">
+ Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Will look like this on POSIX or Linux:
+
+ </para>
+
+ <scons_output example="ex5" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And like this on Windows:
+
+ </para>
+
+ <scons_output example="ex5" os="win32">
+ <scons_output_command>scons -Q hello.exe</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Caching Implicit Dependencies</title>
+
+ <para>
+
+ Scanning each file for <literal>#include</literal> lines
+ does take some extra processing time.
+ When you're doing a full build of a large system,
+ the scanning time is usually a very small percentage
+ of the overall time spent on the build.
+ You're most likely to notice the scanning time,
+ however, when you <emphasis>rebuild</emphasis>
+ all or part of a large system:
+ &SCons; will likely take some extra time to "think about"
+ what must be built before it issues the
+ first build command
+ (or decides that everything is up to date
+ and nothing must be rebuilt).
+
+ <!--
+ Isn't this expensive? The answer is, it depends. If you do a full build of a
+ large system, the scanning time is insignificant. If you do a rebuild of a
+ large system, then Cons will spend a fair amount of time thinking about it
+ before it decides that nothing has to be done (although not necessarily more
+ time than make!). The good news is that Cons makes it very easy to
+ intelligently subset your build, when you are working on localized changes.
+ -->
+
+ </para>
+
+ <para>
+
+ In practice, having &SCons; scan files saves time
+ relative to the amount of potential time
+ lost to tracking down subtle problems
+ introduced by incorrect dependencies.
+ Nevertheless, the "waiting time"
+ while &SCons; scans files can annoy
+ individual developers waiting for their builds to finish.
+ Consequently, &SCons; lets you cache
+ the implicit dependencies
+ that its scanners find,
+ for use by later builds.
+ You can do this by specifying the
+ &implicit-cache; option on the command line:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q --implicit-cache hello</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If you don't want to specify &implicit-cache;
+ on the command line each time,
+ you can make it the default behavior for your build
+ by setting the &implicit_cache; option
+ in an &SConscript; file:
+
+ </para>
+
+ <sconstruct>
+ SetOption('implicit_cache', 1)
+ </sconstruct>
+
+ <para>
+
+ &SCons; does not cache implicit dependencies like this by default
+ because the &implicit-cache; causes &SCons; to simply use the implicit
+ dependencies stored during the last run, without any checking
+ for whether or not those dependencies are still correct.
+ Specifically, this means &implicit-cache; instructs &SCons;
+ to <emphasis>not</emphasis> rebuild "correctly" in the
+ following cases:
+
+
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <para>
+
+ When &implicit-cache; is used, &SCons; will ignore any changes that
+ may have been made to search paths
+ (like &cv-CPPPATH; or &cv-LIBPATH;,).
+ This can lead to &SCons; not rebuilding a file if a change to
+ &cv-CPPPATH; would normally cause a different, same-named file from
+ a different directory to be used.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ When &implicit-cache; is used, &SCons; will not detect if a
+ same-named file has been added to a directory that is earlier in
+ the search path than the directory in which the file was found
+ last time.
+
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ <section>
+ <title>The &implicit-deps-changed; Option</title>
+
+ <para>
+
+ When using cached implicit dependencies,
+ sometimes you want to "start fresh"
+ and have &SCons; re-scan the files
+ for which it previously cached the dependencies.
+ For example,
+ if you have recently installed a new version of
+ external code that you use for compilation,
+ the external header files will have changed
+ and the previously-cached implicit dependencies
+ will be out of date.
+ You can update them by
+ running &SCons; with the &implicit-deps-changed; option:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q --implicit-deps-changed hello</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In this case, &SCons; will re-scan all of the implicit dependencies
+ and cache updated copies of the information.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &implicit-deps-unchanged; Option</title>
+
+ <para>
+
+ By default when caching dependencies,
+ &SCons; notices when a file has been modified
+ and re-scans the file for any updated
+ implicit dependency information.
+ Sometimes, however, you may want
+ to force &SCons; to use the cached implicit dependencies,
+ even if the source files changed.
+ This can speed up a build for example,
+ when you have changed your source files
+ but know that you haven't changed
+ any <literal>#include</literal> lines.
+ In this case,
+ you can use the &implicit-deps-unchanged; option:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q --implicit-deps-unchanged hello</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In this case,
+ &SCons; will assume that the cached implicit
+ dependencies are correct and
+ will not bother to re-scan changed files.
+ For typical builds after small,
+ incremental changes to source files,
+ the savings may not be very big,
+ but sometimes every bit of
+ improved performance counts.
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>XXX max drift</title>
+
+ XXX SetOption('max_drift')
+
+ </section>
+
+ -->
+
+ </section>
+
+ <section>
+ <title>Explicit Dependencies: the &Depends; Function</title>
+
+ <para>
+
+ Sometimes a file depends on another file
+ that is not detected by an &SCons; scanner.
+ For this situation,
+ &SCons; allows you to specific explicitly that one file
+ depends on another file,
+ and must be rebuilt whenever that file changes.
+ This is specified using the &Depends; method:
+
+ </para>
+
+ <programlisting>
+ hello = Program('hello.c')
+ Depends(hello, 'other_file')
+ </programlisting>
+
+ <!-- XXX mention that you can use arrays for target and source? -->
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit other_file</userinput>
+ [CHANGE THE CONTENTS OF other_file]
+ % <userinput>scons -Q hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ Note that the dependency
+ (the second argument to &Depends;)
+ may also be a list of Node objects
+ (for example, as returned by a call to a Builder):
+
+ </para>
+
+ <programlisting>
+ hello = Program('hello.c')
+ goodbye = Program('goodbye.c')
+ Depends(hello, goodbye)
+ </programlisting>
+
+ <para>
+
+ in which case the dependency or dependencies
+ will be built before the target(s):
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -c goodbye.c -o goodbye.o
+ cc -o goodbye goodbye.o
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Dependencies From External Files: the &ParseDepends;
+ Function</title>
+
+ <para>
+
+ &SCons; has built-in scanners for a number of languages. Sometimes
+ these scanners fail to extract certain implicit dependencies due
+ to limitations of the scanner implementation.
+
+ </para>
+
+ <para>
+
+ The following example illustrates a case where the built-in C
+ scanner is unable to extract the implicit dependency on a header
+ file.
+
+ </para>
+
+ <scons_example name="macroinc">
+ <file name="hello.c" printme="1">
+ #define FOO_HEADER &lt;foo.h&gt;
+ #include FOO_HEADER
+
+ int main() {
+ return FOO;
+ }
+ </file>
+ <file name="SConstruct">
+ Program('hello', 'hello.c', CPPPATH='.')
+ </file>
+ <file name="foo.h">
+ #define FOO 42
+ </file>
+ </scons_example>
+
+ <scons_output example="macroinc" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command output=" [CHANGE CONTENTS OF foo.h]"
+ >edit foo.h</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Apparently, the scanner does not know about the header dependency.
+ Being not a full-fledged C preprocessor, the scanner does not
+ expand the macro.
+
+ </para>
+
+ <para>
+
+ In these cases, you may also use the compiler to extract the
+ implicit dependencies. &ParseDepends; can parse the contents of
+ the compiler output in the style of &Make;, and explicitly
+ establish all of the listed dependencies.
+
+ </para>
+
+ <para>
+
+ The following example uses &ParseDepends; to process a compiler
+ generated dependency file which is generated as a side effect
+ during compilation of the object file:
+
+ </para>
+
+ <!-- XXX The ParseDepends example below fakes proper working by a
+ priori specification of the dependency file. The produced hello.d
+ file is not found (or used) for unknown reasons. -->
+
+ <scons_example name="parsedep">
+ <file name="hello.c">
+ #define FOO_HEADER &lt;foo.h&gt;
+ #include FOO_HEADER
+
+ int main() {
+ return FOO;
+ }
+ </file>
+ <file name="SConstruct" printme="1">
+ obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
+ SideEffect('hello.d', obj)
+ ParseDepends('hello.d')
+ Program('hello', obj)
+ </file>
+ <file name="foo.h">
+ #define FOO 42
+ </file>
+ <file name="hello.d">
+ hello.o: hello.c foo.h
+ </file>
+ </scons_example>
+
+ <scons_output example="parsedep" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command output=" [CHANGE CONTENTS OF foo.h]"
+ >edit foo.h</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Parsing dependencies from a compiler-generated
+ <filename>.d</filename> file has a chicken-and-egg problem, that
+ causes unnecessary rebuilds:
+
+ </para>
+
+ <scons_example name="parsedeprebuild">
+ <file name="hello.c">
+ #define FOO_HEADER &lt;foo.h&gt;
+ #include FOO_HEADER
+
+ int main() {
+ return FOO;
+ }
+ </file>
+ <file name="SConstruct">
+ obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
+ SideEffect('hello.d', obj)
+ ParseDepends('hello.d')
+ Program('hello', obj)
+ </file>
+ <file name="foo.h">
+ #define FOO 42
+ </file>
+ </scons_example>
+
+ <!--
+ <scons_output example="parsedeprebuild" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c -MD -MF hello.d -I. hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q --debug=explain</userinput>
+ scons: rebuilding `hello.o' because `foo.h' is a new dependency
+ cc -o hello.o -c -MD -MF hello.d -I. hello.c
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ In the first pass, the dependency file is generated while the
+ object file is compiled. At that time, &SCons; does not know about
+ the dependency on <filename>foo.h</filename>. In the second pass,
+ the object file is regenerated because <filename>foo.h</filename>
+ is detected as a new dependency.
+
+ </para>
+
+ <para>
+
+ &ParseDepends; immediately reads the specified file at invocation
+ time and just returns if the file does not exist. A dependency
+ file generated during the build process is not automatically
+ parsed again. Hence, the compiler-extracted dependencies are not
+ stored in the signature database during the same build pass. This
+ limitation of &ParseDepends; leads to unnecessary recompilations.
+ Therefore, &ParseDepends; should only be used if scanners are not
+ available for the employed language or not powerful enough for the
+ specific task.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Ignoring Dependencies: the &Ignore; Function</title>
+
+ <para>
+
+ Sometimes it makes sense
+ to not rebuild a program,
+ even if a dependency file changes.
+ In this case,
+ you would tell &SCons; specifically
+ to ignore a dependency as follows:
+
+ </para>
+
+ <scons_example name="ignore">
+ <file name="SConstruct" printme="1">
+ hello = Program('hello.c')
+ Ignore(hello, 'hello.h')
+ </file>
+ <file name="hello.c">
+ #include "hello.h"
+ int main() { printf("Hello, %s!\n", string); }
+ </file>
+ <file name="hello.h">
+ #define string "world"
+ </file>
+ </scons_example>
+
+ <!-- XXX mention that you can use lists for target and source? -->
+
+ <!--
+ <scons_output example="ignore">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
+ </scons_output>
+ -->
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit hello.h</userinput>
+ [CHANGE THE CONTENTS OF hello.h]
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </screen>
+
+ <para>
+
+ Now, the above example is a little contrived,
+ because it's hard to imagine a real-world situation
+ where you wouldn't want to rebuild &hello;
+ if the &hello_h; file changed.
+ A more realistic example
+ might be if the &hello;
+ program is being built in a
+ directory that is shared between multiple systems
+ that have different copies of the
+ &stdio_h; include file.
+ In that case,
+ &SCons; would notice the differences between
+ the different systems' copies of &stdio_h;
+ and would rebuild &hello;
+ each time you change systems.
+ You could avoid these rebuilds as follows:
+
+ </para>
+
+ <programlisting>
+ hello = Program('hello.c', CPPPATH=['/usr/include'])
+ Ignore(hello, '/usr/include/stdio.h')
+ </programlisting>
+
+ <para>
+ &Ignore; can also be used to prevent a generated file from being built
+ by default. This is due to the fact that directories depend on
+ their contents. So to ignore a generated file from the default build,
+ you specify that the directory should ignore the generated file.
+ Note that the file will still be built if the user specifically
+ requests the target on scons command line, or if the file is
+ a dependency of another file which is requested and/or is built
+ by default.
+ </para>
+
+ <scons_example name="ignore_explicit">
+ <file name="SConstruct" printme="1">
+ hello_obj=Object('hello.c')
+ hello = Program(hello_obj)
+ Ignore('.',[hello,hello_obj])
+ </file>
+ <file name="hello.c">
+ #include "stdio.h"
+ int main() { printf("Hello!\n"); }
+ </file>
+ </scons_example>
+
+ <scons_output example="ignore_explicit" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+ </section>
+
+ <section>
+ <title>Order-Only Dependencies: the &Requires; Function</title>
+
+ <para>
+
+ Occasionally,
+ it may be useful to specify that a certain
+ file or directory must, if necessary,
+ be built or created before some other target is built,
+ but that changes to that file or directory
+ do <emphasis>not</emphasis>
+ require that the target itself be rebuilt.
+ Such a relationship is called an
+ <emphasis>order-only dependency</emphasis>
+ because it only affects the order in which
+ things must be built--the dependency before the target--but
+ it is not a strict dependency relationship
+ because the target should not
+ change in response to changes in the dependent file.
+
+ </para>
+
+ <para>
+
+ For example, suppose that you want to create a file
+ every time you run a build
+ that identifies the time the build was performed,
+ the version number, etc.,
+ and which is included in every program that you build.
+ The version file's contents will change every build.
+ If you specify a normal dependency relationship,
+ then every program that depends on
+ that file would be rebuilt every time you ran &SCons;.
+ For example, we could use some Python code in
+ a &SConstruct; file to create a new <filename>version.c</filename> file
+ with a string containing the current date every time
+ we run &SCons;,
+ and then link a program with the resulting object file
+ by listing <filename>version.c</filename> in the sources:
+
+ </para>
+
+ <scons_example name="no-Requires">
+ <file name="SConstruct" printme="1">
+ import time
+
+ version_c_text = """
+ char *date = "%s";
+ """ % time.ctime(time.time())
+ open('version.c', 'w').write(version_c_text)
+
+ hello = Program(['hello.c', 'version.c'])
+ </file>
+ <file name="hello.c">
+ extern char *date;
+ int main() { printf("Hello, %s! I was built: %s\n", date); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ If we list <filename>version.c</filename> as an actual source file,
+ though, then <filename>version.o</filename>
+ will get rebuilt every time we run &SCons;
+ (because the &SConstruct; file itself changes
+ the contents of <filename>version.c</filename>)
+ and the <filename>hello</filename> executable
+ will get re-linked every time
+ (because the <filename>version.o</filename> file changes):
+
+ </para>
+
+ <!--
+
+ <scons_output example="no-Requires">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ gcc -o hello.o -c hello.c
+ gcc -o version.o -c version.c
+ gcc -o hello hello.o version.o
+ % <userinput>scons -Q</userinput>
+ gcc -o version.o -c version.c
+ gcc -o hello hello.o version.o
+ % <userinput>scons -Q</userinput>
+ gcc -o version.o -c version.c
+ gcc -o hello hello.o version.o
+ </screen>
+
+ <para>
+
+ One solution is to use the &Requires; function
+ to specify that the <filename>version.o</filename>
+ must be rebuilt before it is used by the link step,
+ but that changes to <filename>version.o</filename>
+ should not actually cause the <filename>hello</filename>
+ executable to be re-linked:
+
+ </para>
+
+ <scons_example name="Requires">
+ <file name="SConstruct" printme="1">
+ import time
+
+ version_c_text = """
+ char *date = "%s";
+ """ % time.ctime(time.time())
+ open('version.c', 'w').write(version_c_text)
+
+ version_obj = Object('version.c')
+
+ hello = Program('hello.c',
+ LINKFLAGS = str(version_obj[0]))
+
+ Requires(hello, version_obj)
+ </file>
+ <file name="hello.c">
+ extern char *date;
+ int main() { printf("Hello, %s! I was built: %s\n", date); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Notice that because we can no longer list <filename>version.c</filename>
+ as one of the sources for the <filename>hello</filename> program,
+ we have to find some other way to get it into the link command line.
+ For this example, we're cheating a bit and stuffing the
+ object file name (extracted from <literal>version_obj</literal>
+ list returned by the &b-Object; call)
+ into the &cv-link-LINKFLAGS; variable,
+ because &cv-LINKFLAGS; is already included
+ in the &cv-link-LINKCOM; command line.
+
+ </para>
+
+ <para>
+
+ With these changes,
+ we get the desired behavior of
+ re-building the <filename>version.o</filename> file,
+ and therefore re-linking the <filename>hello</filename> executable,
+ only when the <filename>hello.c</filename> has changed:
+
+ </para>
+
+ <scons_output example="Requires">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>The &AlwaysBuild; Function</title>
+
+ <para>
+
+ How &SCons; handles dependencies can also be affected
+ by the &AlwaysBuild; method.
+ When a file is passed to the &AlwaysBuild; method,
+ like so:
+
+ </para>
+
+ <scons_example name="AlwaysBuild">
+ <file name="SConstruct" printme="1">
+ hello = Program('hello.c')
+ AlwaysBuild(hello)
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, %s!\n", string); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then the specified target file (&hello; in our example)
+ will always be considered out-of-date and
+ rebuilt whenever that target file is evaluated
+ while walking the dependency graph:
+
+ </para>
+
+ <scons_output example="AlwaysBuild">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The &AlwaysBuild; function has a somewhat misleading name,
+ because it does not actually mean the target file will
+ be rebuilt every single time &SCons; is invoked.
+ Instead, it means that the target will, in fact,
+ be rebuilt whenever the target file is encountered
+ while evaluating the targets specified on
+ the command line (and their dependencies).
+ So specifying some other target on the command line,
+ a target that does <emphasis>not</emphasis>
+ itself depend on the &AlwaysBuild; target,
+ will still be rebuilt only if it's out-of-date
+ with respect to its dependencies:
+
+ </para>
+
+ <scons_output example="AlwaysBuild">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q hello.o</scons_output_command>
+ </scons_output>
+
+ <!--
+
+ XXX AlwaysBuild() and Alias Nodes
+
+ XXX AlwaysBuild() and Dir Nodes
+
+ XXX AlwaysBuild() with no sources
+
+ -->
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>The &Salt; Method</title>
+
+ <para>
+
+ XXX Salt() (are we going to implement this ?)
+
+ original Cons classic POD documentation:
+
+=head2 The C<Salt> method
+
+The C<Salt> method adds a constant value to the signature calculation
+for every derived file. It is invoked as follows:
+
+ Salt $string;
+
+Changing the Salt value will force a complete rebuild of every derived
+file. This can be used to force rebuilds in certain desired
+circumstances. For example,
+
+ Salt `uname -s`;
+
+Would force a complete rebuild of every derived file whenever the
+operating system on which the build is performed (as reported by C<uname
+-s>) changes.
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/depends.xml b/doc/user/depends.xml
new file mode 100644
index 0000000..b72f41f
--- /dev/null
+++ b/doc/user/depends.xml
@@ -0,0 +1,1776 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ So far we've seen how &SCons; handles one-time builds.
+ But one of the main functions of a build tool like &SCons;
+ is to rebuild only what is necessary
+ when source files change--or, put another way,
+ &SCons; should <emphasis>not</emphasis>
+ waste time rebuilding things that don't need to be rebuilt.
+ You can see this at work simply by re-invoking &SCons;
+ after building our simple &hello; example:
+
+ </para>
+
+
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ </screen>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </screen>
+
+ <para>
+
+ Note that &SCons; reports <literal>"...is up to date"</literal>
+ only for target files named explicitly on the command line,
+ to avoid cluttering the output.
+
+ </para>
+
+ <section>
+ <title>Deciding When an Input File Has Changed: the &Decider; Function</title>
+
+ <para>
+
+ Another aspect of avoiding unnecessary rebuilds
+ is the fundamental build tool behavior
+ of <emphasis>rebuilding</emphasis>
+ things when an input file changes,
+ so that the built software is up to date.
+ By default,
+ &SCons; keeps track of this through an
+ MD5 &signature;, or checksum, of the contents of each file,
+ although you can easily configure
+ &SCons; to use the
+ modification times (or time stamps)
+ instead.
+ You can even specify your own Python function
+ for deciding if an input file has changed.
+
+ </para>
+
+ <section>
+ <title>Using MD5 Signatures to Decide if a File Has Changed</title>
+
+ <para>
+
+ By default,
+ &SCons; keeps track of whether a file has changed
+ based on an MD5 checksum of the file's contents,
+ not the file's modification time.
+ This means that you may be surprised by the
+ default &SCons; behavior if you are used to the
+ &Make; convention of forcing
+ a rebuild by updating the file's modification time
+ (using the &touch; command, for example):
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>touch hello.c</userinput>
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </screen>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>edit hello.c</userinput>
+ [CHANGE THE CONTENTS OF hello.c]
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ Note that you can, if you wish,
+ specify this default behavior
+ (MD5 signatures) explicitly
+ using the &Decider; function as follows:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ Decider('MD5')
+ </programlisting>
+
+ <para>
+
+ You can also use the string <literal>'content'</literal>
+ as a synonym for <literal>'MD5'</literal>
+ when calling the &Decider; function.
+
+ </para>
+
+ <section>
+ <title>Ramifications of Using MD5 Signatures</title>
+
+ <para>
+
+ Using MD5 signatures to decide if an input file has changed
+ has one surprising benefit:
+ if a source file has been changed
+ in such a way that the contents of the
+ rebuilt target file(s)
+ will be exactly the same as the last time
+ the file was built,
+ then any "downstream" target files
+ that depend on the rebuilt-but-not-changed target
+ file actually need not be rebuilt.
+
+ </para>
+
+ <para>
+
+ So if, for example,
+ a user were to only change a comment in a &hello_c; file,
+ then the rebuilt &hello_o; file
+ would be exactly the same as the one previously built
+ (assuming the compiler doesn't put any build-specific
+ information in the object file).
+ &SCons; would then realize that it would not
+ need to rebuild the &hello; program as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>edit hello.c</userinput>
+ [CHANGE A COMMENT IN hello.c]
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ scons: `hello' is up to date.
+ </screen>
+
+ <para>
+
+ In essence, &SCons;
+ "short-circuits" any dependent builds
+ when it realizes that a target file
+ has been rebuilt to exactly the same file as the last build.
+ This does take some extra processing time
+ to read the contents of the target (&hello_o;) file,
+ but often saves time when the rebuild that was avoided
+ would have been time-consuming and expensive.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Using Time Stamps to Decide If a File Has Changed</title>
+
+ <para>
+
+ If you prefer, you can
+ configure &SCons; to use the modification time
+ of a file, not the file contents,
+ when deciding if a target needs to be rebuilt.
+ &SCons; gives you two ways to use time stamps
+ to decide if an input file has changed
+ since the last time a target has been built.
+
+ </para>
+
+ <para>
+
+ The most familiar way to use time stamps
+ is the way &Make; does:
+ that is, have &SCons; decide
+ that a target must be rebuilt
+ if a source file's modification time is
+ <emphasis>newer</emphasis>
+ than the target file.
+ To do this, call the &Decider;
+ function as follows:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ Decider('timestamp-newer')
+ </programlisting>
+
+ <para>
+
+ This makes &SCons; act like &Make;
+ when a file's modification time is updated
+ (using the &touch; command, for example):
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>touch hello.c</userinput>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ And, in fact, because this behavior is the same
+ as the behavior of &Make;,
+ you can also use the string <literal>'make'</literal>
+ as a synonym for <literal>'timestamp-newer'</literal>
+ when calling the &Decider; function:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ Decider('make')
+ </programlisting>
+
+ <para>
+
+ One drawback to using times stamps exactly like &Make;
+ is that if an input file's modification time suddenly
+ becomes <emphasis>older</emphasis> than a target file,
+ the target file will not be rebuilt.
+ This can happen if an old copy of a source file is restored
+ from a backup archive, for example.
+ The contents of the restored file will likely be different
+ than they were the last time a dependent target was built,
+ but the target won't be rebuilt
+ because the modification time of the source file
+ is not newer than the target.
+
+ </para>
+
+ <para>
+
+ Because &SCons; actually stores information
+ about the source files' time stamps whenever a target is built,
+ it can handle this situation by checking for
+ an exact match of the source file time stamp,
+ instead of just whether or not the source file
+ is newer than the target file.
+ To do this, specify the argument
+ <literal>'timestamp-match'</literal>
+ when calling the &Decider; function:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ Decider('timestamp-match')
+ </programlisting>
+
+ <para>
+
+ When configured this way,
+ &SCons; will rebuild a target whenever
+ a source file's modification time has changed.
+ So if we use the <literal>touch -t</literal>
+ option to change the modification time of
+ &hello_c; to an old date (January 1, 1989),
+ &SCons; will still rebuild the target file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>touch -t 198901010000 hello.c</userinput>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ In general, the only reason to prefer
+ <literal>timestamp-newer</literal>
+ instead of
+ <literal>timestamp-match</literal>,
+ would be if you have some specific reason
+ to require this &Make;-like behavior of
+ not rebuilding a target when an otherwise-modified
+ source file is older.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title>
+
+ <para>
+
+ As a performance enhancement,
+ &SCons; provides a way to use
+ MD5 checksums of file contents
+ but to read those contents
+ only when the file's timestamp has changed.
+ To do this, call the &Decider;
+ function with <literal>'MD5-timestamp'</literal>
+ argument as follows:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ Decider('MD5-timestamp')
+ </programlisting>
+
+ <para>
+
+ So configured, &SCons; will still behave like
+ it does when using <literal>Decider('MD5')</literal>:
+
+ </para>
+
+ <!--
+
+ We want to generate the output as follows,
+ but our "surrogate" system for generating the
+ output seems to get this wrong.
+ Just in-line the output for now.
+
+ <scons_output example="MD5-timestamp" os="posix">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>touch hello.c</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>touch hello.c</userinput>
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit hello.c</userinput>
+ [CHANGE THE CONTENTS OF hello.c]
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ However, the second call to &SCons; in the above output,
+ when the build is up-to-date,
+ will have been performed by simply looking at the
+ modification time of the &hello_c; file,
+ not by opening it and performing
+ an MD5 checksum calcuation on its contents.
+ This can significantly speed up many up-to-date builds.
+
+ </para>
+
+ <para>
+
+ The only drawback to using
+ <literal>Decider('MD5-timestamp')</literal>
+ is that &SCons; will <emphasis>not</emphasis>
+ rebuild a target file if a source file was modified
+ within one second of the last time &SCons; built the file.
+ While most developers are programming,
+ this isn't a problem in practice,
+ since it's unlikely that someone will have built
+ and then thought quickly enough to make a substantive
+ change to a source file within one second.
+ Certain build scripts or
+ continuous integration tools may, however,
+ rely on the ability to apply changes to files
+ automatically and then rebuild as quickly as possible,
+ in which case use of
+ <literal>Decider('MD5-timestamp')</literal>
+ may not be appropriate.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Writing Your Own Custom &Decider; Function</title>
+
+ <para>
+
+ The different string values that we've passed to
+ the &Decider; function are essentially used by &SCons;
+ to pick one of several specific internal functions
+ that implement various ways of deciding if a dependency
+ (usually a source file)
+ has changed since a target file has been built.
+ As it turns out,
+ you can also supply your own function
+ to decide if a dependency has changed.
+
+ </para>
+
+ <para>
+
+ For example, suppose we have an input file
+ that contains a lot of data,
+ in some specific regular format,
+ that is used to rebuild a lot of different target files,
+ but each target file really only depends on
+ one particular section of the input file.
+ We'd like to have each target file depend on
+ only its section of the input file.
+ However, since the input file may contain a lot of data,
+ we want to open the input file only if its timestamp has changed.
+ This could done with a custom
+ &Decider; function that might look something like this:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ def decide_if_changed(dependency, target, prev_ni):
+ if self.get_timestamp() != prev_ni.timestamp:
+ dep = str(dependency)
+ tgt = str(target)
+ if specific_part_of_file_has_changed(dep, tgt):
+ return True
+ return False
+ Decider(decide_if_changed)
+ </programlisting>
+
+ <para>
+
+ Note that in the function definition,
+ the <varname>dependency</varname>
+ (input file) is the first argument,
+ and then the &target;.
+ Both of these are passed to the functions as
+ SCons &Node; objects,
+ which we convert to strings using the Python
+ <function>str()</function>.
+
+ </para>
+
+ <para>
+
+ The third argument, <varname>prev_ni</varname>,
+ is an object that holds the
+ signature or timestamp information
+ that was recorded about the dependency
+ the last time the target was built.
+ A <varname>prev_ni</varname> object can hold
+ different information,
+ depending on the type of thing that the
+ <varname>dependency</varname> argument represents.
+ For normal files,
+ the <varname>prev_ni</varname> object
+ has the following attributes:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>.csig</term>
+
+ <listitem>
+ <para>
+ The <emphasis>content signature</emphasis>,
+ or MD5 checksum, of the contents of the
+ <varname>dependency</varname>
+ file the list time the &target; was built.
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>.size</term>
+
+ <listitem>
+ <para>
+ The size in bytes of the <varname>dependency</varname>
+ file the list time the target was built.
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>.timestamp</term>
+
+ <listitem>
+ <para>
+ The modification time of the <varname>dependency</varname>
+ file the list time the &target; was built.
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ Note that ignoring some of the arguments
+ in your custom &Decider; function
+ is a perfectly normal thing to do,
+ if they don't impact the way you want to
+ decide if the dependency file has changed.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Mixing Different Ways of Deciding If a File Has Changed</title>
+
+ <para>
+
+ The previous examples have all demonstrated calling
+ the global &Decider; function
+ to configure all dependency decisions that &SCons; makes.
+ Sometimes, however, you want to be able to configure
+ different decision-making for different targets.
+ When that's necessary, you can use the
+ <function>env.Decider</function>
+ method to affect only the configuration
+ decisions for targets built with a
+ specific construction environment.
+
+ </para>
+
+ <para>
+
+ For example, if we arbitrarily want to build
+ one program using MD5 checkums
+ and another using file modification times
+ from the same source
+ we might configure it this way:
+
+ </para>
+
+ <programlisting>
+ env1 = Environment(CPPPATH = ['.'])
+ env2 = env1.Clone()
+ env2.Decider('timestamp-match')
+ env1.Program('prog-MD5', 'program1.c')
+ env2.Program('prog-timestamp', 'program2.c')
+ </programlisting>
+
+ <para>
+
+ If both of the programs include the same
+ <filename>inc.h</filename> file,
+ then updating the modification time of
+ <filename>inc.h</filename>
+ (using the &touch; command)
+ will cause only <filename>prog-timestamp</filename>
+ to be rebuilt:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o program1.o -c -I. program1.c
+ cc -o prog-MD5 program1.o
+ cc -o program2.o -c -I. program2.c
+ cc -o prog-timestamp program2.o
+ % <userinput>touch inc.h</userinput>
+ % <userinput>scons -Q</userinput>
+ cc -o program2.o -c -I. program2.c
+ cc -o prog-timestamp program2.o
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Older Functions for Deciding When an Input File Has Changed</title>
+
+ <para>
+
+ &SCons; still supports two functions that used to be the
+ primary methods for configuring the
+ decision about whether or not an input file has changed.
+ Although they're not officially deprecated yet,
+ their use is discouraged,
+ mainly because they rely on a somewhat
+ confusing distinction between how
+ source files and target files are handled.
+ These functions are documented here mainly in case you
+ encounter them in existing &SConscript; files.
+
+ </para>
+
+ <section>
+ <title>The &SourceSignatures; Function</title>
+
+ <para>
+
+ The &SourceSignatures; function is fairly straightforward,
+ and supports two different argument values
+ to configure whether source file changes should be decided
+ using MD5 signatures:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ SourceSignatures('MD5')
+ </programlisting>
+
+ <para>
+
+ Or using time stamps:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ SourceSignatures('timestamp')
+ </programlisting>
+
+ <para>
+
+ These are roughly equivalent to specifying
+ <function>Decider('MD5')</function>
+ or
+ <function>Decider('timestamp-match')</function>,
+ respectively,
+ although it only affects how SCons makes
+ decisions about dependencies on
+ <emphasis>source</emphasis> files--that is,
+ files that are not built from any other files.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &TargetSignatures; Function</title>
+
+ <para>
+
+ The &TargetSignatures; function
+ specifies how &SCons; decides
+ when a target file has changed
+ <emphasis>when it is used as a
+ dependency of (input to) another target</emphasis>--that is,
+ the &TargetSignatures; function configures
+ how the signatures of "intermediate" target files
+ are used when deciding if a "downstream" target file
+ must be rebuilt.
+ <footnote><para>
+ This easily-overlooked distinction between
+ how &SCons; decides if the target itself must be rebuilt
+ and how the target is then used to decide if a different
+ target must be rebuilt is one of the confusing
+ things that has led to the &TargetSignatures;
+ and &SourceSignatures; functions being
+ replaced by the simpler &Decider; function.
+ </para></footnote>
+
+ </para>
+
+ <para>
+
+ The &TargetSignatures; function supports the same
+ <literal>'MD5'</literal> and <literal>'timestamp'</literal>
+ argument values that are supported by the &SourceSignatures;,
+ with the same meanings, but applied to target files.
+ That is, in the example:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ TargetSignatures('MD5')
+ </programlisting>
+
+ <para>
+
+ The MD5 checksum of the &hello_o; target file
+ will be used to decide if it has changed since the last
+ time the "downstream" &hello; target file was built.
+ And in the example:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ TargetSignatures('timestamp')
+ </programlisting>
+
+ <para>
+
+ The modification time of the &hello_o; target file
+ will be used to decide if it has changed since the last
+ time the "downstream" &hello; target file was built.
+
+ </para>
+
+ <para>
+
+ The &TargetSignatures; function supports
+ two additional argument values:
+ <literal>'source'</literal> and <literal>'build'</literal>.
+ The <literal>'source'</literal> argument
+ specifies that decisions involving
+ whether target files have changed
+ since a previous build
+ should use the same behavior
+ for the decisions configured for source files
+ (using the &SourceSignatures; function).
+ So in the example:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ TargetSignatures('source')
+ SourceSignatures('timestamp')
+ </programlisting>
+
+ <para>
+
+ All files, both targets and sources,
+ will use modification times
+ when deciding if an input file
+ has changed since the last
+ time a target was built.
+
+ </para>
+
+ <para>
+
+ Lastly, the <literal>'build'</literal> argument
+ specifies that &SCons; should examine
+ the build status of a target file
+ and always rebuild a "downstream" target
+ if the target file was itself rebuilt,
+ without re-examining the contents or timestamp
+ of the newly-built target file.
+ If the target file was not rebuilt during
+ this &scons; invocation,
+ then the target file will be examined
+ the same way as configured by
+ the &SourceSignature; call
+ to decide if it has changed.
+
+ </para>
+
+ <para>
+
+ This mimics the behavior of
+ <literal>build signatures</literal>
+ in earlier versions of &SCons;.
+ A &buildsignature; re-combined
+ signatures of all the input files
+ that went into making the target file,
+ so that the target file itself
+ did not need to have its contents read
+ to compute an MD5 signature.
+ This can improve performance for some configurations,
+ but is generally not as effective as using
+ <literal>Decider('MD5-timestamp')</literal>.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title>
+
+ <para>
+
+ Now suppose that our "Hello, World!" program
+ actually has an <literal>#include</literal> line
+ to include the &hello_h; file in the compilation:
+
+ </para>
+
+ <programlisting>
+ #include &lt;hello.h&gt;
+ int
+ main()
+ {
+ printf("Hello, %s!\n", string);
+ }
+ </programlisting>
+
+ <para>
+
+ And, for completeness, the &hello_h; file looks like this:
+
+ </para>
+
+
+ <programlisting>
+ #define string "world"
+ </programlisting>
+
+ <para>
+
+ In this case, we want &SCons; to recognize that,
+ if the contents of the &hello_h; file change,
+ the &hello; program must be recompiled.
+ To do this, we need to modify the
+ &SConstruct; file like so:
+
+ </para>
+
+
+ <programlisting>
+ Program('hello.c', CPPPATH = '.')
+ </programlisting>
+
+ <para>
+
+ The &cv-link-CPPPATH; value
+ tells &SCons; to look in the current directory
+ (<literal>'.'</literal>)
+ for any files included by C source files
+ (<filename>.c</filename> or <filename>.h</filename> files).
+ With this assignment in the &SConstruct; file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c -I. hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit hello.h</userinput>
+ [CHANGE THE CONTENTS OF hello.h]
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c -I. hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ First, notice that &SCons;
+ added the <literal>-I.</literal> argument
+ from the &cv-CPPPATH; variable
+ so that the compilation would find the
+ &hello_h; file in the local directory.
+
+ </para>
+
+ <para>
+
+ Second, realize that &SCons; knows that the &hello;
+ program must be rebuilt
+ because it scans the contents of
+ the &hello_c; file
+ for the <literal>#include</literal> lines that indicate
+ another file is being included in the compilation.
+ &SCons; records these as
+ <emphasis>implicit dependencies</emphasis>
+ of the target file,
+ Consequently,
+ when the &hello_h; file changes,
+ &SCons; realizes that the &hello_c; file includes it,
+ and rebuilds the resulting &hello; program
+ that depends on both the &hello_c; and &hello_h; files.
+
+ </para>
+
+ <para>
+
+ Like the &cv-link-LIBPATH; variable,
+ the &cv-CPPPATH; variable
+ may be a list of directories,
+ or a string separated by
+ the system-specific path separation character
+ (':' on POSIX/Linux, ';' on Windows).
+ Either way, &SCons; creates the
+ right command-line options
+ so that the following example:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
+ </programlisting>
+
+ <para>
+
+ Will look like this on POSIX or Linux:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c -Iinclude -I/home/project/inc hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ And like this on Windows:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q hello.exe</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Fohello.obj /c hello.c /nologo /Iinclude /I\home\project\inc
+ link /nologo /OUT:hello.exe hello.obj
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Caching Implicit Dependencies</title>
+
+ <para>
+
+ Scanning each file for <literal>#include</literal> lines
+ does take some extra processing time.
+ When you're doing a full build of a large system,
+ the scanning time is usually a very small percentage
+ of the overall time spent on the build.
+ You're most likely to notice the scanning time,
+ however, when you <emphasis>rebuild</emphasis>
+ all or part of a large system:
+ &SCons; will likely take some extra time to "think about"
+ what must be built before it issues the
+ first build command
+ (or decides that everything is up to date
+ and nothing must be rebuilt).
+
+ <!--
+ Isn't this expensive? The answer is, it depends. If you do a full build of a
+ large system, the scanning time is insignificant. If you do a rebuild of a
+ large system, then Cons will spend a fair amount of time thinking about it
+ before it decides that nothing has to be done (although not necessarily more
+ time than make!). The good news is that Cons makes it very easy to
+ intelligently subset your build, when you are working on localized changes.
+ -->
+
+ </para>
+
+ <para>
+
+ In practice, having &SCons; scan files saves time
+ relative to the amount of potential time
+ lost to tracking down subtle problems
+ introduced by incorrect dependencies.
+ Nevertheless, the "waiting time"
+ while &SCons; scans files can annoy
+ individual developers waiting for their builds to finish.
+ Consequently, &SCons; lets you cache
+ the implicit dependencies
+ that its scanners find,
+ for use by later builds.
+ You can do this by specifying the
+ &implicit-cache; option on the command line:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --implicit-cache hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </screen>
+
+ <para>
+
+ If you don't want to specify &implicit-cache;
+ on the command line each time,
+ you can make it the default behavior for your build
+ by setting the &implicit_cache; option
+ in an &SConscript; file:
+
+ </para>
+
+ <programlisting>
+ SetOption('implicit_cache', 1)
+ </programlisting>
+
+ <para>
+
+ &SCons; does not cache implicit dependencies like this by default
+ because the &implicit-cache; causes &SCons; to simply use the implicit
+ dependencies stored during the last run, without any checking
+ for whether or not those dependencies are still correct.
+ Specifically, this means &implicit-cache; instructs &SCons;
+ to <emphasis>not</emphasis> rebuild "correctly" in the
+ following cases:
+
+
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <para>
+
+ When &implicit-cache; is used, &SCons; will ignore any changes that
+ may have been made to search paths
+ (like &cv-CPPPATH; or &cv-LIBPATH;,).
+ This can lead to &SCons; not rebuilding a file if a change to
+ &cv-CPPPATH; would normally cause a different, same-named file from
+ a different directory to be used.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ When &implicit-cache; is used, &SCons; will not detect if a
+ same-named file has been added to a directory that is earlier in
+ the search path than the directory in which the file was found
+ last time.
+
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ <section>
+ <title>The &implicit-deps-changed; Option</title>
+
+ <para>
+
+ When using cached implicit dependencies,
+ sometimes you want to "start fresh"
+ and have &SCons; re-scan the files
+ for which it previously cached the dependencies.
+ For example,
+ if you have recently installed a new version of
+ external code that you use for compilation,
+ the external header files will have changed
+ and the previously-cached implicit dependencies
+ will be out of date.
+ You can update them by
+ running &SCons; with the &implicit-deps-changed; option:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --implicit-deps-changed hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </screen>
+
+ <para>
+
+ In this case, &SCons; will re-scan all of the implicit dependencies
+ and cache updated copies of the information.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &implicit-deps-unchanged; Option</title>
+
+ <para>
+
+ By default when caching dependencies,
+ &SCons; notices when a file has been modified
+ and re-scans the file for any updated
+ implicit dependency information.
+ Sometimes, however, you may want
+ to force &SCons; to use the cached implicit dependencies,
+ even if the source files changed.
+ This can speed up a build for example,
+ when you have changed your source files
+ but know that you haven't changed
+ any <literal>#include</literal> lines.
+ In this case,
+ you can use the &implicit-deps-unchanged; option:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --implicit-deps-unchanged hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </screen>
+
+ <para>
+
+ In this case,
+ &SCons; will assume that the cached implicit
+ dependencies are correct and
+ will not bother to re-scan changed files.
+ For typical builds after small,
+ incremental changes to source files,
+ the savings may not be very big,
+ but sometimes every bit of
+ improved performance counts.
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>XXX max drift</title>
+
+ XXX SetOption('max_drift')
+
+ </section>
+
+ -->
+
+ </section>
+
+ <section>
+ <title>Explicit Dependencies: the &Depends; Function</title>
+
+ <para>
+
+ Sometimes a file depends on another file
+ that is not detected by an &SCons; scanner.
+ For this situation,
+ &SCons; allows you to specific explicitly that one file
+ depends on another file,
+ and must be rebuilt whenever that file changes.
+ This is specified using the &Depends; method:
+
+ </para>
+
+ <programlisting>
+ hello = Program('hello.c')
+ Depends(hello, 'other_file')
+ </programlisting>
+
+ <!-- XXX mention that you can use arrays for target and source? -->
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit other_file</userinput>
+ [CHANGE THE CONTENTS OF other_file]
+ % <userinput>scons -Q hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ Note that the dependency
+ (the second argument to &Depends;)
+ may also be a list of Node objects
+ (for example, as returned by a call to a Builder):
+
+ </para>
+
+ <programlisting>
+ hello = Program('hello.c')
+ goodbye = Program('goodbye.c')
+ Depends(hello, goodbye)
+ </programlisting>
+
+ <para>
+
+ in which case the dependency or dependencies
+ will be built before the target(s):
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -c goodbye.c -o goodbye.o
+ cc -o goodbye goodbye.o
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Dependencies From External Files: the &ParseDepends;
+ Function</title>
+
+ <para>
+
+ &SCons; has built-in scanners for a number of languages. Sometimes
+ these scanners fail to extract certain implicit dependencies due
+ to limitations of the scanner implementation.
+
+ </para>
+
+ <para>
+
+ The following example illustrates a case where the built-in C
+ scanner is unable to extract the implicit dependency on a header
+ file.
+
+ </para>
+
+ <programlisting>
+ #define FOO_HEADER &lt;foo.h&gt;
+ #include FOO_HEADER
+
+ int main() {
+ return FOO;
+ }
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c -I. hello.c
+ cc -o hello hello.o
+ % <userinput>edit foo.h</userinput>
+ [CHANGE CONTENTS OF foo.h]
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Apparently, the scanner does not know about the header dependency.
+ Being not a full-fledged C preprocessor, the scanner does not
+ expand the macro.
+
+ </para>
+
+ <para>
+
+ In these cases, you may also use the compiler to extract the
+ implicit dependencies. &ParseDepends; can parse the contents of
+ the compiler output in the style of &Make;, and explicitly
+ establish all of the listed dependencies.
+
+ </para>
+
+ <para>
+
+ The following example uses &ParseDepends; to process a compiler
+ generated dependency file which is generated as a side effect
+ during compilation of the object file:
+
+ </para>
+
+ <!-- XXX The ParseDepends example below fakes proper working by a
+ priori specification of the dependency file. The produced hello.d
+ file is not found (or used) for unknown reasons. -->
+
+ <programlisting>
+ obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
+ SideEffect('hello.d', obj)
+ ParseDepends('hello.d')
+ Program('hello', obj)
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c -MD -MF hello.d -I. hello.c
+ cc -o hello hello.o
+ % <userinput>edit foo.h</userinput>
+ [CHANGE CONTENTS OF foo.h]
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c -MD -MF hello.d -I. hello.c
+ </screen>
+
+ <para>
+
+ Parsing dependencies from a compiler-generated
+ <filename>.d</filename> file has a chicken-and-egg problem, that
+ causes unnecessary rebuilds:
+
+ </para>
+
+
+
+ <!--
+ <scons_output example="parsedeprebuild" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c -MD -MF hello.d -I. hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q --debug=explain</userinput>
+ scons: rebuilding `hello.o' because `foo.h' is a new dependency
+ cc -o hello.o -c -MD -MF hello.d -I. hello.c
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ In the first pass, the dependency file is generated while the
+ object file is compiled. At that time, &SCons; does not know about
+ the dependency on <filename>foo.h</filename>. In the second pass,
+ the object file is regenerated because <filename>foo.h</filename>
+ is detected as a new dependency.
+
+ </para>
+
+ <para>
+
+ &ParseDepends; immediately reads the specified file at invocation
+ time and just returns if the file does not exist. A dependency
+ file generated during the build process is not automatically
+ parsed again. Hence, the compiler-extracted dependencies are not
+ stored in the signature database during the same build pass. This
+ limitation of &ParseDepends; leads to unnecessary recompilations.
+ Therefore, &ParseDepends; should only be used if scanners are not
+ available for the employed language or not powerful enough for the
+ specific task.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Ignoring Dependencies: the &Ignore; Function</title>
+
+ <para>
+
+ Sometimes it makes sense
+ to not rebuild a program,
+ even if a dependency file changes.
+ In this case,
+ you would tell &SCons; specifically
+ to ignore a dependency as follows:
+
+ </para>
+
+ <programlisting>
+ hello = Program('hello.c')
+ Ignore(hello, 'hello.h')
+ </programlisting>
+
+ <!-- XXX mention that you can use lists for target and source? -->
+
+ <!--
+ <scons_output example="ignore">
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
+ <scons_output_command>scons -Q hello</scons_output_command>
+ XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
+ </scons_output>
+ -->
+
+ <screen>
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit hello.h</userinput>
+ [CHANGE THE CONTENTS OF hello.h]
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </screen>
+
+ <para>
+
+ Now, the above example is a little contrived,
+ because it's hard to imagine a real-world situation
+ where you wouldn't want to rebuild &hello;
+ if the &hello_h; file changed.
+ A more realistic example
+ might be if the &hello;
+ program is being built in a
+ directory that is shared between multiple systems
+ that have different copies of the
+ &stdio_h; include file.
+ In that case,
+ &SCons; would notice the differences between
+ the different systems' copies of &stdio_h;
+ and would rebuild &hello;
+ each time you change systems.
+ You could avoid these rebuilds as follows:
+
+ </para>
+
+ <programlisting>
+ hello = Program('hello.c', CPPPATH=['/usr/include'])
+ Ignore(hello, '/usr/include/stdio.h')
+ </programlisting>
+
+ <para>
+ &Ignore; can also be used to prevent a generated file from being built
+ by default. This is due to the fact that directories depend on
+ their contents. So to ignore a generated file from the default build,
+ you specify that the directory should ignore the generated file.
+ Note that the file will still be built if the user specifically
+ requests the target on scons command line, or if the file is
+ a dependency of another file which is requested and/or is built
+ by default.
+ </para>
+
+ <programlisting>
+ hello_obj=Object('hello.c')
+ hello = Program(hello_obj)
+ Ignore('.',[hello,hello_obj])
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ % <userinput>scons -Q hello</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </screen>
+ </section>
+
+ <section>
+ <title>Order-Only Dependencies: the &Requires; Function</title>
+
+ <para>
+
+ Occasionally,
+ it may be useful to specify that a certain
+ file or directory must, if necessary,
+ be built or created before some other target is built,
+ but that changes to that file or directory
+ do <emphasis>not</emphasis>
+ require that the target itself be rebuilt.
+ Such a relationship is called an
+ <emphasis>order-only dependency</emphasis>
+ because it only affects the order in which
+ things must be built--the dependency before the target--but
+ it is not a strict dependency relationship
+ because the target should not
+ change in response to changes in the dependent file.
+
+ </para>
+
+ <para>
+
+ For example, suppose that you want to create a file
+ every time you run a build
+ that identifies the time the build was performed,
+ the version number, etc.,
+ and which is included in every program that you build.
+ The version file's contents will change every build.
+ If you specify a normal dependency relationship,
+ then every program that depends on
+ that file would be rebuilt every time you ran &SCons;.
+ For example, we could use some Python code in
+ a &SConstruct; file to create a new <filename>version.c</filename> file
+ with a string containing the current date every time
+ we run &SCons;,
+ and then link a program with the resulting object file
+ by listing <filename>version.c</filename> in the sources:
+
+ </para>
+
+ <programlisting>
+ import time
+
+ version_c_text = """
+ char *date = "%s";
+ """ % time.ctime(time.time())
+ open('version.c', 'w').write(version_c_text)
+
+ hello = Program(['hello.c', 'version.c'])
+ </programlisting>
+
+ <para>
+
+ If we list <filename>version.c</filename> as an actual source file,
+ though, then <filename>version.o</filename>
+ will get rebuilt every time we run &SCons;
+ (because the &SConstruct; file itself changes
+ the contents of <filename>version.c</filename>)
+ and the <filename>hello</filename> executable
+ will get re-linked every time
+ (because the <filename>version.o</filename> file changes):
+
+ </para>
+
+ <!--
+
+ <scons_output example="no-Requires">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ gcc -o hello.o -c hello.c
+ gcc -o version.o -c version.c
+ gcc -o hello hello.o version.o
+ % <userinput>scons -Q</userinput>
+ gcc -o version.o -c version.c
+ gcc -o hello hello.o version.o
+ % <userinput>scons -Q</userinput>
+ gcc -o version.o -c version.c
+ gcc -o hello hello.o version.o
+ </screen>
+
+ <para>
+
+ One solution is to use the &Requires; function
+ to specify that the <filename>version.o</filename>
+ must be rebuilt before it is used by the link step,
+ but that changes to <filename>version.o</filename>
+ should not actually cause the <filename>hello</filename>
+ executable to be re-linked:
+
+ </para>
+
+ <programlisting>
+ import time
+
+ version_c_text = """
+ char *date = "%s";
+ """ % time.ctime(time.time())
+ open('version.c', 'w').write(version_c_text)
+
+ version_obj = Object('version.c')
+
+ hello = Program('hello.c',
+ LINKFLAGS = str(version_obj[0]))
+
+ Requires(hello, version_obj)
+ </programlisting>
+
+ <para>
+
+ Notice that because we can no longer list <filename>version.c</filename>
+ as one of the sources for the <filename>hello</filename> program,
+ we have to find some other way to get it into the link command line.
+ For this example, we're cheating a bit and stuffing the
+ object file name (extracted from <literal>version_obj</literal>
+ list returned by the &b-Object; call)
+ into the &cv-link-LINKFLAGS; variable,
+ because &cv-LINKFLAGS; is already included
+ in the &cv-link-LINKCOM; command line.
+
+ </para>
+
+ <para>
+
+ With these changes,
+ we get the desired behavior of
+ re-building the <filename>version.o</filename> file,
+ and therefore re-linking the <filename>hello</filename> executable,
+ only when the <filename>hello.c</filename> has changed:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o version.o -c version.c
+ cc -o hello.o -c hello.c
+ cc -o hello version.o hello.o
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ % <userinput>edit hello.c</userinput>
+ [CHANGE THE CONTENTS OF hello.c]
+ % <userinput>scons -Q</userinput>
+ cc -o version.o -c version.c
+ cc -o hello.o -c hello.c
+ cc -o hello version.o hello.o
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &AlwaysBuild; Function</title>
+
+ <para>
+
+ How &SCons; handles dependencies can also be affected
+ by the &AlwaysBuild; method.
+ When a file is passed to the &AlwaysBuild; method,
+ like so:
+
+ </para>
+
+ <programlisting>
+ hello = Program('hello.c')
+ AlwaysBuild(hello)
+ </programlisting>
+
+ <para>
+
+ Then the specified target file (&hello; in our example)
+ will always be considered out-of-date and
+ rebuilt whenever that target file is evaluated
+ while walking the dependency graph:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q</userinput>
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ The &AlwaysBuild; function has a somewhat misleading name,
+ because it does not actually mean the target file will
+ be rebuilt every single time &SCons; is invoked.
+ Instead, it means that the target will, in fact,
+ be rebuilt whenever the target file is encountered
+ while evaluating the targets specified on
+ the command line (and their dependencies).
+ So specifying some other target on the command line,
+ a target that does <emphasis>not</emphasis>
+ itself depend on the &AlwaysBuild; target,
+ will still be rebuilt only if it's out-of-date
+ with respect to its dependencies:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello.o</userinput>
+ scons: `hello.o' is up to date.
+ </screen>
+
+ <!--
+
+ XXX AlwaysBuild() and Alias Nodes
+
+ XXX AlwaysBuild() and Dir Nodes
+
+ XXX AlwaysBuild() with no sources
+
+ -->
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>The &Salt; Method</title>
+
+ <para>
+
+ XXX Salt() (are we going to implement this ?)
+
+ original Cons classic POD documentation:
+
+=head2 The C<Salt> method
+
+The C<Salt> method adds a constant value to the signature calculation
+for every derived file. It is invoked as follows:
+
+ Salt $string;
+
+Changing the Salt value will force a complete rebuild of every derived
+file. This can be used to force rebuilds in certain desired
+circumstances. For example,
+
+ Salt `uname -s`;
+
+Would force a complete rebuild of every derived file whenever the
+operating system on which the build is performed (as reported by C<uname
+-s>) changes.
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/environments.in b/doc/user/environments.in
new file mode 100644
index 0000000..124aaaa
--- /dev/null
+++ b/doc/user/environments.in
@@ -0,0 +1,1678 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 More on construction environments
+
+As previously mentioned, a B<construction environment> is an object that
+has a set of keyword/value pairs and a set of methods, and which is used
+to tell Cons how target files should be built. This section describes
+how Cons uses and expands construction environment values to control its
+build behavior.
+
+=head2 Construction variable expansion
+
+Construction variables from a construction environment are expanded
+by preceding the keyword with a C<%> (percent sign):
+
+ Construction variables:
+ XYZZY => 'abracadabra',
+
+ The string: "The magic word is: %XYZZY!"
+ expands to: "The magic word is: abracadabra!"
+
+A construction variable name may be surrounded by C<{> and C<}> (curly
+braces), which are stripped as part of the expansion. This can
+sometimes be necessary to separate a variable expansion from trailing
+alphanumeric characters:
+
+ Construction variables:
+ OPT => 'value1',
+ OPTION => 'value2',
+
+ The string: "%OPT %{OPT}ION %OPTION %{OPTION}"
+ expands to: "value1 value1ION value2 value2"
+
+Construction variable expansion is recursive, that is, a string
+containing C<%->expansions after substitution will be re-expanded until
+no further substitutions can be made:
+
+ Construction variables:
+ STRING => 'The result is: %FOO',
+ FOO => '%BAR',
+ BAR => 'final value',
+
+ The string: "The string says: %STRING"
+ expands to: "The string says: The result is: final value"
+
+If a construction variable is not defined in an environment, then the
+null string is substituted:
+
+ Construction variables:
+ FOO => 'value1',
+ BAR => 'value2',
+
+ The string: "%FOO <%NO_VARIABLE> %BAR"
+ expands to: "value1 <> value2"
+
+A doubled C<%%> will be replaced by a single C<%>:
+
+ The string: "Here is a percent sign: %%"
+ expands to: "Here is a percent sign: %"
+
+=head2 Default construction variables
+
+When you specify no arguments when creating a new construction
+environment:
+
+ $env = new cons();
+
+Cons creates a reference to a new, default construction
+environment. This contains a number of construction variables and some
+methods. At the present writing, the default construction variables on a
+UNIX system are:
+
+ CC => 'cc',
+ CFLAGS => '',
+ CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
+ CXX => '%CC',
+ CXXFLAGS => '%CFLAGS',
+ CXXCOM => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>',
+ INCDIRPREFIX => '-I',
+ INCDIRSUFFIX => '',
+ LINK => '%CXX',
+ LINKCOM => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS',
+ LINKMODULECOM => '%LD -r -o %> %<',
+ LIBDIRPREFIX => '-L',
+ LIBDIRSUFFIX => '',
+ AR => 'ar',
+ ARFLAGS => 'r',
+ ARCOM => ['%AR %ARFLAGS %> %<', '%RANLIB %>'],
+ RANLIB => 'ranlib',
+ AS => 'as',
+ ASFLAGS => '',
+ ASCOM => '%AS %ASFLAGS %< -o %>',
+ LD => 'ld',
+ LDFLAGS => '',
+ PREFLIB => 'lib',
+ SUFLIB => '.a',
+ SUFLIBS => '.so:.a',
+ SUFOBJ => '.o',
+ SIGNATURE => [ '*' => 'build' ],
+ ENV => { 'PATH' => '/bin:/usr/bin' },
+
+
+And on a Windows system (Windows NT), the default construction variables
+are (unless the default rule style is set using the B<DefaultRules>
+method):
+
+ CC => 'cl',
+ CFLAGS => '/nologo',
+ CCCOM => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>',
+ CXXCOM => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>',
+ INCDIRPREFIX => '/I',
+ INCDIRSUFFIX => '',
+ LINK => 'link',
+ LINKCOM => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS',
+ LINKMODULECOM => '%LD /r /o %> %<',
+ LIBDIRPREFIX => '/LIBPATH:',
+ LIBDIRSUFFIX => '',
+ AR => 'lib',
+ ARFLAGS => '/nologo ',
+ ARCOM => "%AR %ARFLAGS /out:%> %<",
+ RANLIB => '',
+ LD => 'link',
+ LDFLAGS => '/nologo ',
+ PREFLIB => '',
+ SUFEXE => '.exe',
+ SUFLIB => '.lib',
+ SUFLIBS => '.dll:.lib',
+ SUFOBJ => '.obj',
+ SIGNATURE => [ '*' => 'build' ],
+
+These variables are used by the various methods associated with the
+environment. In particular, any method that ultimately invokes an external
+command will substitute these variables into the final command, as
+appropriate. For example, the C<Objects> method takes a number of source
+files and arranges to derive, if necessary, the corresponding object
+files:
+
+ Objects $env 'foo.c', 'bar.c';
+
+This will arrange to produce, if necessary, F<foo.o> and F<bar.o>. The
+command invoked is simply C<%CCCOM>, which expands, through substitution,
+to the appropriate external command required to build each object. The
+substitution rules will be discussed in detail in the next section.
+
+The construction variables are also used for other purposes. For example,
+C<CPPPATH> is used to specify a colon-separated path of include
+directories. These are intended to be passed to the C preprocessor and are
+also used by the C-file scanning machinery to determine the dependencies
+involved in a C Compilation.
+
+Variables beginning with underscore are created by various methods,
+and should normally be considered ``internal'' variables. For example,
+when a method is called which calls for the creation of an object from
+a C source, the variable C<_IFLAGS> is created: this corresponds to the
+C<-I> switches required by the C compiler to represent the directories
+specified by C<CPPPATH>.
+
+Note that, for any particular environment, the value of a variable is set
+once, and then never reset (to change a variable, you must create a new
+environment. Methods are provided for copying existing environments for this
+purpose). Some internal variables, such as C<_IFLAGS> are created on demand,
+but once set, they remain fixed for the life of the environment.
+
+The C<CFLAGS>, C<LDFLAGS>, and C<ARFLAGS> variables all supply a place
+for passing options to the compiler, loader, and archiver, respectively.
+
+The C<INCDIRPREFIX> and C<INCDIRSUFFIX> variables specify option
+strings to be appended to the beginning and end, respectively, of each
+include directory so that the compiler knows where to find F<.h> files.
+Similarly, the C<LIBDIRPREFIX> and C<LIBDIRSUFFIX> variables specify the
+option string to be appended to the beginning of and end, respectively,
+of each directory that the linker should search for libraries.
+
+Another variable, C<ENV>, is used to determine the system environment during
+the execution of an external command. By default, the only environment
+variable that is set is C<PATH>, which is the execution path for a UNIX
+command. For the utmost reproducibility, you should really arrange to set
+your own execution path, in your top-level F<Construct> file (or perhaps by
+importing an appropriate construction package with the Perl C<use>
+command). The default variables are intended to get you off the ground.
+
+=head2 Expanding variables in construction commands
+
+Within a construction command, construction variables will be expanded
+according to the rules described above. In addition to normal variable
+expansion from the construction environment, construction commands also
+expand the following pseudo-variables to insert the specific input and
+output files in the command line that will be executed:
+
+=over 10
+
+=item %>
+
+The target file name. In a multi-target command, this expands to the
+first target mentioned.)
+
+=item %0
+
+Same as C<%E<gt>>.
+
+=item %1, %2, ..., %9
+
+These refer to the first through ninth input file, respectively.
+
+=item %E<lt>
+
+The full set of input file names. If any of these have been used
+anywhere else in the current command line (via C<%1>, C<%2>, etc.), then
+those will be deleted from the list provided by C<%E<lt>>. Consider the
+following command found in a F<Conscript> file in the F<test> directory:
+
+ Command $env 'tgt', qw(foo bar baz), qq(
+ echo %< -i %1 > %>
+ echo %< -i %2 >> %>
+ echo %< -i %3 >> %>
+ );
+
+If F<tgt> needed to be updated, then this would result in the execution of
+the following commands, assuming that no remapping has been established for
+the F<test> directory:
+
+ echo test/bar test/baz -i test/foo > test/tgt
+ echo test/foo test/baz -i test/bar >> test/tgt
+ echo test/foo test/bar -i test/baz >> test/tgt
+
+=back
+
+Any of the above pseudo-variables may be followed immediately by one of
+the following suffixes to select a portion of the expanded path name:
+
+ :a the absolute path to the file name
+ :b the directory plus the file name stripped of any suffix
+ :d the directory
+ :f the file name
+ :s the file name suffix
+ :F the file name stripped of any suffix
+ :S the absolute path path to a Linked source file
+
+Continuing with the above example, C<%E<lt>:f> would expand to C<foo bar baz>,
+and C<%E<gt>:d> would expand to C<test>.
+
+There are additional C<%> elements which affect the command line(s):
+
+=over 10
+
+=item %[ %]
+
+It is possible to programmatically rewrite part of the command by
+enclosing part of it between C<%[> and C<%]>. This will call the
+construction variable named as the first word enclosed in the brackets
+as a Perl code reference; the results of this call will be used to
+replace the contents of the brackets in the command line. For example,
+given an existing input file named F<tgt.in>:
+
+ @keywords = qw(foo bar baz);
+ $env = new cons(X_COMMA => sub { join(",", @_) });
+ Command $env 'tgt', 'tgt.in', qq(
+ echo '# Keywords: %[X_COMMA @keywords %]' > %>
+ cat %< >> %>
+ );
+
+This will execute:
+
+ echo '# Keywords: foo,bar,baz' > tgt
+ cat tgt.in >> tgt
+
+=item %( %)
+
+Cons includes the text of the command line in the MD5 signature for a
+build, so that targets get rebuilt if you change the command line (to
+add or remove an option, for example). Command-line text in between
+C<%(> and C<%)>, however, will be ignored for MD5 signature calculation.
+
+Internally, Cons uses C<%(> and C<%)> around include and library
+directory options (C<-I> and C<-L> on UNIX systems, C</I> and
+C</LIBPATH> on Windows NT) to avoid rebuilds just because the directory
+list changes. Rebuilds occur only if the changed directory list causes
+any included I<files> to change, and a changed include file is detected
+by the MD5 signature calculation on the actual file contents.
+
+=back
+
+XXX DESCRIBE THE Literal() FUNCTION, TOO XXX
+
+=head2 Expanding construction variables in file names
+
+Cons expands construction variables in the source and target file names
+passed to the various construction methods according to the expansion
+rules described above:
+
+ $env = new cons(
+ DESTDIR => 'programs',
+ SRCDIR => 'src',
+ );
+ Program $env '%DESTDIR/hello', '%SRCDIR/hello.c';
+
+This allows for flexible configuration, through the construction
+environment, of directory names, suffixes, etc.
+
+-->
+
+ <para>
+
+ An <literal>environment</literal>
+ is a collection of values that
+ can affect how a program executes.
+ &SCons; distinguishes between three
+ different types of environments
+ that can affect the behavior of &SCons; itself
+ (subject to the configuration in the &SConscript; files),
+ as well as the compilers and other tools it executes:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>External Environment</term>
+
+ <listitem>
+ <para>
+
+ The <literal>external environment</literal>
+ is the set of variables in the user's environment
+ at the time the user runs &SCons.
+ These variables are available within the &SConscript; files
+ through the Python <literal>os.environ</literal> dictionary.
+ See <xref linkend="sect-external-environments"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>&ConsEnv;</term>
+
+ <listitem>
+ <para>
+
+ A &consenv;
+ is a distinct object creating within
+ a &SConscript; file and
+ and which contains values that
+ affect how &SCons; decides
+ what action to use to build a target,
+ and even to define which targets
+ should be built from which sources.
+ One of the most powerful features of &SCons;
+ is the ability to create multiple &consenvs;,
+ including the ability to clone a new, customized
+ &consenv; from an existing &consenv;.
+ See <xref linkend="sect-construction-environments"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Execution Environment</term>
+
+ <listitem>
+ <para>
+
+ An <literal>execution environment</literal>
+ is the values that &SCons; sets
+ when executing an external
+ command (such as a compiler or linker)
+ to build one or more targets.
+ Note that this is not the same as
+ the <literal>external environment</literal>
+ (see above).
+ See <xref linkend="sect-execution-environments"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ Unlike &Make;, &SCons; does not automatically
+ copy or import values between different environments
+ (with the exception of explicit clones of &consenvs,
+ which inherit values from their parent).
+ This is a deliberate design choice
+ to make sure that builds are,
+ by default, repeatable regardless of
+ the values in the user's external environment.
+ This avoids a whole class of problems with builds
+ where a developer's local build works
+ because a custom variable setting
+ causes a different compiler or build option to be used,
+ but the checked-in change breaks the official build
+ because it uses different environment variable settings.
+
+ </para>
+
+ <para>
+
+ Note that the &SConscript; writer can
+ easily arrange for variables to be
+ copied or imported between environments,
+ and this is often very useful
+ (or even downright necessary)
+ to make it easy for developers
+ to customize the build in appropriate ways.
+ The point is <emphasis>not</emphasis>
+ that copying variables between different environments
+ is evil and must always be avoided.
+ Instead, it should be up to the
+ implementer of the build system
+ to make conscious choices
+ about how and when to import
+ a variable from one environment to another,
+ making informed decisions about
+ striking the right balance
+ between making the build
+ repeatable on the one hand
+ and convenient to use on the other.
+
+ </para>
+
+ <section id="sect-external-environments">
+ <title>Using Values From the External Environment</title>
+
+ <para>
+
+ The <literal>external environment</literal>
+ variable settings that
+ the user has in force
+ when executing &SCons;
+ are available through the normal Python
+ <envar>os.environ</envar>
+ dictionary.
+ This means that you must add an
+ <literal>import os</literal> statement
+ to any &SConscript; file
+ in which you want to use
+ values from the user's external environment.
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ import os
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ More usefully, you can use the
+ <envar>os.environ</envar>
+ dictionary in your &SConscript;
+ files to initialize &consenvs;
+ with values from the user's external environment.
+ See the next section,
+ <xref linkend="sect-construction-environments"></xref>,
+ for information on how to do this.
+
+ </para>
+
+ </section>
+
+ <section id="sect-construction-environments">
+ <title>Construction Environments</title>
+
+ <para>
+
+ It is rare that all of the software in a large,
+ complicated system needs to be built the same way.
+ For example, different source files may need different options
+ enabled on the command line,
+ or different executable programs need to be linked
+ with different libraries.
+ &SCons; accommodates these different build
+ requirements by allowing you to create and
+ configure multiple &consenvs;
+ that control how the software is built.
+ A &consenv; is an object
+ that has a number of associated
+ &consvars;, each with a name and a value.
+ (A construction environment also has an attached
+ set of &Builder; methods,
+ about which we'll learn more later.)
+
+ </para>
+
+ <section>
+ <title>Creating a &ConsEnv;: the &Environment; Function</title>
+
+ <para>
+
+ A &consenv; is created by the &Environment; method:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ </sconstruct>
+
+ <para>
+
+ By default, &SCons; initializes every
+ new construction environment
+ with a set of &consvars;
+ based on the tools that it finds on your system,
+ plus the default set of builder methods
+ necessary for using those tools.
+ The construction variables
+ are initialized with values describing
+ the C compiler,
+ the Fortran compiler,
+ the linker,
+ etc.,
+ as well as the command lines to invoke them.
+
+ </para>
+
+ <para>
+
+ When you initialize a construction environment
+ you can set the values of the
+ environment's &consvars;
+ to control how a program is built.
+ For example:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment(CC = 'gcc',
+ CCFLAGS = '-O2')
+
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ The construction environment in this example
+ is still initialized with the same default
+ construction variable values,
+ except that the user has explicitly specified use of the
+ GNU C compiler &gcc;,
+ and further specifies that the <literal>-O2</literal>
+ (optimization level two)
+ flag should be used when compiling the object file.
+ In other words, the explicit initializations of
+ &cv-link-CC; and &cv-link-CCFLAGS;
+ override the default values in the newly-created
+ construction environment.
+ So a run from this example would look like:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Fetching Values From a &ConsEnv;</title>
+
+ <para>
+
+ You can fetch individual construction variables
+ using the normal syntax
+ for accessing individual named items in a Python dictionary:
+
+ </para>
+
+ <scons_example name="ex6">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ print "CC is:", env['CC']
+ </file>
+ </scons_example>
+
+ <para>
+
+ This example &SConstruct; file doesn't build anything,
+ but because it's actually a Python script,
+ it will print the value of &cv-link-CC; for us:
+
+ </para>
+
+ <scons_output example="ex6">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ A construction environment, however,
+ is actually an object with associated methods, etc.
+ If you want to have direct access to only the
+ dictionary of construction variables,
+ you can fetch this using the &Dictionary; method:
+
+ </para>
+
+ <scons_example name="ex6b">
+ <file name="SConstruct" printme="1">
+ env = Environment(FOO = 'foo', BAR = 'bar')
+ dict = env.Dictionary()
+ for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
+ print "key = %s, value = %s" % (key, dict[key])
+ </file>
+ </scons_Example>
+
+ <para>
+
+ This &SConstruct; file
+ will print the specified dictionary items for us on POSIX
+ systems as follows:
+
+ </para>
+
+ <scons_output example="ex6b" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And on Windows:
+
+ </para>
+
+ <scons_output example="ex6b" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If you want to loop and print the values of
+ all of the construction variables in a construction environment,
+ the Python code to do that in sorted order might look something like:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ dict = env.Dictionary()
+ keys = dict.keys()
+ keys.sort()
+ for key in keys:
+ print "construction variable = '%s', value = '%s'" % (key, dict[key])
+ </sconstruct>
+
+ </section>
+
+ <section>
+ <title>Expanding Values From a &ConsEnv;: the &subst; Method</title>
+
+ <para>
+
+ Another way to get information from
+ a construction environment.
+ is to use the &subst; method
+ on a string containing <literal>$</literal> expansions
+ of construction variable names.
+ As a simple example,
+ the example from the previous
+ section that used
+ <literal>env['CC']</literal>
+ to fetch the value of &cv-link-CC;
+ could also be written as:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ print "CC is:", env.subst('$CC')
+ </sconstruct>
+
+ <para>
+
+ One advantage of using
+ &subst; to expand strings is
+ that construction variables
+ in the result get re-expanded until
+ there are no expansions left in the string.
+ So a simple fetch of a value like
+ &cv-link-CCCOM;:
+
+ </para>
+
+ <sconstruct>
+ env = Environment(CCFLAGS = '-DFOO')
+ print "CCCOM is:", env['CCCOM']
+ </sconstruct>
+
+ <para>
+
+ Will print the unexpanded value of &cv-CCCOM;,
+ showing us the construction
+ variables that still need to be expanded:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Calling the &subst; method on <varname>$CCOM</varname>,
+ however:
+
+ </para>
+
+ <sconstruct>
+ env = Environment(CCFLAGS = '-DFOO')
+ print "CCCOM is:", env.subst('$CCCOM')
+ </sconstruct>
+
+ <para>
+
+ Will recursively expand all of
+ the construction variables prefixed
+ with <literal>$</literal> (dollar signs),
+ showing us the final output:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CCCOM is: gcc -DFOO -c -o
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Note that because we're not expanding this
+ in the context of building something
+ there are no target or source files
+ for &cv-link-TARGET; and &cv-link-SOURCES; to expand.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Controlling the Default &ConsEnv;: the &DefaultEnvironment; Function</title>
+
+ <para>
+
+ All of the &Builder; functions that we've introduced so far,
+ like &Program; and &Library;,
+ actually use a default &consenv;
+ that contains settings
+ for the various compilers
+ and other tools that
+ &SCons; configures by default,
+ or otherwise knows about
+ and has discovered on your system.
+ The goal of the default construction environment
+ is to make many configurations to "just work"
+ to build software using
+ readily available tools
+ with a minimum of configuration changes.
+
+ </para>
+
+ <para>
+
+ You can, however, control the settings
+ in the default contstruction environment
+ by using the &DefaultEnvironment; function
+ to initialize various settings:
+
+ </para>
+
+ <sconstruct>
+
+ DefaultEnvironment(CC = '/usr/local/bin/gcc')
+
+ </sconstruct>
+
+ <para>
+
+ When configured as above,
+ all calls to the &Program;
+ or &Object; Builder
+ will build object files with the
+ <filename>/usr/local/bin/gcc</filename>
+ compiler.
+
+ </para>
+
+ <para>
+
+ Note that the &DefaultEnvironment; function
+ returns the initialized
+ default construction environment object,
+ which can then be manipulated like any
+ other construction environment.
+ So the following
+ would be equivalent to the
+ previous example,
+ setting the &cv-CC;
+ variable to <filename>/usr/local/bin/gcc</filename>
+ but as a separate step after
+ the default construction environment has been initialized:
+
+ </para>
+
+ <sconstruct>
+
+ env = DefaultEnvironment()
+ env['CC'] = '/usr/local/bin/gcc'
+
+ </sconstruct>
+
+ <para>
+
+ One very common use of the &DefaultEnvironment; function
+ is to speed up &SCons; initialization.
+ As part of trying to make most default
+ configurations "just work,"
+ &SCons; will actually
+ search the local system for installed
+ compilers and other utilities.
+ This search can take time,
+ especially on systems with
+ slow or networked file systems.
+ If you know which compiler(s) and/or
+ other utilities you want to configure,
+ you can control the search
+ that &SCons; performs
+ by specifying some specific
+ tool modules with which to
+ initialize the default construction environment:
+
+ </para>
+
+ <sconstruct>
+
+ env = DefaultEnvironment(tools = ['gcc', 'gnulink'],
+ CC = '/usr/local/bin/gcc')
+
+ </sconstruct>
+
+ <para>
+
+ So the above example would tell &SCons;
+ to explicitly configure the default environment
+ to use its normal GNU Compiler and GNU Linker settings
+ (without having to search for them,
+ or any other utilities for that matter),
+ and specifically to use the compiler found at
+ <filename>/usr/local/bin/gcc</filename>.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Multiple &ConsEnvs;</title>
+
+ <para>
+
+ The real advantage of construction environments
+ is that you can create as many different construction
+ environments as you need,
+ each tailored to a different way to build
+ some piece of software or other file.
+ If, for example, we need to build
+ one program with the <literal>-O2</literal> flag
+ and another with the <literal>-g</literal> (debug) flag,
+ we would do this like so:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
+
+ opt.Program('foo', 'foo.c')
+
+ dbg.Program('bar', 'bar.c')
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ <file name="bar.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <scons_output example="ex2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ We can even use multiple construction environments to build
+ multiple versions of a single program.
+ If you do this by simply trying to use the
+ &b-link-Program; builder with both environments, though,
+ like this:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct" printme="1">
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
+
+ opt.Program('foo', 'foo.c')
+
+ dbg.Program('foo', 'foo.c')
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then &SCons; generates the following error:
+
+ </para>
+
+ <scons_output example="ex3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ This is because the two &b-Program; calls have
+ each implicitly told &SCons; to generate an object file named
+ <filename>foo.o</filename>,
+ one with a &cv-link-CCFLAGS; value of
+ <literal>-O2</literal>
+ and one with a &cv-link-CCFLAGS; value of
+ <literal>-g</literal>.
+ &SCons; can't just decide that one of them
+ should take precedence over the other,
+ so it generates the error.
+ To avoid this problem,
+ we must explicitly specify
+ that each environment compile
+ <filename>foo.c</filename>
+ to a separately-named object file
+ using the &b-link-Object; builder, like so:
+
+ </para>
+
+ <scons_example name="ex4">
+ <file name="SConstruct" printme="1">
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
+
+ o = opt.Object('foo-opt', 'foo.c')
+ opt.Program(o)
+
+ d = dbg.Object('foo-dbg', 'foo.c')
+ dbg.Program(d)
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Notice that each call to the &b-Object; builder
+ returns a value,
+ an internal &SCons; object that
+ represents the object file that will be built.
+ We then use that object
+ as input to the &b-Program; builder.
+ This avoids having to specify explicitly
+ the object file name in multiple places,
+ and makes for a compact, readable
+ &SConstruct; file.
+ Our &SCons; output then looks like:
+
+ </para>
+
+ <scons_output example="ex4">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Making Copies of &ConsEnvs;: the &Clone; Method</title>
+
+ <para>
+
+ Sometimes you want more than one construction environment
+ to share the same values for one or more variables.
+ Rather than always having to repeat all of the common
+ variables when you create each construction environment,
+ you can use the &Clone; method
+ to create a copy of a construction environment.
+
+ </para>
+
+ <para>
+
+ Like the &Environment; call that creates a construction environment,
+ the &Clone; method takes &consvar; assignments,
+ which will override the values in the copied construction environment.
+ For example, suppose we want to use &gcc;
+ to create three versions of a program,
+ one optimized, one debug, and one with neither.
+ We could do this by creating a "base" construction environment
+ that sets &cv-link-CC; to &gcc;,
+ and then creating two copies,
+ one which sets &cv-link-CCFLAGS; for optimization
+ and the other which sets &cv-CCFLAGS; for debugging:
+
+ </para>
+
+ <scons_example name="ex5">
+ <file name="SConstruct" printme="1">
+ env = Environment(CC = 'gcc')
+ opt = env.Clone(CCFLAGS = '-O2')
+ dbg = env.Clone(CCFLAGS = '-g')
+
+ env.Program('foo', 'foo.c')
+
+ o = opt.Object('foo-opt', 'foo.c')
+ opt.Program(o)
+
+ d = dbg.Object('foo-dbg', 'foo.c')
+ dbg.Program(d)
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then our output would look like:
+
+ </para>
+
+ <scons_output example="ex5">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Replacing Values: the &Replace; Method</title>
+
+ <para>
+
+ You can replace existing construction variable values
+ using the &Replace; method:
+
+ </para>
+
+ <scons_example name="Replace1">
+ <file name="SConstruct" printme="1">
+ env = Environment(CCFLAGS = '-DDEFINE1')
+ env.Replace(CCFLAGS = '-DDEFINE2')
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ The replacing value
+ (<literal>-DDEFINE2</literal> in the above example)
+ completely replaces the value in the
+ construction environment:
+
+ </para>
+
+ <scons_output example="Replace1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ You can safely call &Replace;
+ for construction variables that
+ don't exist in the construction environment:
+
+ </para>
+
+ <scons_example name="Replace-nonexistent">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Replace(NEW_VARIABLE = 'xyzzy')
+ print "NEW_VARIABLE =", env['NEW_VARIABLE']
+ </file>
+ </scons_example>
+
+ <para>
+
+ In this case,
+ the construction variable simply
+ gets added to the construction environment:
+
+ </para>
+
+ <scons_output example="Replace-nonexistent">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Because the variables
+ aren't expanded until the construction environment
+ is actually used to build the targets,
+ and because &SCons; function and method calls
+ are order-independent,
+ the last replacement "wins"
+ and is used to build all targets,
+ regardless of the order in which
+ the calls to Replace() are
+ interspersed with calls to
+ builder methods:
+
+ </para>
+
+ <scons_example name="Replace2">
+ <file name="SConstruct" printme="1">
+ env = Environment(CCFLAGS = '-DDEFINE1')
+ print "CCFLAGS =", env['CCFLAGS']
+ env.Program('foo.c')
+
+ env.Replace(CCFLAGS = '-DDEFINE2')
+ print "CCFLAGS =", env['CCFLAGS']
+ env.Program('bar.c')
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ <file name="bar.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ The timing of when the replacement
+ actually occurs relative
+ to when the targets get built
+ becomes apparent
+ if we run &scons; without the <literal>-Q</literal>
+ option:
+
+ </para>
+
+ <scons_output example="Replace2">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Because the replacement occurs while
+ the &SConscript; files are being read,
+ the &cv-link-CCFLAGS;
+ variable has already been set to
+ <literal>-DDEFINE2</literal>
+ by the time the &foo_o; target is built,
+ even though the call to the &Replace;
+ method does not occur until later in
+ the &SConscript; file.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Setting Values Only If They're Not Already Defined: the &SetDefault; Method</title>
+
+ <para>
+
+ Sometimes it's useful to be able to specify
+ that a construction variable should be
+ set to a value only if the construction environment
+ does not already have that variable defined
+ You can do this with the &SetDefault; method,
+ which behaves similarly to the <function>set_default</function>
+ method of Python dictionary objects:
+
+ </para>
+
+ <sconstruct>
+ env.SetDefault(SPECIAL_FLAG = '-extra-option')
+ </sconstruct>
+
+ <para>
+
+ This is especially useful
+ when writing your own <literal>Tool</literal> modules
+ to apply variables to construction environments.
+ <!--
+ See <xref linkend="chap-tool-modules"></xref>
+ for more information about writing
+ Tool modules.
+ -->
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Appending to the End of Values: the &Append; Method</title>
+
+ <para>
+
+ You can append a value to
+ an existing construction variable
+ using the &Append; method:
+
+ </para>
+
+ <scons_example name="ex8">
+ <file name="SConstruct" printme="1">
+ env = Environment(CCFLAGS = ['-DMY_VALUE'])
+ env.Append(CCFLAGS = ['-DLAST'])
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; then supplies both the <literal>-DMY_VALUE</literal> and
+ <literal>-DLAST</literal> flags when compiling the object file:
+
+ </para>
+
+ <scons_output example="ex8">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If the construction variable doesn't already exist,
+ the &Append; method will create it:
+
+ </para>
+
+ <scons_example name="Append-nonexistent">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Append(NEW_VARIABLE = 'added')
+ print "NEW_VARIABLE =", env['NEW_VARIABLE']
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which yields:
+
+ </para>
+
+ <scons_output example="Append-nonexistent">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that the &Append; function tries to be "smart"
+ about how the new value is appended to the old value.
+ If both are strings, the previous and new strings
+ are simply concatenated.
+ Similarly, if both are lists,
+ the lists are concatenated.
+ If, however, one is a string and the other is a list,
+ the string is added as a new element to the list.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Appending Unique Values: the &AppendUnique; Method</title>
+
+ <para>
+
+ Some times it's useful to add a new value
+ only if the existing construction variable
+ doesn't already contain the value.
+ This can be done using the &AppendUnique; method:
+
+ </para>
+
+ <sconstruct>
+ env.AppendUnique(CCFLAGS=['-g'])
+ </sconstruct>
+
+ <para>
+
+ In the above example,
+ the <literal>-g</literal> would be added
+ only if the &cv-CCFLAGS; variable
+ does not already contain a <literal>-g</literal> value.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Appending to the Beginning of Values: the &Prepend; Method</title>
+
+ <para>
+
+ You can append a value to the beginning of
+ an existing construction variable
+ using the &Prepend; method:
+
+ </para>
+
+ <scons_example name="ex9">
+ <file name="SConstruct" printme="1">
+ env = Environment(CCFLAGS = ['-DMY_VALUE'])
+ env.Prepend(CCFLAGS = ['-DFIRST'])
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ int main() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; then supplies both the <literal>-DFIRST</literal> and
+ <literal>-DMY_VALUE</literal> flags when compiling the object file:
+
+ </para>
+
+ <scons_output example="ex9">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If the construction variable doesn't already exist,
+ the &Prepend; method will create it:
+
+ </para>
+
+ <scons_example name="Prepend-nonexistent">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Prepend(NEW_VARIABLE = 'added')
+ print "NEW_VARIABLE =", env['NEW_VARIABLE']
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which yields:
+
+ </para>
+
+ <scons_output example="Prepend-nonexistent">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Like the &Append; function,
+ the &Prepend; function tries to be "smart"
+ about how the new value is appended to the old value.
+ If both are strings, the previous and new strings
+ are simply concatenated.
+ Similarly, if both are lists,
+ the lists are concatenated.
+ If, however, one is a string and the other is a list,
+ the string is added as a new element to the list.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Prepending Unique Values: the &PrependUnique; Method</title>
+
+ <para>
+
+ Some times it's useful to add a new value
+ to the beginning of a construction variable
+ only if the existing value
+ doesn't already contain the to-be-added value.
+ This can be done using the &PrependUnique; method:
+
+ </para>
+
+ <sconstruct>
+ env.PrependUnique(CCFLAGS=['-g'])
+ </sconstruct>
+
+ <para>
+
+ In the above example,
+ the <literal>-g</literal> would be added
+ only if the &cv-CCFLAGS; variable
+ does not already contain a <literal>-g</literal> value.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="sect-execution-environments">
+ <title>Controlling the Execution Environment for Issued Commands</title>
+
+ <para>
+
+ When &SCons; builds a target file,
+ it does not execute the commands with
+ the same external environment
+ that you used to execute &SCons;.
+ Instead, it uses the dictionary
+ stored in the &cv-link-ENV; construction variable
+ as the external environment
+ for executing commands.
+
+ </para>
+
+ <para>
+
+ The most important ramification of this behavior
+ is that the &PATH; environment variable,
+ which controls where the operating system
+ will look for commands and utilities,
+ is not the same as in the external environment
+ from which you called &SCons;.
+ This means that &SCons; will not, by default,
+ necessarily find all of the tools
+ that you can execute from the command line.
+
+ </para>
+
+ <para>
+
+ The default value of the &PATH; environment variable
+ on a POSIX system
+ is <literal>/usr/local/bin:/bin:/usr/bin</literal>.
+ The default value of the &PATH; environment variable
+ on a Windows system comes from the Windows registry
+ value for the command interpreter.
+ If you want to execute any commands--compilers, linkers, etc.--that
+ are not in these default locations,
+ you need to set the &PATH; value
+ in the &cv-ENV; dictionary
+ in your construction environment.
+
+ </para>
+
+ <para>
+
+ The simplest way to do this is to initialize explicitly
+ the value when you create the construction environment;
+ this is one way to do that:
+
+ </para>
+
+ <sconstruct>
+ path = ['/usr/local/bin', '/bin', '/usr/bin']
+ env = Environment(ENV = {'PATH' : path})
+ </sconstruct>
+
+ <para>
+
+ Assign a dictionary to the &cv-ENV;
+ construction variable in this way
+ completely resets the external environment
+ so that the only variable that will be
+ set when external commands are executed
+ will be the &PATH; value.
+ If you want to use the rest of
+ the values in &cv-ENV; and only
+ set the value of &PATH;,
+ the most straightforward way is probably:
+
+ </para>
+
+ <sconstruct>
+ env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin']
+ </sconstruct>
+
+ <para>
+
+ Note that &SCons; does allow you to define
+ the directories in the &PATH; in a string,
+ separated by the pathname-separator character
+ for your system (':' on POSIX systems, ';' on Windows):
+
+ </para>
+
+ <sconstruct>
+ env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin'
+ </sconstruct>
+
+ <para>
+
+ But doing so makes your &SConscript; file less portable,
+ (although in this case that may not be a huge concern
+ since the directories you list are likley system-specific, anyway).
+
+ </para>
+
+ <!--
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Command('foo', [], '__ROOT__/usr/bin/printenv.py')
+ </file>
+ <file name="__ROOT__/usr/bin/printenv.py" chmod="0755">
+ #!/usr/bin/env python
+ import os
+ import sys
+ if len(sys.argv) > 1:
+ keys = sys.argv[1:]
+ else:
+ keys = os.environ.keys()
+ keys.sort()
+ for key in keys:
+ print " " + key + "=" + os.environ[key]
+ </file>
+ </scons_example>
+
+ <para>
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <section>
+ <title>Propagating &PATH; From the External Environment</title>
+
+ <para>
+
+ You may want to propagate the external &PATH;
+ to the execution environment for commands.
+ You do this by initializing the &PATH;
+ variable with the &PATH; value from
+ the <literal>os.environ</literal>
+ dictionary,
+ which is Python's way of letting you
+ get at the external environment:
+
+ </para>
+
+ <sconstruct>
+ import os
+ env = Environment(ENV = {'PATH' : os.environ['PATH']})
+ </sconstruct>
+
+ <para>
+
+ Alternatively, you may find it easier
+ to just propagate the entire external
+ environment to the execution environment
+ for commands.
+ This is simpler to code than explicity
+ selecting the &PATH; value:
+
+ </para>
+
+ <sconstruct>
+ import os
+ env = Environment(ENV = os.environ)
+ </sconstruct>
+
+ <para>
+
+ Either of these will guarantee that
+ &SCons; will be able to execute
+ any command that you can execute from the command line.
+ The drawback is that the build can behave
+ differently if it's run by people with
+ different &PATH; values in their environment--for example,
+ if both the <literal>/bin</literal> and
+ <literal>/usr/local/bin</literal> directories
+ have different &cc; commands,
+ then which one will be used to compile programs
+ will depend on which directory is listed
+ first in the user's &PATH; variable.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Adding to <varname>PATH</varname> Values in the Execution Environment</title>
+
+ <para>
+
+ One of the most common requirements
+ for manipulating a variable in the execution environment
+ is to add one or more custom directories to a search
+ like the <envar>$PATH</envar> variable on Linux or POSIX systems,
+ or the <envar>%PATH%</envar> variable on Windows,
+ so that a locally-installed compiler or other utility
+ can be found when &SCons; tries to execute it to update a target.
+ &SCons; provides &PrependENVPath; and &AppendENVPath; functions
+ to make adding things to execution variables convenient.
+ You call these functions by specifying the variable
+ to which you want the value added,
+ and then value itself.
+ So to add some <filename>/usr/local</filename> directories
+ to the <envar>$PATH</envar> and <envar>$LIB</envar> variables,
+ you might:
+
+ </para>
+
+ <sconstruct>
+ env = Environment(ENV = os.environ)
+ env.PrependENVPath('PATH', '/usr/local/bin')
+ env.AppendENVPath('LIB', '/usr/local/lib')
+ </sconstruct>
+
+ <para>
+
+ Note that the added values are strings,
+ and if you want to add multiple directories to
+ a variable like <envar>$PATH</envar>,
+ you must include the path separate character
+ (<literal>:</literal> on Linux or POSIX,
+ <literal>;</literal> on Windows)
+ in the string.
+
+ </para>
+
+ </section>
+
+ </section>
diff --git a/doc/user/environments.xml b/doc/user/environments.xml
new file mode 100644
index 0000000..b9a60b9
--- /dev/null
+++ b/doc/user/environments.xml
@@ -0,0 +1,1684 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 More on construction environments
+
+As previously mentioned, a B<construction environment> is an object that
+has a set of keyword/value pairs and a set of methods, and which is used
+to tell Cons how target files should be built. This section describes
+how Cons uses and expands construction environment values to control its
+build behavior.
+
+=head2 Construction variable expansion
+
+Construction variables from a construction environment are expanded
+by preceding the keyword with a C<%> (percent sign):
+
+ Construction variables:
+ XYZZY => 'abracadabra',
+
+ The string: "The magic word is: %XYZZY!"
+ expands to: "The magic word is: abracadabra!"
+
+A construction variable name may be surrounded by C<{> and C<}> (curly
+braces), which are stripped as part of the expansion. This can
+sometimes be necessary to separate a variable expansion from trailing
+alphanumeric characters:
+
+ Construction variables:
+ OPT => 'value1',
+ OPTION => 'value2',
+
+ The string: "%OPT %{OPT}ION %OPTION %{OPTION}"
+ expands to: "value1 value1ION value2 value2"
+
+Construction variable expansion is recursive, that is, a string
+containing C<%->expansions after substitution will be re-expanded until
+no further substitutions can be made:
+
+ Construction variables:
+ STRING => 'The result is: %FOO',
+ FOO => '%BAR',
+ BAR => 'final value',
+
+ The string: "The string says: %STRING"
+ expands to: "The string says: The result is: final value"
+
+If a construction variable is not defined in an environment, then the
+null string is substituted:
+
+ Construction variables:
+ FOO => 'value1',
+ BAR => 'value2',
+
+ The string: "%FOO <%NO_VARIABLE> %BAR"
+ expands to: "value1 <> value2"
+
+A doubled C<%%> will be replaced by a single C<%>:
+
+ The string: "Here is a percent sign: %%"
+ expands to: "Here is a percent sign: %"
+
+=head2 Default construction variables
+
+When you specify no arguments when creating a new construction
+environment:
+
+ $env = new cons();
+
+Cons creates a reference to a new, default construction
+environment. This contains a number of construction variables and some
+methods. At the present writing, the default construction variables on a
+UNIX system are:
+
+ CC => 'cc',
+ CFLAGS => '',
+ CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
+ CXX => '%CC',
+ CXXFLAGS => '%CFLAGS',
+ CXXCOM => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>',
+ INCDIRPREFIX => '-I',
+ INCDIRSUFFIX => '',
+ LINK => '%CXX',
+ LINKCOM => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS',
+ LINKMODULECOM => '%LD -r -o %> %<',
+ LIBDIRPREFIX => '-L',
+ LIBDIRSUFFIX => '',
+ AR => 'ar',
+ ARFLAGS => 'r',
+ ARCOM => ['%AR %ARFLAGS %> %<', '%RANLIB %>'],
+ RANLIB => 'ranlib',
+ AS => 'as',
+ ASFLAGS => '',
+ ASCOM => '%AS %ASFLAGS %< -o %>',
+ LD => 'ld',
+ LDFLAGS => '',
+ PREFLIB => 'lib',
+ SUFLIB => '.a',
+ SUFLIBS => '.so:.a',
+ SUFOBJ => '.o',
+ SIGNATURE => [ '*' => 'build' ],
+ ENV => { 'PATH' => '/bin:/usr/bin' },
+
+
+And on a Windows system (Windows NT), the default construction variables
+are (unless the default rule style is set using the B<DefaultRules>
+method):
+
+ CC => 'cl',
+ CFLAGS => '/nologo',
+ CCCOM => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>',
+ CXXCOM => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>',
+ INCDIRPREFIX => '/I',
+ INCDIRSUFFIX => '',
+ LINK => 'link',
+ LINKCOM => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS',
+ LINKMODULECOM => '%LD /r /o %> %<',
+ LIBDIRPREFIX => '/LIBPATH:',
+ LIBDIRSUFFIX => '',
+ AR => 'lib',
+ ARFLAGS => '/nologo ',
+ ARCOM => "%AR %ARFLAGS /out:%> %<",
+ RANLIB => '',
+ LD => 'link',
+ LDFLAGS => '/nologo ',
+ PREFLIB => '',
+ SUFEXE => '.exe',
+ SUFLIB => '.lib',
+ SUFLIBS => '.dll:.lib',
+ SUFOBJ => '.obj',
+ SIGNATURE => [ '*' => 'build' ],
+
+These variables are used by the various methods associated with the
+environment. In particular, any method that ultimately invokes an external
+command will substitute these variables into the final command, as
+appropriate. For example, the C<Objects> method takes a number of source
+files and arranges to derive, if necessary, the corresponding object
+files:
+
+ Objects $env 'foo.c', 'bar.c';
+
+This will arrange to produce, if necessary, F<foo.o> and F<bar.o>. The
+command invoked is simply C<%CCCOM>, which expands, through substitution,
+to the appropriate external command required to build each object. The
+substitution rules will be discussed in detail in the next section.
+
+The construction variables are also used for other purposes. For example,
+C<CPPPATH> is used to specify a colon-separated path of include
+directories. These are intended to be passed to the C preprocessor and are
+also used by the C-file scanning machinery to determine the dependencies
+involved in a C Compilation.
+
+Variables beginning with underscore are created by various methods,
+and should normally be considered ``internal'' variables. For example,
+when a method is called which calls for the creation of an object from
+a C source, the variable C<_IFLAGS> is created: this corresponds to the
+C<-I> switches required by the C compiler to represent the directories
+specified by C<CPPPATH>.
+
+Note that, for any particular environment, the value of a variable is set
+once, and then never reset (to change a variable, you must create a new
+environment. Methods are provided for copying existing environments for this
+purpose). Some internal variables, such as C<_IFLAGS> are created on demand,
+but once set, they remain fixed for the life of the environment.
+
+The C<CFLAGS>, C<LDFLAGS>, and C<ARFLAGS> variables all supply a place
+for passing options to the compiler, loader, and archiver, respectively.
+
+The C<INCDIRPREFIX> and C<INCDIRSUFFIX> variables specify option
+strings to be appended to the beginning and end, respectively, of each
+include directory so that the compiler knows where to find F<.h> files.
+Similarly, the C<LIBDIRPREFIX> and C<LIBDIRSUFFIX> variables specify the
+option string to be appended to the beginning of and end, respectively,
+of each directory that the linker should search for libraries.
+
+Another variable, C<ENV>, is used to determine the system environment during
+the execution of an external command. By default, the only environment
+variable that is set is C<PATH>, which is the execution path for a UNIX
+command. For the utmost reproducibility, you should really arrange to set
+your own execution path, in your top-level F<Construct> file (or perhaps by
+importing an appropriate construction package with the Perl C<use>
+command). The default variables are intended to get you off the ground.
+
+=head2 Expanding variables in construction commands
+
+Within a construction command, construction variables will be expanded
+according to the rules described above. In addition to normal variable
+expansion from the construction environment, construction commands also
+expand the following pseudo-variables to insert the specific input and
+output files in the command line that will be executed:
+
+=over 10
+
+=item %>
+
+The target file name. In a multi-target command, this expands to the
+first target mentioned.)
+
+=item %0
+
+Same as C<%E<gt>>.
+
+=item %1, %2, ..., %9
+
+These refer to the first through ninth input file, respectively.
+
+=item %E<lt>
+
+The full set of input file names. If any of these have been used
+anywhere else in the current command line (via C<%1>, C<%2>, etc.), then
+those will be deleted from the list provided by C<%E<lt>>. Consider the
+following command found in a F<Conscript> file in the F<test> directory:
+
+ Command $env 'tgt', qw(foo bar baz), qq(
+ echo %< -i %1 > %>
+ echo %< -i %2 >> %>
+ echo %< -i %3 >> %>
+ );
+
+If F<tgt> needed to be updated, then this would result in the execution of
+the following commands, assuming that no remapping has been established for
+the F<test> directory:
+
+ echo test/bar test/baz -i test/foo > test/tgt
+ echo test/foo test/baz -i test/bar >> test/tgt
+ echo test/foo test/bar -i test/baz >> test/tgt
+
+=back
+
+Any of the above pseudo-variables may be followed immediately by one of
+the following suffixes to select a portion of the expanded path name:
+
+ :a the absolute path to the file name
+ :b the directory plus the file name stripped of any suffix
+ :d the directory
+ :f the file name
+ :s the file name suffix
+ :F the file name stripped of any suffix
+ :S the absolute path path to a Linked source file
+
+Continuing with the above example, C<%E<lt>:f> would expand to C<foo bar baz>,
+and C<%E<gt>:d> would expand to C<test>.
+
+There are additional C<%> elements which affect the command line(s):
+
+=over 10
+
+=item %[ %]
+
+It is possible to programmatically rewrite part of the command by
+enclosing part of it between C<%[> and C<%]>. This will call the
+construction variable named as the first word enclosed in the brackets
+as a Perl code reference; the results of this call will be used to
+replace the contents of the brackets in the command line. For example,
+given an existing input file named F<tgt.in>:
+
+ @keywords = qw(foo bar baz);
+ $env = new cons(X_COMMA => sub { join(",", @_) });
+ Command $env 'tgt', 'tgt.in', qq(
+ echo '# Keywords: %[X_COMMA @keywords %]' > %>
+ cat %< >> %>
+ );
+
+This will execute:
+
+ echo '# Keywords: foo,bar,baz' > tgt
+ cat tgt.in >> tgt
+
+=item %( %)
+
+Cons includes the text of the command line in the MD5 signature for a
+build, so that targets get rebuilt if you change the command line (to
+add or remove an option, for example). Command-line text in between
+C<%(> and C<%)>, however, will be ignored for MD5 signature calculation.
+
+Internally, Cons uses C<%(> and C<%)> around include and library
+directory options (C<-I> and C<-L> on UNIX systems, C</I> and
+C</LIBPATH> on Windows NT) to avoid rebuilds just because the directory
+list changes. Rebuilds occur only if the changed directory list causes
+any included I<files> to change, and a changed include file is detected
+by the MD5 signature calculation on the actual file contents.
+
+=back
+
+XXX DESCRIBE THE Literal() FUNCTION, TOO XXX
+
+=head2 Expanding construction variables in file names
+
+Cons expands construction variables in the source and target file names
+passed to the various construction methods according to the expansion
+rules described above:
+
+ $env = new cons(
+ DESTDIR => 'programs',
+ SRCDIR => 'src',
+ );
+ Program $env '%DESTDIR/hello', '%SRCDIR/hello.c';
+
+This allows for flexible configuration, through the construction
+environment, of directory names, suffixes, etc.
+
+-->
+
+ <para>
+
+ An <literal>environment</literal>
+ is a collection of values that
+ can affect how a program executes.
+ &SCons; distinguishes between three
+ different types of environments
+ that can affect the behavior of &SCons; itself
+ (subject to the configuration in the &SConscript; files),
+ as well as the compilers and other tools it executes:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>External Environment</term>
+
+ <listitem>
+ <para>
+
+ The <literal>external environment</literal>
+ is the set of variables in the user's environment
+ at the time the user runs &SCons;.
+ These variables are available within the &SConscript; files
+ through the Python <literal>os.environ</literal> dictionary.
+ See <xref linkend="sect-external-environments"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>&ConsEnv;</term>
+
+ <listitem>
+ <para>
+
+ A &consenv;
+ is a distinct object creating within
+ a &SConscript; file and
+ and which contains values that
+ affect how &SCons; decides
+ what action to use to build a target,
+ and even to define which targets
+ should be built from which sources.
+ One of the most powerful features of &SCons;
+ is the ability to create multiple &consenvs;,
+ including the ability to clone a new, customized
+ &consenv; from an existing &consenv;.
+ See <xref linkend="sect-construction-environments"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Execution Environment</term>
+
+ <listitem>
+ <para>
+
+ An <literal>execution environment</literal>
+ is the values that &SCons; sets
+ when executing an external
+ command (such as a compiler or linker)
+ to build one or more targets.
+ Note that this is not the same as
+ the <literal>external environment</literal>
+ (see above).
+ See <xref linkend="sect-execution-environments"></xref>, below.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ Unlike &Make;, &SCons; does not automatically
+ copy or import values between different environments
+ (with the exception of explicit clones of &consenvs;,
+ which inherit values from their parent).
+ This is a deliberate design choice
+ to make sure that builds are,
+ by default, repeatable regardless of
+ the values in the user's external environment.
+ This avoids a whole class of problems with builds
+ where a developer's local build works
+ because a custom variable setting
+ causes a different compiler or build option to be used,
+ but the checked-in change breaks the official build
+ because it uses different environment variable settings.
+
+ </para>
+
+ <para>
+
+ Note that the &SConscript; writer can
+ easily arrange for variables to be
+ copied or imported between environments,
+ and this is often very useful
+ (or even downright necessary)
+ to make it easy for developers
+ to customize the build in appropriate ways.
+ The point is <emphasis>not</emphasis>
+ that copying variables between different environments
+ is evil and must always be avoided.
+ Instead, it should be up to the
+ implementer of the build system
+ to make conscious choices
+ about how and when to import
+ a variable from one environment to another,
+ making informed decisions about
+ striking the right balance
+ between making the build
+ repeatable on the one hand
+ and convenient to use on the other.
+
+ </para>
+
+ <section id="sect-external-environments">
+ <title>Using Values From the External Environment</title>
+
+ <para>
+
+ The <literal>external environment</literal>
+ variable settings that
+ the user has in force
+ when executing &SCons;
+ are available through the normal Python
+ <envar>os.environ</envar>
+ dictionary.
+ This means that you must add an
+ <literal>import os</literal> statement
+ to any &SConscript; file
+ in which you want to use
+ values from the user's external environment.
+
+ </para>
+
+ <programlisting>
+ import os
+ </programlisting>
+
+ <para>
+
+ More usefully, you can use the
+ <envar>os.environ</envar>
+ dictionary in your &SConscript;
+ files to initialize &consenvs;
+ with values from the user's external environment.
+ See the next section,
+ <xref linkend="sect-construction-environments"></xref>,
+ for information on how to do this.
+
+ </para>
+
+ </section>
+
+ <section id="sect-construction-environments">
+ <title>Construction Environments</title>
+
+ <para>
+
+ It is rare that all of the software in a large,
+ complicated system needs to be built the same way.
+ For example, different source files may need different options
+ enabled on the command line,
+ or different executable programs need to be linked
+ with different libraries.
+ &SCons; accommodates these different build
+ requirements by allowing you to create and
+ configure multiple &consenvs;
+ that control how the software is built.
+ A &consenv; is an object
+ that has a number of associated
+ &consvars;, each with a name and a value.
+ (A construction environment also has an attached
+ set of &Builder; methods,
+ about which we'll learn more later.)
+
+ </para>
+
+ <section>
+ <title>Creating a &ConsEnv;: the &Environment; Function</title>
+
+ <para>
+
+ A &consenv; is created by the &Environment; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <para>
+
+ By default, &SCons; initializes every
+ new construction environment
+ with a set of &consvars;
+ based on the tools that it finds on your system,
+ plus the default set of builder methods
+ necessary for using those tools.
+ The construction variables
+ are initialized with values describing
+ the C compiler,
+ the Fortran compiler,
+ the linker,
+ etc.,
+ as well as the command lines to invoke them.
+
+ </para>
+
+ <para>
+
+ When you initialize a construction environment
+ you can set the values of the
+ environment's &consvars;
+ to control how a program is built.
+ For example:
+
+ </para>
+
+ <programlisting>
+ import os
+
+ env = Environment(CC = 'gcc',
+ CCFLAGS = '-O2')
+
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ The construction environment in this example
+ is still initialized with the same default
+ construction variable values,
+ except that the user has explicitly specified use of the
+ GNU C compiler &gcc;,
+ and further specifies that the <literal>-O2</literal>
+ (optimization level two)
+ flag should be used when compiling the object file.
+ In other words, the explicit initializations of
+ &cv-link-CC; and &cv-link-CCFLAGS;
+ override the default values in the newly-created
+ construction environment.
+ So a run from this example would look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ gcc -o foo.o -c -O2 foo.c
+ gcc -o foo foo.o
+ </screen>
+
+ </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>
+
+ <programlisting>
+ env = Environment()
+ print "CC is:", env['CC']
+ </programlisting>
+
+ <para>
+
+ This example &SConstruct; file doesn't build anything,
+ but because it's actually a Python script,
+ it will print the value of &cv-link-CC; for us:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CC is: cc
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ A construction environment, however,
+ is actually an object with associated methods, etc.
+ If you want to have direct access to only the
+ dictionary of construction variables,
+ you can fetch this using the &Dictionary; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment(FOO = 'foo', BAR = 'bar')
+ dict = env.Dictionary()
+ for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
+ print "key = %s, value = %s" % (key, dict[key])
+ </programlisting>
+
+ <para>
+
+ This &SConstruct; file
+ will print the specified dictionary items for us on POSIX
+ systems as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ key = OBJSUFFIX, value = .o
+ key = LIBSUFFIX, value = .a
+ key = PROGSUFFIX, value =
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ And on Windows:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ key = OBJSUFFIX, value = .obj
+ key = LIBSUFFIX, value = .lib
+ key = PROGSUFFIX, value = .exe
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ If you want to loop and print the values of
+ all of the construction variables in a construction environment,
+ the Python code to do that in sorted order might look something like:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ dict = env.Dictionary()
+ keys = dict.keys()
+ keys.sort()
+ for key in keys:
+ print "construction variable = '%s', value = '%s'" % (key, dict[key])
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Expanding Values From a &ConsEnv;: the &subst; Method</title>
+
+ <para>
+
+ Another way to get information from
+ a construction environment.
+ is to use the &subst; method
+ on a string containing <literal>$</literal> expansions
+ of construction variable names.
+ As a simple example,
+ the example from the previous
+ section that used
+ <literal>env['CC']</literal>
+ to fetch the value of &cv-link-CC;
+ could also be written as:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ print "CC is:", env.subst('$CC')
+ </programlisting>
+
+ <para>
+
+ One advantage of using
+ &subst; to expand strings is
+ that construction variables
+ in the result get re-expanded until
+ there are no expansions left in the string.
+ So a simple fetch of a value like
+ &cv-link-CCCOM;:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CCFLAGS = '-DFOO')
+ print "CCCOM is:", env['CCCOM']
+ </programlisting>
+
+ <para>
+
+ Will print the unexpanded value of &cv-CCCOM;,
+ showing us the construction
+ variables that still need to be expanded:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Calling the &subst; method on <varname>$CCOM</varname>,
+ however:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CCFLAGS = '-DFOO')
+ print "CCCOM is:", env.subst('$CCCOM')
+ </programlisting>
+
+ <para>
+
+ Will recursively expand all of
+ the construction variables prefixed
+ with <literal>$</literal> (dollar signs),
+ showing us the final output:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CCCOM is: gcc -DFOO -c -o
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Note that because we're not expanding this
+ in the context of building something
+ there are no target or source files
+ for &cv-link-TARGET; and &cv-link-SOURCES; to expand.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Controlling the Default &ConsEnv;: the &DefaultEnvironment; Function</title>
+
+ <para>
+
+ All of the &Builder; functions that we've introduced so far,
+ like &Program; and &Library;,
+ actually use a default &consenv;
+ that contains settings
+ for the various compilers
+ and other tools that
+ &SCons; configures by default,
+ or otherwise knows about
+ and has discovered on your system.
+ The goal of the default construction environment
+ is to make many configurations to "just work"
+ to build software using
+ readily available tools
+ with a minimum of configuration changes.
+
+ </para>
+
+ <para>
+
+ You can, however, control the settings
+ in the default contstruction environment
+ by using the &DefaultEnvironment; function
+ to initialize various settings:
+
+ </para>
+
+ <programlisting>
+
+ DefaultEnvironment(CC = '/usr/local/bin/gcc')
+
+ </programlisting>
+
+ <para>
+
+ When configured as above,
+ all calls to the &Program;
+ or &Object; Builder
+ will build object files with the
+ <filename>/usr/local/bin/gcc</filename>
+ compiler.
+
+ </para>
+
+ <para>
+
+ Note that the &DefaultEnvironment; function
+ returns the initialized
+ default construction environment object,
+ which can then be manipulated like any
+ other construction environment.
+ So the following
+ would be equivalent to the
+ previous example,
+ setting the &cv-CC;
+ variable to <filename>/usr/local/bin/gcc</filename>
+ but as a separate step after
+ the default construction environment has been initialized:
+
+ </para>
+
+ <programlisting>
+
+ env = DefaultEnvironment()
+ env['CC'] = '/usr/local/bin/gcc'
+
+ </programlisting>
+
+ <para>
+
+ One very common use of the &DefaultEnvironment; function
+ is to speed up &SCons; initialization.
+ As part of trying to make most default
+ configurations "just work,"
+ &SCons; will actually
+ search the local system for installed
+ compilers and other utilities.
+ This search can take time,
+ especially on systems with
+ slow or networked file systems.
+ If you know which compiler(s) and/or
+ other utilities you want to configure,
+ you can control the search
+ that &SCons; performs
+ by specifying some specific
+ tool modules with which to
+ initialize the default construction environment:
+
+ </para>
+
+ <programlisting>
+
+ env = DefaultEnvironment(tools = ['gcc', 'gnulink'],
+ CC = '/usr/local/bin/gcc')
+
+ </programlisting>
+
+ <para>
+
+ So the above example would tell &SCons;
+ to explicitly configure the default environment
+ to use its normal GNU Compiler and GNU Linker settings
+ (without having to search for them,
+ or any other utilities for that matter),
+ and specifically to use the compiler found at
+ <filename>/usr/local/bin/gcc</filename>.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Multiple &ConsEnvs;</title>
+
+ <para>
+
+ The real advantage of construction environments
+ is that you can create as many different construction
+ environments as you need,
+ each tailored to a different way to build
+ some piece of software or other file.
+ If, for example, we need to build
+ one program with the <literal>-O2</literal> flag
+ and another with the <literal>-g</literal> (debug) flag,
+ we would do this like so:
+
+ </para>
+
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
+
+ opt.Program('foo', 'foo.c')
+
+ dbg.Program('bar', 'bar.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o bar.o -c -g bar.c
+ cc -o bar bar.o
+ cc -o foo.o -c -O2 foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <para>
+
+ We can even use multiple construction environments to build
+ multiple versions of a single program.
+ If you do this by simply trying to use the
+ &b-link-Program; builder with both environments, though,
+ like this:
+
+ </para>
+
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
+
+ opt.Program('foo', 'foo.c')
+
+ dbg.Program('foo', 'foo.c')
+ </programlisting>
+
+ <para>
+
+ Then &SCons; generates the following error:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+
+ scons: warning: Two different environments were specified for target foo.o,
+ but they appear to have the same action: CCCom(target, source, env)
+ File "/home/my/project/SConstruct", line 6, in ?
+
+ scons: warning: Two different environments were specified for target foo,
+ but they appear to have the same action: Cat(target, source, env)
+ File "/home/my/project/SConstruct", line 6, in ?
+ cc -o foo.o -c -g foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <para>
+
+ This is because the two &b-Program; calls have
+ each implicitly told &SCons; to generate an object file named
+ <filename>foo.o</filename>,
+ one with a &cv-link-CCFLAGS; value of
+ <literal>-O2</literal>
+ and one with a &cv-link-CCFLAGS; value of
+ <literal>-g</literal>.
+ &SCons; can't just decide that one of them
+ should take precedence over the other,
+ so it generates the error.
+ To avoid this problem,
+ we must explicitly specify
+ that each environment compile
+ <filename>foo.c</filename>
+ to a separately-named object file
+ using the &b-link-Object; builder, like so:
+
+ </para>
+
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
+
+ o = opt.Object('foo-opt', 'foo.c')
+ opt.Program(o)
+
+ d = dbg.Object('foo-dbg', 'foo.c')
+ dbg.Program(d)
+ </programlisting>
+
+ <para>
+
+ Notice that each call to the &b-Object; builder
+ returns a value,
+ an internal &SCons; object that
+ represents the object file that will be built.
+ We then use that object
+ as input to the &b-Program; builder.
+ This avoids having to specify explicitly
+ the object file name in multiple places,
+ and makes for a compact, readable
+ &SConstruct; file.
+ Our &SCons; output then looks like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o foo-dbg.o -c -g foo.c
+ cc -o foo-dbg foo-dbg.o
+ cc -o foo-opt.o -c -O2 foo.c
+ cc -o foo-opt foo-opt.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Making Copies of &ConsEnvs;: the &Clone; Method</title>
+
+ <para>
+
+ Sometimes you want more than one construction environment
+ to share the same values for one or more variables.
+ Rather than always having to repeat all of the common
+ variables when you create each construction environment,
+ you can use the &Clone; method
+ to create a copy of a construction environment.
+
+ </para>
+
+ <para>
+
+ Like the &Environment; call that creates a construction environment,
+ the &Clone; method takes &consvar; assignments,
+ which will override the values in the copied construction environment.
+ For example, suppose we want to use &gcc;
+ to create three versions of a program,
+ one optimized, one debug, and one with neither.
+ We could do this by creating a "base" construction environment
+ that sets &cv-link-CC; to &gcc;,
+ and then creating two copies,
+ one which sets &cv-link-CCFLAGS; for optimization
+ and the other which sets &cv-CCFLAGS; for debugging:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CC = 'gcc')
+ opt = env.Clone(CCFLAGS = '-O2')
+ dbg = env.Clone(CCFLAGS = '-g')
+
+ env.Program('foo', 'foo.c')
+
+ o = opt.Object('foo-opt', 'foo.c')
+ opt.Program(o)
+
+ d = dbg.Object('foo-dbg', 'foo.c')
+ dbg.Program(d)
+ </programlisting>
+
+ <para>
+
+ Then our output would look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ gcc -o foo.o -c foo.c
+ gcc -o foo foo.o
+ gcc -o foo-dbg.o -c -g foo.c
+ gcc -o foo-dbg foo-dbg.o
+ gcc -o foo-opt.o -c -O2 foo.c
+ gcc -o foo-opt foo-opt.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Replacing Values: the &Replace; Method</title>
+
+ <para>
+
+ You can replace existing construction variable values
+ using the &Replace; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CCFLAGS = '-DDEFINE1')
+ env.Replace(CCFLAGS = '-DDEFINE2')
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ The replacing value
+ (<literal>-DDEFINE2</literal> in the above example)
+ completely replaces the value in the
+ construction environment:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o foo.o -c -DDEFINE2 foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <para>
+
+ You can safely call &Replace;
+ for construction variables that
+ don't exist in the construction environment:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Replace(NEW_VARIABLE = 'xyzzy')
+ print "NEW_VARIABLE =", env['NEW_VARIABLE']
+ </programlisting>
+
+ <para>
+
+ In this case,
+ the construction variable simply
+ gets added to the construction environment:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ NEW_VARIABLE = xyzzy
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Because the variables
+ aren't expanded until the construction environment
+ is actually used to build the targets,
+ and because &SCons; function and method calls
+ are order-independent,
+ the last replacement "wins"
+ and is used to build all targets,
+ regardless of the order in which
+ the calls to Replace() are
+ interspersed with calls to
+ builder methods:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CCFLAGS = '-DDEFINE1')
+ print "CCFLAGS =", env['CCFLAGS']
+ env.Program('foo.c')
+
+ env.Replace(CCFLAGS = '-DDEFINE2')
+ print "CCFLAGS =", env['CCFLAGS']
+ env.Program('bar.c')
+ </programlisting>
+
+ <para>
+
+ The timing of when the replacement
+ actually occurs relative
+ to when the targets get built
+ becomes apparent
+ if we run &scons; without the <literal>-Q</literal>
+ option:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ CCFLAGS = -DDEFINE1
+ CCFLAGS = -DDEFINE2
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -o bar.o -c -DDEFINE2 bar.c
+ cc -o bar bar.o
+ cc -o foo.o -c -DDEFINE2 foo.c
+ cc -o foo foo.o
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ Because the replacement occurs while
+ the &SConscript; files are being read,
+ the &cv-link-CCFLAGS;
+ variable has already been set to
+ <literal>-DDEFINE2</literal>
+ by the time the &foo_o; target is built,
+ even though the call to the &Replace;
+ method does not occur until later in
+ the &SConscript; file.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Setting Values Only If They're Not Already Defined: the &SetDefault; Method</title>
+
+ <para>
+
+ Sometimes it's useful to be able to specify
+ that a construction variable should be
+ set to a value only if the construction environment
+ does not already have that variable defined
+ You can do this with the &SetDefault; method,
+ which behaves similarly to the <function>set_default</function>
+ method of Python dictionary objects:
+
+ </para>
+
+ <programlisting>
+ env.SetDefault(SPECIAL_FLAG = '-extra-option')
+ </programlisting>
+
+ <para>
+
+ This is especially useful
+ when writing your own <literal>Tool</literal> modules
+ to apply variables to construction environments.
+ <!--
+ See <xref linkend="chap-tool-modules"></xref>
+ for more information about writing
+ Tool modules.
+ -->
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Appending to the End of Values: the &Append; Method</title>
+
+ <para>
+
+ You can append a value to
+ an existing construction variable
+ using the &Append; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CCFLAGS = ['-DMY_VALUE'])
+ env.Append(CCFLAGS = ['-DLAST'])
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ &SCons; then supplies both the <literal>-DMY_VALUE</literal> and
+ <literal>-DLAST</literal> flags when compiling the object file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o foo.o -c -DMY_VALUE -DLAST foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <para>
+
+ If the construction variable doesn't already exist,
+ the &Append; method will create it:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Append(NEW_VARIABLE = 'added')
+ print "NEW_VARIABLE =", env['NEW_VARIABLE']
+ </programlisting>
+
+ <para>
+
+ Which yields:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ NEW_VARIABLE = added
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Note that the &Append; function tries to be "smart"
+ about how the new value is appended to the old value.
+ If both are strings, the previous and new strings
+ are simply concatenated.
+ Similarly, if both are lists,
+ the lists are concatenated.
+ If, however, one is a string and the other is a list,
+ the string is added as a new element to the list.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Appending Unique Values: the &AppendUnique; Method</title>
+
+ <para>
+
+ Some times it's useful to add a new value
+ only if the existing construction variable
+ doesn't already contain the value.
+ This can be done using the &AppendUnique; method:
+
+ </para>
+
+ <programlisting>
+ env.AppendUnique(CCFLAGS=['-g'])
+ </programlisting>
+
+ <para>
+
+ In the above example,
+ the <literal>-g</literal> would be added
+ only if the &cv-CCFLAGS; variable
+ does not already contain a <literal>-g</literal> value.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Appending to the Beginning of Values: the &Prepend; Method</title>
+
+ <para>
+
+ You can append a value to the beginning of
+ an existing construction variable
+ using the &Prepend; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CCFLAGS = ['-DMY_VALUE'])
+ env.Prepend(CCFLAGS = ['-DFIRST'])
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ &SCons; then supplies both the <literal>-DFIRST</literal> and
+ <literal>-DMY_VALUE</literal> flags when compiling the object file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o foo.o -c -DFIRST -DMY_VALUE foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <para>
+
+ If the construction variable doesn't already exist,
+ the &Prepend; method will create it:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Prepend(NEW_VARIABLE = 'added')
+ print "NEW_VARIABLE =", env['NEW_VARIABLE']
+ </programlisting>
+
+ <para>
+
+ Which yields:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ NEW_VARIABLE = added
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Like the &Append; function,
+ the &Prepend; function tries to be "smart"
+ about how the new value is appended to the old value.
+ If both are strings, the previous and new strings
+ are simply concatenated.
+ Similarly, if both are lists,
+ the lists are concatenated.
+ If, however, one is a string and the other is a list,
+ the string is added as a new element to the list.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Prepending Unique Values: the &PrependUnique; Method</title>
+
+ <para>
+
+ Some times it's useful to add a new value
+ to the beginning of a construction variable
+ only if the existing value
+ doesn't already contain the to-be-added value.
+ This can be done using the &PrependUnique; method:
+
+ </para>
+
+ <programlisting>
+ env.PrependUnique(CCFLAGS=['-g'])
+ </programlisting>
+
+ <para>
+
+ In the above example,
+ the <literal>-g</literal> would be added
+ only if the &cv-CCFLAGS; variable
+ does not already contain a <literal>-g</literal> value.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="sect-execution-environments">
+ <title>Controlling the Execution Environment for Issued Commands</title>
+
+ <para>
+
+ When &SCons; builds a target file,
+ it does not execute the commands with
+ the same external environment
+ that you used to execute &SCons;.
+ Instead, it uses the dictionary
+ stored in the &cv-link-ENV; construction variable
+ as the external environment
+ for executing commands.
+
+ </para>
+
+ <para>
+
+ The most important ramification of this behavior
+ is that the &PATH; environment variable,
+ which controls where the operating system
+ will look for commands and utilities,
+ is not the same as in the external environment
+ from which you called &SCons;.
+ This means that &SCons; will not, by default,
+ necessarily find all of the tools
+ that you can execute from the command line.
+
+ </para>
+
+ <para>
+
+ The default value of the &PATH; environment variable
+ on a POSIX system
+ is <literal>/usr/local/bin:/bin:/usr/bin</literal>.
+ The default value of the &PATH; environment variable
+ on a Windows system comes from the Windows registry
+ value for the command interpreter.
+ If you want to execute any commands--compilers, linkers, etc.--that
+ are not in these default locations,
+ you need to set the &PATH; value
+ in the &cv-ENV; dictionary
+ in your construction environment.
+
+ </para>
+
+ <para>
+
+ The simplest way to do this is to initialize explicitly
+ the value when you create the construction environment;
+ this is one way to do that:
+
+ </para>
+
+ <programlisting>
+ path = ['/usr/local/bin', '/bin', '/usr/bin']
+ env = Environment(ENV = {'PATH' : path})
+ </programlisting>
+
+ <para>
+
+ Assign a dictionary to the &cv-ENV;
+ construction variable in this way
+ completely resets the external environment
+ so that the only variable that will be
+ set when external commands are executed
+ will be the &PATH; value.
+ If you want to use the rest of
+ the values in &cv-ENV; and only
+ set the value of &PATH;,
+ the most straightforward way is probably:
+
+ </para>
+
+ <programlisting>
+ env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin']
+ </programlisting>
+
+ <para>
+
+ Note that &SCons; does allow you to define
+ the directories in the &PATH; in a string,
+ separated by the pathname-separator character
+ for your system (':' on POSIX systems, ';' on Windows):
+
+ </para>
+
+ <programlisting>
+ env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin'
+ </programlisting>
+
+ <para>
+
+ But doing so makes your &SConscript; file less portable,
+ (although in this case that may not be a huge concern
+ since the directories you list are likley system-specific, anyway).
+
+ </para>
+
+ <!--
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Command('foo', [], '__ROOT__/usr/bin/printenv.py')
+ </file>
+ <file name="__ROOT__/usr/bin/printenv.py" chmod="0755">
+ #!/usr/bin/env python
+ import os
+ import sys
+ if len(sys.argv) > 1:
+ keys = sys.argv[1:]
+ else:
+ keys = os.environ.keys()
+ keys.sort()
+ for key in keys:
+ print " " + key + "=" + os.environ[key]
+ </file>
+ </scons_example>
+
+ <para>
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <section>
+ <title>Propagating &PATH; From the External Environment</title>
+
+ <para>
+
+ You may want to propagate the external &PATH;
+ to the execution environment for commands.
+ You do this by initializing the &PATH;
+ variable with the &PATH; value from
+ the <literal>os.environ</literal>
+ dictionary,
+ which is Python's way of letting you
+ get at the external environment:
+
+ </para>
+
+ <programlisting>
+ import os
+ env = Environment(ENV = {'PATH' : os.environ['PATH']})
+ </programlisting>
+
+ <para>
+
+ Alternatively, you may find it easier
+ to just propagate the entire external
+ environment to the execution environment
+ for commands.
+ This is simpler to code than explicity
+ selecting the &PATH; value:
+
+ </para>
+
+ <programlisting>
+ import os
+ env = Environment(ENV = os.environ)
+ </programlisting>
+
+ <para>
+
+ Either of these will guarantee that
+ &SCons; will be able to execute
+ any command that you can execute from the command line.
+ The drawback is that the build can behave
+ differently if it's run by people with
+ different &PATH; values in their environment--for example,
+ if both the <literal>/bin</literal> and
+ <literal>/usr/local/bin</literal> directories
+ have different &cc; commands,
+ then which one will be used to compile programs
+ will depend on which directory is listed
+ first in the user's &PATH; variable.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Adding to <varname>PATH</varname> Values in the Execution Environment</title>
+
+ <para>
+
+ One of the most common requirements
+ for manipulating a variable in the execution environment
+ is to add one or more custom directories to a search
+ like the <envar>$PATH</envar> variable on Linux or POSIX systems,
+ or the <envar>%PATH%</envar> variable on Windows,
+ so that a locally-installed compiler or other utility
+ can be found when &SCons; tries to execute it to update a target.
+ &SCons; provides &PrependENVPath; and &AppendENVPath; functions
+ to make adding things to execution variables convenient.
+ You call these functions by specifying the variable
+ to which you want the value added,
+ and then value itself.
+ So to add some <filename>/usr/local</filename> directories
+ to the <envar>$PATH</envar> and <envar>$LIB</envar> variables,
+ you might:
+
+ </para>
+
+ <programlisting>
+ env = Environment(ENV = os.environ)
+ env.PrependENVPath('PATH', '/usr/local/bin')
+ env.AppendENVPath('LIB', '/usr/local/lib')
+ </programlisting>
+
+ <para>
+
+ Note that the added values are strings,
+ and if you want to add multiple directories to
+ a variable like <envar>$PATH</envar>,
+ you must include the path separate character
+ (<literal>:</literal> on Linux or POSIX,
+ <literal>;</literal> on Windows)
+ in the string.
+
+ </para>
+
+ </section>
+
+ </section>
diff --git a/doc/user/errors.in b/doc/user/errors.in
new file mode 100644
index 0000000..0051953
--- /dev/null
+++ b/doc/user/errors.in
@@ -0,0 +1,41 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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/errors.xml b/doc/user/errors.xml
new file mode 100644
index 0000000..0051953
--- /dev/null
+++ b/doc/user/errors.xml
@@ -0,0 +1,41 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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
index 0000000..0051953
--- /dev/null
+++ b/doc/user/example.in
@@ -0,0 +1,41 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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.xml b/doc/user/example.xml
new file mode 100644
index 0000000..0051953
--- /dev/null
+++ b/doc/user/example.xml
@@ -0,0 +1,41 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <section>
+ <title>XXX</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
diff --git a/doc/user/factories.in b/doc/user/factories.in
new file mode 100644
index 0000000..0cea6c4
--- /dev/null
+++ b/doc/user/factories.in
@@ -0,0 +1,507 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; provides a number of platform-independent functions,
+ called <literal>factories</literal>,
+ that perform common file system manipulations
+ like copying, moving or deleting files and directories,
+ or making directories.
+ These functions are <literal>factories</literal>
+ because they don't perform the action
+ at the time they're called,
+ they each return an &Action; object
+ that can be executed at the appropriate time.
+
+ </para>
+
+ <section>
+ <title>Copying Files or Directories: The &Copy; Factory</title>
+
+ <para>
+
+ Suppose you want to arrange to make a copy of a file,
+ and don't have a suitable pre-existing builder.
+ <footnote>
+ <para>
+ Unfortunately, in the early days of SCons design,
+ we used the name &Copy; for the function that
+ returns a copy of the environment,
+ otherwise that would be the logical choice for
+ a Builder that copies a file or directory tree
+ to a target location.
+ </para>
+ </footnote>
+ One way would be to use the &Copy; action factory
+ in conjunction with the &Command; builder:
+
+ </para>
+
+ <scons_example name="Copy1">
+ <file name="SConstruct" printme="1">
+ Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
+ </file>
+ <file name="file.in">file.in</file>
+ </scons_example>
+
+ <para>
+
+ Notice that the action returned by the &Copy; factory
+ will expand the &cv-link-TARGET; and &cv-link-SOURCE; strings
+ at the time &file_out; is built,
+ and that the order of the arguments
+ is the same as that of a builder itself--that is,
+ target first, followed by source:
+
+ </para>
+
+ <scons_output example="Copy1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ You can, of course, name a file explicitly
+ instead of using &cv-TARGET; or &cv-SOURCE;:
+
+ </para>
+
+ <scons_example name="Copy2">
+ <file name="SConstruct" printme="1">
+ Command("file.out", [], Copy("$TARGET", "file.in"))
+ </file>
+ <file name="file.in">file.in</file>
+ </scons_example>
+
+ <para>
+
+ Which executes as:
+
+ </para>
+
+ <scons_output example="Copy2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The usefulness of the &Copy; factory
+ becomes more apparent when
+ you use it in a list of actions
+ passed to the &Command; builder.
+ For example, suppose you needed to run a
+ file through a utility that only modifies files in-place,
+ and can't "pipe" input to output.
+ One solution is to copy the source file
+ to a temporary file name,
+ run the utility,
+ and then copy the modified temporary file to the target,
+ which the &Copy; factory makes extremely easy:
+
+ </para>
+
+ <scons_example name="Copy3">
+ <file name="S" printme="1">
+ Command("file.out", "file.in",
+ [
+ Copy("tempfile", "$SOURCE"),
+ "modify tempfile",
+ Copy("$TARGET", "tempfile"),
+ ])
+ </file>
+ <file name="SConstruct">
+ env = DefaultEnvironment()
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ SConscript('S')
+ </file>
+ <file name="file.in">file.in</file>
+ <file name="modify" chmod="0755">
+ touch $*
+ </file>
+ </scons_example>
+
+ <para>
+
+ The output then looks like:
+
+ </para>
+
+ <scons_output example="Copy3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Deleting Files or Directories: The &Delete; Factory</title>
+
+ <para>
+
+ If you need to delete a file,
+ then the &Delete; factory
+ can be used in much the same way as
+ the &Copy; factory.
+ For example, if we want to make sure that
+ the temporary file
+ in our last example doesn't exist before
+ we copy to it,
+ we could add &Delete; to the beginning
+ of the command list:
+
+ </para>
+
+ <scons_example name="Delete1">
+ <file name="S" printme="1">
+ Command("file.out", "file.in",
+ [
+ Delete("tempfile"),
+ Copy("tempfile", "$SOURCE"),
+ "modify tempfile",
+ Copy("$TARGET", "tempfile"),
+ ])
+ </file>
+ <file name="SConstruct">
+ env = DefaultEnvironment()
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ SConscript('S')
+ </file>
+ <file name="file.in">file.in</file>
+ <file name="modify" chmod="0755">
+ touch $*
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which then executes as follows:
+
+ </para>
+
+ <scons_output example="Delete1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Of course, like all of these &Action; factories,
+ the &Delete factory also expands
+ &cv-link-TARGET; and &cv-link-SOURCE; variables appropriately.
+ For example:
+
+ </para>
+
+ <scons_example name="Delete2">
+ <file name="SConstruct" printme="1">
+ Command("file.out", "file.in",
+ [
+ Delete("$TARGET"),
+ Copy("$TARGET", "$SOURCE")
+ ])
+ </file>
+ <file name="file.in">file.in</file>
+ </scons_example>
+
+ <para>
+
+ Executes as:
+
+ </para>
+
+ <scons_output example="Delete2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note, however, that you typically don't need to
+ call the &Delete; factory explicitly in this way;
+ by default, &SCons; deletes its target(s)
+ for you before executing any action.
+
+ </para>
+
+ <para>
+
+ One word of caution about using the &Delete; factory:
+ it has the same variable expansions available
+ as any other factory, including the &cv-SOURCE; variable.
+ Specifying <literal>Delete("$SOURCE")</literal>
+ is not something you usually want to do!
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Moving (Renaming) Files or Directories: The &Move; Factory</title>
+
+ <para>
+
+ The &Move; factory
+ allows you to rename a file or directory.
+ For example, if we don't want to copy the temporary file,
+ we could use:
+
+ </para>
+
+ <scons_example name="Move">
+ <file name="S" printme="1">
+ Command("file.out", "file.in",
+ [
+ Copy("tempfile", "$SOURCE"),
+ "modify tempfile",
+ Move("$TARGET", "tempfile"),
+ ])
+ </file>
+ <file name="SConstruct">
+ env = DefaultEnvironment()
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ SConscript('S')
+ </file>
+ <file name="file.in">file.in</file>
+ <file name="modify" chmod="0755">
+ touch $*
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which would execute as:
+
+ </para>
+
+ <scons_output example="Move">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Updating the Modification Time of a File: The &Touch; Factory</title>
+
+ <para>
+
+ If you just need to update the
+ recorded modification time for a file,
+ use the &Touch; factory:
+
+ </para>
+
+ <scons_example name="Touch">
+ <file name="S" printme="1">
+ Command("file.out", "file.in",
+ [
+ Copy("$TARGET", "$SOURCE"),
+ Touch("$TARGET"),
+ ])
+ </file>
+ <file name="SConstruct">
+ env = DefaultEnvironment()
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ SConscript('S')
+ </file>
+ <file name="file.in">file.in</file>
+ </scons_example>
+
+ <para>
+
+ Which executes as:
+
+ </para>
+
+ <scons_output example="Touch">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Creating a Directory: The &Mkdir; Factory</title>
+
+ <para>
+
+ If you need to create a directory,
+ use the &Mkdir; factory.
+ For example, if we need to process
+ a file in a temporary directory
+ in which the processing tool
+ will create other files that we don't care about,
+ you could use:
+
+ </para>
+
+ <scons_example name="Mkdir">
+ <file name="S" printme="1">
+ Command("file.out", "file.in",
+ [
+ Delete("tempdir"),
+ Mkdir("tempdir"),
+ Copy("tempdir/${SOURCE.file}", "$SOURCE"),
+ "process tempdir",
+ Move("$TARGET", "tempdir/output_file"),
+ Delete("tempdir"),
+ ])
+ </file>
+ <file name="SConstruct">
+ env = DefaultEnvironment()
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ SConscript('S')
+ </file>
+ <file name="file.in">file.in</file>
+ <file name="process" chmod="0755">
+ touch $*
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which executes as:
+
+ </para>
+
+ <scons_output example="Mkdir">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Changing File or Directory Permissions: The &Chmod; Factory</title>
+
+ <para>
+
+ To change permissions on a file or directory,
+ use the &Chmod; factory.
+ The permission argument uses POSIX-style
+ permission bits and should typically
+ be expressed as an octal,
+ not decimal, number:
+
+ </para>
+
+ <scons_example name="Chmod">
+ <file name="SConstruct" printme="1">
+ Command("file.out", "file.in",
+ [
+ Copy("$TARGET", "$SOURCE"),
+ Chmod("$TARGET", 0755),
+ ])
+ </file>
+ <file name="file.in">file.in</file>
+ </scons_example>
+
+ <para>
+
+ Which executes:
+
+ </para>
+
+ <scons_output example="Chmod">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Executing an action immediately: the &Execute; Function</title>
+
+ <para>
+
+ We've been showing you how to use &Action; factories
+ in the &Command; function.
+ You can also execute an &Action; returned by a factory
+ (or actually, any &Action;)
+ at the time the &SConscript; file is read
+ by using the &Execute; function.
+ For example, if we need to make sure that
+ a directory exists before we build any targets,
+
+ </para>
+
+ <scons_example name="Execute">
+ <file name="SConstruct" printme="1">
+ Execute(Mkdir('__ROOT__/tmp/my_temp_directory'))
+ </file>
+ </scons_example>
+
+ <para>
+
+ Notice that this will
+ create the directory while
+ the &SConscript; file is being read:
+
+ </para>
+
+ <scons_output example="Execute">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If you're familiar with Python,
+ you may wonder why you would want to use this
+ instead of just calling the native Python
+ <function>os.mkdir()</function> function.
+ The advantage here is that the &Mkdir;
+ action will behave appropriately if the user
+ specifies the &SCons; <option>-n</option> or
+ <option>-q</option> options--that is,
+ it will print the action but not actually
+ make the directory when <option>-n</option> is specified,
+ or make the directory but not print the action
+ when <option>-q</option> is specified.
+
+ </para>
+
+ <para>
+
+ The &Execute; function returns the exit status
+ or return value of the underlying action being executed.
+ It will also print an error message if the action
+ fails and returns a non-zero value.
+ &SCons; will <emphasis>not</emphasis>, however,
+ actually stop the build if the action fails.
+ If you want the build to stop
+ in response to a failure in an action called by &Execute;,
+ you must do so by explicitly
+ checking the return value
+ and calling the &Exit; function
+ (or a Python equivalent):
+
+ </para>
+
+ <sconstruct>
+ if Execute(Mkdir('__ROOT__/tmp/my_temp_directory')):
+ # A problem occurred while making the temp directory.
+ Exit(1)
+ </sconstruct>
+
+ </section>
diff --git a/doc/user/factories.xml b/doc/user/factories.xml
new file mode 100644
index 0000000..17e52bd
--- /dev/null
+++ b/doc/user/factories.xml
@@ -0,0 +1,466 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; provides a number of platform-independent functions,
+ called <literal>factories</literal>,
+ that perform common file system manipulations
+ like copying, moving or deleting files and directories,
+ or making directories.
+ These functions are <literal>factories</literal>
+ because they don't perform the action
+ at the time they're called,
+ they each return an &Action; object
+ that can be executed at the appropriate time.
+
+ </para>
+
+ <section>
+ <title>Copying Files or Directories: The &Copy; Factory</title>
+
+ <para>
+
+ Suppose you want to arrange to make a copy of a file,
+ and don't have a suitable pre-existing builder.
+ <footnote>
+ <para>
+ Unfortunately, in the early days of SCons design,
+ we used the name &Copy; for the function that
+ returns a copy of the environment,
+ otherwise that would be the logical choice for
+ a Builder that copies a file or directory tree
+ to a target location.
+ </para>
+ </footnote>
+ One way would be to use the &Copy; action factory
+ in conjunction with the &Command; builder:
+
+ </para>
+
+ <programlisting>
+ Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
+ </programlisting>
+
+ <para>
+
+ Notice that the action returned by the &Copy; factory
+ will expand the &cv-link-TARGET; and &cv-link-SOURCE; strings
+ at the time &file_out; is built,
+ and that the order of the arguments
+ is the same as that of a builder itself--that is,
+ target first, followed by source:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Copy("file.out", "file.in")
+ </screen>
+
+ <para>
+
+ You can, of course, name a file explicitly
+ instead of using &cv-TARGET; or &cv-SOURCE;:
+
+ </para>
+
+ <programlisting>
+ Command("file.out", [], Copy("$TARGET", "file.in"))
+ </programlisting>
+
+ <para>
+
+ Which executes as:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Copy("file.out", "file.in")
+ </screen>
+
+ <para>
+
+ The usefulness of the &Copy; factory
+ becomes more apparent when
+ you use it in a list of actions
+ passed to the &Command; builder.
+ For example, suppose you needed to run a
+ file through a utility that only modifies files in-place,
+ and can't "pipe" input to output.
+ One solution is to copy the source file
+ to a temporary file name,
+ run the utility,
+ and then copy the modified temporary file to the target,
+ which the &Copy; factory makes extremely easy:
+
+ </para>
+
+ <programlisting>
+ Command("file.out", "file.in",
+ [
+ Copy("tempfile", "$SOURCE"),
+ "modify tempfile",
+ Copy("$TARGET", "tempfile"),
+ ])
+ </programlisting>
+
+ <para>
+
+ The output then looks like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Copy("tempfile", "file.in")
+ modify tempfile
+ Copy("file.out", "tempfile")
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Deleting Files or Directories: The &Delete; Factory</title>
+
+ <para>
+
+ If you need to delete a file,
+ then the &Delete; factory
+ can be used in much the same way as
+ the &Copy; factory.
+ For example, if we want to make sure that
+ the temporary file
+ in our last example doesn't exist before
+ we copy to it,
+ we could add &Delete; to the beginning
+ of the command list:
+
+ </para>
+
+ <programlisting>
+ Command("file.out", "file.in",
+ [
+ Delete("tempfile"),
+ Copy("tempfile", "$SOURCE"),
+ "modify tempfile",
+ Copy("$TARGET", "tempfile"),
+ ])
+ </programlisting>
+
+ <para>
+
+ Which then executes as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Delete("tempfile")
+ Copy("tempfile", "file.in")
+ modify tempfile
+ Copy("file.out", "tempfile")
+ </screen>
+
+ <para>
+
+ Of course, like all of these &Action; factories,
+ the &Delete; factory also expands
+ &cv-link-TARGET; and &cv-link-SOURCE; variables appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ Command("file.out", "file.in",
+ [
+ Delete("$TARGET"),
+ Copy("$TARGET", "$SOURCE")
+ ])
+ </programlisting>
+
+ <para>
+
+ Executes as:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Delete("file.out")
+ Copy("file.out", "file.in")
+ </screen>
+
+ <para>
+
+ Note, however, that you typically don't need to
+ call the &Delete; factory explicitly in this way;
+ by default, &SCons; deletes its target(s)
+ for you before executing any action.
+
+ </para>
+
+ <para>
+
+ One word of caution about using the &Delete; factory:
+ it has the same variable expansions available
+ as any other factory, including the &cv-SOURCE; variable.
+ Specifying <literal>Delete("$SOURCE")</literal>
+ is not something you usually want to do!
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Moving (Renaming) Files or Directories: The &Move; Factory</title>
+
+ <para>
+
+ The &Move; factory
+ allows you to rename a file or directory.
+ For example, if we don't want to copy the temporary file,
+ we could use:
+
+ </para>
+
+ <programlisting>
+ Command("file.out", "file.in",
+ [
+ Copy("tempfile", "$SOURCE"),
+ "modify tempfile",
+ Move("$TARGET", "tempfile"),
+ ])
+ </programlisting>
+
+ <para>
+
+ Which would execute as:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Copy("tempfile", "file.in")
+ modify tempfile
+ Move("file.out", "tempfile")
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Updating the Modification Time of a File: The &Touch; Factory</title>
+
+ <para>
+
+ If you just need to update the
+ recorded modification time for a file,
+ use the &Touch; factory:
+
+ </para>
+
+ <programlisting>
+ Command("file.out", "file.in",
+ [
+ Copy("$TARGET", "$SOURCE"),
+ Touch("$TARGET"),
+ ])
+ </programlisting>
+
+ <para>
+
+ Which executes as:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Copy("file.out", "file.in")
+ Touch("file.out")
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Creating a Directory: The &Mkdir; Factory</title>
+
+ <para>
+
+ If you need to create a directory,
+ use the &Mkdir; factory.
+ For example, if we need to process
+ a file in a temporary directory
+ in which the processing tool
+ will create other files that we don't care about,
+ you could use:
+
+ </para>
+
+ <programlisting>
+ Command("file.out", "file.in",
+ [
+ Delete("tempdir"),
+ Mkdir("tempdir"),
+ Copy("tempdir/${SOURCE.file}", "$SOURCE"),
+ "process tempdir",
+ Move("$TARGET", "tempdir/output_file"),
+ Delete("tempdir"),
+ ])
+ </programlisting>
+
+ <para>
+
+ Which executes as:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Delete("tempdir")
+ Mkdir("tempdir")
+ Copy("tempdir/file.in", "file.in")
+ process tempdir
+ Move("file.out", "tempdir/output_file")
+ scons: *** [file.out] tempdir/output_file: No such file or directory
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Changing File or Directory Permissions: The &Chmod; Factory</title>
+
+ <para>
+
+ To change permissions on a file or directory,
+ use the &Chmod; factory.
+ The permission argument uses POSIX-style
+ permission bits and should typically
+ be expressed as an octal,
+ not decimal, number:
+
+ </para>
+
+ <programlisting>
+ Command("file.out", "file.in",
+ [
+ Copy("$TARGET", "$SOURCE"),
+ Chmod("$TARGET", 0755),
+ ])
+ </programlisting>
+
+ <para>
+
+ Which executes:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Copy("file.out", "file.in")
+ Chmod("file.out", 0755)
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Executing an action immediately: the &Execute; Function</title>
+
+ <para>
+
+ We've been showing you how to use &Action; factories
+ in the &Command; function.
+ You can also execute an &Action; returned by a factory
+ (or actually, any &Action;)
+ at the time the &SConscript; file is read
+ by using the &Execute; function.
+ For example, if we need to make sure that
+ a directory exists before we build any targets,
+
+ </para>
+
+ <programlisting>
+ Execute(Mkdir('/tmp/my_temp_directory'))
+ </programlisting>
+
+ <para>
+
+ Notice that this will
+ create the directory while
+ the &SConscript; file is being read:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ Mkdir("/tmp/my_temp_directory")
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ scons: `.' is up to date.
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ If you're familiar with Python,
+ you may wonder why you would want to use this
+ instead of just calling the native Python
+ <function>os.mkdir()</function> function.
+ The advantage here is that the &Mkdir;
+ action will behave appropriately if the user
+ specifies the &SCons; <option>-n</option> or
+ <option>-q</option> options--that is,
+ it will print the action but not actually
+ make the directory when <option>-n</option> is specified,
+ or make the directory but not print the action
+ when <option>-q</option> is specified.
+
+ </para>
+
+ <para>
+
+ The &Execute; function returns the exit status
+ or return value of the underlying action being executed.
+ It will also print an error message if the action
+ fails and returns a non-zero value.
+ &SCons; will <emphasis>not</emphasis>, however,
+ actually stop the build if the action fails.
+ If you want the build to stop
+ in response to a failure in an action called by &Execute;,
+ you must do so by explicitly
+ checking the return value
+ and calling the &Exit; function
+ (or a Python equivalent):
+
+ </para>
+
+ <programlisting>
+ if Execute(Mkdir('/tmp/my_temp_directory')):
+ # A problem occurred while making the temp directory.
+ Exit(1)
+ </programlisting>
+
+ </section>
diff --git a/doc/user/file-removal.in b/doc/user/file-removal.in
new file mode 100644
index 0000000..c26f020
--- /dev/null
+++ b/doc/user/file-removal.in
@@ -0,0 +1,223 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ There are two occasions when &SCons; will,
+ by default, remove target files.
+ The first is when &SCons; determines that
+ an target file needs to be rebuilt
+ and removes the existing version of the target
+ before executing
+ The second is when &SCons; is invoked with the
+ <literal>-c</literal> option to "clean"
+ a tree of its built targets.
+
+ These behaviours can be suppressed with the
+ &Precious; and &NoClean; functions, respectively.
+
+ </para>
+
+ <section>
+ <title>Preventing target removal during build: the &Precious; Function</title>
+
+ <para>
+
+ By default, &SCons; removes targets before building them.
+ Sometimes, however, this is not what you want.
+ For example, you may want to update a library incrementally,
+ not by having it deleted and then rebuilt from all
+ of the constituent object files.
+ In such cases, you can use the
+ &Precious; method to prevent
+ &SCons; from removing the target before it is built:
+
+ </para>
+
+ <scons_example name="precious-ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment(RANLIBCOM='')
+ lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ env.Precious(lib)
+ </file>
+ <file name="f1.c">
+ int f1() { }
+ </file>
+ <file name="f2.c">
+ int f2() { }
+ </file>
+ <file name="f3.c">
+ int f3() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Although the output doesn't look any different,
+ &SCons; does not, in fact,
+ delete the target library before rebuilding it:
+
+ </para>
+
+ <scons_output example="precious-ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ &SCons; will, however, still delete files marked as &Precious;
+ when the <literal>-c</literal> option is used.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Preventing target removal during clean: the &NoClean; Function</title>
+
+ <para>
+
+ By default, &SCons; removes all built targets when invoked
+ with the <literal>-c</literal> option to clean a source tree
+ of built targets.
+ Sometimes, however, this is not what you want.
+ For example, you may want to remove only intermediate generated files
+ (such as object files),
+ but leave the final targets
+ (the libraries)
+ untouched.
+
+ In such cases, you can use the &NoClean; method to prevent &SCons;
+ from removing a target during a clean:
+
+ </para>
+
+ <scons_example name="noclean-ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment(RANLIBCOM='')
+ lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ env.NoClean(lib)
+ </file>
+ <file name="f1.c">
+ int f1() { }
+ </file>
+ <file name="f2.c">
+ int f2() { }
+ </file>
+ <file name="f3.c">
+ int f3() { }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Notice that the <filename>libfoo.a</filename>
+ is not listed as a removed file:
+
+ </para>
+
+ <scons_output example="noclean-ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -c</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Removing additional files during clean: the &Clean; Function</title>
+
+ <para>
+
+ There may be additional files that you want removed
+ when the <literal>-c</literal> option is used,
+ but which &SCons; doesn't know about
+ because they're not normal target files.
+ For example, perhaps a command you invoke
+ creates a log file as
+ part of building the target file you want.
+ You would like the log file cleaned,
+ but you don't want to have to teach
+ SCons that the command
+ "builds" two files.
+
+ </para>
+
+ <para>
+
+ You can use the &Clean; function to arrange for additional files
+ to be removed when the <literal>-c</literal> option is used.
+ Notice, however, that the &Clean; function takes two arguments,
+ and the <emphasis>second</emphasis> argument
+ is the name of the additional file you want cleaned
+ (<filename>foo.log</filename> in this example):
+
+ </para>
+
+ <scons_example name="clean-ex1">
+ <file name="S" printme="1">
+ t = Command('foo.out', 'foo.in', 'build -o $TARGET $SOURCE')
+ Clean(t, 'foo.log')
+ </file>
+ <file name="SConstruct">
+ env = DefaultEnvironment()
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
+ SConscript('S')
+ </file>
+ <file name="foo.in">
+ foo.in
+ </file>
+ <file name="foo.log">
+ foo.log
+ </file>
+ <file name="build" chmod="0755">
+ cat $3 > $2
+ </file>
+ </scons_example>
+
+ <para>
+
+ The first argument is the target with which you want
+ the cleaning of this additional file associated.
+ In the above example,
+ we've used the return value from the
+ &Command; function,
+ which represents the
+ <filename>foo.out</filename>
+ target.
+ Now whenever the
+ <filename>foo.out</filename> target is cleaned
+ by the <literal>-c</literal> option,
+ the <filename>foo.log</filename> file
+ will be removed as well:
+
+ </para>
+
+ <scons_output example="clean-ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ </scons_output>
+
+ </section>
diff --git a/doc/user/file-removal.xml b/doc/user/file-removal.xml
new file mode 100644
index 0000000..542fd38
--- /dev/null
+++ b/doc/user/file-removal.xml
@@ -0,0 +1,202 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ There are two occasions when &SCons; will,
+ by default, remove target files.
+ The first is when &SCons; determines that
+ an target file needs to be rebuilt
+ and removes the existing version of the target
+ before executing
+ The second is when &SCons; is invoked with the
+ <literal>-c</literal> option to "clean"
+ a tree of its built targets.
+
+ These behaviours can be suppressed with the
+ &Precious; and &NoClean; functions, respectively.
+
+ </para>
+
+ <section>
+ <title>Preventing target removal during build: the &Precious; Function</title>
+
+ <para>
+
+ By default, &SCons; removes targets before building them.
+ Sometimes, however, this is not what you want.
+ For example, you may want to update a library incrementally,
+ not by having it deleted and then rebuilt from all
+ of the constituent object files.
+ In such cases, you can use the
+ &Precious; method to prevent
+ &SCons; from removing the target before it is built:
+
+ </para>
+
+ <programlisting>
+ env = Environment(RANLIBCOM='')
+ lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ env.Precious(lib)
+ </programlisting>
+
+ <para>
+
+ Although the output doesn't look any different,
+ &SCons; does not, in fact,
+ delete the target library before rebuilding it:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o f1.o -c f1.c
+ cc -o f2.o -c f2.c
+ cc -o f3.o -c f3.c
+ ar rc libfoo.a f1.o f2.o f3.o
+ </screen>
+
+ <para>
+
+ &SCons; will, however, still delete files marked as &Precious;
+ when the <literal>-c</literal> option is used.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Preventing target removal during clean: the &NoClean; Function</title>
+
+ <para>
+
+ By default, &SCons; removes all built targets when invoked
+ with the <literal>-c</literal> option to clean a source tree
+ of built targets.
+ Sometimes, however, this is not what you want.
+ For example, you may want to remove only intermediate generated files
+ (such as object files),
+ but leave the final targets
+ (the libraries)
+ untouched.
+
+ In such cases, you can use the &NoClean; method to prevent &SCons;
+ from removing a target during a clean:
+
+ </para>
+
+ <programlisting>
+ env = Environment(RANLIBCOM='')
+ lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ env.NoClean(lib)
+ </programlisting>
+
+ <para>
+
+ Notice that the <filename>libfoo.a</filename>
+ is not listed as a removed file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o f1.o -c f1.c
+ cc -o f2.o -c f2.c
+ cc -o f3.o -c f3.c
+ ar rc libfoo.a f1.o f2.o f3.o
+ % <userinput>scons -c</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Cleaning targets ...
+ Removed f1.o
+ Removed f2.o
+ Removed f3.o
+ scons: done cleaning targets.
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Removing additional files during clean: the &Clean; Function</title>
+
+ <para>
+
+ There may be additional files that you want removed
+ when the <literal>-c</literal> option is used,
+ but which &SCons; doesn't know about
+ because they're not normal target files.
+ For example, perhaps a command you invoke
+ creates a log file as
+ part of building the target file you want.
+ You would like the log file cleaned,
+ but you don't want to have to teach
+ SCons that the command
+ "builds" two files.
+
+ </para>
+
+ <para>
+
+ You can use the &Clean; function to arrange for additional files
+ to be removed when the <literal>-c</literal> option is used.
+ Notice, however, that the &Clean; function takes two arguments,
+ and the <emphasis>second</emphasis> argument
+ is the name of the additional file you want cleaned
+ (<filename>foo.log</filename> in this example):
+
+ </para>
+
+ <programlisting>
+ t = Command('foo.out', 'foo.in', 'build -o $TARGET $SOURCE')
+ Clean(t, 'foo.log')
+ </programlisting>
+
+ <para>
+
+ The first argument is the target with which you want
+ the cleaning of this additional file associated.
+ In the above example,
+ we've used the return value from the
+ &Command; function,
+ which represents the
+ <filename>foo.out</filename>
+ target.
+ Now whenever the
+ <filename>foo.out</filename> target is cleaned
+ by the <literal>-c</literal> option,
+ the <filename>foo.log</filename> file
+ will be removed as well:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ build -o foo.out foo.in
+ % <userinput>scons -Q -c</userinput>
+ Removed foo.out
+ Removed foo.log
+ </screen>
+
+ </section>
diff --git a/doc/user/hierarchy.in b/doc/user/hierarchy.in
new file mode 100644
index 0000000..a917d10
--- /dev/null
+++ b/doc/user/hierarchy.in
@@ -0,0 +1,794 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+
+=head2 The Build command
+
+By default, Cons does not change its working directory to the directory
+containing a subsidiary F<Conscript> file it is including. This behavior
+can be enabled for a build by specifying, in the top-level F<Construct>
+file:
+
+ Conscript_chdir 1;
+
+When enabled, Cons will change to the subsidiary F<Conscript> file's
+containing directory while reading in that file, and then change back
+to the top-level directory once the file has been processed.
+
+It is expected that this behavior will become the default in some future
+version of Cons. To prepare for this transition, builds that expect
+Cons to remain at the top of the build while it reads in a subsidiary
+F<Conscript> file should explicitly disable this feature as follows:
+
+ Conscript_chdir 0;
+
+=head2 Relative, top-relative, and absolute file names
+
+(There is another file prefix, ``!'', that is interpreted specially by
+Cons. See discussion of the C<Link> command, below, for details.)
+
+
+=head2 Using modules in build scripts
+
+You may pull modules into each F<Conscript> file using the normal Perl
+C<use> or C<require> statements:
+
+ use English;
+ require My::Module;
+
+Each C<use> or C<require> only affects the one F<Conscript> file in which
+it appears. To use a module in multiple F<Conscript> files, you must
+put a C<use> or C<require> statement in each one that needs the module.
+
+
+=head2 Scope of variables
+
+The top-level F<Construct> file and all F<Conscript> files begin life in
+a common, separate Perl package. B<Cons> controls the symbol table for
+the package so that, the symbol table for each script is empty, except
+for the F<Construct> file, which gets some of the command line arguments.
+All of the variables that are set or used, therefore, are set by the
+script itself, not by some external script.
+
+Variables can be explicitly B<imported> by a script from its parent
+script. To import a variable, it must have been B<exported> by the parent
+and initialized (otherwise an error will occur).
+
+
+=head2 The Export command
+
+The C<Export> command is used as in the following example:
+
+ $env = new cons();
+ $INCLUDE = "#export/include";
+ $LIB = "#export/lib";
+ Export qw( env INCLUDE LIB );
+ Build qw( util/Conscript );
+
+The values of the simple variables mentioned in the C<Export> list will be
+squirreled away by any subsequent C<Build> commands. The C<Export> command
+will only export Perl B<scalar> variables, that is, variables whose name
+begins with C<$>. Other variables, objects, etc. can be exported by
+reference, but all scripts will refer to the same object, and this object
+should be considered to be read-only by the subsidiary scripts and by the
+original exporting script. It's acceptable, however, to assign a new value
+to the exported scalar variable, that won't change the underlying variable
+referenced. This sequence, for example, is OK:
+
+ $env = new cons();
+ Export qw( env INCLUDE LIB );
+ Build qw( util/Conscript );
+ $env = new cons(CFLAGS => '-O');
+ Build qw( other/Conscript );
+
+It doesn't matter whether the variable is set before or after the C<Export>
+command. The important thing is the value of the variable at the time the
+C<Build> command is executed. This is what gets squirreled away. Any
+subsequent C<Export> commands, by the way, invalidate the first: you must
+mention all the variables you wish to export on each C<Export> command.
+
+
+=head2 The Import command
+
+Variables exported by the C<Export> command can be imported into subsidiary
+scripts by the C<Import> command. The subsidiary script always imports
+variables directly from the superior script. Consider this example:
+
+ Import qw( env INCLUDE );
+
+This is only legal if the parent script exported both C<$env> and
+C<$INCLUDE>. It also must have given each of these variables values. It is
+OK for the subsidiary script to only import a subset of the exported
+variables (in this example, C<$LIB>, which was exported by the previous
+example, is not imported).
+
+All the imported variables are automatically re-exported, so the sequence:
+
+ Import qw ( env INCLUDE );
+ Build qw ( beneath-me/Conscript );
+
+will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only
+C<$env> is to be exported, then the following will suffice:
+
+ Import qw ( env INCLUDE );
+ Export qw ( env );
+ Build qw ( beneath-me/Conscript );
+
+Needless to say, the variables may be modified locally before invoking
+C<Build> on the subsidiary script.
+
+=head2 Build script evaluation order
+
+The only constraint on the ordering of build scripts is that superior
+scripts are evaluated before their inferior scripts. The top-level
+F<Construct> file, for instance, is evaluated first, followed by any
+inferior scripts. This is all you really need to know about the evaluation
+order, since order is generally irrelevant. Consider the following C<Build>
+command:
+
+ Build qw(
+ drivers/display/Conscript
+ drivers/mouse/Conscript
+ parser/Conscript
+ utilities/Conscript
+ );
+
+We've chosen to put the script names in alphabetical order, simply because
+that's the most convenient for maintenance purposes. Changing the order will
+make no difference to the build.
+
+-->
+
+ <para>
+
+ The source code for large software projects
+ rarely stays in a single directory,
+ but is nearly always divided into a
+ hierarchy of directories.
+ Organizing a large software build using &SCons;
+ involves creating a hierarchy of build scripts
+ using the &SConscript; function.
+
+ </para>
+
+ <section>
+ <title>&SConscript; Files</title>
+
+ <para>
+
+ As we've already seen,
+ the build script at the top of the tree is called &SConstruct;.
+ The top-level &SConstruct; file can
+ use the &SConscript; function to
+ include other subsidiary scripts in the build.
+ These subsidiary scripts can, in turn,
+ use the &SConscript; function
+ to include still other scripts in the build.
+ By convention, these subsidiary scripts are usually
+ named &SConscript;.
+ For example, a top-level &SConstruct; file might
+ arrange for four subsidiary scripts to be included
+ in the build as follows:
+
+ </para>
+
+ <sconstruct>
+ SConscript(['drivers/display/SConscript',
+ 'drivers/mouse/SConscript',
+ 'parser/SConscript',
+ 'utilities/SConscript'])
+ </sconstruct>
+
+ <para>
+
+ In this case, the &SConstruct; file
+ lists all of the &SConscript; files in the build explicitly.
+ (Note, however, that not every directory in the tree
+ necessarily has an &SConscript; file.)
+ Alternatively, the <literal>drivers</literal>
+ subdirectory might contain an intermediate
+ &SConscript; file,
+ in which case the &SConscript; call in
+ the top-level &SConstruct; file
+ would look like:
+
+ </para>
+
+ <sconstruct>
+ SConscript(['drivers/SConscript',
+ 'parser/SConscript',
+ 'utilities/SConscript'])
+ </sconstruct>
+
+ <para>
+
+ And the subsidiary &SConscript; file in the
+ <literal>drivers</literal> subdirectory
+ would look like:
+
+ </para>
+
+ <sconstruct>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </sconstruct>
+
+ <para>
+
+ Whether you list all of the &SConscript; files in the
+ top-level &SConstruct; file,
+ or place a subsidiary &SConscript; file in
+ intervening directories,
+ or use some mix of the two schemes,
+ is up to you and the needs of your software.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Path Names Are Relative to the &SConscript; Directory</title>
+
+ <para>
+
+ Subsidiary &SConscript; files make it easy to create a build
+ hierarchy because all of the file and directory names
+ in a subsidiary &SConscript; files are interpreted
+ relative to the directory in which the &SConscript; file lives.
+ Typically, this allows the &SConscript; file containing the
+ instructions to build a target file
+ to live in the same directory as the source files
+ from which the target will be built,
+ making it easy to update how the software is built
+ whenever files are added or deleted
+ (or other changes are made).
+
+ </para>
+
+ <para>
+
+ For example, suppose we want to build two programs
+ &prog1; and &prog2; in two separate directories
+ with the same names as the programs.
+ One typical way to do this would be
+ with a top-level &SConstruct; file like this:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ SConscript(['prog1/SConscript',
+ 'prog2/SConscript'])
+ </file>
+ <file name="prog1/SConscript">
+ env = Environment()
+ env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c'])
+ </file>
+ <file name="prog2/SConscript">
+ env = Environment()
+ env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c'])
+ </file>
+ <directory name="prog1"></directory>
+ <file name="prog1/main.c">
+ x
+ </file>
+ <file name="prog1/foo1.c">
+ x
+ </file>
+ <file name="prog1/foo2.c">
+ x
+ </file>
+ <directory name="prog2"></directory>
+ <file name="prog2/main.c">
+ x
+ </file>
+ <file name="prog2/bar1.c">
+ x
+ </file>
+ <file name="prog2/bar2.c">
+ x
+ </file>
+ </scons_example>
+
+ <para>
+
+ And subsidiary &SConscript; files that look like this:
+
+ </para>
+
+ <scons_example_file example="ex1" name="prog1/SConscript">
+ </scons_example_file>
+
+ <para>
+
+ And this:
+
+ </para>
+
+ <scons_example_file example="ex1" name="prog2/SConscript">
+ </scons_example_file>
+
+ <para>
+
+ Then, when we run &SCons; in the top-level directory,
+ our build looks like:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice the following:
+
+ First, you can have files with the same names
+ in multiple directories, like main.c in the above example.
+
+ Second, unlike standard recursive use of &Make;,
+ &SCons; stays in the top-level directory
+ (where the &SConstruct; file lives)
+ and issues commands that use the path names
+ from the top-level directory to the
+ target and source files within the hierarchy.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Top-Level Path Names in Subsidiary &SConscript; Files</title>
+
+ <para>
+
+ If you need to use a file from another directory,
+ it's sometimes more convenient to specify
+ the path to a file in another directory
+ from the top-level &SConstruct; directory,
+ even when you're using that file in
+ a subsidiary &SConscript; file in a subdirectory.
+ You can tell &SCons; to interpret a path name
+ as relative to the top-level &SConstruct; directory,
+ not the local directory of the &SConscript; file,
+ by appending a &hash; (hash mark)
+ to the beginning of the path name:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct">
+ SConscript('src/prog/SConscript')
+ </file>
+ <file name="src/prog/SConscript" printme="1">
+ env = Environment()
+ env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c'])
+ </file>
+ <file name="src/prog/main.c">
+ x
+ </file>
+ <file name="lib/foo1.c">
+ x
+ </file>
+ <file name="src/prog/foo2.c">
+ x
+ </file>
+ </scons_example>
+
+ <para>
+
+ In this example,
+ the <literal>lib</literal> directory is
+ directly underneath the top-level &SConstruct; directory.
+ If the above &SConscript; file is in a subdirectory
+ named <literal>src/prog</literal>,
+ the output would look like:
+
+ </para>
+
+ <scons_output example="ex2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ (Notice that the <literal>lib/foo1.o</literal> object file
+ is built in the same directory as its source file.
+ See <xref linkend="chap-separate"></xref>, below,
+ for information about
+ how to build the object file in a different subdirectory.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Absolute Path Names</title>
+
+ <para>
+
+ Of course, you can always specify
+ an absolute path name for a file--for example:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct">
+ SConscript('src/prog/SConscript')
+ </file>
+ <file name="src/prog/SConscript" printme="1">
+ env = Environment()
+ env.Program('prog', ['main.c', '__ROOT__/usr/joe/lib/foo1.c', 'foo2.c'])
+ </file>
+ <file name="src/prog/main.c">
+ x
+ </file>
+ <file name="__ROOT__/usr/joe/lib/foo1.c">
+ x
+ </file>
+ <file name="src/prog/foo2.c">
+ x
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which, when executed, would yield:
+
+ </para>
+
+ <scons_output example="ex3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ (As was the case with top-relative path names,
+ notice that the <literal>/usr/joe/lib/foo1.o</literal> object file
+ is built in the same directory as its source file.
+ See <xref linkend="chap-separate"></xref>, below,
+ for information about
+ how to build the object file in a different subdirectory.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title>
+
+ <para>
+
+ In the previous example,
+ each of the subsidiary &SConscript; files
+ created its own construction environment
+ by calling &Environment; separately.
+ This obviously works fine,
+ but if each program must be built
+ with the same construction variables,
+ it's cumbersome and error-prone to initialize
+ separate construction environments
+ in the same way over and over in each subsidiary
+ &SConscript; file.
+
+ </para>
+
+ <para>
+
+ &SCons; supports the ability to <emphasis>export</emphasis> variables
+ from a parent &SConscript; file
+ to its subsidiary &SConscript; files,
+ which allows you to share common initialized
+ values throughout your build hierarchy.
+
+ </para>
+
+ <section>
+ <title>Exporting Variables</title>
+
+ <para>
+
+ There are two ways to export a variable,
+ such as a construction environment,
+ from an &SConscript; file,
+ so that it may be used by other &SConscript; files.
+ First, you can call the &Export;
+ function with a list of variables,
+ or a string of white-space separated variable names.
+ Each call to &Export; adds one
+ or more variables to a global list
+ of variables that are available for import
+ by other &SConscript; files.
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ Export('env')
+ </sconstruct>
+
+ <para>
+
+ You may export more than one variable name at a time:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ debug = ARGUMENTS['debug']
+ Export('env', 'debug')
+ </sconstruct>
+
+ <para>
+
+ Because white space is not legal in Python variable names,
+ the &Export; function will even automatically split
+ a string into separate names for you:
+
+ </para>
+
+ <sconstruct>
+ Export('env debug')
+ </sconstruct>
+
+ <para>
+
+ Second, you can specify a list of
+ variables to export as a second argument
+ to the &SConscript; function call:
+
+ </para>
+
+ <sconstruct>
+ SConscript('src/SConscript', 'env')
+ </sconstruct>
+
+ <para>
+
+ Or as the &exports; keyword argument:
+
+ </para>
+
+ <sconstruct>
+ SConscript('src/SConscript', exports='env')
+ </sconstruct>
+
+ <para>
+
+ These calls export the specified variables
+ to only the listed &SConscript; files.
+ You may, however, specify more than one
+ &SConscript; file in a list:
+
+ </para>
+
+ <sconstruct>
+ SConscript(['src1/SConscript',
+ 'src2/SConscript'], exports='env')
+ </sconstruct>
+
+ <para>
+
+ This is functionally equivalent to
+ calling the &SConscript; function
+ multiple times with the same &exports; argument,
+ one per &SConscript; file.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Importing Variables</title>
+
+ <para>
+
+ Once a variable has been exported from a calling
+ &SConscript; file,
+ it may be used in other &SConscript; files
+ by calling the &Import; function:
+
+ </para>
+
+ <sconstruct>
+ Import('env')
+ env.Program('prog', ['prog.c'])
+ </sconstruct>
+
+ <para>
+
+ The &Import; call makes the <literal>env</literal> construction
+ environment available to the &SConscript; file,
+ after which the variable can be used to build
+ programs, libraries, etc.
+
+ </para>
+
+ <para>
+
+ Like the &Export; function,
+ the &Import; function can be used
+ with multiple variable names:
+
+ </para>
+
+ <sconstruct>
+ Import('env', 'debug')
+ env = env.Clone(DEBUG = debug)
+ env.Program('prog', ['prog.c'])
+ </sconstruct>
+
+ <para>
+
+ And the &Import; function will similarly
+ split a string along white-space
+ into separate variable names:
+
+ </para>
+
+ <sconstruct>
+ Import('env debug')
+ env = env.Clone(DEBUG = debug)
+ env.Program('prog', ['prog.c'])
+ </sconstruct>
+
+ <para>
+
+ Lastly, as a special case,
+ you may import all of the variables that
+ have been exported by supplying an asterisk
+ to the &Import; function:
+
+ </para>
+
+ <sconstruct>
+ Import('*')
+ env = env.Clone(DEBUG = debug)
+ env.Program('prog', ['prog.c'])
+ </sconstruct>
+
+ <para>
+
+ If you're dealing with a lot of &SConscript; files,
+ this can be a lot simpler than keeping
+ arbitrary lists of imported variables in each file.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Returning Values From an &SConscript; File</title>
+
+ <para>
+
+ Sometimes, you would like to be able to
+ use information from a subsidiary
+ &SConscript file in some way.
+ For example,
+ suppose that you want to create one
+ library from source files
+ scattered throughout a number
+ of subsidiary &SConscript; files.
+ You can do this by using the &Return;
+ function to return values
+ from the subsidiary &SConscript; files
+ to the calling file.
+
+ </para>
+
+ <para>
+
+ If, for example, we have two subdirectories
+ &foo; and &bar;
+ that should each contribute a source
+ file to a Library,
+ what we'd like to be able to do is
+ collect the object files
+ from the subsidiary &SConscript; calls
+ like this:
+
+ </para>
+
+ <scons_example name="Return">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ Export('env')
+ objs = []
+ for subdir in ['foo', 'bar']:
+ o = SConscript('%s/SConscript' % subdir)
+ objs.append(o)
+ env.Library('prog', objs)
+ </file>
+ <directory name="foo"></directory>
+ <directory name="bar"></directory>
+ <file name="foo/SConscript">
+ Import('env')
+ obj = env.Object('foo.c')
+ Return('obj')
+ </file>
+ <file name="bar/SConscript">
+ Import('env')
+ obj = env.Object('bar.c')
+ Return('obj')
+ </file>
+ <file name="foo/foo.c">
+ void foo(void) { printf("foo/foo.c\n"); }
+ </file>
+ <file name="bar/bar.c">
+ void bar(void) { printf("bar/bar.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ We can do this by using the &Return;
+ function in the
+ <literal>foo/SConscript</literal> file like this:
+
+ </para>
+
+ <scons_example_file example="Return" name="foo/SConscript">
+ </scons_example_file>
+
+ <para>
+
+ (The corresponding
+ <literal>bar/SConscript</literal>
+ file should be pretty obvious.)
+ Then when we run &SCons;,
+ the object files from the subsidiary subdirectories
+ are all correctly archived in the desired library:
+
+ </para>
+
+ <scons_output example="Return">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <!--
+ XXX Return(stop=False)
+ -->
+
+ </section>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Executing From a Subdirectory: the -D, -u and -U Options</title>
+
+ <para>
+
+ XXX -D, -u and -U
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/hierarchy.xml b/doc/user/hierarchy.xml
new file mode 100644
index 0000000..3495c5f
--- /dev/null
+++ b/doc/user/hierarchy.xml
@@ -0,0 +1,746 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>
+
+ <programlisting>
+ SConscript(['drivers/display/SConscript',
+ 'drivers/mouse/SConscript',
+ 'parser/SConscript',
+ 'utilities/SConscript'])
+ </programlisting>
+
+ <para>
+
+ In this case, the &SConstruct; file
+ lists all of the &SConscript; files in the build explicitly.
+ (Note, however, that not every directory in the tree
+ necessarily has an &SConscript; file.)
+ Alternatively, the <literal>drivers</literal>
+ subdirectory might contain an intermediate
+ &SConscript; file,
+ in which case the &SConscript; call in
+ the top-level &SConstruct; file
+ would look like:
+
+ </para>
+
+ <programlisting>
+ SConscript(['drivers/SConscript',
+ 'parser/SConscript',
+ 'utilities/SConscript'])
+ </programlisting>
+
+ <para>
+
+ And the subsidiary &SConscript; file in the
+ <literal>drivers</literal> subdirectory
+ would look like:
+
+ </para>
+
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
+
+ <para>
+
+ Whether you list all of the &SConscript; files in the
+ top-level &SConstruct; file,
+ or place a subsidiary &SConscript; file in
+ intervening directories,
+ or use some mix of the two schemes,
+ is up to you and the needs of your software.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Path Names Are Relative to the &SConscript; Directory</title>
+
+ <para>
+
+ 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>
+
+ <programlisting>
+ SConscript(['prog1/SConscript',
+ 'prog2/SConscript'])
+ </programlisting>
+
+ <para>
+
+ And subsidiary &SConscript; files that look like this:
+
+ </para>
+
+
+ <programlisting>
+ env = Environment()
+ env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c'])
+ </programlisting>
+
+ <para>
+
+ And this:
+
+ </para>
+
+
+ <programlisting>
+ env = Environment()
+ env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c'])
+ </programlisting>
+
+ <para>
+
+ Then, when we run &SCons; in the top-level directory,
+ our build looks like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o prog1/foo1.o -c prog1/foo1.c
+ cc -o prog1/foo2.o -c prog1/foo2.c
+ cc -o prog1/main.o -c prog1/main.c
+ cc -o prog1/prog1 prog1/main.o prog1/foo1.o prog1/foo2.o
+ cc -o prog2/bar1.o -c prog2/bar1.c
+ cc -o prog2/bar2.o -c prog2/bar2.c
+ cc -o prog2/main.o -c prog2/main.c
+ cc -o prog2/prog2 prog2/main.o prog2/bar1.o prog2/bar2.o
+ </screen>
+
+ <para>
+
+ Notice the following:
+
+ First, you can have files with the same names
+ in multiple directories, like main.c in the above example.
+
+ Second, unlike standard recursive use of &Make;,
+ &SCons; stays in the top-level directory
+ (where the &SConstruct; file lives)
+ and issues commands that use the path names
+ from the top-level directory to the
+ target and source files within the hierarchy.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Top-Level Path Names in Subsidiary &SConscript; Files</title>
+
+ <para>
+
+ If you need to use a file from another directory,
+ it's sometimes more convenient to specify
+ the path to a file in another directory
+ from the top-level &SConstruct; directory,
+ even when you're using that file in
+ a subsidiary &SConscript; file in a subdirectory.
+ You can tell &SCons; to interpret a path name
+ as relative to the top-level &SConstruct; directory,
+ not the local directory of the &SConscript; file,
+ by appending a &hash; (hash mark)
+ to the beginning of the path name:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c'])
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o lib/foo1.o -c lib/foo1.c
+ cc -o src/prog/foo2.o -c src/prog/foo2.c
+ cc -o src/prog/main.o -c src/prog/main.c
+ cc -o src/prog/prog src/prog/main.o lib/foo1.o src/prog/foo2.o
+ </screen>
+
+ <para>
+
+ (Notice that the <literal>lib/foo1.o</literal> object file
+ is built in the same directory as its source file.
+ See <xref linkend="chap-separate"></xref>, below,
+ for information about
+ how to build the object file in a different subdirectory.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Absolute Path Names</title>
+
+ <para>
+
+ Of course, you can always specify
+ an absolute path name for a file--for example:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Program('prog', ['main.c', '/usr/joe/lib/foo1.c', 'foo2.c'])
+ </programlisting>
+
+ <para>
+
+ Which, when executed, would yield:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o src/prog/foo2.o -c src/prog/foo2.c
+ cc -o src/prog/main.o -c src/prog/main.c
+ cc -o /usr/joe/lib/foo1.o -c /usr/joe/lib/foo1.c
+ cc -o src/prog/prog src/prog/main.o /usr/joe/lib/foo1.o src/prog/foo2.o
+ </screen>
+
+ <para>
+
+ (As was the case with top-relative path names,
+ notice that the <literal>/usr/joe/lib/foo1.o</literal> object file
+ is built in the same directory as its source file.
+ See <xref linkend="chap-separate"></xref>, below,
+ for information about
+ how to build the object file in a different subdirectory.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title>
+
+ <para>
+
+ In the previous example,
+ each of the subsidiary &SConscript; files
+ created its own construction environment
+ by calling &Environment; separately.
+ This obviously works fine,
+ but if each program must be built
+ with the same construction variables,
+ it's cumbersome and error-prone to initialize
+ separate construction environments
+ in the same way over and over in each subsidiary
+ &SConscript; file.
+
+ </para>
+
+ <para>
+
+ &SCons; supports the ability to <emphasis>export</emphasis> variables
+ from a parent &SConscript; file
+ to its subsidiary &SConscript; files,
+ which allows you to share common initialized
+ values throughout your build hierarchy.
+
+ </para>
+
+ <section>
+ <title>Exporting Variables</title>
+
+ <para>
+
+ There are two ways to export a variable,
+ such as a construction environment,
+ from an &SConscript; file,
+ so that it may be used by other &SConscript; files.
+ First, you can call the &Export;
+ function with a list of variables,
+ or a string of white-space separated variable names.
+ Each call to &Export; adds one
+ or more variables to a global list
+ of variables that are available for import
+ by other &SConscript; files.
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ Export('env')
+ </programlisting>
+
+ <para>
+
+ You may export more than one variable name at a time:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ debug = ARGUMENTS['debug']
+ Export('env', 'debug')
+ </programlisting>
+
+ <para>
+
+ Because white space is not legal in Python variable names,
+ the &Export; function will even automatically split
+ a string into separate names for you:
+
+ </para>
+
+ <programlisting>
+ Export('env debug')
+ </programlisting>
+
+ <para>
+
+ Second, you can specify a list of
+ variables to export as a second argument
+ to the &SConscript; function call:
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript', 'env')
+ </programlisting>
+
+ <para>
+
+ Or as the &exports; keyword argument:
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript', exports='env')
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ SConscript(['src1/SConscript',
+ 'src2/SConscript'], exports='env')
+ </programlisting>
+
+ <para>
+
+ This is functionally equivalent to
+ calling the &SConscript; function
+ multiple times with the same &exports; argument,
+ one per &SConscript; file.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Importing Variables</title>
+
+ <para>
+
+ Once a variable has been exported from a calling
+ &SConscript; file,
+ it may be used in other &SConscript; files
+ by calling the &Import; function:
+
+ </para>
+
+ <programlisting>
+ Import('env')
+ env.Program('prog', ['prog.c'])
+ </programlisting>
+
+ <para>
+
+ The &Import; call makes the <literal>env</literal> construction
+ environment available to the &SConscript; file,
+ after which the variable can be used to build
+ programs, libraries, etc.
+
+ </para>
+
+ <para>
+
+ Like the &Export; function,
+ the &Import; function can be used
+ with multiple variable names:
+
+ </para>
+
+ <programlisting>
+ Import('env', 'debug')
+ env = env.Clone(DEBUG = debug)
+ env.Program('prog', ['prog.c'])
+ </programlisting>
+
+ <para>
+
+ And the &Import; function will similarly
+ split a string along white-space
+ into separate variable names:
+
+ </para>
+
+ <programlisting>
+ Import('env debug')
+ env = env.Clone(DEBUG = debug)
+ env.Program('prog', ['prog.c'])
+ </programlisting>
+
+ <para>
+
+ Lastly, as a special case,
+ you may import all of the variables that
+ have been exported by supplying an asterisk
+ to the &Import; function:
+
+ </para>
+
+ <programlisting>
+ Import('*')
+ env = env.Clone(DEBUG = debug)
+ env.Program('prog', ['prog.c'])
+ </programlisting>
+
+ <para>
+
+ If you're dealing with a lot of &SConscript; files,
+ this can be a lot simpler than keeping
+ arbitrary lists of imported variables in each file.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Returning Values From an &SConscript; File</title>
+
+ <para>
+
+ Sometimes, you would like to be able to
+ use information from a subsidiary
+ &SConscript; file in some way.
+ For example,
+ suppose that you want to create one
+ library from source files
+ scattered throughout a number
+ of subsidiary &SConscript; files.
+ You can do this by using the &Return;
+ function to return values
+ from the subsidiary &SConscript; files
+ to the calling file.
+
+ </para>
+
+ <para>
+
+ If, for example, we have two subdirectories
+ &foo; and &bar;
+ that should each contribute a source
+ file to a Library,
+ what we'd like to be able to do is
+ collect the object files
+ from the subsidiary &SConscript; calls
+ like this:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ Export('env')
+ objs = []
+ for subdir in ['foo', 'bar']:
+ o = SConscript('%s/SConscript' % subdir)
+ objs.append(o)
+ env.Library('prog', objs)
+ </programlisting>
+
+ <para>
+
+ We can do this by using the &Return;
+ function in the
+ <literal>foo/SConscript</literal> file like this:
+
+ </para>
+
+
+ <programlisting>
+ Import('env')
+ obj = env.Object('foo.c')
+ Return('obj')
+ </programlisting>
+
+ <para>
+
+ (The corresponding
+ <literal>bar/SConscript</literal>
+ file should be pretty obvious.)
+ Then when we run &SCons;,
+ the object files from the subsidiary subdirectories
+ are all correctly archived in the desired library:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o bar/bar.o -c bar/bar.c
+ cc -o foo/foo.o -c foo/foo.c
+ ar rc libprog.a foo/foo.o bar/bar.o
+ ranlib libprog.a
+ </screen>
+
+ <!--
+ XXX Return(stop=False)
+ -->
+
+ </section>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Executing From a Subdirectory: the -D, -u and -U Options</title>
+
+ <para>
+
+ XXX -D, -u and -U
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/install.in b/doc/user/install.in
new file mode 100644
index 0000000..cce2de3
--- /dev/null
+++ b/doc/user/install.in
@@ -0,0 +1,247 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ Once a program is built,
+ it is often appropriate to install it in another
+ directory for public use.
+ You use the &Install; method
+ to arrange for a program, or any other file,
+ to be copied into a destination directory:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('__ROOT__/usr/bin', hello)
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Note, however, that installing a file is
+ still considered a type of file "build."
+ This is important when you remember that
+ the default behavior of &SCons; is
+ to build files in or below the current directory.
+ If, as in the example above,
+ you are installing files in a directory
+ outside of the top-level &SConstruct; file's directory tree,
+ you must specify that directory
+ (or a higher directory, such as <literal>/</literal>)
+ for it to install anything there:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q __ROOT__/usr/bin</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ It can, however, be cumbersome to remember
+ (and type) the specific destination directory
+ in which the program (or any other file)
+ should be installed.
+ This is an area where the &Alias;
+ function comes in handy,
+ allowing you, for example,
+ to create a pseudo-target named <literal>install</literal>
+ that can expand to the specified destination directory:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('__ROOT__/usr/bin', hello)
+ env.Alias('install', '__ROOT__/usr/bin')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ This then yields the more natural
+ ability to install the program
+ in its destination as follows:
+
+ </para>
+
+ <scons_output example="ex2">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q install</scons_output_command>
+ </scons_output>
+
+ <section>
+ <title>Installing Multiple Files in a Directory</title>
+
+ <para>
+
+ You can install multiple files into a directory
+ simply by calling the &Install; function multiple times:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.Install('__ROOT__/usr/bin', hello)
+ env.Install('__ROOT__/usr/bin', goodbye)
+ env.Alias('install', '__ROOT__/usr/bin')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="goodbye.c">
+ int main() { printf("Goodbye, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Or, more succinctly, listing the multiple input
+ files in a list
+ (just like you can do with any other builder):
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.Install('__ROOT__/usr/bin', [hello, goodbye])
+ env.Alias('install', '__ROOT__/usr/bin')
+ </sconstruct>
+
+ <para>
+
+ Either of these two examples yields:
+
+ </para>
+
+ <scons_output example="ex3">
+ <scons_output_command>scons -Q install</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Installing a File Under a Different Name</title>
+
+ <para>
+
+ The &Install; method preserves the name
+ of the file when it is copied into the
+ destination directory.
+ If you need to change the name of the file
+ when you copy it, use the &InstallAs; function:
+
+ </para>
+
+ <scons_example name="ex4">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.InstallAs('__ROOT__/usr/bin/hello-new', hello)
+ env.Alias('install', '__ROOT__/usr/bin')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ This installs the <literal>hello</literal>
+ program with the name <literal>hello-new</literal>
+ as follows:
+
+ </para>
+
+ <scons_output example="ex4">
+ <scons_output_command>scons -Q install</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Installing Multiple Files Under Different Names</title>
+
+ <para>
+
+ Lastly, if you have multiple files that all
+ need to be installed with different file names,
+ you can either call the &InstallAs; function
+ multiple times, or as a shorthand,
+ you can supply same-length lists
+ for both the target and source arguments:
+
+ </para>
+
+ <scons_example name="ex5">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.InstallAs(['__ROOT__/usr/bin/hello-new',
+ '__ROOT__/usr/bin/goodbye-new'],
+ [hello, goodbye])
+ env.Alias('install', '__ROOT__/usr/bin')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="goodbye.c">
+ int main() { printf("Goodbye, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ In this case, the &InstallAs; function
+ loops through both lists simultaneously,
+ and copies each source file into its corresponding
+ target file name:
+
+ </para>
+
+ <scons_output example="ex5">
+ <scons_output_command>scons -Q install</scons_output_command>
+ </scons_output>
+
+ </section>
diff --git a/doc/user/install.xml b/doc/user/install.xml
new file mode 100644
index 0000000..e011986
--- /dev/null
+++ b/doc/user/install.xml
@@ -0,0 +1,237 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('/usr/bin', hello)
+ </programlisting>
+
+ <para>
+
+ Note, however, that installing a file is
+ still considered a type of file "build."
+ This is important when you remember that
+ the default behavior of &SCons; is
+ to build files in or below the current directory.
+ If, as in the example above,
+ you are installing files in a directory
+ outside of the top-level &SConstruct; file's directory tree,
+ you must specify that directory
+ (or a higher directory, such as <literal>/</literal>)
+ for it to install anything there:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q /usr/bin</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('/usr/bin', hello)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ This then yields the more natural
+ ability to install the program
+ in its destination as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q install</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.Install('/usr/bin', hello)
+ env.Install('/usr/bin', goodbye)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ Or, more succinctly, listing the multiple input
+ files in a list
+ (just like you can do with any other builder):
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.Install('/usr/bin', [hello, goodbye])
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ Either of these two examples yields:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q install</userinput>
+ cc -o goodbye.o -c goodbye.c
+ cc -o goodbye goodbye.o
+ Install file: "goodbye" as "/usr/bin/goodbye"
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ Install file: "hello" as "/usr/bin/hello"
+ </screen>
+
+ </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>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.InstallAs('/usr/bin/hello-new', hello)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ This installs the <literal>hello</literal>
+ program with the name <literal>hello-new</literal>
+ as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q install</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ Install file: "hello" as "/usr/bin/hello-new"
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Installing Multiple Files Under Different Names</title>
+
+ <para>
+
+ Lastly, if you have multiple files that all
+ need to be installed with different file names,
+ you can either call the &InstallAs; function
+ multiple times, or as a shorthand,
+ you can supply same-length lists
+ for both the target and source arguments:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.InstallAs(['/usr/bin/hello-new',
+ '/usr/bin/goodbye-new'],
+ [hello, goodbye])
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ In this case, the &InstallAs; function
+ loops through both lists simultaneously,
+ and copies each source file into its corresponding
+ target file name:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q install</userinput>
+ cc -o goodbye.o -c goodbye.c
+ cc -o goodbye goodbye.o
+ Install file: "goodbye" as "/usr/bin/goodbye-new"
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ Install file: "hello" as "/usr/bin/hello-new"
+ </screen>
+
+ </section>
diff --git a/doc/user/java.in b/doc/user/java.in
new file mode 100644
index 0000000..358d79b
--- /dev/null
+++ b/doc/user/java.in
@@ -0,0 +1,657 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ So far, we've been using examples of
+ building C and C++ programs
+ to demonstrate the features of &SCons;.
+ &SCons; also supports building Java programs,
+ but Java builds are handled slightly differently,
+ which reflects the ways in which
+ the Java compiler and tools
+ build programs differently than
+ other languages' tool chains.
+
+ </para>
+
+ <section>
+ <title>Building Java Class Files: the &b-Java; Builder</title>
+
+ <para>
+
+ The basic activity when programming in Java,
+ of course, is to take one or more <filename>.java</filename> files
+ containing Java source code
+ and to call the Java compiler
+ to turn them into one or more
+ <filename>.class</filename> files.
+ In &SCons;, you do this
+ by giving the &b-link-Java; Builder
+ a target directory in which
+ to put the <filename>.class</filename> files,
+ and a source directory that contains
+ the <filename>.java</filename> files:
+
+ </para>
+
+ <scons_example name="java">
+ <file name="SConstruct" printme="1">
+ Java('classes', 'src')
+ </file>
+ <file name="src/Example1.java">
+ public class Example1
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ <file name="src/Example2.java">
+ public class Example2
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ <file name="src/Example3.java">
+ public class Example3
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ </scons_example>
+
+ <para>
+
+ If the <filename>src</filename> directory contains
+ three <filename>.java</filename> source files,
+ then running &SCons; might look like this:
+
+ </para>
+
+ <scons_output example="java">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ &SCons; will actually search the <filename>src</filename>
+ directory tree for all of the <filename>.java</filename> files.
+ The Java compiler will then create the
+ necessary class files in the <filename>classes</filename> subdirectory,
+ based on the class names found in the <filename>.java</filename> files.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>How &SCons; Handles Java Dependencies</title>
+
+ <para>
+
+ In addition to searching the source directory for
+ <filename>.java</filename> files,
+ &SCons; actually runs the <filename>.java</filename> files
+ through a stripped-down Java parser that figures out
+ what classes are defined.
+ In other words, &SCons; knows,
+ without you having to tell it,
+ what <filename>.class</filename> files
+ will be produced by the &javac; call.
+ So our one-liner example from the preceding section:
+
+ </para>
+
+ <scons_example name="java-classes">
+ <file name="SConstruct" printme="1">
+ Java('classes', 'src')
+ </file>
+ <file name="src/Example1.java">
+ public class Example1
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ public class AdditionalClass1
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ <file name="src/Example2.java">
+ public class Example2
+ {
+ class Inner2 {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ }
+ </file>
+ <file name="src/Example3.java">
+ public class Example3
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ public class AdditionalClass3
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Will not only tell you reliably
+ that the <filename>.class</filename> files
+ in the <filename>classes</filename> subdirectory
+ are up-to-date:
+
+ </para>
+
+ <scons_output example="java-classes">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q classes</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ But it will also remove all of the generated
+ <filename>.class</filename> files,
+ even for inner classes,
+ without you having to specify them manually.
+ For example, if our
+ <filename>Example1.java</filename>
+ and
+ <filename>Example3.java</filename>
+ files both define additional classes,
+ and the class defined in <filename>Example2.java</filename>
+ has an inner class,
+ running <userinput>scons -c</userinput>
+ will clean up all of those <filename>.class</filename> files
+ as well:
+
+ </para>
+
+ <scons_output example="java-classes">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c classes</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ To ensure correct handling of <filename>.class</filename>
+ dependencies in all cases, you need to tell &SCons; which Java
+ version is being used. This is needed because Java 1.5 changed
+ the <filename>.class</filename> file names for nested anonymous
+ inner classes. Use the <varname>JAVAVERSION</varname> construction
+ variable to specify the version in use. With Java 1.6, the
+ one-liner example can then be defined like this:
+
+ </para>
+
+ <sconstruct>
+ Java('classes', 'src', JAVAVERSION='1.6')
+ </sconstruct>
+
+ <para>
+ See <varname>JAVAVERSION</varname> in the man page for more information.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building Java Archive (<filename>.jar</filename>) Files: the &b-Jar; Builder</title>
+
+ <para>
+
+ After building the class files,
+ it's common to collect them into
+ a Java archive (<filename>.jar</filename>) file,
+ which you do by calling the &b-link-Jar; Builder method.
+ If you want to just collect all of the
+ class files within a subdirectory,
+ you can just specify that subdirectory
+ as the &b-Jar; source:
+
+ </para>
+
+ <scons_example name="jar1">
+ <file name="SConstruct" printme="1">
+ Java(target = 'classes', source = 'src')
+ Jar(target = 'test.jar', source = 'classes')
+ </file>
+ <file name="src/Example1.java">
+ public class Example1
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ <file name="src/Example2.java">
+ public class Example2
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ <file name="src/Example3.java">
+ public class Example3
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; will then pass that directory
+ to the &jar; command,
+ which will collect all of the underlying
+ <filename>.class</filename> files:
+
+ </para>
+
+ <scons_output example="jar1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If you want to keep all of the
+ <filename>.class</filename> files
+ for multiple programs in one location,
+ and only archive some of them in
+ each <filename>.jar</filename> file,
+ you can pass the &b-Jar; builder a
+ list of files as its source.
+ It's extremely simple to create multiple
+ <filename>.jar</filename> files this way,
+ using the lists of target class files created
+ by calls to the &b-link-Java; builder
+ as sources to the various &b-Jar; calls:
+
+ </para>
+
+ <scons_example name="jar2">
+ <file name="SConstruct" printme="1">
+ prog1_class_files = Java(target = 'classes', source = 'prog1')
+ prog2_class_files = Java(target = 'classes', source = 'prog2')
+ Jar(target = 'prog1.jar', source = prog1_class_files)
+ Jar(target = 'prog2.jar', source = prog2_class_files)
+ </file>
+ <file name="prog1/Example1.java">
+ public class Example1
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ <file name="prog1/Example2.java">
+ public class Example2
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ <file name="prog2/Example3.java">
+ public class Example3
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ <file name="prog2/Example4.java">
+ public class Example4
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ </scons_example>
+
+ <para>
+
+ This will then create
+ <filename>prog1.jar</filename>
+ and <filename>prog2.jar</filename>
+ next to the subdirectories
+ that contain their <filename>.java</filename> files:
+
+ </para>
+
+ <scons_output example="jar2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Building C Header and Stub Files: the &b-JavaH; Builder</title>
+
+ <para>
+
+ You can generate C header and source files
+ for implementing native methods,
+ by using the &b-link-JavaH; Builder.
+ There are several ways of using the &JavaH Builder.
+ One typical invocation might look like:
+
+ </para>
+
+ <scons_example name="javah">
+ <file name="SConstruct" printme="1">
+ classes = Java(target = 'classes', source = 'src/pkg/sub')
+ JavaH(target = 'native', source = classes)
+ </file>
+ <file name="src/pkg/sub/Example1.java">
+ package pkg.sub;
+ public class Example1
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ <file name="src/pkg/sub/Example2.java">
+ package pkg.sub;
+ public class Example2
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ <file name="src/pkg/sub/Example3.java">
+ package pkg.sub;
+ public class Example3
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ </scons_example>
+
+ <para>
+
+ The source is a list of class files generated by the
+ call to the &b-link-Java; Builder,
+ and the target is the output directory in
+ which we want the C header files placed.
+ The target
+ gets converted into the <option>-d</option>
+ when &SCons; runs &javah;:
+
+ </para>
+
+ <scons_output example="javah">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In this case,
+ the call to &javah;
+ will generate the header files
+ <filename>native/pkg_sub_Example1.h</filename>,
+ <filename>native/pkg_sub_Example2.h</filename>
+ and
+ <filename>native/pkg_sub_Example3.h</filename>.
+ Notice that &SCons; remembered that the class
+ files were generated with a target directory of
+ <filename>classes</filename>,
+ and that it then specified that target directory
+ as the <option>-classpath</option> option
+ to the call to &javah;.
+
+ </para>
+
+ <para>
+
+ Although it's more convenient to use
+ the list of class files returned by
+ the &b-Java; Builder
+ as the source of a call to the &b-JavaH; Builder,
+ you <emphasis>can</emphasis>
+ specify the list of class files
+ by hand, if you prefer.
+ If you do,
+ you need to set the
+ &cv-link-JAVACLASSDIR; construction variable
+ when calling &b-JavaH;:
+
+ </para>
+
+ <scons_example name="JAVACLASSDIR">
+ <file name="SConstruct" printme="1">
+ Java(target = 'classes', source = 'src/pkg/sub')
+ class_file_list = ['classes/pkg/sub/Example1.class',
+ 'classes/pkg/sub/Example2.class',
+ 'classes/pkg/sub/Example3.class']
+ JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes')
+ </file>
+ <file name="src/pkg/sub/Example1.java">
+ package pkg.sub;
+ public class Example1
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ <file name="src/pkg/sub/Example2.java">
+ package pkg.sub;
+ public class Example2
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ <file name="src/pkg/sub/Example3.java">
+ package pkg.sub;
+ public class Example3
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ </scons_example>
+
+ <para>
+
+ The &cv-JAVACLASSDIR; value then
+ gets converted into the <option>-classpath</option>
+ when &SCons; runs &javah;:
+
+ </para>
+
+ <scons_output example="JAVACLASSDIR">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Lastly, if you don't want a separate header file
+ generated for each source file,
+ you can specify an explicit File Node
+ as the target of the &b-JavaH; Builder:
+
+ </para>
+
+ <scons_example name="javah_file">
+ <file name="SConstruct" printme="1">
+ classes = Java(target = 'classes', source = 'src/pkg/sub')
+ JavaH(target = File('native.h'), source = classes)
+ </file>
+ <file name="src/pkg/sub/Example1.java">
+ package pkg.sub;
+ public class Example1
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ <file name="src/pkg/sub/Example2.java">
+ package pkg.sub;
+ public class Example2
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ <file name="src/pkg/sub/Example3.java">
+ package pkg.sub;
+ public class Example3
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Because &SCons; assumes by default
+ that the target of the &b-JavaH; builder is a directory,
+ you need to use the &File; function
+ to make sure that &SCons; doesn't
+ create a directory named <filename>native.h</filename>.
+ When a file is used, though,
+ &SCons; correctly converts the file name
+ into the &javah; <option>-o</option> option:
+
+ </para>
+
+ <scons_output example="javah_file">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Building RMI Stub and Skeleton Class Files: the &b-RMIC; Builder</title>
+
+ <para>
+
+ You can generate Remote Method Invocation stubs
+ by using the &b-link-RMIC; Builder.
+ The source is a list of directories,
+ typically returned by a call to the &b-link-Java; Builder,
+ and the target is an output directory
+ where the <filename>_Stub.class</filename>
+ and <filename>_Skel.class</filename> files will
+ be placed:
+
+ </para>
+
+ <scons_example name="RMIC">
+ <file name="SConstruct" printme="1">
+ classes = Java(target = 'classes', source = 'src/pkg/sub')
+ RMIC(target = 'outdir', source = classes)
+ </file>
+ <file name="src/pkg/sub/Example1.java">
+ package pkg.sub;
+ public class Example1
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ <file name="src/pkg/sub/Example2.java">
+ package pkg.sub;
+ public class Example2
+ {
+ public static void main(String[] args)
+ {
+ }
+ }
+ </file>
+ </scons_example>
+
+ <para>
+
+ As it did with the &b-link-JavaH; Builder,
+ &SCons; remembers the class directory
+ and passes it as the <option>-classpath</option> option
+ to &rmic:
+
+ </para>
+
+ <scons_output example="RMIC">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ This example would generate the files
+ <filename>outdir/pkg/sub/Example1_Skel.class</filename>,
+ <filename>outdir/pkg/sub/Example1_Stub.class</filename>,
+ <filename>outdir/pkg/sub/Example2_Skel.class</filename> and
+ <filename>outdir/pkg/sub/Example2_Stub.class</filename>.
+
+ </para>
+
+ </section>
diff --git a/doc/user/java.xml b/doc/user/java.xml
new file mode 100644
index 0000000..8198b65
--- /dev/null
+++ b/doc/user/java.xml
@@ -0,0 +1,433 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ So far, we've been using examples of
+ building C and C++ programs
+ to demonstrate the features of &SCons;.
+ &SCons; also supports building Java programs,
+ but Java builds are handled slightly differently,
+ which reflects the ways in which
+ the Java compiler and tools
+ build programs differently than
+ other languages' tool chains.
+
+ </para>
+
+ <section>
+ <title>Building Java Class Files: the &b-Java; Builder</title>
+
+ <para>
+
+ The basic activity when programming in Java,
+ of course, is to take one or more <filename>.java</filename> files
+ containing Java source code
+ and to call the Java compiler
+ to turn them into one or more
+ <filename>.class</filename> files.
+ In &SCons;, you do this
+ by giving the &b-link-Java; Builder
+ a target directory in which
+ to put the <filename>.class</filename> files,
+ and a source directory that contains
+ the <filename>.java</filename> files:
+
+ </para>
+
+ <programlisting>
+ Java('classes', 'src')
+ </programlisting>
+
+ <para>
+
+ If the <filename>src</filename> directory contains
+ three <filename>.java</filename> source files,
+ then running &SCons; might look like this:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java
+ </screen>
+
+ <para>
+
+ &SCons; will actually search the <filename>src</filename>
+ directory tree for all of the <filename>.java</filename> files.
+ The Java compiler will then create the
+ necessary class files in the <filename>classes</filename> subdirectory,
+ based on the class names found in the <filename>.java</filename> files.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>How &SCons; Handles Java Dependencies</title>
+
+ <para>
+
+ In addition to searching the source directory for
+ <filename>.java</filename> files,
+ &SCons; actually runs the <filename>.java</filename> files
+ through a stripped-down Java parser that figures out
+ what classes are defined.
+ In other words, &SCons; knows,
+ without you having to tell it,
+ what <filename>.class</filename> files
+ will be produced by the &javac; call.
+ So our one-liner example from the preceding section:
+
+ </para>
+
+ <programlisting>
+ Java('classes', 'src')
+ </programlisting>
+
+ <para>
+
+ Will not only tell you reliably
+ that the <filename>.class</filename> files
+ in the <filename>classes</filename> subdirectory
+ are up-to-date:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java
+ % <userinput>scons -Q classes</userinput>
+ scons: `classes' is up to date.
+ </screen>
+
+ <para>
+
+ But it will also remove all of the generated
+ <filename>.class</filename> files,
+ even for inner classes,
+ without you having to specify them manually.
+ For example, if our
+ <filename>Example1.java</filename>
+ and
+ <filename>Example3.java</filename>
+ files both define additional classes,
+ and the class defined in <filename>Example2.java</filename>
+ has an inner class,
+ running <userinput>scons -c</userinput>
+ will clean up all of those <filename>.class</filename> files
+ as well:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java
+ % <userinput>scons -Q -c classes</userinput>
+ Removed classes/Example1.class
+ Removed classes/AdditionalClass1.class
+ Removed classes/Example2$Inner2.class
+ Removed classes/Example2.class
+ Removed classes/Example3.class
+ Removed classes/AdditionalClass3.class
+ </screen>
+
+ <para>
+
+ To ensure correct handling of <filename>.class</filename>
+ dependencies in all cases, you need to tell &SCons; which Java
+ version is being used. This is needed because Java 1.5 changed
+ the <filename>.class</filename> file names for nested anonymous
+ inner classes. Use the <varname>JAVAVERSION</varname> construction
+ variable to specify the version in use. With Java 1.6, the
+ one-liner example can then be defined like this:
+
+ </para>
+
+ <programlisting>
+ Java('classes', 'src', JAVAVERSION='1.6')
+ </programlisting>
+
+ <para>
+ See <varname>JAVAVERSION</varname> in the man page for more information.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building Java Archive (<filename>.jar</filename>) Files: the &b-Jar; Builder</title>
+
+ <para>
+
+ After building the class files,
+ it's common to collect them into
+ a Java archive (<filename>.jar</filename>) file,
+ which you do by calling the &b-link-Jar; Builder method.
+ If you want to just collect all of the
+ class files within a subdirectory,
+ you can just specify that subdirectory
+ as the &b-Jar; source:
+
+ </para>
+
+ <programlisting>
+ Java(target = 'classes', source = 'src')
+ Jar(target = 'test.jar', source = 'classes')
+ </programlisting>
+
+ <para>
+
+ &SCons; will then pass that directory
+ to the &jar; command,
+ which will collect all of the underlying
+ <filename>.class</filename> files:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java
+ jar cf test.jar classes
+ </screen>
+
+ <para>
+
+ If you want to keep all of the
+ <filename>.class</filename> files
+ for multiple programs in one location,
+ and only archive some of them in
+ each <filename>.jar</filename> file,
+ you can pass the &b-Jar; builder a
+ list of files as its source.
+ It's extremely simple to create multiple
+ <filename>.jar</filename> files this way,
+ using the lists of target class files created
+ by calls to the &b-link-Java; builder
+ as sources to the various &b-Jar; calls:
+
+ </para>
+
+ <programlisting>
+ prog1_class_files = Java(target = 'classes', source = 'prog1')
+ prog2_class_files = Java(target = 'classes', source = 'prog2')
+ Jar(target = 'prog1.jar', source = prog1_class_files)
+ Jar(target = 'prog2.jar', source = prog2_class_files)
+ </programlisting>
+
+ <para>
+
+ This will then create
+ <filename>prog1.jar</filename>
+ and <filename>prog2.jar</filename>
+ next to the subdirectories
+ that contain their <filename>.java</filename> files:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ javac -d classes -sourcepath prog1 prog1/Example1.java prog1/Example2.java
+ javac -d classes -sourcepath prog2 prog2/Example3.java prog2/Example4.java
+ jar cf prog1.jar -C classes Example1.class -C classes Example2.class
+ jar cf prog2.jar -C classes Example3.class -C classes Example4.class
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Building C Header and Stub Files: the &b-JavaH; Builder</title>
+
+ <para>
+
+ You can generate C header and source files
+ for implementing native methods,
+ by using the &b-link-JavaH; Builder.
+ There are several ways of using the &JavaH; Builder.
+ One typical invocation might look like:
+
+ </para>
+
+ <programlisting>
+ classes = Java(target = 'classes', source = 'src/pkg/sub')
+ JavaH(target = 'native', source = classes)
+ </programlisting>
+
+ <para>
+
+ The source is a list of class files generated by the
+ call to the &b-link-Java; Builder,
+ and the target is the output directory in
+ which we want the C header files placed.
+ The target
+ gets converted into the <option>-d</option>
+ when &SCons; runs &javah;:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java
+ javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3
+ </screen>
+
+ <para>
+
+ In this case,
+ the call to &javah;
+ will generate the header files
+ <filename>native/pkg_sub_Example1.h</filename>,
+ <filename>native/pkg_sub_Example2.h</filename>
+ and
+ <filename>native/pkg_sub_Example3.h</filename>.
+ Notice that &SCons; remembered that the class
+ files were generated with a target directory of
+ <filename>classes</filename>,
+ and that it then specified that target directory
+ as the <option>-classpath</option> option
+ to the call to &javah;.
+
+ </para>
+
+ <para>
+
+ Although it's more convenient to use
+ the list of class files returned by
+ the &b-Java; Builder
+ as the source of a call to the &b-JavaH; Builder,
+ you <emphasis>can</emphasis>
+ specify the list of class files
+ by hand, if you prefer.
+ If you do,
+ you need to set the
+ &cv-link-JAVACLASSDIR; construction variable
+ when calling &b-JavaH;:
+
+ </para>
+
+ <programlisting>
+ Java(target = 'classes', source = 'src/pkg/sub')
+ class_file_list = ['classes/pkg/sub/Example1.class',
+ 'classes/pkg/sub/Example2.class',
+ 'classes/pkg/sub/Example3.class']
+ JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes')
+ </programlisting>
+
+ <para>
+
+ The &cv-JAVACLASSDIR; value then
+ gets converted into the <option>-classpath</option>
+ when &SCons; runs &javah;:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java
+ javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3
+ </screen>
+
+ <para>
+
+ Lastly, if you don't want a separate header file
+ generated for each source file,
+ you can specify an explicit File Node
+ as the target of the &b-JavaH; Builder:
+
+ </para>
+
+ <programlisting>
+ classes = Java(target = 'classes', source = 'src/pkg/sub')
+ JavaH(target = File('native.h'), source = classes)
+ </programlisting>
+
+ <para>
+
+ Because &SCons; assumes by default
+ that the target of the &b-JavaH; builder is a directory,
+ you need to use the &File; function
+ to make sure that &SCons; doesn't
+ create a directory named <filename>native.h</filename>.
+ When a file is used, though,
+ &SCons; correctly converts the file name
+ into the &javah; <option>-o</option> option:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java
+ javah -o native.h -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Building RMI Stub and Skeleton Class Files: the &b-RMIC; Builder</title>
+
+ <para>
+
+ You can generate Remote Method Invocation stubs
+ by using the &b-link-RMIC; Builder.
+ The source is a list of directories,
+ typically returned by a call to the &b-link-Java; Builder,
+ and the target is an output directory
+ where the <filename>_Stub.class</filename>
+ and <filename>_Skel.class</filename> files will
+ be placed:
+
+ </para>
+
+ <programlisting>
+ classes = Java(target = 'classes', source = 'src/pkg/sub')
+ RMIC(target = 'outdir', source = classes)
+ </programlisting>
+
+ <para>
+
+ As it did with the &b-link-JavaH; Builder,
+ &SCons; remembers the class directory
+ and passes it as the <option>-classpath</option> option
+ to &rmic;:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java
+ rmic -d outdir -classpath classes pkg.sub.Example1 pkg.sub.Example2
+ </screen>
+
+ <para>
+
+ This example would generate the files
+ <filename>outdir/pkg/sub/Example1_Skel.class</filename>,
+ <filename>outdir/pkg/sub/Example1_Stub.class</filename>,
+ <filename>outdir/pkg/sub/Example2_Skel.class</filename> and
+ <filename>outdir/pkg/sub/Example2_Stub.class</filename>.
+
+ </para>
+
+ </section>
diff --git a/doc/user/less-simple.in b/doc/user/less-simple.in
new file mode 100644
index 0000000..e19ba13
--- /dev/null
+++ b/doc/user/less-simple.in
@@ -0,0 +1,623 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ In this chapter,
+ you will see several examples of
+ very simple build configurations using &SCons;,
+ which will demonstrate how easy
+ it is to use &SCons; to
+ build programs from several different programming languages
+ on different types of systems.
+
+ </para>
+
+ <section>
+ <title>Specifying the Name of the Target (Output) File</title>
+
+ <para>
+
+ You've seen that when you call the &b-link-Program; builder method,
+ it builds the resulting program with the same
+ base name as the source file.
+ That is, the following call to build an
+ executable program from the &hello_c; source file
+ will build an executable program named &hello; on POSIX systems,
+ and an executable program named &hello_exe; on Windows systems:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ If you want to build a program with
+ a different name than the base of the source file name,
+ you simply put the target file name
+ to the left of the source file name:
+
+ </para>
+
+ <scons_example name="target">
+ <file name="SConstruct" printme="1">
+ Program('new_hello', 'hello.c')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ (&SCons; requires the target file name first,
+ followed by the source file name,
+ so that the order mimics that of an
+ assignment statement in most programming languages,
+ including Python:
+ <literal>"program = source files"</literal>.)
+
+ </para>
+
+ <para>
+
+ Now &SCons; will build an executable program
+ named &new_hello; when run on a POSIX system:
+
+ </para>
+
+ <scons_output example="target" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And &SCons; will build an executable program
+ named &new_hello_exe; when run on a Windows system:
+
+ </para>
+
+ <scons_output example="target" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Compiling Multiple Source Files</title>
+
+ <para>
+
+ You've just seen how to configure &SCons;
+ to compile a program from a single source file.
+ It's more common, of course,
+ that you'll need to build a program from
+ many input source files, not just one.
+ To do this, you need to put the
+ source files in a Python list
+ (enclosed in square brackets),
+ like so:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ Program(['prog.c', 'file1.c', 'file2.c'])
+ </file>
+ <file name="prog.c">
+ int main() { printf("prog.c\n"); }
+ </file>
+ <file name="file1.c">
+ void file1() { printf("file1.c\n"); }
+ </file>
+ <file name="file2.c">
+ void file2() { printf("file2.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ A build of the above example would look like:
+
+ </para>
+
+ <scons_output example="ex2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice that &SCons;
+ deduces the output program name
+ from the first source file specified
+ in the list--that is,
+ because the first source file was &prog_c;,
+ &SCons; will name the resulting program &prog;
+ (or &prog_exe; on a Windows system).
+ If you want to specify a different program name,
+ then (as we've seen in the previous section)
+ you slide the list of source files
+ over to the right
+ to make room for the output program file name.
+ (&SCons; puts the output file name to the left
+ of the source file names
+ so that the order mimics that of an
+ assignment statement: "program = source files".)
+ This makes our example:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct" printme="1">
+ Program('program', ['prog.c', 'file1.c', 'file2.c'])
+ </file>
+ <file name="prog.c">
+ int main() { printf("prog.c\n"); }
+ </file>
+ <file name="file1.c">
+ void file1() { printf("file1.c\n"); }
+ </file>
+ <file name="file2.c">
+ void file2() { printf("file2.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ On Linux, a build of this example would look like:
+
+ </para>
+
+ <scons_output example="ex3" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Or on Windows:
+
+ </para>
+
+ <scons_output example="ex3" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Making a list of files with &Glob;</title>
+
+ <para>
+
+ You can also use the &Glob; function to find all files matching a
+ certain template, using the standard shell pattern matching
+ characters <literal>*</literal>, <literal>?</literal>
+ and <literal>[abc]</literal> to match any of
+ <literal>a</literal>, <literal>b</literal> or <literal>c</literal>.
+ <literal>[!abc]</literal> is also supported,
+ to match any character <emphasis>except</emphasis>
+ <literal>a</literal>, <literal>b</literal> or <literal>c</literal>.
+ This makes many multi-source-file builds quite easy:
+
+ </para>
+
+ <sconstruct>
+ Program('program', Glob('*.c'))
+ </sconstruct>
+
+ <para>
+
+ The SCons man page has more details on using &Glob;
+ with variant directories
+ (see <xref linkend="chap-variants"></xref>, below)
+ and repositories
+ (see <xref linkend="chap-repositories"></xref>, below),
+ and returning strings rather than Nodes.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Specifying Single Files Vs. Lists of Files</title>
+
+ <para>
+
+ We've now shown you two ways to specify
+ the source for a program,
+ one with a list of files:
+
+ </para>
+
+ <sconstruct>
+ Program('hello', ['file1.c', 'file2.c'])
+ </sconstruct>
+
+ <para>
+
+ And one with a single file:
+
+ </para>
+
+ <sconstruct>
+ Program('hello', 'hello.c')
+ </sconstruct>
+
+ <para>
+
+ You could actually put a single file name in a list, too,
+ which you might prefer just for the sake of consistency:
+
+ </para>
+
+ <sconstruct>
+ Program('hello', ['hello.c'])
+ </sconstruct>
+
+ <para>
+
+ &SCons; functions will accept a single file name in either form.
+ In fact, internally, &SCons; treats all input as lists of files,
+ but allows you to omit the square brackets
+ to cut down a little on the typing
+ when there's only a single file name.
+
+ </para>
+
+ <important>
+
+ <para>
+
+ Although &SCons; functions
+ are forgiving about whether or not you
+ use a string vs. a list for a single file name,
+ Python itself is more strict about
+ treating lists and strings differently.
+ So where &SCons; allows either
+ a string or list:
+
+ </para>
+
+ <sconstruct>
+ # The following two calls both work correctly:
+ Program('program1', 'program1.c')
+ Program('program2', ['program2.c'])
+ </sconstruct>
+
+ <para>
+
+ Trying to do "Python things" that mix strings and
+ lists will cause errors or lead to incorrect results:
+
+ </para>
+
+ <sconstruct>
+ common_sources = ['file1.c', 'file2.c']
+
+ # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR
+ # BECAUSE IT TRIES TO ADD A STRING TO A LIST:
+ Program('program1', common_sources + 'program1.c')
+
+ # The following works correctly, because it's adding two
+ # lists together to make another list.
+ Program('program2', common_sources + ['program2.c'])
+ </sconstruct>
+
+ </important>
+
+ </section>
+
+ <section>
+ <title>Making Lists of Files Easier to Read</title>
+
+ <para>
+
+ One drawback to the use of a Python list
+ for source files is that
+ each file name must be enclosed in quotes
+ (either single quotes or double quotes).
+ This can get cumbersome and difficult to read
+ when the list of file names is long.
+ Fortunately, &SCons; and Python provide a number of ways
+ to make sure that
+ the &SConstruct; file stays easy to read.
+
+ </para>
+
+ <para>
+
+ To make long lists of file names
+ easier to deal with, &SCons; provides a
+ &Split; function
+ that takes a quoted list of file names,
+ with the names separated by spaces or other white-space characters,
+ and turns it into a list of separate file names.
+ Using the &Split; function turns the
+ previous example into:
+
+ </para>
+
+ <programlisting>
+ Program('program', Split('main.c file1.c file2.c'))
+ </programlisting>
+
+ <para>
+
+ (If you're already familiar with Python,
+ you'll have realized that this is similar to the
+ <function>split()</function> method
+ in the Python standard <function>string</function> module.
+ Unlike the <function>string.split()</function> method,
+ however, the &Split; function
+ does not require a string as input
+ and will wrap up a single non-string object in a list,
+ or return its argument untouched if it's already a list.
+ This comes in handy as a way to make sure
+ arbitrary values can be passed to &SCons; functions
+ without having to check the type of the variable by hand.)
+
+ </para>
+
+ <para>
+
+ Putting the call to the &Split; function
+ inside the &b-Program; call
+ can also be a little unwieldy.
+ A more readable alternative is to
+ assign the output from the &Split; call
+ to a variable name,
+ and then use the variable when calling the
+ &b-Program; function:
+
+ </para>
+
+ <programlisting>
+ src_files = Split('main.c file1.c file2.c')
+ Program('program', src_files)
+ </programlisting>
+
+ <para>
+
+ Lastly, the &Split; function
+ doesn't care how much white space separates
+ the file names in the quoted string.
+ This allows you to create lists of file
+ names that span multiple lines,
+ which often makes for easier editing:
+
+ </para>
+
+ <programlisting>
+ src_files = Split("""main.c
+ file1.c
+ file2.c""")
+ Program('program', src_files)
+ </programlisting>
+
+ <para>
+
+ (Note in this example that we used
+ the Python "triple-quote" syntax,
+ which allows a string to contain
+ multiple lines.
+ The three quotes can be either
+ single or double quotes.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Keyword Arguments</title>
+
+ <para>
+
+ &SCons; also allows you to identify
+ the output file and input source files
+ using Python keyword arguments.
+ The output file is known as the
+ <emphasis>target</emphasis>,
+ and the source file(s) are known (logically enough) as the
+ <emphasis>source</emphasis>.
+ The Python syntax for this is:
+
+ </para>
+
+ <programlisting>
+ src_files = Split('main.c file1.c file2.c')
+ Program(target = 'program', source = src_files)
+ </programlisting>
+
+ <para>
+
+ Because the keywords explicitly identify
+ what each argument is,
+ you can actually reverse the order if you prefer:
+
+ </para>
+
+ <programlisting>
+ src_files = Split('main.c file1.c file2.c')
+ Program(source = src_files, target = 'program')
+ </programlisting>
+
+ <para>
+
+ Whether or not you choose to use keyword arguments
+ to identify the target and source files,
+ and the order in which you specify them
+ when using keywords,
+ are purely personal choices;
+ &SCons; functions the same regardless.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Compiling Multiple Programs</title>
+
+ <para>
+
+ In order to compile multiple programs
+ within the same &SConstruct; file,
+ simply call the &Program; method
+ multiple times,
+ once for each program you need to build:
+
+ </para>
+
+ <scons_example name="ex4">
+ <file name="SConstruct" printme="1">
+ Program('foo.c')
+ Program('bar', ['bar1.c', 'bar2.c'])
+ </file>
+ <file name="foo.c">
+ int main() { printf("foo.c\n"); }
+ </file>
+ <file name="bar1.c">
+ int main() { printf("bar1.c\n"); }
+ </file>
+ <file name="bar2.c">
+ void bar2() { printf("bar2.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; would then build the programs as follows:
+
+ </para>
+
+ <scons_output example="ex4">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice that &SCons; does not necessarily build the
+ programs in the same order in which you specify
+ them in the &SConstruct; file.
+ &SCons; does, however, recognize that
+ the individual object files must be built
+ before the resulting program can be built.
+ We'll discuss this in greater detail in
+ the "Dependencies" section, below.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Sharing Source Files Between Multiple Programs</title>
+
+ <para>
+
+ It's common to re-use code by sharing source files
+ between multiple programs.
+ One way to do this is to create a library
+ from the common source files,
+ which can then be linked into resulting programs.
+ (Creating libraries is discussed in
+ <xref linkend="chap-libraries"></xref>, below.)
+
+ </para>
+
+ <para>
+
+ A more straightforward, but perhaps less convenient,
+ way to share source files between multiple programs
+ is simply to include the common files
+ in the lists of source files for each program:
+
+ </para>
+
+ <scons_example name="ex5">
+ <file name="SConstruct" printme="1">
+ Program(Split('foo.c common1.c common2.c'))
+ Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
+ </file>
+ <file name="foo.c">
+ int main() { printf("foo.c\n"); }
+ </file>
+ <file name="bar1.c">
+ int main() { printf("bar1.c\n"); }
+ </file>
+ <file name="bar2.c">
+ int bar2() { printf("bar2.c\n"); }
+ </file>
+ <file name="common1.c">
+ void common1() { printf("common1.c\n"); }
+ </file>
+ <file name="common2.c">
+ void common22() { printf("common2.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; recognizes that the object files for
+ the &common1_c; and &common2_c; source files
+ each need to be built only once,
+ even though the resulting object files are
+ each linked in to both of the resulting executable programs:
+
+ </para>
+
+ <scons_output example="ex5">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If two or more programs
+ share a lot of common source files,
+ repeating the common files in the list for each program
+ can be a maintenance problem when you need to change the
+ list of common files.
+ You can simplify this by creating a separate Python list
+ to hold the common file names,
+ and concatenating it with other lists
+ using the Python &plus; operator:
+
+ </para>
+
+ <programlisting>
+ common = ['common1.c', 'common2.c']
+ foo_files = ['foo.c'] + common
+ bar_files = ['bar1.c', 'bar2.c'] + common
+ Program('foo', foo_files)
+ Program('bar', bar_files)
+ </programlisting>
+
+ <para>
+
+ This is functionally equivalent to the previous example.
+
+ </para>
+
+ </section>
diff --git a/doc/user/less-simple.xml b/doc/user/less-simple.xml
new file mode 100644
index 0000000..57c61e2
--- /dev/null
+++ b/doc/user/less-simple.xml
@@ -0,0 +1,608 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ In this chapter,
+ you will see several examples of
+ very simple build configurations using &SCons;,
+ which will demonstrate how easy
+ it is to use &SCons; to
+ build programs from several different programming languages
+ on different types of systems.
+
+ </para>
+
+ <section>
+ <title>Specifying the Name of the Target (Output) File</title>
+
+ <para>
+
+ You've seen that when you call the &b-link-Program; builder method,
+ it builds the resulting program with the same
+ base name as the source file.
+ That is, the following call to build an
+ executable program from the &hello_c; source file
+ will build an executable program named &hello; on POSIX systems,
+ and an executable program named &hello_exe; on Windows systems:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ If you want to build a program with
+ a different name than the base of the source file name,
+ you simply put the target file name
+ to the left of the source file name:
+
+ </para>
+
+ <programlisting>
+ Program('new_hello', 'hello.c')
+ </programlisting>
+
+ <para>
+
+ (&SCons; requires the target file name first,
+ followed by the source file name,
+ so that the order mimics that of an
+ assignment statement in most programming languages,
+ including Python:
+ <literal>"program = source files"</literal>.)
+
+ </para>
+
+ <para>
+
+ Now &SCons; will build an executable program
+ named &new_hello; when run on a POSIX system:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o new_hello hello.o
+ </screen>
+
+ <para>
+
+ And &SCons; will build an executable program
+ named &new_hello_exe; when run on a Windows system:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Fohello.obj /c hello.c /nologo
+ link /nologo /OUT:new_hello.exe hello.obj
+ </screen>
+
+ </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>
+
+ <programlisting>
+ Program(['prog.c', 'file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ A build of the above example would look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o file1.o -c file1.c
+ cc -o file2.o -c file2.c
+ cc -o prog.o -c prog.c
+ cc -o prog prog.o file1.o file2.o
+ </screen>
+
+ <para>
+
+ Notice that &SCons;
+ deduces the output program name
+ from the first source file specified
+ in the list--that is,
+ because the first source file was &prog_c;,
+ &SCons; will name the resulting program &prog;
+ (or &prog_exe; on a Windows system).
+ If you want to specify a different program name,
+ then (as we've seen in the previous section)
+ you slide the list of source files
+ over to the right
+ to make room for the output program file name.
+ (&SCons; puts the output file name to the left
+ of the source file names
+ so that the order mimics that of an
+ assignment statement: "program = source files".)
+ This makes our example:
+
+ </para>
+
+ <programlisting>
+ Program('program', ['prog.c', 'file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ On Linux, a build of this example would look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o file1.o -c file1.c
+ cc -o file2.o -c file2.c
+ cc -o prog.o -c prog.c
+ cc -o program prog.o file1.o file2.o
+ </screen>
+
+ <para>
+
+ Or on Windows:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Fofile1.obj /c file1.c /nologo
+ cl /Fofile2.obj /c file2.c /nologo
+ cl /Foprog.obj /c prog.c /nologo
+ link /nologo /OUT:program.exe prog.obj file1.obj file2.obj
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Making a list of files with &Glob;</title>
+
+ <para>
+
+ You can also use the &Glob; function to find all files matching a
+ certain template, using the standard shell pattern matching
+ characters <literal>*</literal>, <literal>?</literal>
+ and <literal>[abc]</literal> to match any of
+ <literal>a</literal>, <literal>b</literal> or <literal>c</literal>.
+ <literal>[!abc]</literal> is also supported,
+ to match any character <emphasis>except</emphasis>
+ <literal>a</literal>, <literal>b</literal> or <literal>c</literal>.
+ This makes many multi-source-file builds quite easy:
+
+ </para>
+
+ <programlisting>
+ Program('program', Glob('*.c'))
+ </programlisting>
+
+ <para>
+
+ The SCons man page has more details on using &Glob;
+ with variant directories
+ (see <xref linkend="chap-variants"></xref>, below)
+ and repositories
+ (see <xref linkend="chap-repositories"></xref>, below),
+ and returning strings rather than Nodes.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Specifying Single Files Vs. Lists of Files</title>
+
+ <para>
+
+ We've now shown you two ways to specify
+ the source for a program,
+ one with a list of files:
+
+ </para>
+
+ <programlisting>
+ Program('hello', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ And one with a single file:
+
+ </para>
+
+ <programlisting>
+ Program('hello', 'hello.c')
+ </programlisting>
+
+ <para>
+
+ You could actually put a single file name in a list, too,
+ which you might prefer just for the sake of consistency:
+
+ </para>
+
+ <programlisting>
+ Program('hello', ['hello.c'])
+ </programlisting>
+
+ <para>
+
+ &SCons; functions will accept a single file name in either form.
+ In fact, internally, &SCons; treats all input as lists of files,
+ but allows you to omit the square brackets
+ to cut down a little on the typing
+ when there's only a single file name.
+
+ </para>
+
+ <important>
+
+ <para>
+
+ Although &SCons; functions
+ are forgiving about whether or not you
+ use a string vs. a list for a single file name,
+ Python itself is more strict about
+ treating lists and strings differently.
+ So where &SCons; allows either
+ a string or list:
+
+ </para>
+
+ <programlisting>
+ # The following two calls both work correctly:
+ Program('program1', 'program1.c')
+ Program('program2', ['program2.c'])
+ </programlisting>
+
+ <para>
+
+ Trying to do "Python things" that mix strings and
+ lists will cause errors or lead to incorrect results:
+
+ </para>
+
+ <programlisting>
+ common_sources = ['file1.c', 'file2.c']
+
+ # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR
+ # BECAUSE IT TRIES TO ADD A STRING TO A LIST:
+ Program('program1', common_sources + 'program1.c')
+
+ # The following works correctly, because it's adding two
+ # lists together to make another list.
+ Program('program2', common_sources + ['program2.c'])
+ </programlisting>
+
+ </important>
+
+ </section>
+
+ <section>
+ <title>Making Lists of Files Easier to Read</title>
+
+ <para>
+
+ One drawback to the use of a Python list
+ for source files is that
+ each file name must be enclosed in quotes
+ (either single quotes or double quotes).
+ This can get cumbersome and difficult to read
+ when the list of file names is long.
+ Fortunately, &SCons; and Python provide a number of ways
+ to make sure that
+ the &SConstruct; file stays easy to read.
+
+ </para>
+
+ <para>
+
+ To make long lists of file names
+ easier to deal with, &SCons; provides a
+ &Split; function
+ that takes a quoted list of file names,
+ with the names separated by spaces or other white-space characters,
+ and turns it into a list of separate file names.
+ Using the &Split; function turns the
+ previous example into:
+
+ </para>
+
+ <programlisting>
+ Program('program', Split('main.c file1.c file2.c'))
+ </programlisting>
+
+ <para>
+
+ (If you're already familiar with Python,
+ you'll have realized that this is similar to the
+ <function>split()</function> method
+ in the Python standard <function>string</function> module.
+ Unlike the <function>string.split()</function> method,
+ however, the &Split; function
+ does not require a string as input
+ and will wrap up a single non-string object in a list,
+ or return its argument untouched if it's already a list.
+ This comes in handy as a way to make sure
+ arbitrary values can be passed to &SCons; functions
+ without having to check the type of the variable by hand.)
+
+ </para>
+
+ <para>
+
+ Putting the call to the &Split; function
+ inside the &b-Program; call
+ can also be a little unwieldy.
+ A more readable alternative is to
+ assign the output from the &Split; call
+ to a variable name,
+ and then use the variable when calling the
+ &b-Program; function:
+
+ </para>
+
+ <programlisting>
+ src_files = Split('main.c file1.c file2.c')
+ Program('program', src_files)
+ </programlisting>
+
+ <para>
+
+ Lastly, the &Split; function
+ doesn't care how much white space separates
+ the file names in the quoted string.
+ This allows you to create lists of file
+ names that span multiple lines,
+ which often makes for easier editing:
+
+ </para>
+
+ <programlisting>
+ src_files = Split("""main.c
+ file1.c
+ file2.c""")
+ Program('program', src_files)
+ </programlisting>
+
+ <para>
+
+ (Note in this example that we used
+ the Python "triple-quote" syntax,
+ which allows a string to contain
+ multiple lines.
+ The three quotes can be either
+ single or double quotes.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Keyword Arguments</title>
+
+ <para>
+
+ &SCons; also allows you to identify
+ the output file and input source files
+ using Python keyword arguments.
+ The output file is known as the
+ <emphasis>target</emphasis>,
+ and the source file(s) are known (logically enough) as the
+ <emphasis>source</emphasis>.
+ The Python syntax for this is:
+
+ </para>
+
+ <programlisting>
+ src_files = Split('main.c file1.c file2.c')
+ Program(target = 'program', source = src_files)
+ </programlisting>
+
+ <para>
+
+ Because the keywords explicitly identify
+ what each argument is,
+ you can actually reverse the order if you prefer:
+
+ </para>
+
+ <programlisting>
+ src_files = Split('main.c file1.c file2.c')
+ Program(source = src_files, target = 'program')
+ </programlisting>
+
+ <para>
+
+ Whether or not you choose to use keyword arguments
+ to identify the target and source files,
+ and the order in which you specify them
+ when using keywords,
+ are purely personal choices;
+ &SCons; functions the same regardless.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Compiling Multiple Programs</title>
+
+ <para>
+
+ In order to compile multiple programs
+ within the same &SConstruct; file,
+ simply call the &Program; method
+ multiple times,
+ once for each program you need to build:
+
+ </para>
+
+ <programlisting>
+ Program('foo.c')
+ Program('bar', ['bar1.c', 'bar2.c'])
+ </programlisting>
+
+ <para>
+
+ &SCons; would then build the programs as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o bar1.o -c bar1.c
+ cc -o bar2.o -c bar2.c
+ cc -o bar bar1.o bar2.o
+ cc -o foo.o -c foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <para>
+
+ Notice that &SCons; does not necessarily build the
+ programs in the same order in which you specify
+ them in the &SConstruct; file.
+ &SCons; does, however, recognize that
+ the individual object files must be built
+ before the resulting program can be built.
+ We'll discuss this in greater detail in
+ the "Dependencies" section, below.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Sharing Source Files Between Multiple Programs</title>
+
+ <para>
+
+ It's common to re-use code by sharing source files
+ between multiple programs.
+ One way to do this is to create a library
+ from the common source files,
+ which can then be linked into resulting programs.
+ (Creating libraries is discussed in
+ <xref linkend="chap-libraries"></xref>, below.)
+
+ </para>
+
+ <para>
+
+ A more straightforward, but perhaps less convenient,
+ way to share source files between multiple programs
+ is simply to include the common files
+ in the lists of source files for each program:
+
+ </para>
+
+ <programlisting>
+ Program(Split('foo.c common1.c common2.c'))
+ Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
+ </programlisting>
+
+ <para>
+
+ &SCons; recognizes that the object files for
+ the &common1_c; and &common2_c; source files
+ each need to be built only once,
+ even though the resulting object files are
+ each linked in to both of the resulting executable programs:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o bar1.o -c bar1.c
+ cc -o bar2.o -c bar2.c
+ cc -o common1.o -c common1.c
+ cc -o common2.o -c common2.c
+ cc -o bar bar1.o bar2.o common1.o common2.o
+ cc -o foo.o -c foo.c
+ cc -o foo foo.o common1.o common2.o
+ </screen>
+
+ <para>
+
+ If two or more programs
+ share a lot of common source files,
+ repeating the common files in the list for each program
+ can be a maintenance problem when you need to change the
+ list of common files.
+ You can simplify this by creating a separate Python list
+ to hold the common file names,
+ and concatenating it with other lists
+ using the Python &plus; operator:
+
+ </para>
+
+ <programlisting>
+ common = ['common1.c', 'common2.c']
+ foo_files = ['foo.c'] + common
+ bar_files = ['bar1.c', 'bar2.c'] + common
+ Program('foo', foo_files)
+ Program('bar', bar_files)
+ </programlisting>
+
+ <para>
+
+ This is functionally equivalent to the previous example.
+
+ </para>
+
+ </section>
diff --git a/doc/user/libraries.in b/doc/user/libraries.in
new file mode 100644
index 0000000..4cce091
--- /dev/null
+++ b/doc/user/libraries.in
@@ -0,0 +1,445 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ It's often useful to organize large software projects
+ by collecting parts of the software into one or more libraries.
+ &SCons; makes it easy to create libraries
+ and to use them in the programs.
+
+ </para>
+
+ <section>
+ <title>Building Libraries</title>
+
+ <para>
+
+ You build your own libraries by specifying &b-link-Library;
+ instead of &b-link-Program;:
+
+ </para>
+
+ <scons_example name="ex1" printme="1">
+ <file name="SConstruct" printme="1">
+ Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ </file>
+ <file name="f1.c">
+ void f1() { printf("f1.c\n"); }
+ </file>
+ <file name="f2.c">
+ void f2() { printf("f2.c\n"); }
+ </file>
+ <file name="f3.c">
+ void f3() { printf("f3.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; uses the appropriate library prefix and suffix for your system.
+ So on POSIX or Linux systems,
+ the above example would build as follows
+ (although &ranlib; may not be called on all systems):
+
+ </para>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ On a Windows system,
+ a build of the above example would look like:
+
+ </para>
+
+ <scons_output example="ex1" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The rules for the target name of the library
+ are similar to those for programs:
+ if you don't explicitly specify a target library name,
+ &SCons; will deduce one from the
+ name of the first source file specified,
+ and &SCons; will add an appropriate
+ file prefix and suffix if you leave them off.
+
+ </para>
+
+ <section>
+ <title>Building Libraries From Source Code or Object Files</title>
+
+ <para>
+
+ The previous example shows building a library from a
+ list of source files.
+ You can, however, also give the &b-link-Library; call
+ object files,
+ and it will correctly realize
+ In fact, you can arbitrarily mix source code files
+ and object files in the source list:
+
+ </para>
+
+ <scons_example name="objects" printme="1">
+ <file name="SConstruct" printme="1">
+ Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o'])
+ </file>
+ <file name="f1.c">
+ void f1() { printf("f1.c\n"); }
+ </file>
+ <file name="f2.o">
+ object file
+ </file>
+ <file name="f3.c">
+ void f3() { printf("f3.c\n"); }
+ </file>
+ <file name="f4.o">
+ object file
+ </file>
+ </scons_example>
+
+ <para>
+
+ And SCons realizes that only the source code files
+ must be compiled into object files
+ before creating the final library:
+
+ </para>
+
+ <scons_output example="objects" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Of course, in this example, the object files
+ must already exist for the build to succeed.
+ See <xref linkend="chap-nodes"></xref>, below,
+ for information about how you can
+ build object files explicitly
+ and include the built files in a library.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building Static Libraries Explicitly: the &b-StaticLibrary; Builder</title>
+
+ <para>
+
+ The &b-link-Library; function builds a traditional static library.
+ If you want to be explicit about the type of library being built,
+ you can use the synonym &b-link-StaticLibrary; function
+ instead of &b-Library;:
+
+ </para>
+
+ <scons_example name="StaticLibrary" printme="1">
+ <file name="SConstruct" printme="1">
+ StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
+ </file>
+ </scons_example>
+
+ <para>
+
+ There is no functional difference between the
+ &b-link-StaticLibrary; and &b-Library; functions.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building Shared (DLL) Libraries: the &b-SharedLibrary; Builder</title>
+
+ <para>
+
+ If you want to build a shared library (on POSIX systems)
+ or a DLL file (on Windows systems),
+ you use the &b-link-SharedLibrary; function:
+
+ </para>
+
+ <scons_example name="SharedLibrary" printme="1">
+ <file name="SConstruct" printme="1">
+ SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
+ </file>
+ <file name="f1.c">
+ void f1() { printf("f1.c\n"); }
+ </file>
+ <file name="f2.c">
+ void f2() { printf("f2.c\n"); }
+ </file>
+ <file name="f3.c">
+ void f3() { printf("f3.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ The output on POSIX:
+
+ </para>
+
+ <scons_output example="SharedLibrary" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And the output on Windows:
+
+ </para>
+
+ <scons_output example="SharedLibrary" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice again that &SCons; takes care of
+ building the output file correctly,
+ adding the <literal>-shared</literal> option
+ for a POSIX compilation,
+ and the <literal>/dll</literal> option on Windows.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Linking with Libraries</title>
+
+ <para>
+
+ Usually, you build a library
+ because you want to link it with one or more programs.
+ You link libraries with a program by specifying
+ the libraries in the &cv-link-LIBS; construction variable,
+ and by specifying the directory in which
+ the library will be found in the
+ &cv-link-LIBPATH; construction variable:
+
+ <!-- In the preceding paragraph, the "$" notation for
+ LIBS, LIBPATH etc. is used for the first time.
+ Maybe some words of explanation would be nice. -->
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.')
+ </file>
+ <file name="f1.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="f2.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="f3.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="prog.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Notice, of course, that you don't need to specify a library
+ prefix (like <literal>lib</literal>)
+ or suffix (like <literal>.a</literal> or <literal>.lib</literal>).
+ &SCons; uses the correct prefix or suffix for the current system.
+
+ </para>
+
+ <para>
+
+ On a POSIX or Linux system,
+ a build of the above example would look like:
+
+ </para>
+
+ <scons_output example="ex2" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ On a Windows system,
+ a build of the above example would look like:
+
+ </para>
+
+ <scons_output example="ex2" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ As usual, notice that &SCons; has taken care
+ of constructing the correct command lines
+ to link with the specified library on each system.
+
+ </para>
+
+ <para>
+
+ Note also that,
+ if you only have a single library to link with,
+ you can specify the library name in single string,
+ instead of a Python list,
+ so that:
+
+ </para>
+
+ <sconstruct>
+ Program('prog.c', LIBS='foo', LIBPATH='.')
+ </sconstruct>
+
+ <para>
+
+ is equivalent to:
+
+ </para>
+
+ <sconstruct>
+ Program('prog.c', LIBS=['foo'], LIBPATH='.')
+ </sconstruct>
+
+ <para>
+
+ This is similar to the way that &SCons;
+ handles either a string or a list to
+ specify a single source file.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Finding Libraries: the &cv-LIBPATH; Construction Variable</title>
+
+ <para>
+
+ By default, the linker will only look in
+ certain system-defined directories for libraries.
+ &SCons; knows how to look for libraries
+ in directories that you specify with the
+ &cv-link-LIBPATH; construction variable.
+ &cv-LIBPATH; consists of a list of
+ directory names, like so:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct" printme="1">
+ Program('prog.c', LIBS = 'm',
+ LIBPATH = ['/usr/lib', '/usr/local/lib'])
+ </file>
+ <file name="prog.c">
+ int main() { printf("prog.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Using a Python list is preferred because it's portable
+ across systems. Alternatively, you could put all of
+ the directory names in a single string, separated by the
+ system-specific path separator character:
+ a colon on POSIX systems:
+
+ </para>
+
+ <sconstruct>
+ LIBPATH = '/usr/lib:/usr/local/lib'
+ </sconstruct>
+
+ <para>
+
+ or a semi-colon on Windows systems:
+
+ </para>
+
+ <sconstruct>
+ LIBPATH = 'C:\\lib;D:\\lib'
+ </sconstruct>
+
+ <para>
+
+ (Note that Python requires that the backslash
+ separators in a Windows path name
+ be escaped within strings.)
+
+ </para>
+
+ <para>
+
+ When the linker is executed,
+ &SCons; will create appropriate flags
+ so that the linker will look for
+ libraries in the same directories as &SCons;.
+ So on a POSIX or Linux system,
+ a build of the above example would look like:
+
+ </para>
+
+ <scons_output example="ex3" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ On a Windows system,
+ a build of the above example would look like:
+
+ </para>
+
+ <scons_output example="ex3" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+ <!-- The link command is too wide in the PDF version.
+ There are some other examples of this throughout the document. -->
+
+ <para>
+
+ Note again that &SCons; has taken care of
+ the system-specific details of creating
+ the right command-line options.
+
+ </para>
+
+ </section>
diff --git a/doc/user/libraries.xml b/doc/user/libraries.xml
new file mode 100644
index 0000000..e3821ce
--- /dev/null
+++ b/doc/user/libraries.xml
@@ -0,0 +1,451 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ It's often useful to organize large software projects
+ by collecting parts of the software into one or more libraries.
+ &SCons; makes it easy to create libraries
+ and to use them in the programs.
+
+ </para>
+
+ <section>
+ <title>Building Libraries</title>
+
+ <para>
+
+ You build your own libraries by specifying &b-link-Library;
+ instead of &b-link-Program;:
+
+ </para>
+
+ <programlisting>
+ Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o f1.o -c f1.c
+ cc -o f2.o -c f2.c
+ cc -o f3.o -c f3.c
+ ar rc libfoo.a f1.o f2.o f3.o
+ ranlib libfoo.a
+ </screen>
+
+ <para>
+
+ On a Windows system,
+ a build of the above example would look like:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Fof1.obj /c f1.c /nologo
+ cl /Fof2.obj /c f2.c /nologo
+ cl /Fof3.obj /c f3.c /nologo
+ lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj
+ </screen>
+
+ <para>
+
+ The rules for the target name of the library
+ are similar to those for programs:
+ if you don't explicitly specify a target library name,
+ &SCons; will deduce one from the
+ name of the first source file specified,
+ and &SCons; will add an appropriate
+ file prefix and suffix if you leave them off.
+
+ </para>
+
+ <section>
+ <title>Building Libraries From Source Code or Object Files</title>
+
+ <para>
+
+ The previous example shows building a library from a
+ list of source files.
+ You can, however, also give the &b-link-Library; call
+ object files,
+ and it will correctly realize
+ In fact, you can arbitrarily mix source code files
+ and object files in the source list:
+
+ </para>
+
+ <programlisting>
+ Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o'])
+ </programlisting>
+
+ <para>
+
+ And SCons realizes that only the source code files
+ must be compiled into object files
+ before creating the final library:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o f1.o -c f1.c
+ cc -o f3.o -c f3.c
+ ar rc libfoo.a f1.o f2.o f3.o f4.o
+ ranlib libfoo.a
+ </screen>
+
+ <para>
+
+ Of course, in this example, the object files
+ must already exist for the build to succeed.
+ See <xref linkend="chap-nodes"></xref>, below,
+ for information about how you can
+ build object files explicitly
+ and include the built files in a library.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building Static Libraries Explicitly: the &b-StaticLibrary; Builder</title>
+
+ <para>
+
+ The &b-link-Library; function builds a traditional static library.
+ If you want to be explicit about the type of library being built,
+ you can use the synonym &b-link-StaticLibrary; function
+ instead of &b-Library;:
+
+ </para>
+
+ <programlisting>
+ StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
+ </programlisting>
+
+ <para>
+
+ There is no functional difference between the
+ &b-link-StaticLibrary; and &b-Library; functions.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building Shared (DLL) Libraries: the &b-SharedLibrary; Builder</title>
+
+ <para>
+
+ If you want to build a shared library (on POSIX systems)
+ or a DLL file (on Windows systems),
+ you use the &b-link-SharedLibrary; function:
+
+ </para>
+
+ <programlisting>
+ SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
+ </programlisting>
+
+ <para>
+
+ The output on POSIX:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o f1.os -c f1.c
+ cc -o f2.os -c f2.c
+ cc -o f3.os -c f3.c
+ cc -o libfoo.so -shared f1.os f2.os f3.os
+ </screen>
+
+ <para>
+
+ And the output on Windows:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Fof1.obj /c f1.c /nologo
+ cl /Fof2.obj /c f2.c /nologo
+ cl /Fof3.obj /c f3.c /nologo
+ link /nologo /dll /out:foo.dll /implib:foo.lib f1.obj f2.obj f3.obj
+ RegServerFunc(target, source, env)
+ </screen>
+
+ <para>
+
+ Notice again that &SCons; takes care of
+ building the output file correctly,
+ adding the <literal>-shared</literal> option
+ for a POSIX compilation,
+ and the <literal>/dll</literal> option on Windows.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Linking with Libraries</title>
+
+ <para>
+
+ Usually, you build a library
+ because you want to link it with one or more programs.
+ You link libraries with a program by specifying
+ the libraries in the &cv-link-LIBS; construction variable,
+ and by specifying the directory in which
+ the library will be found in the
+ &cv-link-LIBPATH; construction variable:
+
+ <!-- In the preceding paragraph, the "$" notation for
+ LIBS, LIBPATH etc. is used for the first time.
+ Maybe some words of explanation would be nice. -->
+
+ </para>
+
+ <programlisting>
+ Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.')
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o f1.o -c f1.c
+ cc -o f2.o -c f2.c
+ cc -o f3.o -c f3.c
+ ar rc libfoo.a f1.o f2.o f3.o
+ ranlib libfoo.a
+ cc -o prog.o -c prog.c
+ cc -o prog prog.o -L. -lfoo -lbar
+ </screen>
+
+ <para>
+
+ On a Windows system,
+ a build of the above example would look like:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Fof1.obj /c f1.c /nologo
+ cl /Fof2.obj /c f2.c /nologo
+ cl /Fof3.obj /c f3.c /nologo
+ lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj
+ cl /Foprog.obj /c prog.c /nologo
+ link /nologo /OUT:prog.exe /LIBPATH:. foo.lib bar.lib prog.obj
+ </screen>
+
+ <para>
+
+ As usual, notice that &SCons; has taken care
+ of constructing the correct command lines
+ to link with the specified library on each system.
+
+ </para>
+
+ <para>
+
+ Note also that,
+ if you only have a single library to link with,
+ you can specify the library name in single string,
+ instead of a Python list,
+ so that:
+
+ </para>
+
+ <programlisting>
+ Program('prog.c', LIBS='foo', LIBPATH='.')
+ </programlisting>
+
+ <para>
+
+ is equivalent to:
+
+ </para>
+
+ <programlisting>
+ Program('prog.c', LIBS=['foo'], LIBPATH='.')
+ </programlisting>
+
+ <para>
+
+ This is similar to the way that &SCons;
+ handles either a string or a list to
+ specify a single source file.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Finding Libraries: the &cv-LIBPATH; Construction Variable</title>
+
+ <para>
+
+ By default, the linker will only look in
+ certain system-defined directories for libraries.
+ &SCons; knows how to look for libraries
+ in directories that you specify with the
+ &cv-link-LIBPATH; construction variable.
+ &cv-LIBPATH; consists of a list of
+ directory names, like so:
+
+ </para>
+
+ <programlisting>
+ Program('prog.c', LIBS = 'm',
+ LIBPATH = ['/usr/lib', '/usr/local/lib'])
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ LIBPATH = '/usr/lib:/usr/local/lib'
+ </programlisting>
+
+ <para>
+
+ or a semi-colon on Windows systems:
+
+ </para>
+
+ <programlisting>
+ LIBPATH = 'C:\\lib;D:\\lib'
+ </programlisting>
+
+ <para>
+
+ (Note that Python requires that the backslash
+ separators in a Windows path name
+ be escaped within strings.)
+
+ </para>
+
+ <para>
+
+ When the linker is executed,
+ &SCons; will create appropriate flags
+ so that the linker will look for
+ libraries in the same directories as &SCons;.
+ So on a POSIX or Linux system,
+ a build of the above example would look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o prog.o -c prog.c
+ cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm
+ </screen>
+
+ <para>
+
+ On a Windows system,
+ a build of the above example would look like:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Foprog.obj /c prog.c /nologo
+ link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj
+ </screen>
+ <!-- The link command is too wide in the PDF version.
+ There are some other examples of this throughout the document. -->
+
+ <para>
+
+ Note again that &SCons; has taken care of
+ the system-specific details of creating
+ the right command-line options.
+
+ </para>
+
+ </section>
diff --git a/doc/user/main.in b/doc/user/main.in
new file mode 100644
index 0000000..949a90a
--- /dev/null
+++ b/doc/user/main.in
@@ -0,0 +1,385 @@
+<?xml version="1.0"?>
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+
+ <!ENTITY % version SYSTEM "../version.xml">
+ %version;
+
+ <!ENTITY % scons SYSTEM "../scons.mod">
+ %scons;
+
+ <!ENTITY % builders-mod SYSTEM "builders.mod">
+ %builders-mod;
+
+ <!ENTITY % tools-mod SYSTEM "tools.mod">
+ %tools-mod;
+
+ <!ENTITY % variables-mod SYSTEM "variables.mod">
+ %variables-mod;
+
+ <!ENTITY actions SYSTEM "actions.xml">
+ <!ENTITY alias SYSTEM "alias.xml">
+ <!ENTITY ant SYSTEM "ant.xml">
+ <!ENTITY build-install SYSTEM "build-install.xml">
+ <!ENTITY builders SYSTEM "builders.xml">
+ <!ENTITY builders-built-in SYSTEM "builders-built-in.xml">
+ <!ENTITY builders-commands SYSTEM "builders-commands.xml">
+ <!ENTITY builders-writing SYSTEM "builders-writing.xml">
+ <!ENTITY add-method SYSTEM "add-method.xml">
+ <!ENTITY caching SYSTEM "caching.xml">
+ <!ENTITY command-line SYSTEM "command-line.xml">
+ <!ENTITY copyright SYSTEM "copyright.xml">
+ <!ENTITY depends SYSTEM "depends.xml">
+ <!ENTITY environments SYSTEM "environments.xml">
+ <!ENTITY errors SYSTEM "errors.xml">
+ <!ENTITY example SYSTEM "example.xml">
+ <!ENTITY factories SYSTEM "factories.xml">
+ <!ENTITY file-removal SYSTEM "file-removal.xml">
+ <!ENTITY hierarchy SYSTEM "hierarchy.xml">
+ <!ENTITY java SYSTEM "java.xml">
+ <!ENTITY install SYSTEM "install.xml">
+ <!ENTITY less-simple SYSTEM "less-simple.xml">
+ <!ENTITY libraries SYSTEM "libraries.xml">
+ <!ENTITY make SYSTEM "make.xml">
+ <!ENTITY mergeflags SYSTEM "mergeflags.xml">
+ <!ENTITY misc SYSTEM "misc.xml">
+ <!ENTITY nodes SYSTEM "nodes.xml">
+ <!ENTITY output SYSTEM "output.xml">
+ <!ENTITY parseconfig SYSTEM "parseconfig.xml">
+ <!ENTITY parseflags SYSTEM "parseflags.xml">
+ <!ENTITY preface SYSTEM "preface.xml">
+ <!ENTITY python SYSTEM "python.xml">
+ <!ENTITY repositories SYSTEM "repositories.xml">
+ <!ENTITY run SYSTEM "run.xml">
+ <!ENTITY scanners SYSTEM "scanners.xml">
+ <!ENTITY sconf SYSTEM "sconf.xml">
+ <!ENTITY separate SYSTEM "separate.xml">
+ <!ENTITY simple SYSTEM "simple.xml">
+ <!ENTITY sourcecode SYSTEM "sourcecode.xml">
+ <!ENTITY tasks SYSTEM "tasks.xml">
+ <!ENTITY tools SYSTEM "tools.xml">
+ <!ENTITY troubleshoot SYSTEM "troubleshoot.xml">
+ <!ENTITY variables-xml SYSTEM "variables.xml">
+ <!ENTITY variants SYSTEM "variants.xml">
+
+ <!ENTITY builders-gen SYSTEM "builders.gen">
+ <!ENTITY tools-gen SYSTEM "tools.gen">
+ <!ENTITY variables-gen SYSTEM "variables.gen">
+
+]>
+
+ <!--
+
+ XXX FindFile()
+ XXX FindPathDirs()
+ XXX GetBuildPath()
+ XXX GetLaunchDir()
+
+ XXX ParseDepends()
+ XXX Platform()
+ XXX SConsignFile()
+ XXX Tools()
+
+ XXX GetOption('duplicate')
+ XXX SetOption('duplicate')
+ XXX - - duplicate=
+
+ XXX CheckTypeSize()
+
+ XXX - - diskcheck=
+
+ XXX - - warn=
+
+ -->
+
+<book>
+ <bookinfo>
+ <title>SCons User Guide &buildversion;</title>
+
+ <author>
+ <firstname>Steven</firstname>
+ <surname>Knight</surname>
+ </author>
+
+ <edition>Revision &buildrevision; (&builddate;)</edition>
+
+ <pubdate>2004, 2005, 2006, 2007, 2008</pubdate>
+
+ <copyright>
+ <year>2004, 2005, 2006, 2007, 2008</year>
+ <holder>Steven Knight</holder>
+ </copyright>
+
+ <legalnotice>
+ &copyright;
+ </legalnotice>
+
+ <releaseinfo>version &buildversion;</releaseinfo>
+
+ </bookinfo>
+
+ <preface id="chap-preface">
+ <title>Preface</title>
+ &preface;
+ </preface>
+
+ <chapter id="chap-build-install">
+ <title>Building and Installing &SCons;</title>
+ &build-install;
+ </chapter>
+
+ <chapter id="chap-simple">
+ <title>Simple Builds</title>
+ &simple;
+ </chapter>
+
+ <chapter id="chap-less-simple">
+ <title>Less Simple Things to Do With Builds</title>
+ &less-simple;
+ </chapter>
+
+ <chapter id="chap-libraries">
+ <title>Building and Linking with Libraries</title>
+ &libraries;
+ </chapter>
+
+ <chapter id="chap-nodes">
+ <title>Node Objects</title>
+ &nodes;
+ </chapter>
+
+ <chapter id="chap-depends">
+ <title>Dependencies</title>
+ &depends;
+ </chapter>
+
+ <chapter id="chap-environments">
+ <title>Environments</title>
+ &environments;
+ </chapter>
+
+ <!-- These next three sections should be combined into one chapter -->
+ <chapter id="chap-mergeflags">
+ <title>Merging Options into the Environment: the &MergeFlags; Function</title>
+ &mergeflags;
+ </chapter>
+ <chapter id="chap-parseflags">
+ <title>Separating Compile Arguments into their Variables: the &ParseFlags; Function</title>
+ &parseflags;
+ </chapter>
+ <chapter id="chap-parseconfig">
+ <title>Finding Installed Library Information: the &ParseConfig; Function</title>
+ &parseconfig;
+ </chapter>
+
+ <chapter id="chap-output">
+ <title>Controlling Build Output</title>
+ &output;
+ </chapter>
+
+ <chapter id="chap-command-line">
+ <title>Controlling a Build From the Command Line</title>
+ &command-line;
+ </chapter>
+
+ <chapter id="chap-install">
+ <title>Installing Files in Other Directories: the &Install; Builder</title>
+ &install;
+ </chapter>
+
+ <chapter id="chap-factories">
+ <title>Platform-Independent File System Manipulation</title>
+ &factories;
+ </chapter>
+
+ <chapter id="chap-file-removal">
+ <title>Controlling Removal of Targets</title>
+ &file-removal;
+ </chapter>
+
+ <chapter id="chap-hierarchical">
+ <title>Hierarchical Builds</title>
+ &hierarchy;
+ </chapter>
+
+ <chapter id="chap-separate">
+ <title>Separating Source and Build Directories</title>
+ &separate;
+ </chapter>
+
+ <chapter id="chap-variants">
+ <title>Variant Builds</title>
+ &variants;
+ </chapter>
+
+ <!--
+
+ <chapter id="chap-builders-built-in">
+ <title>Built-In Builders</title>
+ &builders-built-in;
+ </chapter>
+
+ -->
+
+ <chapter id="chap-builders-writing">
+ <title>Writing Your Own Builders</title>
+ &builders-writing;
+ </chapter>
+
+ <chapter id="chap-builders-commands">
+ <title>Not Writing a Builder: the &Command; Builder</title>
+ &builders-commands;
+ </chapter>
+
+ <chapter id="chap-add-method">
+ <title>Pseudo-Builders: the AddMethod function</title>
+ &add-method;
+ </chapter>
+
+ <!--
+
+ XXX Action()
+ XXX AddPostAction()
+ XXX AddPreAction()
+
+ <chapter id="chap-actions">
+ <title>&SCons; Actions</title>
+ &actions;
+ </chapter>
+
+ -->
+
+ <chapter id="chap-scanners">
+ <title>Writing Scanners</title>
+ &scanners;
+ </chapter>
+
+ <chapter id="chap-repositories">
+ <title>Building From Code Repositories</title>
+ &repositories;
+ </chapter>
+
+ <chapter id="chap-sconf">
+ <title>Multi-Platform Configuration (&Autoconf; Functionality)</title>
+ &sconf;
+ </chapter>
+
+ <!--
+
+ <chapter id="chap-sourcecode">
+ <title>Fetching Files From Source Code Management Systems</title>
+ &sourcecode;
+ </chapter>
+
+ -->
+
+ <chapter id="chap-caching">
+ <title>Caching Built Files</title>
+ &caching;
+ </chapter>
+
+ <chapter id="chap-alias">
+ <title>Alias Targets</title>
+ &alias;
+ </chapter>
+
+ <chapter id="chap-java">
+ <title>Java Builds</title>
+ &java;
+ </chapter>
+
+ <!--
+
+ <chapter id="chap-run">
+ <title>How to Run &SCons;</title>
+ &run;
+ </chapter>
+
+ -->
+
+ <chapter id="chap-misc">
+ <title>Miscellaneous Functionality</title>
+ &misc;
+ </chapter>
+
+ <chapter id="chap-troubleshooting">
+ <title>Troubleshooting</title>
+ &troubleshoot;
+ </chapter>
+
+ <appendix id="app-variables">
+ <title>Construction Variables</title>
+ &variables-xml;
+ </appendix>
+
+ <appendix id="app-builders">
+ <title>Builders</title>
+ &builders;
+ </appendix>
+
+ <appendix id="app-tools">
+ <title>Tools</title>
+ &tools;
+ </appendix>
+
+ <appendix id="app-tasks">
+ <title>Handling Common Tasks</title>
+ &tasks;
+ </appendix>
+
+ <!--
+
+ <appendix id="app-python">
+ <title>Python Overview</title>
+ &example;
+ </appendix>
+
+ <appendix id="app-example">
+ <title>Complex &SCons; Example</title>
+ &example;
+ </appendix>
+
+ <appendix id="app-make">
+ <title>Converting From Make</title>
+ &make;
+ </appendix>
+
+ <appendix id="app-cons">
+ <title>Converting From Cons</title>
+ &cons;
+ </appendix>
+
+ <appendix id="app-ant">
+ <title>Converting From Ant</title>
+ &ant;
+ </appendix>
+
+ -->
+
+</book>
diff --git a/doc/user/main.xml b/doc/user/main.xml
new file mode 100644
index 0000000..949a90a
--- /dev/null
+++ b/doc/user/main.xml
@@ -0,0 +1,385 @@
+<?xml version="1.0"?>
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+
+ <!ENTITY % version SYSTEM "../version.xml">
+ %version;
+
+ <!ENTITY % scons SYSTEM "../scons.mod">
+ %scons;
+
+ <!ENTITY % builders-mod SYSTEM "builders.mod">
+ %builders-mod;
+
+ <!ENTITY % tools-mod SYSTEM "tools.mod">
+ %tools-mod;
+
+ <!ENTITY % variables-mod SYSTEM "variables.mod">
+ %variables-mod;
+
+ <!ENTITY actions SYSTEM "actions.xml">
+ <!ENTITY alias SYSTEM "alias.xml">
+ <!ENTITY ant SYSTEM "ant.xml">
+ <!ENTITY build-install SYSTEM "build-install.xml">
+ <!ENTITY builders SYSTEM "builders.xml">
+ <!ENTITY builders-built-in SYSTEM "builders-built-in.xml">
+ <!ENTITY builders-commands SYSTEM "builders-commands.xml">
+ <!ENTITY builders-writing SYSTEM "builders-writing.xml">
+ <!ENTITY add-method SYSTEM "add-method.xml">
+ <!ENTITY caching SYSTEM "caching.xml">
+ <!ENTITY command-line SYSTEM "command-line.xml">
+ <!ENTITY copyright SYSTEM "copyright.xml">
+ <!ENTITY depends SYSTEM "depends.xml">
+ <!ENTITY environments SYSTEM "environments.xml">
+ <!ENTITY errors SYSTEM "errors.xml">
+ <!ENTITY example SYSTEM "example.xml">
+ <!ENTITY factories SYSTEM "factories.xml">
+ <!ENTITY file-removal SYSTEM "file-removal.xml">
+ <!ENTITY hierarchy SYSTEM "hierarchy.xml">
+ <!ENTITY java SYSTEM "java.xml">
+ <!ENTITY install SYSTEM "install.xml">
+ <!ENTITY less-simple SYSTEM "less-simple.xml">
+ <!ENTITY libraries SYSTEM "libraries.xml">
+ <!ENTITY make SYSTEM "make.xml">
+ <!ENTITY mergeflags SYSTEM "mergeflags.xml">
+ <!ENTITY misc SYSTEM "misc.xml">
+ <!ENTITY nodes SYSTEM "nodes.xml">
+ <!ENTITY output SYSTEM "output.xml">
+ <!ENTITY parseconfig SYSTEM "parseconfig.xml">
+ <!ENTITY parseflags SYSTEM "parseflags.xml">
+ <!ENTITY preface SYSTEM "preface.xml">
+ <!ENTITY python SYSTEM "python.xml">
+ <!ENTITY repositories SYSTEM "repositories.xml">
+ <!ENTITY run SYSTEM "run.xml">
+ <!ENTITY scanners SYSTEM "scanners.xml">
+ <!ENTITY sconf SYSTEM "sconf.xml">
+ <!ENTITY separate SYSTEM "separate.xml">
+ <!ENTITY simple SYSTEM "simple.xml">
+ <!ENTITY sourcecode SYSTEM "sourcecode.xml">
+ <!ENTITY tasks SYSTEM "tasks.xml">
+ <!ENTITY tools SYSTEM "tools.xml">
+ <!ENTITY troubleshoot SYSTEM "troubleshoot.xml">
+ <!ENTITY variables-xml SYSTEM "variables.xml">
+ <!ENTITY variants SYSTEM "variants.xml">
+
+ <!ENTITY builders-gen SYSTEM "builders.gen">
+ <!ENTITY tools-gen SYSTEM "tools.gen">
+ <!ENTITY variables-gen SYSTEM "variables.gen">
+
+]>
+
+ <!--
+
+ XXX FindFile()
+ XXX FindPathDirs()
+ XXX GetBuildPath()
+ XXX GetLaunchDir()
+
+ XXX ParseDepends()
+ XXX Platform()
+ XXX SConsignFile()
+ XXX Tools()
+
+ XXX GetOption('duplicate')
+ XXX SetOption('duplicate')
+ XXX - - duplicate=
+
+ XXX CheckTypeSize()
+
+ XXX - - diskcheck=
+
+ XXX - - warn=
+
+ -->
+
+<book>
+ <bookinfo>
+ <title>SCons User Guide &buildversion;</title>
+
+ <author>
+ <firstname>Steven</firstname>
+ <surname>Knight</surname>
+ </author>
+
+ <edition>Revision &buildrevision; (&builddate;)</edition>
+
+ <pubdate>2004, 2005, 2006, 2007, 2008</pubdate>
+
+ <copyright>
+ <year>2004, 2005, 2006, 2007, 2008</year>
+ <holder>Steven Knight</holder>
+ </copyright>
+
+ <legalnotice>
+ &copyright;
+ </legalnotice>
+
+ <releaseinfo>version &buildversion;</releaseinfo>
+
+ </bookinfo>
+
+ <preface id="chap-preface">
+ <title>Preface</title>
+ &preface;
+ </preface>
+
+ <chapter id="chap-build-install">
+ <title>Building and Installing &SCons;</title>
+ &build-install;
+ </chapter>
+
+ <chapter id="chap-simple">
+ <title>Simple Builds</title>
+ &simple;
+ </chapter>
+
+ <chapter id="chap-less-simple">
+ <title>Less Simple Things to Do With Builds</title>
+ &less-simple;
+ </chapter>
+
+ <chapter id="chap-libraries">
+ <title>Building and Linking with Libraries</title>
+ &libraries;
+ </chapter>
+
+ <chapter id="chap-nodes">
+ <title>Node Objects</title>
+ &nodes;
+ </chapter>
+
+ <chapter id="chap-depends">
+ <title>Dependencies</title>
+ &depends;
+ </chapter>
+
+ <chapter id="chap-environments">
+ <title>Environments</title>
+ &environments;
+ </chapter>
+
+ <!-- These next three sections should be combined into one chapter -->
+ <chapter id="chap-mergeflags">
+ <title>Merging Options into the Environment: the &MergeFlags; Function</title>
+ &mergeflags;
+ </chapter>
+ <chapter id="chap-parseflags">
+ <title>Separating Compile Arguments into their Variables: the &ParseFlags; Function</title>
+ &parseflags;
+ </chapter>
+ <chapter id="chap-parseconfig">
+ <title>Finding Installed Library Information: the &ParseConfig; Function</title>
+ &parseconfig;
+ </chapter>
+
+ <chapter id="chap-output">
+ <title>Controlling Build Output</title>
+ &output;
+ </chapter>
+
+ <chapter id="chap-command-line">
+ <title>Controlling a Build From the Command Line</title>
+ &command-line;
+ </chapter>
+
+ <chapter id="chap-install">
+ <title>Installing Files in Other Directories: the &Install; Builder</title>
+ &install;
+ </chapter>
+
+ <chapter id="chap-factories">
+ <title>Platform-Independent File System Manipulation</title>
+ &factories;
+ </chapter>
+
+ <chapter id="chap-file-removal">
+ <title>Controlling Removal of Targets</title>
+ &file-removal;
+ </chapter>
+
+ <chapter id="chap-hierarchical">
+ <title>Hierarchical Builds</title>
+ &hierarchy;
+ </chapter>
+
+ <chapter id="chap-separate">
+ <title>Separating Source and Build Directories</title>
+ &separate;
+ </chapter>
+
+ <chapter id="chap-variants">
+ <title>Variant Builds</title>
+ &variants;
+ </chapter>
+
+ <!--
+
+ <chapter id="chap-builders-built-in">
+ <title>Built-In Builders</title>
+ &builders-built-in;
+ </chapter>
+
+ -->
+
+ <chapter id="chap-builders-writing">
+ <title>Writing Your Own Builders</title>
+ &builders-writing;
+ </chapter>
+
+ <chapter id="chap-builders-commands">
+ <title>Not Writing a Builder: the &Command; Builder</title>
+ &builders-commands;
+ </chapter>
+
+ <chapter id="chap-add-method">
+ <title>Pseudo-Builders: the AddMethod function</title>
+ &add-method;
+ </chapter>
+
+ <!--
+
+ XXX Action()
+ XXX AddPostAction()
+ XXX AddPreAction()
+
+ <chapter id="chap-actions">
+ <title>&SCons; Actions</title>
+ &actions;
+ </chapter>
+
+ -->
+
+ <chapter id="chap-scanners">
+ <title>Writing Scanners</title>
+ &scanners;
+ </chapter>
+
+ <chapter id="chap-repositories">
+ <title>Building From Code Repositories</title>
+ &repositories;
+ </chapter>
+
+ <chapter id="chap-sconf">
+ <title>Multi-Platform Configuration (&Autoconf; Functionality)</title>
+ &sconf;
+ </chapter>
+
+ <!--
+
+ <chapter id="chap-sourcecode">
+ <title>Fetching Files From Source Code Management Systems</title>
+ &sourcecode;
+ </chapter>
+
+ -->
+
+ <chapter id="chap-caching">
+ <title>Caching Built Files</title>
+ &caching;
+ </chapter>
+
+ <chapter id="chap-alias">
+ <title>Alias Targets</title>
+ &alias;
+ </chapter>
+
+ <chapter id="chap-java">
+ <title>Java Builds</title>
+ &java;
+ </chapter>
+
+ <!--
+
+ <chapter id="chap-run">
+ <title>How to Run &SCons;</title>
+ &run;
+ </chapter>
+
+ -->
+
+ <chapter id="chap-misc">
+ <title>Miscellaneous Functionality</title>
+ &misc;
+ </chapter>
+
+ <chapter id="chap-troubleshooting">
+ <title>Troubleshooting</title>
+ &troubleshoot;
+ </chapter>
+
+ <appendix id="app-variables">
+ <title>Construction Variables</title>
+ &variables-xml;
+ </appendix>
+
+ <appendix id="app-builders">
+ <title>Builders</title>
+ &builders;
+ </appendix>
+
+ <appendix id="app-tools">
+ <title>Tools</title>
+ &tools;
+ </appendix>
+
+ <appendix id="app-tasks">
+ <title>Handling Common Tasks</title>
+ &tasks;
+ </appendix>
+
+ <!--
+
+ <appendix id="app-python">
+ <title>Python Overview</title>
+ &example;
+ </appendix>
+
+ <appendix id="app-example">
+ <title>Complex &SCons; Example</title>
+ &example;
+ </appendix>
+
+ <appendix id="app-make">
+ <title>Converting From Make</title>
+ &make;
+ </appendix>
+
+ <appendix id="app-cons">
+ <title>Converting From Cons</title>
+ &cons;
+ </appendix>
+
+ <appendix id="app-ant">
+ <title>Converting From Ant</title>
+ &ant;
+ </appendix>
+
+ -->
+
+</book>
diff --git a/doc/user/make.in b/doc/user/make.in
new file mode 100644
index 0000000..e778c61
--- /dev/null
+++ b/doc/user/make.in
@@ -0,0 +1,121 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ 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/make.xml b/doc/user/make.xml
new file mode 100644
index 0000000..e778c61
--- /dev/null
+++ b/doc/user/make.xml
@@ -0,0 +1,121 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Why Cons? Why not Make?
+
+Cons is a B<make> replacement. In the following paragraphs, we look at a few
+of the undesirable characteristics of make, and typical build environments
+based on make, that motivated the development of Cons.
+
+=head2 Build complexity
+
+Traditional make-based systems of any size tend to become quite complex. The
+original make utility and its derivatives have contributed to this tendency
+in a number of ways. Make is not good at dealing with systems that are
+spread over multiple directories. Various work-arounds are used to overcome
+this difficulty; the usual choice is for make to invoke itself recursively
+for each sub-directory of a build. This leads to complicated code, in which
+it is often unclear how a variable is set, or what effect the setting of a
+variable will have on the build as a whole. The make scripting language has
+gradually been extended to provide more possibilities, but these have
+largely served to clutter an already overextended language. Often, builds
+are done in multiple passes in order to provide appropriate products from
+one directory to another directory. This represents a further increase in
+build complexity.
+
+
+=head2 Build reproducibility
+
+The bane of all makes has always been the correct handling of
+dependencies. Most often, an attempt is made to do a reasonable job of
+dependencies within a single directory, but no serious attempt is made to do
+the job between directories. Even when dependencies are working correctly,
+make's reliance on a simple time stamp comparison to determine whether a
+file is out of date with respect to its dependents is not, in general,
+adequate for determining when a file should be rederived. If an external
+library, for example, is rebuilt and then ``snapped'' into place, the
+timestamps on its newly created files may well be earlier than the last
+local build, since it was built before it became visible.
+
+
+=head2 Variant builds
+
+Make provides only limited facilities for handling variant builds. With the
+proliferation of hardware platforms and the need for debuggable
+vs. optimized code, the ability to easily create these variants is
+essential. More importantly, if variants are created, it is important to
+either be able to separate the variants or to be able to reproduce the
+original or variant at will. With make it is very difficult to separate the
+builds into multiple build directories, separate from the source. And if
+this technique isn't used, it's also virtually impossible to guarantee at
+any given time which variant is present in the tree, without resorting to a
+complete rebuild.
+
+
+=head2 Repositories
+
+Make provides only limited support for building software from code that
+exists in a central repository directory structure. The VPATH feature of
+GNU make (and some other make implementations) is intended to provide this,
+but doesn't work as expected: it changes the path of target file to the
+VPATH name too early in its analysis, and therefore searches for all
+dependencies in the VPATH directory. To ensure correct development builds,
+it is important to be able to create a file in a local build directory and
+have any files in a code repository (a VPATH directory, in make terms) that
+depend on the local file get rebuilt properly. This isn't possible with
+VPATH, without coding a lot of complex repository knowledge directly into
+the makefiles.
+
+-->
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <section>
+ <title>Differences Between &Make; and &SCons;</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Advantages of &SCons; Over &Make;</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
diff --git a/doc/user/mergeflags.in b/doc/user/mergeflags.in
new file mode 100644
index 0000000..b50992b
--- /dev/null
+++ b/doc/user/mergeflags.in
@@ -0,0 +1,137 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; construction environments have a &MergeFlags; method
+ that merges a dictionary of values into the construction environment.
+ &MergeFlags; treats each value in the dictionary
+ as a list of options such as one might pass to a command
+ (such as a compiler or linker).
+ &MergeFlags; will not duplicate an option
+ if it already exists in the construction environment variable.
+
+ </para>
+
+ <para>
+
+ &MergeFlags; tries to be intelligent about merging options.
+ When merging options to any variable
+ whose name ends in <varname>PATH</varname>,
+ &MergeFlags; keeps the leftmost occurrence of the option,
+ because in typical lists of directory paths,
+ the first occurrence "wins."
+ When merging options to any other variable name,
+ &MergeFlags; keeps the rightmost occurrence of the option,
+ because in a list of typical command-line options,
+ the last occurrence "wins."
+
+ </para>
+
+ <scons_example name="MergeFlags1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Append(CCFLAGS = '-option -O3 -O1')
+ flags = { 'CCFLAGS' : '-whatever -O3' }
+ env.MergeFlags(flags)
+ print env['CCFLAGS']
+ </file>
+ </scons_example>
+
+ <scons_output example="MergeFlags1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that the default value for &cv-link-CCFLAGS;
+ <!--
+ [TODO: for when we make CLVar public]
+ is a <varname>CLVar</varname>,
+ -->
+ is an internal &SCons; object
+ which automatically converts
+ the options we specified as a string into a list.
+
+ </para>
+
+ <scons_example name="MergeFlags2">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include'])
+ flags = { 'CPPPATH' : ['/usr/opt/include', '/usr/local/include'] }
+ env.MergeFlags(flags)
+ print env['CPPPATH']
+ </file>
+ </scons_example>
+
+ <scons_output example="MergeFlags2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that the default value for &cv-link-CPPPATH;
+ <!--
+ [TODO: for when we make CLVar public]
+ is a Python list, not a <varname>CLVar</varname>,
+ -->
+ is a normal Python list,
+ so we must specify its values as a list
+ in the dictionary we pass to the &MergeFlags; function.
+
+ </para>
+
+ <para>
+
+ If &MergeFlags; is passed anything other than a dictionary,
+ it calls the &ParseFlags; method to convert it into a dictionary.
+
+ </para>
+
+ <scons_example name="MergeFlags3">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Append(CCFLAGS = '-option -O3 -O1')
+ env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include'])
+ env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include')
+ print env['CCFLAGS']
+ print env['CPPPATH']
+ </file>
+ </scons_example>
+
+ <scons_output example="MergeFlags3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In the combined example above,
+ &ParseFlags; has sorted the options into their corresponding variables
+ and returned a dictionary for &MergeFlags; to apply
+ to the construction variables
+ in the specified construction environment.
+
+ </para>
diff --git a/doc/user/mergeflags.xml b/doc/user/mergeflags.xml
new file mode 100644
index 0000000..7edc986
--- /dev/null
+++ b/doc/user/mergeflags.xml
@@ -0,0 +1,138 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; construction environments have a &MergeFlags; method
+ that merges a dictionary of values into the construction environment.
+ &MergeFlags; treats each value in the dictionary
+ as a list of options such as one might pass to a command
+ (such as a compiler or linker).
+ &MergeFlags; will not duplicate an option
+ if it already exists in the construction environment variable.
+
+ </para>
+
+ <para>
+
+ &MergeFlags; tries to be intelligent about merging options.
+ When merging options to any variable
+ whose name ends in <varname>PATH</varname>,
+ &MergeFlags; keeps the leftmost occurrence of the option,
+ because in typical lists of directory paths,
+ the first occurrence "wins."
+ When merging options to any other variable name,
+ &MergeFlags; keeps the rightmost occurrence of the option,
+ because in a list of typical command-line options,
+ the last occurrence "wins."
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Append(CCFLAGS = '-option -O3 -O1')
+ flags = { 'CCFLAGS' : '-whatever -O3' }
+ env.MergeFlags(flags)
+ print env['CCFLAGS']
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ ['-option', '-O1', '-whatever', '-O3']
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Note that the default value for &cv-link-CCFLAGS;
+ <!--
+ [TODO: for when we make CLVar public]
+ is a <varname>CLVar</varname>,
+ -->
+ is an internal &SCons; object
+ which automatically converts
+ the options we specified as a string into a list.
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include'])
+ flags = { 'CPPPATH' : ['/usr/opt/include', '/usr/local/include'] }
+ env.MergeFlags(flags)
+ print env['CPPPATH']
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ ['/include', '/usr/local/include', '/usr/include', '/usr/opt/include']
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ Note that the default value for &cv-link-CPPPATH;
+ <!--
+ [TODO: for when we make CLVar public]
+ is a Python list, not a <varname>CLVar</varname>,
+ -->
+ is a normal Python list,
+ so we must specify its values as a list
+ in the dictionary we pass to the &MergeFlags; function.
+
+ </para>
+
+ <para>
+
+ If &MergeFlags; is passed anything other than a dictionary,
+ it calls the &ParseFlags; method to convert it into a dictionary.
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Append(CCFLAGS = '-option -O3 -O1')
+ env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include'])
+ env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include')
+ print env['CCFLAGS']
+ print env['CPPPATH']
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ ['-option', '-O1', '-whatever', '-O3']
+ ['/include', '/usr/local/include', '/usr/include', '/usr/opt/include']
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ In the combined example above,
+ &ParseFlags; has sorted the options into their corresponding variables
+ and returned a dictionary for &MergeFlags; to apply
+ to the construction variables
+ in the specified construction environment.
+
+ </para>
diff --git a/doc/user/misc.in b/doc/user/misc.in
new file mode 100644
index 0000000..6679134
--- /dev/null
+++ b/doc/user/misc.in
@@ -0,0 +1,606 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; supports a lot of additional functionality
+ that doesn't readily fit into the other chapters.
+
+ </para>
+
+ <section>
+ <title>Verifying the Python Version: the &EnsurePythonVersion; Function</title>
+
+ <para>
+
+ Although the &SCons; code itself will run
+ on any Python version 1.5.2 or later,
+ you are perfectly free to make use of
+ Python syntax and modules from more modern versions
+ (for example, Python 2.4 or 2.5)
+ when writing your &SConscript; files
+ or your own local modules.
+ If you do this, it's usually helpful to
+ configure &SCons; to exit gracefully with an error message
+ if it's being run with a version of Python
+ that simply won't work with your code.
+ This is especially true if you're going to use &SCons;
+ to build source code that you plan to distribute publicly,
+ where you can't be sure of the Python version
+ that an anonymous remote user might use
+ to try to build your software.
+
+ </para>
+
+ <para>
+
+ &SCons; provides an &EnsurePythonVersion; function for this.
+ You simply pass it the major and minor versions
+ numbers of the version of Python you require:
+
+ </para>
+
+ <!--
+
+ TODO: Figure out how to generate the error message
+ regardless of executing Python version by faking out
+ the infrastructure in some way.
+
+ <scons_example name="EnsurePythonVersion">
+ <file name="SConstruct" printme="1">
+ EnsurePythonVersion(2, 5)
+ </file>
+ </scons_example>
+
+ -->
+
+ <sconstruct>
+ EnsurePythonVersion(2, 5)
+ </sconstruct>
+
+ <para>
+
+ And then &SCons will exit with the following error
+ message when a user runs it with an unsupported
+ earlier version of Python:
+
+ </para>
+
+ <!--
+
+ TODO: Figure out how to generate the error message
+ regardless of executing Python version by faking out
+ the infrastructure in some way.
+
+ <scons_output example="EnsurePythonVersion">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Python 2.5 or greater required, but you have Python 2.3.6
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Verifying the SCons Version: the &EnsureSConsVersion; Function</title>
+
+ <para>
+
+ You may, of course, write your &SConscript; files
+ to use features that were only added in
+ recent versions of &SCons;.
+ When you publicly distribute software that is built using &SCons;,
+ it's helpful to have &SCons;
+ verify the version being used and
+ exit gracefully with an error message
+ if the user's version of &SCons; won't work
+ with your &SConscript; files.
+ &SCons; provides an &EnsureSConsVersion; function
+ that verifies the version of &SCons;
+ in the same
+ the &EnsurePythonVersion; function
+ verifies the version of Python,
+ by passing in the major and minor versions
+ numbers of the version of SCons you require:
+
+ </para>
+
+ <!--
+
+ TODO: Figure out how to generate the error message
+ regardless of executing SCons version by faking out
+ the infrastructure in some way.
+
+ <scons_example name="EnsureSConsVersion">
+ <file name="SConstruct" printme="1">
+ EnsureSConsVersion(1, 0)
+ </file>
+ </scons_example>
+
+ -->
+
+ <sconstruct>
+ EnsureSConsVersion(1, 0)
+ </sconstruct>
+
+ <para>
+
+ And then &SCons will exit with the following error
+ message when a user runs it with an unsupported
+ earlier version of &SCons;:
+
+ </para>
+
+ <!--
+
+ TODO: Figure out how to generate the error message
+ regardless of executing SCons version by faking out
+ the infrastructure in some way.
+
+ <scons_output example="EnsureSConsVersion">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ SCons 1.0 or greater required, but you have SCons 0.98.5
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Explicitly Terminating &SCons; While Reading &SConscript; Files: the &Exit; Function</title>
+
+ <para>
+
+ &SCons; supports an &Exit; function
+ which can be used to terminate &SCons;
+ while reading the &SConscript; files,
+ usually because you've detected a condition
+ under which it doesn't make sense to proceed:
+
+ </para>
+
+ <scons_example name="Exit">
+ <file name="SConstruct" printme="1">
+ if ARGUMENTS.get('FUTURE'):
+ print "The FUTURE option is not supported yet!"
+ Exit(2)
+ env = Environment()
+ env.Program('hello.c')
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ </scons_example>
+
+ <scons_output example="Exit">
+ <scons_output_command>scons -Q FUTURE=1</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The &Exit; function takes as an argument
+ the (numeric) exit status that you want &SCons; to exit with.
+ If you don't specify a value,
+ the default is to exit with <literal>0</literal>,
+ which indicates successful execution.
+
+ </para>
+
+ <para>
+
+ Note that the &Exit; function
+ is equivalent to calling the Python
+ <function>sys.exit</function> function
+ (which the it actually calls),
+ but because &Exit; is a &SCons; function,
+ you don't have to import the Python
+ <literal>sys</literal> module to use it.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Searching for Files: the &FindFile; Function</title>
+
+ <para>
+
+ The &FindFile; function searches for a file in a list of directories.
+ If there is only one directory, it can be given as a simple string.
+ The function returns a File node if a matching file exists,
+ or None if no file is found.
+ (See the documentation for the &Glob; function for an alternative way
+ of searching for entries in a directory.)
+
+ </para>
+
+ <scons_example name="FindFile1a">
+ <file name="SConstruct" printme="1">
+ # one directory
+ print FindFile('missing', '.')
+ t = FindFile('exists', '.')
+ print t.__class__, t
+ </file>
+ <file name="exists">
+ exists
+ </file>
+ </scons_example>
+
+ <scons_output example="FindFile1a" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <scons_example name="FindFile1b">
+ <file name="SConstruct" printme="1">
+ # several directories
+ includes = [ '.', 'include', 'src/include']
+ headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h']
+ for hdr in headers:
+ print '%-12s' % ('%s:' % hdr), FindFile(hdr, includes)
+ </file>
+ <file name="config.h">
+ exists
+ </file>
+ <directory name="src"></directory>
+ <directory name="src/include"></directory>
+ </file>
+ <file name="src/include/private.h">
+ exists
+ <directory name="include"></directory>
+ </file>
+ <file name="include/dist.h">
+ exists
+ </scons_example>
+
+ <scons_output example="FindFile1b" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <!-- The man page says this should work, but it fails.
+ <para>
+
+ If the 'file' parameter is a list of files,
+ a list of File nodes is returned.
+
+ </para>
+
+ <scons_example name="FindFile1c">
+ <file name="SConstruct" printme="1">
+ # several directories
+ includes = [ '.', 'include', 'src/include']
+ headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h']
+ print FindFile(headers, includes)
+ </file>
+ <file name="config.h">
+ exists
+ </file>
+ <directory name="src"></directory>
+ <directory name="src/include"></directory>
+ </file>
+ <file name="src/include/private.h">
+ exists
+ <directory name="include"></directory>
+ </file>
+ <file name="include/dist.h">
+ exists
+ </scons_example>
+
+ <scons_output example="FindFile1c" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+ -->
+
+ <para>
+
+ If the file exists in more than one directory,
+ only the first occurrence is returned.
+
+ </para>
+
+ <scons_example name="FindFile1d">
+ <file name="SConstruct" printme="1">
+ print FindFile('multiple', ['sub1', 'sub2', 'sub3'])
+ print FindFile('multiple', ['sub2', 'sub3', 'sub1'])
+ print FindFile('multiple', ['sub3', 'sub1', 'sub2'])
+ </file>
+ <directory name="sub1"></directory>
+ <file name="sub1/multiple">
+ exists
+ </file>
+ <directory name="sub2"></directory>
+ <file name="sub2/multiple">
+ exists
+ </file>
+ <directory name="sub3"></directory>
+ <file name="sub3/multiple">
+ exists
+ </file>
+ </scons_example>
+
+ <scons_output example="FindFile1d" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <!-- file may be a list of file names or a single file name. -->
+
+ <para>
+
+ In addition to existing files, &FindFile; will also find derived files
+ (that is, non-leaf files) that haven't been built yet.
+ (Leaf files should already exist, or the build will fail!)
+
+ </para>
+
+ <scons_example name="FindFile2">
+ <file name="SConstruct" printme="1">
+ # Neither file exists, so build will fail
+ Command('derived', 'leaf', 'cat >$TARGET $SOURCE')
+ print FindFile('leaf', '.')
+ print FindFile('derived', '.')
+ </file>
+ </scons_example>
+
+ <scons_output example="FindFile2" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <scons_example name="FindFile2">
+ <file name="SConstruct" printme="1">
+ # Only 'leaf' exists
+ Command('derived', 'leaf', 'cat >$TARGET $SOURCE')
+ print FindFile('leaf', '.')
+ print FindFile('derived', '.')
+ </file>
+ <file name="leaf">
+ leaf
+ </file>
+ </scons_example>
+
+ <scons_output example="FindFile2" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If a source file exists, &FindFile; will correctly return the name
+ in the build directory.
+
+ </para>
+
+ <scons_example name="FindFile3">
+ <file name="SConstruct" printme="1">
+ # Only 'src/leaf' exists
+ VariantDir('build', 'src')
+ print FindFile('leaf', 'build')
+ </file>
+ <directory name="src"></directory>
+ <file name="src/leaf">
+ leaf
+ </file>
+ </scons_example>
+
+ <scons_output example="FindFile3" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Handling Nested Lists: the &Flatten; Function</title>
+
+ <para>
+
+ &SCons; supports a &Flatten; function
+ which takes an input Python sequence
+ (list or tuple)
+ and returns a flattened list
+ containing just the individual elements of
+ the sequence.
+ This can be handy when trying to examine
+ a list composed of the lists
+ returned by calls to various Builders.
+ For example, you might collect
+ object files built in different ways
+ into one call to the &Program; Builder
+ by just enclosing them in a list, as follows:
+
+ </para>
+
+ <scons_example name="Flatten1">
+ <file name="SConstruct" printme="1">
+ objects = [
+ Object('prog1.c'),
+ Object('prog2.c', CCFLAGS='-DFOO'),
+ ]
+ Program(objects)
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ <file name="prog2.c">
+ prog2.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Because the Builder calls in &SCons;
+ flatten their input lists,
+ this works just fine to build the program:
+
+ </para>
+
+ <scons_output example="Flatten1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ But if you were debugging your build
+ and wanted to print the absolute path
+ of each object file in the
+ <varname>objects</varname> list,
+ you might try the following simple approach,
+ trying to print each Node's
+ <literal>abspath</literal>
+ attribute:
+
+ </para>
+
+ <scons_example name="Flatten2">
+ <file name="SConstruct" printme="1">
+ objects = [
+ Object('prog1.c'),
+ Object('prog2.c', CCFLAGS='-DFOO'),
+ ]
+ Program(objects)
+
+ for object_file in objects:
+ print object_file.abspath
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ <file name="prog2.c">
+ prog2.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ This does not work as expected
+ because each call to <function>str</function>
+ is operating an embedded list returned by
+ each &Object; call,
+ not on the underlying Nodes within those lists:
+
+ </para>
+
+ <scons_output example="Flatten2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The solution is to use the &Flatten; function
+ so that you can pass each Node to
+ the <function>str</function> separately:
+
+ </para>
+
+ <scons_example name="Flatten3">
+ <file name="SConstruct" printme="1">
+ objects = [
+ Object('prog1.c'),
+ Object('prog2.c', CCFLAGS='-DFOO'),
+ ]
+ Program(objects)
+
+ for object_file in Flatten(objects):
+ print object_file.abspath
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ <file name="prog2.c">
+ prog2.c
+ </file>
+ </scons_example>
+
+ <!--
+
+ TODO: can't use this now because it displays the temporary path name
+
+ <scons_output example="Flatten3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ /home/me/project/prog1.o
+ /home/me/project/prog2.o
+ cc -o prog1.o -c prog1.c
+ cc -o prog2.o -c -DFOO prog2.c
+ cc -o prog1 prog1.o prog2.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Finding the Invocation Directory: the &GetLaunchDir; Function</title>
+
+ <para>
+
+ If you need to find the directory from
+ which the user invoked the &scons; command,
+ you can use the &GetLaunchDir; function:
+
+ </para>
+
+ <sconstruct>
+ env = Environment(
+ LAUNCHDIR = GetLaunchDir(),
+ )
+ env.Command('directory_build_info',
+ '$LAUNCHDIR/build_info'
+ Copy('$TARGET', '$SOURCE'))
+ </sconstruct>
+
+ <para>
+
+ Because &SCons; is usually invoked from the top-level
+ directory in which the &SConstruct; file lives,
+ the Python <function>os.getcwd()</function>
+ is often equivalent.
+ However, the &SCons;
+ <literal>-u</literal>,
+ <literal>-U</literal>
+ and
+ <literal>-D</literal>
+ command-line options,
+ when invoked from a subdirectory,
+ will cause &SCons; to change to the directory
+ in which the &SConstruct; file is found.
+ When those options are used,
+ &GetLaunchDir; will still return the path to the
+ user's invoking subdirectory,
+ allowing the &SConscript; configuration
+ to still get at configuration (or other) files
+ from the originating directory.
+
+ </para>
+
+ </section>
diff --git a/doc/user/misc.xml b/doc/user/misc.xml
new file mode 100644
index 0000000..a2305ee
--- /dev/null
+++ b/doc/user/misc.xml
@@ -0,0 +1,565 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; supports a lot of additional functionality
+ that doesn't readily fit into the other chapters.
+
+ </para>
+
+ <section>
+ <title>Verifying the Python Version: the &EnsurePythonVersion; Function</title>
+
+ <para>
+
+ Although the &SCons; code itself will run
+ on any Python version 1.5.2 or later,
+ you are perfectly free to make use of
+ Python syntax and modules from more modern versions
+ (for example, Python 2.4 or 2.5)
+ when writing your &SConscript; files
+ or your own local modules.
+ If you do this, it's usually helpful to
+ configure &SCons; to exit gracefully with an error message
+ if it's being run with a version of Python
+ that simply won't work with your code.
+ This is especially true if you're going to use &SCons;
+ to build source code that you plan to distribute publicly,
+ where you can't be sure of the Python version
+ that an anonymous remote user might use
+ to try to build your software.
+
+ </para>
+
+ <para>
+
+ &SCons; provides an &EnsurePythonVersion; function for this.
+ You simply pass it the major and minor versions
+ numbers of the version of Python you require:
+
+ </para>
+
+ <!--
+
+ TODO: Figure out how to generate the error message
+ regardless of executing Python version by faking out
+ the infrastructure in some way.
+
+ <scons_example name="EnsurePythonVersion">
+ <file name="SConstruct" printme="1">
+ EnsurePythonVersion(2, 5)
+ </file>
+ </scons_example>
+
+ -->
+
+ <programlisting>
+ EnsurePythonVersion(2, 5)
+ </programlisting>
+
+ <para>
+
+ And then &SCons; will exit with the following error
+ message when a user runs it with an unsupported
+ earlier version of Python:
+
+ </para>
+
+ <!--
+
+ TODO: Figure out how to generate the error message
+ regardless of executing Python version by faking out
+ the infrastructure in some way.
+
+ <scons_output example="EnsurePythonVersion">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Python 2.5 or greater required, but you have Python 2.3.6
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Verifying the SCons Version: the &EnsureSConsVersion; Function</title>
+
+ <para>
+
+ You may, of course, write your &SConscript; files
+ to use features that were only added in
+ recent versions of &SCons;.
+ When you publicly distribute software that is built using &SCons;,
+ it's helpful to have &SCons;
+ verify the version being used and
+ exit gracefully with an error message
+ if the user's version of &SCons; won't work
+ with your &SConscript; files.
+ &SCons; provides an &EnsureSConsVersion; function
+ that verifies the version of &SCons;
+ in the same
+ the &EnsurePythonVersion; function
+ verifies the version of Python,
+ by passing in the major and minor versions
+ numbers of the version of SCons you require:
+
+ </para>
+
+ <!--
+
+ TODO: Figure out how to generate the error message
+ regardless of executing SCons version by faking out
+ the infrastructure in some way.
+
+ <scons_example name="EnsureSConsVersion">
+ <file name="SConstruct" printme="1">
+ EnsureSConsVersion(1, 0)
+ </file>
+ </scons_example>
+
+ -->
+
+ <programlisting>
+ EnsureSConsVersion(1, 0)
+ </programlisting>
+
+ <para>
+
+ And then &SCons; will exit with the following error
+ message when a user runs it with an unsupported
+ earlier version of &SCons;:
+
+ </para>
+
+ <!--
+
+ TODO: Figure out how to generate the error message
+ regardless of executing SCons version by faking out
+ the infrastructure in some way.
+
+ <scons_output example="EnsureSConsVersion">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ SCons 1.0 or greater required, but you have SCons 0.98.5
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Explicitly Terminating &SCons; While Reading &SConscript; Files: the &Exit; Function</title>
+
+ <para>
+
+ &SCons; supports an &Exit; function
+ which can be used to terminate &SCons;
+ while reading the &SConscript; files,
+ usually because you've detected a condition
+ under which it doesn't make sense to proceed:
+
+ </para>
+
+ <programlisting>
+ if ARGUMENTS.get('FUTURE'):
+ print "The FUTURE option is not supported yet!"
+ Exit(2)
+ env = Environment()
+ env.Program('hello.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q FUTURE=1</userinput>
+ The FUTURE option is not supported yet!
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ The &Exit; function takes as an argument
+ the (numeric) exit status that you want &SCons; to exit with.
+ If you don't specify a value,
+ the default is to exit with <literal>0</literal>,
+ which indicates successful execution.
+
+ </para>
+
+ <para>
+
+ Note that the &Exit; function
+ is equivalent to calling the Python
+ <function>sys.exit</function> function
+ (which the it actually calls),
+ but because &Exit; is a &SCons; function,
+ you don't have to import the Python
+ <literal>sys</literal> module to use it.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Searching for Files: the &FindFile; Function</title>
+
+ <para>
+
+ The &FindFile; function searches for a file in a list of directories.
+ If there is only one directory, it can be given as a simple string.
+ The function returns a File node if a matching file exists,
+ or None if no file is found.
+ (See the documentation for the &Glob; function for an alternative way
+ of searching for entries in a directory.)
+
+ </para>
+
+ <programlisting>
+ # one directory
+ print FindFile('missing', '.')
+ t = FindFile('exists', '.')
+ print t.__class__, t
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ None
+ SCons.Node.FS.File exists
+ scons: `.' is up to date.
+ </screen>
+
+ <programlisting>
+ # several directories
+ includes = [ '.', 'include', 'src/include']
+ headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h']
+ for hdr in headers:
+ print '%-12s' % ('%s:' % hdr), FindFile(hdr, includes)
+</programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ nonesuch.h: None
+ config.h: config.h
+ private.h: src/include/private.h
+ dist.h: include/dist.h
+ scons: `.' is up to date.
+ </screen>
+
+ <!-- The man page says this should work, but it fails.
+ <para>
+
+ If the 'file' parameter is a list of files,
+ a list of File nodes is returned.
+
+ </para>
+
+ <scons_example name="FindFile1c">
+ <file name="SConstruct" printme="1">
+ # several directories
+ includes = [ '.', 'include', 'src/include']
+ headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h']
+ print FindFile(headers, includes)
+ </file>
+ <file name="config.h">
+ exists
+ </file>
+ <directory name="src"></directory>
+ <directory name="src/include"></directory>
+ </file>
+ <file name="src/include/private.h">
+ exists
+ <directory name="include"></directory>
+ </file>
+ <file name="include/dist.h">
+ exists
+ </scons_example>
+
+ <scons_output example="FindFile1c" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+ -->
+
+ <para>
+
+ If the file exists in more than one directory,
+ only the first occurrence is returned.
+
+ </para>
+
+ <programlisting>
+ print FindFile('multiple', ['sub1', 'sub2', 'sub3'])
+ print FindFile('multiple', ['sub2', 'sub3', 'sub1'])
+ print FindFile('multiple', ['sub3', 'sub1', 'sub2'])
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ sub1/multiple
+ sub2/multiple
+ sub3/multiple
+ scons: `.' is up to date.
+ </screen>
+
+ <!-- file may be a list of file names or a single file name. -->
+
+ <para>
+
+ In addition to existing files, &FindFile; will also find derived files
+ (that is, non-leaf files) that haven't been built yet.
+ (Leaf files should already exist, or the build will fail!)
+
+ </para>
+
+ <programlisting>
+ # Neither file exists, so build will fail
+ Command('derived', 'leaf', 'cat &gt;$TARGET $SOURCE')
+ print FindFile('leaf', '.')
+ print FindFile('derived', '.')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ None
+ derived
+ scons: *** [derived] Source `leaf' not found, needed by target `derived'.
+ </screen>
+
+ <programlisting>
+ # Neither file exists, so build will fail
+ Command('derived', 'leaf', 'cat &gt;$TARGET $SOURCE')
+ print FindFile('leaf', '.')
+ print FindFile('derived', '.')
+
+ # Only 'leaf' exists
+ Command('derived', 'leaf', 'cat &gt;$TARGET $SOURCE')
+ print FindFile('leaf', '.')
+ print FindFile('derived', '.')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ leaf
+ derived
+ cat &gt; derived leaf
+ </screen>
+
+ <para>
+
+ If a source file exists, &FindFile; will correctly return the name
+ in the build directory.
+
+ </para>
+
+ <programlisting>
+ # Only 'src/leaf' exists
+ VariantDir('build', 'src')
+ print FindFile('leaf', 'build')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ build/leaf
+ scons: `.' is up to date.
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Handling Nested Lists: the &Flatten; Function</title>
+
+ <para>
+
+ &SCons; supports a &Flatten; function
+ which takes an input Python sequence
+ (list or tuple)
+ and returns a flattened list
+ containing just the individual elements of
+ the sequence.
+ This can be handy when trying to examine
+ a list composed of the lists
+ returned by calls to various Builders.
+ For example, you might collect
+ object files built in different ways
+ into one call to the &Program; Builder
+ by just enclosing them in a list, as follows:
+
+ </para>
+
+ <programlisting>
+ objects = [
+ Object('prog1.c'),
+ Object('prog2.c', CCFLAGS='-DFOO'),
+ ]
+ Program(objects)
+ </programlisting>
+
+ <para>
+
+ Because the Builder calls in &SCons;
+ flatten their input lists,
+ this works just fine to build the program:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o prog1.o -c prog1.c
+ cc -o prog2.o -c -DFOO prog2.c
+ cc -o prog1 prog1.o prog2.o
+ </screen>
+
+ <para>
+
+ But if you were debugging your build
+ and wanted to print the absolute path
+ of each object file in the
+ <varname>objects</varname> list,
+ you might try the following simple approach,
+ trying to print each Node's
+ <literal>abspath</literal>
+ attribute:
+
+ </para>
+
+ <programlisting>
+ objects = [
+ Object('prog1.c'),
+ Object('prog2.c', CCFLAGS='-DFOO'),
+ ]
+ Program(objects)
+
+ for object_file in objects:
+ print object_file.abspath
+ </programlisting>
+
+ <para>
+
+ This does not work as expected
+ because each call to <function>str</function>
+ is operating an embedded list returned by
+ each &Object; call,
+ not on the underlying Nodes within those lists:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ AttributeError: NodeList instance has no attribute 'abspath':
+ File "/home/my/project/SConstruct", line 8:
+ print object_file.abspath
+ </screen>
+
+ <para>
+
+ The solution is to use the &Flatten; function
+ so that you can pass each Node to
+ the <function>str</function> separately:
+
+ </para>
+
+ <programlisting>
+ objects = [
+ Object('prog1.c'),
+ Object('prog2.c', CCFLAGS='-DFOO'),
+ ]
+ Program(objects)
+
+ for object_file in Flatten(objects):
+ print object_file.abspath
+ </programlisting>
+
+ <!--
+
+ TODO: can't use this now because it displays the temporary path name
+
+ <scons_output example="Flatten3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ /home/me/project/prog1.o
+ /home/me/project/prog2.o
+ cc -o prog1.o -c prog1.c
+ cc -o prog2.o -c -DFOO prog2.c
+ cc -o prog1 prog1.o prog2.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Finding the Invocation Directory: the &GetLaunchDir; Function</title>
+
+ <para>
+
+ If you need to find the directory from
+ which the user invoked the &scons; command,
+ you can use the &GetLaunchDir; function:
+
+ </para>
+
+ <programlisting>
+ env = Environment(
+ LAUNCHDIR = GetLaunchDir(),
+ )
+ env.Command('directory_build_info',
+ '$LAUNCHDIR/build_info'
+ Copy('$TARGET', '$SOURCE'))
+ </programlisting>
+
+ <para>
+
+ Because &SCons; is usually invoked from the top-level
+ directory in which the &SConstruct; file lives,
+ the Python <function>os.getcwd()</function>
+ is often equivalent.
+ However, the &SCons;
+ <literal>-u</literal>,
+ <literal>-U</literal>
+ and
+ <literal>-D</literal>
+ command-line options,
+ when invoked from a subdirectory,
+ will cause &SCons; to change to the directory
+ in which the &SConstruct; file is found.
+ When those options are used,
+ &GetLaunchDir; will still return the path to the
+ user's invoking subdirectory,
+ allowing the &SConscript; configuration
+ to still get at configuration (or other) files
+ from the originating directory.
+
+ </para>
+
+ </section>
diff --git a/doc/user/nodes.in b/doc/user/nodes.in
new file mode 100644
index 0000000..c914ce5
--- /dev/null
+++ b/doc/user/nodes.in
@@ -0,0 +1,386 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ Internally, &SCons; represents all of the files
+ and directories it knows about as &Nodes;.
+ These internal objects
+ (not object <emphasis>files</emphasis>)
+ can be used in a variety of ways
+ to make your &SConscript;
+ files portable and easy to read.
+
+ </para>
+
+ <section>
+ <title>Builder Methods Return Lists of Target Nodes</title>
+
+ <para>
+
+ All builder methods return a list of
+ &Node; objects that identify the
+ target file or files that will be built.
+ These returned &Nodes; can be passed
+ as arguments to other builder methods.
+
+ </para>
+
+ <para>
+
+ For example, suppose that we want to build
+ the two object files that make up a program with different options.
+ This would mean calling the &b-link-Object;
+ builder once for each object file,
+ specifying the desired options:
+
+ </para>
+
+ <sconstruct>
+ Object('hello.c', CCFLAGS='-DHELLO')
+ Object('goodbye.c', CCFLAGS='-DGOODBYE')
+ </sconstruct>
+
+ <para>
+
+ One way to combine these object files
+ into the resulting program
+ would be to call the &b-link-Program;
+ builder with the names of the object files
+ listed as sources:
+
+ </para>
+
+ <sconstruct>
+ Object('hello.c', CCFLAGS='-DHELLO')
+ Object('goodbye.c', CCFLAGS='-DGOODBYE')
+ Program(['hello.o', 'goodbye.o'])
+ </sconstruct>
+
+ <para>
+
+ The problem with specifying the names as strings
+ is that our &SConstruct; file is no longer portable
+ across operating systems.
+ It won't, for example, work on Windows
+ because the object files there would be
+ named &hello_obj; and &goodbye_obj;,
+ not &hello_o; and &goodbye_o;.
+
+ </para>
+
+ <para>
+
+ A better solution is to assign the lists of targets
+ returned by the calls to the &b-Object; builder to variables,
+ which we can then concatenate in our
+ call to the &b-Program; builder:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ hello_list = Object('hello.c', CCFLAGS='-DHELLO')
+ goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
+ Program(hello_list + goodbye_list)
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="goodbye.c">
+ int main() { printf("Goodbye, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ This makes our &SConstruct; file portable again,
+ the build output on Linux looking like:
+
+ </para>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And on Windows:
+
+ </para>
+
+ <scons_output example="ex1" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ We'll see examples of using the list of nodes
+ returned by builder methods throughout
+ the rest of this guide.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Explicitly Creating File and Directory Nodes</title>
+
+ <para>
+
+ It's worth mentioning here that
+ &SCons; maintains a clear distinction
+ between Nodes that represent files
+ and Nodes that represent directories.
+ &SCons; supports &File; and &Dir;
+ functions that, respectively,
+ return a file or directory Node:
+
+ </para>
+
+ <scons_example name="print">
+ <file name="SConstruct" printme="1">
+ hello_c = File('hello.c')
+ Program(hello_c)
+
+ classes = Dir('classes')
+ Java(classes, 'src')
+ </file>
+ </scons_example>
+
+ <para>
+
+ Normally, you don't need to call
+ &File; or &Dir; directly,
+ because calling a builder method automatically
+ treats strings as the names of files or directories,
+ and translates them into
+ the Node objects for you.
+ The &File; and &Dir; functions can come in handy
+ in situations where you need to explicitly
+ instruct &SCons; about the type of Node being
+ passed to a builder or other function,
+ or unambiguously refer to a specific
+ file in a directory tree.
+ <!--
+ (For an example of when you might
+ need to use &File; or &Dir; to
+ prevent ambiguous interpretation of a string
+ naming a file or directory, see
+ <xref linkend="chap-hierarchy">.)
+ -->
+
+ </para>
+
+ <para>
+
+ There are also times when you may need to
+ refer to an entry in a file system
+ without knowing in advance
+ whether it's a file or a directory.
+ For those situations,
+ &SCons; also supports an &Entry; function,
+ which returns a Node
+ that can represent either a file or a directory.
+
+ </para>
+
+ <sconstruct>
+ xyzzy = Entry('xyzzy')
+ </sconstruct>
+
+ <para>
+
+ The returned <literal>xyzzy</literal> Node
+ will be turned into a file or directory Node
+ the first time it is used by a builder method
+ or other function that
+ requires one vs. the other.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Printing &Node; File Names</title>
+
+ <para>
+
+ One of the most common things you can do
+ with a Node is use it to print the
+ file name that the node represents.
+ Keep in mind, though, that because the object
+ returned by a builder call
+ is a <emphasis>list</emphasis> of Nodes,
+ you must use Python subscripts
+ to fetch individual Nodes from the list.
+ For example, the following &SConstruct; file:
+
+ </para>
+
+ <scons_example name="print">
+ <file name="SConstruct" printme="1">
+ object_list = Object('hello.c')
+ program_list = Program(object_list)
+ print "The object file is:", object_list[0]
+ print "The program file is:", program_list[0]
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Would print the following file names on a POSIX system:
+
+ </para>
+
+ <scons_output example="print" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And the following file names on a Windows system:
+
+ </para>
+
+ <scons_output example="print" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that in the above example,
+ the <literal>object_list[0]</literal>
+ extracts an actual Node <emphasis>object</emphasis>
+ from the list,
+ and the Python <literal>print</literal> statement
+ converts the object to a string for printing.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Using a &Node;'s File Name as a String</title>
+
+ <para>
+
+ Printing a &Node;'s name
+ as described in the previous section
+ works because the string representation of a &Node; object
+ is the name of the file.
+ If you want to do something other than
+ print the name of the file,
+ you can fetch it by using the builtin Python
+ &str; function.
+ For example, if you want to use the Python
+ <function>os.path.exists</function>
+ to figure out whether a file
+ exists while the &SConstruct; file
+ is being read and executed,
+ you can fetch the string as follows:
+
+ </para>
+
+ <scons_example name="exists">
+ <file name="SConstruct" printme="1">
+ import os.path
+ program_list = Program('hello.c')
+ program_name = str(program_list[0])
+ if not os.path.exists(program_name):
+ print program_name, "does not exist!"
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which executes as follows on a POSIX system:
+
+ </para>
+
+ <scons_output example="exists" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Fetching the Contents of a &Node;</title>
+
+ <para>
+
+ XXX Describe using read() and readlines()
+ when we add that as a public interface.
+
+ </para>
+
+ <scons_example name="read">
+ <file name="SConstruct" printme="1">
+ hello_c = File('hello.c')
+ contents = hello_c.read()
+ print "contents are:"
+ print contents
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which executes as follows on a POSIX system:
+
+ </para>
+
+ <scons_output example="read" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ -->
+
+ <!--
+
+ <section>
+ <title>Python Value &Node;</title>
+
+ <para>
+
+ XXX Value()
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/nodes.xml b/doc/user/nodes.xml
new file mode 100644
index 0000000..46215c4
--- /dev/null
+++ b/doc/user/nodes.xml
@@ -0,0 +1,401 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ Internally, &SCons; represents all of the files
+ and directories it knows about as &Nodes;.
+ These internal objects
+ (not object <emphasis>files</emphasis>)
+ can be used in a variety of ways
+ to make your &SConscript;
+ files portable and easy to read.
+
+ </para>
+
+ <section>
+ <title>Builder Methods Return Lists of Target Nodes</title>
+
+ <para>
+
+ All builder methods return a list of
+ &Node; objects that identify the
+ target file or files that will be built.
+ These returned &Nodes; can be passed
+ as arguments to other builder methods.
+
+ </para>
+
+ <para>
+
+ For example, suppose that we want to build
+ the two object files that make up a program with different options.
+ This would mean calling the &b-link-Object;
+ builder once for each object file,
+ specifying the desired options:
+
+ </para>
+
+ <programlisting>
+ Object('hello.c', CCFLAGS='-DHELLO')
+ Object('goodbye.c', CCFLAGS='-DGOODBYE')
+ </programlisting>
+
+ <para>
+
+ One way to combine these object files
+ into the resulting program
+ would be to call the &b-link-Program;
+ builder with the names of the object files
+ listed as sources:
+
+ </para>
+
+ <programlisting>
+ Object('hello.c', CCFLAGS='-DHELLO')
+ Object('goodbye.c', CCFLAGS='-DGOODBYE')
+ Program(['hello.o', 'goodbye.o'])
+ </programlisting>
+
+ <para>
+
+ The problem with specifying the names as strings
+ is that our &SConstruct; file is no longer portable
+ across operating systems.
+ It won't, for example, work on Windows
+ because the object files there would be
+ named &hello_obj; and &goodbye_obj;,
+ not &hello_o; and &goodbye_o;.
+
+ </para>
+
+ <para>
+
+ A better solution is to assign the lists of targets
+ returned by the calls to the &b-Object; builder to variables,
+ which we can then concatenate in our
+ call to the &b-Program; builder:
+
+ </para>
+
+ <programlisting>
+ hello_list = Object('hello.c', CCFLAGS='-DHELLO')
+ goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
+ Program(hello_list + goodbye_list)
+ </programlisting>
+
+ <para>
+
+ This makes our &SConstruct; file portable again,
+ the build output on Linux looking like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o goodbye.o -c -DGOODBYE goodbye.c
+ cc -o hello.o -c -DHELLO hello.c
+ cc -o hello hello.o goodbye.o
+ </screen>
+
+ <para>
+
+ And on Windows:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Fogoodbye.obj /c goodbye.c -DGOODBYE
+ cl /Fohello.obj /c hello.c -DHELLO
+ link /nologo /OUT:hello.exe hello.obj goodbye.obj
+ </screen>
+
+ <para>
+
+ We'll see examples of using the list of nodes
+ returned by builder methods throughout
+ the rest of this guide.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Explicitly Creating File and Directory Nodes</title>
+
+ <para>
+
+ It's worth mentioning here that
+ &SCons; maintains a clear distinction
+ between Nodes that represent files
+ and Nodes that represent directories.
+ &SCons; supports &File; and &Dir;
+ functions that, respectively,
+ return a file or directory Node:
+
+ </para>
+
+ <programlisting>
+ hello_c = File('hello.c')
+ Program(hello_c)
+
+ classes = Dir('classes')
+ Java(classes, 'src')
+ </programlisting>
+
+ <para>
+
+ Normally, you don't need to call
+ &File; or &Dir; directly,
+ because calling a builder method automatically
+ treats strings as the names of files or directories,
+ and translates them into
+ the Node objects for you.
+ The &File; and &Dir; functions can come in handy
+ in situations where you need to explicitly
+ instruct &SCons; about the type of Node being
+ passed to a builder or other function,
+ or unambiguously refer to a specific
+ file in a directory tree.
+ <!--
+ (For an example of when you might
+ need to use &File; or &Dir; to
+ prevent ambiguous interpretation of a string
+ naming a file or directory, see
+ <xref linkend="chap-hierarchy">.)
+ -->
+
+ </para>
+
+ <para>
+
+ There are also times when you may need to
+ refer to an entry in a file system
+ without knowing in advance
+ whether it's a file or a directory.
+ For those situations,
+ &SCons; also supports an &Entry; function,
+ which returns a Node
+ that can represent either a file or a directory.
+
+ </para>
+
+ <programlisting>
+ xyzzy = Entry('xyzzy')
+ </programlisting>
+
+ <para>
+
+ The returned <literal>xyzzy</literal> Node
+ will be turned into a file or directory Node
+ the first time it is used by a builder method
+ or other function that
+ requires one vs. the other.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Printing &Node; File Names</title>
+
+ <para>
+
+ One of the most common things you can do
+ with a Node is use it to print the
+ file name that the node represents.
+ Keep in mind, though, that because the object
+ returned by a builder call
+ is a <emphasis>list</emphasis> of Nodes,
+ you must use Python subscripts
+ to fetch individual Nodes from the list.
+ For example, the following &SConstruct; file:
+
+ </para>
+
+ <programlisting>
+ hello_c = File('hello.c')
+ Program(hello_c)
+
+ classes = Dir('classes')
+ Java(classes, 'src')
+
+ object_list = Object('hello.c')
+ program_list = Program(object_list)
+ print "The object file is:", object_list[0]
+ print "The program file is:", program_list[0]
+ </programlisting>
+
+ <para>
+
+ Would print the following file names on a POSIX system:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ The object file is: hello.o
+ The program file is: hello
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ And the following file names on a Windows system:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ The object file is: hello.obj
+ The program file is: hello.exe
+ cl /Fohello.obj /c hello.c /nologo
+ link /nologo /OUT:hello.exe hello.obj
+ </screen>
+
+ <para>
+
+ Note that in the above example,
+ the <literal>object_list[0]</literal>
+ extracts an actual Node <emphasis>object</emphasis>
+ from the list,
+ and the Python <literal>print</literal> statement
+ converts the object to a string for printing.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Using a &Node;'s File Name as a String</title>
+
+ <para>
+
+ Printing a &Node;'s name
+ as described in the previous section
+ works because the string representation of a &Node; object
+ is the name of the file.
+ If you want to do something other than
+ print the name of the file,
+ you can fetch it by using the builtin Python
+ &str; function.
+ For example, if you want to use the Python
+ <function>os.path.exists</function>
+ to figure out whether a file
+ exists while the &SConstruct; file
+ is being read and executed,
+ you can fetch the string as follows:
+
+ </para>
+
+ <programlisting>
+ import os.path
+ program_list = Program('hello.c')
+ program_name = str(program_list[0])
+ if not os.path.exists(program_name):
+ print program_name, "does not exist!"
+ </programlisting>
+
+ <para>
+
+ Which executes as follows on a POSIX system:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ hello does not exist!
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Fetching the Contents of a &Node;</title>
+
+ <para>
+
+ XXX Describe using read() and readlines()
+ when we add that as a public interface.
+
+ </para>
+
+ <scons_example name="read">
+ <file name="SConstruct" printme="1">
+ hello_c = File('hello.c')
+ contents = hello_c.read()
+ print "contents are:"
+ print contents
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which executes as follows on a POSIX system:
+
+ </para>
+
+ <scons_output example="read" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ -->
+
+ <!--
+
+ <section>
+ <title>Python Value &Node;</title>
+
+ <para>
+
+ XXX Value()
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/output.in b/doc/user/output.in
new file mode 100644
index 0000000..1f600f3
--- /dev/null
+++ b/doc/user/output.in
@@ -0,0 +1,681 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ A key aspect of creating a usable build configuration
+ is providing good output from the build
+ so its users can readily understand
+ what the build is doing
+ and get information about how to control the build.
+ &SCons; provides several ways of
+ controlling output from the build configuration
+ to help make the build
+ more useful and understandable.
+
+ </para>
+
+ <section>
+ <title>Providing Build Help: the &Help; Function</title>
+
+ <para>
+
+ It's often very useful to be able to give
+ users some help that describes the
+ specific targets, build options, etc.,
+ that can be used for your build.
+ &SCons; provides the &Help; function
+ to allow you to specify this help text:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ Help("""
+ Type: 'scons program' to build the production program,
+ 'scons debug' to build the debug version.
+ """)
+ </file>
+ </scons_example>
+
+ <para>
+
+ (Note the above use of the Python triple-quote syntax,
+ which comes in very handy for
+ specifying multi-line strings like help text.)
+
+ </para>
+
+ <para>
+
+ When the &SConstruct; or &SConscript; files
+ contain such a call to the &Help; function,
+ the specified help text will be displayed in response to
+ the &SCons; <literal>-h</literal> option:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -h</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The &SConscript; files may contain
+ multiple calls to the &Help; function,
+ in which case the specified text(s)
+ will be concatenated when displayed.
+ This allows you to split up the
+ help text across multiple &SConscript; files.
+ In this situation, the order in
+ which the &SConscript; files are called
+ will determine the order in which the &Help; functions are called,
+ which will determine the order in which
+ the various bits of text will get concatenated.
+
+ </para>
+
+ <para>
+
+ Another use would be to make the help text conditional
+ on some variable.
+ For example, suppose you only want to display
+ a line about building a Windows-only
+ version of a program when actually
+ run on Windows.
+ The following &SConstruct; file:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+
+ Help("\nType: 'scons program' to build the production program.\n")
+
+ if env['PLATFORM'] == 'win32':
+ Help("\nType: 'scons windebug' to build the Windows debug version.\n")
+ </file>
+ </scons_example>
+
+ <para>
+
+ Will display the complete help text on Windows:
+
+ </para>
+
+ <scons_output example="ex2" os="win32">
+ <scons_output_command>scons -h</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ But only show the relevant option on a Linux or UNIX system:
+
+ </para>
+
+ <scons_output example="ex2" os="posix">
+ <scons_output_command>scons -h</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If there is no &Help; text in the &SConstruct; or
+ &SConscript; files,
+ &SCons; will revert to displaying its
+ standard list that describes the &SCons; command-line
+ options.
+ This list is also always displayed whenever
+ the <literal>-H</literal> option is used.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Controlling How &SCons; Prints Build Commands: the <envar>$*COMSTR</envar> Variables</title>
+
+ <para>
+
+ Sometimes the commands executed
+ to compile object files or link programs
+ (or build other targets)
+ can get very long,
+ long enough to make it difficult for users
+ to distinguish error messages or
+ other important build output
+ from the commands themselves.
+ All of the default <envar>$*COM</envar> variables
+ that specify the command lines
+ used to build various types of target files
+ have a corresponding <envar>$*COMSTR</envar> variable
+ that can be set to an alternative
+ string that will be displayed
+ when the target is built.
+
+ </para>
+
+ <para>
+
+ For example, suppose you want to
+ have &SCons; display a
+ <literal>"Compiling"</literal>
+ message whenever it's compiling an object file,
+ and a
+ <literal>"Linking"</literal>
+ when it's linking an executable.
+ You could write a &SConstruct; file
+ that looks like:
+
+ </para>
+
+ <scons_example name="COMSTR">
+ <file name="SConstruct" printme="1">
+ env = Environment(CCCOMSTR = "Compiling $TARGET",
+ LINKCOMSTR = "Linking $TARGET")
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which would then yield the output:
+
+ </para>
+
+ <!--
+
+ <scons_output example="COMSTR" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Compiling foo.o
+ Linking foo
+ </screen>
+
+ <para>
+
+ &SCons; performs complete variable substitution
+ on <envar>$*COMSTR</envar> variables,
+ so they have access to all of the
+ standard variables like &cv-TARGET; &cv-SOURCES;, etc.,
+ as well as any construction variables
+ that happen to be configured in
+ the construction environment
+ used to build a specific target.
+
+ </para>
+
+ <para>
+
+ Of course, sometimes it's still important to
+ be able to see the exact command
+ that &SCons; will execute to build a target.
+ For example, you may simply need to verify
+ that &SCons; is configured to supply
+ the right options to the compiler,
+ or a developer may want to
+ cut-and-paste a compile command
+ to add a few options
+ for a custom test.
+
+ </para>
+
+ <para>
+
+ One common way to give users
+ control over whether or not
+ &SCons; should print the actual command line
+ or a short, configured summary
+ is to add support for a
+ <varname>VERBOSE</varname>
+ command-line variable to your &SConstruct; file.
+ A simple configuration for this might look like:
+
+ </para>
+
+ <scons_example name="COMSTR-VERBOSE">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ if ARGUMENTS.get('VERBOSE') != "1':
+ env['CCCOMSTR'] = "Compiling $TARGET"
+ env['LINKCOMSTR'] = "Linking $TARGET"
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+
+ By only setting the appropriate
+ <envar>$*COMSTR</envar> variables
+ if the user specifies
+ <literal>VERBOSE=1</literal>
+ on the command line,
+ the user has control
+ over how &SCons;
+ displays these particular command lines:
+
+ </para>
+
+ <!--
+
+ <scons_output example="COMSTR-VERBOSE" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q VERBOSE=1</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Compiling foo.o
+ Linking foo
+ % <userinput>scons -Q -c</userinput>
+ Removed foo.o
+ Removed foo
+ % <userinput>scons -Q VERBOSE=1</userinput>
+ cc -o foo.o -c foo.c
+ cc -o foo foo.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Providing Build Progress Output: the &Progress; Function</title>
+
+ <para>
+
+ Another aspect of providing good build output
+ is to give the user feedback
+ about what &SCons; is doing
+ even when nothing is being built at the moment.
+ This can be especially true for large builds
+ when most of the targets are already up-to-date.
+ Because &SCons; can take a long time
+ making absolutely sure that every
+ target is, in fact, up-to-date
+ with respect to a lot of dependency files,
+ it can be easy for users to mistakenly
+ conclude that &SCons; is hung
+ or that there is some other problem with the build.
+
+ </para>
+
+ <para>
+
+ One way to deal with this perception
+ is to configure &SCons; to print something to
+ let the user know what it's "thinking about."
+ The &Progress; function
+ allows you to specify a string
+ that will be printed for every file
+ that &SCons; is "considering"
+ while it is traversing the dependency graph
+ to decide what targets are or are not up-to-date.
+
+ </para>
+
+ <scons_example name="Progress-TARGET">
+ <file name="SConstruct" printme="1">
+ Progress('Evaluating $TARGET\n')
+ Program('f1.c')
+ Program('f2.c')
+ </file>
+ <file name="f1.c">
+ f1.c
+ </file>
+ <file name="f2.c">
+ f2.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Note that the &Progress; function does not
+ arrange for a newline to be printed automatically
+ at the end of the string (as does the Python
+ <literal>print</literal> statement),
+ and we must specify the
+ <literal>\n</literal>
+ that we want printed at the end of the configured string.
+ This configuration, then,
+ will have &SCons;
+ print that it is <literal>Evaluating</literal>
+ each file that it encounters
+ in turn as it traverses the dependency graph:
+
+ </para>
+
+ <scons_output example="Progress-TARGET" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Of course, normally you don't want to add
+ all of these additional lines to your build output,
+ as that can make it difficult for the user
+ to find errors or other important messages.
+ A more useful way to display
+ this progress might be
+ to have the file names printed
+ directly to the user's screen,
+ not to the same standard output
+ stream where build output is printed,
+ and to use a carriage return character
+ (<literal>\r</literal>)
+ so that each file name gets re-printed on the same line.
+ Such a configuration would look like:
+
+ </para>
+
+ <sconstruct>
+ Progress('$TARGET\r',
+ file=open('/dev/tty', 'w'),
+ overwrite=True)
+ Program('f1.c')
+ Program('f2.c')
+ </sconstruct>
+
+ <para>
+
+ Note that we also specified the
+ <literal>overwrite=True</literal> argument
+ to the &Progress; function,
+ which causes &SCons; to
+ "wipe out" the previous string with space characters
+ before printing the next &Progress; string.
+ Without the
+ <literal>overwrite=True</literal> argument,
+ a shorter file name would not overwrite
+ all of the charactes in a longer file name that
+ precedes it,
+ making it difficult to tell what the
+ actual file name is on the output.
+ Also note that we opened up the
+ <filename>/dev/tty</filename> file
+ for direct access (on POSIX) to
+ the user's screen.
+ On Windows, the equivalent would be to open
+ the <filename>con:</filename> file name.
+
+ </para>
+
+ <para>
+
+ Also, it's important to know that although you can use
+ <literal>$TARGET</literal> to substitute the name of
+ the node in the string,
+ the &Progress; function does <emphasis>not</emphasis>
+ perform general variable substitution
+ (because there's not necessarily a construction
+ environment involved in evaluating a node
+ like a source file, for example).
+
+ </para>
+
+ <para>
+
+ You can also specify a list of strings
+ to the &Progress; function,
+ in which case &SCons; will
+ display each string in turn.
+ This can be used to implement a "spinner"
+ by having &SCons; cycle through a
+ sequence of strings:
+
+ </para>
+
+ <sconstruct>
+ Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5)
+ Program('f1.c')
+ Program('f2.c')
+ </sconstruct>
+
+ <para>
+
+ Note that here we have also used the
+ <literal>interval=</literal>
+ keyword argument to have &SCons;
+ only print a new "spinner" string
+ once every five evaluated nodes.
+ Using an <literal>interval=</literal> count,
+ even with strings that use <literal>$TARGET</literal> like
+ our examples above,
+ can be a good way to lessen the
+ work that &SCons; expends printing &Progress; strings,
+ while still giving the user feedback
+ that indicates &SCons; is still
+ working on evaluating the build.
+
+ </para>
+
+ <para>
+
+ Lastly, you can have direct control
+ over how to print each evaluated node
+ by passing a Python function
+ (or other Python callable)
+ to the &Progress function.
+ Your function will be called
+ for each evaluated node,
+ allowing you to
+ implement more sophisticated logic
+ like adding a counter:
+
+ </para>
+
+ <scons_example name="Progress-callable">
+ <file name="SConstruct" printme="1">
+ screen = open('/dev/tty', 'w')
+ count = 0
+ def progress_function(node)
+ count += 1
+ screen.write('Node %4d: %s\r' % (count, node))
+
+ Progress(progress_function)
+ </file>
+ </scons_example>
+
+ <para>
+
+ Of course, if you choose,
+ you could completely ignore the
+ <varname>node</varname> argument to the function,
+ and just print a count,
+ or anything else you wish.
+
+ </para>
+
+ <para>
+
+ (Note that there's an obvious follow-on question here:
+ how would you find the total number of nodes
+ that <emphasis>will be</emphasis>
+ evaluated so you can tell the user how
+ close the build is to finishing?
+ Unfortunately, in the general case,
+ there isn't a good way to do that,
+ short of having &SCons; evaluate its
+ dependency graph twice,
+ first to count the total and
+ the second time to actually build the targets.
+ This would be necessary because
+ you can't know in advance which
+ target(s) the user actually requested
+ to be built.
+ The entire build may consist of thousands of Nodes,
+ for example,
+ but maybe the user specifically requested
+ that only a single object file be built.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Printing Detailed Build Status: the &GetBuildFailures; Function</title>
+
+ <para>
+
+ SCons, like most build tools, returns zero status to
+ the shell on success and nonzero status on failure.
+ Sometimes it's useful to give more information about
+ the build status at the end of the run, for instance
+ to print an informative message, send an email, or
+ page the poor slob who broke the build.
+
+ </para>
+
+ <para>
+
+ SCons provides a &GetBuildFailures; method that
+ you can use in a python <function>atexit</function> function
+ to get a list of objects describing the actions that failed
+ while attempting to build targets. There can be more
+ than one if you're using <literal>-j</literal>. Here's a
+ simple example:
+
+ </para>
+
+ <scons_example name="gbf1">
+ <file name="SConstruct" printme="1">
+ import atexit
+
+ def print_build_failures():
+ from SCons.Script import GetBuildFailures
+ for bf in GetBuildFailures():
+ print "%s failed: %s" % (bf.node, bf.errstr)
+ atexit.register(print_build_failures)
+ </file>
+ </scons_example>
+
+ <para>
+
+ The <function>atexit.register</function> call
+ registers <function>print_build_failures</function>
+ as an <function>atexit</function> callback, to be called
+ before &SCons; exits. When that function is called,
+ it calls &GetBuildFailures; to fetch the list of failed objects.
+ See the man page
+ for the detailed contents of the returned objects;
+ some of the more useful attributes are
+ <literal>.node</literal>,
+ <literal>.errstr</literal>,
+ <literal>.filename</literal>, and
+ <literal>.command</literal>.
+ The <literal>filename</literal> is not necessarily
+ the same file as the <literal>node</literal>; the
+ <literal>node</literal> is the target that was
+ being built when the error occurred, while the
+ <literal>filename</literal>is the file or dir that
+ actually caused the error.
+ Note: only call &GetBuildFailures; at the end of the
+ build; calling it at any other time is undefined.
+
+ </para>
+
+ <para>
+
+ Here is a more complete example showing how to
+ turn each element of &GetBuildFailures; into a string:
+
+ </para>
+
+ <scons_example name="gbf2">
+ <file name="SConstruct" printme="1">
+ # Make the build fail if we pass fail=1 on the command line
+ if ARGUMENTS.get('fail', 0):
+ Command('target', 'source', ['/bin/false'])
+
+ def bf_to_str(bf):
+ """Convert an element of GetBuildFailures() to a string
+ in a useful way."""
+ import SCons.Errors
+ if bf is None: # unknown targets product None in list
+ return '(unknown tgt)'
+ elif isinstance(bf, SCons.Errors.StopError):
+ return str(bf)
+ elif bf.node:
+ return str(bf.node) + ': ' + bf.errstr
+ elif bf.filename:
+ return bf.filename + ': ' + bf.errstr
+ return 'unknown failure: ' + bf.errstr
+ import atexit
+
+ def build_status():
+ """Convert the build status to a 2-tuple, (status, msg)."""
+ from SCons.Script import GetBuildFailures
+ bf = GetBuildFailures()
+ if bf:
+ # bf is normally a list of build failures; if an element is None,
+ # it's because of a target that scons doesn't know anything about.
+ status = 'failed'
+ failures_message = "\n".join(["Failed building %s" % bf_to_str(x)
+ for x in bf if x is not None])
+ else:
+ # if bf is None, the build completed successfully.
+ status = 'ok'
+ failures_message = ''
+ return (status, failures_message)
+
+ def display_build_status():
+ """Display the build status. Called by atexit.
+ Here you could do all kinds of complicated things."""
+ status, failures_message = build_status()
+ if status == 'failed':
+ print "FAILED!!!!" # could display alert, ring bell, etc.
+ elif status == 'ok':
+ print "Build succeeded."
+ print failures_message
+
+ atexit.register(display_build_status)
+ </file>
+ </scons_example>
+
+ <para>
+
+ When this runs, you'll see the appropriate output:
+
+ </para>
+
+ <scons_output example="gbf2">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q fail=1</scons_output_command>
+ </scons_output>
+
+ </section>
diff --git a/doc/user/output.xml b/doc/user/output.xml
new file mode 100644
index 0000000..89b443b
--- /dev/null
+++ b/doc/user/output.xml
@@ -0,0 +1,703 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ A key aspect of creating a usable build configuration
+ is providing good output from the build
+ so its users can readily understand
+ what the build is doing
+ and get information about how to control the build.
+ &SCons; provides several ways of
+ controlling output from the build configuration
+ to help make the build
+ more useful and understandable.
+
+ </para>
+
+ <section>
+ <title>Providing Build Help: the &Help; Function</title>
+
+ <para>
+
+ It's often very useful to be able to give
+ users some help that describes the
+ specific targets, build options, etc.,
+ that can be used for your build.
+ &SCons; provides the &Help; function
+ to allow you to specify this help text:
+
+ </para>
+
+ <programlisting>
+ Help("""
+ Type: 'scons program' to build the production program,
+ 'scons debug' to build the debug version.
+ """)
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -h</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+
+ Type: 'scons program' to build the production program,
+ 'scons debug' to build the debug version.
+
+ Use scons -H for help about command-line options.
+ </screen>
+
+ <para>
+
+ The &SConscript; files may contain
+ multiple calls to the &Help; function,
+ in which case the specified text(s)
+ will be concatenated when displayed.
+ This allows you to split up the
+ help text across multiple &SConscript; files.
+ In this situation, the order in
+ which the &SConscript; files are called
+ will determine the order in which the &Help; functions are called,
+ which will determine the order in which
+ the various bits of text will get concatenated.
+
+ </para>
+
+ <para>
+
+ Another use would be to make the help text conditional
+ on some variable.
+ For example, suppose you only want to display
+ a line about building a Windows-only
+ version of a program when actually
+ run on Windows.
+ The following &SConstruct; file:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+
+ Help("\nType: 'scons program' to build the production program.\n")
+
+ if env['PLATFORM'] == 'win32':
+ Help("\nType: 'scons windebug' to build the Windows debug version.\n")
+ </programlisting>
+
+ <para>
+
+ Will display the complete help text on Windows:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -h</userinput>
+ scons: Reading SConscript files ...
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ scons: done reading SConscript files.
+
+ Type: 'scons program' to build the production program.
+
+ Type: 'scons windebug' to build the Windows debug version.
+
+ Use scons -H for help about command-line options.
+ </screen>
+
+ <para>
+
+ But only show the relevant option on a Linux or UNIX system:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -h</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+
+ Type: 'scons program' to build the production program.
+
+ Use scons -H for help about command-line options.
+ </screen>
+
+ <para>
+
+ If there is no &Help; text in the &SConstruct; or
+ &SConscript; files,
+ &SCons; will revert to displaying its
+ standard list that describes the &SCons; command-line
+ options.
+ This list is also always displayed whenever
+ the <literal>-H</literal> option is used.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Controlling How &SCons; Prints Build Commands: the <envar>$*COMSTR</envar> Variables</title>
+
+ <para>
+
+ Sometimes the commands executed
+ to compile object files or link programs
+ (or build other targets)
+ can get very long,
+ long enough to make it difficult for users
+ to distinguish error messages or
+ other important build output
+ from the commands themselves.
+ All of the default <envar>$*COM</envar> variables
+ that specify the command lines
+ used to build various types of target files
+ have a corresponding <envar>$*COMSTR</envar> variable
+ that can be set to an alternative
+ string that will be displayed
+ when the target is built.
+
+ </para>
+
+ <para>
+
+ For example, suppose you want to
+ have &SCons; display a
+ <literal>"Compiling"</literal>
+ message whenever it's compiling an object file,
+ and a
+ <literal>"Linking"</literal>
+ when it's linking an executable.
+ You could write a &SConstruct; file
+ that looks like:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CCCOMSTR = "Compiling $TARGET",
+ LINKCOMSTR = "Linking $TARGET")
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ Which would then yield the output:
+
+ </para>
+
+ <!--
+
+ <scons_output example="COMSTR" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Compiling foo.o
+ Linking foo
+ </screen>
+
+ <para>
+
+ &SCons; performs complete variable substitution
+ on <envar>$*COMSTR</envar> variables,
+ so they have access to all of the
+ standard variables like &cv-TARGET; &cv-SOURCES;, etc.,
+ as well as any construction variables
+ that happen to be configured in
+ the construction environment
+ used to build a specific target.
+
+ </para>
+
+ <para>
+
+ Of course, sometimes it's still important to
+ be able to see the exact command
+ that &SCons; will execute to build a target.
+ For example, you may simply need to verify
+ that &SCons; is configured to supply
+ the right options to the compiler,
+ or a developer may want to
+ cut-and-paste a compile command
+ to add a few options
+ for a custom test.
+
+ </para>
+
+ <para>
+
+ One common way to give users
+ control over whether or not
+ &SCons; should print the actual command line
+ or a short, configured summary
+ is to add support for a
+ <varname>VERBOSE</varname>
+ command-line variable to your &SConstruct; file.
+ A simple configuration for this might look like:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ if ARGUMENTS.get('VERBOSE') != "1':
+ env['CCCOMSTR'] = "Compiling $TARGET"
+ env['LINKCOMSTR'] = "Linking $TARGET"
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+
+ By only setting the appropriate
+ <envar>$*COMSTR</envar> variables
+ if the user specifies
+ <literal>VERBOSE=1</literal>
+ on the command line,
+ the user has control
+ over how &SCons;
+ displays these particular command lines:
+
+ </para>
+
+ <!--
+
+ <scons_output example="COMSTR-VERBOSE" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q VERBOSE=1</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Compiling foo.o
+ Linking foo
+ % <userinput>scons -Q -c</userinput>
+ Removed foo.o
+ Removed foo
+ % <userinput>scons -Q VERBOSE=1</userinput>
+ cc -o foo.o -c foo.c
+ cc -o foo foo.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Providing Build Progress Output: the &Progress; Function</title>
+
+ <para>
+
+ Another aspect of providing good build output
+ is to give the user feedback
+ about what &SCons; is doing
+ even when nothing is being built at the moment.
+ This can be especially true for large builds
+ when most of the targets are already up-to-date.
+ Because &SCons; can take a long time
+ making absolutely sure that every
+ target is, in fact, up-to-date
+ with respect to a lot of dependency files,
+ it can be easy for users to mistakenly
+ conclude that &SCons; is hung
+ or that there is some other problem with the build.
+
+ </para>
+
+ <para>
+
+ One way to deal with this perception
+ is to configure &SCons; to print something to
+ let the user know what it's "thinking about."
+ The &Progress; function
+ allows you to specify a string
+ that will be printed for every file
+ that &SCons; is "considering"
+ while it is traversing the dependency graph
+ to decide what targets are or are not up-to-date.
+
+ </para>
+
+ <programlisting>
+ Progress('Evaluating $TARGET\n')
+ Program('f1.c')
+ Program('f2.c')
+ </programlisting>
+
+ <para>
+
+ Note that the &Progress; function does not
+ arrange for a newline to be printed automatically
+ at the end of the string (as does the Python
+ <literal>print</literal> statement),
+ and we must specify the
+ <literal>\n</literal>
+ that we want printed at the end of the configured string.
+ This configuration, then,
+ will have &SCons;
+ print that it is <literal>Evaluating</literal>
+ each file that it encounters
+ in turn as it traverses the dependency graph:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Evaluating SConstruct
+ Evaluating f1.c
+ Evaluating f1.o
+ cc -o f1.o -c f1.c
+ Evaluating f1
+ cc -o f1 f1.o
+ Evaluating f2.c
+ Evaluating f2.o
+ cc -o f2.o -c f2.c
+ Evaluating f2
+ cc -o f2 f2.o
+ Evaluating .
+ </screen>
+
+ <para>
+
+ Of course, normally you don't want to add
+ all of these additional lines to your build output,
+ as that can make it difficult for the user
+ to find errors or other important messages.
+ A more useful way to display
+ this progress might be
+ to have the file names printed
+ directly to the user's screen,
+ not to the same standard output
+ stream where build output is printed,
+ and to use a carriage return character
+ (<literal>\r</literal>)
+ so that each file name gets re-printed on the same line.
+ Such a configuration would look like:
+
+ </para>
+
+ <programlisting>
+ Progress('$TARGET\r',
+ file=open('/dev/tty', 'w'),
+ overwrite=True)
+ Program('f1.c')
+ Program('f2.c')
+ </programlisting>
+
+ <para>
+
+ Note that we also specified the
+ <literal>overwrite=True</literal> argument
+ to the &Progress; function,
+ which causes &SCons; to
+ "wipe out" the previous string with space characters
+ before printing the next &Progress; string.
+ Without the
+ <literal>overwrite=True</literal> argument,
+ a shorter file name would not overwrite
+ all of the charactes in a longer file name that
+ precedes it,
+ making it difficult to tell what the
+ actual file name is on the output.
+ Also note that we opened up the
+ <filename>/dev/tty</filename> file
+ for direct access (on POSIX) to
+ the user's screen.
+ On Windows, the equivalent would be to open
+ the <filename>con:</filename> file name.
+
+ </para>
+
+ <para>
+
+ Also, it's important to know that although you can use
+ <literal>$TARGET</literal> to substitute the name of
+ the node in the string,
+ the &Progress; function does <emphasis>not</emphasis>
+ perform general variable substitution
+ (because there's not necessarily a construction
+ environment involved in evaluating a node
+ like a source file, for example).
+
+ </para>
+
+ <para>
+
+ You can also specify a list of strings
+ to the &Progress; function,
+ in which case &SCons; will
+ display each string in turn.
+ This can be used to implement a "spinner"
+ by having &SCons; cycle through a
+ sequence of strings:
+
+ </para>
+
+ <programlisting>
+ Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5)
+ Program('f1.c')
+ Program('f2.c')
+ </programlisting>
+
+ <para>
+
+ Note that here we have also used the
+ <literal>interval=</literal>
+ keyword argument to have &SCons;
+ only print a new "spinner" string
+ once every five evaluated nodes.
+ Using an <literal>interval=</literal> count,
+ even with strings that use <literal>$TARGET</literal> like
+ our examples above,
+ can be a good way to lessen the
+ work that &SCons; expends printing &Progress; strings,
+ while still giving the user feedback
+ that indicates &SCons; is still
+ working on evaluating the build.
+
+ </para>
+
+ <para>
+
+ Lastly, you can have direct control
+ over how to print each evaluated node
+ by passing a Python function
+ (or other Python callable)
+ to the &Progress; function.
+ Your function will be called
+ for each evaluated node,
+ allowing you to
+ implement more sophisticated logic
+ like adding a counter:
+
+ </para>
+
+ <programlisting>
+ screen = open('/dev/tty', 'w')
+ count = 0
+ def progress_function(node)
+ count += 1
+ screen.write('Node %4d: %s\r' % (count, node))
+
+ Progress(progress_function)
+ </programlisting>
+
+ <para>
+
+ Of course, if you choose,
+ you could completely ignore the
+ <varname>node</varname> argument to the function,
+ and just print a count,
+ or anything else you wish.
+
+ </para>
+
+ <para>
+
+ (Note that there's an obvious follow-on question here:
+ how would you find the total number of nodes
+ that <emphasis>will be</emphasis>
+ evaluated so you can tell the user how
+ close the build is to finishing?
+ Unfortunately, in the general case,
+ there isn't a good way to do that,
+ short of having &SCons; evaluate its
+ dependency graph twice,
+ first to count the total and
+ the second time to actually build the targets.
+ This would be necessary because
+ you can't know in advance which
+ target(s) the user actually requested
+ to be built.
+ The entire build may consist of thousands of Nodes,
+ for example,
+ but maybe the user specifically requested
+ that only a single object file be built.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Printing Detailed Build Status: the &GetBuildFailures; Function</title>
+
+ <para>
+
+ SCons, like most build tools, returns zero status to
+ the shell on success and nonzero status on failure.
+ Sometimes it's useful to give more information about
+ the build status at the end of the run, for instance
+ to print an informative message, send an email, or
+ page the poor slob who broke the build.
+
+ </para>
+
+ <para>
+
+ SCons provides a &GetBuildFailures; method that
+ you can use in a python <function>atexit</function> function
+ to get a list of objects describing the actions that failed
+ while attempting to build targets. There can be more
+ than one if you're using <literal>-j</literal>. Here's a
+ simple example:
+
+ </para>
+
+ <programlisting>
+ import atexit
+
+ def print_build_failures():
+ from SCons.Script import GetBuildFailures
+ for bf in GetBuildFailures():
+ print "%s failed: %s" % (bf.node, bf.errstr)
+ atexit.register(print_build_failures)
+ </programlisting>
+
+ <para>
+
+ The <function>atexit.register</function> call
+ registers <function>print_build_failures</function>
+ as an <function>atexit</function> callback, to be called
+ before &SCons; exits. When that function is called,
+ it calls &GetBuildFailures; to fetch the list of failed objects.
+ See the man page
+ for the detailed contents of the returned objects;
+ some of the more useful attributes are
+ <literal>.node</literal>,
+ <literal>.errstr</literal>,
+ <literal>.filename</literal>, and
+ <literal>.command</literal>.
+ The <literal>filename</literal> is not necessarily
+ the same file as the <literal>node</literal>; the
+ <literal>node</literal> is the target that was
+ being built when the error occurred, while the
+ <literal>filename</literal>is the file or dir that
+ actually caused the error.
+ Note: only call &GetBuildFailures; at the end of the
+ build; calling it at any other time is undefined.
+
+ </para>
+
+ <para>
+
+ Here is a more complete example showing how to
+ turn each element of &GetBuildFailures; into a string:
+
+ </para>
+
+ <programlisting>
+ # Make the build fail if we pass fail=1 on the command line
+ if ARGUMENTS.get('fail', 0):
+ Command('target', 'source', ['/bin/false'])
+
+ def bf_to_str(bf):
+ """Convert an element of GetBuildFailures() to a string
+ in a useful way."""
+ import SCons.Errors
+ if bf is None: # unknown targets product None in list
+ return '(unknown tgt)'
+ elif isinstance(bf, SCons.Errors.StopError):
+ return str(bf)
+ elif bf.node:
+ return str(bf.node) + ': ' + bf.errstr
+ elif bf.filename:
+ return bf.filename + ': ' + bf.errstr
+ return 'unknown failure: ' + bf.errstr
+ import atexit
+
+ def build_status():
+ """Convert the build status to a 2-tuple, (status, msg)."""
+ from SCons.Script import GetBuildFailures
+ bf = GetBuildFailures()
+ if bf:
+ # bf is normally a list of build failures; if an element is None,
+ # it's because of a target that scons doesn't know anything about.
+ status = 'failed'
+ failures_message = "\n".join(["Failed building %s" % bf_to_str(x)
+ for x in bf if x is not None])
+ else:
+ # if bf is None, the build completed successfully.
+ status = 'ok'
+ failures_message = ''
+ return (status, failures_message)
+
+ def display_build_status():
+ """Display the build status. Called by atexit.
+ Here you could do all kinds of complicated things."""
+ status, failures_message = build_status()
+ if status == 'failed':
+ print "FAILED!!!!" # could display alert, ring bell, etc.
+ elif status == 'ok':
+ print "Build succeeded."
+ print failures_message
+
+ atexit.register(display_build_status)
+ </programlisting>
+
+ <para>
+
+ When this runs, you'll see the appropriate output:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ Build succeeded.
+ % <userinput>scons -Q fail=1</userinput>
+ scons: *** [target] Source `source' not found, needed by target `target'.
+ FAILED!!!!
+ Failed building target: Source `source' not found, needed by target `target'.
+ </screen>
+
+ </section>
diff --git a/doc/user/parseconfig.in b/doc/user/parseconfig.in
new file mode 100644
index 0000000..db97c35
--- /dev/null
+++ b/doc/user/parseconfig.in
@@ -0,0 +1,114 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ Configuring the right options to build programs to work with
+ libraries--especially shared libraries--that are available
+ on POSIX systems can be very complicated.
+ To help this situation,
+ various utilies with names that end in <filename>config</filename>
+ return the command-line options for the GNU Compiler Collection (GCC)
+ that are needed to use these libraries;
+ for example, the command-line options
+ to use a library named <filename>lib</filename>
+ would be found by calling a utility named <filename>lib-config</filename>.
+
+ </para>
+
+ <para>
+
+ A more recent convention is that these options
+ are available from the generic <filename>pkg-config</filename> program,
+ which has common framework, error handling, and the like,
+ so that all the package creator has to do is provide the set of strings
+ for his particular package.
+
+ </para>
+
+ <para>
+
+ &SCons; construction environments have a &ParseConfig; method
+ that executes a <filename>*config</filename> utility
+ (either <filename>pkg-config</filename> or a
+ more specific utility)
+ and configures the appropriate construction variables
+ in the environment
+ based on the command-line options
+ returned by the specified command.
+
+ </para>
+
+ <scons_example name="ParseConfig1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env['CPPPATH'] = ['/lib/compat']
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ print env['CPPPATH']
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; will execute the specified command string,
+ parse the resultant flags,
+ and add the flags to the appropriate environment variables.
+
+ </para>
+
+ <scons_output example="ParseConfig1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In the example above, &SCons; has added the include directory to
+ <varname>CPPPATH</varname>.
+ (Depending upon what other flags are emitted by the
+ <filename>pkg-config</filename> command,
+ other variables may have been extended as well.)
+
+ </para>
+
+ <para>
+
+ Note that the options are merged with existing options using
+ the &MergeFlags; method,
+ so that each option only occurs once in the construction variable:
+
+ </para>
+
+ <scons_example name="ParseConfig2">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ print env['CPPPATH']
+ </file>
+ </scons_example>
+
+ <scons_output example="ParseConfig2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
diff --git a/doc/user/parseconfig.xml b/doc/user/parseconfig.xml
new file mode 100644
index 0000000..1f85ad0
--- /dev/null
+++ b/doc/user/parseconfig.xml
@@ -0,0 +1,132 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ Configuring the right options to build programs to work with
+ libraries--especially shared libraries--that are available
+ on POSIX systems can be very complicated.
+ To help this situation,
+ various utilies with names that end in <filename>config</filename>
+ return the command-line options for the GNU Compiler Collection (GCC)
+ that are needed to use these libraries;
+ for example, the command-line options
+ to use a library named <filename>lib</filename>
+ would be found by calling a utility named <filename>lib-config</filename>.
+
+ </para>
+
+ <para>
+
+ A more recent convention is that these options
+ are available from the generic <filename>pkg-config</filename> program,
+ which has common framework, error handling, and the like,
+ so that all the package creator has to do is provide the set of strings
+ for his particular package.
+
+ </para>
+
+ <para>
+
+ &SCons; construction environments have a &ParseConfig; method
+ that executes a <filename>*config</filename> utility
+ (either <filename>pkg-config</filename> or a
+ more specific utility)
+ and configures the appropriate construction variables
+ in the environment
+ based on the command-line options
+ returned by the specified command.
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env['CPPPATH'] = ['/lib/compat']
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ print env['CPPPATH']
+ </programlisting>
+
+ <para>
+
+ &SCons; will execute the specified command string,
+ parse the resultant flags,
+ and add the flags to the appropriate environment variables.
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Package x11 was not found in the pkg-config search path.
+ Perhaps you should add the directory containing `x11.pc'
+ to the PKG_CONFIG_PATH environment variable
+ No package 'x11' found
+ OSError: 'pkg-config x11 --cflags --libs' exited 1:
+ File "/home/my/project/SConstruct", line 3:
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ File "bootstrap/src/engine/SCons/Environment.py", line 1474:
+ None
+ File "bootstrap/src/engine/SCons/Environment.py", line 593:
+ None
+ </screen>
+
+ <para>
+
+ In the example above, &SCons; has added the include directory to
+ <varname>CPPPATH</varname>.
+ (Depending upon what other flags are emitted by the
+ <filename>pkg-config</filename> command,
+ other variables may have been extended as well.)
+
+ </para>
+
+ <para>
+
+ Note that the options are merged with existing options using
+ the &MergeFlags; method,
+ so that each option only occurs once in the construction variable:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ print env['CPPPATH']
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ Package x11 was not found in the pkg-config search path.
+ Perhaps you should add the directory containing `x11.pc'
+ to the PKG_CONFIG_PATH environment variable
+ No package 'x11' found
+ OSError: 'pkg-config x11 --cflags --libs' exited 1:
+ File "/home/my/project/SConstruct", line 2:
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ File "bootstrap/src/engine/SCons/Environment.py", line 1474:
+ None
+ File "bootstrap/src/engine/SCons/Environment.py", line 593:
+ None
+ </screen>
diff --git a/doc/user/parseflags.in b/doc/user/parseflags.in
new file mode 100644
index 0000000..b21df4f
--- /dev/null
+++ b/doc/user/parseflags.in
@@ -0,0 +1,184 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; has a bewildering array of construction variables
+ for different types of options when building programs.
+ Sometimes you may not know exactly which variable
+ should be used for a particular option.
+
+ </para>
+
+ <para>
+
+ &SCons; construction environments have a &ParseFlags; method
+ that takes a set of typical command-line options
+ and distrbutes them into the appropriate construction variables.
+ Historically, it was created to support the &ParseConfig; method,
+ so it focuses on options used by the GNU Compiler Collection (GCC)
+ for the C and C++ toolchains.
+
+ </para>
+
+ <para>
+
+ &ParseFlags; returns a dictionary containing the options
+ distributed into their respective construction variables.
+ Normally, this dictionary would be passed to &MergeFlags;
+ to merge the options into a &consenv;,
+ but the dictionary can be edited if desired to provide
+ additional functionality.
+ (Note that if the flags are not going to be edited,
+ calling &MergeFlags; with the options directly
+ will avoid an additional step.)
+
+ </para>
+
+ <scons_example name="ParseFlags1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo")
+ l = d.items()
+ l.sort()
+ for k,v in l:
+ if v:
+ print k, v
+ env.MergeFlags(d)
+ env.Program('f1.c')
+ </file>
+ <file name="f1.c">
+ int main() { return 0; }
+ </file>
+ </scons_example>
+
+ <scons_output example="ParseFlags1" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that if the options are limited to generic types
+ like those above,
+ they will be correctly translated for other platform types:
+
+ </para>
+
+ <scons_output example="ParseFlags1" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Since the assumption is that the flags are used for the GCC toolchain,
+ unrecognized flags are placed in &cv-link-CCFLAGS;
+ so they will be used for both C and C++ compiles:
+
+ </para>
+
+ <scons_example name="ParseFlags2">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ d = env.ParseFlags("-whatever")
+ l = d.items()
+ l.sort()
+ for k,v in l:
+ if v:
+ print k, v
+ env.MergeFlags(d)
+ env.Program('f1.c')
+ </file>
+ <file name="f1.c">
+ int main() { return 0; }
+ </file>
+ </scons_example>
+
+ <scons_output example="ParseFlags2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ &ParseFlags; will also accept a (recursive) list of strings as input;
+ the list is flattened before the strings are processed:
+
+ </para>
+
+ <scons_example name="ParseFlags3">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]])
+ l = d.items()
+ l.sort()
+ for k,v in l:
+ if v:
+ print k, v
+ env.MergeFlags(d)
+ env.Program('f1.c')
+ </file>
+ <file name="f1.c">
+ int main() { return 0; }
+ </file>
+ </scons_example>
+
+ <scons_output example="ParseFlags3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If a string begins with a "!" (an exclamation mark, often called a bang),
+ the string is passed to the shell for execution.
+ The output of the command is then parsed:
+
+ </para>
+
+ <scons_example name="ParseFlags4">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"])
+ l = d.items()
+ l.sort()
+ for k,v in l:
+ if v:
+ print k, v
+ env.MergeFlags(d)
+ env.Program('f1.c')
+ </file>
+ <file name="f1.c">
+ int main() { return 0; }
+ </file>
+ </scons_example>
+
+ <scons_output example="ParseFlags4">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ &ParseFlags; is regularly updated for new options;
+ consult the man page for details about those currently recognized.
+
+ </para>
diff --git a/doc/user/parseflags.xml b/doc/user/parseflags.xml
new file mode 100644
index 0000000..6900291
--- /dev/null
+++ b/doc/user/parseflags.xml
@@ -0,0 +1,199 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; has a bewildering array of construction variables
+ for different types of options when building programs.
+ Sometimes you may not know exactly which variable
+ should be used for a particular option.
+
+ </para>
+
+ <para>
+
+ &SCons; construction environments have a &ParseFlags; method
+ that takes a set of typical command-line options
+ and distrbutes them into the appropriate construction variables.
+ Historically, it was created to support the &ParseConfig; method,
+ so it focuses on options used by the GNU Compiler Collection (GCC)
+ for the C and C++ toolchains.
+
+ </para>
+
+ <para>
+
+ &ParseFlags; returns a dictionary containing the options
+ distributed into their respective construction variables.
+ Normally, this dictionary would be passed to &MergeFlags;
+ to merge the options into a &consenv;,
+ but the dictionary can be edited if desired to provide
+ additional functionality.
+ (Note that if the flags are not going to be edited,
+ calling &MergeFlags; with the options directly
+ will avoid an additional step.)
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo")
+ l = d.items()
+ l.sort()
+ for k,v in l:
+ if v:
+ print k, v
+ env.MergeFlags(d)
+ env.Program('f1.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CPPPATH ['/opt/include']
+ LIBPATH ['/opt/lib']
+ LIBS ['foo']
+ cc -o f1.o -c -I/opt/include f1.c
+ cc -o f1 f1.o -L/opt/lib -lfoo
+ </screen>
+
+ <para>
+
+ Note that if the options are limited to generic types
+ like those above,
+ they will be correctly translated for other platform types:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ CPPPATH ['/opt/include']
+ LIBPATH ['/opt/lib']
+ LIBS ['foo']
+ cl /Fof1.obj /c f1.c /nologo /I\opt\include
+ link /nologo /OUT:f1.exe /LIBPATH:\opt\lib foo.lib f1.obj
+ </screen>
+
+ <para>
+
+ Since the assumption is that the flags are used for the GCC toolchain,
+ unrecognized flags are placed in &cv-link-CCFLAGS;
+ so they will be used for both C and C++ compiles:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ d = env.ParseFlags("-whatever")
+ l = d.items()
+ l.sort()
+ for k,v in l:
+ if v:
+ print k, v
+ env.MergeFlags(d)
+ env.Program('f1.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CCFLAGS -whatever
+ cc -o f1.o -c -whatever f1.c
+ cc -o f1 f1.o
+ </screen>
+
+ <para>
+
+ &ParseFlags; will also accept a (recursive) list of strings as input;
+ the list is flattened before the strings are processed:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]])
+ l = d.items()
+ l.sort()
+ for k,v in l:
+ if v:
+ print k, v
+ env.MergeFlags(d)
+ env.Program('f1.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CPPPATH ['/opt/include']
+ LIBPATH ['/opt/lib']
+ LIBS ['foo']
+ cc -o f1.o -c -I/opt/include f1.c
+ cc -o f1 f1.o -L/opt/lib -lfoo
+ </screen>
+
+ <para>
+
+ If a string begins with a "!" (an exclamation mark, often called a bang),
+ the string is passed to the shell for execution.
+ The output of the command is then parsed:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"])
+ l = d.items()
+ l.sort()
+ for k,v in l:
+ if v:
+ print k, v
+ env.MergeFlags(d)
+ env.Program('f1.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CPPPATH ['/opt/include']
+ LIBPATH ['/opt/lib']
+ LIBS ['foo']
+ cc -o f1.o -c -I/opt/include f1.c
+ cc -o f1 f1.o -L/opt/lib -lfoo
+ </screen>
+
+ <para>
+
+ &ParseFlags; is regularly updated for new options;
+ consult the man page for details about those currently recognized.
+
+ </para>
diff --git a/doc/user/preface.in b/doc/user/preface.in
new file mode 100644
index 0000000..de4cb43
--- /dev/null
+++ b/doc/user/preface.in
@@ -0,0 +1,426 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ Thank you for taking the time to read about &SCons;.
+ &SCons; is a next-generation
+ software construction tool,
+ or make tool--that is, a software utility
+ for building software (or other files)
+ and keeping built software up-to-date
+ whenever the underlying input files change.
+
+ </para>
+
+ <para>
+
+ The most distinctive thing about &SCons;
+ is that its configuration files are
+ actually <emphasis>scripts</emphasis>,
+ written in the &Python; programming language.
+ This is in contrast to most alternative build tools,
+ which typically invent a new language to
+ configure the build.
+ &SCons; still has a learning curve, of course,
+ because you have to know what functions to call
+ to set up your build properly,
+ but the underlying syntax used should be familiar
+ to anyone who has ever looked at a Python script.
+
+ </para>
+
+ <para>
+
+ Paradoxically,
+ using Python as the configuration file format
+ makes &SCons;
+ <emphasis>easier</emphasis>
+ for non-programmers to learn
+ than the cryptic languages of other build tools,
+ which are usually invented by programmers for other programmers.
+ This is in no small part due to the
+ consistency and readability that are hallmarks of Python.
+ It just so happens that making a real, live
+ scripting language the basis for the
+ configuration files
+ makes it a snap for more accomplished programmers
+ to do more complicated things with builds,
+ as necessary.
+
+ </para>
+
+ <!--
+
+ <section>
+ <title>Why &SCons;?</title>
+
+ <para>
+
+ &SCons; is a response to a perennial problem:
+ building software is harder than it should be.
+ In a nutshell: the old, reliable model of the
+ venerable and ubiquitous &Make; program
+ has had a hard time keeping up with
+ how complicated building software has become.
+ The fact that &Make; has kept up as well as it has is impressive,
+ and a testament to how the simplicity.
+ But anyone who has wrestled with &Automake; and &Autoconf;
+ to try to guarantee that a bit of software
+ will build correctly on multiple platforms
+ can tell you that it takes a lot of work to get right.
+
+ </para>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>&SCons; Principles</title>
+
+ <para>
+
+ There are a few overriding principles
+ we try to live up to in designing and implementing &SCons:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>Correctness</term>
+
+ <listitem>
+ <para>
+
+ First and foremost,
+ by default, &SCons; guarantees a correct build
+ even if it means sacrificing performance a little.
+ We strive to guarantee the build is correct
+ regardless of how the software being built is structured,
+ how it may have been written,
+ or how unusual the tools are that build it.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Performance</term>
+
+ <listitem>
+ <para>
+
+ Given that the build is correct,
+ we try to make &SCons; build software
+ as quickly as possible.
+ In particular, wherever we may have needed to slow
+ down the default &SCons; behavior to guarantee a correct build,
+ we also try to make it easy to speed up &SCons;
+ through optimization options that let you trade off
+ guaranteed correctness in all end cases for
+ a speedier build in the usual cases.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Convenience</term>
+
+ <listitem>
+ <para>
+
+ &SCons; tries to do as much for you out of the box as reasonable,
+ including detecting the right tools on your system
+ and using them correctly to build the software.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ In a nutshell, we try hard to make &SCons; just
+ "do the right thing" and build software correctly,
+ with a minimum of hassles.
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>History</title>
+
+ <para>
+
+ &SCons; originated with a design
+ that was submitted to the Software Carpentry
+ design competition in 2000.
+
+ </para>
+
+ <para>
+
+ &SCons; is the direct descendant
+ of a Perl utility called &Cons;.
+ &Cons; in turn based some of its ideas on &Jam;,
+ a build tool from Perforce Systems.
+
+ </para>
+
+ <para>
+
+ XXX history of SCons
+
+ </para>
+
+ </section>
+
+ -->
+
+ <!--
+
+ <section>
+ <title>Conventions</title>
+
+ <para>
+
+ XXX conventions used in this manual
+
+ </para>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>A Caveat About This Guide's Completeness</title>
+
+ <para>
+
+ One word of warning as you read through this Guide:
+ Like too much Open Source software out there,
+ the &SCons; documentation isn't always
+ kept up-to-date with the available features.
+ In other words,
+ there's a lot that &SCons; can do that
+ isn't yet covered in this User's Guide.
+ (Come to think of it,
+ that also describes a lot of proprietary software, doesn't it?)
+
+ </para>
+
+ <para>
+
+ Although this User's Guide isn't as complete as we'd like it to be,
+ our development process does emphasize
+ making sure that the &SCons; man page is kept up-to-date
+ with new features.
+ So if you're trying to figure out how to do something
+ that &SCons; supports
+ but can't find enough (or any) information here,
+ it would be worth your while to look
+ at the man page to see if the information is covered there.
+ And if you do,
+ maybe you'd even consider contributing
+ a section to the User's Guide
+ so the next person looking for
+ that information won't have to
+ go through the same thing...?
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Acknowledgements</title>
+
+ <para>
+
+ &SCons; would not exist without a lot of help
+ from a lot of people,
+ many of whom may not even be aware
+ that they helped or served as inspiration.
+ So in no particular order,
+ and at the risk of leaving out someone:
+
+ </para>
+
+ <para>
+
+ First and foremost,
+ &SCons; owes a tremendous debt to Bob Sidebotham,
+ the original author of the classic Perl-based &Cons; tool
+ which Bob first released to the world back around 1996.
+ Bob's work on Cons classic provided the underlying architecture
+ and model of specifying a build configuration
+ using a real scripting language.
+ My real-world experience working on Cons
+ informed many of the design decisions in SCons,
+ including the improved parallel build support,
+ making Builder objects easily definable by users,
+ and separating the build engine from the wrapping interface.
+
+ </para>
+
+ <para>
+
+ Greg Wilson was instrumental in getting
+ &SCons; started as a real project
+ when he initiated the Software Carpentry design
+ competition in February 2000.
+ Without that nudge,
+ marrying the advantages of the Cons classic
+ architecture with the readability of Python
+ might have just stayed no more than a nice idea.
+
+ </para>
+
+ <para>
+
+ The entire &SCons; team have been
+ absolutely wonderful to work with,
+ and &SCons; would be nowhere near as useful a
+ tool without the energy, enthusiasm
+ and time people have contributed over the past few years.
+ The "core team"
+ of Chad Austin, Anthony Roach,
+ Bill Deegan, Charles Crain, Steve Leblanc, Greg Noel,
+ Gary Oberbrunner, Greg Spencer and Christoph Wiedemann
+ have been great about reviewing my (and other) changes
+ and catching problems before they get in the code base.
+ Of particular technical note:
+ Anthony's outstanding and innovative work on the tasking engine
+ has given &SCons; a vastly superior parallel build model;
+ Charles has been the master of the crucial Node infrastructure;
+ Christoph's work on the Configure infrastructure
+ has added crucial Autoconf-like functionality;
+ and Greg has provided excellent support
+ for Microsoft Visual Studio.
+
+ </para>
+
+ <para>
+
+ Special thanks to David Snopek for contributing
+ his underlying "Autoscons" code that formed
+ the basis of Christoph's work with the Configure functionality.
+ David was extremely generous in making
+ this code available to &SCons;,
+ given that he initially released it under the GPL
+ and &SCons; is released under a less-restrictive MIT-style license.
+
+ </para>
+
+ <!--
+
+ <para>
+
+ &SCons; has received contributions
+ from many other people, of course:
+ Matt Balvin (extending long command-line support on Windows),
+ Allen Bierbaum (extensions and fixes to Options),
+ Steve Christensen (help text sorting and function action signature fixes),
+ Michael Cook (avoiding losing signal bits from executed commands),
+ Derrick 'dman' Hudson (),
+ Alex Jacques (work on the Windows scons.bat file),
+ Stephen Kennedy (performance enhancements),
+ Lachlan O'Dea (SharedObject() support for masm
+ and normalized paths for the WhereIs() function),
+ Damyan Pepper (keeping output like Make),
+ Jeff Petkau (significant fixes for CacheDir and other areas),
+ Stefan Reichor (Ghostscript support),
+ Zed Shaw (Append() and Replace() environment methods),
+ Terrel Shumway (build and test fixes, as well as the SCons Wiki)
+ and
+ sam th (dynamic checks for utilities).
+
+ </para>
+
+ -->
+
+ <para>
+
+ Thanks to Peter Miller
+ for his splendid change management system, &Aegis;,
+ which has provided the &SCons; project
+ with a robust development methodology from day one,
+ and which showed me how you could
+ integrate incremental regression tests into
+ a practical development cycle
+ (years before eXtreme Programming arrived on the scene).
+
+ </para>
+
+ <para>
+
+ And last, thanks to Guido van Rossum
+ for his elegant scripting language,
+ which is the basis not only for the &SCons; implementation,
+ but for the interface itself.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Contact</title>
+
+ <para>
+
+ The best way to contact people involved with SCons,
+ including the author,
+ is through the SCons mailing lists.
+
+ </para>
+
+ <para>
+
+ If you want to ask general questions about how to use &SCons;
+ send email to &scons-users;.
+
+ </para>
+
+ <para>
+
+ If you want to contact the &SCons; development community directly,
+ send email to &scons-devel;.
+
+ </para>
+
+ <para>
+
+ If you want to receive announcements about &SCons,
+ join the low-volume &scons-announce; mailing list.
+
+ </para>
+
+ </section>
diff --git a/doc/user/preface.xml b/doc/user/preface.xml
new file mode 100644
index 0000000..2c6d8f4
--- /dev/null
+++ b/doc/user/preface.xml
@@ -0,0 +1,426 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ Thank you for taking the time to read about &SCons;.
+ &SCons; is a next-generation
+ software construction tool,
+ or make tool--that is, a software utility
+ for building software (or other files)
+ and keeping built software up-to-date
+ whenever the underlying input files change.
+
+ </para>
+
+ <para>
+
+ The most distinctive thing about &SCons;
+ is that its configuration files are
+ actually <emphasis>scripts</emphasis>,
+ written in the &Python; programming language.
+ This is in contrast to most alternative build tools,
+ which typically invent a new language to
+ configure the build.
+ &SCons; still has a learning curve, of course,
+ because you have to know what functions to call
+ to set up your build properly,
+ but the underlying syntax used should be familiar
+ to anyone who has ever looked at a Python script.
+
+ </para>
+
+ <para>
+
+ Paradoxically,
+ using Python as the configuration file format
+ makes &SCons;
+ <emphasis>easier</emphasis>
+ for non-programmers to learn
+ than the cryptic languages of other build tools,
+ which are usually invented by programmers for other programmers.
+ This is in no small part due to the
+ consistency and readability that are hallmarks of Python.
+ It just so happens that making a real, live
+ scripting language the basis for the
+ configuration files
+ makes it a snap for more accomplished programmers
+ to do more complicated things with builds,
+ as necessary.
+
+ </para>
+
+ <!--
+
+ <section>
+ <title>Why &SCons;?</title>
+
+ <para>
+
+ &SCons; is a response to a perennial problem:
+ building software is harder than it should be.
+ In a nutshell: the old, reliable model of the
+ venerable and ubiquitous &Make; program
+ has had a hard time keeping up with
+ how complicated building software has become.
+ The fact that &Make; has kept up as well as it has is impressive,
+ and a testament to how the simplicity.
+ But anyone who has wrestled with &Automake; and &Autoconf;
+ to try to guarantee that a bit of software
+ will build correctly on multiple platforms
+ can tell you that it takes a lot of work to get right.
+
+ </para>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>&SCons; Principles</title>
+
+ <para>
+
+ There are a few overriding principles
+ we try to live up to in designing and implementing &SCons;:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>Correctness</term>
+
+ <listitem>
+ <para>
+
+ First and foremost,
+ by default, &SCons; guarantees a correct build
+ even if it means sacrificing performance a little.
+ We strive to guarantee the build is correct
+ regardless of how the software being built is structured,
+ how it may have been written,
+ or how unusual the tools are that build it.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Performance</term>
+
+ <listitem>
+ <para>
+
+ Given that the build is correct,
+ we try to make &SCons; build software
+ as quickly as possible.
+ In particular, wherever we may have needed to slow
+ down the default &SCons; behavior to guarantee a correct build,
+ we also try to make it easy to speed up &SCons;
+ through optimization options that let you trade off
+ guaranteed correctness in all end cases for
+ a speedier build in the usual cases.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Convenience</term>
+
+ <listitem>
+ <para>
+
+ &SCons; tries to do as much for you out of the box as reasonable,
+ including detecting the right tools on your system
+ and using them correctly to build the software.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ In a nutshell, we try hard to make &SCons; just
+ "do the right thing" and build software correctly,
+ with a minimum of hassles.
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>History</title>
+
+ <para>
+
+ &SCons; originated with a design
+ that was submitted to the Software Carpentry
+ design competition in 2000.
+
+ </para>
+
+ <para>
+
+ &SCons; is the direct descendant
+ of a Perl utility called &Cons;.
+ &Cons; in turn based some of its ideas on &Jam;,
+ a build tool from Perforce Systems.
+
+ </para>
+
+ <para>
+
+ XXX history of SCons
+
+ </para>
+
+ </section>
+
+ -->
+
+ <!--
+
+ <section>
+ <title>Conventions</title>
+
+ <para>
+
+ XXX conventions used in this manual
+
+ </para>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>A Caveat About This Guide's Completeness</title>
+
+ <para>
+
+ One word of warning as you read through this Guide:
+ Like too much Open Source software out there,
+ the &SCons; documentation isn't always
+ kept up-to-date with the available features.
+ In other words,
+ there's a lot that &SCons; can do that
+ isn't yet covered in this User's Guide.
+ (Come to think of it,
+ that also describes a lot of proprietary software, doesn't it?)
+
+ </para>
+
+ <para>
+
+ Although this User's Guide isn't as complete as we'd like it to be,
+ our development process does emphasize
+ making sure that the &SCons; man page is kept up-to-date
+ with new features.
+ So if you're trying to figure out how to do something
+ that &SCons; supports
+ but can't find enough (or any) information here,
+ it would be worth your while to look
+ at the man page to see if the information is covered there.
+ And if you do,
+ maybe you'd even consider contributing
+ a section to the User's Guide
+ so the next person looking for
+ that information won't have to
+ go through the same thing...?
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Acknowledgements</title>
+
+ <para>
+
+ &SCons; would not exist without a lot of help
+ from a lot of people,
+ many of whom may not even be aware
+ that they helped or served as inspiration.
+ So in no particular order,
+ and at the risk of leaving out someone:
+
+ </para>
+
+ <para>
+
+ First and foremost,
+ &SCons; owes a tremendous debt to Bob Sidebotham,
+ the original author of the classic Perl-based &Cons; tool
+ which Bob first released to the world back around 1996.
+ Bob's work on Cons classic provided the underlying architecture
+ and model of specifying a build configuration
+ using a real scripting language.
+ My real-world experience working on Cons
+ informed many of the design decisions in SCons,
+ including the improved parallel build support,
+ making Builder objects easily definable by users,
+ and separating the build engine from the wrapping interface.
+
+ </para>
+
+ <para>
+
+ Greg Wilson was instrumental in getting
+ &SCons; started as a real project
+ when he initiated the Software Carpentry design
+ competition in February 2000.
+ Without that nudge,
+ marrying the advantages of the Cons classic
+ architecture with the readability of Python
+ might have just stayed no more than a nice idea.
+
+ </para>
+
+ <para>
+
+ The entire &SCons; team have been
+ absolutely wonderful to work with,
+ and &SCons; would be nowhere near as useful a
+ tool without the energy, enthusiasm
+ and time people have contributed over the past few years.
+ The "core team"
+ of Chad Austin, Anthony Roach,
+ Bill Deegan, Charles Crain, Steve Leblanc, Greg Noel,
+ Gary Oberbrunner, Greg Spencer and Christoph Wiedemann
+ have been great about reviewing my (and other) changes
+ and catching problems before they get in the code base.
+ Of particular technical note:
+ Anthony's outstanding and innovative work on the tasking engine
+ has given &SCons; a vastly superior parallel build model;
+ Charles has been the master of the crucial Node infrastructure;
+ Christoph's work on the Configure infrastructure
+ has added crucial Autoconf-like functionality;
+ and Greg has provided excellent support
+ for Microsoft Visual Studio.
+
+ </para>
+
+ <para>
+
+ Special thanks to David Snopek for contributing
+ his underlying "Autoscons" code that formed
+ the basis of Christoph's work with the Configure functionality.
+ David was extremely generous in making
+ this code available to &SCons;,
+ given that he initially released it under the GPL
+ and &SCons; is released under a less-restrictive MIT-style license.
+
+ </para>
+
+ <!--
+
+ <para>
+
+ &SCons; has received contributions
+ from many other people, of course:
+ Matt Balvin (extending long command-line support on Windows),
+ Allen Bierbaum (extensions and fixes to Options),
+ Steve Christensen (help text sorting and function action signature fixes),
+ Michael Cook (avoiding losing signal bits from executed commands),
+ Derrick 'dman' Hudson (),
+ Alex Jacques (work on the Windows scons.bat file),
+ Stephen Kennedy (performance enhancements),
+ Lachlan O'Dea (SharedObject() support for masm
+ and normalized paths for the WhereIs() function),
+ Damyan Pepper (keeping output like Make),
+ Jeff Petkau (significant fixes for CacheDir and other areas),
+ Stefan Reichor (Ghostscript support),
+ Zed Shaw (Append() and Replace() environment methods),
+ Terrel Shumway (build and test fixes, as well as the SCons Wiki)
+ and
+ sam th (dynamic checks for utilities).
+
+ </para>
+
+ -->
+
+ <para>
+
+ Thanks to Peter Miller
+ for his splendid change management system, &Aegis;,
+ which has provided the &SCons; project
+ with a robust development methodology from day one,
+ and which showed me how you could
+ integrate incremental regression tests into
+ a practical development cycle
+ (years before eXtreme Programming arrived on the scene).
+
+ </para>
+
+ <para>
+
+ And last, thanks to Guido van Rossum
+ for his elegant scripting language,
+ which is the basis not only for the &SCons; implementation,
+ but for the interface itself.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Contact</title>
+
+ <para>
+
+ The best way to contact people involved with SCons,
+ including the author,
+ is through the SCons mailing lists.
+
+ </para>
+
+ <para>
+
+ If you want to ask general questions about how to use &SCons;
+ send email to &scons-users;.
+
+ </para>
+
+ <para>
+
+ If you want to contact the &SCons; development community directly,
+ send email to &scons-devel;.
+
+ </para>
+
+ <para>
+
+ If you want to receive announcements about &SCons;,
+ join the low-volume &scons-announce; mailing list.
+
+ </para>
+
+ </section>
diff --git a/doc/user/python.in b/doc/user/python.in
new file mode 100644
index 0000000..aa49030
--- /dev/null
+++ b/doc/user/python.in
@@ -0,0 +1,154 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <!--
+
+ <section>
+ <title>Python Overview</title>
+
+ <para>
+
+ This section will provide a brief overview of
+ the Python programming language.
+ Skip this section if you are already familiar with Python
+ (or you're really intent on diving into &SCons;
+ and just picking up things as you go).
+
+ </para>
+
+ <para>
+
+ Python has a lot of good
+ documentation freely available on-line
+ to help you get started.
+ The standard tutorial is available at XXX.
+
+
+ </para>
+
+ <para>
+
+ Python is very easy to pick up.
+
+ </para>
+
+ <para>
+
+ Python variables must be assigned to before they can be referenced.
+
+ </para>
+
+ <para>
+
+ Assignment is like most programming languages:
+
+ x = 1 + 2
+ z = 3 * x
+
+ </para>
+
+ <para>
+
+ Function calls look like most language function calls:
+
+ a = f(g)
+
+ </para>
+
+ <para>
+
+ Define functions like so:
+
+ def func(arg1, arg2):
+ return arg1 * arg 2
+
+ The number of parameters
+
+ </para>
+
+ <para>
+
+ Strings can be enclosed in single quotes or double quotes,
+ backslashes are used to escape characters,
+ triple-quote syntax lets you include quotes and newlines,
+ raw strings begin with 'r'.
+
+ </para>
+
+ <para>
+
+ Lists are enclosed in square brackets,
+ list items are separated by commas.
+ List references use square brackets and integer index values,
+ slice notation lets you select, delete or replace a range.
+
+ </para>
+
+ <para>
+
+ Dictionaries (hashes) are enclosed in curly brackets,
+ : separates keys from values,
+ , separates items.
+ Dictionary values are referenced using square brackets.
+
+ </para>
+
+ <para>
+
+ Access class attributes (including methods) using a '.'.
+
+ </para>
+
+ <para>
+
+ if: statements look like
+
+ elif: statements look like
+
+ else: statements look like
+
+ </para>
+
+ <para>
+
+ for: statements look like
+
+ while: statements look like
+
+ break statements look like
+
+ continue statements look like
+
+ </para>
+
+ <para>
+
+ pass
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/python.xml b/doc/user/python.xml
new file mode 100644
index 0000000..aa49030
--- /dev/null
+++ b/doc/user/python.xml
@@ -0,0 +1,154 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <!--
+
+ <section>
+ <title>Python Overview</title>
+
+ <para>
+
+ This section will provide a brief overview of
+ the Python programming language.
+ Skip this section if you are already familiar with Python
+ (or you're really intent on diving into &SCons;
+ and just picking up things as you go).
+
+ </para>
+
+ <para>
+
+ Python has a lot of good
+ documentation freely available on-line
+ to help you get started.
+ The standard tutorial is available at XXX.
+
+
+ </para>
+
+ <para>
+
+ Python is very easy to pick up.
+
+ </para>
+
+ <para>
+
+ Python variables must be assigned to before they can be referenced.
+
+ </para>
+
+ <para>
+
+ Assignment is like most programming languages:
+
+ x = 1 + 2
+ z = 3 * x
+
+ </para>
+
+ <para>
+
+ Function calls look like most language function calls:
+
+ a = f(g)
+
+ </para>
+
+ <para>
+
+ Define functions like so:
+
+ def func(arg1, arg2):
+ return arg1 * arg 2
+
+ The number of parameters
+
+ </para>
+
+ <para>
+
+ Strings can be enclosed in single quotes or double quotes,
+ backslashes are used to escape characters,
+ triple-quote syntax lets you include quotes and newlines,
+ raw strings begin with 'r'.
+
+ </para>
+
+ <para>
+
+ Lists are enclosed in square brackets,
+ list items are separated by commas.
+ List references use square brackets and integer index values,
+ slice notation lets you select, delete or replace a range.
+
+ </para>
+
+ <para>
+
+ Dictionaries (hashes) are enclosed in curly brackets,
+ : separates keys from values,
+ , separates items.
+ Dictionary values are referenced using square brackets.
+
+ </para>
+
+ <para>
+
+ Access class attributes (including methods) using a '.'.
+
+ </para>
+
+ <para>
+
+ if: statements look like
+
+ elif: statements look like
+
+ else: statements look like
+
+ </para>
+
+ <para>
+
+ for: statements look like
+
+ while: statements look like
+
+ break statements look like
+
+ continue statements look like
+
+ </para>
+
+ <para>
+
+ pass
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/repositories.in b/doc/user/repositories.in
new file mode 100644
index 0000000..8c97b02
--- /dev/null
+++ b/doc/user/repositories.in
@@ -0,0 +1,641 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ Often, a software project will have
+ one or more central repositories,
+ directory trees that contain
+ source code, or derived files, or both.
+ You can eliminate additional unnecessary
+ rebuilds of files by having &SCons;
+ use files from one or more code repositories
+ to build files in your local build tree.
+
+ </para>
+
+ <section>
+ <title>The &Repository; Method</title>
+
+ <!--
+
+ The repository directories specified may contain source files, derived files
+ (objects, libraries and executables), or both. If there is no local file
+ (source or derived) under the directory in which Cons is executed, then the
+ first copy of a same-named file found under a repository directory will be
+ used to build any local derived files.
+
+ -->
+
+ <para>
+
+ It's often useful to allow multiple programmers working
+ on a project to build software from
+ source files and/or derived files that
+ are stored in a centrally-accessible repository,
+ a directory copy of the source code tree.
+ (Note that this is not the sort of repository
+ maintained by a source code management system
+ like BitKeeper, CVS, or Subversion.)
+ <!--
+ For information about using &SCons;
+ with these systems, see the section,
+ "Fetching Files From Source Code Management Systems,"
+ below.)
+ -->
+ You use the &Repository; method
+ to tell &SCons; to search one or more
+ central code repositories (in order)
+ for any source files and derived files
+ that are not present in the local build tree:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Program('hello.c')
+ Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Multiple calls to the &Repository; method
+ will simply add repositories to the global list
+ that &SCons; maintains,
+ with the exception that &SCons; will automatically eliminate
+ the current directory and any non-existent
+ directories from the list.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Finding source files in repositories</title>
+
+ <para>
+
+ The above example
+ specifies that &SCons;
+ will first search for files under
+ the <filename>/usr/repository1</filename> tree
+ and next under the <filename>/usr/repository2</filename> tree.
+ &SCons; expects that any files it searches
+ for will be found in the same position
+ relative to the top-level directory.
+ In the above example, if the &hello_c; file is not
+ found in the local build tree,
+ &SCons; will search first for
+ a <filename>/usr/repository1/hello.c</filename> file
+ and then for a <filename>/usr/repository2/hello.c</filename> file
+ to use in its place.
+
+ </para>
+
+ <para>
+
+ So given the &SConstruct; file above,
+ if the &hello_c; file exists in the local
+ build directory,
+ &SCons; will rebuild the &hello; program
+ as normal:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If, however, there is no local &hello_c; file,
+ but one exists in <filename>/usr/repository1</filename>,
+ &SCons; will recompile the &hello; program
+ from the source file it finds in the repository:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct">
+ env = Environment()
+ env.Program('hello.c')
+ Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2')
+ </file>
+ <file name="__ROOT__/usr/repository1/hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <scons_output example="ex2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And similarly, if there is no local &hello_c; file
+ and no <filename>/usr/repository1/hello.c</filename>,
+ but one exists in <filename>/usr/repository2</filename>:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct">
+ env = Environment()
+ env.Program('hello.c')
+ Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2')
+ </file>
+ <file name="__ROOT__/usr/repository2/hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <scons_output example="ex3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Finding <literal>#include</literal> files in repositories</title>
+
+ <para>
+
+ We've already seen that SCons will scan the contents of
+ a source file for <literal>#include</literal> file names
+ and realize that targets built from that source file
+ also depend on the <literal>#include</literal> file(s).
+ For each directory in the &cv-link-CPPPATH; list,
+ &SCons; will actually search the corresponding directories
+ in any repository trees and establish the
+ correct dependencies on any
+ <literal>#include</literal> files that it finds
+ in repository directory.
+
+ </para>
+
+ <para>
+
+ Unless the C compiler also knows about these directories
+ in the repository trees, though,
+ it will be unable to find the <literal>#include</literal> files.
+ If, for example, the &hello_c; file in
+ our previous example includes the &hello.h;
+ in its current directory,
+ and the &hello.h; only exists in the repository:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ hello.c:1: hello.h: No such file or directory
+ </screen>
+
+ <para>
+
+ In order to inform the C compiler about the repositories,
+ &SCons; will add appropriate
+ <literal>-I</literal> flags to the compilation commands
+ for each directory in the &cv-CPPPATH; list.
+ So if we add the current directory to the
+ construction environment &cv-CPPPATH; like so:
+
+ </para>
+
+ <scons_example name="CPPPATH">
+ <file name="SConstruct" printme="1">
+ env = Environment(CPPPATH = ['.'])
+ env.Program('hello.c')
+ Repository('__ROOT__/usr/repository1')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then re-executing &SCons; yields:
+
+ </para>
+
+ <scons_output example="CPPPATH">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The order of the <literal>-I</literal> options replicates,
+ for the C preprocessor,
+ the same repository-directory search path
+ that &SCons; uses for its own dependency analysis.
+ If there are multiple repositories and multiple &cv-CPPPATH;
+ directories, &SCons; will add the repository directories
+ to the beginning of each &cv-CPPPATH; directory,
+ rapidly multiplying the number of <literal>-I</literal> flags.
+ If, for example, the &cv-CPPPATH; contains three directories
+ (and shorter repository path names!):
+
+ </para>
+
+ <scons_example name="CPPPATH3">
+ <file name="SConstruct" printme="1">
+ env = Environment(CPPPATH = ['dir1', 'dir2', 'dir3'])
+ env.Program('hello.c')
+ Repository('__ROOT__/r1', '__ROOT__/r2')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then we'll end up with nine <literal>-I</literal> options
+ on the command line,
+ three (for each of the &cv-CPPPATH; directories)
+ times three (for the local directory plus the two repositories):
+
+ </para>
+
+ <scons_output example="CPPPATH3">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+<!--
+
+Cons classic did the following, does SCons?
+
+In order to shorten the command lines as much as possible, Cons will
+remove C<-I> flags for any directories, locally or in the repositories,
+which do not actually exist. (Note that the C<-I> flags are not included
+in the MD5 signature calculation for the target file, so the target will
+not be recompiled if the compilation command changes due to a directory
+coming into existence.)
+
+-->
+
+ <section>
+ <title>Limitations on <literal>#include</literal> files in repositories</title>
+
+ <para>
+
+ &SCons; relies on the C compiler's
+ <literal>-I</literal> options to control the order in which
+ the preprocessor will search the repository directories
+ for <literal>#include</literal> files.
+ This causes a problem, however, with how the C preprocessor
+ handles <literal>#include</literal> lines with
+ the file name included in double-quotes.
+
+ </para>
+
+ <para>
+
+ As we've seen,
+ &SCons; will compile the &hello_c; file from
+ the repository if it doesn't exist in
+ the local directory.
+ If, however, the &hello_c; file in the repository contains
+ a <literal>#include</literal> line with the file name in
+ double quotes:
+
+ </para>
+
+ <programlisting>
+ #include "hello.h"
+ int
+ main(int argc, char *argv[])
+ {
+ printf(HELLO_MESSAGE);
+ return (0);
+ }
+ </programlisting>
+
+ <para>
+
+ Then the C preprocessor will <emphasis>always</emphasis>
+ use a &hello_h; file from the repository directory first,
+ even if there is a &hello_h; file in the local directory,
+ despite the fact that the command line specifies
+ <literal>-I</literal> as the first option:
+
+ </para>
+
+ <scons_example name="quote1">
+ <file name="SConstruct">
+ env = Environment(CPPPATH = ['.'])
+ env.Program('hello.c')
+ Repository('__ROOT__/usr/repository1')
+ </file>
+ <file name="__ROOT__/usr/repository1/hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <scons_output example="quote1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ This behavior of the C preprocessor--always search
+ for a <literal>#include</literal> file in double-quotes
+ first in the same directory as the source file,
+ and only then search the <literal>-I</literal>--can
+ not, in general, be changed.
+ In other words, it's a limitation
+ that must be lived with if you want to use
+ code repositories in this way.
+ There are three ways you can possibly
+ work around this C preprocessor behavior:
+
+ </para>
+
+ <orderedlist>
+
+ <listitem>
+ <para>
+
+ Some modern versions of C compilers do have an option
+ to disable or control this behavior.
+ If so, add that option to &cv-link-CFLAGS;
+ (or &cv-link-CXXFLAGS; or both) in your construction environment(s).
+ Make sure the option is used for all construction
+ environments that use C preprocessing!
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ Change all occurrences of <literal>#include "file.h"</literal>
+ to <literal>#include &amp;lt;file.h&amp;gt;</literal>.
+ Use of <literal>#include</literal> with angle brackets
+ does not have the same behavior--the <literal>-I</literal>
+ directories are searched first
+ for <literal>#include</literal> files--which
+ gives &SCons; direct control over the list of
+ directories the C preprocessor will search.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ Require that everyone working with compilation from
+ repositories check out and work on entire directories of files,
+ not individual files.
+ (If you use local wrapper scripts around
+ your source code control system's command,
+ you could add logic to enforce this restriction there.
+
+ </para>
+ </listitem>
+
+ </orderedlist>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Finding the &SConstruct; file in repositories</title>
+
+ <para>
+
+ &SCons; will also search in repositories
+ for the &SConstruct; file and any specified &SConscript; files.
+ This poses a problem, though: how can &SCons; search a
+ repository tree for an &SConstruct; file
+ if the &SConstruct; file itself contains the information
+ about the pathname of the repository?
+ To solve this problem, &SCons; allows you
+ to specify repository directories
+ on the command line using the <literal>-Y</literal> option:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput>
+ </screen>
+
+ <para>
+
+ When looking for source or derived files,
+ &SCons; will first search the repositories
+ specified on the command line,
+ and then search the repositories
+ specified in the &SConstruct; or &SConscript; files.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Finding derived files in repositories</title>
+
+ <para>
+
+ If a repository contains not only source files,
+ but also derived files (such as object files,
+ libraries, or executables), &SCons; will perform
+ its normal MD5 signature calculation to
+ decide if a derived file in a repository is up-to-date,
+ or the derived file must be rebuilt in the local build directory.
+ For the &SCons; signature calculation to work correctly,
+ a repository tree must contain the &sconsign; files
+ that &SCons; uses to keep track of signature information.
+
+ </para>
+
+ <para>
+
+ Usually, this would be done by a build integrator
+ who would run &SCons; in the repository
+ to create all of its derived files and &sconsign; files,
+ or who would run &SCons; in a separate build directory
+ and copy the resulting tree to the desired repository:
+
+ </para>
+
+ <scons_example name="ex4">
+ <file name="SConstruct">
+ env = Environment()
+ env.Program(['hello.c', 'file1.c', 'file2.c'])
+ Repository('/usr/repository1', '/usr/repository2')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="file1.c">
+ int f1() { printf("file1\n"); }
+ </file>
+ <file name="file2.c">
+ int f2() { printf("file2.c\n"); }
+ </file>
+ </scons_example>
+
+ <scons_output example="ex4">
+ <scons_output_command>cd /usr/repository1</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ (Note that this is safe even if the &SConstruct; file
+ lists <filename>/usr/repository1</filename> as a repository,
+ because &SCons; will remove the current build directory
+ from its repository list for that invocation.)
+
+ </para>
+
+ <para>
+
+ Now, with the repository populated,
+ we only need to create the one local source file
+ we're interested in working with at the moment,
+ and use the <literal>-Y</literal> option to
+ tell &SCons; to fetch any other files it needs
+ from the repository:
+
+ </para>
+
+ <!--
+ <scons_output example="ex4">
+ <scons_output_command>cd $HOME/build</scons_output_command>
+ <scons_output_command>edit hello.c</scons_output_command>
+ <scons_output_command>scons -Q -Y __ROOT__/usr/repository1</scons_output_command>
+ </scons_output>
+ -->
+ <screen>
+ % <userinput>cd $HOME/build</userinput>
+ % <userinput>edit hello.c</userinput>
+ % <userinput>scons -Q -Y /usr/repository1</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o
+ </screen>
+
+ <para>
+
+ Notice that &SCons; realizes that it does not need to
+ rebuild local copies <filename>file1.o</filename> and <filename>file2.o</filename> files,
+ but instead uses the already-compiled files
+ from the repository.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Guaranteeing local copies of files</title>
+
+ <para>
+
+ If the repository tree contains the complete results of a build,
+ and we try to build from the repository
+ without any files in our local tree,
+ something moderately surprising happens:
+
+ </para>
+
+ <screen>
+ % <userinput>mkdir $HOME/build2</userinput>
+ % <userinput>cd $HOME/build2</userinput>
+ % <userinput>scons -Q -Y /usr/all/repository hello</userinput>
+ scons: `hello' is up-to-date.
+ </screen>
+
+ <para>
+
+ Why does &SCons; say that the &hello; program
+ is up-to-date when there is no &hello; program
+ in the local build directory?
+ Because the repository (not the local directory)
+ contains the up-to-date &hello; program,
+ and &SCons; correctly determines that nothing
+ needs to be done to rebuild that
+ up-to-date copy of the file.
+
+ </para>
+
+ <para>
+
+ There are, however, many times when you want to ensure that a
+ local copy of a file always exists.
+ A packaging or testing script, for example,
+ may assume that certain generated files exist locally.
+ To tell &SCons; to make a copy of any up-to-date repository
+ file in the local build directory,
+ use the &Local; function:
+
+ </para>
+
+ <scons_example name="ex5">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ hello = env.Program('hello.c')
+ Local(hello)
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ If we then run the same command,
+ &SCons; will make a local copy of the program
+ from the repository copy,
+ and tell you that it is doing so:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Y /usr/all/repository hello</userinput>
+ Local copy of hello from /usr/all/repository/hello
+ scons: `hello' is up-to-date.
+ </screen>
+
+ <para>
+
+ (Notice that, because the act of making the local copy
+ is not considered a "build" of the &hello; file,
+ &SCons; still reports that it is up-to-date.)
+
+ </para>
+
+ </section>
diff --git a/doc/user/repositories.xml b/doc/user/repositories.xml
new file mode 100644
index 0000000..7d955c3
--- /dev/null
+++ b/doc/user/repositories.xml
@@ -0,0 +1,595 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ Often, a software project will have
+ one or more central repositories,
+ directory trees that contain
+ source code, or derived files, or both.
+ You can eliminate additional unnecessary
+ rebuilds of files by having &SCons;
+ use files from one or more code repositories
+ to build files in your local build tree.
+
+ </para>
+
+ <section>
+ <title>The &Repository; Method</title>
+
+ <!--
+
+ The repository directories specified may contain source files, derived files
+ (objects, libraries and executables), or both. If there is no local file
+ (source or derived) under the directory in which Cons is executed, then the
+ first copy of a same-named file found under a repository directory will be
+ used to build any local derived files.
+
+ -->
+
+ <para>
+
+ It's often useful to allow multiple programmers working
+ on a project to build software from
+ source files and/or derived files that
+ are stored in a centrally-accessible repository,
+ a directory copy of the source code tree.
+ (Note that this is not the sort of repository
+ maintained by a source code management system
+ like BitKeeper, CVS, or Subversion.)
+ <!--
+ For information about using &SCons;
+ with these systems, see the section,
+ "Fetching Files From Source Code Management Systems,"
+ below.)
+ -->
+ You use the &Repository; method
+ to tell &SCons; to search one or more
+ central code repositories (in order)
+ for any source files and derived files
+ that are not present in the local build tree:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Program('hello.c')
+ Repository('/usr/repository1', '/usr/repository2')
+ </programlisting>
+
+ <para>
+
+ Multiple calls to the &Repository; method
+ will simply add repositories to the global list
+ that &SCons; maintains,
+ with the exception that &SCons; will automatically eliminate
+ the current directory and any non-existent
+ directories from the list.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Finding source files in repositories</title>
+
+ <para>
+
+ The above example
+ specifies that &SCons;
+ will first search for files under
+ the <filename>/usr/repository1</filename> tree
+ and next under the <filename>/usr/repository2</filename> tree.
+ &SCons; expects that any files it searches
+ for will be found in the same position
+ relative to the top-level directory.
+ In the above example, if the &hello_c; file is not
+ found in the local build tree,
+ &SCons; will search first for
+ a <filename>/usr/repository1/hello.c</filename> file
+ and then for a <filename>/usr/repository2/hello.c</filename> file
+ to use in its place.
+
+ </para>
+
+ <para>
+
+ So given the &SConstruct; file above,
+ if the &hello_c; file exists in the local
+ build directory,
+ &SCons; will rebuild the &hello; program
+ as normal:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <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>
+
+
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c /usr/repository1/hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <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>
+
+
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c /usr/repository2/hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Finding <literal>#include</literal> files in repositories</title>
+
+ <para>
+
+ We've already seen that SCons will scan the contents of
+ a source file for <literal>#include</literal> file names
+ and realize that targets built from that source file
+ also depend on the <literal>#include</literal> file(s).
+ For each directory in the &cv-link-CPPPATH; list,
+ &SCons; will actually search the corresponding directories
+ in any repository trees and establish the
+ correct dependencies on any
+ <literal>#include</literal> files that it finds
+ in repository directory.
+
+ </para>
+
+ <para>
+
+ Unless the C compiler also knows about these directories
+ in the repository trees, though,
+ it will be unable to find the <literal>#include</literal> files.
+ If, for example, the &hello_c; file in
+ our previous example includes the &hello;.h;
+ in its current directory,
+ and the &hello;.h; only exists in the repository:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ hello.c:1: hello.h: No such file or directory
+ </screen>
+
+ <para>
+
+ In order to inform the C compiler about the repositories,
+ &SCons; will add appropriate
+ <literal>-I</literal> flags to the compilation commands
+ for each directory in the &cv-CPPPATH; list.
+ So if we add the current directory to the
+ construction environment &cv-CPPPATH; like so:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CPPPATH = ['.'])
+ env.Program('hello.c')
+ Repository('/usr/repository1')
+ </programlisting>
+
+ <para>
+
+ Then re-executing &SCons; yields:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c -I. -I/usr/repository1 hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ The order of the <literal>-I</literal> options replicates,
+ for the C preprocessor,
+ the same repository-directory search path
+ that &SCons; uses for its own dependency analysis.
+ If there are multiple repositories and multiple &cv-CPPPATH;
+ directories, &SCons; will add the repository directories
+ to the beginning of each &cv-CPPPATH; directory,
+ rapidly multiplying the number of <literal>-I</literal> flags.
+ If, for example, the &cv-CPPPATH; contains three directories
+ (and shorter repository path names!):
+
+ </para>
+
+ <programlisting>
+ env = Environment(CPPPATH = ['dir1', 'dir2', 'dir3'])
+ env.Program('hello.c')
+ Repository('/r1', '/r2')
+ </programlisting>
+
+ <para>
+
+ Then we'll end up with nine <literal>-I</literal> options
+ on the command line,
+ three (for each of the &cv-CPPPATH; directories)
+ times three (for the local directory plus the two repositories):
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c -Idir1 -I/r1/dir1 -I/r2/dir1 -Idir2 -I/r1/dir2 -I/r2/dir2 -Idir3 -I/r1/dir3 -I/r2/dir3 hello.c
+ cc -o hello hello.o
+ </screen>
+
+<!--
+
+Cons classic did the following, does SCons?
+
+In order to shorten the command lines as much as possible, Cons will
+remove C<-I> flags for any directories, locally or in the repositories,
+which do not actually exist. (Note that the C<-I> flags are not included
+in the MD5 signature calculation for the target file, so the target will
+not be recompiled if the compilation command changes due to a directory
+coming into existence.)
+
+-->
+
+ <section>
+ <title>Limitations on <literal>#include</literal> files in repositories</title>
+
+ <para>
+
+ &SCons; relies on the C compiler's
+ <literal>-I</literal> options to control the order in which
+ the preprocessor will search the repository directories
+ for <literal>#include</literal> files.
+ This causes a problem, however, with how the C preprocessor
+ handles <literal>#include</literal> lines with
+ the file name included in double-quotes.
+
+ </para>
+
+ <para>
+
+ As we've seen,
+ &SCons; will compile the &hello_c; file from
+ the repository if it doesn't exist in
+ the local directory.
+ If, however, the &hello_c; file in the repository contains
+ a <literal>#include</literal> line with the file name in
+ double quotes:
+
+ </para>
+
+ <programlisting>
+ #include "hello.h"
+ int
+ main(int argc, char *argv[])
+ {
+ printf(HELLO_MESSAGE);
+ return (0);
+ }
+ </programlisting>
+
+ <para>
+
+ Then the C preprocessor will <emphasis>always</emphasis>
+ use a &hello_h; file from the repository directory first,
+ even if there is a &hello_h; file in the local directory,
+ despite the fact that the command line specifies
+ <literal>-I</literal> as the first option:
+
+ </para>
+
+
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c -I. -I/usr/repository1 /usr/repository1/hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <para>
+
+ This behavior of the C preprocessor--always search
+ for a <literal>#include</literal> file in double-quotes
+ first in the same directory as the source file,
+ and only then search the <literal>-I</literal>--can
+ not, in general, be changed.
+ In other words, it's a limitation
+ that must be lived with if you want to use
+ code repositories in this way.
+ There are three ways you can possibly
+ work around this C preprocessor behavior:
+
+ </para>
+
+ <orderedlist>
+
+ <listitem>
+ <para>
+
+ Some modern versions of C compilers do have an option
+ to disable or control this behavior.
+ If so, add that option to &cv-link-CFLAGS;
+ (or &cv-link-CXXFLAGS; or both) in your construction environment(s).
+ Make sure the option is used for all construction
+ environments that use C preprocessing!
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ Change all occurrences of <literal>#include "file.h"</literal>
+ to <literal>#include &lt;file.h&gt;</literal>.
+ Use of <literal>#include</literal> with angle brackets
+ does not have the same behavior--the <literal>-I</literal>
+ directories are searched first
+ for <literal>#include</literal> files--which
+ gives &SCons; direct control over the list of
+ directories the C preprocessor will search.
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ Require that everyone working with compilation from
+ repositories check out and work on entire directories of files,
+ not individual files.
+ (If you use local wrapper scripts around
+ your source code control system's command,
+ you could add logic to enforce this restriction there.
+
+ </para>
+ </listitem>
+
+ </orderedlist>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Finding the &SConstruct; file in repositories</title>
+
+ <para>
+
+ &SCons; will also search in repositories
+ for the &SConstruct; file and any specified &SConscript; files.
+ This poses a problem, though: how can &SCons; search a
+ repository tree for an &SConstruct; file
+ if the &SConstruct; file itself contains the information
+ about the pathname of the repository?
+ To solve this problem, &SCons; allows you
+ to specify repository directories
+ on the command line using the <literal>-Y</literal> option:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput>
+ </screen>
+
+ <para>
+
+ When looking for source or derived files,
+ &SCons; will first search the repositories
+ specified on the command line,
+ and then search the repositories
+ specified in the &SConstruct; or &SConscript; files.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Finding derived files in repositories</title>
+
+ <para>
+
+ If a repository contains not only source files,
+ but also derived files (such as object files,
+ libraries, or executables), &SCons; will perform
+ its normal MD5 signature calculation to
+ decide if a derived file in a repository is up-to-date,
+ or the derived file must be rebuilt in the local build directory.
+ For the &SCons; signature calculation to work correctly,
+ a repository tree must contain the &sconsign; files
+ that &SCons; uses to keep track of signature information.
+
+ </para>
+
+ <para>
+
+ Usually, this would be done by a build integrator
+ who would run &SCons; in the repository
+ to create all of its derived files and &sconsign; files,
+ or who would run &SCons; in a separate build directory
+ and copy the resulting tree to the desired repository:
+
+ </para>
+
+
+
+ <screen>
+ % <userinput>cd /usr/repository1</userinput>
+ % <userinput>scons -Q</userinput>
+ cc -o file1.o -c file1.c
+ cc -o file2.o -c file2.c
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o file1.o file2.o
+ </screen>
+
+ <para>
+
+ (Note that this is safe even if the &SConstruct; file
+ lists <filename>/usr/repository1</filename> as a repository,
+ because &SCons; will remove the current build directory
+ from its repository list for that invocation.)
+
+ </para>
+
+ <para>
+
+ Now, with the repository populated,
+ we only need to create the one local source file
+ we're interested in working with at the moment,
+ and use the <literal>-Y</literal> option to
+ tell &SCons; to fetch any other files it needs
+ from the repository:
+
+ </para>
+
+ <!--
+ <scons_output example="ex4">
+ <scons_output_command>cd $HOME/build</scons_output_command>
+ <scons_output_command>edit hello.c</scons_output_command>
+ <scons_output_command>scons -Q -Y __ROOT__/usr/repository1</scons_output_command>
+ </scons_output>
+ -->
+ <screen>
+ % <userinput>cd $HOME/build</userinput>
+ % <userinput>edit hello.c</userinput>
+ % <userinput>scons -Q -Y /usr/repository1</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o
+ </screen>
+
+ <para>
+
+ Notice that &SCons; realizes that it does not need to
+ rebuild local copies <filename>file1.o</filename> and <filename>file2.o</filename> files,
+ but instead uses the already-compiled files
+ from the repository.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Guaranteeing local copies of files</title>
+
+ <para>
+
+ If the repository tree contains the complete results of a build,
+ and we try to build from the repository
+ without any files in our local tree,
+ something moderately surprising happens:
+
+ </para>
+
+ <screen>
+ % <userinput>mkdir $HOME/build2</userinput>
+ % <userinput>cd $HOME/build2</userinput>
+ % <userinput>scons -Q -Y /usr/all/repository hello</userinput>
+ scons: `hello' is up-to-date.
+ </screen>
+
+ <para>
+
+ Why does &SCons; say that the &hello; program
+ is up-to-date when there is no &hello; program
+ in the local build directory?
+ Because the repository (not the local directory)
+ contains the up-to-date &hello; program,
+ and &SCons; correctly determines that nothing
+ needs to be done to rebuild that
+ up-to-date copy of the file.
+
+ </para>
+
+ <para>
+
+ There are, however, many times when you want to ensure that a
+ local copy of a file always exists.
+ A packaging or testing script, for example,
+ may assume that certain generated files exist locally.
+ To tell &SCons; to make a copy of any up-to-date repository
+ file in the local build directory,
+ use the &Local; function:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ Local(hello)
+ </programlisting>
+
+ <para>
+
+ If we then run the same command,
+ &SCons; will make a local copy of the program
+ from the repository copy,
+ and tell you that it is doing so:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Y /usr/all/repository hello</userinput>
+ Local copy of hello from /usr/all/repository/hello
+ scons: `hello' is up-to-date.
+ </screen>
+
+ <para>
+
+ (Notice that, because the act of making the local copy
+ is not considered a "build" of the &hello; file,
+ &SCons; still reports that it is up-to-date.)
+
+ </para>
+
+ </section>
diff --git a/doc/user/run.in b/doc/user/run.in
new file mode 100644
index 0000000..946a7ed
--- /dev/null
+++ b/doc/user/run.in
@@ -0,0 +1,375 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Invoking Cons
+
+The C<cons> command is usually invoked from the root of the build tree. A
+F<Construct> file must exist in that directory. If the C<-f> argument is
+used, then an alternate F<Construct> file may be used (and, possibly, an
+alternate root, since C<cons> will cd to F<Construct> file's containing
+directory).
+
+If C<cons> is invoked from a child of the root of the build tree with
+the C<-t> argument, it will walk up the directory hierarchy looking for a
+F<Construct> file. (An alternate name may still be specified with C<-f>.)
+The targets supplied on the command line will be modified to be relative
+to the discovered F<Construct> file. For example, from a directory
+containing a top-level F<Construct> file, the following invocation:
+
+ % cd libfoo/subdir
+ % cons -t target
+
+is exactly equivalent to:
+
+ % cons libfoo/subdir/target
+
+If there are any C<Default> targets specified in the directory hierarchy's
+F<Construct> or F<Conscript> files, only the default targets at or below
+the directory from which C<cons -t> was invoked will be built.
+
+The command is invoked as follows:
+
+ cons <arguments> , <construct-args>
+
+where I<arguments> can be any of the following, in any order:
+
+=over 10
+
+=item I<target>
+
+Build the specified target. If I<target> is a directory, then recursively
+build everything within that directory.
+
+=item I<+pattern>
+
+Limit the F<Conscript> files considered to just those that match I<pattern>,
+which is a Perl regular expression. Multiple C<+> arguments are accepted.
+
+=item I<name>=<val>
+
+Sets I<name> to value I<val> in the C<ARG> hash passed to the top-level
+F<Construct> file.
+
+=item C<-cc>
+
+Show command that would have been executed, when retrieving from cache. No
+indication that the file has been retrieved is given; this is useful for
+generating build logs that can be compared with real build logs.
+
+=item C<-cd>
+
+Disable all caching. Do not retrieve from cache nor flush to cache.
+
+=item C<-cr>
+
+Build dependencies in random order. This is useful when building multiple
+similar trees with caching enabled.
+
+=item C<-cs>
+
+Synchronize existing build targets that are found to be up-to-date with
+cache. This is useful if caching has been disabled with -cc or just recently
+enabled with UseCache.
+
+=item C<-d>
+
+Enable dependency debugging.
+
+=item C<-f> <file>
+
+Use the specified file instead of F<Construct> (but first change to
+containing directory of I<file>).
+
+=item C<-h>
+
+Show a help message local to the current build if one such is defined, and
+exit.
+
+=item C<-k>
+
+Keep going as far as possible after errors.
+
+=item C<-o> <file>
+
+Read override file I<file>.
+
+=item C<-p>
+
+Show construction products in specified trees. No build is attempted.
+
+=item C<-pa>
+
+Show construction products and associated actions. No build is attempted.
+
+=item C<-pw>
+
+Show products and where they are defined. No build is attempted.
+
+=item C<-q>
+
+Make the build quiet. Multiple C<-q> options may be specified.
+
+A single C<-q> options suppress messages about Installing and Removing
+targets.
+
+Two C<-q> options suppress build command lines and target up-to-date
+messages.
+
+=item C<-r>
+
+Remove construction products associated with <targets>. No build is
+attempted.
+
+=item C<-R> <repos>
+
+Search for files in I<repos>. Multiple B<-R> I<repos> directories are
+searched in the order specified.
+
+=item C<-S> <pkg>
+
+Use the sig::<pkg> package to calculate. Supported <pkg> values
+include "md5" for MD5 signature calculation and "md5::debug" for debug
+information about MD5 signature calculation.
+
+If the specified package ends in <::debug>, signature debug information
+will be printed to the file name specified in the C<CONS_SIG_DEBUG>
+environment variable, or to standard output if the environment variable
+is not set.
+
+=item C<-t>
+
+Traverse up the directory hierarchy looking for a F<Construct> file,
+if none exists in the current directory. Targets will be modified to
+be relative to the F<Construct> file.
+
+Internally, C<cons> will change its working directory to the directory
+which contains the top-level F<Construct> file and report:
+
+ cons: Entering directory `top-level-directory'
+
+This message indicates to an invoking editor (such as emacs) or build
+environment that Cons will now report all file names relative to the
+top-level directory. This message can not be suppressed with the C<-q>
+option.
+
+=item C<-v>
+
+Show C<cons> version and continue processing.
+
+=item C<-V>
+
+Show C<cons> version and exit.
+
+=item C<-wf> <file>
+
+Write all filenames considered into I<file>.
+
+=item C<-x>
+
+Show a help message similar to this one, and exit.
+
+=back
+
+And I<construct-args> can be any arguments that you wish to process in the
+F<Construct> file. Note that there should be a B<-,-> separating the arguments
+to cons and the arguments that you wish to process in the F<Construct> file.
+
+Processing of I<construct-args> can be done by any standard package like
+B<Getopt> or its variants, or any user defined package. B<cons> will pass in
+the I<construct-args> as B<@ARGV> and will not attempt to interpret anything
+after the B<-,->.
+
+ % cons -R /usr/local/repository -d os=solaris +driver -,- -c test -f DEBUG
+
+would pass the following to cons
+
+ -R /usr/local/repository -d os=solaris +driver
+
+and the following, to the top level F<Construct> file as B<@ARGV>
+
+ -c test -f DEBUG
+
+Note that C<cons -r .> is equivalent to a full recursive C<make clean>,
+but requires no support in the F<Construct> file or any F<Conscript>
+files. This is most useful if you are compiling files into source
+directories (if you separate the F<build> and F<export> directories,
+then you can just remove the directories).
+
+The options C<-p>, C<-pa>, and C<-pw> are extremely useful for use as an aid
+in reading scripts or debugging them. If you want to know what script
+installs F<export/include/foo.h>, for example, just type:
+
+ % cons -pw export/include/foo.h
+
+=head1 Selective builds
+
+Cons provides two methods for reducing the size of given build. The first is
+by specifying targets on the command line, and the second is a method for
+pruning the build tree. We'll consider target specification first.
+
+
+=head2 Selective targeting
+
+Like make, Cons allows the specification of ``targets'' on the command
+line. Cons targets may be either files or directories. When a directory is
+specified, this is simply a short-hand notation for every derivable
+product-,-that Cons knows about-,-in the specified directory and below. For
+example:
+
+ % cons build/hello/hello.o
+
+means build F<hello.o> and everything that F<hello.o> might need. This is
+from a previous version of the B<Hello, World!> program in which F<hello.o>
+depended upon F<export/include/world.h>. If that file is not up-to-date
+(because someone modified F<src/world/world.h)>, then it will be rebuilt,
+even though it is in a directory remote from F<build/hello>.
+
+In this example:
+
+ % cons build
+
+Everything in the F<build> directory is built, if necessary. Again, this may
+cause more files to be built. In particular, both F<export/include/world.h>
+and F<export/lib/libworld.a> are required by the F<build/hello> directory,
+and so they will be built if they are out-of-date.
+
+If we do, instead:
+
+ % cons export
+
+then only the files that should be installed in the export directory will be
+rebuilt, if necessary, and then installed there. Note that C<cons build>
+might build files that C<cons export> doesn't build, and vice-versa.
+
+
+=head1 Build Pruning
+
+In conjunction with target selection, B<build pruning> can be used to reduce
+the scope of the build. In the previous peAcH and baNaNa example, we have
+already seen how script-driven build pruning can be used to make only half
+of the potential build available for any given invocation of C<cons>. Cons
+also provides, as a convenience, a command line convention that allows you
+to specify which F<Conscript> files actually get ``built''-,-that is,
+incorporated into the build tree. For example:
+
+ % cons build +world
+
+The C<+> argument introduces a Perl regular expression. This must, of
+course, be quoted at the shell level if there are any shell meta-characters
+within the expression. The expression is matched against each F<Conscript>
+file which has been mentioned in a C<Build> statement, and only those
+scripts with matching names are actually incorporated into the build
+tree. Multiple such arguments are allowed, in which case a match against any
+of them is sufficient to cause a script to be included.
+
+In the example, above, the F<hello> program will not be built, since Cons
+will have no knowledge of the script F<hello/Conscript>. The F<libworld.a>
+archive will be built, however, if need be.
+
+There are a couple of uses for build pruning via the command line. Perhaps
+the most useful is the ability to make local changes, and then, with
+sufficient knowledge of the consequences of those changes, restrict the size
+of the build tree in order to speed up the rebuild time. A second use for
+build pruning is to actively prevent the recompilation of certain files that
+you know will recompile due to, for example, a modified header file. You may
+know that either the changes to the header file are immaterial, or that the
+changes may be safely ignored for most of the tree, for testing
+purposes.With Cons, the view is that it is pragmatic to admit this type of
+behavior, with the understanding that on the next full build everything that
+needs to be rebuilt will be. There is no equivalent to a ``make touch''
+command, to mark files as permanently up-to-date. So any risk that is
+incurred by build pruning is mitigated. For release quality work, obviously,
+we recommend that you do not use build pruning (it's perfectly OK to use
+during integration, however, for checking compilation, etc. Just be sure to
+do an unconstrained build before committing the integration).
+
+-->
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <section>
+ <title>Command-Line Options</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Getting at Command-Line Arguments</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Selective Builds</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Build Pruning</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>Overriding Construction Variables</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
diff --git a/doc/user/run.xml b/doc/user/run.xml
new file mode 100644
index 0000000..946a7ed
--- /dev/null
+++ b/doc/user/run.xml
@@ -0,0 +1,375 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Invoking Cons
+
+The C<cons> command is usually invoked from the root of the build tree. A
+F<Construct> file must exist in that directory. If the C<-f> argument is
+used, then an alternate F<Construct> file may be used (and, possibly, an
+alternate root, since C<cons> will cd to F<Construct> file's containing
+directory).
+
+If C<cons> is invoked from a child of the root of the build tree with
+the C<-t> argument, it will walk up the directory hierarchy looking for a
+F<Construct> file. (An alternate name may still be specified with C<-f>.)
+The targets supplied on the command line will be modified to be relative
+to the discovered F<Construct> file. For example, from a directory
+containing a top-level F<Construct> file, the following invocation:
+
+ % cd libfoo/subdir
+ % cons -t target
+
+is exactly equivalent to:
+
+ % cons libfoo/subdir/target
+
+If there are any C<Default> targets specified in the directory hierarchy's
+F<Construct> or F<Conscript> files, only the default targets at or below
+the directory from which C<cons -t> was invoked will be built.
+
+The command is invoked as follows:
+
+ cons <arguments> , <construct-args>
+
+where I<arguments> can be any of the following, in any order:
+
+=over 10
+
+=item I<target>
+
+Build the specified target. If I<target> is a directory, then recursively
+build everything within that directory.
+
+=item I<+pattern>
+
+Limit the F<Conscript> files considered to just those that match I<pattern>,
+which is a Perl regular expression. Multiple C<+> arguments are accepted.
+
+=item I<name>=<val>
+
+Sets I<name> to value I<val> in the C<ARG> hash passed to the top-level
+F<Construct> file.
+
+=item C<-cc>
+
+Show command that would have been executed, when retrieving from cache. No
+indication that the file has been retrieved is given; this is useful for
+generating build logs that can be compared with real build logs.
+
+=item C<-cd>
+
+Disable all caching. Do not retrieve from cache nor flush to cache.
+
+=item C<-cr>
+
+Build dependencies in random order. This is useful when building multiple
+similar trees with caching enabled.
+
+=item C<-cs>
+
+Synchronize existing build targets that are found to be up-to-date with
+cache. This is useful if caching has been disabled with -cc or just recently
+enabled with UseCache.
+
+=item C<-d>
+
+Enable dependency debugging.
+
+=item C<-f> <file>
+
+Use the specified file instead of F<Construct> (but first change to
+containing directory of I<file>).
+
+=item C<-h>
+
+Show a help message local to the current build if one such is defined, and
+exit.
+
+=item C<-k>
+
+Keep going as far as possible after errors.
+
+=item C<-o> <file>
+
+Read override file I<file>.
+
+=item C<-p>
+
+Show construction products in specified trees. No build is attempted.
+
+=item C<-pa>
+
+Show construction products and associated actions. No build is attempted.
+
+=item C<-pw>
+
+Show products and where they are defined. No build is attempted.
+
+=item C<-q>
+
+Make the build quiet. Multiple C<-q> options may be specified.
+
+A single C<-q> options suppress messages about Installing and Removing
+targets.
+
+Two C<-q> options suppress build command lines and target up-to-date
+messages.
+
+=item C<-r>
+
+Remove construction products associated with <targets>. No build is
+attempted.
+
+=item C<-R> <repos>
+
+Search for files in I<repos>. Multiple B<-R> I<repos> directories are
+searched in the order specified.
+
+=item C<-S> <pkg>
+
+Use the sig::<pkg> package to calculate. Supported <pkg> values
+include "md5" for MD5 signature calculation and "md5::debug" for debug
+information about MD5 signature calculation.
+
+If the specified package ends in <::debug>, signature debug information
+will be printed to the file name specified in the C<CONS_SIG_DEBUG>
+environment variable, or to standard output if the environment variable
+is not set.
+
+=item C<-t>
+
+Traverse up the directory hierarchy looking for a F<Construct> file,
+if none exists in the current directory. Targets will be modified to
+be relative to the F<Construct> file.
+
+Internally, C<cons> will change its working directory to the directory
+which contains the top-level F<Construct> file and report:
+
+ cons: Entering directory `top-level-directory'
+
+This message indicates to an invoking editor (such as emacs) or build
+environment that Cons will now report all file names relative to the
+top-level directory. This message can not be suppressed with the C<-q>
+option.
+
+=item C<-v>
+
+Show C<cons> version and continue processing.
+
+=item C<-V>
+
+Show C<cons> version and exit.
+
+=item C<-wf> <file>
+
+Write all filenames considered into I<file>.
+
+=item C<-x>
+
+Show a help message similar to this one, and exit.
+
+=back
+
+And I<construct-args> can be any arguments that you wish to process in the
+F<Construct> file. Note that there should be a B<-,-> separating the arguments
+to cons and the arguments that you wish to process in the F<Construct> file.
+
+Processing of I<construct-args> can be done by any standard package like
+B<Getopt> or its variants, or any user defined package. B<cons> will pass in
+the I<construct-args> as B<@ARGV> and will not attempt to interpret anything
+after the B<-,->.
+
+ % cons -R /usr/local/repository -d os=solaris +driver -,- -c test -f DEBUG
+
+would pass the following to cons
+
+ -R /usr/local/repository -d os=solaris +driver
+
+and the following, to the top level F<Construct> file as B<@ARGV>
+
+ -c test -f DEBUG
+
+Note that C<cons -r .> is equivalent to a full recursive C<make clean>,
+but requires no support in the F<Construct> file or any F<Conscript>
+files. This is most useful if you are compiling files into source
+directories (if you separate the F<build> and F<export> directories,
+then you can just remove the directories).
+
+The options C<-p>, C<-pa>, and C<-pw> are extremely useful for use as an aid
+in reading scripts or debugging them. If you want to know what script
+installs F<export/include/foo.h>, for example, just type:
+
+ % cons -pw export/include/foo.h
+
+=head1 Selective builds
+
+Cons provides two methods for reducing the size of given build. The first is
+by specifying targets on the command line, and the second is a method for
+pruning the build tree. We'll consider target specification first.
+
+
+=head2 Selective targeting
+
+Like make, Cons allows the specification of ``targets'' on the command
+line. Cons targets may be either files or directories. When a directory is
+specified, this is simply a short-hand notation for every derivable
+product-,-that Cons knows about-,-in the specified directory and below. For
+example:
+
+ % cons build/hello/hello.o
+
+means build F<hello.o> and everything that F<hello.o> might need. This is
+from a previous version of the B<Hello, World!> program in which F<hello.o>
+depended upon F<export/include/world.h>. If that file is not up-to-date
+(because someone modified F<src/world/world.h)>, then it will be rebuilt,
+even though it is in a directory remote from F<build/hello>.
+
+In this example:
+
+ % cons build
+
+Everything in the F<build> directory is built, if necessary. Again, this may
+cause more files to be built. In particular, both F<export/include/world.h>
+and F<export/lib/libworld.a> are required by the F<build/hello> directory,
+and so they will be built if they are out-of-date.
+
+If we do, instead:
+
+ % cons export
+
+then only the files that should be installed in the export directory will be
+rebuilt, if necessary, and then installed there. Note that C<cons build>
+might build files that C<cons export> doesn't build, and vice-versa.
+
+
+=head1 Build Pruning
+
+In conjunction with target selection, B<build pruning> can be used to reduce
+the scope of the build. In the previous peAcH and baNaNa example, we have
+already seen how script-driven build pruning can be used to make only half
+of the potential build available for any given invocation of C<cons>. Cons
+also provides, as a convenience, a command line convention that allows you
+to specify which F<Conscript> files actually get ``built''-,-that is,
+incorporated into the build tree. For example:
+
+ % cons build +world
+
+The C<+> argument introduces a Perl regular expression. This must, of
+course, be quoted at the shell level if there are any shell meta-characters
+within the expression. The expression is matched against each F<Conscript>
+file which has been mentioned in a C<Build> statement, and only those
+scripts with matching names are actually incorporated into the build
+tree. Multiple such arguments are allowed, in which case a match against any
+of them is sufficient to cause a script to be included.
+
+In the example, above, the F<hello> program will not be built, since Cons
+will have no knowledge of the script F<hello/Conscript>. The F<libworld.a>
+archive will be built, however, if need be.
+
+There are a couple of uses for build pruning via the command line. Perhaps
+the most useful is the ability to make local changes, and then, with
+sufficient knowledge of the consequences of those changes, restrict the size
+of the build tree in order to speed up the rebuild time. A second use for
+build pruning is to actively prevent the recompilation of certain files that
+you know will recompile due to, for example, a modified header file. You may
+know that either the changes to the header file are immaterial, or that the
+changes may be safely ignored for most of the tree, for testing
+purposes.With Cons, the view is that it is pragmatic to admit this type of
+behavior, with the understanding that on the next full build everything that
+needs to be rebuilt will be. There is no equivalent to a ``make touch''
+command, to mark files as permanently up-to-date. So any risk that is
+incurred by build pruning is mitigated. For release quality work, obviously,
+we recommend that you do not use build pruning (it's perfectly OK to use
+during integration, however, for checking compilation, etc. Just be sure to
+do an unconstrained build before committing the integration).
+
+-->
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <section>
+ <title>Command-Line Options</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Getting at Command-Line Arguments</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Selective Builds</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Build Pruning</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>Overriding Construction Variables</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
diff --git a/doc/user/scanners.in b/doc/user/scanners.in
new file mode 100644
index 0000000..8fa36d7
--- /dev/null
+++ b/doc/user/scanners.in
@@ -0,0 +1,331 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Using and writing dependency scanners
+
+QuickScan allows simple target-independent scanners to be set up for
+source files. Only one QuickScan scanner may be associated with any given
+source file and environment, although the same scanner may (and should)
+be used for multiple files of a given type.
+
+A QuickScan scanner is only ever invoked once for a given source file,
+and it is only invoked if the file is used by some target in the tree
+(i.e., there is a dependency on the source file).
+
+QuickScan is invoked as follows:
+
+ QuickScan CONSENV CODEREF, FILENAME [, PATH]
+
+The subroutine referenced by CODEREF is expected to return a list of
+filenames included directly by FILE. These filenames will, in turn, be
+scanned. The optional PATH argument supplies a lookup path for finding
+FILENAME and/or files returned by the user-supplied subroutine. The PATH
+may be a reference to an array of lookup-directory names, or a string of
+names separated by the system's separator character (':' on UNIX systems,
+';' on Windows NT).
+
+The subroutine is called once for each line in the file, with $_ set to the
+current line. If the subroutine needs to look at additional lines, or, for
+that matter, the entire file, then it may read them itself, from the
+filehandle SCAN. It may also terminate the loop, if it knows that no further
+include information is available, by closing the filehandle.
+
+Whether or not a lookup path is provided, QuickScan first tries to lookup
+the file relative to the current directory (for the top-level file
+supplied directly to QuickScan), or from the directory containing the
+file which referenced the file. This is not very general, but seems good
+enough, especially if you have the luxury of writing your own utilities
+and can control the use of the search path in a standard way.
+
+Here's a real example, taken from a F<Construct> file here:
+
+ sub cons::SMFgen {
+ my($env, @tables) = @_;
+ foreach $t (@tables) {
+ $env->QuickScan(sub { /\b\S*?\.smf\b/g }, "$t.smf",
+ $env->{SMF_INCLUDE_PATH});
+ $env->Command(["$t.smdb.cc","$t.smdb.h","$t.snmp.cc",
+ "$t.ami.cc", "$t.http.cc"], "$t.smf",
+ q(smfgen %( %SMF_INCLUDE_OPT %) %<));
+ }
+ }
+
+The subroutine above finds all names of the form <name>.smf in the
+file. It will return the names even if they're found within comments,
+but that's OK (the mechanism is forgiving of extra files; they're just
+ignored on the assumption that the missing file will be noticed when
+the program, in this example, smfgen, is actually invoked).
+
+[NOTE that the form C<$env-E<gt>QuickScan ...> and C<$env-E<gt>Command
+...> should not be necessary, but, for some reason, is required
+for this particular invocation. This appears to be a bug in Perl or
+a misunderstanding on my part; this invocation style does not always
+appear to be necessary.]
+
+Here is another way to build the same scanner. This one uses an
+explicit code reference, and also (unnecessarily, in this case) reads
+the whole file itself:
+
+ sub myscan {
+ my(@includes);
+ do {
+ push(@includes, /\b\S*?\.smf\b/g);
+ } while <SCAN>;
+ @includes
+ }
+
+Note that the order of the loop is reversed, with the loop test at the
+end. This is because the first line is already read for you. This scanner
+can be attached to a source file by:
+
+ QuickScan $env \&myscan, "$_.smf";
+
+This final example, which scans a different type of input file, takes
+over the file scanning rather than being called for each input line:
+
+ $env->QuickScan(
+ sub { my(@includes) = ();
+ do {
+ push(@includes, $3)
+ if /^(#include|import)\s+(\")(.+)(\")/ && $3
+ } while <SCAN>;
+ @includes
+ },
+ "$idlFileName",
+ "$env->{CPPPATH};$BUILD/ActiveContext/ACSCLientInterfaces"
+ );
+
+-->
+
+ <para>
+
+ &SCons; has built-in scanners that know how to look in
+ C, Fortran and IDL source files for information about
+ other files that targets built from those files depend on--for example,
+ in the case of files that use the C preprocessor,
+ the <filename>.h</filename> files that are specified
+ using <literal>#include</literal> lines in the source.
+ You can use the same mechanisms that &SCons; uses to create
+ its built-in scanners to write scanners of your own for file types
+ that &SCons; does not know how to scan "out of the box."
+
+ </para>
+
+ <section>
+ <title>A Simple Scanner Example</title>
+
+ <para>
+
+ Suppose, for example, that we want to create a simple scanner
+ for <filename>.foo</filename> files.
+ A <filename>.foo</filename> file contains some text that
+ will be processed,
+ and can include other files on lines that begin
+ with <literal>include</literal>
+ followed by a file name:
+
+ </para>
+
+ <programlisting>
+ include filename.foo
+ </programlisting>
+
+ <para>
+
+ Scanning a file will be handled by a Python function
+ that you must supply.
+ Here is a function that will use the Python
+ <filename>re</filename> module
+ to scan for the <literal>include</literal> lines in our example:
+
+ </para>
+
+ <programlisting>
+ import re
+
+ include_re = re.compile(r'^include\s+(\S+)$', re.M)
+
+ def kfile_scan(node, env, path, arg):
+ contents = node.get_text_contents()
+ return include_re.findall(contents)
+ </programlisting>
+
+ <para>
+
+ The scanner function must
+ accept the four specified arguments
+ and return a list of implicit dependencies.
+ Presumably, these would be dependencies found
+ from examining the contents of the file,
+ although the function can perform any
+ manipulation at all to generate the list of
+ dependencies.
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>node</term>
+
+ <listitem>
+ <para>
+
+ An &SCons; node object representing the file being scanned.
+ The path name to the file can be
+ used by converting the node to a string
+ using the <literal>str()</literal> function,
+ or an internal &SCons; <literal>get_text_contents()</literal>
+ object method can be used to fetch the contents.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The construction environment in effect for this scan.
+ The scanner function may choose to use construction
+ variables from this environment to affect its behavior.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>path</term>
+
+ <listitem>
+ <para>
+
+ A list of directories that form the search path for included files
+ for this scanner.
+ This is how &SCons; handles the &cv-link-CPPPATH; and &cv-link-LIBPATH;
+ variables.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>arg</term>
+
+ <listitem>
+ <para>
+
+ An optional argument that you can choose to
+ have passed to this scanner function by
+ various scanner instances.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ A Scanner object is created using the &Scanner; function,
+ which typically takes an <literal>skeys</literal> argument
+ to associate the type of file suffix with this scanner.
+ The Scanner object must then be associated with the
+ &cv-link-SCANNERS; construction variable of a construction environment,
+ typically by using the &Append; method:
+
+ </para>
+
+ <programlisting>
+ kscan = Scanner(function = kfile_scan,
+ skeys = ['.k'])
+ env.Append(SCANNERS = kscan)
+ </programlisting>
+
+ <para>
+
+ When we put it all together, it looks like:
+
+ </para>
+
+ <scons_example name="scan">
+ <file name="SConstruct" printme="1">
+ import re
+
+ include_re = re.compile(r'^include\s+(\S+)$', re.M)
+
+ def kfile_scan(node, env, path):
+ contents = node.get_text_contents()
+ includes = include_re.findall(contents)
+ return includes
+
+ kscan = Scanner(function = kfile_scan,
+ skeys = ['.k'])
+
+ env = Environment(ENV = {'PATH' : '__ROOT__/usr/local/bin'})
+ env.Append(SCANNERS = kscan)
+
+ env.Command('foo', 'foo.k', 'kprocess &lt; $SOURCES &gt; $TARGET')
+ </file>
+ <file name="foo.k">
+ include other_file
+ </file>
+ <file name="other_file">
+ other_file
+ </file>
+ <directory name="__ROOT__/usr"></directory>
+ <directory name="__ROOT__/usr/local"></directory>
+ <directory name="__ROOT__/usr/local/bin"></directory>
+ <file name="__ROOT_/usr/local/bin/kprocess" chmod="755">
+ cat
+ </file>
+ </scons_example>
+
+ <!--
+
+ <para>
+
+ Now if we run &scons;
+ and then re-run it after changing the contents of
+ <filename>other_file</filename>,
+ the <filename>foo</filename>
+ target file will be automatically rebuilt:
+
+ </para>
+
+ <scons_output example="scan">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF other_file]">edit other_file</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ </section>
diff --git a/doc/user/scanners.xml b/doc/user/scanners.xml
new file mode 100644
index 0000000..d34b222
--- /dev/null
+++ b/doc/user/scanners.xml
@@ -0,0 +1,317 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Using and writing dependency scanners
+
+QuickScan allows simple target-independent scanners to be set up for
+source files. Only one QuickScan scanner may be associated with any given
+source file and environment, although the same scanner may (and should)
+be used for multiple files of a given type.
+
+A QuickScan scanner is only ever invoked once for a given source file,
+and it is only invoked if the file is used by some target in the tree
+(i.e., there is a dependency on the source file).
+
+QuickScan is invoked as follows:
+
+ QuickScan CONSENV CODEREF, FILENAME [, PATH]
+
+The subroutine referenced by CODEREF is expected to return a list of
+filenames included directly by FILE. These filenames will, in turn, be
+scanned. The optional PATH argument supplies a lookup path for finding
+FILENAME and/or files returned by the user-supplied subroutine. The PATH
+may be a reference to an array of lookup-directory names, or a string of
+names separated by the system's separator character (':' on UNIX systems,
+';' on Windows NT).
+
+The subroutine is called once for each line in the file, with $_ set to the
+current line. If the subroutine needs to look at additional lines, or, for
+that matter, the entire file, then it may read them itself, from the
+filehandle SCAN. It may also terminate the loop, if it knows that no further
+include information is available, by closing the filehandle.
+
+Whether or not a lookup path is provided, QuickScan first tries to lookup
+the file relative to the current directory (for the top-level file
+supplied directly to QuickScan), or from the directory containing the
+file which referenced the file. This is not very general, but seems good
+enough, especially if you have the luxury of writing your own utilities
+and can control the use of the search path in a standard way.
+
+Here's a real example, taken from a F<Construct> file here:
+
+ sub cons::SMFgen {
+ my($env, @tables) = @_;
+ foreach $t (@tables) {
+ $env->QuickScan(sub { /\b\S*?\.smf\b/g }, "$t.smf",
+ $env->{SMF_INCLUDE_PATH});
+ $env->Command(["$t.smdb.cc","$t.smdb.h","$t.snmp.cc",
+ "$t.ami.cc", "$t.http.cc"], "$t.smf",
+ q(smfgen %( %SMF_INCLUDE_OPT %) %<));
+ }
+ }
+
+The subroutine above finds all names of the form <name>.smf in the
+file. It will return the names even if they're found within comments,
+but that's OK (the mechanism is forgiving of extra files; they're just
+ignored on the assumption that the missing file will be noticed when
+the program, in this example, smfgen, is actually invoked).
+
+[NOTE that the form C<$env-E<gt>QuickScan ...> and C<$env-E<gt>Command
+...> should not be necessary, but, for some reason, is required
+for this particular invocation. This appears to be a bug in Perl or
+a misunderstanding on my part; this invocation style does not always
+appear to be necessary.]
+
+Here is another way to build the same scanner. This one uses an
+explicit code reference, and also (unnecessarily, in this case) reads
+the whole file itself:
+
+ sub myscan {
+ my(@includes);
+ do {
+ push(@includes, /\b\S*?\.smf\b/g);
+ } while <SCAN>;
+ @includes
+ }
+
+Note that the order of the loop is reversed, with the loop test at the
+end. This is because the first line is already read for you. This scanner
+can be attached to a source file by:
+
+ QuickScan $env \&myscan, "$_.smf";
+
+This final example, which scans a different type of input file, takes
+over the file scanning rather than being called for each input line:
+
+ $env->QuickScan(
+ sub { my(@includes) = ();
+ do {
+ push(@includes, $3)
+ if /^(#include|import)\s+(\")(.+)(\")/ && $3
+ } while <SCAN>;
+ @includes
+ },
+ "$idlFileName",
+ "$env->{CPPPATH};$BUILD/ActiveContext/ACSCLientInterfaces"
+ );
+
+-->
+
+ <para>
+
+ &SCons; has built-in scanners that know how to look in
+ C, Fortran and IDL source files for information about
+ other files that targets built from those files depend on--for example,
+ in the case of files that use the C preprocessor,
+ the <filename>.h</filename> files that are specified
+ using <literal>#include</literal> lines in the source.
+ You can use the same mechanisms that &SCons; uses to create
+ its built-in scanners to write scanners of your own for file types
+ that &SCons; does not know how to scan "out of the box."
+
+ </para>
+
+ <section>
+ <title>A Simple Scanner Example</title>
+
+ <para>
+
+ Suppose, for example, that we want to create a simple scanner
+ for <filename>.foo</filename> files.
+ A <filename>.foo</filename> file contains some text that
+ will be processed,
+ and can include other files on lines that begin
+ with <literal>include</literal>
+ followed by a file name:
+
+ </para>
+
+ <programlisting>
+ include filename.foo
+ </programlisting>
+
+ <para>
+
+ Scanning a file will be handled by a Python function
+ that you must supply.
+ Here is a function that will use the Python
+ <filename>re</filename> module
+ to scan for the <literal>include</literal> lines in our example:
+
+ </para>
+
+ <programlisting>
+ import re
+
+ include_re = re.compile(r'^include\s+(\S+)$', re.M)
+
+ def kfile_scan(node, env, path, arg):
+ contents = node.get_text_contents()
+ return include_re.findall(contents)
+ </programlisting>
+
+ <para>
+
+ The scanner function must
+ accept the four specified arguments
+ and return a list of implicit dependencies.
+ Presumably, these would be dependencies found
+ from examining the contents of the file,
+ although the function can perform any
+ manipulation at all to generate the list of
+ dependencies.
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>node</term>
+
+ <listitem>
+ <para>
+
+ An &SCons; node object representing the file being scanned.
+ The path name to the file can be
+ used by converting the node to a string
+ using the <literal>str()</literal> function,
+ or an internal &SCons; <literal>get_text_contents()</literal>
+ object method can be used to fetch the contents.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The construction environment in effect for this scan.
+ The scanner function may choose to use construction
+ variables from this environment to affect its behavior.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>path</term>
+
+ <listitem>
+ <para>
+
+ A list of directories that form the search path for included files
+ for this scanner.
+ This is how &SCons; handles the &cv-link-CPPPATH; and &cv-link-LIBPATH;
+ variables.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>arg</term>
+
+ <listitem>
+ <para>
+
+ An optional argument that you can choose to
+ have passed to this scanner function by
+ various scanner instances.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ A Scanner object is created using the &Scanner; function,
+ which typically takes an <literal>skeys</literal> argument
+ to associate the type of file suffix with this scanner.
+ The Scanner object must then be associated with the
+ &cv-link-SCANNERS; construction variable of a construction environment,
+ typically by using the &Append; method:
+
+ </para>
+
+ <programlisting>
+ kscan = Scanner(function = kfile_scan,
+ skeys = ['.k'])
+ env.Append(SCANNERS = kscan)
+ </programlisting>
+
+ <para>
+
+ When we put it all together, it looks like:
+
+ </para>
+
+ <programlisting>
+ import re
+
+ include_re = re.compile(r'^include\s+(\S+)$', re.M)
+
+ def kfile_scan(node, env, path):
+ contents = node.get_text_contents()
+ includes = include_re.findall(contents)
+ return includes
+
+ kscan = Scanner(function = kfile_scan,
+ skeys = ['.k'])
+
+ env = Environment(ENV = {'PATH' : '/usr/local/bin'})
+ env.Append(SCANNERS = kscan)
+
+ env.Command('foo', 'foo.k', 'kprocess &lt; $SOURCES &gt; $TARGET')
+ </programlisting>
+
+ <!--
+
+ <para>
+
+ Now if we run &scons;
+ and then re-run it after changing the contents of
+ <filename>other_file</filename>,
+ the <filename>foo</filename>
+ target file will be automatically rebuilt:
+
+ </para>
+
+ <scons_output example="scan">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF other_file]">edit other_file</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ </section>
diff --git a/doc/user/sconf.in b/doc/user/sconf.in
new file mode 100644
index 0000000..c4092c9
--- /dev/null
+++ b/doc/user/sconf.in
@@ -0,0 +1,486 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; has integrated support for multi-platform build configuration
+ similar to that offered by GNU &Autoconf;,
+ such as
+ figuring out what libraries or header files
+ are available on the local system.
+ This section describes how to use
+ this &SCons feature.
+
+ </para>
+
+ <note>
+ <para>
+ This chapter is still under development,
+ so not everything is explained as well as it should be.
+ See the &SCons; man page for additional information.
+ </para>
+ </note>
+
+ <section>
+ <title>&Configure_Contexts;</title>
+
+ <para>
+
+ The basic framework for multi-platform build configuration
+ in &SCons; is to attach a &configure_context; to a
+ construction environment by calling the &Configure; function,
+ perform a number of checks for
+ libraries, functions, header files, etc.,
+ and to then call the configure context's &Finish; method
+ to finish off the configuration:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ conf = Configure(env)
+ # Checks for libraries, header files, etc. go here!
+ env = conf.Finish()
+ </sconstruct>
+
+ <para>
+
+ &SCons; provides a number of basic checks,
+ as well as a mechanism for adding your own custom checks.
+
+ </para>
+
+ <para>
+
+ Note that &SCons; uses its own dependency
+ mechanism to determine when a check
+ needs to be run--that is,
+ &SCons; does not run the checks
+ every time it is invoked,
+ but caches the values returned by previous checks
+ and uses the cached values unless something has changed.
+ This saves a tremendous amount
+ of developer time while working on
+ cross-platform build issues.
+
+ </para>
+
+ <para>
+
+ The next sections describe
+ the basic checks that &SCons; supports,
+ as well as how to add your own custom checks.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Checking for the Existence of Header Files</title>
+
+ <para>
+
+ Testing the existence of a header file
+ requires knowing what language the header file is.
+ A configure context has a &CheckCHeader; method
+ that checks for the existence of a C header file:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckCHeader('math.h'):
+ print 'Math.h must be installed!'
+ Exit(1)
+ if conf.CheckCHeader('foo.h'):
+ conf.env.Append('-DHAS_FOO_H')
+ env = conf.Finish()
+ </sconstruct>
+
+ <para>
+
+ Note that you can choose to terminate
+ the build if a given header file doesn't exist,
+ or you can modify the construction environment
+ based on the existence of a header file.
+
+ </para>
+
+ <para>
+
+ If you need to check for the existence
+ a C++ header file,
+ use the &CheckCXXHeader; method:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckCXXHeader('vector.h'):
+ print 'vector.h must be installed!'
+ Exit(1)
+ env = conf.Finish()
+ </sconstruct>
+
+ </section>
+
+ <section>
+ <title>Checking for the Availability of a Function</title>
+
+ <para>
+
+ Check for the availability of a specific function
+ using the &CheckFunc; method:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckFunc('strcpy'):
+ print 'Did not find strcpy(), using local version'
+ conf.env.Append(CPPDEFINES = '-Dstrcpy=my_local_strcpy')
+ env = conf.Finish()
+ </sconstruct>
+
+ </section>
+
+ <section>
+ <title>Checking for the Availability of a Library</title>
+
+ <para>
+
+ Check for the availability of a library
+ using the &CheckLib; method.
+ You only specify the basename of the library,
+ you don't need to add a <literal>lib</literal>
+ prefix or a <literal>.a</literal> or <literal>.lib</literal> suffix:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckLib('m'):
+ print 'Did not find libm.a or m.lib, exiting!'
+ Exit(1)
+ env = conf.Finish()
+ </sconstruct>
+
+ <para>
+
+ Because the ability to use a library successfully
+ often depends on having access to a header file
+ that describes the library's interface,
+ you can check for a library
+ <emphasis>and</emphasis> a header file
+ at the same time by using the
+ &CheckLibWithHeader; method:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckLibWithHeader('m', 'math.h', 'c'):
+ print 'Did not find libm.a or m.lib, exiting!'
+ Exit(1)
+ env = conf.Finish()
+ </sconstruct>
+
+ <para>
+
+ This is essentially shorthand for
+ separate calls to the &CheckHeader; and &CheckLib;
+ functions.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Checking for the Availability of a &typedef;</title>
+
+ <para>
+
+ Check for the availability of a &typedef;
+ by using the &CheckType; method:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckType('off_t'):
+ print 'Did not find off_t typedef, assuming int'
+ conf.env.Append(CCFLAGS = '-Doff_t=int')
+ env = conf.Finish()
+ </sconstruct>
+
+ <para>
+
+ You can also add a string that will be
+ placed at the beginning of the test file
+ that will be used to check for the &typedef;.
+ This provide a way to specify
+ files that must be included to find the &typedef;:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckType('off_t', '#include &amp;lt;sys/types.h&amp;gt;\n'):
+ print 'Did not find off_t typedef, assuming int'
+ conf.env.Append(CCFLAGS = '-Doff_t=int')
+ env = conf.Finish()
+ </sconstruct>
+
+ </section>
+
+ <section>
+ <title>Adding Your Own Custom Checks</title>
+
+ <para>
+
+ A custom check is a Python function
+ that checks for a certain condition to exist
+ on the running system,
+ usually using methods that &SCons;
+ supplies to take care of the details
+ of checking whether a compilation succeeds,
+ a link succeeds,
+ a program is runnable,
+ etc.
+ A simple custom check for the existence of
+ a specific library might look as follows:
+
+ </para>
+
+ <sconstruct>
+ mylib_test_source_file = """
+ #include &amp;lt;mylib.h&amp;gt;
+ int main(int argc, char **argv)
+ {
+ MyLibrary mylib(argc, argv);
+ return 0;
+ }
+ """
+
+ def CheckMyLibrary(context):
+ context.Message('Checking for MyLibrary...')
+ result = context.TryLink(mylib_test_source_file, '.c')
+ context.Result(result)
+ return result
+ </sconstruct>
+
+ <para>
+
+ The &Message; and &Result; methods
+ should typically begin and end a custom check to
+ let the user know what's going on:
+ the &Message; call prints the
+ specified message (with no trailing newline)
+ and the &Result; call prints
+ <literal>yes</literal> if the check succeeds and
+ <literal>no</literal> if it doesn't.
+ The &TryLink; method
+ actually tests for whether the
+ specified program text
+ will successfully link.
+
+ </para>
+
+ <para>
+
+ (Note that a custom check can modify
+ its check based on any arguments you
+ choose to pass it,
+ or by using or modifying the configure context environment
+ in the <literal>context.env</literal> attribute.)
+
+ </para>
+
+ <para>
+
+ This custom check function is
+ then attached to the &configure_context;
+ by passing a dictionary
+ to the &Configure; call
+ that maps a name of the check
+ to the underlying function:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
+ </sconstruct>
+
+ <para>
+
+ You'll typically want to make
+ the check and the function name the same,
+ as we've done here,
+ to avoid potential confusion.
+
+ </para>
+
+ <para>
+
+ We can then put these pieces together
+ and actually call the <literal>CheckMyLibrary</literal> check
+ as follows:
+
+ </para>
+
+ <sconstruct>
+ mylib_test_source_file = """
+ #include &amp;lt;mylib.h&amp;gt;
+ int main(int argc, char **argv)
+ {
+ MyLibrary mylib(argc, argv);
+ return 0;
+ }
+ """
+
+ def CheckMyLibrary(context):
+ context.Message('Checking for MyLibrary... ')
+ result = context.TryLink(mylib_test_source_file, '.c')
+ context.Result(result)
+ return result
+
+ env = Environment()
+ conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
+ if not conf.CheckMyLibrary():
+ print 'MyLibrary is not installed!'
+ Exit(1)
+ env = conf.Finish()
+
+ # We would then add actual calls like Program() to build
+ # something using the "env" construction environment.
+ </sconstruct>
+
+ <para>
+
+ If MyLibrary is not installed on the system,
+ the output will look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript file ...
+ Checking for MyLibrary... failed
+ MyLibrary is not installed!
+ </screen>
+
+ <para>
+
+ If MyLibrary is installed,
+ the output will look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript file ...
+ Checking for MyLibrary... failed
+ scons: done reading SConscript
+ scons: Building targets ...
+ .
+ .
+ .
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Not Configuring When Cleaning Targets</title>
+
+ <para>
+
+ Using multi-platform configuration
+ as described in the previous sections
+ will run the configuration commands
+ even when invoking
+ <userinput>scons -c</userinput>
+ to clean targets:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q -c</userinput>
+ Checking for MyLibrary... yes
+ Removed foo.o
+ Removed foo
+ </screen>
+
+ <para>
+
+ Although running the platform checks
+ when removing targets doesn't hurt anything,
+ it's usually unnecessary.
+ You can avoid this by using the
+ &GetOption(); method to
+ check whether the <option>-c</option> (clean)
+ option has been invoked on the command line:
+
+ </para>
+
+ <sconstruct>
+ env = Environment()
+ if not env.GetOption('clean'):
+ conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
+ if not conf.CheckMyLibrary():
+ print 'MyLibrary is not installed!'
+ Exit(1)
+ env = conf.Finish()
+ </sconstruct>
+
+ <screen>
+ % <userinput>scons -Q -c</userinput>
+ Removed foo.o
+ Removed foo
+ </screen>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Controlling Configuration: the &config; Option</title>
+
+ <para>
+
+ XXX -D, -u and -U
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml
new file mode 100644
index 0000000..16ba534
--- /dev/null
+++ b/doc/user/sconf.xml
@@ -0,0 +1,486 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ &SCons; has integrated support for multi-platform build configuration
+ similar to that offered by GNU &Autoconf;,
+ such as
+ figuring out what libraries or header files
+ are available on the local system.
+ This section describes how to use
+ this &SCons; feature.
+
+ </para>
+
+ <note>
+ <para>
+ This chapter is still under development,
+ so not everything is explained as well as it should be.
+ See the &SCons; man page for additional information.
+ </para>
+ </note>
+
+ <section>
+ <title>&Configure_Contexts;</title>
+
+ <para>
+
+ The basic framework for multi-platform build configuration
+ in &SCons; is to attach a &configure_context; to a
+ construction environment by calling the &Configure; function,
+ perform a number of checks for
+ libraries, functions, header files, etc.,
+ and to then call the configure context's &Finish; method
+ to finish off the configuration:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ conf = Configure(env)
+ # Checks for libraries, header files, etc. go here!
+ env = conf.Finish()
+ </programlisting>
+
+ <para>
+
+ &SCons; provides a number of basic checks,
+ as well as a mechanism for adding your own custom checks.
+
+ </para>
+
+ <para>
+
+ Note that &SCons; uses its own dependency
+ mechanism to determine when a check
+ needs to be run--that is,
+ &SCons; does not run the checks
+ every time it is invoked,
+ but caches the values returned by previous checks
+ and uses the cached values unless something has changed.
+ This saves a tremendous amount
+ of developer time while working on
+ cross-platform build issues.
+
+ </para>
+
+ <para>
+
+ The next sections describe
+ the basic checks that &SCons; supports,
+ as well as how to add your own custom checks.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Checking for the Existence of Header Files</title>
+
+ <para>
+
+ Testing the existence of a header file
+ requires knowing what language the header file is.
+ A configure context has a &CheckCHeader; method
+ that checks for the existence of a C header file:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckCHeader('math.h'):
+ print 'Math.h must be installed!'
+ Exit(1)
+ if conf.CheckCHeader('foo.h'):
+ conf.env.Append('-DHAS_FOO_H')
+ env = conf.Finish()
+ </programlisting>
+
+ <para>
+
+ Note that you can choose to terminate
+ the build if a given header file doesn't exist,
+ or you can modify the construction environment
+ based on the existence of a header file.
+
+ </para>
+
+ <para>
+
+ If you need to check for the existence
+ a C++ header file,
+ use the &CheckCXXHeader; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckCXXHeader('vector.h'):
+ print 'vector.h must be installed!'
+ Exit(1)
+ env = conf.Finish()
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Checking for the Availability of a Function</title>
+
+ <para>
+
+ Check for the availability of a specific function
+ using the &CheckFunc; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckFunc('strcpy'):
+ print 'Did not find strcpy(), using local version'
+ conf.env.Append(CPPDEFINES = '-Dstrcpy=my_local_strcpy')
+ env = conf.Finish()
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Checking for the Availability of a Library</title>
+
+ <para>
+
+ Check for the availability of a library
+ using the &CheckLib; method.
+ You only specify the basename of the library,
+ you don't need to add a <literal>lib</literal>
+ prefix or a <literal>.a</literal> or <literal>.lib</literal> suffix:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckLib('m'):
+ print 'Did not find libm.a or m.lib, exiting!'
+ Exit(1)
+ env = conf.Finish()
+ </programlisting>
+
+ <para>
+
+ Because the ability to use a library successfully
+ often depends on having access to a header file
+ that describes the library's interface,
+ you can check for a library
+ <emphasis>and</emphasis> a header file
+ at the same time by using the
+ &CheckLibWithHeader; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckLibWithHeader('m', 'math.h', 'c'):
+ print 'Did not find libm.a or m.lib, exiting!'
+ Exit(1)
+ env = conf.Finish()
+ </programlisting>
+
+ <para>
+
+ This is essentially shorthand for
+ separate calls to the &CheckHeader; and &CheckLib;
+ functions.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Checking for the Availability of a &typedef;</title>
+
+ <para>
+
+ Check for the availability of a &typedef;
+ by using the &CheckType; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckType('off_t'):
+ print 'Did not find off_t typedef, assuming int'
+ conf.env.Append(CCFLAGS = '-Doff_t=int')
+ env = conf.Finish()
+ </programlisting>
+
+ <para>
+
+ You can also add a string that will be
+ placed at the beginning of the test file
+ that will be used to check for the &typedef;.
+ This provide a way to specify
+ files that must be included to find the &typedef;:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ conf = Configure(env)
+ if not conf.CheckType('off_t', '#include &lt;sys/types.h&gt;\n'):
+ print 'Did not find off_t typedef, assuming int'
+ conf.env.Append(CCFLAGS = '-Doff_t=int')
+ env = conf.Finish()
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Adding Your Own Custom Checks</title>
+
+ <para>
+
+ A custom check is a Python function
+ that checks for a certain condition to exist
+ on the running system,
+ usually using methods that &SCons;
+ supplies to take care of the details
+ of checking whether a compilation succeeds,
+ a link succeeds,
+ a program is runnable,
+ etc.
+ A simple custom check for the existence of
+ a specific library might look as follows:
+
+ </para>
+
+ <programlisting>
+ mylib_test_source_file = """
+ #include &lt;mylib.h&gt;
+ int main(int argc, char **argv)
+ {
+ MyLibrary mylib(argc, argv);
+ return 0;
+ }
+ """
+
+ def CheckMyLibrary(context):
+ context.Message('Checking for MyLibrary...')
+ result = context.TryLink(mylib_test_source_file, '.c')
+ context.Result(result)
+ return result
+ </programlisting>
+
+ <para>
+
+ The &Message; and &Result; methods
+ should typically begin and end a custom check to
+ let the user know what's going on:
+ the &Message; call prints the
+ specified message (with no trailing newline)
+ and the &Result; call prints
+ <literal>yes</literal> if the check succeeds and
+ <literal>no</literal> if it doesn't.
+ The &TryLink; method
+ actually tests for whether the
+ specified program text
+ will successfully link.
+
+ </para>
+
+ <para>
+
+ (Note that a custom check can modify
+ its check based on any arguments you
+ choose to pass it,
+ or by using or modifying the configure context environment
+ in the <literal>context.env</literal> attribute.)
+
+ </para>
+
+ <para>
+
+ This custom check function is
+ then attached to the &configure_context;
+ by passing a dictionary
+ to the &Configure; call
+ that maps a name of the check
+ to the underlying function:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
+ </programlisting>
+
+ <para>
+
+ You'll typically want to make
+ the check and the function name the same,
+ as we've done here,
+ to avoid potential confusion.
+
+ </para>
+
+ <para>
+
+ We can then put these pieces together
+ and actually call the <literal>CheckMyLibrary</literal> check
+ as follows:
+
+ </para>
+
+ <programlisting>
+ mylib_test_source_file = """
+ #include &lt;mylib.h&gt;
+ int main(int argc, char **argv)
+ {
+ MyLibrary mylib(argc, argv);
+ return 0;
+ }
+ """
+
+ def CheckMyLibrary(context):
+ context.Message('Checking for MyLibrary... ')
+ result = context.TryLink(mylib_test_source_file, '.c')
+ context.Result(result)
+ return result
+
+ env = Environment()
+ conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
+ if not conf.CheckMyLibrary():
+ print 'MyLibrary is not installed!'
+ Exit(1)
+ env = conf.Finish()
+
+ # We would then add actual calls like Program() to build
+ # something using the "env" construction environment.
+ </programlisting>
+
+ <para>
+
+ If MyLibrary is not installed on the system,
+ the output will look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript file ...
+ Checking for MyLibrary... failed
+ MyLibrary is not installed!
+ </screen>
+
+ <para>
+
+ If MyLibrary is installed,
+ the output will look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript file ...
+ Checking for MyLibrary... failed
+ scons: done reading SConscript
+ scons: Building targets ...
+ .
+ .
+ .
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Not Configuring When Cleaning Targets</title>
+
+ <para>
+
+ Using multi-platform configuration
+ as described in the previous sections
+ will run the configuration commands
+ even when invoking
+ <userinput>scons -c</userinput>
+ to clean targets:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q -c</userinput>
+ Checking for MyLibrary... yes
+ Removed foo.o
+ Removed foo
+ </screen>
+
+ <para>
+
+ Although running the platform checks
+ when removing targets doesn't hurt anything,
+ it's usually unnecessary.
+ You can avoid this by using the
+ &GetOption;(); method to
+ check whether the <option>-c</option> (clean)
+ option has been invoked on the command line:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ if not env.GetOption('clean'):
+ conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
+ if not conf.CheckMyLibrary():
+ print 'MyLibrary is not installed!'
+ Exit(1)
+ env = conf.Finish()
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q -c</userinput>
+ Removed foo.o
+ Removed foo
+ </screen>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Controlling Configuration: the &config; Option</title>
+
+ <para>
+
+ XXX -D, -u and -U
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/separate.in b/doc/user/separate.in
new file mode 100644
index 0000000..edc6da8
--- /dev/null
+++ b/doc/user/separate.in
@@ -0,0 +1,540 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Separating source and build trees
+
+It's often desirable to keep any derived files from the build completely
+separate from the source files. This makes it much easier to keep track of
+just what is a source file, and also makes it simpler to handle B<variant>
+builds, especially if you want the variant builds to co-exist.
+
+=head2 Separating build and source directories using the Link command
+
+Cons provides a simple mechanism that handles all of these requirements. The
+C<Link> command is invoked as in this example:
+
+ Link 'build' => 'src';
+
+The specified directories are ``linked'' to the specified source
+directory. Let's suppose that you setup a source directory, F<src>, with the
+sub-directories F<world> and F<hello> below it, as in the previous
+example. You could then substitute for the original build lines the
+following:
+
+ Build qw(
+ build/world/Conscript
+ build/hello/Conscript
+ );
+
+Notice that you treat the F<Conscript> file as if it existed in the build
+directory. Now if you type the same command as before, you will get the
+following results:
+
+ % cons export
+ Install build/world/world.h as export/include/world.h
+ cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o
+ cc -Iexport/include -c build/world/world.c -o build/world/world.o
+ ar r build/world/libworld.a build/world/world.o
+ ar: creating build/world/libworld.a
+ ranlib build/world/libworld.a
+ Install build/world/libworld.a as export/lib/libworld.a
+ cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld
+ Install build/hello/hello as export/bin/hello
+
+Again, Cons has taken care of the details for you. In particular, you will
+notice that all the builds are done using source files and object files from
+the build directory. For example, F<build/world/world.o> is compiled from
+F<build/world/world.c>, and F<export/include/world.h> is installed from
+F<build/world/world.h>. This is accomplished on most systems by the simple
+expedient of ``hard'' linking the required files from each source directory
+into the appropriate build directory.
+
+The links are maintained correctly by Cons, no matter what you do to the
+source directory. If you modify a source file, your editor may do this ``in
+place'' or it may rename it first and create a new file. In the latter case,
+any hard link will be lost. Cons will detect this condition the next time
+the source file is needed, and will relink it appropriately.
+
+You'll also notice, by the way, that B<no> changes were required to the
+underlying F<Conscript> files. And we can go further, as we shall see in the
+next section.
+
+=head2 Explicit references to the source directory
+
+When using the C<Link> command on some operating systems or with some
+tool chains, it's sometimes useful to have a command actually use
+the path name to the source directory, not the build directory. For
+example, on systems that must copy, not "hard link," the F<src/> and
+F<build/> copies of C<Linked> files, using the F<src/> path of a file
+name might make an editor aware that a syntax error must be fixed in the
+source directory, not the build directory.
+
+You can tell Cons that you want to use the "source path" for a file by
+preceding the file name with a ``!'' (exclamation point). For example,
+if we add a ``!'' to the beginning of a source file:
+
+ Program $env "foo", "!foo.c"; # Notice initial ! on foo.c
+
+Cons will compile the target as follows:
+
+ cc -c src/foo.c -o build/foo.o
+ cc -o build/foo build/foo.o
+
+Notice that Cons has compiled the program from the the F<src/foo.c>
+source file. Without the initial ``!'', Cons would have compiled the
+program using the F<build/foo.c> path name.
+
+-->
+
+ <para>
+
+ It's often useful to keep any built files completely
+ separate from the source files.
+ In &SCons;, this is usually done by creating one or more separate
+ <emphasis>variant directory trees</emphasis>
+ that are used to hold the built objects files, libraries,
+ and executable programs, etc.
+ for a specific flavor, or variant, of build.
+ &SCons; provides two ways to do this,
+ one through the &SConscript; function that we've already seen,
+ and the second through a more flexible &VariantDir; function.
+
+ </para>
+
+ <para>
+
+ One historical note: the &VariantDir; function
+ used to be called &BuildDir;.
+ That name is still supported
+ but has been deprecated
+ because the &SCons; functionality
+ differs from the model of a "build directory"
+ implemented by other build systems like the GNU Autotools.
+
+ </para>
+
+ <section>
+ <title>Specifying a Variant Directory Tree as Part of an &SConscript; Call</title>
+
+ <para>
+
+ The most straightforward way to establish a variant directory tree
+ uses the fact that the usual way to
+ set up a build hierarchy is to have an
+ &SConscript; file in the source subdirectory.
+ If you then pass a &variant_dir; argument to the
+ &SConscript; function call:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ SConscript('src/SConscript', variant_dir='build')
+ </file>
+ <file name="src/SConscript">
+ env = Environment()
+ env.Program('hello.c')
+ </file>
+ <file name="src/hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; will then build all of the files in
+ the &build; subdirectory:
+
+ </para>
+
+ <scons_output example="ex1">
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ But wait a minute--what's going on here?
+ &SCons; created the object file
+ <filename>build/hello.o</filename>
+ in the &build; subdirectory,
+ as expected.
+ But even though our &hello_c; file lives in the &src; subdirectory,
+ &SCons; has actually compiled a
+ <filename>build/hello.c</filename> file
+ to create the object file.
+
+ </para>
+
+ <para>
+
+ What's happened is that &SCons; has <emphasis>duplicated</emphasis>
+ the &hello_c; file from the &src; subdirectory
+ to the &build; subdirectory,
+ and built the program from there.
+ The next section explains why &SCons; does this.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Why &SCons; Duplicates Source Files in a Variant Directory Tree</title>
+
+ <para>
+
+ &SCons; duplicates source files in variant directory trees
+ because it's the most straightforward way to guarantee a correct build
+ <emphasis>regardless of include-file directory paths,
+ relative references between files,
+ or tool support for putting files in different locations</emphasis>,
+ and the &SCons; philosophy is to, by default,
+ guarantee a correct build in all cases.
+
+ </para>
+
+ <para>
+
+ The most direct reason to duplicate source files
+ in variant directories
+ is simply that some tools (mostly older versions)
+ are written to only build their output files
+ in the same directory as the source files.
+ In this case, the choices are either
+ to build the output file in the source directory
+ and move it to the variant directory,
+ or to duplicate the source files in the variant directory.
+
+ </para>
+
+ <para>
+
+ Additionally,
+ relative references between files
+ can cause problems if we don't
+ just duplicate the hierarchy of source files
+ in the variant directory.
+ You can see this at work in
+ use of the C preprocessor <literal>#include</literal>
+ mechanism with double quotes, not angle brackets:
+
+ </para>
+
+ <sconstruct>
+ #include "file.h"
+ </sconstruct>
+
+ <para>
+
+ The <emphasis>de facto</emphasis> standard behavior
+ for most C compilers in this case
+ is to first look in the same directory
+ as the source file that contains the <literal>#include</literal> line,
+ then to look in the directories in the preprocessor search path.
+ Add to this that the &SCons; implementation of
+ support for code repositories
+ (described below)
+ means not all of the files
+ will be found in the same directory hierarchy,
+ and the simplest way to make sure
+ that the right include file is found
+ is to duplicate the source files into the variant directory,
+ which provides a correct build
+ regardless of the original location(s) of the source files.
+
+ </para>
+
+ <para>
+
+ Although source-file duplication guarantees a correct build
+ even in these end-cases,
+ it <emphasis>can</emphasis> usually be safely disabled.
+ The next section describes
+ how you can disable the duplication of source files
+ in the variant directory.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Telling &SCons; to Not Duplicate Source Files in the Variant Directory Tree</title>
+
+ <para>
+
+ In most cases and with most tool sets,
+ &SCons; can place its target files in a build subdirectory
+ <emphasis>without</emphasis>
+ duplicating the source files
+ and everything will work just fine.
+ You can disable the default &SCons; behavior
+ by specifying <literal>duplicate=0</literal>
+ when you call the &SConscript; function:
+
+ </para>
+
+ <sconstruct>
+ SConscript('src/SConscript', variant_dir='build', duplicate=0)
+ </sconstruct>
+
+ <para>
+
+ When this flag is specified,
+ &SCons; uses the variant directory
+ like most people expect--that is,
+ the output files are placed in the variant directory
+ while the source files stay in the source directory:
+
+ </para>
+
+ <screen>
+ % <userinput>ls src</userinput>
+ SConscript
+ hello.c
+ % <userinput>scons -Q</userinput>
+ cc -c src/hello.c -o build/hello.o
+ cc -o build/hello build/hello.o
+ % <userinput>ls build</userinput>
+ hello
+ hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &VariantDir; Function</title>
+
+ <para>
+
+ Use the &VariantDir; function to establish that target
+ files should be built in a separate directory
+ from the source files:
+
+ </para>
+
+ <scons_example name="ex_builddir">
+ <file name="SConstruct" printme="1">
+ VariantDir('build', 'src')
+ env = Environment()
+ env.Program('build/hello.c')
+ </file>
+ <file name="src/hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Note that when you're not using
+ an &SConscript; file in the &src; subdirectory,
+ you must actually specify that
+ the program must be built from
+ the <filename>build/hello.c</filename>
+ file that &SCons; will duplicate in the
+ &build; subdirectory.
+
+ </para>
+
+ <para>
+
+ When using the &VariantDir; function directly,
+ &SCons; still duplicates the source files
+ in the variant directory by default:
+
+ </para>
+
+ <scons_output example="ex_builddir">
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ You can specify the same <literal>duplicate=0</literal> argument
+ that you can specify for an &SConscript; call:
+
+ </para>
+
+ <scons_example name="ex_duplicate_0">
+ <file name="SConstruct" printme="1">
+ VariantDir('build', 'src', duplicate=0)
+ env = Environment()
+ env.Program('build/hello.c')
+ </file>
+ <file name="src/hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ In which case &SCons;
+ will disable duplication of the source files:
+
+ </para>
+
+ <scons_output example="ex_duplicate_0">
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Using &VariantDir; With an &SConscript; File</title>
+
+ <para>
+
+ Even when using the &VariantDir; function,
+ it's much more natural to use it with
+ a subsidiary &SConscript; file.
+ For example, if the
+ <filename>src/SConscript</filename>
+ looks like this:
+
+ </para>
+
+ <scons_example name="example_builddir_sconscript">
+ <file name="SConstruct">
+ VariantDir('build', 'src')
+ SConscript('build/SConscript')
+ </file>
+ <file name="src/SConscript" printme="1">
+ env = Environment()
+ env.Program('hello.c')
+ </file>
+ <file name="src/hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then our &SConstruct; file could look like:
+
+ </para>
+
+ <scons_example_file example="example_builddir_sconscript" name="SConstruct">
+ </scons_example_file>
+
+ <para>
+
+ Yielding the following output:
+
+ </para>
+
+ <scons_output example="example_builddir_sconscript">
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice that this is completely equivalent
+ to the use of &SConscript; that we
+ learned about in the previous section.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Using &Glob; with &VariantDir;</title>
+
+ <para>
+
+ The &Glob; file name pattern matching function
+ works just as usual when using &VariantDir;.
+ For example, if the
+ <filename>src/SConscript</filename>
+ looks like this:
+
+ </para>
+
+ <scons_example name="example_glob_builddir_sconscript">
+ <file name="SConstruct">
+ VariantDir('build', 'src')
+ SConscript('build/SConscript')
+ </file>
+ <file name="src/SConscript" printme="1">
+ env = Environment()
+ env.Program('hello', Glob('*.c'))
+ </file>
+ <file name="src/f1.c">
+ #include "f2.h"
+ int main() { printf(f2()); }
+ </file>
+ <file name="src/f2.c">
+ const char * f2() { return("Hello, world!\n"); }
+ </file>
+ <file name="src/f2.h">
+ const char * f2();
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then with the same &SConstruct; file as in the previous section,
+ and source files <filename>f1.c</filename>
+ and <filename>f2.c</filename> in src,
+ we would see the following output:
+
+ </para>
+
+ <scons_output example="example_glob_builddir_sconscript">
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The &Glob; function returns Nodes in the
+ <filename>build/</filename> tree, as you'd expect.
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Why You'd Want to Call &VariantDir; Instead of &SConscript;</title>
+
+ <para>
+
+ XXX why call VariantDir() instead of SConscript(variant_dir=)
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/separate.xml b/doc/user/separate.xml
new file mode 100644
index 0000000..fd5bdf0
--- /dev/null
+++ b/doc/user/separate.xml
@@ -0,0 +1,520 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Separating source and build trees
+
+It's often desirable to keep any derived files from the build completely
+separate from the source files. This makes it much easier to keep track of
+just what is a source file, and also makes it simpler to handle B<variant>
+builds, especially if you want the variant builds to co-exist.
+
+=head2 Separating build and source directories using the Link command
+
+Cons provides a simple mechanism that handles all of these requirements. The
+C<Link> command is invoked as in this example:
+
+ Link 'build' => 'src';
+
+The specified directories are ``linked'' to the specified source
+directory. Let's suppose that you setup a source directory, F<src>, with the
+sub-directories F<world> and F<hello> below it, as in the previous
+example. You could then substitute for the original build lines the
+following:
+
+ Build qw(
+ build/world/Conscript
+ build/hello/Conscript
+ );
+
+Notice that you treat the F<Conscript> file as if it existed in the build
+directory. Now if you type the same command as before, you will get the
+following results:
+
+ % cons export
+ Install build/world/world.h as export/include/world.h
+ cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o
+ cc -Iexport/include -c build/world/world.c -o build/world/world.o
+ ar r build/world/libworld.a build/world/world.o
+ ar: creating build/world/libworld.a
+ ranlib build/world/libworld.a
+ Install build/world/libworld.a as export/lib/libworld.a
+ cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld
+ Install build/hello/hello as export/bin/hello
+
+Again, Cons has taken care of the details for you. In particular, you will
+notice that all the builds are done using source files and object files from
+the build directory. For example, F<build/world/world.o> is compiled from
+F<build/world/world.c>, and F<export/include/world.h> is installed from
+F<build/world/world.h>. This is accomplished on most systems by the simple
+expedient of ``hard'' linking the required files from each source directory
+into the appropriate build directory.
+
+The links are maintained correctly by Cons, no matter what you do to the
+source directory. If you modify a source file, your editor may do this ``in
+place'' or it may rename it first and create a new file. In the latter case,
+any hard link will be lost. Cons will detect this condition the next time
+the source file is needed, and will relink it appropriately.
+
+You'll also notice, by the way, that B<no> changes were required to the
+underlying F<Conscript> files. And we can go further, as we shall see in the
+next section.
+
+=head2 Explicit references to the source directory
+
+When using the C<Link> command on some operating systems or with some
+tool chains, it's sometimes useful to have a command actually use
+the path name to the source directory, not the build directory. For
+example, on systems that must copy, not "hard link," the F<src/> and
+F<build/> copies of C<Linked> files, using the F<src/> path of a file
+name might make an editor aware that a syntax error must be fixed in the
+source directory, not the build directory.
+
+You can tell Cons that you want to use the "source path" for a file by
+preceding the file name with a ``!'' (exclamation point). For example,
+if we add a ``!'' to the beginning of a source file:
+
+ Program $env "foo", "!foo.c"; # Notice initial ! on foo.c
+
+Cons will compile the target as follows:
+
+ cc -c src/foo.c -o build/foo.o
+ cc -o build/foo build/foo.o
+
+Notice that Cons has compiled the program from the the F<src/foo.c>
+source file. Without the initial ``!'', Cons would have compiled the
+program using the F<build/foo.c> path name.
+
+-->
+
+ <para>
+
+ It's often useful to keep any built files completely
+ separate from the source files.
+ In &SCons;, this is usually done by creating one or more separate
+ <emphasis>variant directory trees</emphasis>
+ that are used to hold the built objects files, libraries,
+ and executable programs, etc.
+ for a specific flavor, or variant, of build.
+ &SCons; provides two ways to do this,
+ one through the &SConscript; function that we've already seen,
+ and the second through a more flexible &VariantDir; function.
+
+ </para>
+
+ <para>
+
+ One historical note: the &VariantDir; function
+ used to be called &BuildDir;.
+ That name is still supported
+ but has been deprecated
+ because the &SCons; functionality
+ differs from the model of a "build directory"
+ implemented by other build systems like the GNU Autotools.
+
+ </para>
+
+ <section>
+ <title>Specifying a Variant Directory Tree as Part of an &SConscript; Call</title>
+
+ <para>
+
+ The most straightforward way to establish a variant directory tree
+ uses the fact that the usual way to
+ set up a build hierarchy is to have an
+ &SConscript; file in the source subdirectory.
+ If you then pass a &variant_dir; argument to the
+ &SConscript; function call:
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript', variant_dir='build')
+ </programlisting>
+
+ <para>
+
+ &SCons; will then build all of the files in
+ the &build; subdirectory:
+
+ </para>
+
+ <screen>
+ % <userinput>ls src</userinput>
+ SConscript hello.c
+ % <userinput>scons -Q</userinput>
+ cc -o build/hello.o -c build/hello.c
+ cc -o build/hello build/hello.o
+ % <userinput>ls build</userinput>
+ SConscript hello hello.c hello.o
+ </screen>
+
+ <para>
+
+ But wait a minute--what's going on here?
+ &SCons; created the object file
+ <filename>build/hello.o</filename>
+ in the &build; subdirectory,
+ as expected.
+ But even though our &hello_c; file lives in the &src; subdirectory,
+ &SCons; has actually compiled a
+ <filename>build/hello.c</filename> file
+ to create the object file.
+
+ </para>
+
+ <para>
+
+ What's happened is that &SCons; has <emphasis>duplicated</emphasis>
+ the &hello_c; file from the &src; subdirectory
+ to the &build; subdirectory,
+ and built the program from there.
+ The next section explains why &SCons; does this.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Why &SCons; Duplicates Source Files in a Variant Directory Tree</title>
+
+ <para>
+
+ &SCons; duplicates source files in variant directory trees
+ because it's the most straightforward way to guarantee a correct build
+ <emphasis>regardless of include-file directory paths,
+ relative references between files,
+ or tool support for putting files in different locations</emphasis>,
+ and the &SCons; philosophy is to, by default,
+ guarantee a correct build in all cases.
+
+ </para>
+
+ <para>
+
+ The most direct reason to duplicate source files
+ in variant directories
+ is simply that some tools (mostly older versions)
+ are written to only build their output files
+ in the same directory as the source files.
+ In this case, the choices are either
+ to build the output file in the source directory
+ and move it to the variant directory,
+ or to duplicate the source files in the variant directory.
+
+ </para>
+
+ <para>
+
+ Additionally,
+ relative references between files
+ can cause problems if we don't
+ just duplicate the hierarchy of source files
+ in the variant directory.
+ You can see this at work in
+ use of the C preprocessor <literal>#include</literal>
+ mechanism with double quotes, not angle brackets:
+
+ </para>
+
+ <programlisting>
+ #include "file.h"
+ </programlisting>
+
+ <para>
+
+ The <emphasis>de facto</emphasis> standard behavior
+ for most C compilers in this case
+ is to first look in the same directory
+ as the source file that contains the <literal>#include</literal> line,
+ then to look in the directories in the preprocessor search path.
+ Add to this that the &SCons; implementation of
+ support for code repositories
+ (described below)
+ means not all of the files
+ will be found in the same directory hierarchy,
+ and the simplest way to make sure
+ that the right include file is found
+ is to duplicate the source files into the variant directory,
+ which provides a correct build
+ regardless of the original location(s) of the source files.
+
+ </para>
+
+ <para>
+
+ Although source-file duplication guarantees a correct build
+ even in these end-cases,
+ it <emphasis>can</emphasis> usually be safely disabled.
+ The next section describes
+ how you can disable the duplication of source files
+ in the variant directory.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Telling &SCons; to Not Duplicate Source Files in the Variant Directory Tree</title>
+
+ <para>
+
+ In most cases and with most tool sets,
+ &SCons; can place its target files in a build subdirectory
+ <emphasis>without</emphasis>
+ duplicating the source files
+ and everything will work just fine.
+ You can disable the default &SCons; behavior
+ by specifying <literal>duplicate=0</literal>
+ when you call the &SConscript; function:
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript', variant_dir='build', duplicate=0)
+ </programlisting>
+
+ <para>
+
+ When this flag is specified,
+ &SCons; uses the variant directory
+ like most people expect--that is,
+ the output files are placed in the variant directory
+ while the source files stay in the source directory:
+
+ </para>
+
+ <screen>
+ % <userinput>ls src</userinput>
+ SConscript
+ hello.c
+ % <userinput>scons -Q</userinput>
+ cc -c src/hello.c -o build/hello.o
+ cc -o build/hello build/hello.o
+ % <userinput>ls build</userinput>
+ hello
+ hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &VariantDir; Function</title>
+
+ <para>
+
+ Use the &VariantDir; function to establish that target
+ files should be built in a separate directory
+ from the source files:
+
+ </para>
+
+ <programlisting>
+ VariantDir('build', 'src')
+ env = Environment()
+ env.Program('build/hello.c')
+ </programlisting>
+
+ <para>
+
+ Note that when you're not using
+ an &SConscript; file in the &src; subdirectory,
+ you must actually specify that
+ the program must be built from
+ the <filename>build/hello.c</filename>
+ file that &SCons; will duplicate in the
+ &build; subdirectory.
+
+ </para>
+
+ <para>
+
+ When using the &VariantDir; function directly,
+ &SCons; still duplicates the source files
+ in the variant directory by default:
+
+ </para>
+
+ <screen>
+ % <userinput>ls src</userinput>
+ hello.c
+ % <userinput>scons -Q</userinput>
+ cc -o build/hello.o -c build/hello.c
+ cc -o build/hello build/hello.o
+ % <userinput>ls build</userinput>
+ hello hello.c hello.o
+ </screen>
+
+ <para>
+
+ You can specify the same <literal>duplicate=0</literal> argument
+ that you can specify for an &SConscript; call:
+
+ </para>
+
+ <programlisting>
+ VariantDir('build', 'src', duplicate=0)
+ env = Environment()
+ env.Program('build/hello.c')
+ </programlisting>
+
+ <para>
+
+ In which case &SCons;
+ will disable duplication of the source files:
+
+ </para>
+
+ <screen>
+ % <userinput>ls src</userinput>
+ hello.c
+ % <userinput>scons -Q</userinput>
+ cc -o build/hello.o -c src/hello.c
+ cc -o build/hello build/hello.o
+ % <userinput>ls build</userinput>
+ hello hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Using &VariantDir; With an &SConscript; File</title>
+
+ <para>
+
+ Even when using the &VariantDir; function,
+ it's much more natural to use it with
+ a subsidiary &SConscript; file.
+ For example, if the
+ <filename>src/SConscript</filename>
+ looks like this:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ Then our &SConstruct; file could look like:
+
+ </para>
+
+
+ <programlisting>
+ VariantDir('build', 'src')
+ SConscript('build/SConscript')
+ </programlisting>
+
+ <para>
+
+ Yielding the following output:
+
+ </para>
+
+ <screen>
+ % <userinput>ls src</userinput>
+ SConscript hello.c
+ % <userinput>scons -Q</userinput>
+ cc -o build/hello.o -c build/hello.c
+ cc -o build/hello build/hello.o
+ % <userinput>ls build</userinput>
+ SConscript hello hello.c hello.o
+ </screen>
+
+ <para>
+
+ Notice that this is completely equivalent
+ to the use of &SConscript; that we
+ learned about in the previous section.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Using &Glob; with &VariantDir;</title>
+
+ <para>
+
+ The &Glob; file name pattern matching function
+ works just as usual when using &VariantDir;.
+ For example, if the
+ <filename>src/SConscript</filename>
+ looks like this:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Program('hello', Glob('*.c'))
+ </programlisting>
+
+ <para>
+
+ Then with the same &SConstruct; file as in the previous section,
+ and source files <filename>f1.c</filename>
+ and <filename>f2.c</filename> in src,
+ we would see the following output:
+
+ </para>
+
+ <screen>
+ % <userinput>ls src</userinput>
+ SConscript f1.c f2.c f2.h
+ % <userinput>scons -Q</userinput>
+ cc -o build/f1.o -c build/f1.c
+ cc -o build/f2.o -c build/f2.c
+ cc -o build/hello build/f1.o build/f2.o
+ % <userinput>ls build</userinput>
+ SConscript f1.c f1.o f2.c f2.h f2.o hello
+ </screen>
+
+ <para>
+
+ The &Glob; function returns Nodes in the
+ <filename>build/</filename> tree, as you'd expect.
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Why You'd Want to Call &VariantDir; Instead of &SConscript;</title>
+
+ <para>
+
+ XXX why call VariantDir() instead of SConscript(variant_dir=)
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/sideeffect.in b/doc/user/sideeffect.in
new file mode 100644
index 0000000..58c7306
--- /dev/null
+++ b/doc/user/sideeffect.in
@@ -0,0 +1,216 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <!--
+
+ <para>
+
+ If &SCons; is unaware that a build step produces an extra file,
+ the &SideEffect; method can be used to identify it,
+ so that the file can be used as a dependency in subsequent build steps.
+ However, the primary use for the &SideEffect; method
+ is to prevent two build steps from simultaneously modifying the same file.
+
+ </para>
+
+ TODO: currently doesn't work due to issue #2154:
+ http://scons.tigris.org/issues/show_bug.cgi?id=2154
+
+ <para>
+
+ If more than one build step creates or manipulates the same file,
+ it can cause unpleasant results if both build steps are run at the same time.
+ The shared file is declared as a side-effect of building the primary targets
+ and &SCons; will prevent the two build steps from running in parallel.
+
+ </para>
+
+ <para>
+
+ In this example, the <filename>SConscript</filename> uses
+ &SideEffect; to inform &SCons; about the additional output file.
+
+ </para>
+
+ <scons_example name="SideEffectSimple">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ f2 = env.Command('file2', 'log', Copy('$TARGET', '$SOURCE'))
+ f1 = env.Command('file1', [],
+ 'echo >$TARGET data1; echo >log updated file1'))
+ env.SideEffect('log', env.Command('file1', [],
+ 'echo >$TARGET data1; echo >log updated file1'))
+ </file>
+ </scons_example>
+
+ <para>
+
+ Even when run in parallel mode, &SCons; will run the two steps in order:
+
+ </para>
+
+ <scons_output example="SideEffectSimple">
+ <scons_output_command>scons -Q --jobs=2</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <para>
+
+ Sometimes a program the you need to call
+ to build a target file
+ will also update another file,
+ such as a log file describing what the program
+ does while building the target.
+ For example, we the folowing configuration
+ would have &SCons; invoke a hypothetical
+ script named <application>build</application>
+ (in the local directory)
+ with command-line arguments that write
+ log information to a common
+ <filename>logfile.txt</filename> file:
+
+ </para>
+
+ <screen>
+ env = Environment()
+ env.Command('file1.out', 'file.in',
+ './build --log logfile.txt $SOURCE $TARGET')
+ env.Command('file2.out', 'file.in',
+ './build --log logfile.txt $SOURCE $TARGET')
+ <screen>
+
+ <para>
+
+ This can cause problems when running
+ the build in parallel if
+ &SCons; decides to update both targets
+ by running both program invocations at the same time.
+ The multiple program invocations
+ may interfere with each other
+ writing to the common log file,
+ leading at best to intermixed output in the log file,
+ and at worst to an actual failed build
+ (on a system like Windows, for example,
+ where only one process at a time can open the log file for writing).
+
+ </para>
+
+ <para>
+
+ We can make sure that &SCons; does not
+ run these <application>build</application>
+ commands at the same time
+ by using the &SideEffect; function
+ to specify that updating
+ the <filename>logfile.txt</filename> file
+ is a side effect of building the specified
+ <filename>file1</filename>
+ and
+ <filename>file2</filename>
+ target files:
+
+ </para>
+
+ <scons_example name="SideEffectShared">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ f1 = env.Command('file1.out', 'file1.in',
+ './build --log logfile.txt $SOURCE $TARGET')
+ f2 = env.Command('file2.out', 'file2.in',
+ './build --log logfile.txt $SOURCE $TARGET')
+ env.SideEffect('logfile.txt', f1 + f2)
+ </file>
+ <file name="file1.in">file1.in</file>
+ <file name="file2.in">file2.in</file>
+ <file name="build" chmod="0755">
+ cat
+ </file>
+ </scons_example>
+
+ <para>
+
+ </para>
+
+ <para>
+
+ This makes sure the the two
+ <application>./build</application> steps are run sequentially,
+ even withthe <filename>--jobs=2</filename> in the command line:
+
+ </para>
+
+ <scons_output example="SideEffectShared">
+ <scons_output_command>scons -Q --jobs=2</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The &SideEffect; function can be called multiple
+ times for the same side-effect file.
+ Additionally, the name used as a &SideEffect; does not
+ even need to actually exist as a file on disk.
+ &SCons; will still make sure
+ that the relevant targets
+ will be executed sequentially, not in parallel:
+
+ </para>
+
+ <scons_example name="SideEffectParallel">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ f1 = env.Command('file1.out', [], 'echo >$TARGET data1')
+ env.SideEffect('not_really_updated', f1)
+ f2 = env.Command('file2.out', [], 'echo >$TARGET data2')
+ env.SideEffect('not_really_updated', f2)
+ </file>
+ </scons_example>
+
+ <scons_output example="SideEffectParallel">
+ <scons_output_command>scons -Q --jobs=2</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that it might be tempting to
+ use &SideEffect; for additional target files
+ that a command produces.
+ For example, versions the Microsoft Visual C/C++ compiler
+ produce a <filename>foo.ilk</filename>
+ alongside compiling <filename>foo.obj</filename> file.
+ Specifying <filename>foo.ilk</filename> as a
+ side-effect of <filename>foo.obj</filename>
+ is <emphasis>not</emphasis> a recommended use of &SideEffect;,
+ because &SCons; handle side-effect files
+ slightly differently in its analysis of the dependency graph.
+ When a command produces multiple output files,
+ they should be specified as multiple targets of
+ the call to the relevant builder function,
+ and the &SideEffect; function itself should really only be used
+ when it's important to ensure that commands are not executed in parallel,
+ such as when a "peripheral" file (such as a log file)
+ may actually updated by more than one command invocation.
+
+ </para>
diff --git a/doc/user/sideeffect.xml b/doc/user/sideeffect.xml
new file mode 100644
index 0000000..df62eca
--- /dev/null
+++ b/doc/user/sideeffect.xml
@@ -0,0 +1,211 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <!--
+
+ <para>
+
+ If &SCons; is unaware that a build step produces an extra file,
+ the &SideEffect; method can be used to identify it,
+ so that the file can be used as a dependency in subsequent build steps.
+ However, the primary use for the &SideEffect; method
+ is to prevent two build steps from simultaneously modifying the same file.
+
+ </para>
+
+ TODO: currently doesn't work due to issue #2154:
+ http://scons.tigris.org/issues/show_bug.cgi?id=2154
+
+ <para>
+
+ If more than one build step creates or manipulates the same file,
+ it can cause unpleasant results if both build steps are run at the same time.
+ The shared file is declared as a side-effect of building the primary targets
+ and &SCons; will prevent the two build steps from running in parallel.
+
+ </para>
+
+ <para>
+
+ In this example, the <filename>SConscript</filename> uses
+ &SideEffect; to inform &SCons; about the additional output file.
+
+ </para>
+
+ <scons_example name="SideEffectSimple">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ f2 = env.Command('file2', 'log', Copy('$TARGET', '$SOURCE'))
+ f1 = env.Command('file1', [],
+ 'echo >$TARGET data1; echo >log updated file1'))
+ env.SideEffect('log', env.Command('file1', [],
+ 'echo >$TARGET data1; echo >log updated file1'))
+ </file>
+ </scons_example>
+
+ <para>
+
+ Even when run in parallel mode, &SCons; will run the two steps in order:
+
+ </para>
+
+ <scons_output example="SideEffectSimple">
+ <scons_output_command>scons -Q --jobs=2</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <para>
+
+ Sometimes a program the you need to call
+ to build a target file
+ will also update another file,
+ such as a log file describing what the program
+ does while building the target.
+ For example, we the folowing configuration
+ would have &SCons; invoke a hypothetical
+ script named <application>build</application>
+ (in the local directory)
+ with command-line arguments that write
+ log information to a common
+ <filename>logfile.txt</filename> file:
+
+ </para>
+
+ <screen>
+ env = Environment()
+ env.Command('file1.out', 'file.in',
+ './build --log logfile.txt $SOURCE $TARGET')
+ env.Command('file2.out', 'file.in',
+ './build --log logfile.txt $SOURCE $TARGET')
+ <screen>
+
+ <para>
+
+ This can cause problems when running
+ the build in parallel if
+ &SCons; decides to update both targets
+ by running both program invocations at the same time.
+ The multiple program invocations
+ may interfere with each other
+ writing to the common log file,
+ leading at best to intermixed output in the log file,
+ and at worst to an actual failed build
+ (on a system like Windows, for example,
+ where only one process at a time can open the log file for writing).
+
+ </para>
+
+ <para>
+
+ We can make sure that &SCons; does not
+ run these <application>build</application>
+ commands at the same time
+ by using the &SideEffect; function
+ to specify that updating
+ the <filename>logfile.txt</filename> file
+ is a side effect of building the specified
+ <filename>file1</filename>
+ and
+ <filename>file2</filename>
+ target files:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ f1 = env.Command('file1.out', 'file1.in',
+ './build --log logfile.txt $SOURCE $TARGET')
+ f2 = env.Command('file2.out', 'file2.in',
+ './build --log logfile.txt $SOURCE $TARGET')
+ env.SideEffect('logfile.txt', f1 + f2)
+ </programlisting>
+
+ <para>
+
+ </para>
+
+ <para>
+
+ This makes sure the the two
+ <application>./build</application> steps are run sequentially,
+ even withthe <filename>--jobs=2</filename> in the command line:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --jobs=2</userinput>
+ ./build --log logfile.txt file1.in file1.out
+ ./build --log logfile.txt file2.in file2.out
+ </screen>
+
+ <para>
+
+ The &SideEffect; function can be called multiple
+ times for the same side-effect file.
+ Additionally, the name used as a &SideEffect; does not
+ even need to actually exist as a file on disk.
+ &SCons; will still make sure
+ that the relevant targets
+ will be executed sequentially, not in parallel:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ f1 = env.Command('file1.out', [], 'echo &gt;$TARGET data1')
+ env.SideEffect('not_really_updated', f1)
+ f2 = env.Command('file2.out', [], 'echo &gt;$TARGET data2')
+ env.SideEffect('not_really_updated', f2)
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q --jobs=2</userinput>
+ echo &gt; file1.out data1
+ echo &gt; file2.out data2
+ </screen>
+
+ <para>
+
+ Note that it might be tempting to
+ use &SideEffect; for additional target files
+ that a command produces.
+ For example, versions the Microsoft Visual C/C++ compiler
+ produce a <filename>foo.ilk</filename>
+ alongside compiling <filename>foo.obj</filename> file.
+ Specifying <filename>foo.ilk</filename> as a
+ side-effect of <filename>foo.obj</filename>
+ is <emphasis>not</emphasis> a recommended use of &SideEffect;,
+ because &SCons; handle side-effect files
+ slightly differently in its analysis of the dependency graph.
+ When a command produces multiple output files,
+ they should be specified as multiple targets of
+ the call to the relevant builder function,
+ and the &SideEffect; function itself should really only be used
+ when it's important to ensure that commands are not executed in parallel,
+ such as when a "peripheral" file (such as a log file)
+ may actually updated by more than one command invocation.
+
+ </para>
diff --git a/doc/user/simple.in b/doc/user/simple.in
new file mode 100644
index 0000000..4d42934
--- /dev/null
+++ b/doc/user/simple.in
@@ -0,0 +1,517 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ In this chapter,
+ you will see several examples of
+ very simple build configurations using &SCons;,
+ which will demonstrate how easy
+ it is to use &SCons; to
+ build programs from several different programming languages
+ on different types of systems.
+
+ </para>
+
+ <section>
+ <title>Building Simple C / C++ Programs</title>
+
+ <para>
+
+ Here's the famous "Hello, World!" program in C:
+
+ </para>
+
+ <programlisting>
+ int
+ main()
+ {
+ printf("Hello, world!\n");
+ }
+ </programlisting>
+
+ <para>
+
+ And here's how to build it using &SCons;.
+ Enter the following into a file named &SConstruct;:
+
+ </para>
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ Program('hello.c')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ This minimal configuration file gives
+ &SCons; two pieces of information:
+ what you want to build
+ (an executable program),
+ and the input file from
+ which you want it built
+ (the <filename>hello.c</filename> file).
+ &b-link-Program; is a <firstterm>builder_method</firstterm>,
+ a Python call that tells &SCons; that you want to build an
+ executable program.
+
+ </para>
+
+ <para>
+
+ That's it. Now run the &scons; command to build the program.
+ On a POSIX-compliant system like Linux or UNIX,
+ you'll see something like:
+
+ </para>
+
+ <scons_output example="ex1" os="posix">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ On a Windows system with the Microsoft Visual C++ compiler,
+ you'll see something like:
+
+ </para>
+
+ <scons_output example="ex1" os="win32">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ First, notice that you only need
+ to specify the name of the source file,
+ and that &SCons; correctly deduces the names of
+ the object and executable files to be built
+ from the base of the source file name.
+
+ </para>
+
+ <para>
+
+ Second, notice that the same input &SConstruct; file,
+ without any changes,
+ generates the correct output file names on both systems:
+ <filename>hello.o</filename> and <filename>hello</filename>
+ on POSIX systems,
+ <filename>hello.obj</filename> and <filename>hello.exe</filename>
+ on Windows systems.
+ This is a simple example of how &SCons;
+ makes it extremely easy to
+ write portable software builds.
+
+ </para>
+
+ <para>
+
+ (Note that we won't provide duplicate side-by-side
+ POSIX and Windows output for all of the examples in this guide;
+ just keep in mind that, unless otherwise specified,
+ any of the examples should work equally well on both types of systems.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building Object Files</title>
+
+ <para>
+
+ The &b-link-Program; builder method is only one of
+ many builder methods that &SCons; provides
+ to build different types of files.
+ Another is the &b-link-Object; builder method,
+ which tells &SCons; to build an object file
+ from the specified source file:
+
+ </para>
+
+ <scons_example name="Object">
+ <file name="SConstruct" printme="1">
+ Object('hello.c')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Now when you run the &scons; command to build the program,
+ it will build just the &hello_o; object file on a POSIX system:
+
+ </para>
+
+ <scons_output example="Object" os="posix">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And just the &hello_obj; object file
+ on a Windows system (with the Microsoft Visual C++ compiler):
+
+ </para>
+
+ <scons_output example="Object" os="win32">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Simple Java Builds</title>
+
+ <para>
+
+ &SCons; also makes building with Java extremely easy.
+ Unlike the &b-link-Program; and &b-link-Object; builder methods,
+ however, the &b-link-Java; builder method
+ requires that you specify
+ the name of a destination directory in which
+ you want the class files placed,
+ followed by the source directory
+ in which the <filename>.java</filename> files live:
+
+ </para>
+
+ <scons_example name="java">
+ <file name="SConstruct" printme="1">
+ Java('classes', 'src')
+ </file>
+ <file name="src/hello.java">
+ public class Example1
+ {
+ public static void main(String[] args)
+ {
+ System.out.println("Hello Java world!\n");
+ }
+ }
+ </file>
+ </scons_example>
+
+ <para>
+
+ If the <filename>src</filename> directory
+ contains a single <filename>hello.java</filename> file,
+ then the output from running the &scons; command
+ would look something like this
+ (on a POSIX system):
+
+ </para>
+
+ <scons_output example="java" os="posix">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ We'll cover Java builds in more detail,
+ including building Java archive (<filename>.jar</filename>)
+ and other types of file,
+ in <xref linkend="chap-java"></xref>.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Cleaning Up After a Build</title>
+
+ <para>
+
+ When using &SCons;, it is unnecessary to add special
+ commands or target names to clean up after a build.
+ Instead, you simply use the
+ <literal>-c</literal> or <literal>--clean</literal>
+ option when you invoke &SCons;,
+ and &SCons; removes the appropriate built files.
+ So if we build our example above
+ and then invoke <literal>scons -c</literal>
+ afterwards, the output on POSIX looks like:
+
+ </para>
+
+ <scons_example name="clean">
+ <file name="SConstruct">
+ Program('hello.c')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <scons_output example="clean" os="posix">
+ <scons_output_command>scons</scons_output_command>
+ <scons_output_command>scons -c</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And the output on Windows looks like:
+
+ </para>
+
+ <scons_output example="clean" os="win32">
+ <scons_output_command>scons</scons_output_command>
+ <scons_output_command>scons -c</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice that &SCons; changes its output to tell you that it
+ is <literal>Cleaning targets ...</literal> and
+ <literal>done cleaning targets.</literal>
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &SConstruct; File</title>
+
+ <para>
+
+ If you're used to build systems like &Make;
+ you've already figured out that the &SConstruct; file
+ is the &SCons; equivalent of a &Makefile;.
+ That is, the &SConstruct; file is the input file
+ that &SCons; reads to control the build.
+
+ </para>
+
+ <section>
+ <title>&SConstruct; Files Are Python Scripts</title>
+
+ <para>
+
+ There is, however, an important difference between
+ an &SConstruct; file and a &Makefile;:
+ the &SConstruct; file is actually a Python script.
+ If you're not already familiar with Python, don't worry.
+ This User's Guide will introduce you step-by-step
+ to the relatively small amount of Python you'll
+ need to know to be able to use &SCons; effectively.
+ And Python is very easy to learn.
+
+ </para>
+
+ <para>
+
+ One aspect of using Python as the
+ scripting language is that you can put comments
+ in your &SConstruct; file using Python's commenting convention;
+ that is, everything between a '#' and the end of the line
+ will be ignored:
+
+ </para>
+
+ <programlisting>
+ # Arrange to build the "hello" program.
+ Program('hello.c') # "hello.c" is the source file.
+ </programlisting>
+
+ <para>
+
+ You'll see throughout the remainder of this Guide
+ that being able to use the power of a
+ real scripting language
+ can greatly simplify the solutions
+ to complex requirements of real-world builds.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>&SCons; Functions Are Order-Independent</title>
+
+ <para>
+
+ One important way in which the &SConstruct;
+ file is not exactly like a normal Python script,
+ and is more like a &Makefile,
+ is that the order in which
+ the &SCons; functions are called in
+ the &SConstruct; file
+ does <emphasis>not</emphasis>
+ affect the order in which &SCons;
+ actually builds the programs and object files
+ you want it to build.<footnote>
+ <para>In programming parlance,
+ the &SConstruct; file is
+ <emphasis>declarative</emphasis>,
+ meaning you tell &SCons; what you want done
+ and let it figure out the order in which to do it,
+ rather than strictly <emphasis>imperative</emphasis>,
+ where you specify explicitly the order in
+ which to do things.
+ </para>
+ </footnote>
+ In other words, when you call the &b-link-Program; builder
+ (or any other builder method),
+ you're not telling &SCons; to build
+ the program at the instant the builder method is called.
+ Instead, you're telling &SCons; to build the program
+ that you want, for example,
+ a program built from a file named &hello_c;,
+ and it's up to &SCons; to build that program
+ (and any other files) whenever it's necessary.
+ (We'll learn more about how
+ &SCons; decides when building or rebuilding a file
+ is necessary in <xref linkend="chap-depends"></xref>, below.)
+
+ </para>
+
+ <para>
+
+ &SCons; reflects this distinction between
+ <emphasis>calling a builder method like</emphasis> &b-Program;
+ and <emphasis>actually building the program</emphasis>
+ by printing the status messages that indicate
+ when it's "just reading" the &SConstruct; file,
+ and when it's actually building the target files.
+ This is to make it clear when &SCons; is
+ executing the Python statements that make up the &SConstruct; file,
+ and when &SCons; is actually executing the
+ commands or other actions to
+ build the necessary files.
+
+ </para>
+
+ <para>
+
+ Let's clarify this with an example.
+ Python has a <literal>print</literal> statement that
+ prints a string of characters to the screen.
+ If we put <literal>print</literal> statements around
+ our calls to the &b-Program; builder method:
+
+ </para>
+
+ <scons_example name="declarative">
+ <file name="SConstruct" printme="1">
+ print "Calling Program('hello.c')"
+ Program('hello.c')
+ print "Calling Program('goodbye.c')"
+ Program('goodbye.c')
+ print "Finished calling Program()"
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ <file name="goodbye.c">
+ int main() { printf("Goodbye, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then when we execute &SCons;,
+ we see the output from the <literal>print</literal>
+ statements in between the messages about
+ reading the &SConscript; files,
+ indicating that that is when the
+ Python statements are being executed:
+
+ </para>
+
+ <scons_output example="declarative" os="posix">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice also that &SCons; built the &goodbye; program first,
+ even though the "reading &SConscript" output
+ shows that we called <literal>Program('hello.c')</literal>
+ first in the &SConstruct; file.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Making the &SCons; Output Less Verbose</title>
+
+ <para>
+
+ You've already seen how &SCons; prints
+ some messages about what it's doing,
+ surrounding the actual commands used to build the software:
+
+ </para>
+
+ <scons_output example="ex1" os="win32">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ These messages emphasize the
+ order in which &SCons; does its work:
+ all of the configuration files
+ (generically referred to as &SConscript; files)
+ are read and executed first,
+ and only then are the target files built.
+ Among other benefits, these messages help to distinguish between
+ errors that occur while the configuration files are read,
+ and errors that occur while targets are being built.
+
+ </para>
+
+ <para>
+
+ One drawback, of course, is that these messages clutter the output.
+ Fortunately, they're easily disabled by using
+ the &Q; option when invoking &SCons;:
+
+ </para>
+
+ <scons_output example="ex1" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Because we want this User's Guide to focus
+ on what &SCons; is actually doing,
+ we're going to use the &Q; option
+ to remove these messages from the
+ output of all the remaining examples in this Guide.
+
+ </para>
+
+ </section>
diff --git a/doc/user/simple.xml b/doc/user/simple.xml
new file mode 100644
index 0000000..598d44b
--- /dev/null
+++ b/doc/user/simple.xml
@@ -0,0 +1,587 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ In this chapter,
+ you will see several examples of
+ very simple build configurations using &SCons;,
+ which will demonstrate how easy
+ it is to use &SCons; to
+ build programs from several different programming languages
+ on different types of systems.
+
+ </para>
+
+ <section>
+ <title>Building Simple C / C++ Programs</title>
+
+ <para>
+
+ Here's the famous "Hello, World!" program in C:
+
+ </para>
+
+ <programlisting>
+ int
+ main()
+ {
+ printf("Hello, world!\n");
+ }
+ </programlisting>
+
+ <para>
+
+ And here's how to build it using &SCons;.
+ Enter the following into a file named &SConstruct;:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ This minimal configuration file gives
+ &SCons; two pieces of information:
+ what you want to build
+ (an executable program),
+ and the input file from
+ which you want it built
+ (the <filename>hello.c</filename> file).
+ &b-link-Program; is a <firstterm>builder_method</firstterm>,
+ a Python call that tells &SCons; that you want to build an
+ executable program.
+
+ </para>
+
+ <para>
+
+ That's it. Now run the &scons; command to build the program.
+ On a POSIX-compliant system like Linux or UNIX,
+ you'll see something like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ On a Windows system with the Microsoft Visual C++ compiler,
+ you'll see something like:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons</userinput>
+ scons: Reading SConscript files ...
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cl /Fohello.obj /c hello.c /nologo
+ link /nologo /OUT:hello.exe hello.obj
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ First, notice that you only need
+ to specify the name of the source file,
+ and that &SCons; correctly deduces the names of
+ the object and executable files to be built
+ from the base of the source file name.
+
+ </para>
+
+ <para>
+
+ Second, notice that the same input &SConstruct; file,
+ without any changes,
+ generates the correct output file names on both systems:
+ <filename>hello.o</filename> and <filename>hello</filename>
+ on POSIX systems,
+ <filename>hello.obj</filename> and <filename>hello.exe</filename>
+ on Windows systems.
+ This is a simple example of how &SCons;
+ makes it extremely easy to
+ write portable software builds.
+
+ </para>
+
+ <para>
+
+ (Note that we won't provide duplicate side-by-side
+ POSIX and Windows output for all of the examples in this guide;
+ just keep in mind that, unless otherwise specified,
+ any of the examples should work equally well on both types of systems.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Building Object Files</title>
+
+ <para>
+
+ The &b-link-Program; builder method is only one of
+ many builder methods that &SCons; provides
+ to build different types of files.
+ Another is the &b-link-Object; builder method,
+ which tells &SCons; to build an object file
+ from the specified source file:
+
+ </para>
+
+ <programlisting>
+ Object('hello.c')
+ </programlisting>
+
+ <para>
+
+ Now when you run the &scons; command to build the program,
+ it will build just the &hello_o; object file on a POSIX system:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -o hello.o -c hello.c
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ And just the &hello_obj; object file
+ on a Windows system (with the Microsoft Visual C++ compiler):
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons</userinput>
+ scons: Reading SConscript files ...
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cl /Fohello.obj /c hello.c /nologo
+ scons: done building targets.
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Simple Java Builds</title>
+
+ <para>
+
+ &SCons; also makes building with Java extremely easy.
+ Unlike the &b-link-Program; and &b-link-Object; builder methods,
+ however, the &b-link-Java; builder method
+ requires that you specify
+ the name of a destination directory in which
+ you want the class files placed,
+ followed by the source directory
+ in which the <filename>.java</filename> files live:
+
+ </para>
+
+ <programlisting>
+ Java('classes', 'src')
+ </programlisting>
+
+ <para>
+
+ If the <filename>src</filename> directory
+ contains a single <filename>hello.java</filename> file,
+ then the output from running the &scons; command
+ would look something like this
+ (on a POSIX system):
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ javac -d classes -sourcepath src src/hello.java
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ We'll cover Java builds in more detail,
+ including building Java archive (<filename>.jar</filename>)
+ and other types of file,
+ in <xref linkend="chap-java"></xref>.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Cleaning Up After a Build</title>
+
+ <para>
+
+ When using &SCons;, it is unnecessary to add special
+ commands or target names to clean up after a build.
+ Instead, you simply use the
+ <literal>-c</literal> or <literal>--clean</literal>
+ option when you invoke &SCons;,
+ and &SCons; removes the appropriate built files.
+ So if we build our example above
+ and then invoke <literal>scons -c</literal>
+ afterwards, the output on POSIX looks like:
+
+ </para>
+
+
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ scons: done building targets.
+ % <userinput>scons -c</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Cleaning targets ...
+ Removed hello.o
+ Removed hello
+ scons: done cleaning targets.
+ </screen>
+
+ <para>
+
+ And the output on Windows looks like:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons</userinput>
+ scons: Reading SConscript files ...
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cl /Fohello.obj /c hello.c /nologo
+ link /nologo /OUT:hello.exe hello.obj
+ scons: done building targets.
+ C:\><userinput>scons -c</userinput>
+ scons: Reading SConscript files ...
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ scons: done reading SConscript files.
+ scons: Cleaning targets ...
+ Removed hello.obj
+ Removed hello.exe
+ scons: done cleaning targets.
+ </screen>
+
+ <para>
+
+ Notice that &SCons; changes its output to tell you that it
+ is <literal>Cleaning targets ...</literal> and
+ <literal>done cleaning targets.</literal>
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &SConstruct; File</title>
+
+ <para>
+
+ If you're used to build systems like &Make;
+ you've already figured out that the &SConstruct; file
+ is the &SCons; equivalent of a &Makefile;.
+ That is, the &SConstruct; file is the input file
+ that &SCons; reads to control the build.
+
+ </para>
+
+ <section>
+ <title>&SConstruct; Files Are Python Scripts</title>
+
+ <para>
+
+ There is, however, an important difference between
+ an &SConstruct; file and a &Makefile;:
+ the &SConstruct; file is actually a Python script.
+ If you're not already familiar with Python, don't worry.
+ This User's Guide will introduce you step-by-step
+ to the relatively small amount of Python you'll
+ need to know to be able to use &SCons; effectively.
+ And Python is very easy to learn.
+
+ </para>
+
+ <para>
+
+ One aspect of using Python as the
+ scripting language is that you can put comments
+ in your &SConstruct; file using Python's commenting convention;
+ that is, everything between a '#' and the end of the line
+ will be ignored:
+
+ </para>
+
+ <programlisting>
+ # Arrange to build the "hello" program.
+ Program('hello.c') # "hello.c" is the source file.
+ </programlisting>
+
+ <para>
+
+ You'll see throughout the remainder of this Guide
+ that being able to use the power of a
+ real scripting language
+ can greatly simplify the solutions
+ to complex requirements of real-world builds.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>&SCons; Functions Are Order-Independent</title>
+
+ <para>
+
+ One important way in which the &SConstruct;
+ file is not exactly like a normal Python script,
+ and is more like a &Makefile;,
+ is that the order in which
+ the &SCons; functions are called in
+ the &SConstruct; file
+ does <emphasis>not</emphasis>
+ affect the order in which &SCons;
+ actually builds the programs and object files
+ you want it to build.<footnote>
+ <para>In programming parlance,
+ the &SConstruct; file is
+ <emphasis>declarative</emphasis>,
+ meaning you tell &SCons; what you want done
+ and let it figure out the order in which to do it,
+ rather than strictly <emphasis>imperative</emphasis>,
+ where you specify explicitly the order in
+ which to do things.
+ </para>
+ </footnote>
+ In other words, when you call the &b-link-Program; builder
+ (or any other builder method),
+ you're not telling &SCons; to build
+ the program at the instant the builder method is called.
+ Instead, you're telling &SCons; to build the program
+ that you want, for example,
+ a program built from a file named &hello_c;,
+ and it's up to &SCons; to build that program
+ (and any other files) whenever it's necessary.
+ (We'll learn more about how
+ &SCons; decides when building or rebuilding a file
+ is necessary in <xref linkend="chap-depends"></xref>, below.)
+
+ </para>
+
+ <para>
+
+ &SCons; reflects this distinction between
+ <emphasis>calling a builder method like</emphasis> &b-Program;
+ and <emphasis>actually building the program</emphasis>
+ by printing the status messages that indicate
+ when it's "just reading" the &SConstruct; file,
+ and when it's actually building the target files.
+ This is to make it clear when &SCons; is
+ executing the Python statements that make up the &SConstruct; file,
+ and when &SCons; is actually executing the
+ commands or other actions to
+ build the necessary files.
+
+ </para>
+
+ <para>
+
+ Let's clarify this with an example.
+ Python has a <literal>print</literal> statement that
+ prints a string of characters to the screen.
+ If we put <literal>print</literal> statements around
+ our calls to the &b-Program; builder method:
+
+ </para>
+
+ <programlisting>
+ print "Calling Program('hello.c')"
+ Program('hello.c')
+ print "Calling Program('goodbye.c')"
+ Program('goodbye.c')
+ print "Finished calling Program()"
+ </programlisting>
+
+ <para>
+
+ Then when we execute &SCons;,
+ we see the output from the <literal>print</literal>
+ statements in between the messages about
+ reading the &SConscript; files,
+ indicating that that is when the
+ Python statements are being executed:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ Calling Program('hello.c')
+ Calling Program('goodbye.c')
+ Finished calling Program()
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -o goodbye.o -c goodbye.c
+ cc -o goodbye goodbye.o
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ Notice also that &SCons; built the &goodbye; program first,
+ even though the "reading &SConscript;" output
+ shows that we called <literal>Program('hello.c')</literal>
+ first in the &SConstruct; file.
+
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Making the &SCons; Output Less Verbose</title>
+
+ <para>
+
+ You've already seen how &SCons; prints
+ some messages about what it's doing,
+ surrounding the actual commands used to build the software:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons</userinput>
+ scons: Reading SConscript files ...
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cl /Fohello.obj /c hello.c /nologo
+ link /nologo /OUT:hello.exe hello.obj
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ These messages emphasize the
+ order in which &SCons; does its work:
+ all of the configuration files
+ (generically referred to as &SConscript; files)
+ are read and executed first,
+ and only then are the target files built.
+ Among other benefits, these messages help to distinguish between
+ errors that occur while the configuration files are read,
+ and errors that occur while targets are being built.
+
+ </para>
+
+ <para>
+
+ One drawback, of course, is that these messages clutter the output.
+ Fortunately, they're easily disabled by using
+ the &Q; option when invoking &SCons;:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ cl /Fohello.obj /c hello.c /nologo
+ link /nologo /OUT:hello.exe hello.obj
+ </screen>
+
+ <para>
+
+ Because we want this User's Guide to focus
+ on what &SCons; is actually doing,
+ we're going to use the &Q; option
+ to remove these messages from the
+ output of all the remaining examples in this Guide.
+
+ </para>
+
+ </section>
diff --git a/doc/user/sourcecode.in b/doc/user/sourcecode.in
new file mode 100644
index 0000000..5cbbe1a
--- /dev/null
+++ b/doc/user/sourcecode.in
@@ -0,0 +1,162 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+-->
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <section>
+ <title>Fetching Source Code From BitKeeper</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <scons_example name="ex_bitkeeper">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.SourceCode('.', env.BitKeeper())
+ env.Program('hello.c')
+ </file>
+ <file name="s.hello.c">
+ s.hello.c
+ </file>
+ </scons_example>
+
+ <scons_output example="ex_bitkeeper">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From CVS</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <scons_example name="ex_cvs">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.SourceCode('.', env.CVS('/usr/local/CVS'))
+ env.Program('hello.c')
+ </file>
+ </scons_example>
+
+ <scons_output example="ex_cvs">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From RCS</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <scons_example name="ex_rcs">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.SourceCode('.', env.RCS())
+ env.Program('hello.c')
+ </file>
+ <file name="hello.c,v">
+ hello.c,v
+ </file>
+ </scons_example>
+
+ <scons_output example="ex_rcs">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From SCCS</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <scons_example name="ex_sccs">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.SourceCode('.', env.SCCS())
+ env.Program('hello.c')
+ </file>
+ <file name="s.hello.c">
+ s.hello.c
+ </file>
+ </scons_example>
+
+ <scons_output example="ex_sccs">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Fetching Source Code From Subversion</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <scons_example name="ex_subversion">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.SourceCode('.', env.Subversion('XXX'))
+ env.Program('hello.c')
+ </file>
+ </scons_example>
+
+ <scons_output example="ex_subversion">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ -->
diff --git a/doc/user/sourcecode.xml b/doc/user/sourcecode.xml
new file mode 100644
index 0000000..aebcd20
--- /dev/null
+++ b/doc/user/sourcecode.xml
@@ -0,0 +1,157 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+-->
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <section>
+ <title>Fetching Source Code From BitKeeper</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.BitKeeper())
+ env.Program('hello.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ bk get hello.c
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From CVS</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.CVS('/usr/local/CVS'))
+ env.Program('hello.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cvs -d /usr/local/CVS co hello.c
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From RCS</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.RCS())
+ env.Program('hello.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ co hello.c
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From SCCS</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.SCCS())
+ env.Program('hello.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ sccs get hello.c
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Fetching Source Code From Subversion</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ <scons_example name="ex_subversion">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.SourceCode('.', env.Subversion('XXX'))
+ env.Program('hello.c')
+ </file>
+ </scons_example>
+
+ <scons_output example="ex_subversion">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ -->
diff --git a/doc/user/tasks.in b/doc/user/tasks.in
new file mode 100644
index 0000000..14775c8
--- /dev/null
+++ b/doc/user/tasks.in
@@ -0,0 +1,108 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<para>
+There is a common set of simple tasks that many build configurations rely
+on as they become more complex. Most build tools have special
+purpose constructs for performing these tasks, but since &SConscript;
+files are &Python; scripts, you can use more flexible built-in &Python;
+services to perform these tasks. This appendix lists a number of these
+tasks and how to implement them in &Python;.
+</para>
+
+<example>
+<title>Wildcard globbing to create a list of filenames</title>
+<programlisting>
+files = Glob(wildcard)
+</programlisting>
+</example>
+
+<example>
+<title>Filename extension substitution</title>
+<programlisting>
+import os.path
+filename = os.path.splitext(filename)[0]+extension
+</programlisting>
+</example>
+
+<example>
+<title>Appending a path prefix to a list of filenames</title>
+<programlisting>
+import os.path
+filenames = [os.path.join(prefix, x) for x in filenames]
+</programlisting>
+
+<simpara>or in Python 1.5.2:</simpara>
+
+<programlisting>
+import os.path
+new_filenames = []
+for x in filenames:
+ new_filenames.append(os.path.join(prefix, x))
+</programlisting>
+</example>
+
+<example>
+<title>Substituting a path prefix with another one</title>
+<programlisting>
+if filename.find(old_prefix) == 0:
+ filename = filename.replace(old_prefix, new_prefix)
+</programlisting>
+
+<simpara>or in Python 1.5.2:</simpara>
+
+<programlisting>
+import string
+if string.find(filename, old_prefix) == 0:
+ filename = string.replace(filename, old_prefix, new_prefix)
+</programlisting>
+</example>
+
+<example>
+<title>Filtering a filename list to exclude/retain only a specific set
+of extensions</title>
+<programlisting>
+import os.path
+filenames = [x for x in filenames if os.path.splitext(x)[1] in extensions]
+</programlisting>
+
+<simpara>or in Python 1.5.2:</simpara>
+
+<programlisting>
+import os.path
+new_filenames = []
+for x in filenames:
+ if os.path.splitext(x)[1] in extensions:
+ new_filenames.append(x)
+</programlisting>
+</example>
+
+<example>
+<title>The "backtick function": run a shell command and capture the
+output</title>
+<programlisting>import os
+output = os.popen(command).read()
+</programlisting>
+</example>
diff --git a/doc/user/tasks.xml b/doc/user/tasks.xml
new file mode 100644
index 0000000..14775c8
--- /dev/null
+++ b/doc/user/tasks.xml
@@ -0,0 +1,108 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<para>
+There is a common set of simple tasks that many build configurations rely
+on as they become more complex. Most build tools have special
+purpose constructs for performing these tasks, but since &SConscript;
+files are &Python; scripts, you can use more flexible built-in &Python;
+services to perform these tasks. This appendix lists a number of these
+tasks and how to implement them in &Python;.
+</para>
+
+<example>
+<title>Wildcard globbing to create a list of filenames</title>
+<programlisting>
+files = Glob(wildcard)
+</programlisting>
+</example>
+
+<example>
+<title>Filename extension substitution</title>
+<programlisting>
+import os.path
+filename = os.path.splitext(filename)[0]+extension
+</programlisting>
+</example>
+
+<example>
+<title>Appending a path prefix to a list of filenames</title>
+<programlisting>
+import os.path
+filenames = [os.path.join(prefix, x) for x in filenames]
+</programlisting>
+
+<simpara>or in Python 1.5.2:</simpara>
+
+<programlisting>
+import os.path
+new_filenames = []
+for x in filenames:
+ new_filenames.append(os.path.join(prefix, x))
+</programlisting>
+</example>
+
+<example>
+<title>Substituting a path prefix with another one</title>
+<programlisting>
+if filename.find(old_prefix) == 0:
+ filename = filename.replace(old_prefix, new_prefix)
+</programlisting>
+
+<simpara>or in Python 1.5.2:</simpara>
+
+<programlisting>
+import string
+if string.find(filename, old_prefix) == 0:
+ filename = string.replace(filename, old_prefix, new_prefix)
+</programlisting>
+</example>
+
+<example>
+<title>Filtering a filename list to exclude/retain only a specific set
+of extensions</title>
+<programlisting>
+import os.path
+filenames = [x for x in filenames if os.path.splitext(x)[1] in extensions]
+</programlisting>
+
+<simpara>or in Python 1.5.2:</simpara>
+
+<programlisting>
+import os.path
+new_filenames = []
+for x in filenames:
+ if os.path.splitext(x)[1] in extensions:
+ new_filenames.append(x)
+</programlisting>
+</example>
+
+<example>
+<title>The "backtick function": run a shell command and capture the
+output</title>
+<programlisting>import os
+output = os.popen(command).read()
+</programlisting>
+</example>
diff --git a/doc/user/tools.in b/doc/user/tools.in
new file mode 100644
index 0000000..cc0628e
--- /dev/null
+++ b/doc/user/tools.in
@@ -0,0 +1,38 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<para>
+
+This appendix contains descriptions of all of the
+Tools modules that are
+available "out of the box" in this version of SCons.
+
+</para>
+
+<variablelist>
+
+&tools-gen;
+
+</variablelist>
diff --git a/doc/user/tools.xml b/doc/user/tools.xml
new file mode 100644
index 0000000..cc0628e
--- /dev/null
+++ b/doc/user/tools.xml
@@ -0,0 +1,38 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<para>
+
+This appendix contains descriptions of all of the
+Tools modules that are
+available "out of the box" in this version of SCons.
+
+</para>
+
+<variablelist>
+
+&tools-gen;
+
+</variablelist>
diff --git a/doc/user/troubleshoot.in b/doc/user/troubleshoot.in
new file mode 100644
index 0000000..c729149
--- /dev/null
+++ b/doc/user/troubleshoot.in
@@ -0,0 +1,875 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ The experience of configuring any
+ software build tool to build a large code base
+ usually, at some point,
+ involves trying to figure out why
+ the tool is behaving a certain way,
+ and how to get it to behave the way you want.
+ &SCons; is no different.
+ This appendix contains a number of
+ different ways in which you can
+ get some additional insight into &SCons' behavior.
+
+ </para>
+
+ <para>
+
+ Note that we're always interested in trying to
+ improve how you can troubleshoot configuration problems.
+ If you run into a problem that has
+ you scratching your head,
+ and which there just doesn't seem to be a good way to debug,
+ odds are pretty good that someone else will run into
+ the same problem, too.
+ If so, please let the SCons development team know
+ (preferably by filing a bug report
+ or feature request at our project pages at tigris.org)
+ so that we can use your feedback
+ to try to come up with a better way to help you,
+ and others, get the necessary insight into &SCons; behavior
+ to help identify and fix configuration issues.
+
+ </para>
+
+ <section>
+ <title>Why is That Target Being Rebuilt? the &debug-explain; Option</title>
+
+ <para>
+
+ Let's look at a simple example of
+ a misconfigured build
+ that causes a target to be rebuilt
+ every time &SCons; is run:
+
+ </para>
+
+ <scons_example name="explain1">
+ <file name="SConstruct" printme="1">
+ # Intentionally misspell the output file name in the
+ # command used to create the file:
+ Command('file.out', 'file.in', 'cp $SOURCE file.oout')
+ </file>
+ <file name="file.in">
+ file.in
+ </file>
+ </scons_example>
+
+ <para>
+
+ (Note to Windows users: The POSIX &cp; command
+ copies the first file named on the command line
+ to the second file.
+ In our example, it copies the &file_in; file
+ to the &file_out; file.)
+
+ </para>
+
+ <para>
+
+ Now if we run &SCons; multiple times on this example,
+ we see that it re-runs the &cp;
+ command every time:
+
+ </para>
+
+ <scons_output example="explain1" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In this example,
+ the underlying cause is obvious:
+ we've intentionally misspelled the output file name
+ in the &cp; command,
+ so the command doesn't actually
+ build the &file_out; file that we've told &SCons; to expect.
+ But if the problem weren't obvious,
+ it would be helpful
+ to specify the &debug-explain; option
+ on the command line
+ to have &SCons; tell us very specifically
+ why it's decided to rebuild the target:
+
+ </para>
+
+ <scons_output example="explain1" os="posix">
+ <scons_output_command>scons -Q --debug=explain</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If this had been a more complicated example
+ involving a lot of build output,
+ having &SCons; tell us that
+ it's trying to rebuild the target file
+ because it doesn't exist
+ would be an important clue
+ that something was wrong with
+ the command that we invoked to build it.
+
+ </para>
+
+ <para>
+
+ The &debug-explain; option also comes in handy
+ to help figure out what input file changed.
+ Given a simple configuration that builds
+ a program from three source files,
+ changing one of the source files
+ and rebuilding with the &debug-explain;
+ option shows very specifically
+ why &SCons; rebuilds the files that it does:
+
+ </para>
+
+ <scons_example name="explain2">
+ <file name="SConstruct">
+ Program('prog', ['file1.c', 'file2.c', 'file3.c'])
+ </file>
+ <file name="file1.c">
+ file1.c
+ </file>
+ <file name="file2.c">
+ file2.c
+ </file>
+ <file name="file3.c">
+ file3.c
+ </file>
+ </scons_example>
+
+ <scons_output example="explain2" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF file2.c]">edit file2.c</scons_output_command>
+ <scons_output_command>scons -Q --debug=explain</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ This becomes even more helpful
+ in identifying when a file is rebuilt
+ due to a change in an implicit dependency,
+ such as an incuded <filename>.h</filename> file.
+ If the <filename>file1.c</filename>
+ and <filename>file3.c</filename> files
+ in our example
+ both included a &hello_h; file,
+ then changing that included file
+ and re-running &SCons; with the &debug-explain; option
+ will pinpoint that it's the change to the included file
+ that starts the chain of rebuilds:
+
+ </para>
+
+ <scons_example name="explain3">
+ <file name="SConstruct">
+ Program('prog', ['file1.c', 'file2.c', 'file3.c'], CPPPATH='.')
+ </file>
+ <file name="file1.c">
+ #include &lt;hello.h&gt;
+ file1.c
+ </file>
+ <file name="file2.c">
+ file2.c
+ </file>
+ <file name="file3.c">
+ #include &lt;hello.h&gt;
+ file3.c
+ </file>
+ <file name="hello.h">
+ #define string "world"
+ </file>
+ </scons_example>
+
+ <scons_output example="explain3" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
+ <scons_output_command>scons -Q --debug=explain</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ (Note that the &debug-explain; option will only tell you
+ why &SCons; decided to rebuild necessary targets.
+ It does not tell you what files it examined
+ when deciding <emphasis>not</emphasis>
+ to rebuild a target file,
+ which is often a more valuable question to answer.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>What's in That Construction Environment? the &Dump; Method</title>
+
+ <para>
+
+ When you create a construction environment,
+ &SCons; populates it
+ with construction variables that are set up
+ for various compilers, linkers and utilities
+ that it finds on your system.
+ Although this is usually helpful and what you want,
+ it might be frustrating if &SCons;
+ doesn't set certain variables that you
+ expect to be set.
+ In situations like this,
+ it's sometimes helpful to use the
+ construction environment &Dump; method
+ to print all or some of
+ the construction variables.
+ Note that the &Dump; method
+ <emphasis>returns</emphasis>
+ the representation of the variables
+ in the environment
+ for you to print (or otherwise manipulate):
+
+ </para>
+
+ <scons_example name="Dump">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ print env.Dump()
+ </file>
+ </scons_example>
+
+ <para>
+
+ On a POSIX system with gcc installed,
+ this might generate:
+
+ </para>
+
+ <scons_output example="Dump" os="posix" tools="gcc">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ On a Windows system with Visual C++
+ the output might look like:
+
+ </para>
+
+ <scons_output example="Dump" os="win32" tools="msvc">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The construction environments in these examples have
+ actually been restricted to just gcc and Visual C++,
+ respectively.
+ In a real-life situation,
+ the construction environments will
+ likely contain a great many more variables.
+ Also note that we've massaged the example output above
+ to make the memory address of all objects a constant 0x700000.
+ In reality, you would see a different hexadecimal
+ number for each object.
+
+ </para>
+
+ <para>
+
+ To make it easier to see just what you're
+ interested in,
+ the &Dump; method allows you to
+ specify a specific constrcution variable
+ that you want to disply.
+ For example,
+ it's not unusual to want to verify
+ the external environment used to execute build commands,
+ to make sure that the PATH and other
+ environment variables are set up the way they should be.
+ You can do this as follows:
+
+ </para>
+
+ <scons_example name="Dump_ENV">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ print env.Dump('ENV')
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which might display the following when executed on a POSIX system:
+
+ </para>
+
+ <scons_output example="Dump_ENV" os="posix">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And the following when executed on a Windows system:
+
+ </para>
+
+ <scons_output example="Dump_ENV" os="win32">
+ <scons_output_command>scons</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+
+ <title>What Dependencies Does &SCons; Know About? the &tree; Option</title>
+
+ <para>
+
+ Sometimes the best way to try to figure out what
+ &SCons; is doing is simply to take a look at the
+ dependency graph that it constructs
+ based on your &SConscript; files.
+ The <literal>--tree</literal> option
+ will display all or part of the
+ &SCons; dependency graph in an
+ "ASCII art" graphical format
+ that shows the dependency hierarchy.
+
+ </para>
+
+ <para>
+
+ For example, given the following input &SConstruct; file:
+
+ </para>
+
+ <scons_example name="tree1">
+ <file name="SConstruct" printme="1">
+ env = Environment(CPPPATH = ['.'])
+ env.Program('prog', ['f1.c', 'f2.c', 'f3.c'])
+ </file>
+ <file name="f1.c">
+ #include "inc.h"
+ </file>
+ <file name="f2.c">
+ #include "inc.h"
+ </file>
+ <file name="f3.c">
+ #include "inc.h"
+ </file>
+ <file name="inc.h">
+ inc.h
+ </file>
+ </scons_example>
+
+ <para>
+
+ Running &SCons; with the <literal>--tree=all</literal>
+ option yields:
+
+ </para>
+
+ <scons_output example="tree1">
+ <scons_output_command>scons -Q --tree=all</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The tree will also be printed when the
+ <literal>-n</literal> (no execute) option is used,
+ which allows you to examine the dependency graph
+ for a configuration without actually
+ rebuilding anything in the tree.
+
+ </para>
+
+ <para>
+
+ The <literaL>--tree</literal> option only prints
+ the dependency graph for the specified targets
+ (or the default target(s) if none are specified on the command line).
+ So if you specify a target like <filename>f2.o</filename>
+ on the command line,
+ the <literaL>--tree</literal> option will only
+ print the dependency graph for that file:
+
+ </para>
+
+ <scons_output example="tree1">
+ <scons_output_command>scons -Q --tree=all f2.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ This is, of course, useful for
+ restricting the output from a very large
+ build configuration to just a
+ portion in which you're interested.
+ Multiple targets are fine,
+ in which case a tree will be printed
+ for each specified target:
+
+ </para>
+
+ <scons_output example="tree1">
+ <scons_output_command>scons -Q --tree=all f1.o f3.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The <literal>status</literal> argument may be used
+ to tell &SCons; to print status information about
+ each file in the dependency graph:
+
+ </para>
+
+ <scons_output example="tree1">
+ <scons_output_command>scons -Q --tree=status</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that <literal>--tree=all,status</literal> is equivalent;
+ the <literal>all</literal>
+ is assumed if only <literal>status</literal> is present.
+ As an alternative to <literal>all</literal>,
+ you can specify <literal>--tree=derived</literal>
+ to have &SCons; only print derived targets
+ in the tree output,
+ skipping source files
+ (like <filename>.c</filename> and <filename>.h</filename> files):
+
+ </para>
+
+ <scons_output example="tree1">
+ <scons_output_command>scons -Q --tree=derived</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ You can use the <literal>status</literal>
+ modifier with <literal>derived</literal> as well:
+
+ </para>
+
+ <scons_output example="tree1">
+ <scons_output_command>scons -Q --tree=derived,status</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Note that the order of the <literal>--tree=</literal>
+ arguments doesn't matter;
+ <literal>--tree=status,derived</literal> is
+ completely equivalent.
+
+ </para>
+
+ <para>
+
+ The default behavior of the <literal>--tree</literal> option
+ is to repeat all of the dependencies each time the library dependency
+ (or any other dependency file) is encountered in the tree.
+ If certain target files share other target files,
+ such as two programs that use the same library:
+
+ </para>
+
+ <scons_example name="tree2">
+ <file name="SConstruct" printme="1">
+ env = Environment(CPPPATH = ['.'],
+ LIBS = ['foo'],
+ LIBPATH = ['.'])
+ env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ env.Program('prog1.c')
+ env.Program('prog2.c')
+ </file>
+ <file name="prog1.c">
+ #include "inc.h"
+ </file>
+ <file name="prog2.c">
+ #include "inc.h"
+ </file>
+ <file name="f1.c">
+ #include "inc.h"
+ </file>
+ <file name="f2.c">
+ #include "inc.h"
+ </file>
+ <file name="f3.c">
+ #include "inc.h"
+ </file>
+ <file name="inc.h">
+ inc.h
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then there can be a <emphasis>lot</emphasis> of repetition in the
+ <literal>--tree=</literal> output:
+
+ </para>
+
+ <scons_output example="tree2">
+ <scons_output_command>scons -Q --tree=all</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In a large configuration with many internal libraries
+ and include files,
+ this can very quickly lead to huge output trees.
+ To help make this more manageable,
+ a <literal>prune</literal> modifier may
+ be added to the option list,
+ in which case &SCons;
+ will print the name of a target that has
+ already been visited during the tree-printing
+ in <literal>[square brackets]</literal>
+ as an indication that the dependencies
+ of the target file may be found
+ by looking farther up the tree:
+
+ </para>
+
+ <scons_output example="tree2">
+ <scons_output_command>scons -Q --tree=prune</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Like the <literal>status</literal> keyword,
+ the <literal>prune</literal> argument by itself
+ is equivalent to <literal>--tree=all,prune</literal>.
+
+ </para>
+
+ </section>
+
+ <section>
+
+ <title>How is &SCons; Constructing the Command Lines It Executes? the &debug-presub; Option</title>
+
+ <para>
+
+ Sometimes it's useful to look at the
+ pre-substitution string
+ that &SCons; uses to generate
+ the command lines it executes.
+ This can be done with the &debug-presub; option:
+
+ </para>
+
+ <scons_example name="presub">
+ <file name="SConstruct">
+ env = Environment(CPPPATH = ['.'])
+ env.Program('prog', 'prog.c')
+ </file>
+ <file name="prog.c">
+ prog.c
+ </file>
+ </scons_example>
+
+ <!--
+
+ Have to capture output here, otherwise the - -debug=presub output
+ shows the Python functions from the sconsdoc.py execution wrapper
+ used to generate this manual, not the underlying command-line strings.
+
+ <scons_output example="presub">
+ <scons_output_command>scons -Q - -debug=presub</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q --debug=presub</userinput>
+ Building prog.o with action:
+ $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCOMCOM $SOURCES
+ cc -o prog.o -c -I. prog.c
+ Building prog with action:
+ $SMART_LINKCOM
+ cc -o prog prog.o
+ </screen>
+
+ </section>
+
+ <section>
+
+ <title>Where is &SCons; Searching for Libraries? the &debug-findlibs; Option</title>
+
+ <para>
+
+ To get some insight into what library names
+ &SCons; is searching for,
+ and in which directories it is searching,
+ Use the <literal>--debug=findlibs</literal> option.
+ Given the following input &SConstruct; file:
+
+ </para>
+
+ <scons_example name="findlibs">
+ <file name="SConstruct" printme="1">
+ env = Environment(LIBPATH = ['libs1', 'libs2'])
+ env.Program('prog.c', LIBS=['foo', 'bar'])
+ </file>
+ <file name="prog.c">
+ prog.c
+ </file>
+ <file name="libs1/libfoo.a">
+ libs1/libfoo.a
+ </file>
+ <file name="libs2/libbar.a">
+ libs2/libbar.a
+ </file>
+ </scons_example>
+
+ <para>
+
+ And the libraries <filename>libfoo.a</filename>
+ and <filename>libbar.a</filename>
+ in <filename>libs1</filename> and <filename>libs2</filename>,
+ respectively,
+ use of the <literal>--debug=findlibs</literal> option yields:
+
+ </para>
+
+ <scons_output example="findlibs">
+ <scons_output_command>scons -Q --debug=findlibs</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <!--
+
+ <section>
+
+ <title>What Implicit Dependencies Did the &SCons; Scanner find? the &debug-includes; Option</title>
+
+ <para>
+
+ XXX explain the - - debug=includes option
+
+ </para>
+
+ <scons_example name="includes">
+ <file name="SConstruct" printme="1">
+ env = Environment(CPPPATH = ['inc1', 'inc2'])
+ env.Program('prog.c')
+ </file>
+ <file name="prog.c">
+ #include "file1.h"
+ #include "file2.h"
+ prog.c
+ </file>
+ <file name="inc1/file1.h">
+ inc1/file1.h
+ </file>
+ <file name="inc2/file2.h">
+ inc2/file2.h
+ </file>
+ </scons_example>
+
+ <scons_output example="includes">
+ <scons_output_command>scons -Q - - debug=includes prog</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ -->
+
+ <section>
+
+ <title>Where is &SCons; Blowing Up? the &debug-stacktrace; Option</title>
+
+ <para>
+
+ In general, &SCons; tries to keep its error
+ messages short and informative.
+ That means we usually try to avoid showing
+ the stack traces that are familiar
+ to experienced Python programmers,
+ since they usually contain much more
+ information than is useful to most people.
+
+ </para>
+
+ <para>
+
+ For example, the following &SConstruct file:
+
+ </para>
+
+ <scons_example name="stacktrace">
+ <file name="SConstruct" printme="1">
+ Program('prog.c')
+ </file>
+ </scons_example>
+
+ <para>
+
+ Generates the following error if the
+ <filename>prog.c</filename> file
+ does not exist:
+
+ </para>
+
+ <scons_output example="stacktrace">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ In this case,
+ the error is pretty obvious.
+ But if it weren't,
+ and you wanted to try to get more information
+ about the error,
+ the &debug-stacktrace; option
+ would show you exactly where in the &SCons; source code
+ the problem occurs:
+
+ </para>
+
+ <scons_output example="stacktrace">
+ <scons_output_command>scons -Q --debug=stacktrace</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Of course, if you do need to dive into the &SCons; source code,
+ we'd like to know if, or how,
+ the error messages or troubleshooting options
+ could have been improved to avoid that.
+ Not everyone has the necessary time or
+ Python skill to dive into the source code,
+ and we'd like to improve &SCons;
+ for those people as well...
+
+ </para>
+
+ </section>
+
+ <section>
+
+ <title>How is &SCons; Making Its Decisions? the &taskmastertrace; Option</title>
+
+ <para>
+
+ The internal &SCons; subsystem that handles walking
+ the dependency graph
+ and controls the decision-making about what to rebuild
+ is the <literal>Taskmaster</literal>.
+ &SCons; supports a <literal>--taskmastertrace</literal>
+ option that tells the Taskmaster to print
+ information about the children (dependencies)
+ of the various Nodes on its walk down the graph,
+ which specific dependent Nodes are being evaluated,
+ and in what order.
+
+ </para>
+
+ <para>
+
+ The <literal>--taskmastertrace</literal> option
+ takes as an argument the name of a file in
+ which to put the trace output,
+ with <filename>-</filename> (a single hyphen)
+ indicating that the trace messages
+ should be printed to the standard output:
+
+ </para>
+
+ <scons_example name="taskmastertrace">
+ <file name="SConstruct" printme="1">
+ env = Environment(CPPPATH = ['.'])
+ env.Program('prog.c')
+ </file>
+ <file name="prog.c">
+ #include "inc.h"
+ prog.c
+ </file>
+ <file name="inc.h">
+ #define STRING "one"
+ </file>
+ </scons_example>
+
+ <scons_output example="taskmastertrace" os="posix">
+ <scons_output_command>scons -Q --taskmastertrace=- prog</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The <literal>--taskmastertrace</literal> option
+ doesn't provide information about the actual
+ calculations involved in deciding if a file is up-to-date,
+ but it does show all of the dependencies
+ it knows about for each Node,
+ and the order in which those dependencies are evaluated.
+ This can be useful as an alternate way to determine
+ whether or not your &SCons; configuration,
+ or the implicit dependency scan,
+ has actually identified all the correct dependencies
+ you want it to.
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+
+ <title>Where Are My Build Bottlenecks? the &profile; Option</title>
+
+ <para>
+
+ XXX explain the - - profile= option
+
+ </para>
+
+ </section>
+
+ -->
+
+ <!--
+
+ <section>
+ <title>Troubleshooting Shared Caching: the &cache-debug; Option</title>
+
+ <para>
+
+ XXX describe the - - cache-debug option
+ XXX maybe point to the caching.in chapter?
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/troubleshoot.xml b/doc/user/troubleshoot.xml
new file mode 100644
index 0000000..6bd53f9
--- /dev/null
+++ b/doc/user/troubleshoot.xml
@@ -0,0 +1,1313 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ The experience of configuring any
+ software build tool to build a large code base
+ usually, at some point,
+ involves trying to figure out why
+ the tool is behaving a certain way,
+ and how to get it to behave the way you want.
+ &SCons; is no different.
+ This appendix contains a number of
+ different ways in which you can
+ get some additional insight into &SCons;' behavior.
+
+ </para>
+
+ <para>
+
+ Note that we're always interested in trying to
+ improve how you can troubleshoot configuration problems.
+ If you run into a problem that has
+ you scratching your head,
+ and which there just doesn't seem to be a good way to debug,
+ odds are pretty good that someone else will run into
+ the same problem, too.
+ If so, please let the SCons development team know
+ (preferably by filing a bug report
+ or feature request at our project pages at tigris.org)
+ so that we can use your feedback
+ to try to come up with a better way to help you,
+ and others, get the necessary insight into &SCons; behavior
+ to help identify and fix configuration issues.
+
+ </para>
+
+ <section>
+ <title>Why is That Target Being Rebuilt? the &debug-explain; Option</title>
+
+ <para>
+
+ Let's look at a simple example of
+ a misconfigured build
+ that causes a target to be rebuilt
+ every time &SCons; is run:
+
+ </para>
+
+ <programlisting>
+ # Intentionally misspell the output file name in the
+ # command used to create the file:
+ Command('file.out', 'file.in', 'cp $SOURCE file.oout')
+ </programlisting>
+
+ <para>
+
+ (Note to Windows users: The POSIX &cp; command
+ copies the first file named on the command line
+ to the second file.
+ In our example, it copies the &file_in; file
+ to the &file_out; file.)
+
+ </para>
+
+ <para>
+
+ Now if we run &SCons; multiple times on this example,
+ we see that it re-runs the &cp;
+ command every time:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cp file.in file.oout
+ % <userinput>scons -Q</userinput>
+ cp file.in file.oout
+ % <userinput>scons -Q</userinput>
+ cp file.in file.oout
+ </screen>
+
+ <para>
+
+ In this example,
+ the underlying cause is obvious:
+ we've intentionally misspelled the output file name
+ in the &cp; command,
+ so the command doesn't actually
+ build the &file_out; file that we've told &SCons; to expect.
+ But if the problem weren't obvious,
+ it would be helpful
+ to specify the &debug-explain; option
+ on the command line
+ to have &SCons; tell us very specifically
+ why it's decided to rebuild the target:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --debug=explain</userinput>
+ scons: building `file.out' because it doesn't exist
+ cp file.in file.oout
+ </screen>
+
+ <para>
+
+ If this had been a more complicated example
+ involving a lot of build output,
+ having &SCons; tell us that
+ it's trying to rebuild the target file
+ because it doesn't exist
+ would be an important clue
+ that something was wrong with
+ the command that we invoked to build it.
+
+ </para>
+
+ <para>
+
+ The &debug-explain; option also comes in handy
+ to help figure out what input file changed.
+ Given a simple configuration that builds
+ a program from three source files,
+ changing one of the source files
+ and rebuilding with the &debug-explain;
+ option shows very specifically
+ why &SCons; rebuilds the files that it does:
+
+ </para>
+
+
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o file1.o -c file1.c
+ cc -o file2.o -c file2.c
+ cc -o file3.o -c file3.c
+ cc -o prog file1.o file2.o file3.o
+ % <userinput>edit file2.c</userinput>
+ [CHANGE THE CONTENTS OF file2.c]
+ % <userinput>scons -Q --debug=explain</userinput>
+ scons: rebuilding `file2.o' because `file2.c' changed
+ cc -o file2.o -c file2.c
+ scons: rebuilding `prog' because `file2.o' changed
+ cc -o prog file1.o file2.o file3.o
+ </screen>
+
+ <para>
+
+ This becomes even more helpful
+ in identifying when a file is rebuilt
+ due to a change in an implicit dependency,
+ such as an incuded <filename>.h</filename> file.
+ If the <filename>file1.c</filename>
+ and <filename>file3.c</filename> files
+ in our example
+ both included a &hello_h; file,
+ then changing that included file
+ and re-running &SCons; with the &debug-explain; option
+ will pinpoint that it's the change to the included file
+ that starts the chain of rebuilds:
+
+ </para>
+
+
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o file1.o -c -I. file1.c
+ cc -o file2.o -c -I. file2.c
+ cc -o file3.o -c -I. file3.c
+ cc -o prog file1.o file2.o file3.o
+ % <userinput>edit hello.h</userinput>
+ [CHANGE THE CONTENTS OF hello.h]
+ % <userinput>scons -Q --debug=explain</userinput>
+ scons: rebuilding `file1.o' because `hello.h' changed
+ cc -o file1.o -c -I. file1.c
+ scons: rebuilding `file3.o' because `hello.h' changed
+ cc -o file3.o -c -I. file3.c
+ scons: rebuilding `prog' because:
+ `file1.o' changed
+ `file3.o' changed
+ cc -o prog file1.o file2.o file3.o
+ </screen>
+
+ <para>
+
+ (Note that the &debug-explain; option will only tell you
+ why &SCons; decided to rebuild necessary targets.
+ It does not tell you what files it examined
+ when deciding <emphasis>not</emphasis>
+ to rebuild a target file,
+ which is often a more valuable question to answer.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>What's in That Construction Environment? the &Dump; Method</title>
+
+ <para>
+
+ When you create a construction environment,
+ &SCons; populates it
+ with construction variables that are set up
+ for various compilers, linkers and utilities
+ that it finds on your system.
+ Although this is usually helpful and what you want,
+ it might be frustrating if &SCons;
+ doesn't set certain variables that you
+ expect to be set.
+ In situations like this,
+ it's sometimes helpful to use the
+ construction environment &Dump; method
+ to print all or some of
+ the construction variables.
+ Note that the &Dump; method
+ <emphasis>returns</emphasis>
+ the representation of the variables
+ in the environment
+ for you to print (or otherwise manipulate):
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ print env.Dump()
+ </programlisting>
+
+ <para>
+
+ On a POSIX system with gcc installed,
+ this might generate:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ { 'BUILDERS': {'_InternalInstall': &lt;function InstallBuilderWrapper at 0x700000&gt;, '_InternalInstallAs': &lt;function InstallAsBuilderWrapper at 0x700000&gt;},
+ 'CONFIGUREDIR': '#/.sconf_temp',
+ 'CONFIGURELOG': '#/config.log',
+ 'CPPSUFFIXES': [ '.c',
+ '.C',
+ '.cxx',
+ '.cpp',
+ '.c++',
+ '.cc',
+ '.h',
+ '.H',
+ '.hxx',
+ '.hpp',
+ '.hh',
+ '.F',
+ '.fpp',
+ '.FPP',
+ '.m',
+ '.mm',
+ '.S',
+ '.spp',
+ '.SPP'],
+ 'DSUFFIXES': ['.d'],
+ 'Dir': &lt;SCons.Defaults.Variable_Method_Caller instance at 0x700000&gt;,
+ 'Dirs': &lt;SCons.Defaults.Variable_Method_Caller instance at 0x700000&gt;,
+ 'ENV': {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'},
+ 'ESCAPE': &lt;function escape at 0x700000&gt;,
+ 'File': &lt;SCons.Defaults.Variable_Method_Caller instance at 0x700000&gt;,
+ 'HOST_ARCH': None,
+ 'HOST_OS': None,
+ 'IDLSUFFIXES': ['.idl', '.IDL'],
+ 'INSTALL': &lt;function copyFunc at 0x700000&gt;,
+ 'LIBPREFIX': 'lib',
+ 'LIBPREFIXES': ['$LIBPREFIX'],
+ 'LIBSUFFIX': '.a',
+ 'LIBSUFFIXES': ['$LIBSUFFIX', '$SHLIBSUFFIX'],
+ 'MAXLINELENGTH': 128072,
+ 'OBJPREFIX': '',
+ 'OBJSUFFIX': '.o',
+ 'PLATFORM': 'posix',
+ 'PROGPREFIX': '',
+ 'PROGSUFFIX': '',
+ 'PSPAWN': &lt;function piped_env_spawn at 0x700000&gt;,
+ 'RDirs': &lt;SCons.Defaults.Variable_Method_Caller instance at 0x700000&gt;,
+ 'SCANNERS': [],
+ 'SHELL': 'sh',
+ 'SHLIBPREFIX': '$LIBPREFIX',
+ 'SHLIBSUFFIX': '.so',
+ 'SHOBJPREFIX': '$OBJPREFIX',
+ 'SHOBJSUFFIX': '$OBJSUFFIX',
+ 'SPAWN': &lt;function spawnvpe_spawn at 0x700000&gt;,
+ 'TARGET_ARCH': None,
+ 'TARGET_OS': None,
+ 'TEMPFILE': &lt;class SCons.Platform.TempFileMunge at 0x700000&gt;,
+ 'TEMPFILEPREFIX': '@',
+ 'TOOLS': ['install', 'install'],
+ '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
+ '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
+ '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
+ '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
+ '__RPATH': '$_RPATH',
+ '_concat': &lt;function _concat at 0x700000&gt;,
+ '_defines': &lt;function _defines at 0x700000&gt;,
+ '_stripixes': &lt;function _stripixes at 0x700000&gt;}
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ scons: `.' is up to date.
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ On a Windows system with Visual C++
+ the output might look like:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons</userinput>
+ scons: Reading SConscript files ...
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ { 'BUILDERS': {'_InternalInstall': &lt;function InstallBuilderWrapper at 0x700000&gt;, 'Object': &lt;SCons.Builder.CompositeBuilder instance at 0x700000&gt;, 'PCH': &lt;SCons.Builder.BuilderBase instance at 0x700000&gt;, 'RES': &lt;SCons.Builder.BuilderBase instance at 0x700000&gt;, 'SharedObject': &lt;SCons.Builder.CompositeBuilder instance at 0x700000&gt;, 'StaticObject': &lt;SCons.Builder.CompositeBuilder instance at 0x700000&gt;, '_InternalInstallAs': &lt;function InstallAsBuilderWrapper at 0x700000&gt;},
+ 'CC': 'cl',
+ 'CCCOM': &lt;SCons.Action.FunctionAction instance at 0x700000&gt;,
+ 'CCFLAGS': ['/nologo'],
+ 'CCPCHFLAGS': ['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'],
+ 'CCPDBFLAGS': ['${(PDB and "/Z7") or ""}'],
+ 'CFILESUFFIX': '.c',
+ 'CFLAGS': [],
+ 'CONFIGUREDIR': '#/.sconf_temp',
+ 'CONFIGURELOG': '#/config.log',
+ 'CPPDEFPREFIX': '/D',
+ 'CPPDEFSUFFIX': '',
+ 'CPPSUFFIXES': [ '.c',
+ '.C',
+ '.cxx',
+ '.cpp',
+ '.c++',
+ '.cc',
+ '.h',
+ '.H',
+ '.hxx',
+ '.hpp',
+ '.hh',
+ '.F',
+ '.fpp',
+ '.FPP',
+ '.m',
+ '.mm',
+ '.S',
+ '.spp',
+ '.SPP'],
+ 'CXX': '$CC',
+ 'CXXCOM': '$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM',
+ 'CXXFILESUFFIX': '.cc',
+ 'CXXFLAGS': ['$(', '/TP', '$)'],
+ 'DSUFFIXES': ['.d'],
+ 'Dir': &lt;SCons.Defaults.Variable_Method_Caller instance at 0x700000&gt;,
+ 'Dirs': &lt;SCons.Defaults.Variable_Method_Caller instance at 0x700000&gt;,
+ 'ENV': { 'PATH': 'C:/WINDOWS\\System32',
+ 'PATHEXT': '.COM;.EXE;.BAT;.CMD',
+ 'SystemRoot': 'C:/WINDOWS'},
+ 'ESCAPE': &lt;function escape at 0x700000&gt;,
+ 'File': &lt;SCons.Defaults.Variable_Method_Caller instance at 0x700000&gt;,
+ 'HOST_ARCH': '',
+ 'HOST_OS': 'win32',
+ 'IDLSUFFIXES': ['.idl', '.IDL'],
+ 'INCPREFIX': '/I',
+ 'INCSUFFIX': '',
+ 'INSTALL': &lt;function copyFunc at 0x700000&gt;,
+ 'LIBPREFIX': '',
+ 'LIBPREFIXES': ['$LIBPREFIX'],
+ 'LIBSUFFIX': '.lib',
+ 'LIBSUFFIXES': ['$LIBSUFFIX'],
+ 'MAXLINELENGTH': 2048,
+ 'MSVC_SETUP_RUN': True,
+ 'OBJPREFIX': '',
+ 'OBJSUFFIX': '.obj',
+ 'PCHCOM': '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS',
+ 'PCHPDBFLAGS': ['${(PDB and "/Yd") or ""}'],
+ 'PLATFORM': 'win32',
+ 'PROGPREFIX': '',
+ 'PROGSUFFIX': '.exe',
+ 'PSPAWN': &lt;function piped_spawn at 0x700000&gt;,
+ 'RC': 'rc',
+ 'RCCOM': &lt;SCons.Action.FunctionAction instance at 0x700000&gt;,
+ 'RCFLAGS': [],
+ 'RCSUFFIXES': ['.rc', '.rc2'],
+ 'RDirs': &lt;SCons.Defaults.Variable_Method_Caller instance at 0x700000&gt;,
+ 'SCANNERS': [],
+ 'SHCC': '$CC',
+ 'SHCCCOM': &lt;SCons.Action.FunctionAction instance at 0x700000&gt;,
+ 'SHCCFLAGS': ['$CCFLAGS'],
+ 'SHCFLAGS': ['$CFLAGS'],
+ 'SHCXX': '$CXX',
+ 'SHCXXCOM': '$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM',
+ 'SHCXXFLAGS': ['$CXXFLAGS'],
+ 'SHELL': None,
+ 'SHLIBPREFIX': '',
+ 'SHLIBSUFFIX': '.dll',
+ 'SHOBJPREFIX': '$OBJPREFIX',
+ 'SHOBJSUFFIX': '$OBJSUFFIX',
+ 'SPAWN': &lt;function spawn at 0x700000&gt;,
+ 'STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME': 1,
+ 'TARGET_ARCH': '',
+ 'TARGET_OS': 'win32',
+ 'TEMPFILE': &lt;class SCons.Platform.TempFileMunge at 0x700000&gt;,
+ 'TEMPFILEPREFIX': '@',
+ 'TOOLS': ['msvc', 'install', 'install'],
+ '_CCCOMCOM': '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $CCPCHFLAGS $CCPDBFLAGS',
+ '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
+ '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
+ '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
+ '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
+ '_MSVC_OUTPUT_FLAG': &lt;function msvc_output_flag at 0x700000&gt;,
+ '_concat': &lt;function _concat at 0x700000&gt;,
+ '_defines': &lt;function _defines at 0x700000&gt;,
+ '_stripixes': &lt;function _stripixes at 0x700000&gt;}
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ scons: `.' is up to date.
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ The construction environments in these examples have
+ actually been restricted to just gcc and Visual C++,
+ respectively.
+ In a real-life situation,
+ the construction environments will
+ likely contain a great many more variables.
+ Also note that we've massaged the example output above
+ to make the memory address of all objects a constant 0x700000.
+ In reality, you would see a different hexadecimal
+ number for each object.
+
+ </para>
+
+ <para>
+
+ To make it easier to see just what you're
+ interested in,
+ the &Dump; method allows you to
+ specify a specific constrcution variable
+ that you want to disply.
+ For example,
+ it's not unusual to want to verify
+ the external environment used to execute build commands,
+ to make sure that the PATH and other
+ environment variables are set up the way they should be.
+ You can do this as follows:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ print env.Dump('ENV')
+ </programlisting>
+
+ <para>
+
+ Which might display the following when executed on a POSIX system:
+
+ </para>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ scons: `.' is up to date.
+ scons: done building targets.
+ </screen>
+
+ <para>
+
+ And the following when executed on a Windows system:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons</userinput>
+ scons: Reading SConscript files ...
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ { 'PATH': 'C:/WINDOWS\\System32',
+ 'PATHEXT': '.COM;.EXE;.BAT;.CMD',
+ 'SystemRoot': 'C:/WINDOWS'}
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ scons: `.' is up to date.
+ scons: done building targets.
+ </screen>
+
+ </section>
+
+ <section>
+
+ <title>What Dependencies Does &SCons; Know About? the &tree; Option</title>
+
+ <para>
+
+ Sometimes the best way to try to figure out what
+ &SCons; is doing is simply to take a look at the
+ dependency graph that it constructs
+ based on your &SConscript; files.
+ The <literal>--tree</literal> option
+ will display all or part of the
+ &SCons; dependency graph in an
+ "ASCII art" graphical format
+ that shows the dependency hierarchy.
+
+ </para>
+
+ <para>
+
+ For example, given the following input &SConstruct; file:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CPPPATH = ['.'])
+ env.Program('prog', ['f1.c', 'f2.c', 'f3.c'])
+ </programlisting>
+
+ <para>
+
+ Running &SCons; with the <literal>--tree=all</literal>
+ option yields:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --tree=all</userinput>
+ cc -o f1.o -c -I. f1.c
+ cc -o f2.o -c -I. f2.c
+ cc -o f3.o -c -I. f3.c
+ cc -o prog f1.o f2.o f3.o
+ +-.
+ +-SConstruct
+ +-f1.c
+ +-f1.o
+ | +-f1.c
+ | +-inc.h
+ +-f2.c
+ +-f2.o
+ | +-f2.c
+ | +-inc.h
+ +-f3.c
+ +-f3.o
+ | +-f3.c
+ | +-inc.h
+ +-inc.h
+ +-prog
+ +-f1.o
+ | +-f1.c
+ | +-inc.h
+ +-f2.o
+ | +-f2.c
+ | +-inc.h
+ +-f3.o
+ +-f3.c
+ +-inc.h
+ </screen>
+
+ <para>
+
+ The tree will also be printed when the
+ <literal>-n</literal> (no execute) option is used,
+ which allows you to examine the dependency graph
+ for a configuration without actually
+ rebuilding anything in the tree.
+
+ </para>
+
+ <para>
+
+ The <literal>--tree</literal> option only prints
+ the dependency graph for the specified targets
+ (or the default target(s) if none are specified on the command line).
+ So if you specify a target like <filename>f2.o</filename>
+ on the command line,
+ the <literal>--tree</literal> option will only
+ print the dependency graph for that file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --tree=all f2.o</userinput>
+ cc -o f2.o -c -I. f2.c
+ +-f2.o
+ +-f2.c
+ +-inc.h
+ </screen>
+
+ <para>
+
+ This is, of course, useful for
+ restricting the output from a very large
+ build configuration to just a
+ portion in which you're interested.
+ Multiple targets are fine,
+ in which case a tree will be printed
+ for each specified target:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --tree=all f1.o f3.o</userinput>
+ cc -o f1.o -c -I. f1.c
+ +-f1.o
+ +-f1.c
+ +-inc.h
+ cc -o f3.o -c -I. f3.c
+ +-f3.o
+ +-f3.c
+ +-inc.h
+ </screen>
+
+ <para>
+
+ The <literal>status</literal> argument may be used
+ to tell &SCons; to print status information about
+ each file in the dependency graph:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --tree=status</userinput>
+ cc -o f1.o -c -I. f1.c
+ cc -o f2.o -c -I. f2.c
+ cc -o f3.o -c -I. f3.c
+ cc -o prog f1.o f2.o f3.o
+ E = exists
+ R = exists in repository only
+ b = implicit builder
+ B = explicit builder
+ S = side effect
+ P = precious
+ A = always build
+ C = current
+ N = no clean
+ H = no cache
+
+ [E b ]+-.
+ [E C ] +-SConstruct
+ [E C ] +-f1.c
+ [E B C ] +-f1.o
+ [E C ] | +-f1.c
+ [E C ] | +-inc.h
+ [E C ] +-f2.c
+ [E B C ] +-f2.o
+ [E C ] | +-f2.c
+ [E C ] | +-inc.h
+ [E C ] +-f3.c
+ [E B C ] +-f3.o
+ [E C ] | +-f3.c
+ [E C ] | +-inc.h
+ [E C ] +-inc.h
+ [E B C ] +-prog
+ [E B C ] +-f1.o
+ [E C ] | +-f1.c
+ [E C ] | +-inc.h
+ [E B C ] +-f2.o
+ [E C ] | +-f2.c
+ [E C ] | +-inc.h
+ [E B C ] +-f3.o
+ [E C ] +-f3.c
+ [E C ] +-inc.h
+ </screen>
+
+ <para>
+
+ Note that <literal>--tree=all,status</literal> is equivalent;
+ the <literal>all</literal>
+ is assumed if only <literal>status</literal> is present.
+ As an alternative to <literal>all</literal>,
+ you can specify <literal>--tree=derived</literal>
+ to have &SCons; only print derived targets
+ in the tree output,
+ skipping source files
+ (like <filename>.c</filename> and <filename>.h</filename> files):
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --tree=derived</userinput>
+ cc -o f1.o -c -I. f1.c
+ cc -o f2.o -c -I. f2.c
+ cc -o f3.o -c -I. f3.c
+ cc -o prog f1.o f2.o f3.o
+ +-.
+ +-f1.o
+ +-f2.o
+ +-f3.o
+ +-prog
+ +-f1.o
+ +-f2.o
+ +-f3.o
+ </screen>
+
+ <para>
+
+ You can use the <literal>status</literal>
+ modifier with <literal>derived</literal> as well:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --tree=derived,status</userinput>
+ cc -o f1.o -c -I. f1.c
+ cc -o f2.o -c -I. f2.c
+ cc -o f3.o -c -I. f3.c
+ cc -o prog f1.o f2.o f3.o
+ E = exists
+ R = exists in repository only
+ b = implicit builder
+ B = explicit builder
+ S = side effect
+ P = precious
+ A = always build
+ C = current
+ N = no clean
+ H = no cache
+
+ [E b ]+-.
+ [E B C ] +-f1.o
+ [E B C ] +-f2.o
+ [E B C ] +-f3.o
+ [E B C ] +-prog
+ [E B C ] +-f1.o
+ [E B C ] +-f2.o
+ [E B C ] +-f3.o
+ </screen>
+
+ <para>
+
+ Note that the order of the <literal>--tree=</literal>
+ arguments doesn't matter;
+ <literal>--tree=status,derived</literal> is
+ completely equivalent.
+
+ </para>
+
+ <para>
+
+ The default behavior of the <literal>--tree</literal> option
+ is to repeat all of the dependencies each time the library dependency
+ (or any other dependency file) is encountered in the tree.
+ If certain target files share other target files,
+ such as two programs that use the same library:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CPPPATH = ['.'],
+ LIBS = ['foo'],
+ LIBPATH = ['.'])
+ env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ env.Program('prog1.c')
+ env.Program('prog2.c')
+ </programlisting>
+
+ <para>
+
+ Then there can be a <emphasis>lot</emphasis> of repetition in the
+ <literal>--tree=</literal> output:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --tree=all</userinput>
+ cc -o f1.o -c -I. f1.c
+ cc -o f2.o -c -I. f2.c
+ cc -o f3.o -c -I. f3.c
+ ar rc libfoo.a f1.o f2.o f3.o
+ ranlib libfoo.a
+ cc -o prog1.o -c -I. prog1.c
+ cc -o prog1 prog1.o -L. -lfoo
+ cc -o prog2.o -c -I. prog2.c
+ cc -o prog2 prog2.o -L. -lfoo
+ +-.
+ +-SConstruct
+ +-f1.c
+ +-f1.o
+ | +-f1.c
+ | +-inc.h
+ +-f2.c
+ +-f2.o
+ | +-f2.c
+ | +-inc.h
+ +-f3.c
+ +-f3.o
+ | +-f3.c
+ | +-inc.h
+ +-inc.h
+ +-libfoo.a
+ | +-f1.o
+ | | +-f1.c
+ | | +-inc.h
+ | +-f2.o
+ | | +-f2.c
+ | | +-inc.h
+ | +-f3.o
+ | +-f3.c
+ | +-inc.h
+ +-prog1
+ | +-prog1.o
+ | | +-prog1.c
+ | | +-inc.h
+ | +-libfoo.a
+ | +-f1.o
+ | | +-f1.c
+ | | +-inc.h
+ | +-f2.o
+ | | +-f2.c
+ | | +-inc.h
+ | +-f3.o
+ | +-f3.c
+ | +-inc.h
+ +-prog1.c
+ +-prog1.o
+ | +-prog1.c
+ | +-inc.h
+ +-prog2
+ | +-prog2.o
+ | | +-prog2.c
+ | | +-inc.h
+ | +-libfoo.a
+ | +-f1.o
+ | | +-f1.c
+ | | +-inc.h
+ | +-f2.o
+ | | +-f2.c
+ | | +-inc.h
+ | +-f3.o
+ | +-f3.c
+ | +-inc.h
+ +-prog2.c
+ +-prog2.o
+ +-prog2.c
+ +-inc.h
+ </screen>
+
+ <para>
+
+ In a large configuration with many internal libraries
+ and include files,
+ this can very quickly lead to huge output trees.
+ To help make this more manageable,
+ a <literal>prune</literal> modifier may
+ be added to the option list,
+ in which case &SCons;
+ will print the name of a target that has
+ already been visited during the tree-printing
+ in <literal>[square brackets]</literal>
+ as an indication that the dependencies
+ of the target file may be found
+ by looking farther up the tree:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --tree=prune</userinput>
+ cc -o f1.o -c -I. f1.c
+ cc -o f2.o -c -I. f2.c
+ cc -o f3.o -c -I. f3.c
+ ar rc libfoo.a f1.o f2.o f3.o
+ ranlib libfoo.a
+ cc -o prog1.o -c -I. prog1.c
+ cc -o prog1 prog1.o -L. -lfoo
+ cc -o prog2.o -c -I. prog2.c
+ cc -o prog2 prog2.o -L. -lfoo
+ +-.
+ +-SConstruct
+ +-f1.c
+ +-f1.o
+ | +-f1.c
+ | +-inc.h
+ +-f2.c
+ +-f2.o
+ | +-f2.c
+ | +-inc.h
+ +-f3.c
+ +-f3.o
+ | +-f3.c
+ | +-inc.h
+ +-inc.h
+ +-libfoo.a
+ | +-[f1.o]
+ | +-[f2.o]
+ | +-[f3.o]
+ +-prog1
+ | +-prog1.o
+ | | +-prog1.c
+ | | +-inc.h
+ | +-[libfoo.a]
+ +-prog1.c
+ +-[prog1.o]
+ +-prog2
+ | +-prog2.o
+ | | +-prog2.c
+ | | +-inc.h
+ | +-[libfoo.a]
+ +-prog2.c
+ +-[prog2.o]
+ </screen>
+
+ <para>
+
+ Like the <literal>status</literal> keyword,
+ the <literal>prune</literal> argument by itself
+ is equivalent to <literal>--tree=all,prune</literal>.
+
+ </para>
+
+ </section>
+
+ <section>
+
+ <title>How is &SCons; Constructing the Command Lines It Executes? the &debug-presub; Option</title>
+
+ <para>
+
+ Sometimes it's useful to look at the
+ pre-substitution string
+ that &SCons; uses to generate
+ the command lines it executes.
+ This can be done with the &debug-presub; option:
+
+ </para>
+
+
+
+ <!--
+
+ Have to capture output here, otherwise the - -debug=presub output
+ shows the Python functions from the sconsdoc.py execution wrapper
+ used to generate this manual, not the underlying command-line strings.
+
+ <scons_output example="presub">
+ <scons_output_command>scons -Q - -debug=presub</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q --debug=presub</userinput>
+ Building prog.o with action:
+ $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCOMCOM $SOURCES
+ cc -o prog.o -c -I. prog.c
+ Building prog with action:
+ $SMART_LINKCOM
+ cc -o prog prog.o
+ </screen>
+
+ </section>
+
+ <section>
+
+ <title>Where is &SCons; Searching for Libraries? the &debug-findlibs; Option</title>
+
+ <para>
+
+ To get some insight into what library names
+ &SCons; is searching for,
+ and in which directories it is searching,
+ Use the <literal>--debug=findlibs</literal> option.
+ Given the following input &SConstruct; file:
+
+ </para>
+
+ <programlisting>
+ env = Environment(LIBPATH = ['libs1', 'libs2'])
+ env.Program('prog.c', LIBS=['foo', 'bar'])
+ </programlisting>
+
+ <para>
+
+ And the libraries <filename>libfoo.a</filename>
+ and <filename>libbar.a</filename>
+ in <filename>libs1</filename> and <filename>libs2</filename>,
+ respectively,
+ use of the <literal>--debug=findlibs</literal> option yields:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --debug=findlibs</userinput>
+ findlibs: looking for 'libfoo.a' in 'libs1' ...
+ findlibs: ... FOUND 'libfoo.a' in 'libs1'
+ findlibs: looking for 'libfoo.so' in 'libs1' ...
+ findlibs: looking for 'libfoo.so' in 'libs2' ...
+ findlibs: looking for 'libbar.a' in 'libs1' ...
+ findlibs: looking for 'libbar.a' in 'libs2' ...
+ findlibs: ... FOUND 'libbar.a' in 'libs2'
+ findlibs: looking for 'libbar.so' in 'libs1' ...
+ findlibs: looking for 'libbar.so' in 'libs2' ...
+ cc -o prog.o -c prog.c
+ cc -o prog prog.o -Llibs1 -Llibs2 -lfoo -lbar
+ </screen>
+
+ </section>
+
+ <!--
+
+ <section>
+
+ <title>What Implicit Dependencies Did the &SCons; Scanner find? the &debug-includes; Option</title>
+
+ <para>
+
+ XXX explain the - - debug=includes option
+
+ </para>
+
+ <scons_example name="includes">
+ <file name="SConstruct" printme="1">
+ env = Environment(CPPPATH = ['inc1', 'inc2'])
+ env.Program('prog.c')
+ </file>
+ <file name="prog.c">
+ #include "file1.h"
+ #include "file2.h"
+ prog.c
+ </file>
+ <file name="inc1/file1.h">
+ inc1/file1.h
+ </file>
+ <file name="inc2/file2.h">
+ inc2/file2.h
+ </file>
+ </scons_example>
+
+ <scons_output example="includes">
+ <scons_output_command>scons -Q - - debug=includes prog</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ -->
+
+ <section>
+
+ <title>Where is &SCons; Blowing Up? the &debug-stacktrace; Option</title>
+
+ <para>
+
+ In general, &SCons; tries to keep its error
+ messages short and informative.
+ That means we usually try to avoid showing
+ the stack traces that are familiar
+ to experienced Python programmers,
+ since they usually contain much more
+ information than is useful to most people.
+
+ </para>
+
+ <para>
+
+ For example, the following &SConstruct; file:
+
+ </para>
+
+ <programlisting>
+ Program('prog.c')
+ </programlisting>
+
+ <para>
+
+ Generates the following error if the
+ <filename>prog.c</filename> file
+ does not exist:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'.
+ </screen>
+
+ <para>
+
+ In this case,
+ the error is pretty obvious.
+ But if it weren't,
+ and you wanted to try to get more information
+ about the error,
+ the &debug-stacktrace; option
+ would show you exactly where in the &SCons; source code
+ the problem occurs:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --debug=stacktrace</userinput>
+ scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'.
+ scons: internal stack trace:
+ File "bootstrap/src/engine/SCons/Job.py", line 197, in start
+ File "bootstrap/src/engine/SCons/Script/Main.py", line 167, in prepare
+ File "bootstrap/src/engine/SCons/Taskmaster.py", line 190, in prepare
+ File "bootstrap/src/engine/SCons/Executor.py", line 397, in prepare
+ </screen>
+
+ <para>
+
+ Of course, if you do need to dive into the &SCons; source code,
+ we'd like to know if, or how,
+ the error messages or troubleshooting options
+ could have been improved to avoid that.
+ Not everyone has the necessary time or
+ Python skill to dive into the source code,
+ and we'd like to improve &SCons;
+ for those people as well...
+
+ </para>
+
+ </section>
+
+ <section>
+
+ <title>How is &SCons; Making Its Decisions? the &taskmastertrace; Option</title>
+
+ <para>
+
+ The internal &SCons; subsystem that handles walking
+ the dependency graph
+ and controls the decision-making about what to rebuild
+ is the <literal>Taskmaster</literal>.
+ &SCons; supports a <literal>--taskmastertrace</literal>
+ option that tells the Taskmaster to print
+ information about the children (dependencies)
+ of the various Nodes on its walk down the graph,
+ which specific dependent Nodes are being evaluated,
+ and in what order.
+
+ </para>
+
+ <para>
+
+ The <literal>--taskmastertrace</literal> option
+ takes as an argument the name of a file in
+ which to put the trace output,
+ with <filename>-</filename> (a single hyphen)
+ indicating that the trace messages
+ should be printed to the standard output:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CPPPATH = ['.'])
+ env.Program('prog.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q --taskmastertrace=- prog</userinput>
+
+ Taskmaster: Looking for a node to evaluate
+ Taskmaster: Considering node &lt;no_state 0 'prog'&gt; and its children:
+ Taskmaster: &lt;no_state 0 'prog.o'&gt;
+ Taskmaster: adjusted ref count: &lt;pending 1 'prog'&gt;, child 'prog.o'
+ Taskmaster: Considering node &lt;no_state 0 'prog.o'&gt; and its children:
+ Taskmaster: &lt;no_state 0 'prog.c'&gt;
+ Taskmaster: &lt;no_state 0 'inc.h'&gt;
+ Taskmaster: adjusted ref count: &lt;pending 1 'prog.o'&gt;, child 'prog.c'
+ Taskmaster: adjusted ref count: &lt;pending 2 'prog.o'&gt;, child 'inc.h'
+ Taskmaster: Considering node &lt;no_state 0 'prog.c'&gt; and its children:
+ Taskmaster: Evaluating &lt;pending 0 'prog.c'&gt;
+
+ Task.make_ready_current(): node &lt;pending 0 'prog.c'&gt;
+ Task.prepare(): node &lt;up_to_date 0 'prog.c'&gt;
+ Task.executed_with_callbacks(): node &lt;up_to_date 0 'prog.c'&gt;
+ Task.postprocess(): node &lt;up_to_date 0 'prog.c'&gt;
+ Task.postprocess(): removing &lt;up_to_date 0 'prog.c'&gt;
+ Task.postprocess(): adjusted parent ref count &lt;pending 1 'prog.o'&gt;
+
+ Taskmaster: Looking for a node to evaluate
+ Taskmaster: Considering node &lt;no_state 0 'inc.h'&gt; and its children:
+ Taskmaster: Evaluating &lt;pending 0 'inc.h'&gt;
+
+ Task.make_ready_current(): node &lt;pending 0 'inc.h'&gt;
+ Task.prepare(): node &lt;up_to_date 0 'inc.h'&gt;
+ Task.executed_with_callbacks(): node &lt;up_to_date 0 'inc.h'&gt;
+ Task.postprocess(): node &lt;up_to_date 0 'inc.h'&gt;
+ Task.postprocess(): removing &lt;up_to_date 0 'inc.h'&gt;
+ Task.postprocess(): adjusted parent ref count &lt;pending 0 'prog.o'&gt;
+
+ Taskmaster: Looking for a node to evaluate
+ Taskmaster: Considering node &lt;pending 0 'prog.o'&gt; and its children:
+ Taskmaster: &lt;up_to_date 0 'prog.c'&gt;
+ Taskmaster: &lt;up_to_date 0 'inc.h'&gt;
+ Taskmaster: Evaluating &lt;pending 0 'prog.o'&gt;
+
+ Task.make_ready_current(): node &lt;pending 0 'prog.o'&gt;
+ Task.prepare(): node &lt;executing 0 'prog.o'&gt;
+ Task.execute(): node &lt;executing 0 'prog.o'&gt;
+ cc -o prog.o -c -I. prog.c
+ Task.executed_with_callbacks(): node &lt;executing 0 'prog.o'&gt;
+ Task.postprocess(): node &lt;executed 0 'prog.o'&gt;
+ Task.postprocess(): removing &lt;executed 0 'prog.o'&gt;
+ Task.postprocess(): adjusted parent ref count &lt;pending 0 'prog'&gt;
+
+ Taskmaster: Looking for a node to evaluate
+ Taskmaster: Considering node &lt;pending 0 'prog'&gt; and its children:
+ Taskmaster: &lt;executed 0 'prog.o'&gt;
+ Taskmaster: Evaluating &lt;pending 0 'prog'&gt;
+
+ Task.make_ready_current(): node &lt;pending 0 'prog'&gt;
+ Task.prepare(): node &lt;executing 0 'prog'&gt;
+ Task.execute(): node &lt;executing 0 'prog'&gt;
+ cc -o prog prog.o
+ Task.executed_with_callbacks(): node &lt;executing 0 'prog'&gt;
+ Task.postprocess(): node &lt;executed 0 'prog'&gt;
+
+ Taskmaster: Looking for a node to evaluate
+ Taskmaster: No candidate anymore.
+ </screen>
+
+ <para>
+
+ The <literal>--taskmastertrace</literal> option
+ doesn't provide information about the actual
+ calculations involved in deciding if a file is up-to-date,
+ but it does show all of the dependencies
+ it knows about for each Node,
+ and the order in which those dependencies are evaluated.
+ This can be useful as an alternate way to determine
+ whether or not your &SCons; configuration,
+ or the implicit dependency scan,
+ has actually identified all the correct dependencies
+ you want it to.
+
+ </para>
+
+ </section>
+
+ <!--
+
+ <section>
+
+ <title>Where Are My Build Bottlenecks? the &profile; Option</title>
+
+ <para>
+
+ XXX explain the - - profile= option
+
+ </para>
+
+ </section>
+
+ -->
+
+ <!--
+
+ <section>
+ <title>Troubleshooting Shared Caching: the &cache-debug; Option</title>
+
+ <para>
+
+ XXX describe the - - cache-debug option
+ XXX maybe point to the caching.in chapter?
+
+ </para>
+
+ </section>
+
+ -->
diff --git a/doc/user/variables.in b/doc/user/variables.in
new file mode 100644
index 0000000..85fb9cd
--- /dev/null
+++ b/doc/user/variables.in
@@ -0,0 +1,56 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<para>
+
+This appendix contains descriptions of all of the
+construction variables that are <emphasis>potentially</emphasis>
+available "out of the box" in this version of SCons.
+Whether or not setting a construction variable
+in a construction environment
+will actually have an effect depends on
+whether any of the Tools and/or Builders
+that use the variable have been
+included in the construction environment.
+
+</para>
+
+<para>
+
+In this appendix, we have
+appended the initial <envar>$</envar>
+(dollar sign) to the beginning of each
+variable name when it appears in the text,
+but left off the dollar sign
+in the left-hand column
+where the name appears for each entry.
+
+</para>
+
+<variablelist>
+
+&variables-gen;
+
+</variablelist>
diff --git a/doc/user/variables.xml b/doc/user/variables.xml
new file mode 100644
index 0000000..85fb9cd
--- /dev/null
+++ b/doc/user/variables.xml
@@ -0,0 +1,56 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<para>
+
+This appendix contains descriptions of all of the
+construction variables that are <emphasis>potentially</emphasis>
+available "out of the box" in this version of SCons.
+Whether or not setting a construction variable
+in a construction environment
+will actually have an effect depends on
+whether any of the Tools and/or Builders
+that use the variable have been
+included in the construction environment.
+
+</para>
+
+<para>
+
+In this appendix, we have
+appended the initial <envar>$</envar>
+(dollar sign) to the beginning of each
+variable name when it appears in the text,
+but left off the dollar sign
+in the left-hand column
+where the name appears for each entry.
+
+</para>
+
+<variablelist>
+
+&variables-gen;
+
+</variablelist>
diff --git a/doc/user/variants.in b/doc/user/variants.in
new file mode 100644
index 0000000..696e174
--- /dev/null
+++ b/doc/user/variants.in
@@ -0,0 +1,151 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Variant builds
+
+=head2 Variations on a theme
+
+Other variations of this model are possible. For example, you might decide
+that you want to separate out your include files into platform dependent and
+platform independent files. In this case, you'd have to define an
+alternative to C<$INCLUDE> for platform-dependent files. Most F<Conscript>
+files, generating purely platform-independent include files, would not have
+to change.
+
+You might also want to be able to compile your whole system with debugging
+or profiling, for example, enabled. You could do this with appropriate
+command line options, such as C<DEBUG=on>. This would then be translated
+into the appropriate platform-specific requirements to enable debugging
+(this might include turning off optimization, for example). You could
+optionally vary the name space for these different types of systems, but, as
+we'll see in the next section, it's not B<essential> to do this, since Cons
+is pretty smart about rebuilding things when you change options.
+
+-->
+
+ <para>
+
+ The &variant_dir; keyword argument of
+ the &SConscript; function provides everything
+ we need to show how easy it is to create
+ variant builds using &SCons;.
+ Suppose, for example, that we want to
+ build a program for both Windows and Linux platforms,
+ but that we want to build it in a shared directory
+ with separate side-by-side build directories
+ for the Windows and Linux versions of the program.
+
+ </para>
+
+ <scons_example name="ex_variants">
+ <file name="SConstruct" printme="1">
+ platform = ARGUMENTS.get('OS', Platform())
+
+ include = "#export/$PLATFORM/include"
+ lib = "#export/$PLATFORM/lib"
+ bin = "#export/$PLATFORM/bin"
+
+ env = Environment(PLATFORM = platform,
+ BINDIR = bin,
+ INCDIR = include,
+ LIBDIR = lib,
+ CPPPATH = [include],
+ LIBPATH = [lib],
+ LIBS = 'world')
+
+ Export('env')
+
+ env.SConscript('src/SConscript', variant_dir='build/$PLATFORM')
+ </file>
+ <directory name="src"></directory>
+ <directory name="src/hello"></directory>
+ <directory name="src/world"></directory>
+ <file name="src/SConscript">
+ Import('env')
+ SConscript('hello/SConscript')
+ SConscript('world/SConscript')
+ </file>
+ <file name="src/hello/SConscript">
+ Import('env')
+ hello = env.Program('hello.c')
+ env.Install('$BINDIR', hello)
+ </file>
+ <file name="src/hello/hello.c">
+ #include "world.h"
+ int main(int argc, char *argv[]) { printf "hello.c\n"; world(); }
+ </file>
+ <file name="src/world/SConscript">
+ Import('env')
+ world = env.Library('world.c')
+ env.Install('$LIBDIR', world)
+ env.Install('$INCDIR', 'world.h')
+ </file>
+ <file name="src/world/world.h">
+ #define STRING "world.h"
+ extern int world();
+ </file>
+ <file name="src/world/world.c">
+ int world() { printf "world.c\n"; }
+ </file>
+ </scons_example>
+
+ <para>
+
+ This SConstruct file,
+ when run on a Linux system, yields:
+
+ </para>
+
+ <scons_output example="ex_variants" os="posix">
+ <scons_output_command>scons -Q OS=linux</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ The same SConstruct file on Windows would build:
+
+ </para>
+
+ <scons_output example="ex_variants" os="win32">
+ <scons_output_command>scons -Q OS=windows</scons_output_command>
+ </scons_output>
+
+ <!--
+
+ <scons_example name="ex_var2">
+ <file name="SConstruct" printme="1">
+ env = Environment(OS = ARGUMENTS.get('OS'))
+ for os in ['newell', 'post']:
+ SConscript('src/SConscript', variant_dir='build/' + os)
+ </file>
+ </scons_example>
+
+ <scons_output example="ex_var2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
diff --git a/doc/user/variants.xml b/doc/user/variants.xml
new file mode 100644
index 0000000..016202a
--- /dev/null
+++ b/doc/user/variants.xml
@@ -0,0 +1,146 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+<!--
+
+=head1 Variant builds
+
+=head2 Variations on a theme
+
+Other variations of this model are possible. For example, you might decide
+that you want to separate out your include files into platform dependent and
+platform independent files. In this case, you'd have to define an
+alternative to C<$INCLUDE> for platform-dependent files. Most F<Conscript>
+files, generating purely platform-independent include files, would not have
+to change.
+
+You might also want to be able to compile your whole system with debugging
+or profiling, for example, enabled. You could do this with appropriate
+command line options, such as C<DEBUG=on>. This would then be translated
+into the appropriate platform-specific requirements to enable debugging
+(this might include turning off optimization, for example). You could
+optionally vary the name space for these different types of systems, but, as
+we'll see in the next section, it's not B<essential> to do this, since Cons
+is pretty smart about rebuilding things when you change options.
+
+-->
+
+ <para>
+
+ The &variant_dir; keyword argument of
+ the &SConscript; function provides everything
+ we need to show how easy it is to create
+ variant builds using &SCons;.
+ Suppose, for example, that we want to
+ build a program for both Windows and Linux platforms,
+ but that we want to build it in a shared directory
+ with separate side-by-side build directories
+ for the Windows and Linux versions of the program.
+
+ </para>
+
+ <programlisting>
+ platform = ARGUMENTS.get('OS', Platform())
+
+ include = "#export/$PLATFORM/include"
+ lib = "#export/$PLATFORM/lib"
+ bin = "#export/$PLATFORM/bin"
+
+ env = Environment(PLATFORM = platform,
+ BINDIR = bin,
+ INCDIR = include,
+ LIBDIR = lib,
+ CPPPATH = [include],
+ LIBPATH = [lib],
+ LIBS = 'world')
+
+ Export('env')
+
+ env.SConscript('src/SConscript', variant_dir='build/$PLATFORM')
+ </programlisting>
+
+ <para>
+
+ This SConstruct file,
+ when run on a Linux system, yields:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q OS=linux</userinput>
+ Install file: "build/linux/world/world.h" as "export/linux/include/world.h"
+ cc -o build/linux/hello/hello.o -c -Iexport/linux/include build/linux/hello/hello.c
+ cc -o build/linux/world/world.o -c -Iexport/linux/include build/linux/world/world.c
+ ar rc build/linux/world/libworld.a build/linux/world/world.o
+ ranlib build/linux/world/libworld.a
+ Install file: "build/linux/world/libworld.a" as "export/linux/lib/libworld.a"
+ cc -o build/linux/hello/hello build/linux/hello/hello.o -Lexport/linux/lib -lworld
+ Install file: "build/linux/hello/hello" as "export/linux/bin/hello"
+ </screen>
+
+ <para>
+
+ The same SConstruct file on Windows would build:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q OS=windows</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ Install file: "build/windows/world/world.h" as "export/windows/include/world.h"
+ cl /Fobuild\windows\hello\hello.obj /c build\windows\hello\hello.c /nologo /Iexport\windows\include
+ cl /Fobuild\windows\world\world.obj /c build\windows\world\world.c /nologo /Iexport\windows\include
+ lib /nologo /OUT:build\windows\world\world.lib build\windows\world\world.obj
+ Install file: "build/windows/world/world.lib" as "export/windows/lib/world.lib"
+ link /nologo /OUT:build\windows\hello\hello.exe /LIBPATH:export\windows\lib world.lib build\windows\hello\hello.obj
+ Install file: "build/windows/hello/hello.exe" as "export/windows/bin/hello.exe"
+ </screen>
+
+ <!--
+
+ <scons_example name="ex_var2">
+ <file name="SConstruct" printme="1">
+ env = Environment(OS = ARGUMENTS.get('OS'))
+ for os in ['newell', 'post']:
+ SConscript('src/SConscript', variant_dir='build/' + os)
+ </file>
+ </scons_example>
+
+ <scons_output example="ex_var2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->