Add design documentation.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 10 Aug 2001 09:55:19 +0000 (09:55 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 10 Aug 2001 09:55:19 +0000 (09:55 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@20 fdb21ef1-2011-0410-befe-b5e4ea1792b1

18 files changed:
Construct
doc/.aeignore [new file with mode: 0644]
doc/Conscript [new file with mode: 0644]
doc/copyright.sgml [new file with mode: 0644]
doc/design/.aeignore [new file with mode: 0644]
doc/design/acks.sgml [new file with mode: 0644]
doc/design/bground.sgml [new file with mode: 0644]
doc/design/engine.fig [new file with mode: 0644]
doc/design/engine.jpg [new file with mode: 0644]
doc/design/engine.sgml [new file with mode: 0644]
doc/design/goals.sgml [new file with mode: 0644]
doc/design/install.sgml [new file with mode: 0644]
doc/design/intro.sgml [new file with mode: 0644]
doc/design/issues.sgml [new file with mode: 0644]
doc/design/main.sgml [new file with mode: 0644]
doc/design/native.sgml [new file with mode: 0644]
doc/design/overview.sgml [new file with mode: 0644]
doc/scons.mod [new file with mode: 0644]

index 06dd833f1c57557000131844c2dce375fc6fff04..6fe36338137d584ad2a106de82e814dc96e5544b 100644 (file)
--- a/Construct
+++ b/Construct
@@ -90,6 +90,15 @@ Export qw( env test_dir );
 
 Build "etc/Conscript";
 
+#
+# Documentation.
+#
+Link 'build/doc' => 'doc';
+
+Export qw( date env revision version );
+
+Build 'build/doc/Conscript';
+
 #
 # If we're running in the actual Aegis project, pack up a complete
 # source .tar.gz from the project files and files in the change,
diff --git a/doc/.aeignore b/doc/.aeignore
new file mode 100644 (file)
index 0000000..103da1c
--- /dev/null
@@ -0,0 +1,4 @@
+*,D
+.*.swp
+.consign
+version.sgml
diff --git a/doc/Conscript b/doc/Conscript
new file mode 100644 (file)
index 0000000..2841815
--- /dev/null
@@ -0,0 +1,77 @@
+#
+#
+#
+
+Import qw(
+    date
+    env
+    revision
+    version
+);
+
+#
+$verfile = SourcePath("version.sgml");
+open(FILE, ">$verfile") || die "Cannot open '$verfile': $!";
+print FILE <<_EOF_;
+<!--
+THIS IS AN AUTOMATICALLY-GENERATED FILE.  DO NOT EDIT.
+-->
+<!ENTITY build_date "$date">
+<!ENTITY build_version "$version">
+<!ENTITY build_revision "$revision">
+_EOF_
+close(FILE);
+
+Ignore("#$verfile");
+
+#
+#
+#
+
+@doc_dirs = qw(
+    design
+);
+
+# Find internal dependencies in .sgml files:
+#
+#      <!entity bground SYSTEM "bground.sgml">
+#      <graphic 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.
+sub scansgml {
+    my @includes = ();
+    do {
+       if (/<!entity\s+(?:%\s+)?(?:\S+)\s+SYSTEM\s+"([^"]*)">/i) {
+           push(@includes, $1);
+       } elsif (/<graphic[^>]*\sfileref="([^"]*)"/) {
+           push(@includes, "design/$1");
+       }
+    } while (<scan::quickscan::SCAN>);
+    @includes;
+}
+
+$env->QuickScan(\&scansgml, "scons.mod");
+$env->QuickScan(\&scansgml, "copyright.sgml");
+
+foreach $doc (@doc_dirs) {
+    my $main = "$doc/main.sgml";
+    my $out = "main.out";
+
+    $env->QuickScan(\&scansgml, $main);
+
+    $env->Command("HTML/$doc/book1.html", $main,
+       qq(jw -b html -o %>:d %<));
+
+    $env->Command("PS/$doc.ps", $main,
+       [qq(jw -b ps -o %>:d %<),
+        qq(mv %>:d/main.ps %>),
+       ]);
+
+    $env->Command("PDF/$doc.pdf", $main,
+       [qq(jw -b pdf -o %>:d %<),
+        qq(mv %>:d/main.pdf %>),
+#       qq(rm -f %>:d/$out),
+       ]);
+}
diff --git a/doc/copyright.sgml b/doc/copyright.sgml
new file mode 100644 (file)
index 0000000..a4583ae
--- /dev/null
@@ -0,0 +1,20 @@
+<!--
+
+  Legal copyright notice.  Since some of this was published by Software
+  Carpentry for the contest, make sure we reference them and their
+  Open Publication license.
+
+-->
+
+<blockquote>
+ <para>
+
+  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/.aeignore b/doc/design/.aeignore
new file mode 100644 (file)
index 0000000..872e8be
--- /dev/null
@@ -0,0 +1,3 @@
+*,D
+.*.swp
+.consign
diff --git a/doc/design/acks.sgml b/doc/design/acks.sgml
new file mode 100644 (file)
index 0000000..75f0cbf
--- /dev/null
@@ -0,0 +1,160 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+
+ <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.sgml b/doc/design/bground.sgml
new file mode 100644 (file)
index 0000000..dfdb6c8
--- /dev/null
@@ -0,0 +1,67 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+
+ <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/engine.fig b/doc/design/engine.fig
new file mode 100644 (file)
index 0000000..90f3d4f
--- /dev/null
@@ -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 (file)
index 0000000..1e0112a
Binary files /dev/null and b/doc/design/engine.jpg differ
diff --git a/doc/design/engine.sgml b/doc/design/engine.sgml
new file mode 100644 (file)
index 0000000..3bb636b
--- /dev/null
@@ -0,0 +1,1888 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+
+<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>
+
+<REMARK>
+In the current source code, I implemented this as a dictionary attribute
+named <literal>Dictionary</literal>.  While reasonably Pythonic, this
+is ultimately Not Good.  We don't want people using a reference to the
+dictionary to change construction variables out from under an existing
+environment.  We should use an internal <literal>_dict</literal>
+attribute and control access to it through a method, as specified above.
+</REMARK>
+
+  <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>
+
+<REMARK>
+&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?
+</REMARK>
+
+ <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:
+
+ <REMARK>
+ LIST THESE ONCE WE FIGURE OUT WHAT THEY ARE FROM CODING THEM.
+ </REMARK>
+
+  </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',
+                       input_suffix = '.in',
+                       output_suffix = '.html')
+       </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,
+                       input_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',
+                       input_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>
+
+ <REMARK>
+ NEED AN EXAMPLE HERE.
+ </REMARK>
+
+  <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',
+                       input_suffix = '.in',
+                       output_suffix = '.html')
+       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
+   the expected suffixes of input files for this object.  It may also
+   be initialized with an output suffix for the files that this
+   &Builder; object builds.  These arguments are used in automatic
+   dependency analysis and in generating 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(output_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>
+
+<REMARK>
+Do we even need this anymore?
+Now that the individual builders
+have specified <literal>input_suffix</literal>
+and <literal>output_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...
+</REMARK>
+
+  <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>
+
+<REMARK>
+If the &BUILDERMAP; proves unnecessary,
+we could/should get rid of this one, too,
+by adding a parallel <literal>input_suffix</literal>
+argument to the &Scanner; factory...
+Comments?
+</REMARK>
+
+  <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 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>
+
+<REMARK>
+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...
+</REMARK>
+
+ <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>
+
+<REMARK>
+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?
+</REMARK>
+
+<REMARK>
+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...
+</REMARK>
+
+ <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>
+
+<REMARK>
+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?
+</REMARK>
+
+ <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>
+
+<REMARK>
+There should be extensions to this part of the API for
+auxiliary functions like cleaning the cache.
+</REMARK>
+
+ <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>
+
+<REMARK>
+This has been completely superseded by
+the more sophisticated &Task; manager
+that Anthony Roach has contributed.
+I need to write that up...
+</REMARK>
+
+ <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.sgml b/doc/design/goals.sgml
new file mode 100644 (file)
index 0000000..d894fe7
--- /dev/null
@@ -0,0 +1,189 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+
+ <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>
+
+<REMARK>
+To be written.
+</REMARK>
+
+</section>
+
+<section id="sect-fix-cons">
+ <title>Fixing &Cons;'s problems</title>
+
+<REMARK>
+To be written.
+</REMARK>
+
+</section>
diff --git a/doc/design/install.sgml b/doc/design/install.sgml
new file mode 100644 (file)
index 0000000..4d03d11
--- /dev/null
@@ -0,0 +1,9 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+
+<REMARK>
+THIS CHAPTER NEEDS TO BE DISCUSSED AND WRITTEN.
+</REMARK>
diff --git a/doc/design/intro.sgml b/doc/design/intro.sgml
new file mode 100644 (file)
index 0000000..1d80849
--- /dev/null
@@ -0,0 +1,92 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+
+ <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>
+
+<REMARK>
+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.
+</REMARK>
+
+</section>
diff --git a/doc/design/issues.sgml b/doc/design/issues.sgml
new file mode 100644 (file)
index 0000000..6772c83
--- /dev/null
@@ -0,0 +1,176 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+ <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.sgml b/doc/design/main.sgml
new file mode 100644 (file)
index 0000000..745d473
--- /dev/null
@@ -0,0 +1,117 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+
+<!doctype book PUBLIC "-//OASIS//DTD DocBook V4.1//EN"
+[
+
+    <!ENTITY % version SYSTEM "../version.sgml">
+    %version;
+
+    <!ENTITY % scons SYSTEM "../scons.mod">
+    %scons;
+
+    <!ENTITY acks SYSTEM "acks.sgml">
+    <!ENTITY bground SYSTEM "bground.sgml">
+    <!ENTITY engine SYSTEM "engine.sgml">
+    <!ENTITY goals SYSTEM "goals.sgml">
+    <!ENTITY install SYSTEM "install.sgml">
+    <!ENTITY intro SYSTEM "intro.sgml">
+    <!ENTITY issues SYSTEM "issues.sgml">
+    <!ENTITY native SYSTEM "native.sgml">
+    <!ENTITY overview SYSTEM "overview.sgml">
+
+]>
+
+<book>
+  <bookinfo>
+    <title>SCons Design version &build_version;</title>
+
+    <author>
+      <firstname>Steven</firstname>
+      <surname>Knight</surname>
+    </author>
+
+    <edition>Revision &build_revision; (&build_date;)</edition>
+
+    <pubdate>2001</pubdate>
+
+    <copyright>
+      <year>2001</year>
+      <holder>Steven Knight</holder>
+    </copyright>
+
+    <legalnotice>
+      &copyright;
+    </legalnotice>
+
+    <releaseinfo>version &build_version;</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.sgml b/doc/design/native.sgml
new file mode 100644 (file)
index 0000000..c9fd4bf
--- /dev/null
@@ -0,0 +1,343 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+
+<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 reads a configuration file named
+  &SConstruct; in the current directory.  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>
+
+<REMARK>
+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>
+</REMARK>
+
+ <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>
+
+<REMARK>
+These need to be specified and explained
+beyond what the man page will have.
+</REMARK>
+
+  <!-- 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.sgml b/doc/design/overview.sgml
new file mode 100644 (file)
index 0000000..51b473e
--- /dev/null
@@ -0,0 +1,479 @@
+<!--
+
+  Copyright 2001 Steven Knight
+
+-->
+
+<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>
+
+<REMARK>
+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...
+</REMARK>
+
+   <!--
+   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/scons.mod b/doc/scons.mod
new file mode 100644 (file)
index 0000000..902149b
--- /dev/null
@@ -0,0 +1,129 @@
+<!--
+
+  An SCons-specific DTD module, for use with SCons DocBook
+  documentation, that contains names, phrases, acronyms, etc. used
+  throughout the SCons documentation.
+
+-->
+
+
+
+<!ENTITY copyright SYSTEM "copyright.sgml">
+
+
+
+<!--
+
+  Other applications that we reference.
+
+-->
+
+<!ENTITY Autoconf "<application>Autoconf</application>">
+<!ENTITY Cons "<application>Cons</application>">
+<!ENTITY Make "<application>Make</application>">
+<!ENTITY Makepp "<application>Make++</application>">
+<!ENTITY SCons "<application>SCons</application>">
+
+
+
+<!--
+
+  Classes.
+
+-->
+
+<!ENTITY Builder "<classname>Builder</classname>">
+<!ENTITY Job "<classname>Job</classname>">
+<!ENTITY Node "<classname>Node</classname>">
+<!ENTITY Scanner "<classname>Scanner</classname>">
+<!ENTITY Signature "<classname>Signature</classname>">
+
+
+
+<!--
+
+  File names.
+
+-->
+
+<!ENTITY Makefile "<filename>Makefile</filename>">
+<!ENTITY SConscript "<filename>SConscript</filename>">
+<!ENTITY SConstruct "<filename>SConstruct</filename>">
+<!ENTITY sconsign "<filename>.consign</filename>">
+
+
+
+<!--
+
+  Methods and functions.  This includes both functions from both
+  the Build Engine and the Native Python Interface.
+
+-->
+
+<!ENTITY Alias "<function>Alias</function>">
+<!ENTITY Aliases "<function>Aliases</function>">
+<!ENTITY Build "<function>Build</function>">
+<!ENTITY Clean "<function>Clean</function>">
+<!ENTITY Command "<function>Command</function>">
+<!ENTITY Copy "<function>Copy</function>">
+<!ENTITY Default "<function>Default</function>">
+<!ENTITY Environment "<function>Environment</function>">
+<!ENTITY Export "<function>Export</function>">
+<!ENTITY Help "<function>Help</function>">
+<!ENTITY Link "<function>Link</function>">
+<!ENTITY Local "<function>Local</function>">
+<!ENTITY Precious "<function>Precious</function>">
+<!ENTITY Repository "<function>Repository</function>">
+<!ENTITY Task "<function>Task</function>">
+
+
+
+<!--
+
+  Construction variables.
+
+-->
+
+<!ENTITY BUILDERMAP "<varname>BUILDERMAP</varname>">
+<!ENTITY BUILDERS "<varname>BUILDERMAP</varname>">
+<!ENTITY SCANNERMAP "<varname>SCANNERMAP</varname>">
+<!ENTITY SCANNERS "<varname>SCANNERMAP</varname>">
+
+
+
+<!--
+
+  Builder and Scanner objects.
+
+-->
+
+<!ENTITY Object "<function>Object</function>">
+<!ENTITY Library "<function>Library</function>">
+<!ENTITY SharedLibrary "<function>SharedLibrary</function>">
+<!ENTITY Program "<function>Program</function>">
+<!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 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 Dictionary "<literal>Dictionary</literal>">