5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 So far we've seen how &SCons; handles one-time builds.
29 But one of the main functions of a build tool like &SCons;
30 is to rebuild only what is necessary
31 when source files change--or, put another way,
32 &SCons; should <emphasis>not</emphasis>
33 waste time rebuilding things that don't need to be rebuilt.
34 You can see this at work simply by re-invoking &SCons;
35 after building our simple &hello; example:
42 % <userinput>scons -Q</userinput>
43 cc -o hello.o -c hello.c
45 % <userinput>scons -Q</userinput>
46 scons: `.' is up to date.
51 The second time it is executed,
52 &SCons; realizes that the &hello; program
53 is up-to-date with respect to the current &hello_c; source file,
54 and avoids rebuilding it.
55 You can see this more clearly by naming
56 the &hello; program explicitly on the command line:
61 % <userinput>scons -Q hello</userinput>
62 cc -o hello.o -c hello.c
64 % <userinput>scons -Q hello</userinput>
65 scons: `hello' is up to date.
70 Note that &SCons; reports <literal>"...is up to date"</literal>
71 only for target files named explicitly on the command line,
72 to avoid cluttering the output.
77 <title>Deciding When an Input File Has Changed: the &Decider; Function</title>
81 Another aspect of avoiding unnecessary rebuilds
82 is the fundamental build tool behavior
83 of <emphasis>rebuilding</emphasis>
84 things when an input file changes,
85 so that the built software is up to date.
87 &SCons; keeps track of this through an
88 MD5 &signature;, or checksum, of the contents of each file,
89 although you can easily configure
91 modification times (or time stamps)
93 You can even specify your own Python function
94 for deciding if an input file has changed.
99 <title>Using MD5 Signatures to Decide if a File Has Changed</title>
104 &SCons; keeps track of whether a file has changed
105 based on an MD5 checksum of the file's contents,
106 not the file's modification time.
107 This means that you may be surprised by the
108 default &SCons; behavior if you are used to the
109 &Make; convention of forcing
110 a rebuild by updating the file's modification time
111 (using the &touch; command, for example):
116 % <userinput>scons -Q hello</userinput>
117 cc -o hello.o -c hello.c
119 % <userinput>touch hello.c</userinput>
120 % <userinput>scons -Q hello</userinput>
121 scons: `hello' is up to date.
126 Even though the file's modification time has changed,
127 &SCons; realizes that the contents of the
128 &hello_c; file have <emphasis>not</emphasis> changed,
129 and therefore that the &hello; program
131 This avoids unnecessary rebuilds when,
132 for example, someone rewrites the
133 contents of a file without making a change.
134 But if the contents of the file really do change,
135 then &SCons; detects the change
136 and rebuilds the program as required:
141 % <userinput>scons -Q hello</userinput>
142 cc -o hello.o -c hello.c
144 % <userinput>edit hello.c</userinput>
145 [CHANGE THE CONTENTS OF hello.c]
146 % <userinput>scons -Q hello</userinput>
147 cc -o hello.o -c hello.c
153 Note that you can, if you wish,
154 specify this default behavior
155 (MD5 signatures) explicitly
156 using the &Decider; function as follows:
167 You can also use the string <literal>'content'</literal>
168 as a synonym for <literal>'MD5'</literal>
169 when calling the &Decider; function.
174 <title>Ramifications of Using MD5 Signatures</title>
178 Using MD5 signatures to decide if an input file has changed
179 has one surprising benefit:
180 if a source file has been changed
181 in such a way that the contents of the
182 rebuilt target file(s)
183 will be exactly the same as the last time
185 then any "downstream" target files
186 that depend on the rebuilt-but-not-changed target
187 file actually need not be rebuilt.
194 a user were to only change a comment in a &hello_c; file,
195 then the rebuilt &hello_o; file
196 would be exactly the same as the one previously built
197 (assuming the compiler doesn't put any build-specific
198 information in the object file).
199 &SCons; would then realize that it would not
200 need to rebuild the &hello; program as follows:
205 % <userinput>scons -Q hello</userinput>
206 cc -o hello.o -c hello.c
208 % <userinput>edit hello.c</userinput>
209 [CHANGE A COMMENT IN hello.c]
210 % <userinput>scons -Q hello</userinput>
211 cc -o hello.o -c hello.c
212 scons: `hello' is up to date.
218 "short-circuits" any dependent builds
219 when it realizes that a target file
220 has been rebuilt to exactly the same file as the last build.
221 This does take some extra processing time
222 to read the contents of the target (&hello_o;) file,
223 but often saves time when the rebuild that was avoided
224 would have been time-consuming and expensive.
233 <title>Using Time Stamps to Decide If a File Has Changed</title>
237 If you prefer, you can
238 configure &SCons; to use the modification time
239 of a file, not the file contents,
240 when deciding if a target needs to be rebuilt.
241 &SCons; gives you two ways to use time stamps
242 to decide if an input file has changed
243 since the last time a target has been built.
249 The most familiar way to use time stamps
250 is the way &Make; does:
251 that is, have &SCons; decide
252 that a target must be rebuilt
253 if a source file's modification time is
254 <emphasis>newer</emphasis>
255 than the target file.
256 To do this, call the &Decider;
263 Decider('timestamp-newer')
268 This makes &SCons; act like &Make;
269 when a file's modification time is updated
270 (using the &touch; command, for example):
275 % <userinput>scons -Q hello</userinput>
276 cc -o hello.o -c hello.c
278 % <userinput>touch hello.c</userinput>
279 % <userinput>scons -Q hello</userinput>
280 cc -o hello.o -c hello.c
286 And, in fact, because this behavior is the same
287 as the behavior of &Make;,
288 you can also use the string <literal>'make'</literal>
289 as a synonym for <literal>'timestamp-newer'</literal>
290 when calling the &Decider; function:
301 One drawback to using times stamps exactly like &Make;
302 is that if an input file's modification time suddenly
303 becomes <emphasis>older</emphasis> than a target file,
304 the target file will not be rebuilt.
305 This can happen if an old copy of a source file is restored
306 from a backup archive, for example.
307 The contents of the restored file will likely be different
308 than they were the last time a dependent target was built,
309 but the target won't be rebuilt
310 because the modification time of the source file
311 is not newer than the target.
317 Because &SCons; actually stores information
318 about the source files' time stamps whenever a target is built,
319 it can handle this situation by checking for
320 an exact match of the source file time stamp,
321 instead of just whether or not the source file
322 is newer than the target file.
323 To do this, specify the argument
324 <literal>'timestamp-match'</literal>
325 when calling the &Decider; function:
331 Decider('timestamp-match')
336 When configured this way,
337 &SCons; will rebuild a target whenever
338 a source file's modification time has changed.
339 So if we use the <literal>touch -t</literal>
340 option to change the modification time of
341 &hello_c; to an old date (January 1, 1989),
342 &SCons; will still rebuild the target file:
347 % <userinput>scons -Q hello</userinput>
348 cc -o hello.o -c hello.c
350 % <userinput>touch -t 198901010000 hello.c</userinput>
351 % <userinput>scons -Q hello</userinput>
352 cc -o hello.o -c hello.c
358 In general, the only reason to prefer
359 <literal>timestamp-newer</literal>
361 <literal>timestamp-match</literal>,
362 would be if you have some specific reason
363 to require this &Make;-like behavior of
364 not rebuilding a target when an otherwise-modified
365 source file is older.
372 <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title>
376 As a performance enhancement,
377 &SCons; provides a way to use
378 MD5 checksums of file contents
379 but to read those contents
380 only when the file's timestamp has changed.
381 To do this, call the &Decider;
382 function with <literal>'MD5-timestamp'</literal>
389 Decider('MD5-timestamp')
394 So configured, &SCons; will still behave like
395 it does when using <literal>Decider('MD5')</literal>:
401 We want to generate the output as follows,
402 but our "surrogate" system for generating the
403 output seems to get this wrong.
404 Just in-line the output for now.
406 <scons_output example="MD5-timestamp" os="posix">
407 <scons_output_command>scons -Q hello</scons_output_command>
408 <scons_output_command>touch hello.c</scons_output_command>
409 <scons_output_command>scons -Q hello</scons_output_command>
410 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
411 <scons_output_command>scons -Q hello</scons_output_command>
417 % <userinput>scons -Q hello</userinput>
418 cc -o hello.o -c hello.c
420 % <userinput>touch hello.c</userinput>
421 % <userinput>scons -Q hello</userinput>
422 scons: `hello' is up to date.
423 % <userinput>edit hello.c</userinput>
424 [CHANGE THE CONTENTS OF hello.c]
425 % <userinput>scons -Q hello</userinput>
426 cc -o hello.o -c hello.c
432 However, the second call to &SCons; in the above output,
433 when the build is up-to-date,
434 will have been performed by simply looking at the
435 modification time of the &hello_c; file,
436 not by opening it and performing
437 an MD5 checksum calcuation on its contents.
438 This can significantly speed up many up-to-date builds.
444 The only drawback to using
445 <literal>Decider('MD5-timestamp')</literal>
446 is that &SCons; will <emphasis>not</emphasis>
447 rebuild a target file if a source file was modified
448 within one second of the last time &SCons; built the file.
449 While most developers are programming,
450 this isn't a problem in practice,
451 since it's unlikely that someone will have built
452 and then thought quickly enough to make a substantive
453 change to a source file within one second.
454 Certain build scripts or
455 continuous integration tools may, however,
456 rely on the ability to apply changes to files
457 automatically and then rebuild as quickly as possible,
459 <literal>Decider('MD5-timestamp')</literal>
460 may not be appropriate.
467 <title>Writing Your Own Custom &Decider; Function</title>
471 The different string values that we've passed to
472 the &Decider; function are essentially used by &SCons;
473 to pick one of several specific internal functions
474 that implement various ways of deciding if a dependency
475 (usually a source file)
476 has changed since a target file has been built.
478 you can also supply your own function
479 to decide if a dependency has changed.
485 For example, suppose we have an input file
486 that contains a lot of data,
487 in some specific regular format,
488 that is used to rebuild a lot of different target files,
489 but each target file really only depends on
490 one particular section of the input file.
491 We'd like to have each target file depend on
492 only its section of the input file.
493 However, since the input file may contain a lot of data,
494 we want to open the input file only if its timestamp has changed.
495 This could done with a custom
496 &Decider; function that might look something like this:
502 def decide_if_changed(dependency, target, prev_ni):
503 if self.get_timestamp() != prev_ni.timestamp:
504 dep = str(dependency)
506 if specific_part_of_file_has_changed(dep, tgt):
509 Decider(decide_if_changed)
514 Note that in the function definition,
515 the <varname>dependency</varname>
516 (input file) is the first argument,
517 and then the ⌖.
518 Both of these are passed to the functions as
519 SCons &Node; objects,
520 which we convert to strings using the Python
521 <function>str()</function>.
527 The third argument, <varname>prev_ni</varname>,
528 is an object that holds the
529 signature or timestamp information
530 that was recorded about the dependency
531 the last time the target was built.
532 A <varname>prev_ni</varname> object can hold
533 different information,
534 depending on the type of thing that the
535 <varname>dependency</varname> argument represents.
537 the <varname>prev_ni</varname> object
538 has the following attributes:
549 The <emphasis>content signature</emphasis>,
550 or MD5 checksum, of the contents of the
551 <varname>dependency</varname>
552 file the list time the ⌖ was built.
563 The size in bytes of the <varname>dependency</varname>
564 file the list time the target was built.
571 <term>.timestamp</term>
575 The modification time of the <varname>dependency</varname>
576 file the list time the ⌖ was built.
586 Note that ignoring some of the arguments
587 in your custom &Decider; function
588 is a perfectly normal thing to do,
589 if they don't impact the way you want to
590 decide if the dependency file has changed.
597 <title>Mixing Different Ways of Deciding If a File Has Changed</title>
601 The previous examples have all demonstrated calling
602 the global &Decider; function
603 to configure all dependency decisions that &SCons; makes.
604 Sometimes, however, you want to be able to configure
605 different decision-making for different targets.
606 When that's necessary, you can use the
607 <function>env.Decider</function>
608 method to affect only the configuration
609 decisions for targets built with a
610 specific construction environment.
616 For example, if we arbitrarily want to build
617 one program using MD5 checkums
618 and another using file modification times
620 we might configure it this way:
625 env1 = Environment(CPPPATH = ['.'])
627 env2.Decider('timestamp-match')
628 env1.Program('prog-MD5', 'program1.c')
629 env2.Program('prog-timestamp', 'program2.c')
634 If both of the programs include the same
635 <filename>inc.h</filename> file,
636 then updating the modification time of
637 <filename>inc.h</filename>
638 (using the &touch; command)
639 will cause only <filename>prog-timestamp</filename>
645 % <userinput>scons -Q</userinput>
646 cc -o program1.o -c -I. program1.c
647 cc -o prog-MD5 program1.o
648 cc -o program2.o -c -I. program2.c
649 cc -o prog-timestamp program2.o
650 % <userinput>touch inc.h</userinput>
651 % <userinput>scons -Q</userinput>
652 cc -o program2.o -c -I. program2.c
653 cc -o prog-timestamp program2.o
661 <title>Older Functions for Deciding When an Input File Has Changed</title>
665 &SCons; still supports two functions that used to be the
666 primary methods for configuring the
667 decision about whether or not an input file has changed.
668 Although they're not officially deprecated yet,
669 their use is discouraged,
670 mainly because they rely on a somewhat
671 confusing distinction between how
672 source files and target files are handled.
673 These functions are documented here mainly in case you
674 encounter them in existing &SConscript; files.
679 <title>The &SourceSignatures; Function</title>
683 The &SourceSignatures; function is fairly straightforward,
684 and supports two different argument values
685 to configure whether source file changes should be decided
686 using MD5 signatures:
692 SourceSignatures('MD5')
697 Or using time stamps:
703 SourceSignatures('timestamp')
708 These are roughly equivalent to specifying
709 <function>Decider('MD5')</function>
711 <function>Decider('timestamp-match')</function>,
713 although it only affects how SCons makes
714 decisions about dependencies on
715 <emphasis>source</emphasis> files--that is,
716 files that are not built from any other files.
723 <title>The &TargetSignatures; Function</title>
727 The &TargetSignatures; function
728 specifies how &SCons; decides
729 when a target file has changed
730 <emphasis>when it is used as a
731 dependency of (input to) another target</emphasis>--that is,
732 the &TargetSignatures; function configures
733 how the signatures of "intermediate" target files
734 are used when deciding if a "downstream" target file
737 This easily-overlooked distinction between
738 how &SCons; decides if the target itself must be rebuilt
739 and how the target is then used to decide if a different
740 target must be rebuilt is one of the confusing
741 things that has led to the &TargetSignatures;
742 and &SourceSignatures; functions being
743 replaced by the simpler &Decider; function.
750 The &TargetSignatures; function supports the same
751 <literal>'MD5'</literal> and <literal>'timestamp'</literal>
752 argument values that are supported by the &SourceSignatures;,
753 with the same meanings, but applied to target files.
754 That is, in the example:
760 TargetSignatures('MD5')
765 The MD5 checksum of the &hello_o; target file
766 will be used to decide if it has changed since the last
767 time the "downstream" &hello; target file was built.
774 TargetSignatures('timestamp')
779 The modification time of the &hello_o; target file
780 will be used to decide if it has changed since the last
781 time the "downstream" &hello; target file was built.
787 The &TargetSignatures; function supports
788 two additional argument values:
789 <literal>'source'</literal> and <literal>'build'</literal>.
790 The <literal>'source'</literal> argument
791 specifies that decisions involving
792 whether target files have changed
793 since a previous build
794 should use the same behavior
795 for the decisions configured for source files
796 (using the &SourceSignatures; function).
803 TargetSignatures('source')
804 SourceSignatures('timestamp')
809 All files, both targets and sources,
810 will use modification times
811 when deciding if an input file
812 has changed since the last
813 time a target was built.
819 Lastly, the <literal>'build'</literal> argument
820 specifies that &SCons; should examine
821 the build status of a target file
822 and always rebuild a "downstream" target
823 if the target file was itself rebuilt,
824 without re-examining the contents or timestamp
825 of the newly-built target file.
826 If the target file was not rebuilt during
827 this &scons; invocation,
828 then the target file will be examined
829 the same way as configured by
830 the &SourceSignature; call
831 to decide if it has changed.
837 This mimics the behavior of
838 <literal>build signatures</literal>
839 in earlier versions of &SCons;.
840 A &buildsignature; re-combined
841 signatures of all the input files
842 that went into making the target file,
843 so that the target file itself
844 did not need to have its contents read
845 to compute an MD5 signature.
846 This can improve performance for some configurations,
847 but is generally not as effective as using
848 <literal>Decider('MD5-timestamp')</literal>.
857 <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title>
861 Now suppose that our "Hello, World!" program
862 actually has an <literal>#include</literal> line
863 to include the &hello_h; file in the compilation:
868 #include <hello.h>
872 printf("Hello, %s!\n", string);
878 And, for completeness, the &hello_h; file looks like this:
884 #define string "world"
889 In this case, we want &SCons; to recognize that,
890 if the contents of the &hello_h; file change,
891 the &hello; program must be recompiled.
892 To do this, we need to modify the
893 &SConstruct; file like so:
899 Program('hello.c', CPPPATH = '.')
904 The &cv-link-CPPPATH; value
905 tells &SCons; to look in the current directory
906 (<literal>'.'</literal>)
907 for any files included by C source files
908 (<filename>.c</filename> or <filename>.h</filename> files).
909 With this assignment in the &SConstruct; file:
914 % <userinput>scons -Q hello</userinput>
915 cc -o hello.o -c -I. hello.c
917 % <userinput>scons -Q hello</userinput>
918 scons: `hello' is up to date.
919 % <userinput>edit hello.h</userinput>
920 [CHANGE THE CONTENTS OF hello.h]
921 % <userinput>scons -Q hello</userinput>
922 cc -o hello.o -c -I. hello.c
928 First, notice that &SCons;
929 added the <literal>-I.</literal> argument
930 from the &cv-CPPPATH; variable
931 so that the compilation would find the
932 &hello_h; file in the local directory.
938 Second, realize that &SCons; knows that the &hello;
939 program must be rebuilt
940 because it scans the contents of
942 for the <literal>#include</literal> lines that indicate
943 another file is being included in the compilation.
944 &SCons; records these as
945 <emphasis>implicit dependencies</emphasis>
948 when the &hello_h; file changes,
949 &SCons; realizes that the &hello_c; file includes it,
950 and rebuilds the resulting &hello; program
951 that depends on both the &hello_c; and &hello_h; files.
957 Like the &cv-link-LIBPATH; variable,
958 the &cv-CPPPATH; variable
959 may be a list of directories,
960 or a string separated by
961 the system-specific path separation character
962 (':' on POSIX/Linux, ';' on Windows).
963 Either way, &SCons; creates the
964 right command-line options
965 so that the following example:
970 Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
975 Will look like this on POSIX or Linux:
980 % <userinput>scons -Q hello</userinput>
981 cc -o hello.o -c -Iinclude -I/home/project/inc hello.c
987 And like this on Windows:
992 C:\><userinput>scons -Q hello.exe</userinput>
993 cl /Fohello.obj /c hello.c /nologo /Iinclude /I\home\project\inc
994 link /nologo /OUT:hello.exe hello.obj
1000 <title>Caching Implicit Dependencies</title>
1004 Scanning each file for <literal>#include</literal> lines
1005 does take some extra processing time.
1006 When you're doing a full build of a large system,
1007 the scanning time is usually a very small percentage
1008 of the overall time spent on the build.
1009 You're most likely to notice the scanning time,
1010 however, when you <emphasis>rebuild</emphasis>
1011 all or part of a large system:
1012 &SCons; will likely take some extra time to "think about"
1013 what must be built before it issues the
1015 (or decides that everything is up to date
1016 and nothing must be rebuilt).
1019 Isn't this expensive? The answer is, it depends. If you do a full build of a
1020 large system, the scanning time is insignificant. If you do a rebuild of a
1021 large system, then Cons will spend a fair amount of time thinking about it
1022 before it decides that nothing has to be done (although not necessarily more
1023 time than make!). The good news is that Cons makes it very easy to
1024 intelligently subset your build, when you are working on localized changes.
1031 In practice, having &SCons; scan files saves time
1032 relative to the amount of potential time
1033 lost to tracking down subtle problems
1034 introduced by incorrect dependencies.
1035 Nevertheless, the "waiting time"
1036 while &SCons; scans files can annoy
1037 individual developers waiting for their builds to finish.
1038 Consequently, &SCons; lets you cache
1039 the implicit dependencies
1040 that its scanners find,
1041 for use by later builds.
1042 You can do this by specifying the
1043 &implicit-cache; option on the command line:
1048 % <userinput>scons -Q --implicit-cache hello</userinput>
1049 cc -o hello.o -c hello.c
1051 % <userinput>scons -Q hello</userinput>
1052 scons: `hello' is up to date.
1057 If you don't want to specify &implicit-cache;
1058 on the command line each time,
1059 you can make it the default behavior for your build
1060 by setting the &implicit_cache; option
1061 in an &SConscript; file:
1066 SetOption('implicit_cache', 1)
1071 &SCons; does not cache implicit dependencies like this by default
1072 because the &implicit-cache; causes &SCons; to simply use the implicit
1073 dependencies stored during the last run, without any checking
1074 for whether or not those dependencies are still correct.
1075 Specifically, this means &implicit-cache; instructs &SCons;
1076 to <emphasis>not</emphasis> rebuild "correctly" in the
1087 When &implicit-cache; is used, &SCons; will ignore any changes that
1088 may have been made to search paths
1089 (like &cv-CPPPATH; or &cv-LIBPATH;,).
1090 This can lead to &SCons; not rebuilding a file if a change to
1091 &cv-CPPPATH; would normally cause a different, same-named file from
1092 a different directory to be used.
1100 When &implicit-cache; is used, &SCons; will not detect if a
1101 same-named file has been added to a directory that is earlier in
1102 the search path than the directory in which the file was found
1111 <title>The &implicit-deps-changed; Option</title>
1115 When using cached implicit dependencies,
1116 sometimes you want to "start fresh"
1117 and have &SCons; re-scan the files
1118 for which it previously cached the dependencies.
1120 if you have recently installed a new version of
1121 external code that you use for compilation,
1122 the external header files will have changed
1123 and the previously-cached implicit dependencies
1124 will be out of date.
1125 You can update them by
1126 running &SCons; with the &implicit-deps-changed; option:
1131 % <userinput>scons -Q --implicit-deps-changed hello</userinput>
1132 cc -o hello.o -c hello.c
1134 % <userinput>scons -Q hello</userinput>
1135 scons: `hello' is up to date.
1140 In this case, &SCons; will re-scan all of the implicit dependencies
1141 and cache updated copies of the information.
1148 <title>The &implicit-deps-unchanged; Option</title>
1152 By default when caching dependencies,
1153 &SCons; notices when a file has been modified
1154 and re-scans the file for any updated
1155 implicit dependency information.
1156 Sometimes, however, you may want
1157 to force &SCons; to use the cached implicit dependencies,
1158 even if the source files changed.
1159 This can speed up a build for example,
1160 when you have changed your source files
1161 but know that you haven't changed
1162 any <literal>#include</literal> lines.
1164 you can use the &implicit-deps-unchanged; option:
1169 % <userinput>scons -Q --implicit-deps-unchanged hello</userinput>
1170 cc -o hello.o -c hello.c
1172 % <userinput>scons -Q hello</userinput>
1173 scons: `hello' is up to date.
1179 &SCons; will assume that the cached implicit
1180 dependencies are correct and
1181 will not bother to re-scan changed files.
1182 For typical builds after small,
1183 incremental changes to source files,
1184 the savings may not be very big,
1185 but sometimes every bit of
1186 improved performance counts.
1195 <title>XXX max drift</title>
1197 XXX SetOption('max_drift')
1206 <title>Explicit Dependencies: the &Depends; Function</title>
1210 Sometimes a file depends on another file
1211 that is not detected by an &SCons; scanner.
1213 &SCons; allows you to specific explicitly that one file
1214 depends on another file,
1215 and must be rebuilt whenever that file changes.
1216 This is specified using the &Depends; method:
1221 hello = Program('hello.c')
1222 Depends(hello, 'other_file')
1225 <!-- XXX mention that you can use arrays for target and source? -->
1228 % <userinput>scons -Q hello</userinput>
1229 cc -c hello.c -o hello.o
1231 % <userinput>scons -Q hello</userinput>
1232 scons: `hello' is up to date.
1233 % <userinput>edit other_file</userinput>
1234 [CHANGE THE CONTENTS OF other_file]
1235 % <userinput>scons -Q hello</userinput>
1236 cc -c hello.c -o hello.o
1242 Note that the dependency
1243 (the second argument to &Depends;)
1244 may also be a list of Node objects
1245 (for example, as returned by a call to a Builder):
1250 hello = Program('hello.c')
1251 goodbye = Program('goodbye.c')
1252 Depends(hello, goodbye)
1257 in which case the dependency or dependencies
1258 will be built before the target(s):
1263 % <userinput>scons -Q hello</userinput>
1264 cc -c goodbye.c -o goodbye.o
1265 cc -o goodbye goodbye.o
1266 cc -c hello.c -o hello.o
1273 <title>Dependencies From External Files: the &ParseDepends;
1278 &SCons; has built-in scanners for a number of languages. Sometimes
1279 these scanners fail to extract certain implicit dependencies due
1280 to limitations of the scanner implementation.
1286 The following example illustrates a case where the built-in C
1287 scanner is unable to extract the implicit dependency on a header
1293 #define FOO_HEADER <foo.h>
1302 % <userinput>scons -Q</userinput>
1303 cc -o hello.o -c -I. hello.c
1305 % <userinput>edit foo.h</userinput>
1306 [CHANGE CONTENTS OF foo.h]
1307 % <userinput>scons -Q</userinput>
1308 scons: `.' is up to date.
1313 Apparently, the scanner does not know about the header dependency.
1314 Being not a full-fledged C preprocessor, the scanner does not
1321 In these cases, you may also use the compiler to extract the
1322 implicit dependencies. &ParseDepends; can parse the contents of
1323 the compiler output in the style of &Make;, and explicitly
1324 establish all of the listed dependencies.
1330 The following example uses &ParseDepends; to process a compiler
1331 generated dependency file which is generated as a side effect
1332 during compilation of the object file:
1336 <!-- XXX The ParseDepends example below fakes proper working by a
1337 priori specification of the dependency file. The produced hello.d
1338 file is not found (or used) for unknown reasons. -->
1341 obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
1342 SideEffect('hello.d', obj)
1343 ParseDepends('hello.d')
1344 Program('hello', obj)
1348 % <userinput>scons -Q</userinput>
1349 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1351 % <userinput>edit foo.h</userinput>
1352 [CHANGE CONTENTS OF foo.h]
1353 % <userinput>scons -Q</userinput>
1354 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1359 Parsing dependencies from a compiler-generated
1360 <filename>.d</filename> file has a chicken-and-egg problem, that
1361 causes unnecessary rebuilds:
1368 <scons_output example="parsedeprebuild" os="posix">
1369 <scons_output_command>scons -Q</scons_output_command>
1370 <scons_output_command>scons -Q</scons_output_command>
1371 <scons_output_command>scons -Q</scons_output_command>
1376 % <userinput>scons -Q</userinput>
1377 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1379 % <userinput>scons -Q --debug=explain</userinput>
1380 scons: rebuilding `hello.o' because `foo.h' is a new dependency
1381 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1382 % <userinput>scons -Q</userinput>
1383 scons: `.' is up to date.
1388 In the first pass, the dependency file is generated while the
1389 object file is compiled. At that time, &SCons; does not know about
1390 the dependency on <filename>foo.h</filename>. In the second pass,
1391 the object file is regenerated because <filename>foo.h</filename>
1392 is detected as a new dependency.
1398 &ParseDepends; immediately reads the specified file at invocation
1399 time and just returns if the file does not exist. A dependency
1400 file generated during the build process is not automatically
1401 parsed again. Hence, the compiler-extracted dependencies are not
1402 stored in the signature database during the same build pass. This
1403 limitation of &ParseDepends; leads to unnecessary recompilations.
1404 Therefore, &ParseDepends; should only be used if scanners are not
1405 available for the employed language or not powerful enough for the
1413 <title>Ignoring Dependencies: the &Ignore; Function</title>
1417 Sometimes it makes sense
1418 to not rebuild a program,
1419 even if a dependency file changes.
1421 you would tell &SCons; specifically
1422 to ignore a dependency as follows:
1427 hello_obj=Object('hello.c')
1428 hello = Program(hello_obj)
1429 Ignore(hello_obj, 'hello.h')
1432 <!-- XXX mention that you can use lists for target and source? -->
1435 <scons_output example="ignore">
1436 <scons_output_command>scons -Q hello</scons_output_command>
1437 <scons_output_command>scons -Q hello</scons_output_command>
1438 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
1439 <scons_output_command>scons -Q hello</scons_output_command>
1440 XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
1445 % <userinput>scons -Q hello</userinput>
1446 cc -c -o hello.o hello.c
1448 % <userinput>scons -Q hello</userinput>
1449 scons: `hello' is up to date.
1450 % <userinput>edit hello.h</userinput>
1451 [CHANGE THE CONTENTS OF hello.h]
1452 % <userinput>scons -Q hello</userinput>
1453 scons: `hello' is up to date.
1458 Now, the above example is a little contrived,
1459 because it's hard to imagine a real-world situation
1460 where you wouldn't want to rebuild &hello;
1461 if the &hello_h; file changed.
1462 A more realistic example
1463 might be if the &hello;
1464 program is being built in a
1465 directory that is shared between multiple systems
1466 that have different copies of the
1467 &stdio_h; include file.
1469 &SCons; would notice the differences between
1470 the different systems' copies of &stdio_h;
1471 and would rebuild &hello;
1472 each time you change systems.
1473 You could avoid these rebuilds as follows:
1478 hello = Program('hello.c', CPPPATH=['/usr/include'])
1479 Ignore(hello, '/usr/include/stdio.h')
1483 &Ignore; can also be used to prevent a generated file from being built
1484 by default. This is due to the fact that directories depend on
1485 their contents. So to ignore a generated file from the default build,
1486 you specify that the directory should ignore the generated file.
1487 Note that the file will still be built if the user specifically
1488 requests the target on scons command line, or if the file is
1489 a dependency of another file which is requested and/or is built
1494 hello_obj=Object('hello.c')
1495 hello = Program(hello_obj)
1496 Ignore('.',[hello,hello_obj])
1500 % <userinput>scons -Q</userinput>
1501 scons: `.' is up to date.
1502 % <userinput>scons -Q hello</userinput>
1503 cc -o hello.o -c hello.c
1505 % <userinput>scons -Q hello</userinput>
1506 scons: `hello' is up to date.
1511 <title>Order-Only Dependencies: the &Requires; Function</title>
1516 it may be useful to specify that a certain
1517 file or directory must, if necessary,
1518 be built or created before some other target is built,
1519 but that changes to that file or directory
1520 do <emphasis>not</emphasis>
1521 require that the target itself be rebuilt.
1522 Such a relationship is called an
1523 <emphasis>order-only dependency</emphasis>
1524 because it only affects the order in which
1525 things must be built--the dependency before the target--but
1526 it is not a strict dependency relationship
1527 because the target should not
1528 change in response to changes in the dependent file.
1534 For example, suppose that you want to create a file
1535 every time you run a build
1536 that identifies the time the build was performed,
1537 the version number, etc.,
1538 and which is included in every program that you build.
1539 The version file's contents will change every build.
1540 If you specify a normal dependency relationship,
1541 then every program that depends on
1542 that file would be rebuilt every time you ran &SCons;.
1543 For example, we could use some Python code in
1544 a &SConstruct; file to create a new <filename>version.c</filename> file
1545 with a string containing the current date every time
1547 and then link a program with the resulting object file
1548 by listing <filename>version.c</filename> in the sources:
1555 version_c_text = """
1557 """ % time.ctime(time.time())
1558 open('version.c', 'w').write(version_c_text)
1560 hello = Program(['hello.c', 'version.c'])
1565 If we list <filename>version.c</filename> as an actual source file,
1566 though, then the <filename>version.o</filename> file
1567 will get rebuilt every time we run &SCons;
1568 (because the &SConstruct; file itself changes
1569 the contents of <filename>version.c</filename>)
1570 and the <filename>hello</filename> executable
1571 will get re-linked every time
1572 (because the <filename>version.o</filename> file changes):
1577 % <userinput>scons -Q hello</userinput>
1578 cc -o hello.o -c hello.c
1579 cc -o version.o -c version.c
1580 cc -o hello hello.o version.o
1581 % <userinput>sleep 1</userinput>
1582 % <userinput>scons -Q hello</userinput>
1583 cc -o version.o -c version.c
1584 cc -o hello hello.o version.o
1585 % <userinput>sleep 1</userinput>
1586 % <userinput>scons -Q hello</userinput>
1587 cc -o version.o -c version.c
1588 cc -o hello hello.o version.o
1593 (Note that for the above example to work,
1594 we &sleep; for one second in between each run,
1595 so that the &SConstruct; file will create a
1596 <filename>version.c</filename> file with a time string
1597 that's one second later than the previous run.)
1603 One solution is to use the &Requires; function
1604 to specify that the <filename>version.o</filename>
1605 must be rebuilt before it is used by the link step,
1606 but that changes to <filename>version.o</filename>
1607 should not actually cause the <filename>hello</filename>
1608 executable to be re-linked:
1615 version_c_text = """
1617 """ % time.ctime(time.time())
1618 open('version.c', 'w').write(version_c_text)
1620 version_obj = Object('version.c')
1622 hello = Program('hello.c',
1623 LINKFLAGS = str(version_obj[0]))
1625 Requires(hello, version_obj)
1630 Notice that because we can no longer list <filename>version.c</filename>
1631 as one of the sources for the <filename>hello</filename> program,
1632 we have to find some other way to get it into the link command line.
1633 For this example, we're cheating a bit and stuffing the
1634 object file name (extracted from <literal>version_obj</literal>
1635 list returned by the &b-Object; call)
1636 into the &cv-link-LINKFLAGS; variable,
1637 because &cv-LINKFLAGS; is already included
1638 in the &cv-link-LINKCOM; command line.
1645 we get the desired behavior of only
1646 re-linking the <filename>hello</filename> executable
1647 when the <filename>hello.c</filename> has changed,
1648 even though the <filename>version.o</filename> is rebuilt
1649 (because the &SConstruct; file still changes the
1650 <filename>version.c</filename> contents directly each run):
1655 % <userinput>scons -Q hello</userinput>
1656 cc -o version.o -c version.c
1657 cc -o hello.o -c hello.c
1658 cc -o hello version.o hello.o
1659 % <userinput>sleep 1</userinput>
1660 % <userinput>scons -Q hello</userinput>
1661 cc -o version.o -c version.c
1662 scons: `hello' is up to date.
1663 % <userinput>sleep 1</userinput>
1664 % <userinput>edit hello.c</userinput>
1665 [CHANGE THE CONTENTS OF hello.c]
1666 % <userinput>scons -Q hello</userinput>
1667 cc -o version.o -c version.c
1668 cc -o hello.o -c hello.c
1669 cc -o hello version.o hello.o
1670 % <userinput>sleep 1</userinput>
1671 % <userinput>scons -Q hello</userinput>
1672 cc -o version.o -c version.c
1673 scons: `hello' is up to date.
1679 <title>The &AlwaysBuild; Function</title>
1683 How &SCons; handles dependencies can also be affected
1684 by the &AlwaysBuild; method.
1685 When a file is passed to the &AlwaysBuild; method,
1691 hello = Program('hello.c')
1697 Then the specified target file (&hello; in our example)
1698 will always be considered out-of-date and
1699 rebuilt whenever that target file is evaluated
1700 while walking the dependency graph:
1705 % <userinput>scons -Q</userinput>
1706 cc -o hello.o -c hello.c
1708 % <userinput>scons -Q</userinput>
1714 The &AlwaysBuild; function has a somewhat misleading name,
1715 because it does not actually mean the target file will
1716 be rebuilt every single time &SCons; is invoked.
1717 Instead, it means that the target will, in fact,
1718 be rebuilt whenever the target file is encountered
1719 while evaluating the targets specified on
1720 the command line (and their dependencies).
1721 So specifying some other target on the command line,
1722 a target that does <emphasis>not</emphasis>
1723 itself depend on the &AlwaysBuild; target,
1724 will still be rebuilt only if it's out-of-date
1725 with respect to its dependencies:
1730 % <userinput>scons -Q</userinput>
1731 cc -o hello.o -c hello.c
1733 % <userinput>scons -Q hello.o</userinput>
1734 scons: `hello.o' is up to date.
1739 XXX AlwaysBuild() and Alias Nodes
1741 XXX AlwaysBuild() and Dir Nodes
1743 XXX AlwaysBuild() with no sources
1752 <title>The &Salt; Method</title>
1756 XXX Salt() (are we going to implement this ?)
1758 original Cons classic POD documentation:
1760 =head2 The C<Salt> method
1762 The C<Salt> method adds a constant value to the signature calculation
1763 for every derived file. It is invoked as follows:
1767 Changing the Salt value will force a complete rebuild of every derived
1768 file. This can be used to force rebuilds in certain desired
1769 circumstances. For example,
1773 Would force a complete rebuild of every derived file whenever the
1774 operating system on which the build is performed (as reported by C<uname