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.o</userinput>
276 cc -o hello.o -c hello.c
277 % <userinput>touch hello.c</userinput>
278 % <userinput>scons -Q hello.o</userinput>
279 cc -o hello.o -c hello.c
284 And, in fact, because this behavior is the same
285 as the behavior of &Make;,
286 you can also use the string <literal>'make'</literal>
287 as a synonym for <literal>'timestamp-newer'</literal>
288 when calling the &Decider; function:
299 One drawback to using times stamps exactly like &Make;
300 is that if an input file's modification time suddenly
301 becomes <emphasis>older</emphasis> than a target file,
302 the target file will not be rebuilt.
303 This can happen if an old copy of a source file is restored
304 from a backup archive, for example.
305 The contents of the restored file will likely be different
306 than they were the last time a dependent target was built,
307 but the target won't be rebuilt
308 because the modification time of the source file
309 is not newer than the target.
315 Because &SCons; actually stores information
316 about the source files' time stamps whenever a target is built,
317 it can handle this situation by checking for
318 an exact match of the source file time stamp,
319 instead of just whether or not the source file
320 is newer than the target file.
321 To do this, specify the argument
322 <literal>'timestamp-match'</literal>
323 when calling the &Decider; function:
329 Decider('timestamp-match')
334 When configured this way,
335 &SCons; will rebuild a target whenever
336 a source file's modification time has changed.
337 So if we use the <literal>touch -t</literal>
338 option to change the modification time of
339 &hello_c; to an old date (January 1, 1989),
340 &SCons; will still rebuild the target file:
345 % <userinput>scons -Q hello.o</userinput>
346 cc -o hello.o -c hello.c
347 % <userinput>touch -t 198901010000 hello.c</userinput>
348 % <userinput>scons -Q hello.o</userinput>
349 cc -o hello.o -c hello.c
354 In general, the only reason to prefer
355 <literal>timestamp-newer</literal>
357 <literal>timestamp-match</literal>,
358 would be if you have some specific reason
359 to require this &Make;-like behavior of
360 not rebuilding a target when an otherwise-modified
361 source file is older.
368 <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title>
372 As a performance enhancement,
373 &SCons; provides a way to use
374 MD5 checksums of file contents
375 but to read those contents
376 only when the file's timestamp has changed.
377 To do this, call the &Decider;
378 function with <literal>'MD5-timestamp'</literal>
385 Decider('MD5-timestamp')
390 So configured, &SCons; will still behave like
391 it does when using <literal>Decider('MD5')</literal>:
397 We want to generate the output as follows,
398 but our "surrogate" system for generating the
399 output seems to get this wrong.
400 Just in-line the output for now.
402 <scons_output example="MD5-timestamp" os="posix">
403 <scons_output_command>scons -Q hello</scons_output_command>
404 <scons_output_command>touch hello.c</scons_output_command>
405 <scons_output_command>scons -Q hello</scons_output_command>
406 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
407 <scons_output_command>scons -Q hello</scons_output_command>
413 % <userinput>scons -Q hello</userinput>
414 cc -o hello.o -c hello.c
416 % <userinput>touch hello.c</userinput>
417 % <userinput>scons -Q hello</userinput>
418 scons: `hello' is up to date.
419 % <userinput>edit hello.c</userinput>
420 [CHANGE THE CONTENTS OF hello.c]
421 % <userinput>scons -Q hello</userinput>
422 cc -o hello.o -c hello.c
428 However, the second call to &SCons; in the above output,
429 when the build is up-to-date,
430 will have been performed by simply looking at the
431 modification time of the &hello_c; file,
432 not by opening it and performing
433 an MD5 checksum calcuation on its contents.
434 This can significantly speed up many up-to-date builds.
440 The only drawback to using
441 <literal>Decider('MD5-timestamp')</literal>
442 is that &SCons; will <emphasis>not</emphasis>
443 rebuild a target file if a source file was modified
444 within one second of the last time &SCons; built the file.
445 While most developers are programming,
446 this isn't a problem in practice,
447 since it's unlikely that someone will have built
448 and then thought quickly enough to make a substantive
449 change to a source file within one second.
450 Certain build scripts or
451 continuous integration tools may, however,
452 rely on the ability to apply changes to files
453 automatically and then rebuild as quickly as possible,
455 <literal>Decider('MD5-timestamp')</literal>
456 may not be appropriate.
463 <title>Writing Your Own Custom &Decider; Function</title>
467 The different string values that we've passed to
468 the &Decider; function are essentially used by &SCons;
469 to pick one of several specific internal functions
470 that implement various ways of deciding if a dependency
471 (usually a source file)
472 has changed since a target file has been built.
474 you can also supply your own function
475 to decide if a dependency has changed.
481 For example, suppose we have an input file
482 that contains a lot of data,
483 in some specific regular format,
484 that is used to rebuild a lot of different target files,
485 but each target file really only depends on
486 one particular section of the input file.
487 We'd like to have each target file depend on
488 only its section of the input file.
489 However, since the input file may contain a lot of data,
490 we want to open the input file only if its timestamp has changed.
491 This could done with a custom
492 &Decider; function that might look something like this:
498 def decide_if_changed(dependency, target, prev_ni):
499 if self.get_timestamp() != prev_ni.timestamp:
500 dep = str(dependency)
502 if specific_part_of_file_has_changed(dep, tgt):
505 Decider(decide_if_changed)
510 Note that in the function definition,
511 the <varname>dependency</varname>
512 (input file) is the first argument,
513 and then the ⌖.
514 Both of these are passed to the functions as
515 SCons &Node; objects,
516 which we convert to strings using the Python
517 <function>str()</function>.
523 The third argument, <varname>prev_ni</varname>,
524 is an object that holds the
525 signature or timestamp information
526 that was recorded about the dependency
527 the last time the target was built.
528 A <varname>prev_ni</varname> object can hold
529 different information,
530 depending on the type of thing that the
531 <varname>dependency</varname> argument represents.
533 the <varname>prev_ni</varname> object
534 has the following attributes:
545 The <emphasis>content signature</emphasis>,
546 or MD5 checksum, of the contents of the
547 <varname>dependency</varname>
548 file the list time the ⌖ was built.
559 The size in bytes of the <varname>dependency</varname>
560 file the list time the target was built.
567 <term>.timestamp</term>
571 The modification time of the <varname>dependency</varname>
572 file the list time the ⌖ was built.
582 Note that ignoring some of the arguments
583 in your custom &Decider; function
584 is a perfectly normal thing to do,
585 if they don't impact the way you want to
586 decide if the dependency file has changed.
593 <title>Mixing Different Ways of Deciding If a File Has Changed</title>
597 The previous examples have all demonstrated calling
598 the global &Decider; function
599 to configure all dependency decisions that &SCons; makes.
600 Sometimes, however, you want to be able to configure
601 different decision-making for different targets.
602 When that's necessary, you can use the
603 <function>env.Decider</function>
604 method to affect only the configuration
605 decisions for targets built with a
606 specific construction environment.
612 For example, if we arbitrarily want to build
613 one program using MD5 checkums
614 and another using file modification times
616 we might configure it this way:
621 env1 = Environment(CPPPATH = ['.'])
623 env2.Decider('timestamp-match')
624 env1.Program('prog-MD5', 'program1.c')
625 env2.Program('prog-timestamp', 'program2.c')
630 If both of the programs include the same
631 <filename>inc.h</filename> file,
632 then updating the modification time of
633 <filename>inc.h</filename>
634 (using the &touch; command)
635 will cause only <filename>prog-timestamp</filename>
641 % <userinput>scons -Q</userinput>
642 cc -o program1.o -c -I. program1.c
643 cc -o prog-MD5 program1.o
644 cc -o program2.o -c -I. program2.c
645 cc -o prog-timestamp program2.o
646 % <userinput>touch inc.h</userinput>
647 % <userinput>scons -Q</userinput>
648 cc -o program2.o -c -I. program2.c
649 cc -o prog-timestamp program2.o
657 <title>Older Functions for Deciding When an Input File Has Changed</title>
661 &SCons; still supports two functions that used to be the
662 primary methods for configuring the
663 decision about whether or not an input file has changed.
664 Although they're not officially deprecated yet,
665 their use is discouraged,
666 mainly because they rely on a somewhat
667 confusing distinction between how
668 source files and target files are handled.
669 These functions are documented here mainly in case you
670 encounter them in existing &SConscript; files.
675 <title>The &SourceSignatures; Function</title>
679 The &SourceSignatures; function is fairly straightforward,
680 and supports two different argument values
681 to configure whether source file changes should be decided
682 using MD5 signatures:
688 SourceSignatures('MD5')
693 Or using time stamps:
699 SourceSignatures('timestamp')
704 These are roughly equivalent to specifying
705 <function>Decider('MD5')</function>
707 <function>Decider('timestamp-match')</function>,
709 although it only affects how SCons makes
710 decisions about dependencies on
711 <emphasis>source</emphasis> files--that is,
712 files that are not built from any other files.
719 <title>The &TargetSignatures; Function</title>
723 The &TargetSignatures; function
724 specifies how &SCons; decides
725 when a target file has changed
726 <emphasis>when it is used as a
727 dependency of (input to) another target</emphasis>--that is,
728 the &TargetSignatures; function configures
729 how the signatures of "intermediate" target files
730 are used when deciding if a "downstream" target file
733 This easily-overlooked distinction between
734 how &SCons; decides if the target itself must be rebuilt
735 and how the target is then used to decide if a different
736 target must be rebuilt is one of the confusing
737 things that has led to the &TargetSignatures;
738 and &SourceSignatures; functions being
739 replaced by the simpler &Decider; function.
746 The &TargetSignatures; function supports the same
747 <literal>'MD5'</literal> and <literal>'timestamp'</literal>
748 argument values that are supported by the &SourceSignatures;,
749 with the same meanings, but applied to target files.
750 That is, in the example:
756 TargetSignatures('MD5')
761 The MD5 checksum of the &hello_o; target file
762 will be used to decide if it has changed since the last
763 time the "downstream" &hello; target file was built.
770 TargetSignatures('timestamp')
775 The modification time of the &hello_o; target file
776 will be used to decide if it has changed since the last
777 time the "downstream" &hello; target file was built.
783 The &TargetSignatures; function supports
784 two additional argument values:
785 <literal>'source'</literal> and <literal>'build'</literal>.
786 The <literal>'source'</literal> argument
787 specifies that decisions involving
788 whether target files have changed
789 since a previous build
790 should use the same behavior
791 for the decisions configured for source files
792 (using the &SourceSignatures; function).
799 TargetSignatures('source')
800 SourceSignatures('timestamp')
805 All files, both targets and sources,
806 will use modification times
807 when deciding if an input file
808 has changed since the last
809 time a target was built.
815 Lastly, the <literal>'build'</literal> argument
816 specifies that &SCons; should examine
817 the build status of a target file
818 and always rebuild a "downstream" target
819 if the target file was itself rebuilt,
820 without re-examining the contents or timestamp
821 of the newly-built target file.
822 If the target file was not rebuilt during
823 this &scons; invocation,
824 then the target file will be examined
825 the same way as configured by
826 the &SourceSignature; call
827 to decide if it has changed.
833 This mimics the behavior of
834 <literal>build signatures</literal>
835 in earlier versions of &SCons;.
836 A &buildsignature; re-combined
837 signatures of all the input files
838 that went into making the target file,
839 so that the target file itself
840 did not need to have its contents read
841 to compute an MD5 signature.
842 This can improve performance for some configurations,
843 but is generally not as effective as using
844 <literal>Decider('MD5-timestamp')</literal>.
853 <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title>
857 Now suppose that our "Hello, World!" program
858 actually has an <literal>#include</literal> line
859 to include the &hello_h; file in the compilation:
864 #include <hello.h>
868 printf("Hello, %s!\n", string);
874 And, for completeness, the &hello_h; file looks like this:
880 #define string "world"
885 In this case, we want &SCons; to recognize that,
886 if the contents of the &hello_h; file change,
887 the &hello; program must be recompiled.
888 To do this, we need to modify the
889 &SConstruct; file like so:
895 Program('hello.c', CPPPATH = '.')
900 The &cv-link-CPPPATH; value
901 tells &SCons; to look in the current directory
902 (<literal>'.'</literal>)
903 for any files included by C source files
904 (<filename>.c</filename> or <filename>.h</filename> files).
905 With this assignment in the &SConstruct; file:
910 % <userinput>scons -Q hello</userinput>
911 cc -o hello.o -c -I. hello.c
913 % <userinput>scons -Q hello</userinput>
914 scons: `hello' is up to date.
915 % <userinput>edit hello.h</userinput>
916 [CHANGE THE CONTENTS OF hello.h]
917 % <userinput>scons -Q hello</userinput>
918 cc -o hello.o -c -I. hello.c
924 First, notice that &SCons;
925 added the <literal>-I.</literal> argument
926 from the &cv-CPPPATH; variable
927 so that the compilation would find the
928 &hello_h; file in the local directory.
934 Second, realize that &SCons; knows that the &hello;
935 program must be rebuilt
936 because it scans the contents of
938 for the <literal>#include</literal> lines that indicate
939 another file is being included in the compilation.
940 &SCons; records these as
941 <emphasis>implicit dependencies</emphasis>
944 when the &hello_h; file changes,
945 &SCons; realizes that the &hello_c; file includes it,
946 and rebuilds the resulting &hello; program
947 that depends on both the &hello_c; and &hello_h; files.
953 Like the &cv-link-LIBPATH; variable,
954 the &cv-CPPPATH; variable
955 may be a list of directories,
956 or a string separated by
957 the system-specific path separation character
958 (':' on POSIX/Linux, ';' on Windows).
959 Either way, &SCons; creates the
960 right command-line options
961 so that the following example:
966 Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
971 Will look like this on POSIX or Linux:
976 % <userinput>scons -Q hello</userinput>
977 cc -o hello.o -c -Iinclude -I/home/project/inc hello.c
983 And like this on Windows:
988 C:\><userinput>scons -Q hello.exe</userinput>
989 cl /Fohello.obj /c hello.c /nologo /Iinclude /I\home\project\inc
990 link /nologo /OUT:hello.exe hello.obj
996 <title>Caching Implicit Dependencies</title>
1000 Scanning each file for <literal>#include</literal> lines
1001 does take some extra processing time.
1002 When you're doing a full build of a large system,
1003 the scanning time is usually a very small percentage
1004 of the overall time spent on the build.
1005 You're most likely to notice the scanning time,
1006 however, when you <emphasis>rebuild</emphasis>
1007 all or part of a large system:
1008 &SCons; will likely take some extra time to "think about"
1009 what must be built before it issues the
1011 (or decides that everything is up to date
1012 and nothing must be rebuilt).
1015 Isn't this expensive? The answer is, it depends. If you do a full build of a
1016 large system, the scanning time is insignificant. If you do a rebuild of a
1017 large system, then Cons will spend a fair amount of time thinking about it
1018 before it decides that nothing has to be done (although not necessarily more
1019 time than make!). The good news is that Cons makes it very easy to
1020 intelligently subset your build, when you are working on localized changes.
1027 In practice, having &SCons; scan files saves time
1028 relative to the amount of potential time
1029 lost to tracking down subtle problems
1030 introduced by incorrect dependencies.
1031 Nevertheless, the "waiting time"
1032 while &SCons; scans files can annoy
1033 individual developers waiting for their builds to finish.
1034 Consequently, &SCons; lets you cache
1035 the implicit dependencies
1036 that its scanners find,
1037 for use by later builds.
1038 You can do this by specifying the
1039 &implicit-cache; option on the command line:
1044 % <userinput>scons -Q --implicit-cache hello</userinput>
1045 cc -o hello.o -c hello.c
1047 % <userinput>scons -Q hello</userinput>
1048 scons: `hello' is up to date.
1053 If you don't want to specify &implicit-cache;
1054 on the command line each time,
1055 you can make it the default behavior for your build
1056 by setting the &implicit_cache; option
1057 in an &SConscript; file:
1062 SetOption('implicit_cache', 1)
1067 &SCons; does not cache implicit dependencies like this by default
1068 because the &implicit-cache; causes &SCons; to simply use the implicit
1069 dependencies stored during the last run, without any checking
1070 for whether or not those dependencies are still correct.
1071 Specifically, this means &implicit-cache; instructs &SCons;
1072 to <emphasis>not</emphasis> rebuild "correctly" in the
1083 When &implicit-cache; is used, &SCons; will ignore any changes that
1084 may have been made to search paths
1085 (like &cv-CPPPATH; or &cv-LIBPATH;,).
1086 This can lead to &SCons; not rebuilding a file if a change to
1087 &cv-CPPPATH; would normally cause a different, same-named file from
1088 a different directory to be used.
1096 When &implicit-cache; is used, &SCons; will not detect if a
1097 same-named file has been added to a directory that is earlier in
1098 the search path than the directory in which the file was found
1107 <title>The &implicit-deps-changed; Option</title>
1111 When using cached implicit dependencies,
1112 sometimes you want to "start fresh"
1113 and have &SCons; re-scan the files
1114 for which it previously cached the dependencies.
1116 if you have recently installed a new version of
1117 external code that you use for compilation,
1118 the external header files will have changed
1119 and the previously-cached implicit dependencies
1120 will be out of date.
1121 You can update them by
1122 running &SCons; with the &implicit-deps-changed; option:
1127 % <userinput>scons -Q --implicit-deps-changed hello</userinput>
1128 cc -o hello.o -c hello.c
1130 % <userinput>scons -Q hello</userinput>
1131 scons: `hello' is up to date.
1136 In this case, &SCons; will re-scan all of the implicit dependencies
1137 and cache updated copies of the information.
1144 <title>The &implicit-deps-unchanged; Option</title>
1148 By default when caching dependencies,
1149 &SCons; notices when a file has been modified
1150 and re-scans the file for any updated
1151 implicit dependency information.
1152 Sometimes, however, you may want
1153 to force &SCons; to use the cached implicit dependencies,
1154 even if the source files changed.
1155 This can speed up a build for example,
1156 when you have changed your source files
1157 but know that you haven't changed
1158 any <literal>#include</literal> lines.
1160 you can use the &implicit-deps-unchanged; option:
1165 % <userinput>scons -Q --implicit-deps-unchanged hello</userinput>
1166 cc -o hello.o -c hello.c
1168 % <userinput>scons -Q hello</userinput>
1169 scons: `hello' is up to date.
1175 &SCons; will assume that the cached implicit
1176 dependencies are correct and
1177 will not bother to re-scan changed files.
1178 For typical builds after small,
1179 incremental changes to source files,
1180 the savings may not be very big,
1181 but sometimes every bit of
1182 improved performance counts.
1191 <title>XXX max drift</title>
1193 XXX SetOption('max_drift')
1202 <title>Explicit Dependencies: the &Depends; Function</title>
1206 Sometimes a file depends on another file
1207 that is not detected by an &SCons; scanner.
1209 &SCons; allows you to specific explicitly that one file
1210 depends on another file,
1211 and must be rebuilt whenever that file changes.
1212 This is specified using the &Depends; method:
1217 hello = Program('hello.c')
1218 Depends(hello, 'other_file')
1221 <!-- XXX mention that you can use arrays for target and source? -->
1224 % <userinput>scons -Q hello</userinput>
1225 cc -c hello.c -o hello.o
1227 % <userinput>scons -Q hello</userinput>
1228 scons: `hello' is up to date.
1229 % <userinput>edit other_file</userinput>
1230 [CHANGE THE CONTENTS OF other_file]
1231 % <userinput>scons -Q hello</userinput>
1232 cc -c hello.c -o hello.o
1238 Note that the dependency
1239 (the second argument to &Depends;)
1240 may also be a list of Node objects
1241 (for example, as returned by a call to a Builder):
1246 hello = Program('hello.c')
1247 goodbye = Program('goodbye.c')
1248 Depends(hello, goodbye)
1253 in which case the dependency or dependencies
1254 will be built before the target(s):
1259 % <userinput>scons -Q hello</userinput>
1260 cc -c goodbye.c -o goodbye.o
1261 cc -o goodbye goodbye.o
1262 cc -c hello.c -o hello.o
1269 <title>Dependencies From External Files: the &ParseDepends;
1274 &SCons; has built-in scanners for a number of languages. Sometimes
1275 these scanners fail to extract certain implicit dependencies due
1276 to limitations of the scanner implementation.
1282 The following example illustrates a case where the built-in C
1283 scanner is unable to extract the implicit dependency on a header
1289 #define FOO_HEADER <foo.h>
1298 % <userinput>scons -Q</userinput>
1299 cc -o hello.o -c -I. hello.c
1301 % <userinput>edit foo.h</userinput>
1302 [CHANGE CONTENTS OF foo.h]
1303 % <userinput>scons -Q</userinput>
1304 scons: `.' is up to date.
1309 Apparently, the scanner does not know about the header dependency.
1310 Being not a full-fledged C preprocessor, the scanner does not
1317 In these cases, you may also use the compiler to extract the
1318 implicit dependencies. &ParseDepends; can parse the contents of
1319 the compiler output in the style of &Make;, and explicitly
1320 establish all of the listed dependencies.
1326 The following example uses &ParseDepends; to process a compiler
1327 generated dependency file which is generated as a side effect
1328 during compilation of the object file:
1332 <!-- XXX The ParseDepends example below fakes proper working by a
1333 priori specification of the dependency file. The produced hello.d
1334 file is not found (or used) for unknown reasons. -->
1337 obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
1338 SideEffect('hello.d', obj)
1339 ParseDepends('hello.d')
1340 Program('hello', obj)
1344 % <userinput>scons -Q</userinput>
1345 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1347 % <userinput>edit foo.h</userinput>
1348 [CHANGE CONTENTS OF foo.h]
1349 % <userinput>scons -Q</userinput>
1350 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1355 Parsing dependencies from a compiler-generated
1356 <filename>.d</filename> file has a chicken-and-egg problem, that
1357 causes unnecessary rebuilds:
1364 <scons_output example="parsedeprebuild" os="posix">
1365 <scons_output_command>scons -Q</scons_output_command>
1366 <scons_output_command>scons -Q</scons_output_command>
1367 <scons_output_command>scons -Q</scons_output_command>
1372 % <userinput>scons -Q</userinput>
1373 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1375 % <userinput>scons -Q --debug=explain</userinput>
1376 scons: rebuilding `hello.o' because `foo.h' is a new dependency
1377 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1378 % <userinput>scons -Q</userinput>
1379 scons: `.' is up to date.
1384 In the first pass, the dependency file is generated while the
1385 object file is compiled. At that time, &SCons; does not know about
1386 the dependency on <filename>foo.h</filename>. In the second pass,
1387 the object file is regenerated because <filename>foo.h</filename>
1388 is detected as a new dependency.
1394 &ParseDepends; immediately reads the specified file at invocation
1395 time and just returns if the file does not exist. A dependency
1396 file generated during the build process is not automatically
1397 parsed again. Hence, the compiler-extracted dependencies are not
1398 stored in the signature database during the same build pass. This
1399 limitation of &ParseDepends; leads to unnecessary recompilations.
1400 Therefore, &ParseDepends; should only be used if scanners are not
1401 available for the employed language or not powerful enough for the
1409 <title>Ignoring Dependencies: the &Ignore; Function</title>
1413 Sometimes it makes sense
1414 to not rebuild a program,
1415 even if a dependency file changes.
1417 you would tell &SCons; specifically
1418 to ignore a dependency as follows:
1423 hello_obj=Object('hello.c')
1424 hello = Program(hello_obj)
1425 Ignore(hello_obj, 'hello.h')
1428 <!-- XXX mention that you can use lists for target and source? -->
1431 <scons_output example="ignore">
1432 <scons_output_command>scons -Q hello</scons_output_command>
1433 <scons_output_command>scons -Q hello</scons_output_command>
1434 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
1435 <scons_output_command>scons -Q hello</scons_output_command>
1436 XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
1441 % <userinput>scons -Q hello</userinput>
1442 cc -c -o hello.o hello.c
1444 % <userinput>scons -Q hello</userinput>
1445 scons: `hello' is up to date.
1446 % <userinput>edit hello.h</userinput>
1447 [CHANGE THE CONTENTS OF hello.h]
1448 % <userinput>scons -Q hello</userinput>
1449 scons: `hello' is up to date.
1454 Now, the above example is a little contrived,
1455 because it's hard to imagine a real-world situation
1456 where you wouldn't want to rebuild &hello;
1457 if the &hello_h; file changed.
1458 A more realistic example
1459 might be if the &hello;
1460 program is being built in a
1461 directory that is shared between multiple systems
1462 that have different copies of the
1463 &stdio_h; include file.
1465 &SCons; would notice the differences between
1466 the different systems' copies of &stdio_h;
1467 and would rebuild &hello;
1468 each time you change systems.
1469 You could avoid these rebuilds as follows:
1474 hello = Program('hello.c', CPPPATH=['/usr/include'])
1475 Ignore(hello, '/usr/include/stdio.h')
1479 &Ignore; can also be used to prevent a generated file from being built
1480 by default. This is due to the fact that directories depend on
1481 their contents. So to ignore a generated file from the default build,
1482 you specify that the directory should ignore the generated file.
1483 Note that the file will still be built if the user specifically
1484 requests the target on scons command line, or if the file is
1485 a dependency of another file which is requested and/or is built
1490 hello_obj=Object('hello.c')
1491 hello = Program(hello_obj)
1492 Ignore('.',[hello,hello_obj])
1496 % <userinput>scons -Q</userinput>
1497 scons: `.' is up to date.
1498 % <userinput>scons -Q hello</userinput>
1499 cc -o hello.o -c hello.c
1501 % <userinput>scons -Q hello</userinput>
1502 scons: `hello' is up to date.
1507 <title>Order-Only Dependencies: the &Requires; Function</title>
1512 it may be useful to specify that a certain
1513 file or directory must, if necessary,
1514 be built or created before some other target is built,
1515 but that changes to that file or directory
1516 do <emphasis>not</emphasis>
1517 require that the target itself be rebuilt.
1518 Such a relationship is called an
1519 <emphasis>order-only dependency</emphasis>
1520 because it only affects the order in which
1521 things must be built--the dependency before the target--but
1522 it is not a strict dependency relationship
1523 because the target should not
1524 change in response to changes in the dependent file.
1530 For example, suppose that you want to create a file
1531 every time you run a build
1532 that identifies the time the build was performed,
1533 the version number, etc.,
1534 and which is included in every program that you build.
1535 The version file's contents will change every build.
1536 If you specify a normal dependency relationship,
1537 then every program that depends on
1538 that file would be rebuilt every time you ran &SCons;.
1539 For example, we could use some Python code in
1540 a &SConstruct; file to create a new <filename>version.c</filename> file
1541 with a string containing the current date every time
1543 and then link a program with the resulting object file
1544 by listing <filename>version.c</filename> in the sources:
1551 version_c_text = """
1553 """ % time.ctime(time.time())
1554 open('version.c', 'w').write(version_c_text)
1556 hello = Program(['hello.c', 'version.c'])
1561 If we list <filename>version.c</filename> as an actual source file,
1562 though, then the <filename>version.o</filename> file
1563 will get rebuilt every time we run &SCons;
1564 (because the &SConstruct; file itself changes
1565 the contents of <filename>version.c</filename>)
1566 and the <filename>hello</filename> executable
1567 will get re-linked every time
1568 (because the <filename>version.o</filename> file changes):
1573 % <userinput>scons -Q hello</userinput>
1574 cc -o hello.o -c hello.c
1575 cc -o version.o -c version.c
1576 cc -o hello hello.o version.o
1577 % <userinput>sleep 1</userinput>
1578 % <userinput>scons -Q hello</userinput>
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
1589 (Note that for the above example to work,
1590 we &sleep; for one second in between each run,
1591 so that the &SConstruct; file will create a
1592 <filename>version.c</filename> file with a time string
1593 that's one second later than the previous run.)
1599 One solution is to use the &Requires; function
1600 to specify that the <filename>version.o</filename>
1601 must be rebuilt before it is used by the link step,
1602 but that changes to <filename>version.o</filename>
1603 should not actually cause the <filename>hello</filename>
1604 executable to be re-linked:
1611 version_c_text = """
1613 """ % time.ctime(time.time())
1614 open('version.c', 'w').write(version_c_text)
1616 version_obj = Object('version.c')
1618 hello = Program('hello.c',
1619 LINKFLAGS = str(version_obj[0]))
1621 Requires(hello, version_obj)
1626 Notice that because we can no longer list <filename>version.c</filename>
1627 as one of the sources for the <filename>hello</filename> program,
1628 we have to find some other way to get it into the link command line.
1629 For this example, we're cheating a bit and stuffing the
1630 object file name (extracted from <literal>version_obj</literal>
1631 list returned by the &b-Object; call)
1632 into the &cv-link-LINKFLAGS; variable,
1633 because &cv-LINKFLAGS; is already included
1634 in the &cv-link-LINKCOM; command line.
1641 we get the desired behavior of only
1642 re-linking the <filename>hello</filename> executable
1643 when the <filename>hello.c</filename> has changed,
1644 even though the <filename>version.o</filename> is rebuilt
1645 (because the &SConstruct; file still changes the
1646 <filename>version.c</filename> contents directly each run):
1651 % <userinput>scons -Q hello</userinput>
1652 cc -o version.o -c version.c
1653 cc -o hello.o -c hello.c
1654 cc -o hello version.o hello.o
1655 % <userinput>sleep 1</userinput>
1656 % <userinput>scons -Q hello</userinput>
1657 cc -o version.o -c version.c
1658 scons: `hello' is up to date.
1659 % <userinput>sleep 1</userinput>
1660 % <userinput>edit hello.c</userinput>
1661 [CHANGE THE CONTENTS OF hello.c]
1662 % <userinput>scons -Q hello</userinput>
1663 cc -o version.o -c version.c
1664 cc -o hello.o -c hello.c
1665 cc -o hello version.o hello.o
1666 % <userinput>sleep 1</userinput>
1667 % <userinput>scons -Q hello</userinput>
1668 cc -o version.o -c version.c
1669 scons: `hello' is up to date.
1675 <title>The &AlwaysBuild; Function</title>
1679 How &SCons; handles dependencies can also be affected
1680 by the &AlwaysBuild; method.
1681 When a file is passed to the &AlwaysBuild; method,
1687 hello = Program('hello.c')
1693 Then the specified target file (&hello; in our example)
1694 will always be considered out-of-date and
1695 rebuilt whenever that target file is evaluated
1696 while walking the dependency graph:
1701 % <userinput>scons -Q</userinput>
1702 cc -o hello.o -c hello.c
1704 % <userinput>scons -Q</userinput>
1710 The &AlwaysBuild; function has a somewhat misleading name,
1711 because it does not actually mean the target file will
1712 be rebuilt every single time &SCons; is invoked.
1713 Instead, it means that the target will, in fact,
1714 be rebuilt whenever the target file is encountered
1715 while evaluating the targets specified on
1716 the command line (and their dependencies).
1717 So specifying some other target on the command line,
1718 a target that does <emphasis>not</emphasis>
1719 itself depend on the &AlwaysBuild; target,
1720 will still be rebuilt only if it's out-of-date
1721 with respect to its dependencies:
1726 % <userinput>scons -Q</userinput>
1727 cc -o hello.o -c hello.c
1729 % <userinput>scons -Q hello.o</userinput>
1730 scons: `hello.o' is up to date.
1735 XXX AlwaysBuild() and Alias Nodes
1737 XXX AlwaysBuild() and Dir Nodes
1739 XXX AlwaysBuild() with no sources
1748 <title>The &Salt; Method</title>
1752 XXX Salt() (are we going to implement this ?)
1754 original Cons classic POD documentation:
1756 =head2 The C<Salt> method
1758 The C<Salt> method adds a constant value to the signature calculation
1759 for every derived file. It is invoked as follows:
1763 Changing the Salt value will force a complete rebuild of every derived
1764 file. This can be used to force rebuilds in certain desired
1765 circumstances. For example,
1769 Would force a complete rebuild of every derived file whenever the
1770 operating system on which the build is performed (as reported by C<uname