[ci skip] update generated files
[scons.git] / doc / user / depends.xml
blobd4083535f666740b5239b76c04dd1b0a106161ac
1 <?xml version='1.0'?>
3 <!--
4 SPDX-FileCopyrightText: Copyright The SCons Foundation (https://scons.org)
5 SPDX-License-Identifier: MIT
6 SPDX-FileType: DOCUMENTATION
8 This file is processed by the bin/SConsDoc.py module.
9 -->
11 <!DOCTYPE sconsdoc [
12     <!ENTITY % scons SYSTEM "../scons.mod">
13     %scons;
15     <!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
16     %builders-mod;
17     <!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
18     %functions-mod;
19     <!ENTITY % tools-mod SYSTEM "../generated/tools.mod">
20     %tools-mod;
21     <!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
22     %variables-mod;
26 <chapter id="chap-depends"
27          xmlns="http://www.scons.org/dbxsd/v1.0"
28          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
29          xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
30 <title>Dependencies</title>
32 <para>
34   So far we've seen how &SCons; handles one-time builds.
35   But one of the main functions of a build tool like &SCons;
36   is to rebuild only what is necessary
37   when source files change--or, put another way,
38   &SCons; should <emphasis>not</emphasis>
39   waste time rebuilding things that don't need to be rebuilt.
40   You can see this at work simply by re-invoking &SCons;
41   after building our simple &hello; example:
43   </para>
45   <scons_example name="depends_ex1">
46     <file name="SConstruct">
47 Program('hello.c')
48     </file>
49     <file name="hello.c">
50 int main() { printf("Hello, world!\n"); }
51 </file>
52   </scons_example>
54   <scons_output example="depends_ex1" os="posix" suffix="1">
55      <scons_output_command>scons -Q</scons_output_command>
56      <scons_output_command>scons -Q</scons_output_command>
57   </scons_output>
59   <para>
61   The second time it is executed,
62   &SCons; realizes that the &hello; program
63   is up-to-date with respect to the current &hello_c; source file,
64   and avoids rebuilding it.
65   You can see this more clearly by naming
66   the &hello; program explicitly on the command line:
68   </para>
70   <scons_output example="depends_ex1" os="posix" suffix="2">
71      <scons_output_command>scons -Q hello</scons_output_command>
72      <scons_output_command>scons -Q hello</scons_output_command>
73   </scons_output>
75   <para>
77   Note that &SCons; reports <literal>"...is up to date"</literal>
78   only for target files named explicitly on the command line,
79   to avoid cluttering the output.
81   </para>
83   <section>
84   <title>Deciding When an Input File Has Changed:  the &Decider; Function</title>
86     <para>
88     Another aspect of avoiding unnecessary rebuilds
89     is the fundamental build tool behavior
90     of <emphasis>rebuilding</emphasis>
91     things when an input file changes,
92     so that the built software is up to date.
93     By default,
94     &SCons; keeps track of this through a
95     <firstterm>&contentsig;</firstterm>,
96     or hash, of the contents of each file,
97     although you can easily configure
98     &SCons; to use the
99     modification times (or time stamps) instead.
100     You can even write your own Python function
101     for deciding if an input file should trigger a rebuild.
103     </para>
105     <section>
106     <title>Using Content Signatures to Decide if a File Has Changed</title>
108       <para>
110       By default, &SCons;
111       uses a cryptographic hash of the file's contents,
112       not the file's modification time,
113       to decide whether a file has changed.
114       This means that you may be surprised by the
115       default &SCons; behavior if you are used to the
116       &Make; convention of forcing
117       a rebuild by updating the file's modification time
118       (using the &touch; command, for example):
120       </para>
122       <scons_output example="depends_ex1" os="posix" suffix="3">
123          <scons_output_command>scons -Q hello</scons_output_command>
124          <scons_output_command>touch hello.c</scons_output_command>
125          <scons_output_command>scons -Q hello</scons_output_command>
126       </scons_output>
128       <para>
130       Even though the file's modification time has changed,
131       &SCons; realizes that the contents of the
132       &hello_c; file have <emphasis>not</emphasis> changed,
133       and therefore that the &hello; program
134       need not be rebuilt.
135       This avoids unnecessary rebuilds when,
136       for example, someone rewrites the
137       contents of a file without making a change.
138       But if the contents of the file really do change,
139       then &SCons; detects the change
140       and rebuilds the program as required:
142       </para>
144       <scons_output example="depends_ex1" os="posix" suffix="4">
145          <scons_output_command>scons -Q hello</scons_output_command>
146          <scons_output_command output="    [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
147          <scons_output_command>scons -Q hello</scons_output_command>
148       </scons_output>
150       <para>
152       Note that you can, if you wish,
153       specify the default behavior of using
154       &contentsigs; explicitly,
155       using the &f-link-Decider; function as follows:
157       </para>
159       <sconstruct>
160 Program('hello.c')
161 Decider('content')
162       </sconstruct>
164       <para>
166       You can also use the string <literal>'MD5'</literal>
167       as a synonym for <literal>'content'</literal>
168       when calling the &f-Decider; function - this older
169       name is deprecated since &SCons; now supports a
170       choice of hash functions, not just the MD5 function.
172       </para>
174       <section>
175       <title>Ramifications of Using Content Signatures</title>
177         <para>
179         Using &contentsigs; to decide if an input file has changed
180         has one surprising benefit:
181         if a source file has been changed
182         in such a way that the contents of the
183         rebuilt target file(s)
184         will be exactly the same as the last time
185         the file was built,
186         then any "downstream" target files
187         that depend on the rebuilt-but-not-changed target
188         file actually need not be rebuilt.
190         </para>
192         <para>
194         So if, for example,
195         a user were to only change a comment in a &hello_c; file,
196         then the rebuilt &hello_o; file
197         would be exactly the same as the one previously built
198         (assuming the compiler doesn't put any build-specific
199         information in the object file).
200         &SCons; would then realize that it would not
201         need to rebuild the &hello; program as follows:
203         </para>
205         <scons_output example="depends_ex1" os="posix" suffix="5">
206            <scons_output_command>scons -Q hello</scons_output_command>
207            <scons_output_command output="  [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command>
208            <scons_output_command>scons -Q hello</scons_output_command>
209         </scons_output>
211         <para>
213         In essence, &SCons;
214         "short-circuits" any dependent builds
215         when it realizes that a target file
216         has been rebuilt to exactly the same file as the last build.
217         This does take some extra processing time
218         to read the contents of the target (&hello_o;) file,
219         but often saves time when the rebuild that was avoided
220         would have been time-consuming and expensive.
222         </para>
224       </section>
226     </section>
228     <section>
229     <title>Using Time Stamps to Decide If a File Has Changed</title>
231       <para>
233       If you prefer, you can
234       configure &SCons; to use the modification time
235       of a file, not the file contents,
236       when deciding if a target needs to be rebuilt.
237       &SCons; gives you two ways to use time stamps
238       to decide if an input file has changed
239       since the last time a target has been built.
241       </para>
243       <para>
245       The most familiar way to use time stamps
246       is the way &Make; does:
247       that is, have &SCons; decide
248       that a target must be rebuilt
249       if a source file's modification time is
250       <emphasis>newer</emphasis>
251       than the target file.
252       To do this, call the &f-link-Decider;
253       function as follows:
255       </para>
257       <scons_example name="depends_newer">
258         <file name="SConstruct" printme="1">
259 Object('hello.c')
260 Decider('timestamp-newer')
261         </file>
262         <file name="hello.c">
263 int main() { printf("Hello, world!\n"); }
264         </file>
265       </scons_example>
267       <para>
269       This makes &SCons; act like &Make;
270       when a file's modification time is updated
271       (using the &touch; command, for example):
273       </para>
275       <scons_output example="depends_newer" os="posix" suffix="1">
276          <scons_output_command>scons -Q hello.o</scons_output_command>
277          <scons_output_command>touch hello.c</scons_output_command>
278          <scons_output_command>scons -Q hello.o</scons_output_command>
279       </scons_output>
281       <para>
283       And, in fact, because this behavior is the same
284       as the behavior of &Make;,
285       you can also use the string <literal>'make'</literal>
286       as a synonym for <literal>'timestamp-newer'</literal>
287       when calling the &f-Decider; function:
289       </para>
291       <sconstruct>
292 Object('hello.c')
293 Decider('make')
294       </sconstruct>
296       <para>
298       One drawback to using times stamps exactly like &Make;
299       is that if an input file's modification time suddenly
300       becomes <emphasis>older</emphasis> than a target file,
301       the target file will not be rebuilt.
302       This can happen if an old copy of a source file is restored
303       from a backup archive, for example.
304       The contents of the restored file will likely be different
305       than they were the last time a dependent target was built,
306       but the target won't be rebuilt
307       because the modification time of the source file
308       is not newer than the target.
310       </para>
312       <para>
314       Because &SCons; actually stores information
315       about the source files' time stamps whenever a target is built,
316       it can handle this situation by checking for
317       an exact match of the source file time stamp,
318       instead of just whether or not the source file
319       is newer than the target file.
320       To do this, specify the argument
321       <literal>'timestamp-match'</literal>
322       when calling the &f-Decider; function:
324       </para>
326       <scons_example name="depends_match">
327         <file name="SConstruct" printme="1">
328 Object('hello.c')
329 Decider('timestamp-match')
330         </file>
331         <file name="hello.c">
332 int main() { printf("Hello, world!\n"); }
333         </file>
334       </scons_example>
336       <para>
338       When configured this way,
339       &SCons; will rebuild a target whenever
340       a source file's modification time has changed.
341       So if we use the <literal>touch -t</literal>
342       option to change the modification time of
343       &hello_c; to an old date (January 1, 1989),
344       &SCons; will still rebuild the target file:
346       </para>
348       <scons_output example="depends_match" os="posix" suffix="1">
349          <scons_output_command>scons -Q hello.o</scons_output_command>
350          <scons_output_command>touch -t 198901010000 hello.c</scons_output_command>
351          <scons_output_command>scons -Q hello.o</scons_output_command>
352       </scons_output>
354       <para>
356       In general, the only reason to prefer
357       <literal>timestamp-newer</literal>
358       instead of
359       <literal>timestamp-match</literal>,
360       would be if you have some specific reason
361       to require this &Make;-like behavior of
362       not rebuilding a target when an otherwise-modified
363       source file is older.
365       </para>
367     </section>
369     <section>
370     <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title>
372       <para>
374       As a performance enhancement,
375       &SCons; provides a way to use
376       a file's &contentsig;,
377       but to read those contents
378       only when the file's timestamp has changed.
379       To do this, call the &f-link-Decider;
380       function with <literal>'content-timestamp'</literal>
381       argument as follows:
383       </para>
385       <scons_example name="depends_MD5-timestamp">
386         <file name="SConstruct" printme="1">
387 Program('hello.c')
388 Decider('content-timestamp')
389         </file>
390         <file name="hello.c">
391 int main() { printf("Hello, world!\n"); }
392         </file>
393       </scons_example>
395       <para>
397       So configured, &SCons; will still behave like
398       it does when using <literal>Decider('content')</literal>:
400       </para>
402       <!--
404       We want to generate the output as follows,
405       but our "surrogate" system for generating the
406       output seems to get this wrong.
407       Just in-line the output for now.
409       <scons_output example="depends_MD5-timestamp" os="posix" suffix="1">
410          <scons_output_command>scons -Q hello</scons_output_command>
411          <scons_output_command>touch hello.c</scons_output_command>
412          <scons_output_command>scons -Q hello</scons_output_command>
413        <scons_output_command output="    [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
414          <scons_output_command>scons -Q hello</scons_output_command>
415       </scons_output>
417       -->
419       <screen>
420 % <userinput>scons -Q hello</userinput>
421 cc -o hello.o -c hello.c
422 cc -o hello hello.o
423 % <userinput>touch hello.c</userinput>
424 % <userinput>scons -Q hello</userinput>
425 scons: `hello' is up to date.
426 % <userinput>edit hello.c</userinput>
427     [CHANGE THE CONTENTS OF hello.c]
428 % <userinput>scons -Q hello</userinput>
429 cc -o hello.o -c hello.c
430 cc -o hello hello.o
431       </screen>
433       <para>
435       However, the second call to &SCons; in the above output,
436       when the build is up-to-date,
437       will have been performed by simply looking at the
438       modification time of the &hello_c; file,
439       not by opening it and performing
440       a signature calculation on its contents.
441       This can significantly speed up many up-to-date builds.
443       </para>
445       <para>
447       The only drawback to using
448       <literal>Decider('content-timestamp')</literal>
449       is that &SCons; will <emphasis>not</emphasis>
450       rebuild a target file if a source file was modified
451       within one second of the last time &SCons; built the file.
452       While most developers are programming,
453       this isn't a problem in practice,
454       since it's unlikely that someone will have built
455       and then thought quickly enough to make a substantive
456       change to a source file within one second.
457       Certain build scripts or
458       continuous integration tools may, however,
459       rely on the ability to apply changes to files
460       automatically and then rebuild as quickly as possible,
461       in which case use of
462       <literal>Decider('content-timestamp')</literal>
463       may not be appropriate.
465       </para>
467     </section>
469     <section>
470     <title>Extending &SCons;: Writing Your Own Custom &Decider; Function</title>
472       <para>
474       The different string values that we've passed to
475       the &f-link-Decider; function are essentially used by &SCons;
476       to pick one of several specific internal functions
477       that implement various ways of deciding if a dependency
478       (usually a source file)
479       has changed since a target file has been built.
480       As it turns out,
481       you can also supply your own function
482       to decide if a dependency has changed.
484       </para>
486       <para>
488       For example, suppose we have an input file
489       that contains a lot of data,
490       in some specific regular format,
491       that is used to rebuild a lot of different target files,
492       but each target file really only depends on
493       one particular section of the input file.
494       We'd like to have each target file depend on
495       only its section of the input file.
496       However, since the input file may contain a lot of data,
497       we want to open the input file only if its timestamp has changed.
498       This could be done with a custom
499       &Decider; function that might look something like this:
501       </para>
503       <scons_example name="depends_function">
504         <file name="SConstruct" printme="1">
505 Program('hello.c')
506 def decide_if_changed(dependency, target, prev_ni, repo_node=None):
507     if dependency.get_timestamp() != prev_ni.timestamp:
508         dep = str(dependency)
509         tgt = str(target)
510         if specific_part_of_file_has_changed(dep, tgt):
511             return True
512     return False
513 Decider(decide_if_changed)
514         </file>
515         <file name="hello.c">
516 int main() { printf("Hello, world!\n"); }
517         </file>
518       </scons_example>
520       <para>
522       Note that in the function definition,
523       the <varname>dependency</varname>
524       (input file) is the first argument,
525       and then the &target;.
526       Both of these are passed to the functions as
527       SCons &Node; objects,
528       which we convert to strings using the Python
529       <function>str()</function>.
531       </para>
533       <para>
535       The third argument, <varname>prev_ni</varname>,
536       is an object that holds the
537       &contentsig; and/or timestamp information
538       that was recorded about the dependency
539       the last time the target was built.
540       A <varname>prev_ni</varname> object can hold
541       different information,
542       depending on the type of thing that the
543       <varname>dependency</varname> argument represents.
544       For normal files,
545       the <varname>prev_ni</varname> object
546       has the following attributes:
548       </para>
550       <variablelist>
552         <varlistentry>
553         <term><literal>csig</literal></term>
555         <listitem>
556         <para>
557         The &contentsig;:
558         a cryptographic hash, or checksum, of the file contents
559         of the <varname>dependency</varname>
560         file the last time the &target; was built.
561         </para>
562         </listitem>
564         </varlistentry>
566         <varlistentry>
567         <term><literal>size</literal></term>
569         <listitem>
570         <para>
571         The size in bytes of the <varname>dependency</varname>
572         file the last time the target was built.
573         </para>
574         </listitem>
576         </varlistentry>
578         <varlistentry>
579         <term><literal>timestamp</literal></term>
581         <listitem>
582         <para>
583         The modification time of the <varname>dependency</varname>
584         file the last time the &target; was built.
585         </para>
586         </listitem>
588         </varlistentry>
590       </variablelist>
592       <para>
594       These attributes may not be present at the time of the
595       first run.  Without any prior build, no targets have been
596       created and no <filename>.sconsign</filename> DB file exists yet.
597       So you should always check whether the
598       <varname>prev_ni</varname> attribute in question is available
599       (use the Python <function>hasattr</function> method or a
600       <literal>try</literal>-<literal>except</literal> block).
602       </para>
605       <para>
607       The fourth argument <varname>repo_node</varname>
608       is the &Node; to use if it is not None when comparing &BuildInfo;.
609       This is typically only set when the target node only exists in a
610       &Repository;
612       </para>
614       <para>
616       Note that ignoring some of the arguments
617       in your custom &Decider; function
618       is a perfectly normal thing to do,
619       if they don't impact the way you want to
620       decide if the dependency file has changed.
622       </para>
624       <para>
626       We finally present a small example for a
627       <varname>csig</varname>-based decider function. Note how the
628       signature information for the <varname>dependency</varname> file
629       has to get initialized via <function>get_csig</function>
630       during each function call (this is mandatory!).
632       </para>
634       <sconstruct>
635 env = Environment()
638 def config_file_decider(dependency, target, prev_ni, repo_node=None):
639     import os.path
641     # We always have to init the .csig value...
642     dep_csig = dependency.get_csig()
643     # .csig may not exist, because no target was built yet...
644     if not prev_ni.hasattr("csig"):
645         return True
646     # Target file may not exist yet
647     if not os.path.exists(str(target.abspath)):
648         return True
649     if dep_csig != prev_ni.csig:
650         # Some change on source file => update installed one
651         return True
652     return False
655 def update_file():
656     with open("test.txt", "a") as f:
657         f.write("some line\n")
660 update_file()
662 # Activate our own decider function
663 env.Decider(config_file_decider)
665 env.Install("install", "test.txt")
666       </sconstruct>
668     </section>
670     <section>
671     <title>Mixing Different Ways of Deciding If a File Has Changed</title>
673       <para>
675       The previous examples have all demonstrated calling
676       the global &f-link-Decider; function
677       to configure all dependency decisions that &SCons; makes.
678       Sometimes, however, you want to be able to configure
679       different decision-making for different targets.
680       When that's necessary, you can use the &f-env-Decider;
681       method to affect only the configuration
682       decisions for targets built with a
683       specific &consenv;.
685       </para>
687       <para>
689       For example, if we arbitrarily want to build
690       one program using &contentsigs;
691       and another using file modification times
692       from the same source
693       we might configure it this way:
695       </para>
697       <scons_example name="depends_mixing">
698         <file name="SConstruct" printme="1">
699 env1 = Environment(CPPPATH = ['.'])
700 env2 = env1.Clone()
701 env2.Decider('timestamp-match')
702 env1.Program('prog-content', 'program1.c')
703 env2.Program('prog-timestamp', 'program2.c')
704         </file>
705         <file name="program1.c">
706 #include "inc.h"
707 int main() { printf("Hello, world!\n"); }
708         </file>
709         <file name="program2.c">
710 #include "inc.h"
711 int main() { printf("Hello, world!\n"); }
712         </file>
713         <file name="inc.h">
714 #define INC     1
715         </file>
716       </scons_example>
718       <para>
720       If both of the programs include the same
721       <filename>inc.h</filename> file,
722       then updating the modification time of
723       <filename>inc.h</filename>
724       (using the &touch; command)
725       will cause only <filename>prog-timestamp</filename>
726       to be rebuilt:
728       </para>
730       <scons_output example="depends_mixing" os="posix" suffix="1">
731          <scons_output_command>scons -Q</scons_output_command>
732          <scons_output_command>touch inc.h</scons_output_command>
733          <scons_output_command>scons -Q</scons_output_command>
734       </scons_output>
736     </section>
738   </section>
740   <section>
741   <title>Implicit Dependencies:  The &cv-CPPPATH; Construction Variable</title>
743     <para>
745     Now suppose that our "Hello, World!" program
746     actually has an <literal>#include</literal> line
747     to include the &hello_h; file in the compilation:
749     </para>
751     <scons_example name="depends_include">
752       <file name="SConstruct">
753 Program('hello.c', CPPPATH='.')
754       </file>
755       <file name="hello.c" printme="1">
756 #include &lt;hello.h&gt;
758 main()
760     printf("Hello, %s!\n", string);
762       </file>
763       <file name="hello.h">
764 #define string    "world"
765       </file>
766     </scons_example>
768     <para>
770     And, for completeness, the &hello_h; file looks like this:
772     </para>
774     <scons_example_file example="depends_include"  name="hello.h">
775     </scons_example_file>
777     <para>
779     In this case, we want &SCons; to recognize that,
780     if the contents of the &hello_h; file change,
781     the &hello; program must be recompiled.
782     To do this, we need to modify the
783     &SConstruct; file like so:
785     </para>
787     <scons_example_file example="depends_include"  name="SConstruct">
788     </scons_example_file>
790     <para>
792     The &cv-link-CPPPATH; value
793     tells &SCons; to look in the current directory
794     (<literal>'.'</literal>)
795     for any files included by C source files
796     (<filename>.c</filename> or <filename>.h</filename> files).
797     With this assignment in the &SConstruct; file:
799     </para>
801     <scons_output example="depends_include" os="posix" suffix="1">
802        <scons_output_command>scons -Q hello</scons_output_command>
803        <scons_output_command>scons -Q hello</scons_output_command>
804        <scons_output_command output="    [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
805        <scons_output_command>scons -Q hello</scons_output_command>
806     </scons_output>
808     <para>
810     First, notice that &SCons;
811     constructed the <literal>-I.</literal> argument
812     from the <literal>'.'</literal> in the &cv-CPPPATH; variable
813     so that the compilation would find the
814     &hello_h; file in the local directory.
816     </para>
818     <para>
820     Second, realize that &SCons; knows that the &hello;
821     program must be rebuilt
822     because it scans the contents of
823     the &hello_c; file
824     for the <literal>#include</literal> lines that indicate
825     another file is being included in the compilation.
826     &SCons; records these as
827     <emphasis>implicit dependencies</emphasis>
828     of the target file,
829     Consequently,
830     when the &hello_h; file changes,
831     &SCons; realizes that the &hello_c; file includes it,
832     and rebuilds the resulting &hello; program
833     that depends on both the &hello_c; and &hello_h; files.
835     </para>
837     <para>
839     Like the &cv-link-LIBPATH; variable,
840     the &cv-CPPPATH; variable
841     may be a list of directories,
842     or a string separated by
843     the system-specific path separation character
844     (':' on POSIX/Linux, ';' on Windows).
845     Either way, &SCons; creates the
846     right command-line options
847     so that the following example:
849     </para>
851     <scons_example name="depends_ex5">
852       <file name="SConstruct" printme="1">
853 Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
854       </file>
855       <file name="hello.c">
856 int main() { printf("Hello, world!\n"); }
857       </file>
858     </scons_example>
860     <para>
862     Will look like this on POSIX or Linux:
864     </para>
866     <scons_output example="depends_ex5" os="posix" suffix="1">
867        <scons_output_command>scons -Q hello</scons_output_command>
868     </scons_output>
870     <para>
872     And like this on Windows:
874     </para>
876     <scons_output example="depends_ex5" os="win32" suffix="2">
877        <scons_output_command>scons -Q hello.exe</scons_output_command>
878     </scons_output>
880   </section>
882   <section>
883   <title>Caching Implicit Dependencies</title>
885     <para>
887     Scanning each file for <literal>#include</literal> lines
888     does take some extra processing time.
889     When you're doing a full build of a large system,
890     the scanning time is usually a very small percentage
891     of the overall time spent on the build.
892     You're most likely to notice the scanning time,
893     however, when you <emphasis>rebuild</emphasis>
894     all or part of a large system:
895     &SCons; will likely take some extra time to "think about"
896     what must be built before it issues the
897     first build command
898     (or decides that everything is up to date
899     and nothing must be rebuilt).
901  <!--
902  Isn't this expensive? The answer is, it depends. If you do a full build of a
903  large system, the scanning time is insignificant. If you do a rebuild of a
904  large system, then Cons will spend a fair amount of time thinking about it
905  before it decides that nothing has to be done (although not necessarily more
906  time than make!). The good news is that Cons makes it very easy to
907  intelligently subset your build, when you are working on localized changes.
908  -->
910     </para>
912     <para>
914     In practice, having &SCons; scan files saves time
915     relative to the amount of potential time
916     lost to tracking down subtle problems
917     introduced by incorrect dependencies.
918     Nevertheless, the "waiting time"
919     while &SCons; scans files can annoy
920     individual developers waiting for their builds to finish.
921     Consequently, &SCons; lets you cache
922     the implicit dependencies
923     that its scanners find,
924     for use by later builds.
925     You can do this by specifying the
926     &implicit-cache; option on the command line:
928     </para>
930     <scons_output example="depends_ex1" suffix="6">
931        <scons_output_command>scons -Q --implicit-cache hello</scons_output_command>
932        <scons_output_command>scons -Q hello</scons_output_command>
933     </scons_output>
935     <para>
937     If you don't want to specify &implicit-cache;
938     on the command line each time,
939     you can make it the default behavior for your build
940     by setting the &implicit_cache; option
941     in an &SConscript; file:
943     </para>
945     <sconstruct>
946 SetOption('implicit_cache', 1)
947     </sconstruct>
949     <para>
951     &SCons; does not cache implicit dependencies like this by default
952     because the &implicit-cache; causes &SCons; to simply use the implicit
953     dependencies stored during the last run, without any checking
954     for whether or not those dependencies are still correct.
955     Specifically, this means &implicit-cache; instructs &SCons;
956     to <emphasis>not</emphasis> rebuild "correctly" in the
957     following cases:
960     </para>
962     <itemizedlist>
964       <listitem>
965         <para>
967         When &implicit-cache; is used, &SCons; will ignore any changes that
968         may have been made to search paths
969         (like &cv-CPPPATH; or &cv-LIBPATH;).
970         This can lead to &SCons; not rebuilding a file if a change to
971         &cv-CPPPATH; would normally cause a different, same-named file from
972         a different directory to be used.
974         </para>
975       </listitem>
977       <listitem>
978         <para>
980         When &implicit-cache; is used, &SCons; will not detect if a
981         same-named file has been added to a directory that is earlier in
982         the search path than the directory in which the file was found
983         last time.
985         </para>
986       </listitem>
988     </itemizedlist>
990     <section>
991     <title>The &implicit-deps-changed; Option</title>
993       <para>
995       When using cached implicit dependencies,
996       sometimes you want to "start fresh"
997       and have &SCons; re-scan the files
998       for which it previously cached the dependencies.
999       For example,
1000       if you have recently installed a new version of
1001       external code that you use for compilation,
1002       the external header files will have changed
1003       and the previously-cached implicit dependencies
1004       will be out-of-date.
1005       You can update them by
1006       running &SCons; with the &implicit-deps-changed; option:
1008       </para>
1010       <scons_output example="depends_ex1" suffix="7">
1011          <scons_output_command>scons -Q --implicit-deps-changed hello</scons_output_command>
1012          <scons_output_command>scons -Q hello</scons_output_command>
1013       </scons_output>
1015       <para>
1017       In this case, &SCons; will re-scan all of the implicit dependencies
1018       and cache updated copies of the information.
1020       </para>
1022     </section>
1024     <section>
1025     <title>The &implicit-deps-unchanged; Option</title>
1027       <para>
1029       By default, when caching dependencies,
1030       &SCons; notices when a file has been modified
1031       and re-scans the file for any updated
1032       implicit dependency information.
1033       Sometimes, however, you may want
1034       to force &SCons; to use the cached implicit dependencies,
1035       even if the source files changed.
1036       This can speed up a build for example,
1037       when you have changed your source files
1038       but know that you haven't changed
1039       any <literal>#include</literal> lines.
1040       In this case,
1041       you can use the &implicit-deps-unchanged; option:
1043       </para>
1045       <scons_output example="depends_ex1" suffix="8">
1046          <scons_output_command>scons -Q --implicit-deps-unchanged hello</scons_output_command>
1047          <scons_output_command>scons -Q hello</scons_output_command>
1048       </scons_output>
1050       <para>
1052       In this case,
1053       &SCons; will assume that the cached implicit
1054       dependencies are correct and
1055       will not bother to re-scan changed files.
1056       For typical builds after small,
1057       incremental changes to source files,
1058       the savings may not be very big,
1059       but sometimes every bit of
1060       improved performance counts.
1062       </para>
1064     </section>
1066     <!--
1068     <section>
1069     <title>XXX max drift</title>
1071       XXX SetOption('max_drift')
1073     </section>
1075     -->
1077   </section>
1079   <section>
1080   <title>Explicit Dependencies:  the &Depends; Function</title>
1082     <para>
1084     Sometimes a file depends on another file
1085     that is not detected by an &SCons; scanner.
1086     For this situation,
1087     &SCons; allows you to specific explicitly that one file
1088     depends on another file,
1089     and must be rebuilt whenever that file changes.
1090     This is specified using the &f-link-Depends; method:
1092     </para>
1094     <programlisting>
1095 hello = Program('hello.c')
1096 Depends(hello, 'other_file')
1097     </programlisting>
1099     <!-- XXX mention that you can use arrays for target and source? -->
1101     <screen>
1102 % <userinput>scons -Q hello</userinput>
1103 cc -c hello.c -o hello.o
1104 cc -o hello hello.o
1105 % <userinput>scons -Q hello</userinput>
1106 scons: `hello' is up to date.
1107 % <userinput>edit other_file</userinput>
1108     [CHANGE THE CONTENTS OF other_file]
1109 % <userinput>scons -Q hello</userinput>
1110 cc -c hello.c -o hello.o
1111 cc -o hello hello.o
1112     </screen>
1114     <para>
1116     Note that the dependency
1117     (the second argument to &f-Depends;)
1118     may also be a list of Node objects
1119     (for example, as returned by a call to a Builder):
1121     </para>
1123     <programlisting>
1124 hello = Program('hello.c')
1125 goodbye = Program('goodbye.c')
1126 Depends(hello, goodbye)
1127     </programlisting>
1129     <para>
1131     in which case the dependency or dependencies
1132     will be built before the target(s):
1134     </para>
1136     <screen>
1137 % <userinput>scons -Q hello</userinput>
1138 cc -c goodbye.c -o goodbye.o
1139 cc -o goodbye goodbye.o
1140 cc -c hello.c -o hello.o
1141 cc -o hello hello.o
1142     </screen>
1144   </section>
1146   <section>
1147   <title>Dependencies From External Files:  the &ParseDepends;
1148   Function</title>
1150     <para>
1152     &SCons; has built-in scanners for a number of languages. Sometimes
1153     these scanners fail to extract certain implicit dependencies due
1154     to limitations of the scanner implementation.
1156     </para>
1158     <para>
1160     The following example illustrates a case where the built-in C
1161     scanner is unable to extract the implicit dependency on a header
1162     file.
1164     </para>
1166     <scons_example name="depends_macroinc">
1167       <file name="hello.c" printme="1">
1168 #define FOO_HEADER &lt;foo.h&gt;
1169 #include FOO_HEADER
1171 int main() {
1172     return FOO;
1174       </file>
1175       <file name="SConstruct">
1176 Program('hello', 'hello.c', CPPPATH='.')
1177       </file>
1178       <file name="foo.h">
1179 #define FOO 42
1180       </file>
1181     </scons_example>
1183     <scons_output example="depends_macroinc" os="posix" suffix="1">
1184       <scons_output_command>scons -Q</scons_output_command>
1185       <scons_output_command output="   [CHANGE CONTENTS OF foo.h]">edit foo.h</scons_output_command>
1186       <scons_output_command>scons -Q</scons_output_command>
1187     </scons_output>
1189     <para>
1191     Apparently, the scanner does not know about the header dependency.
1192     Not being a full-fledged C preprocessor, the scanner does not
1193     expand the macro.
1195     </para>
1197     <para>
1199     In these cases, you may also use the compiler to extract the
1200     implicit dependencies. &f-link-ParseDepends; can parse the contents of
1201     the compiler output in the style of &Make;, and explicitly
1202     establish all of the listed dependencies.
1204     </para>
1206     <para>
1208     The following example uses &f-ParseDepends; to process a compiler
1209     generated dependency file which is generated as a side effect
1210     during compilation of the object file:
1212     </para>
1214     <!-- XXX The ParseDepends example below fakes proper working by a
1215     priori specification of the dependency file. The produced hello.d
1216     file is not found (or used) for unknown reasons. -->
1218     <scons_example name="depends_parsedep">
1219       <file name="hello.c">
1220 #define FOO_HEADER &lt;foo.h&gt;
1221 #include FOO_HEADER
1223 int main() {
1224     return FOO;
1226       </file>
1227       <file name="SConstruct" printme="1">
1228 obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
1229 SideEffect('hello.d', obj)
1230 ParseDepends('hello.d')
1231 Program('hello', obj)
1232       </file>
1233       <file name="foo.h">
1234 #define FOO 42
1235       </file>
1236       <file name="hello.d">
1237 hello.o: hello.c foo.h
1238       </file>
1239     </scons_example>
1241     <scons_output example="depends_parsedep" os="posix" suffix="1">
1242       <scons_output_command>scons -Q</scons_output_command>
1243       <scons_output_command output="   [CHANGE CONTENTS OF foo.h]">edit foo.h</scons_output_command>
1244       <scons_output_command>scons -Q</scons_output_command>
1245     </scons_output>
1247     <para>
1249     Parsing dependencies from a compiler-generated
1250     <filename>.d</filename> file has a chicken-and-egg problem, that
1251     causes unnecessary rebuilds:
1253     </para>
1255     <scons_example name="depends_parsedeprebuild">
1256       <file name="hello.c">
1257 #define FOO_HEADER &lt;foo.h&gt;
1258 #include FOO_HEADER
1260 int main() {
1261     return FOO;
1263       </file>
1264       <file name="SConstruct">
1265 obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
1266 SideEffect('hello.d', obj)
1267 ParseDepends('hello.d')
1268 Program('hello', obj)
1269       </file>
1270       <file name="foo.h">
1271 #define FOO 42
1272       </file>
1273     </scons_example>
1275     <!--
1276     <scons_output example="depends_parsedeprebuild" os="posix" suffix="1">
1277       <scons_output_command>scons -Q</scons_output_command>
1278       <scons_output_command>scons -Q</scons_output_command>
1279       <scons_output_command>scons -Q</scons_output_command>
1280     </scons_output>
1281     -->
1283     <screen>
1284 % <userinput>scons -Q</userinput>
1285 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1286 cc -o hello hello.o
1287 % <userinput>scons -Q --debug=explain</userinput>
1288 scons: rebuilding `hello.o' because `foo.h' is a new dependency
1289 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1290 % <userinput>scons -Q</userinput>
1291 scons: `.' is up to date.
1292     </screen>
1294     <para>
1296     In the first pass, the dependency file is generated while the
1297     object file is compiled. At that time, &SCons; does not know about
1298     the dependency on <filename>foo.h</filename>. In the second pass,
1299     the object file is regenerated because <filename>foo.h</filename>
1300     is detected as a new dependency.
1302     </para>
1304     <para>
1306     &f-ParseDepends; immediately reads the specified file at invocation
1307     time and just returns if the file does not exist. A dependency
1308     file generated during the build process is not automatically
1309     parsed again. Hence, the compiler-extracted dependencies are not
1310     stored in the signature database during the same build pass. This
1311     limitation of &f-ParseDepends; leads to unnecessary recompilations.
1312     Therefore, &f-ParseDepends; should only be used if scanners are not
1313     available for the employed language or not powerful enough for the
1314     specific task.
1316     </para>
1318   </section>
1320   <section>
1321   <title>Ignoring Dependencies:  the &Ignore; Function</title>
1323     <para>
1325     Sometimes it makes sense
1326     to not rebuild a program,
1327     even if a dependency file changes.
1328     In this case,
1329     you would tell &SCons; specifically
1330     to ignore a dependency using the
1331     &f-link-Ignore; function as follows:
1333     </para>
1335     <scons_example name="depends_ignore">
1336       <file name="SConstruct" printme="1">
1337 hello_obj=Object('hello.c')
1338 hello = Program(hello_obj)
1339 Ignore(hello_obj, 'hello.h')
1340       </file>
1341       <file name="hello.c">
1342 #include "hello.h"
1343 int main() { printf("Hello, %s!\n", string); }
1344       </file>
1345       <file name="hello.h">
1346 #define string    "world"
1347       </file>
1348     </scons_example>
1350     <!-- XXX mention that you can use lists for target and source? -->
1352     <!--
1353     <scons_output example="depends_ignore" suffix="1">
1354       <scons_output_command>scons -Q hello</scons_output_command>
1355       <scons_output_command>scons -Q hello</scons_output_command>
1356       <scons_output_command output="    [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
1357       <scons_output_command>scons -Q hello</scons_output_command>
1358       XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
1359     </scons_output>
1360     -->
1362     <screen>
1363 % <userinput>scons -Q hello</userinput>
1364 cc -c -o hello.o hello.c
1365 cc -o hello hello.o
1366 % <userinput>scons -Q hello</userinput>
1367 scons: `hello' is up to date.
1368 % <userinput>edit hello.h</userinput>
1369   [CHANGE THE CONTENTS OF hello.h]
1370 % <userinput>scons -Q hello</userinput>
1371 scons: `hello' is up to date.
1372     </screen>
1374     <para>
1376     Now, the above example is a little contrived,
1377     because it's hard to imagine a real-world situation
1378     where you wouldn't want to rebuild &hello;
1379     if the &hello_h; file changed.
1380     A more realistic example
1381     might be if the &hello;
1382     program is being built in a
1383     directory that is shared between multiple systems
1384     that have different copies of the
1385     &stdio_h; include file.
1386     In that case,
1387     &SCons; would notice the differences between
1388     the different systems' copies of &stdio_h;
1389     and would rebuild &hello;
1390     each time you change systems.
1391     You could avoid these rebuilds as follows:
1393     </para>
1395     <programlisting>
1396 hello = Program('hello.c', CPPPATH=['/usr/include'])
1397 Ignore(hello, '/usr/include/stdio.h')
1398     </programlisting>
1400     <para>
1401     &f-Ignore; can also be used to prevent a generated file from being built
1402     by default. This is due to the fact that directories depend on
1403     their contents.  So to ignore a generated file from the default build,
1404     you specify that the directory should ignore the generated file.
1405     Note that the file will still be built if the user specifically
1406     requests the target on scons command line, or if the file is
1407     a dependency of another file which is requested and/or is built
1408     by default.
1409     </para>
1411     <scons_example name="depends_ignore_explicit">
1412       <file name="SConstruct" printme="1">
1413 hello_obj=Object('hello.c')
1414 hello = Program(hello_obj)
1415 Ignore('.',[hello,hello_obj])
1416       </file>
1417       <file name="hello.c">
1418 #include "stdio.h"
1419 int main() { printf("Hello!\n"); }
1420       </file>
1421     </scons_example>
1423     <scons_output example="depends_ignore_explicit" os="posix" suffix="1">
1424       <scons_output_command>scons -Q</scons_output_command>
1425       <scons_output_command>scons -Q hello</scons_output_command>
1426       <scons_output_command>scons -Q hello</scons_output_command>
1427     </scons_output>
1428   </section>
1430   <section>
1431   <title>Order-Only Dependencies:  the &Requires; Function</title>
1433     <para>
1435     Occasionally,
1436     it may be useful to specify that a certain
1437     file or directory must, if necessary,
1438     be built or created before some other target is built,
1439     but that changes to that file or directory
1440     do <emphasis>not</emphasis>
1441     require that the target itself be rebuilt.
1442     Such a relationship is called an
1443     <emphasis>order-only dependency</emphasis>
1444     because it only affects the order in which
1445     things must be built--the dependency before the target--but
1446     it is not a strict dependency relationship
1447     because the target should not
1448     change in response to changes in the dependent file.
1450     </para>
1452     <para>
1454     For example, suppose that you want to create a file
1455     every time you run a build
1456     that identifies the time the build was performed,
1457     the version number, etc.,
1458     and which is included in every program that you build.
1459     The version file's contents will change every build.
1460     If you specify a normal dependency relationship,
1461     then every program that depends on
1462     that file would be rebuilt every time you ran &SCons;.
1463     For example, we could use some Python code in
1464     a &SConstruct; file to create a new <filename>version.c</filename> file
1465     with a string containing the current date every time
1466     we run &SCons;,
1467     and then link a program with the resulting object file
1468     by listing <filename>version.c</filename> in the sources:
1470     </para>
1472     <scons_example name="depends_no-Requires">
1473       <file name="SConstruct" printme="1">
1474 import time
1476 version_c_text = """
1477 char *date = "%s";
1478 """ % time.ctime(time.time())
1479 open('version.c', 'w').write(version_c_text)
1481 hello = Program(['hello.c', 'version.c'])
1482       </file>
1483       <file name="hello.c">
1484 extern char *date;
1485 int main() { printf("Hello, %s!  I was built: %s\n", date); }
1486       </file>
1487     </scons_example>
1489     <para>
1491     If we list <filename>version.c</filename> as an actual source file,
1492     though, then the <filename>version.o</filename> file
1493     will get rebuilt every time we run &SCons;
1494     (because the &SConstruct; file itself changes
1495     the contents of <filename>version.c</filename>)
1496     and the <filename>hello</filename> executable
1497     will get re-linked every time
1498     (because the <filename>version.o</filename> file changes):
1500     </para>
1502     <scons_output example="depends_no-Requires" suffix="1">
1503       <scons_output_command>scons -Q hello</scons_output_command>
1504       <scons_output_command>sleep 1</scons_output_command>
1505       <scons_output_command>scons -Q hello</scons_output_command>
1506       <scons_output_command>sleep 1</scons_output_command>
1507       <scons_output_command>scons -Q hello</scons_output_command>
1508     </scons_output>
1510     <para>
1512     (Note that for the above example to work,
1513     we &sleep; for one second in between each run,
1514     so that the &SConstruct; file will create a
1515     <filename>version.c</filename> file with a time string
1516     that's one second later than the previous run.)
1518     </para>
1520     <para>
1522     One solution is to use the &f-link-Requires; function
1523     to specify that the <filename>version.o</filename>
1524     must be rebuilt before it is used by the link step,
1525     but that changes to <filename>version.o</filename>
1526     should not actually cause the <filename>hello</filename>
1527     executable to be re-linked:
1529     </para>
1531     <scons_example name="depends_Requires">
1532       <file name="SConstruct" printme="1">
1533 import time
1535 version_c_text = """
1536 char *date = "%s";
1537 """ % time.ctime(time.time())
1538 open('version.c', 'w').write(version_c_text)
1540 version_obj = Object('version.c')
1542 hello = Program('hello.c',
1543                 LINKFLAGS = str(version_obj[0]))
1545 Requires(hello, version_obj)
1546       </file>
1547       <file name="hello.c">
1548 extern char *date;
1549 int main() { printf("Hello, %s!  I was built: %s\n", date); }
1550       </file>
1551     </scons_example>
1553     <para>
1555     Notice that because we can no longer list <filename>version.c</filename>
1556     as one of the sources for the <filename>hello</filename> program,
1557     we have to find some other way to get it into the link command line.
1558     For this example, we're cheating a bit and stuffing the
1559     object file name (extracted from <literal>version_obj</literal>
1560     list returned by the &b-Object; builder call)
1561     into the &cv-link-LINKFLAGS; variable,
1562     because &cv-LINKFLAGS; is already included
1563     in the &cv-link-LINKCOM; command line.
1565     </para>
1567     <para>
1569     With these changes,
1570     we get the desired behavior of only
1571     re-linking the <filename>hello</filename> executable
1572     when the <filename>hello.c</filename> has changed,
1573     even though the <filename>version.o</filename> is rebuilt
1574     (because the &SConstruct; file still changes the
1575     <filename>version.c</filename> contents directly each run):
1577     </para>
1579     <scons_output example="depends_Requires" suffix="1">
1580       <scons_output_command>scons -Q hello</scons_output_command>
1581       <scons_output_command>sleep 1</scons_output_command>
1582       <scons_output_command>scons -Q hello</scons_output_command>
1583       <scons_output_command>sleep 1</scons_output_command>
1584       <scons_output_command output="    [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
1585       <scons_output_command>scons -Q hello</scons_output_command>
1586       <scons_output_command>sleep 1</scons_output_command>
1587       <scons_output_command>scons -Q hello</scons_output_command>
1588     </scons_output>
1590   </section>
1592   <section>
1593   <title>The &AlwaysBuild; Function</title>
1595     <para>
1597     How &SCons; handles dependencies can also be affected
1598     by the &f-link-AlwaysBuild; method.
1599     When a file is passed to the &f-AlwaysBuild; method,
1600     like so:
1602     </para>
1604     <scons_example name="depends_AlwaysBuild">
1605       <file name="SConstruct" printme="1">
1606 hello = Program('hello.c')
1607 AlwaysBuild(hello)
1608       </file>
1609       <file name="hello.c">
1610 int main() { printf("Hello, %s!\n", string); }
1611       </file>
1612     </scons_example>
1614     <para>
1616     Then the specified target file (&hello; in our example)
1617     will always be considered out-of-date and
1618     rebuilt whenever that target file is evaluated
1619     while walking the dependency graph:
1621     </para>
1623     <scons_output example="depends_AlwaysBuild" suffix="1">
1624       <scons_output_command>scons -Q</scons_output_command>
1625       <scons_output_command>scons -Q</scons_output_command>
1626     </scons_output>
1628     <para>
1630     The &f-AlwaysBuild; function has a somewhat misleading name,
1631     because it does not actually mean the target file will
1632     be rebuilt every single time &SCons; is invoked.
1633     Instead, it means that the target will, in fact,
1634     be rebuilt whenever the target file is encountered
1635     while evaluating the targets specified on
1636     the command line (and their dependencies).
1637     So specifying some other target on the command line,
1638     a target that does <emphasis>not</emphasis>
1639     itself depend on the &f-AlwaysBuild; target,
1640     will still be rebuilt only if it's out-of-date
1641     with respect to its dependencies:
1643     </para>
1645     <scons_output example="depends_AlwaysBuild" suffix="2">
1646       <scons_output_command>scons -Q</scons_output_command>
1647       <scons_output_command>scons -Q hello.o</scons_output_command>
1648     </scons_output>
1650     <!--
1652       XXX AlwaysBuild() and Alias Nodes
1654       XXX AlwaysBuild() and Dir Nodes
1656       XXX AlwaysBuild() with no sources
1658     -->
1660   </section>
1662   <!--
1664   <section>
1665   <title>The &Salt; Method</title>
1667     <para>
1669     XXX Salt() (are we going to implement this ?)
1671         original Cons classic POD documentation:
1673 =head2 The C<Salt> method
1675 The C<Salt> method adds a constant value to the signature calculation
1676 for every derived file.  It is invoked as follows:
1678   Salt $string;
1680 Changing the Salt value will force a complete rebuild of every derived
1681 file.  This can be used to force rebuilds in certain desired
1682 circumstances.  For example,
1684   Salt `uname -s`;
1686 Would force a complete rebuild of every derived file whenever the
1687 operating system on which the build is performed (as reported by C<uname
1688 -s>) changes.
1690     </para>
1692   </section>
1694   -->
1696 </chapter>