Issue 1984: Documentation for ParseDepends
authorpankrat <pankrat@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 22 Aug 2008 15:36:49 +0000 (15:36 +0000)
committerpankrat <pankrat@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 22 Aug 2008 15:36:49 +0000 (15:36 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@3296 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/scons.mod
doc/user/depends.in
doc/user/depends.xml

index deeee33296688266e886ed0ebe98140f5d656113..b924a249770c046883628d5bf4501a5357138e05 100644 (file)
 <!ENTITY PackageOption "<function>PackageOption</function>">
 <!ENTITY PackageVariable "<function>PackageVariable</function>">
 <!ENTITY ParseConfig "<function>ParseConfig</function>">
+<!ENTITY ParseDepends "<function>ParseDepends</function>">
 <!ENTITY ParseFlags "<function>ParseFlags</function>">
 <!ENTITY PathOption "<function>PathOption</function>">
 <!ENTITY PathOption_PathAccept "<function>PathOption.PathAccept</function>">
index e861cbe3d0d5538de0f429fb798d5b2c95b9ce92..13098079c6ddf696483df3efbb1624f10a863fd9 100644 (file)
 
   </section>
 
+  <section>
+  <title>Dependencies From External Files:  the &ParseDepends;
+  Function</title>
+
+    <para>
+
+    &SCons; has built-in scanners for a number of languages. Sometimes
+    these scanners fail to extract certain implicit dependencies due
+    to limitations of the scanner implementation.
+
+    </para>
+
+    <para>
+
+    The following example illustrates a case where the built-in C
+    scanner is unable to extract the implicit dependency on a header
+    file.
+
+    </para>
+
+    <scons_example name="macroinc">
+      <file name="hello.c" printme="1">
+      #define FOO_HEADER &lt;foo.h&gt;
+      #include FOO_HEADER
+
+      int main() {
+          return FOO;
+      }
+      </file>
+      <file name="SConstruct">
+      Program('hello', 'hello.c', CPPPATH='.')
+      </file>
+      <file name="foo.h">
+      #define FOO 42
+      </file>
+    </scons_example>
+
+    <scons_output example="macroinc" os="posix">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command output="   [CHANGE CONTENTS OF foo.h]"
+      >edit foo.h</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+    </scons_output>
+
+    <para>
+
+    Apparently, the scanner does not know about the header dependency.
+    Being not a full-fledged C preprocessor, the scanner does not
+    expand the macro.
+
+    </para>
+
+    <para>
+
+    In these cases, you may also use the compiler to extract the
+    implicit dependencies. &ParseDepends; can parse the contents of
+    the compiler output in the style of &Make;, and explicitly
+    establish all of the listed dependencies.
+
+    </para>
+
+    <para>
+
+    The following example uses &ParseDepends; to process a compiler
+    generated dependency file which is generated as a side effect
+    during compilation of the object file:
+
+    </para>
+
+    <!-- XXX The ParseDepends example below fakes proper working by a
+    priori specification of the dependency file. The produced hello.d
+    file is not found (or used) for unknown reasons. -->
+
+    <scons_example name="parsedep">
+      <file name="hello.c">
+      #define FOO_HEADER &lt;foo.h&gt;
+      #include FOO_HEADER
+
+      int main() {
+          return FOO;
+      }
+      </file>
+      <file name="SConstruct" printme="1">
+      obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
+      SideEffect('hello.d', obj)
+      ParseDepends('hello.d')
+      Program('hello', obj)
+      </file>
+      <file name="foo.h">
+      #define FOO 42
+      </file>
+      <file name="hello.d">
+      hello.o: hello.c foo.h
+      </file>
+    </scons_example>
+
+    <scons_output example="parsedep" os="posix">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command output="   [CHANGE CONTENTS OF foo.h]"
+      >edit foo.h</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+    </scons_output>
+
+    <para>
+
+    Parsing dependencies from a compiler-generated
+    <filename>.d</filename> file has a chicken-and-egg problem, that
+    causes unnecessary rebuilds:
+
+    </para>
+
+    <scons_example name="parsedeprebuild">
+      <file name="hello.c">
+      #define FOO_HEADER &lt;foo.h&gt;
+      #include FOO_HEADER
+
+      int main() {
+          return FOO;
+      }
+      </file>
+      <file name="SConstruct">
+      obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
+      SideEffect('hello.d', obj)
+      ParseDepends('hello.d')
+      Program('hello', obj)
+      </file>
+      <file name="foo.h">
+      #define FOO 42
+      </file>
+    </scons_example>
+
+    <!--
+    <scons_output example="parsedeprebuild" os="posix">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+    </scons_output>
+    -->
+
+    <screen>
+      % <userinput>scons -Q</userinput>
+      cc -o hello.o -c -MD -MF hello.d -I. hello.c
+      cc -o hello hello.o
+      % <userinput>scons -Q --debug=explain</userinput>
+      scons: rebuilding `hello.o' because `foo.h' is a new dependency
+      cc -o hello.o -c -MD -MF hello.d -I. hello.c
+      % <userinput>scons -Q</userinput>
+      scons: `.' is up to date.
+    </screen>
+
+    <para>
+
+    In the first pass, the dependency file is generated while the
+    object file is compiled. At that time, &SCons; does not know about
+    the dependency on <filename>foo.h</filename>. In the second pass,
+    the object file is regenerated because <filename>foo.h</filename>
+    is detected as a new dependency.
+
+    </para>
+
+    <para>
+
+    &ParseDepends; immediately reads the specified file at invocation
+    time and just returns if the file does not exist. A dependency
+    file generated during the build process is not automatically
+    parsed again. Hence, the compiler-extracted dependencies are not
+    stored in the signature database during the same build pass. This
+    limitation of &ParseDepends; leads to unnecessary recompilations.
+    Therefore, &ParseDepends; should only be used if scanners are not
+    available for the employed language or not powerful enough for the
+    specific task.
+
+    </para>
+
+  </section>
+
   <section>
   <title>Ignoring Dependencies:  the &Ignore; Function</title>
 
index b19b4b296f50f67bb6687fb14d72fc97367619e3..61d2579bd29c9889b51f029a809bd92daba31edd 100644 (file)
 
   </section>
 
+  <section>
+  <title>Dependencies From External Files:  the &ParseDepends;
+  Function</title>
+
+    <para>
+
+    &SCons; has built-in scanners for a number of languages. Sometimes
+    these scanners fail to extract certain implicit dependencies due
+    to limitations of the scanner implementation.
+
+    </para>
+
+    <para>
+
+    The following example illustrates a case where the built-in C
+    scanner is unable to extract the implicit dependency on a header
+    file.
+
+    </para>
+
+    <programlisting>
+      #define FOO_HEADER &lt;foo.h&gt;
+      #include FOO_HEADER
+
+      int main() {
+          return FOO;
+      }
+    </programlisting>
+
+    <screen>
+      % <userinput>scons -Q</userinput>
+      cc -o hello.o -c -I. hello.c
+      cc -o hello hello.o
+      % <userinput>edit foo.h</userinput>
+         [CHANGE CONTENTS OF foo.h]
+      % <userinput>scons -Q</userinput>
+      scons: `.' is up to date.
+    </screen>
+
+    <para>
+
+    Apparently, the scanner does not know about the header dependency.
+    Being not a full-fledged C preprocessor, the scanner does not
+    expand the macro.
+
+    </para>
+
+    <para>
+
+    In these cases, you may also use the compiler to extract the
+    implicit dependencies. &ParseDepends; can parse the contents of
+    the compiler output in the style of &Make;, and explicitly
+    establish all of the listed dependencies.
+
+    </para>
+
+    <para>
+
+    The following example uses &ParseDepends; to process a compiler
+    generated dependency file which is generated as a side effect
+    during compilation of the object file:
+
+    </para>
+
+    <!-- XXX The ParseDepends example below fakes proper working by a
+    priori specification of the dependency file. The produced hello.d
+    file is not found (or used) for unknown reasons. -->
+
+    <programlisting>
+      obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
+      SideEffect('hello.d', obj)
+      ParseDepends('hello.d')
+      Program('hello', obj)
+    </programlisting>
+
+    <screen>
+      % <userinput>scons -Q</userinput>
+      cc -o hello.o -c -MD -MF hello.d -I. hello.c
+      cc -o hello hello.o
+      % <userinput>edit foo.h</userinput>
+         [CHANGE CONTENTS OF foo.h]
+      % <userinput>scons -Q</userinput>
+      cc -o hello.o -c -MD -MF hello.d -I. hello.c
+    </screen>
+
+    <para>
+
+    Parsing dependencies from a compiler-generated
+    <filename>.d</filename> file has a chicken-and-egg problem, that
+    causes unnecessary rebuilds:
+
+    </para>
+
+    
+
+    <!--
+    <scons_output example="parsedeprebuild" os="posix">
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+      <scons_output_command>scons -Q</scons_output_command>
+    </scons_output>
+    -->
+
+    <screen>
+      % <userinput>scons -Q</userinput>
+      cc -o hello.o -c -MD -MF hello.d -I. hello.c
+      cc -o hello hello.o
+      % <userinput>scons -Q --debug=explain</userinput>
+      scons: rebuilding `hello.o' because `foo.h' is a new dependency
+      cc -o hello.o -c -MD -MF hello.d -I. hello.c
+      % <userinput>scons -Q</userinput>
+      scons: `.' is up to date.
+    </screen>
+
+    <para>
+
+    In the first pass, the dependency file is generated while the
+    object file is compiled. At that time, &SCons; does not know about
+    the dependency on <filename>foo.h</filename>. In the second pass,
+    the object file is regenerated because <filename>foo.h</filename>
+    is detected as a new dependency.
+
+    </para>
+
+    <para>
+
+    &ParseDepends; immediately reads the specified file at invocation
+    time and just returns if the file does not exist. A dependency
+    file generated during the build process is not automatically
+    parsed again. Hence, the compiler-extracted dependencies are not
+    stored in the signature database during the same build pass. This
+    limitation of &ParseDepends; leads to unnecessary recompilations.
+    Therefore, &ParseDepends; should only be used if scanners are not
+    available for the employed language or not powerful enough for the
+    specific task.
+
+    </para>
+
+  </section>
+
   <section>
   <title>Ignoring Dependencies:  the &Ignore; Function</title>
 
       cc -o hello.o -c hello.c
       cc -o hello version.o hello.o
       % <userinput>scons -Q</userinput>
-      scons: `.' is up to date.
+      cc -o version.o -c version.c
     </screen>
 
   </section>