diff options
author | Ludwig Hähne <pankrat@tigris.org> | 2008-08-22 15:36:49 (GMT) |
---|---|---|
committer | Ludwig Hähne <pankrat@tigris.org> | 2008-08-22 15:36:49 (GMT) |
commit | ffc8f5a6d801c346ef0c1cfcd5e155471aa54f77 (patch) | |
tree | 2fc648383abdc091c1814f3bcf900a40ffac3a87 /doc/user | |
parent | 05aba45c8e1878f2b5ef366fbc8d9da2567d4e55 (diff) | |
download | SCons-ffc8f5a6d801c346ef0c1cfcd5e155471aa54f77.zip SCons-ffc8f5a6d801c346ef0c1cfcd5e155471aa54f77.tar.gz SCons-ffc8f5a6d801c346ef0c1cfcd5e155471aa54f77.tar.bz2 |
Issue 1984: Documentation for ParseDepends
Diffstat (limited to 'doc/user')
-rw-r--r-- | doc/user/depends.in | 176 | ||||
-rw-r--r-- | doc/user/depends.xml | 142 |
2 files changed, 317 insertions, 1 deletions
diff --git a/doc/user/depends.in b/doc/user/depends.in index e861cbe..1309807 100644 --- a/doc/user/depends.in +++ b/doc/user/depends.in @@ -1267,6 +1267,182 @@ </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 <foo.h> + #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 <foo.h> + #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 <foo.h> + #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> diff --git a/doc/user/depends.xml b/doc/user/depends.xml index b19b4b2..61d2579 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -1270,6 +1270,146 @@ </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 <foo.h> + #include FOO_HEADER + + int main() { + return FOO; + } + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -I. hello.c + cc -o hello hello.o + % <userinput>edit foo.h</userinput> + [CHANGE CONTENTS OF foo.h] + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + </screen> + + <para> + + Apparently, the scanner does not know about the header dependency. + Being not a full-fledged C preprocessor, the scanner does not + expand the macro. + + </para> + + <para> + + In these cases, you may also use the compiler to extract the + implicit dependencies. &ParseDepends; can parse the contents of + the compiler output in the style of &Make;, and explicitly + establish all of the listed dependencies. + + </para> + + <para> + + The following example uses &ParseDepends; to process a compiler + generated dependency file which is generated as a side effect + during compilation of the object file: + + </para> + + <!-- XXX The ParseDepends example below fakes proper working by a + priori specification of the dependency file. The produced hello.d + file is not found (or used) for unknown reasons. --> + + <programlisting> + obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.') + SideEffect('hello.d', obj) + ParseDepends('hello.d') + Program('hello', obj) + </programlisting> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -MD -MF hello.d -I. hello.c + cc -o hello hello.o + % <userinput>edit foo.h</userinput> + [CHANGE CONTENTS OF foo.h] + % <userinput>scons -Q</userinput> + cc -o hello.o -c -MD -MF hello.d -I. hello.c + </screen> + + <para> + + Parsing dependencies from a compiler-generated + <filename>.d</filename> file has a chicken-and-egg problem, that + causes unnecessary rebuilds: + + </para> + + + + <!-- + <scons_output example="parsedeprebuild" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + --> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c -MD -MF hello.d -I. hello.c + cc -o hello hello.o + % <userinput>scons -Q --debug=explain</userinput> + scons: rebuilding `hello.o' because `foo.h' is a new dependency + cc -o hello.o -c -MD -MF hello.d -I. hello.c + % <userinput>scons -Q</userinput> + scons: `.' is up to date. + </screen> + + <para> + + In the first pass, the dependency file is generated while the + object file is compiled. At that time, &SCons; does not know about + the dependency on <filename>foo.h</filename>. In the second pass, + the object file is regenerated because <filename>foo.h</filename> + is detected as a new dependency. + + </para> + + <para> + + &ParseDepends; immediately reads the specified file at invocation + time and just returns if the file does not exist. A dependency + file generated during the build process is not automatically + parsed again. Hence, the compiler-extracted dependencies are not + stored in the signature database during the same build pass. This + limitation of &ParseDepends; leads to unnecessary recompilations. + Therefore, &ParseDepends; should only be used if scanners are not + available for the employed language or not powerful enough for the + specific task. + + </para> + + </section> + + <section> <title>Ignoring Dependencies: the &Ignore; Function</title> <para> @@ -1492,7 +1632,7 @@ 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> |