Fix the Requires() examples by adding a sleep command to the
[scons.git] / doc / user / depends.in
index 0262924593b30fc60df6bdb56693244c2ac6e7c2..8ba05048affde3b379e687eb68d4d7bda9606bb1 100644 (file)
   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
--->
-
-<!--
-
-=head2 The C<Salt> method
-
-The C<Salt> method adds a constant value to the signature calculation
-for every derived file.  It is invoked as follows:
-
-  Salt $string;
-
-Changing the Salt value will force a complete rebuild of every derived
-file.  This can be used to force rebuilds in certain desired
-circumstances.  For example,
-
-  Salt `uname -s`;
-
-Would force a complete rebuild of every derived file whenever the
-operating system on which the build is performed (as reported by C<uname
--s>) changes.
-
 -->
 
   <para>
 
   So far we've seen how &SCons; handles one-time builds.
-  But the real point of a build tool like &SCons;
-  is to rebuild only the necessary things
+  But one of the main functions of a build tool like &SCons;
+  is to rebuild only what is necessary
   when source files change--or, put another way,
   &SCons; should <emphasis>not</emphasis>
-  waste time rebuilding things that have already been built.
-  You can see this at work simply be re-invoking &SCons;
+  waste time rebuilding things that don't need to be rebuilt.
+  You can see this at work simply by re-invoking &SCons;
   after building our simple &hello; example:
 
   </para>
@@ -96,33 +75,36 @@ operating system on which the build is performed (as reported by C<uname
   </para>
 
   <section>
-  <title>Deciding When a Source File Has Changed:  the &SourceSignatures; Function</title>
+  <title>Deciding When an Input File Has Changed:  the &Decider; Function</title>
 
     <para>
 
-    The other side of avoiding unnecessary rebuilds
+    Another aspect of avoiding unnecessary rebuilds
     is the fundamental build tool behavior
     of <emphasis>rebuilding</emphasis>
-    things when a source file changes,
+    things when an input file changes,
     so that the built software is up to date.
-    &SCons; keeps track of this through a
-    &signature; for each source file,
-    and allows you to configure
-    whether you want to use the source
-    file contents or the modification time (timestamp)
-    as the signature.
+    By default,
+    &SCons; keeps track of this through an
+    MD5 &signature;, or checksum, of the contents of each file,
+    although you can easily configure
+    &SCons; to use the
+    modification times (or time stamps)
+    instead.
+    You can even specify your own Python function
+    for deciding if an input file has changed.
 
     </para>
 
     <section>
-    <title>MD5 Source File Signatures</title>
+    <title>Using MD5 Signatures to Decide if a File Has Changed</title>
 
       <para>
 
       By default,
-      &SCons; keeps track of whether a source file has changed
-      based on the file's contents,
-      not the modification time.
+      &SCons; keeps track of whether a file has changed
+      based on an MD5 checksum of the file's contents,
+      not the file's modification time.
       This means that you may be surprised by the
       default &SCons; behavior if you are used to the
       &Make; convention of forcing
@@ -164,36 +146,110 @@ operating system on which the build is performed (as reported by C<uname
       Note that you can, if you wish,
       specify this default behavior
       (MD5 signatures) explicitly
-      using the &SourceSignatures; function as follows:
+      using the &Decider; function as follows:
 
       </para>
 
       <sconstruct>
         Program('hello.c')
-        SourceSignatures('MD5')
+        Decider('MD5')
       </sconstruct>
 
+      <para>
+
+      You can also use the string <literal>'content'</literal>
+      as a synonym for <literal>'MD5'</literal>
+      when calling the &Decider; function.
+
+      </para>
+
+      <section>
+      <title>Ramifications of Using MD5 Signatures</title>
+
+        <para>
+
+        Using MD5 signatures to decide if an input file has changed
+        has one surprising benefit:
+        if a source file has been changed
+        in such a way that the contents of the
+        rebuilt target file(s)
+        will be exactly the same as the last time
+        the file was built,
+        then any "downstream" target files
+        that depend on the rebuilt-but-not-changed target
+        file actually need not be rebuilt.
+
+        </para>
+
+        <para>
+
+        So if, for example,
+        a user were to only change a comment in a &hello_c; file,
+        then the rebuilt &hello_o; file
+        would be exactly the same as the one previously built
+        (assuming the compiler doesn't put any build-specific
+        information in the object file).
+        &SCons; would then realize that it would not
+        need to rebuild the &hello; program as follows:
+
+        </para>
+
+        <scons_output example="ex1" os="posix">
+           <scons_output_command>scons -Q hello</scons_output_command>
+           <scons_output_command output="  [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command>
+           <scons_output_command>scons -Q hello</scons_output_command>
+        </scons_output>
+
+        <para>
+
+        In essence, &SCons;
+        "short-circuits" any dependent builds
+        when it realizes that a target file
+        has been rebuilt to exactly the same file as the last build.
+        This does take some extra processing time
+        to read the contents of the target (&hello_o;) file,
+        but often saves time when the rebuild that was avoided
+        would have been time-consuming and expensive.
+
+        </para>
+
+      </section>
+
     </section>
 
     <section>
-    <title>Source File Time Stamps</title>
+    <title>Using Time Stamps to Decide If a File Has Changed</title>
 
       <para>
 
       If you prefer, you can
       configure &SCons; to use the modification time
-      of source files,
-      not the file contents,
-      when deciding if something needs to be rebuilt.
-      To do this, call the &SourceSignatures;
+      of a file, not the file contents,
+      when deciding if a target needs to be rebuilt.
+      &SCons; gives you two ways to use time stamps
+      to decide if an input file has changed
+      since the last time a target has been built.
+
+      </para>
+
+      <para>
+
+      The most familiar way to use time stamps
+      is the way &Make; does:
+      that is, have &SCons; decide
+      that a target must be rebuilt
+      if a source file's modification time is
+      <emphasis>newer</emphasis>
+      than the target file.
+      To do this, call the &Decider;
       function as follows:
 
       </para>
 
-      <scons_example name="ex2">
+      <scons_example name="newer">
         <file name="SConstruct" printme="1">
         Program('hello.c')
-        SourceSignatures('timestamp')
+        Decider('timestamp-newer')
         </file>
         <file name="hello.c">
         int main() { printf("Hello, world!\n"); }
@@ -208,117 +264,245 @@ operating system on which the build is performed (as reported by C<uname
 
       </para>
 
-      <scons_output example="ex2" os="posix">
+      <scons_output example="newer" os="posix">
          <scons_output_command>scons -Q hello</scons_output_command>
          <scons_output_command>touch hello.c</scons_output_command>
          <scons_output_command>scons -Q hello</scons_output_command>
       </scons_output>
 
-    </section>
+      <para>
 
-  </section>
+      And, in fact, because this behavior is the same
+      as the behavior of &Make;,
+      you can also use the string <literal>'make'</literal>
+      as a synonym for <literal>'timestamp-newer'</literal>
+      when calling the &Decider; function:
 
-  <section>
-  <title>Deciding When a Target File Has Changed:  the &TargetSignatures; Function</title>
+      </para>
 
-    <para>
+      <sconstruct>
+        Program('hello.c')
+        Decider('make')
+      </sconstruct>
 
-    As you've just seen,
-    &SCons; uses signatures to decide whether a 
-    target file is up to date or must be rebuilt.
-    When a target file depends on another target file,
-    &SCons; allows you to configure separately
-    how the signatures of "intermediate" target files
-    are used when deciding if a dependent target file
-    must be rebuilt.
+      <para>
 
-    </para>
+      One drawback to using times stamps exactly like &Make;
+      is that if an input file's modification time suddenly
+      becomes <emphasis>older</emphasis> than a target file,
+      the target file will not be rebuilt.
+      This can happen if an old copy of a source file is restored
+      from a backup archive, for example.
+      The contents of the restored file will likely be different
+      than they were the last time a dependent target was built,
+      but the target won't be rebuilt
+      because the modification time of the source file
+      is not newer than the target.
 
-    <section>
-    <title>Build Signatures</title>
+      </para>
 
       <para>
 
-      Modifying a source file
-      will cause not only its direct target file to be rebuilt,
-      but also the target file(s)
-      that depend on that direct target file.
-      In our example,
-      changing the contents of the &hello_c; file causes
-      the &hello_o; file to be rebuilt,
-      which in turn causes the
-      &hello; program to be rebuilt:
+      Because &SCons; actually stores information
+      about the source files' time stamps whenever a target is built,
+      it can handle this situation by checking for
+      an exact match of the source file time stamp,
+      instead of just whether or not the source file
+      is newer than the target file.
+      To do this, specify the argument
+      <literal>'timestamp-match'</literal>
+      when calling the &Decider; function:
 
       </para>
 
-      <scons_output example="ex1" os="posix">
+      <scons_example name="match">
+        <file name="SConstruct" printme="1">
+        Program('hello.c')
+        Decider('timestamp-match')
+        </file>
+        <file name="hello.c">
+        int main() { printf("Hello, world!\n"); }
+        </file>
+      </scons_example>
+
+      <para>
+
+      When configured this way,
+      &SCons; will rebuild a target whenever
+      a source file's modification time has changed.
+      So if we use the <literal>touch -t</literal>
+      option to change the modification time of
+      &hello_c; to an old date (January 1, 1989),
+      &SCons; will still rebuild the target file:
+
+      </para>
+
+      <scons_output example="match" os="posix">
          <scons_output_command>scons -Q hello</scons_output_command>
-         <scons_output_command output="    [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
+         <scons_output_command>touch -t 198901010000 hello.c</scons_output_command>
          <scons_output_command>scons -Q hello</scons_output_command>
       </scons_output>
 
       <para>
 
-      What's not obvious, though,
-      is that &SCons; internally handles the signature of
-      the target file(s)
-      (&hello_o; in the above example)
-      differently from the signature of the source file
-      (&hello_c;).
-      By default,
-      &SCons; tracks whether a target file must be rebuilt
-      by using a &buildsignature;
-      that consists of the combined
-      signatures of all the files
-      that go into making the target file.
-      This is efficient because
-      the accumulated signatures
-      actually give &SCons; all of the
-      information it needs
-      to decide if the target file is out of date.
+      In general, the only reason to prefer
+      <literal>timestamp-newer</literal>
+      instead of
+      <literal>timestamp-match</literal>,
+      would be if you have some specific reason
+      to require this &Make;-like behavior of 
+      not rebuilding a target when an otherwise-modified
+      source file is older.
 
       </para>
 
+    </section>
+
+    <section>
+    <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title>
+
       <para>
 
-      If you wish, you can
-      specify this default behavior
-      (build signatures) explicitly
-      using the &TargetSignatures; function:
+      As a performance enhancement,
+      &SCons; provides a way to use
+      MD5 checksums of file contents
+      but to read those contents
+      only when the file's timestamp has changed.
+      To do this, call the &Decider;
+      function with <literal>'MD5-timestamp'</literal>
+      argument as follows:
 
       </para>
 
-      <sconstruct>
+      <scons_example name="MD5-timestamp">
+        <file name="SConstruct" printme="1">
         Program('hello.c')
-        TargetSignatures('build')
-      </sconstruct>
+        Decider('MD5-timestamp')
+        </file>
+        <file name="hello.c">
+        int main() { printf("Hello, world!\n"); }
+        </file>
+      </scons_example>
+
+      <para>
+
+      So configured, &SCons will still behave like
+      it does when using <literal>Decider('MD5')</literal>:
+
+      </para>
+
+      <!--
+
+      We want to generate the output as follows,
+      but our "surrogate" system for generating the
+      output seems to get this wrong.
+      Just in-line the output for now.
+
+      <scons_output example="MD5-timestamp" os="posix">
+         <scons_output_command>scons -Q hello</scons_output_command>
+         <scons_output_command>touch hello.c</scons_output_command>
+         <scons_output_command>scons -Q hello</scons_output_command>
+       <scons_output_command output="    [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
+         <scons_output_command>scons -Q hello</scons_output_command>
+      </scons_output>
+
+      -->
+
+      <screen>
+         % <userinput>scons -Q hello</userinput>
+         cc -o hello.o -c hello.c
+         cc -o hello hello.o
+         % <userinput>touch hello.c</userinput>
+         % <userinput>scons -Q hello</userinput>
+         scons: `hello' is up to date.
+         % <userinput>edit hello.c</userinput>
+             [CHANGE THE CONTENTS OF hello.c]
+         % <userinput>scons -Q hello</userinput>
+         cc -o hello.o -c hello.c
+         cc -o hello hello.o
+      </screen>
+
+      <para>
+
+      However, the second call to &SCons; in the above output,
+      when the build is up-to-date,
+      will have been performed by simply looking at the
+      modification time of the &hello_c; file,
+      not by opening it and performing
+      an MD5 checksum calcuation on its contents.
+      This can significantly speed up many up-to-date builds.
+
+      </para>
+
+      <para>
+
+      The only drawback to using
+      <literal>Decider('MD5-timestamp')</literal>
+      is that &SCons; will <emphasis>not</emphasis>
+      rebuild a target file if a source file was modified
+      within one second of the last time &SCons; built the file.
+      While most developers are programming,
+      this isn't a problem in practice,
+      since it's unlikely that someone will have built
+      and then thought quickly enough to make a substantive
+      change to a source file within one second.
+      Certain build scripts or
+      continuous integration tools may, however,
+      rely on the ability to apply changes to files
+      automatically and then rebuild as quickly as possible,
+      in which case use of
+      <literal>Decider('MD5-timestamp')</literal>
+      may not be appropriate.
+
+      </para>
 
     </section>
 
     <section>
-    <title>File Contents</title>
+    <title>Writing Your Own Custom &Decider; Function</title>
+
+      <para>
+
+      The different string values that we've passed to
+      the &Decider; function are essentially used by &SCons;
+      to pick one of several specific internal functions
+      that implement various ways of deciding if a dependency
+      (usually a source file)
+      has changed since a target file has been built.
+      As it turns out,
+      you can also supply your own function
+      to decide if a dependency has changed.
+
+      </para>
 
       <para>
 
-      Sometimes a source file can be changed
-      in such a way that the contents of the
-      rebuilt target file(s)
-      will be exactly the same as the last time
-      the file was built.
-      If so, then any other target files
-      that depend on such a built-but-not-changed target
-      file actually need not be rebuilt.
-      You can make &SCons;
-      realize that it does not need to rebuild
-      a dependent target file in this situation
-      using the &TargetSignatures; function as follows:
+      For example, suppose we have an input file
+      that contains a lot of data,
+      in some specific regular format,
+      that is used to rebuild a lot of different target files,
+      but each target file really only depends on
+      one particular section of the input file.
+      We'd like to have each target file depend on
+      only its section of the input file.
+      However, since the input file may contain a lot of data,
+      we want to open the input file only if its timestamp has changed.
+      This could done with a custom
+      &Decider; function that might look something like this:
 
       </para>
 
-      <scons_example name="ex3">
+      <scons_example name="function">
         <file name="SConstruct" printme="1">
         Program('hello.c')
-        TargetSignatures('content')
+        def decide_if_changed(dependency, target, prev_ni):
+            if self.get_timestamp() != prev_ni.timestamp:
+                dep = str(dependency)
+                tgt = str(target)
+                if specific_part_of_file_has_changed(dep, tgt):
+                    return True
+            return False
+        Decider(decide_if_changed)
         </file>
         <file name="hello.c">
         int main() { printf("Hello, world!\n"); }
@@ -327,35 +511,348 @@ operating system on which the build is performed (as reported by C<uname
 
       <para>
 
-      So if, for example,
-      a user were to only change a comment in a C file,
-      then the rebuilt &hello_o; file
-      would be exactly the same as the one previously built
-      (assuming the compiler doesn't put any build-specific
-      information in the object file).
-      &SCons; would then realize that it would not
-      need to rebuild the &hello; program as follows:
+      Note that in the function definition,
+      the <varname>dependency</varname>
+      (input file) is the first argument,
+      and then the &target;.
+      Both of these are passed to the functions as
+      SCons &Node; objects,
+      which we convert to strings using the Python
+      <function>str()</function>.
 
       </para>
 
-      <scons_output example="ex3" os="posix">
-         <scons_output_command>scons -Q hello</scons_output_command>
-         <scons_output_command output="  [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command>
-         <scons_output_command>scons -Q hello</scons_output_command>
+      <para>
+
+      The third argument, <varname>prev_ni</varname>,
+      is an object that holds the
+      signature or timestamp information
+      that was recorded about the dependency
+      the last time the target was built.
+      A <varname>prev_ni</varname> object can hold
+      different information,
+      depending on the type of thing that the
+      <varname>dependency</varname> argument represents.
+      For normal files,
+      the <varname>prev_ni</varname> object
+      has the following attributes:
+
+      </para>
+
+      <variablelist>
+
+        <varlistentry>
+        <term>.csig</term>
+
+        <listitem>
+        <para>
+        The <emphasis>content signature</emphasis>,
+        or MD5 checksum, of the contents of the
+        <varname>dependency</varname>
+        file the list time the &target; was built.
+        </para>
+        </listitem>
+
+        </varlistentry>
+
+        <varlistentry>
+        <term>.size</term>
+
+        <listitem>
+        <para>
+        The size in bytes of the <varname>dependency</varname>
+        file the list time the target was built.
+        </para>
+        </listitem>
+
+        </varlistentry>
+
+        <varlistentry>
+        <term>.timestamp</term>
+
+        <listitem>
+        <para>
+        The modification time of the <varname>dependency</varname>
+        file the list time the &target; was built.
+        </para>
+        </listitem>
+
+        </varlistentry>
+
+      </variablelist>
+
+      <para>
+
+      Note that ignoring some of the arguments
+      in your custom &Decider; function
+      is a perfectly normal thing to do,
+      if they don't impact the way you want to
+      decide if the dependency file has changed.
+
+      </para>
+
+    </section>
+
+    <section>
+    <title>Mixing Different Ways of Deciding If a File Has Changed</title>
+
+      <para>
+
+      The previous examples have all demonstrated calling
+      the global &Decider; function
+      to configure all dependency decisions that &SCons; makes.
+      Sometimes, however, you want to be able to configure
+      different decision-making for different targets.
+      When that's necessary, you can use the
+      <function>env.Decider</function>
+      method to affect only the configuration
+      decisions for targets built with a
+      specific construction environment.
+
+      </para>
+
+      <para>
+
+      For example, if we arbitrarily want to build
+      one program using MD5 checkums
+      and another using file modification times
+      from the same source
+      we might configure it this way:
+
+      </para>
+
+      <scons_example name="mixing">
+        <file name="SConstruct" printme="1">
+        env1 = Environment(CPPPATH = ['.'])
+        env2 = env1.Clone()
+        env2.Decider('timestamp-match')
+        env1.Program('prog-MD5', 'program1.c')
+        env2.Program('prog-timestamp', 'program2.c')
+        </file>
+        <file name="program1.c">
+        #include "inc.h"
+        int main() { printf("Hello, world!\n"); }
+        </file>
+        <file name="program2.c">
+        #include "inc.h"
+        int main() { printf("Hello, world!\n"); }
+        </file>
+        <file name="inc.h">
+        #define INC     1
+        </file>
+      </scons_example>
+
+      <para>
+
+      If both of the programs include the same
+      <filename>inc.h</filename> file,
+      then updating the modification time of
+      <filename>inc.h</filename>
+      (using the &touch; command)
+      will cause only <filename>prog-timestamp</filename>
+      to be rebuilt:
+
+      </para>
+
+      <scons_output example="mixing" os="posix">
+         <scons_output_command>scons -Q</scons_output_command>
+         <scons_output_command>touch inc.h</scons_output_command>
+         <scons_output_command>scons -Q</scons_output_command>
       </scons_output>
 
+    </section>
+
+  </section>
+
+  <section>
+  <title>Older Functions for Deciding When an Input File Has Changed</title>
+
+    <para>
+
+    &SCons; still supports two functions that used to be the
+    primary methods for configuring the
+    decision about whether or not an input file has changed.
+    Although they're not officially deprecated yet,
+    their use is discouraged,
+    mainly because they rely on a somewhat
+    confusing distinction between how
+    source files and target files are handled.
+    These functions are documented here mainly in case you
+    encounter them in existing &SConscript; files.
+
+    </para>
+  
+    <section>
+    <title>The &SourceSignatures; Function</title>
+
+      <para>
+
+      The &SourceSignatures; function is fairly straightforward,
+      and supports two different argument values
+      to configure whether source file changes should be decided
+      using MD5 signatures:
+
+      </para>
+
+      <sconstruct>
+        Program('hello.c')
+        SourceSignatures('MD5')
+      </sconstruct>
+
+      <para>
+
+      Or using time stamps:
+
+      </para>
+
+      <sconstruct>
+        Program('hello.c')
+        SourceSignatures('timestamp')
+      </sconstruct>
+
+      <para>
+
+      These are roughly equivalent to specifying
+      <function>Decider('MD5')</function>
+      or
+      <function>Decider('timestamp-match')</function>,
+      respectively,
+      although it only affects how SCons makes
+      decisions about dependencies on
+      <emphasis>source</emphasis> files--that is,
+      files that are not built from any other files.
+
+      </para>
+
+    </section>
+
+    <section>
+    <title>The &TargetSignatures; Function</title>
+
+      <para>
+
+      The &TargetSignatures; function
+      specifies how &SCons; decides
+      when a target file has changed
+      <emphasis>when it is used as a
+      dependency of (input to) another target</emphasis>--that is,
+      the &TargetSignatures; function configures
+      how the signatures of "intermediate" target files
+      are used when deciding if a "downstream" target file
+      must be rebuilt.
+      <footnote><para>
+      This easily-overlooked distinction between
+      how &SCons; decides if the target itself must be rebuilt
+      and how the target is then used to decide if a different
+      target must be rebuilt is one of the confusing
+      things that has led to the &TargetSignatures;
+      and &SourceSignatures; functions being
+      replaced by the simpler &Decider; function.
+      </para></footnote>
+
+      </para>
+
+      <para>
+
+      The &TargetSignatures; function supports the same
+      <literal>'MD5'</literal> and <literal>'timestamp'</literal>
+      argument values that are supported by the &SourceSignatures;,
+      with the same meanings, but applied to target files.
+      That is, in the example:
+
+      </para>
+
+      <sconstruct>
+        Program('hello.c')
+        TargetSignatures('MD5')
+      </sconstruct>
+
+      <para>
+
+      The MD5 checksum of the &hello_o; target file
+      will be used to decide if it has changed since the last
+      time the "downstream" &hello; target file was built.
+      And in the example:
+      
+      </para>
+
+      <sconstruct>
+        Program('hello.c')
+        TargetSignatures('timestamp')
+      </sconstruct>
+
+      <para>
+
+      The modification time of the &hello_o; target file
+      will be used to decide if it has changed since the last
+      time the "downstream" &hello; target file was built.
+
+      </para>
+
+      <para>
+
+      The &TargetSignatures; function supports
+      two additional argument values:
+      <literal>'source'</literal> and <literal>'build'</literal>.
+      The <literal>'source'</literal> argument
+      specifies that decisions involving
+      whether target files have changed
+      since a previous build
+      should use the same behavior
+      for the decisions configured for source files
+      (using the &SourceSignatures; function).
+      So in the example:
+
+      </para>
+
+      <sconstruct>
+        Program('hello.c')
+        TargetSignatures('source')
+        SourceSignatures('timestamp')
+      </sconstruct>
+
+      <para>
+
+      All files, both targets and sources,
+      will use modification times
+      when deciding if an input file
+      has changed since the last
+      time a target was built.
+
+      </para>
+
+      <para>
+
+      Lastly, the <literal>'build'</literal> argument
+      specifies that &SCons; should examine
+      the build status of a target file
+      and always rebuild a "downstream" target
+      if the target file was itself rebuilt,
+      without re-examining the contents or timestamp
+      of the newly-built target file.
+      If the target file was not rebuilt during
+      this &scons; invocation,
+      then the target file will be examined
+      the same way as configured by
+      the &SourceSignature; call
+      to decide if it has changed.
+
+      </para>
+
       <para>
 
-      In essence, &SCons; has
-      "short-circuited" any dependent builds
-      when it realizes that a target file
-      has been rebuilt to exactly the same file as the last build.
-      So configured,
-      &SCons; does take some extra processing time
-      to scan the contents of the target (&hello_o;) file,
-      but this may save time
-      if the rebuild that was avoided
-      would have been very time-consuming and expensive.
+      This mimics the behavior of
+      <literal>build signatures</literal>
+      in earlier versions of &SCons;.
+      A &buildsignature; re-combined
+      signatures of all the input files
+      that went into making the target file,
+      so that the target file itself
+      did not need to have its contents read
+      to compute an MD5 signature.
+      This can improve performance for some configurations,
+      but is generally not as effective as using
+      <literal>Decider('MD5-timestamp')</literal>.
 
       </para>
 
@@ -369,12 +866,12 @@ operating system on which the build is performed (as reported by C<uname
     <para>
 
     Now suppose that our "Hello, World!" program
-    actually has a <literal>#include</literal> line
+    actually has an <literal>#include</literal> line
     to include the &hello_h; file in the compilation:
 
     </para>
 
-    <scons_example name="ex4">
+    <scons_example name="include">
       <file name="SConstruct">
        Program('hello.c', CPPPATH = '.')
       </file>
@@ -397,7 +894,7 @@ operating system on which the build is performed (as reported by C<uname
 
     </para>
 
-    <scons_example_file example="ex4"  name="hello.h">
+    <scons_example_file example="include"  name="hello.h">
     </scons_example_file>
 
     <para>
@@ -410,12 +907,12 @@ operating system on which the build is performed (as reported by C<uname
 
     </para>
 
-    <scons_example_file example="ex4"  name="SConstruct">
+    <scons_example_file example="include"  name="SConstruct">
     </scons_example_file>
 
     <para>
 
-    The &cv-CPPPATH; value
+    The &cv-link-CPPPATH; value
     tells &SCons; to look in the current directory
     (<literal>'.'</literal>)
     for any files included by C source files
@@ -424,7 +921,7 @@ operating system on which the build is performed (as reported by C<uname
 
     </para>
 
-    <scons_output example="ex4" os="posix">
+    <scons_output example="include" os="posix">
        <scons_output_command>scons -Q hello</scons_output_command>
        <scons_output_command>scons -Q hello</scons_output_command>
        <scons_output_command output="    [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
@@ -462,11 +959,11 @@ operating system on which the build is performed (as reported by C<uname
 
     <para>
 
-    Like the &cv-LIBPATH; variable,
+    Like the &cv-link-LIBPATH; variable,
     the &cv-CPPPATH; variable
     may be a list of directories,
     or a string separated by
-    the system-specific path separate character
+    the system-specific path separation character
     (':' on POSIX/Linux, ';' on Windows).
     Either way, &SCons; creates the
     right command-line options
@@ -572,22 +1069,46 @@ operating system on which the build is performed (as reported by C<uname
        SetOption('implicit_cache', 1)
     </sconstruct>
 
-    <!--
-
     <para>
-    
-    XXX
 
-    </para>
+    &SCons; does not cache implicit dependencies like this by default
+    because the &implicit-cache; causes &SCons; to simply use the implicit
+    dependencies stored during the last run, without any checking
+    for whether or not those dependencies are still correct.
+    Specifically, this means &implicit-cache; instructs &SCons;
+    to <emphasis>not</emphasis> rebuild "correctly" in the
+    following cases:
 
-    <para>
 
-    &SCons; does not cache implicit dependencies like this by default
-    because XXX
-    
     </para>
 
-    -->
+    <itemizedlist>
+
+      <listitem>
+        <para>
+
+        When &implicit-cache; is used, &SCons; will ignore any changes that
+        may have been made to search paths
+        (like &cv-CPPPATH; or &cv-LIBPATH;,).
+        This can lead to &SCons; not rebuilding a file if a change to
+        &cv-CPPPATH; would normally cause a different, same-named file from
+        a different directory to be used.
+
+        </para>
+      </listitem>
+
+      <listitem>
+        <para>
+
+        When &implicit-cache; is used, &SCons; will not detect if a
+        same-named file has been added to a directory that is earlier in
+        the search path than the directory in which the file was found
+        last time.
+
+        </para>
+      </listitem>
+
+    </itemizedlist>
 
     <section>
     <title>The &implicit-deps-changed; Option</title>
@@ -633,7 +1154,7 @@ operating system on which the build is performed (as reported by C<uname
       and re-scans the file for any updated
       implicit dependency information.
       Sometimes, however, you may want
-      to force &SCons; to use the cached implicit dependencies, 
+      to force &SCons; to use the cached implicit dependencies,
       even if the source files changed.
       This can speed up a build for example,
       when you have changed your source files
@@ -665,14 +1186,268 @@ operating system on which the build is performed (as reported by C<uname
 
     </section>
 
+    <!--
+
+    <section>
+    <title>XXX max drift</title>
+
+      XXX SetOption('max_drift')
+
+    </section>
+
+    -->
+
+  </section>
+
+  <section>
+  <title>Explicit Dependencies:  the &Depends; Function</title>
+
+    <para>
+
+    Sometimes a file depends on another file
+    that is not detected by an &SCons; scanner.
+    For this situation,
+    &SCons; allows you to specific explicitly that one file
+    depends on another file,
+    and must be rebuilt whenever that file changes.
+    This is specified using the &Depends; method:
+
+    </para>
+
+    <programlisting>
+       hello = Program('hello.c')
+       Depends(hello, 'other_file')
+    </programlisting>
+
+    <!-- XXX mention that you can use arrays for target and source? -->
+
+    <screen>
+       % <userinput>scons -Q hello</userinput>
+       cc -c hello.c -o hello.o
+       cc -o hello hello.o
+       % <userinput>scons -Q hello</userinput>
+       scons: `hello' is up to date.
+       % <userinput>edit other_file</userinput>
+           [CHANGE THE CONTENTS OF other_file]
+       % <userinput>scons -Q hello</userinput>
+       cc -c hello.c -o hello.o
+       cc -o hello hello.o
+    </screen>
+
+    <para>
+
+    Note that the dependency
+    (the second argument to &Depends;)
+    may also be a list of Node objects
+    (for example, as returned by a call to a Builder):
+
+    </para>
+
+    <programlisting>
+       hello = Program('hello.c')
+       goodbye = Program('goodbye.c')
+       Depends(hello, goodbye)
+    </programlisting>
+
+    <para>
+
+    in which case the dependency or dependencies
+    will be built before the target(s):
+
+    </para>
+
+    <screen>
+       % <userinput>scons -Q hello</userinput>
+       cc -c goodbye.c -o goodbye.o
+       cc -o goodbye goodbye.o
+       cc -c hello.c -o hello.o
+       cc -o hello hello.o
+    </screen>
+
   </section>
 
   <section>
-  <title>Ignoring Dependencies:  the &Ignore; Method</title>
+  <title>Dependencies From External Files:  the &ParseDepends;
+  Function</title>
 
     <para>
 
-    Sometimes it makes sense 
+    &SCons; has built-in scanners for a number of languages. Sometimes
+    these scanners fail to extract certain implicit dependencies due
+    to limitations of the scanner implementation.
+
+    </para>
+
+    <para>
+
+    The following example illustrates a case where the built-in C
+    scanner is unable to extract the implicit dependency on a header
+    file.
+
+    </para>
+
+    <scons_example name="macroinc">
+      <file name="hello.c" printme="1">
+      #define FOO_HEADER &lt;foo.h&gt;
+      #include FOO_HEADER
+
+      int main() {
+          return FOO;
+      }
+      </file>
+      <file name="SConstruct">
+      Program('hello', 'hello.c', CPPPATH='.')
+      </file>
+      <file name="foo.h">
+      #define FOO 42
+      </file>
+    </scons_example>
+
+    <scons_output example="macroinc" os="posix">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command output="   [CHANGE CONTENTS OF foo.h]"
+      >edit foo.h</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+    </scons_output>
+
+    <para>
+
+    Apparently, the scanner does not know about the header dependency.
+    Being not a full-fledged C preprocessor, the scanner does not
+    expand the macro.
+
+    </para>
+
+    <para>
+
+    In these cases, you may also use the compiler to extract the
+    implicit dependencies. &ParseDepends; can parse the contents of
+    the compiler output in the style of &Make;, and explicitly
+    establish all of the listed dependencies.
+
+    </para>
+
+    <para>
+
+    The following example uses &ParseDepends; to process a compiler
+    generated dependency file which is generated as a side effect
+    during compilation of the object file:
+
+    </para>
+
+    <!-- XXX The ParseDepends example below fakes proper working by a
+    priori specification of the dependency file. The produced hello.d
+    file is not found (or used) for unknown reasons. -->
+
+    <scons_example name="parsedep">
+      <file name="hello.c">
+      #define FOO_HEADER &lt;foo.h&gt;
+      #include FOO_HEADER
+
+      int main() {
+          return FOO;
+      }
+      </file>
+      <file name="SConstruct" printme="1">
+      obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
+      SideEffect('hello.d', obj)
+      ParseDepends('hello.d')
+      Program('hello', obj)
+      </file>
+      <file name="foo.h">
+      #define FOO 42
+      </file>
+      <file name="hello.d">
+      hello.o: hello.c foo.h
+      </file>
+    </scons_example>
+
+    <scons_output example="parsedep" os="posix">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command output="   [CHANGE CONTENTS OF foo.h]"
+      >edit foo.h</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+    </scons_output>
+
+    <para>
+
+    Parsing dependencies from a compiler-generated
+    <filename>.d</filename> file has a chicken-and-egg problem, that
+    causes unnecessary rebuilds:
+
+    </para>
+
+    <scons_example name="parsedeprebuild">
+      <file name="hello.c">
+      #define FOO_HEADER &lt;foo.h&gt;
+      #include FOO_HEADER
+
+      int main() {
+          return FOO;
+      }
+      </file>
+      <file name="SConstruct">
+      obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
+      SideEffect('hello.d', obj)
+      ParseDepends('hello.d')
+      Program('hello', obj)
+      </file>
+      <file name="foo.h">
+      #define FOO 42
+      </file>
+    </scons_example>
+
+    <!--
+    <scons_output example="parsedeprebuild" os="posix">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+    </scons_output>
+    -->
+
+    <screen>
+      % <userinput>scons -Q</userinput>
+      cc -o hello.o -c -MD -MF hello.d -I. hello.c
+      cc -o hello hello.o
+      % <userinput>scons -Q --debug=explain</userinput>
+      scons: rebuilding `hello.o' because `foo.h' is a new dependency
+      cc -o hello.o -c -MD -MF hello.d -I. hello.c
+      % <userinput>scons -Q</userinput>
+      scons: `.' is up to date.
+    </screen>
+
+    <para>
+
+    In the first pass, the dependency file is generated while the
+    object file is compiled. At that time, &SCons; does not know about
+    the dependency on <filename>foo.h</filename>. In the second pass,
+    the object file is regenerated because <filename>foo.h</filename>
+    is detected as a new dependency.
+
+    </para>
+
+    <para>
+
+    &ParseDepends; immediately reads the specified file at invocation
+    time and just returns if the file does not exist. A dependency
+    file generated during the build process is not automatically
+    parsed again. Hence, the compiler-extracted dependencies are not
+    stored in the signature database during the same build pass. This
+    limitation of &ParseDepends; leads to unnecessary recompilations.
+    Therefore, &ParseDepends; should only be used if scanners are not
+    available for the employed language or not powerful enough for the
+    specific task.
+
+    </para>
+
+  </section>
+
+  <section>
+  <title>Ignoring Dependencies:  the &Ignore; Function</title>
+
+    <para>
+
+    Sometimes it makes sense
     to not rebuild a program,
     even if a dependency file changes.
     In this case,
@@ -683,11 +1458,12 @@ operating system on which the build is performed (as reported by C<uname
 
     <scons_example name="ignore">
       <file name="SConstruct" printme="1">
-      hello = Program('hello.c')
-      Ignore(hello, 'hello.h')
+      hello_obj=Object('hello.c')
+      hello = Program(hello_obj)
+      Ignore(hello_obj, 'hello.h')
       </file>
       <file name="hello.c">
-      #include "hello.h" 
+      #include "hello.h"
       int main() { printf("Hello, %s!\n", string); }
       </file>
       <file name="hello.h">
@@ -695,7 +1471,7 @@ operating system on which the build is performed (as reported by C<uname
       </file>
     </scons_example>
 
-    <!-- XXX mention that you can use arrays for target and source? -->
+    <!-- XXX mention that you can use lists for target and source? -->
 
     <!--
     <scons_output example="ignore">
@@ -723,7 +1499,7 @@ operating system on which the build is performed (as reported by C<uname
 
     Now, the above example is a little contrived,
     because it's hard to imagine a real-world situation
-    where you wouldn't to rebuild &hello;
+    where you wouldn't want to rebuild &hello;
     if the &hello_h; file changed.
     A more realistic example
     might be if the &hello;
@@ -741,58 +1517,299 @@ operating system on which the build is performed (as reported by C<uname
     </para>
 
     <programlisting>
-       hello = Program('hello.c')
+       hello = Program('hello.c', CPPPATH=['/usr/include'])
        Ignore(hello, '/usr/include/stdio.h')
     </programlisting>
 
+    <para>
+    &Ignore; can also be used to prevent a generated file from being built 
+    by default. This is due to the fact that directories depend on 
+    their contents.  So to ignore a generated file from the default build, 
+    you specify that the directory should ignore the generated file.
+    Note that the file will still be built if the user specifically 
+    requests the target on scons command line, or if the file is
+    a dependency of another file which is requested and/or is built
+    by default.
+    </para>
+
+    <scons_example name="ignore_explicit">
+      <file name="SConstruct" printme="1">
+      hello_obj=Object('hello.c')
+      hello = Program(hello_obj)
+      Ignore('.',[hello,hello_obj])
+      </file>
+      <file name="hello.c">
+      #include "stdio.h"
+      int main() { printf("Hello!\n"); }
+      </file>
+    </scons_example>
+
+    <scons_output example="ignore_explicit" os="posix">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command>scons -Q hello</scons_output_command>
+      <scons_output_command>scons -Q hello</scons_output_command>
+    </scons_output>
   </section>
 
   <section>
-  <title>Explicit Dependencies:  the &Depends; Method</title>
+  <title>Order-Only Dependencies:  the &Requires; Function</title>
 
     <para>
 
-    On the other hand,
-    sometimes a file depends on another file
-    that is not detected by an &SCons; scanner.
-    For this situation,
-    &SCons; allows you to specific explicitly that one file
-    depends on another file,
-    and must be rebuilt whenever that file changes.
-    This is specified using the &Depends; method:
+    Occasionally,
+    it may be useful to specify that a certain
+    file or directory must, if necessary,
+    be built or created before some other target is built,
+    but that changes to that file or directory
+    do <emphasis>not</emphasis>
+    require that the target itself be rebuilt.
+    Such a relationship is called an
+    <emphasis>order-only dependency</emphasis>
+    because it only affects the order in which
+    things must be built--the dependency before the target--but
+    it is not a strict dependency relationship
+    because the target should not
+    change in response to changes in the dependent file.
 
     </para>
 
-    <programlisting>
-       hello = Program('hello.c')
-       Depends(hello, 'other_file')
-    </programlisting>
+    <para>
 
-    <!-- XXX mention that you can use arrays for target and source? -->
+    For example, suppose that you want to create a file
+    every time you run a build
+    that identifies the time the build was performed,
+    the version number, etc.,
+    and which is included in every program that you build.
+    The version file's contents will change every build.
+    If you specify a normal dependency relationship,
+    then every program that depends on
+    that file would be rebuilt every time you ran &SCons;.
+    For example, we could use some Python code in
+    a &SConstruct; file to create a new <filename>version.c</filename> file
+    with a string containing the current date every time
+    we run &SCons;,
+    and then link a program with the resulting object file
+    by listing <filename>version.c</filename> in the sources:
 
-    <screen>
-       % <userinput>scons -Q hello</userinput>
-       cc -c hello.c -o hello.o
-       cc -o hello hello.o
-       % <userinput>scons -Q hello</userinput>
-       scons: `hello' is up to date.
-       % <userinput>edit other_file</userinput>
-           [CHANGE THE CONTENTS OF other_file]
-       % <userinput>scons -Q hello</userinput>
-       cc -c hello.c -o hello.o
-       cc -o hello hello.o
-    </screen>
+    </para>
+
+    <scons_example name="no-Requires">
+      <file name="SConstruct" printme="1">
+      import time
+
+      version_c_text = """
+      char *date = "%s";
+      """ % time.ctime(time.time())
+      open('version.c', 'w').write(version_c_text)
+
+      hello = Program(['hello.c', 'version.c'])
+      </file>
+      <file name="hello.c">
+      extern char *date;
+      int main() { printf("Hello, %s!  I was built: %s\n", date); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    If we list <filename>version.c</filename> as an actual source file,
+    though, then the <filename>version.o</filename> file
+    will get rebuilt every time we run &SCons;
+    (because the &SConstruct; file itself changes
+    the contents of <filename>version.c</filename>)
+    and the <filename>hello</filename> executable
+    will get re-linked every time
+    (because the <filename>version.o</filename> file changes):
+
+    </para>
+
+    <scons_output example="no-Requires">
+      <scons_output_command>scons -Q hello</scons_output_command>
+      <scons_output_command>sleep 1</scons_output_command>
+      <scons_output_command>scons -Q hello</scons_output_command>
+      <scons_output_command>sleep 1</scons_output_command>
+      <scons_output_command>scons -Q hello</scons_output_command>
+    </scons_output>
+
+    <para>
+
+    (Note that for the above example to work,
+    we &sleep; for one second in between each run,
+    so that the &SConstruct; file will create a
+    <filename>version.c</filename> file with a time string
+    that's one second later than the previous run.)
+
+    </para>
+
+    <para>
+
+    One solution is to use the &Requires; function
+    to specify that the <filename>version.o</filename>
+    must be rebuilt before it is used by the link step,
+    but that changes to <filename>version.o</filename>
+    should not actually cause the <filename>hello</filename>
+    executable to be re-linked:
+
+    </para>
+
+    <scons_example name="Requires">
+      <file name="SConstruct" printme="1">
+      import time
+
+      version_c_text = """
+      char *date = "%s";
+      """ % time.ctime(time.time())
+      open('version.c', 'w').write(version_c_text)
+
+      version_obj = Object('version.c')
+
+      hello = Program('hello.c',
+                      LINKFLAGS = str(version_obj[0]))
+
+      Requires(hello, version_obj)
+      </file>
+      <file name="hello.c">
+      extern char *date;
+      int main() { printf("Hello, %s!  I was built: %s\n", date); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    Notice that because we can no longer list <filename>version.c</filename>
+    as one of the sources for the <filename>hello</filename> program,
+    we have to find some other way to get it into the link command line.
+    For this example, we're cheating a bit and stuffing the
+    object file name (extracted from <literal>version_obj</literal>
+    list returned by the &b-Object; call)
+    into the &cv-link-LINKFLAGS; variable,
+    because &cv-LINKFLAGS; is already included
+    in the &cv-link-LINKCOM; command line.
+
+    </para>
+
+    <para>
+
+    With these changes,
+    we get the desired behavior of only
+    re-linking the <filename>hello</filename> executable
+    when the <filename>hello.c</filename> has changed,
+    even though the <filename>version.o</filename> is rebuilt
+    (because the &SConstruct; file still changes the
+    <filename>version.c</filename> contents directly each run):
+
+    </para>
+
+    <scons_output example="Requires">
+      <scons_output_command>scons -Q hello</scons_output_command>
+      <scons_output_command>sleep 1</scons_output_command>
+      <scons_output_command>scons -Q hello</scons_output_command>
+      <scons_output_command>sleep 1</scons_output_command>
+      <scons_output_command output="    [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
+      <scons_output_command>scons -Q hello</scons_output_command>
+      <scons_output_command>sleep 1</scons_output_command>
+      <scons_output_command>scons -Q hello</scons_output_command>
+    </scons_output>
 
   </section>
 
-  <!-->
+  <section>
+  <title>The &AlwaysBuild; Function</title>
+
+    <para>
+
+    How &SCons; handles dependencies can also be affected
+    by the &AlwaysBuild; method.
+    When a file is passed to the &AlwaysBuild; method,
+    like so:
+
+    </para>
+
+    <scons_example name="AlwaysBuild">
+      <file name="SConstruct" printme="1">
+      hello = Program('hello.c')
+      AlwaysBuild(hello)
+      </file>
+      <file name="hello.c">
+      int main() { printf("Hello, %s!\n", string); }
+      </file>
+    </scons_example>
+
+    <para>
+
+    Then the specified target file (&hello; in our example)
+    will always be considered out-of-date and
+    rebuilt whenever that target file is evaluated
+    while walking the dependency graph:
+
+    </para>
+
+    <scons_output example="AlwaysBuild">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+    </scons_output>
+
+    <para>
+
+    The &AlwaysBuild; function has a somewhat misleading name,
+    because it does not actually mean the target file will
+    be rebuilt every single time &SCons; is invoked.
+    Instead, it means that the target will, in fact,
+    be rebuilt whenever the target file is encountered
+    while evaluating the targets specified on
+    the command line (and their dependencies).
+    So specifying some other target on the command line,
+    a target that does <emphasis>not</emphasis>
+    itself depend on the &AlwaysBuild; target,
+    will still be rebuilt only if it's out-of-date
+    with respect to its dependencies:
+
+    </para>
+
+    <scons_output example="AlwaysBuild">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command>scons -Q hello.o</scons_output_command>
+    </scons_output>
+
+    <!--
+
+      XXX AlwaysBuild() and Alias Nodes
+
+      XXX AlwaysBuild() and Dir Nodes
+
+      XXX AlwaysBuild() with no sources
+
+    -->
+
+  </section>
+
+  <!--
 
   <section>
   <title>The &Salt; Method</title>
 
     <para>
 
-    XXX
+    XXX Salt() (are we going to implement this ?)
+
+        original Cons classic POD documentation:
+
+=head2 The C<Salt> method
+
+The C<Salt> method adds a constant value to the signature calculation
+for every derived file.  It is invoked as follows:
+
+  Salt $string;
+
+Changing the Salt value will force a complete rebuild of every derived
+file.  This can be used to force rebuilds in certain desired
+circumstances.  For example,
+
+  Salt `uname -s`;
+
+Would force a complete rebuild of every derived file whenever the
+operating system on which the build is performed (as reported by C<uname
+-s>) changes.
 
     </para>