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:
39 <scons_example name="ex1">
40 <file name="SConstruct">
44 int main() { printf("Hello, world!\n"); }
48 <scons_output example="ex1" os="posix">
49 <scons_output_command>scons -Q</scons_output_command>
50 <scons_output_command>scons -Q</scons_output_command>
55 The second time it is executed,
56 &SCons; realizes that the &hello; program
57 is up-to-date with respect to the current &hello_c; source file,
58 and avoids rebuilding it.
59 You can see this more clearly by naming
60 the &hello; program explicitly on the command line:
64 <scons_output example="ex1" os="posix">
65 <scons_output_command>scons -Q hello</scons_output_command>
66 <scons_output_command>scons -Q hello</scons_output_command>
71 Note that &SCons; reports <literal>"...is up to date"</literal>
72 only for target files named explicitly on the command line,
73 to avoid cluttering the output.
78 <title>Deciding When an Input File Has Changed: the &Decider; Function</title>
82 Another aspect of avoiding unnecessary rebuilds
83 is the fundamental build tool behavior
84 of <emphasis>rebuilding</emphasis>
85 things when an input file changes,
86 so that the built software is up to date.
88 &SCons; keeps track of this through an
89 MD5 &signature;, or checksum, of the contents of each file,
90 although you can easily configure
92 modification times (or time stamps)
94 You can even specify your own Python function
95 for deciding if an input file has changed.
100 <title>Using MD5 Signatures to Decide if a File Has Changed</title>
105 &SCons; keeps track of whether a file has changed
106 based on an MD5 checksum of the file's contents,
107 not the file's modification time.
108 This means that you may be surprised by the
109 default &SCons; behavior if you are used to the
110 &Make; convention of forcing
111 a rebuild by updating the file's modification time
112 (using the &touch; command, for example):
116 <scons_output example="ex1" os="posix">
117 <scons_output_command>scons -Q hello</scons_output_command>
118 <scons_output_command>touch hello.c</scons_output_command>
119 <scons_output_command>scons -Q hello</scons_output_command>
124 Even though the file's modification time has changed,
125 &SCons; realizes that the contents of the
126 &hello_c; file have <emphasis>not</emphasis> changed,
127 and therefore that the &hello; program
129 This avoids unnecessary rebuilds when,
130 for example, someone rewrites the
131 contents of a file without making a change.
132 But if the contents of the file really do change,
133 then &SCons; detects the change
134 and rebuilds the program as required:
138 <scons_output example="ex1" os="posix">
139 <scons_output_command>scons -Q hello</scons_output_command>
140 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
141 <scons_output_command>scons -Q hello</scons_output_command>
146 Note that you can, if you wish,
147 specify this default behavior
148 (MD5 signatures) explicitly
149 using the &Decider; function as follows:
160 You can also use the string <literal>'content'</literal>
161 as a synonym for <literal>'MD5'</literal>
162 when calling the &Decider; function.
167 <title>Ramifications of Using MD5 Signatures</title>
171 Using MD5 signatures to decide if an input file has changed
172 has one surprising benefit:
173 if a source file has been changed
174 in such a way that the contents of the
175 rebuilt target file(s)
176 will be exactly the same as the last time
178 then any "downstream" target files
179 that depend on the rebuilt-but-not-changed target
180 file actually need not be rebuilt.
187 a user were to only change a comment in a &hello_c; file,
188 then the rebuilt &hello_o; file
189 would be exactly the same as the one previously built
190 (assuming the compiler doesn't put any build-specific
191 information in the object file).
192 &SCons; would then realize that it would not
193 need to rebuild the &hello; program as follows:
197 <scons_output example="ex1" os="posix">
198 <scons_output_command>scons -Q hello</scons_output_command>
199 <scons_output_command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command>
200 <scons_output_command>scons -Q hello</scons_output_command>
206 "short-circuits" any dependent builds
207 when it realizes that a target file
208 has been rebuilt to exactly the same file as the last build.
209 This does take some extra processing time
210 to read the contents of the target (&hello_o;) file,
211 but often saves time when the rebuild that was avoided
212 would have been time-consuming and expensive.
221 <title>Using Time Stamps to Decide If a File Has Changed</title>
225 If you prefer, you can
226 configure &SCons; to use the modification time
227 of a file, not the file contents,
228 when deciding if a target needs to be rebuilt.
229 &SCons; gives you two ways to use time stamps
230 to decide if an input file has changed
231 since the last time a target has been built.
237 The most familiar way to use time stamps
238 is the way &Make; does:
239 that is, have &SCons; decide
240 that a target must be rebuilt
241 if a source file's modification time is
242 <emphasis>newer</emphasis>
243 than the target file.
244 To do this, call the &Decider;
249 <scons_example name="newer">
250 <file name="SConstruct" printme="1">
252 Decider('timestamp-newer')
254 <file name="hello.c">
255 int main() { printf("Hello, world!\n"); }
261 This makes &SCons; act like &Make;
262 when a file's modification time is updated
263 (using the &touch; command, for example):
267 <scons_output example="newer" os="posix">
268 <scons_output_command>scons -Q hello</scons_output_command>
269 <scons_output_command>touch hello.c</scons_output_command>
270 <scons_output_command>scons -Q hello</scons_output_command>
275 And, in fact, because this behavior is the same
276 as the behavior of &Make;,
277 you can also use the string <literal>'make'</literal>
278 as a synonym for <literal>'timestamp-newer'</literal>
279 when calling the &Decider; function:
290 One drawback to using times stamps exactly like &Make;
291 is that if an input file's modification time suddenly
292 becomes <emphasis>older</emphasis> than a target file,
293 the target file will not be rebuilt.
294 This can happen if an old copy of a source file is restored
295 from a backup archive, for example.
296 The contents of the restored file will likely be different
297 than they were the last time a dependent target was built,
298 but the target won't be rebuilt
299 because the modification time of the source file
300 is not newer than the target.
306 Because &SCons; actually stores information
307 about the source files' time stamps whenever a target is built,
308 it can handle this situation by checking for
309 an exact match of the source file time stamp,
310 instead of just whether or not the source file
311 is newer than the target file.
312 To do this, specify the argument
313 <literal>'timestamp-match'</literal>
314 when calling the &Decider; function:
318 <scons_example name="match">
319 <file name="SConstruct" printme="1">
321 Decider('timestamp-match')
323 <file name="hello.c">
324 int main() { printf("Hello, world!\n"); }
330 When configured this way,
331 &SCons; will rebuild a target whenever
332 a source file's modification time has changed.
333 So if we use the <literal>touch -t</literal>
334 option to change the modification time of
335 &hello_c; to an old date (January 1, 1989),
336 &SCons; will still rebuild the target file:
340 <scons_output example="match" os="posix">
341 <scons_output_command>scons -Q hello</scons_output_command>
342 <scons_output_command>touch -t 198901010000 hello.c</scons_output_command>
343 <scons_output_command>scons -Q hello</scons_output_command>
348 In general, the only reason to prefer
349 <literal>timestamp-newer</literal>
351 <literal>timestamp-match</literal>,
352 would be if you have some specific reason
353 to require this &Make;-like behavior of
354 not rebuilding a target when an otherwise-modified
355 source file is older.
362 <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title>
366 As a performance enhancement,
367 &SCons; provides a way to use
368 MD5 checksums of file contents
369 but to read those contents
370 only when the file's timestamp has changed.
371 To do this, call the &Decider;
372 function with <literal>'MD5-timestamp'</literal>
377 <scons_example name="MD5-timestamp">
378 <file name="SConstruct" printme="1">
380 Decider('MD5-timestamp')
382 <file name="hello.c">
383 int main() { printf("Hello, world!\n"); }
389 So configured, &SCons will still behave like
390 it does when using <literal>Decider('MD5')</literal>:
396 We want to generate the output as follows,
397 but our "surrogate" system for generating the
398 output seems to get this wrong.
399 Just in-line the output for now.
401 <scons_output example="MD5-timestamp" os="posix">
402 <scons_output_command>scons -Q hello</scons_output_command>
403 <scons_output_command>touch hello.c</scons_output_command>
404 <scons_output_command>scons -Q hello</scons_output_command>
405 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
406 <scons_output_command>scons -Q hello</scons_output_command>
412 % <userinput>scons -Q hello</userinput>
413 cc -o hello.o -c hello.c
415 % <userinput>touch hello.c</userinput>
416 % <userinput>scons -Q hello</userinput>
417 scons: `hello' is up to date.
418 % <userinput>edit hello.c</userinput>
419 [CHANGE THE CONTENTS OF hello.c]
420 % <userinput>scons -Q hello</userinput>
421 cc -o hello.o -c hello.c
427 However, the second call to &SCons; in the above output,
428 when the build is up-to-date,
429 will have been performed by simply looking at the
430 modification time of the &hello_c; file,
431 not by opening it and performing
432 an MD5 checksum calcuation on its contents.
433 This can significantly speed up many up-to-date builds.
439 The only drawback to using
440 <literal>Decider('MD5-timestamp')</literal>
441 is that &SCons; will <emphasis>not</emphasis>
442 rebuild a target file if a source file was modified
443 within one second of the last time &SCons; built the file.
444 While most developers are programming,
445 this isn't a problem in practice,
446 since it's unlikely that someone will have built
447 and then thought quickly enough to make a substantive
448 change to a source file within one second.
449 Certain build scripts or
450 continuous integration tools may, however,
451 rely on the ability to apply changes to files
452 automatically and then rebuild as quickly as possible,
454 <literal>Decider('MD5-timestamp')</literal>
455 may not be appropriate.
462 <title>Writing Your Own Custom &Decider; Function</title>
466 The different string values that we've passed to
467 the &Decider; function are essentially used by &SCons;
468 to pick one of several specific internal functions
469 that implement various ways of deciding if a dependency
470 (usually a source file)
471 has changed since a target file has been built.
473 you can also supply your own function
474 to decide if a dependency has changed.
480 For example, suppose we have an input file
481 that contains a lot of data,
482 in some specific regular format,
483 that is used to rebuild a lot of different target files,
484 but each target file really only depends on
485 one particular section of the input file.
486 We'd like to have each target file depend on
487 only its section of the input file.
488 However, since the input file may contain a lot of data,
489 we want to open the input file only if its timestamp has changed.
490 This could done with a custom
491 &Decider; function that might look something like this:
495 <scons_example name="function">
496 <file name="SConstruct" printme="1">
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)
507 <file name="hello.c">
508 int main() { printf("Hello, world!\n"); }
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:
624 <scons_example name="mixing">
625 <file name="SConstruct" printme="1">
626 env1 = Environment(CPPPATH = ['.'])
628 env2.Decider('timestamp-match')
629 env1.Program('prog-MD5', 'program1.c')
630 env2.Program('prog-timestamp', 'program2.c')
632 <file name="program1.c">
634 int main() { printf("Hello, world!\n"); }
636 <file name="program2.c">
638 int main() { printf("Hello, world!\n"); }
647 If both of the programs include the same
648 <filename>inc.h</filename> file,
649 then updating the modification time of
650 <filename>inc.h</filename>
651 (using the &touch; command)
652 will cause only <filename>prog-timestamp</filename>
657 <scons_output example="mixing" os="posix">
658 <scons_output_command>scons -Q</scons_output_command>
659 <scons_output_command>touch inc.h</scons_output_command>
660 <scons_output_command>scons -Q</scons_output_command>
668 <title>Older Functions for Deciding When an Input File Has Changed</title>
672 &SCons; still supports two functions that used to be the
673 primary methods for configuring the
674 decision about whether or not an input file has changed.
675 Although they're not officially deprecated yet,
676 their use is discouraged,
677 mainly because they rely on a somewhat
678 confusing distinction between how
679 source files and target files are handled.
680 These functions are documented here mainly in case you
681 encounter them in existing &SConscript; files.
686 <title>The &SourceSignatures; Function</title>
690 The &SourceSignatures; function is fairly straightforward,
691 and supports two different argument values
692 to configure whether source file changes should be decided
693 using MD5 signatures:
699 SourceSignatures('MD5')
704 Or using time stamps:
710 SourceSignatures('timestamp')
715 These are roughly equivalent to specifying
716 <function>Decider('MD5')</function>
718 <function>Decider('timestamp-match')</function>,
720 although it only affects how SCons makes
721 decisions about dependencies on
722 <emphasis>source</emphasis> files--that is,
723 files that are not built from any other files.
730 <title>The &TargetSignatures; Function</title>
734 The &TargetSignatures; function
735 specifies how &SCons; decides
736 when a target file has changed
737 <emphasis>when it is used as a
738 dependency of (input to) another target</emphasis>--that is,
739 the &TargetSignatures; function configures
740 how the signatures of "intermediate" target files
741 are used when deciding if a "downstream" target file
744 This easily-overlooked distinction between
745 how &SCons; decides if the target itself must be rebuilt
746 and how the target is then used to decide if a different
747 target must be rebuilt is one of the confusing
748 things that has led to the &TargetSignatures;
749 and &SourceSignatures; functions being
750 replaced by the simpler &Decider; function.
757 The &TargetSignatures; function supports the same
758 <literal>'MD5'</literal> and <literal>'timestamp'</literal>
759 argument values that are supported by the &SourceSignatures;,
760 with the same meanings, but applied to target files.
761 That is, in the example:
767 TargetSignatures('MD5')
772 The MD5 checksum of the &hello_o; target file
773 will be used to decide if it has changed since the last
774 time the "downstream" &hello; target file was built.
781 TargetSignatures('timestamp')
786 The modification time of the &hello_o; target file
787 will be used to decide if it has changed since the last
788 time the "downstream" &hello; target file was built.
794 The &TargetSignatures; function supports
795 two additional argument values:
796 <literal>'source'</literal> and <literal>'build'</literal>.
797 The <literal>'source'</literal> argument
798 specifies that decisions involving
799 whether target files have changed
800 since a previous build
801 should use the same behavior
802 for the decisions configured for source files
803 (using the &SourceSignatures; function).
810 TargetSignatures('source')
811 SourceSignatures('timestamp')
816 All files, both targets and sources,
817 will use modification times
818 when deciding if an input file
819 has changed since the last
820 time a target was built.
826 Lastly, the <literal>'build'</literal> argument
827 specifies that &SCons; should examine
828 the build status of a target file
829 and always rebuild a "downstream" target
830 if the target file was itself rebuilt,
831 without re-examining the contents or timestamp
832 of the newly-built target file.
833 If the target file was not rebuilt during
834 this &scons; invocation,
835 then the target file will be examined
836 the same way as configured by
837 the &SourceSignature; call
838 to decide if it has changed.
844 This mimics the behavior of
845 <literal>build signatures</literal>
846 in earlier versions of &SCons;.
847 A &buildsignature; re-combined
848 signatures of all the input files
849 that went into making the target file,
850 so that the target file itself
851 did not need to have its contents read
852 to compute an MD5 signature.
853 This can improve performance for some configurations,
854 but is generally not as effective as using
855 <literal>Decider('MD5-timestamp')</literal>.
864 <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title>
868 Now suppose that our "Hello, World!" program
869 actually has an <literal>#include</literal> line
870 to include the &hello_h; file in the compilation:
874 <scons_example name="include">
875 <file name="SConstruct">
876 Program('hello.c', CPPPATH = '.')
878 <file name="hello.c" printme="1">
879 #include <hello.h>
883 printf("Hello, %s!\n", string);
886 <file name="hello.h">
887 #define string "world"
893 And, for completeness, the &hello_h; file looks like this:
897 <scons_example_file example="include" name="hello.h">
898 </scons_example_file>
902 In this case, we want &SCons; to recognize that,
903 if the contents of the &hello_h; file change,
904 the &hello; program must be recompiled.
905 To do this, we need to modify the
906 &SConstruct; file like so:
910 <scons_example_file example="include" name="SConstruct">
911 </scons_example_file>
915 The &cv-link-CPPPATH; value
916 tells &SCons; to look in the current directory
917 (<literal>'.'</literal>)
918 for any files included by C source files
919 (<filename>.c</filename> or <filename>.h</filename> files).
920 With this assignment in the &SConstruct; file:
924 <scons_output example="include" os="posix">
925 <scons_output_command>scons -Q hello</scons_output_command>
926 <scons_output_command>scons -Q hello</scons_output_command>
927 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
928 <scons_output_command>scons -Q hello</scons_output_command>
933 First, notice that &SCons;
934 added the <literal>-I.</literal> argument
935 from the &cv-CPPPATH; variable
936 so that the compilation would find the
937 &hello_h; file in the local directory.
943 Second, realize that &SCons; knows that the &hello;
944 program must be rebuilt
945 because it scans the contents of
947 for the <literal>#include</literal> lines that indicate
948 another file is being included in the compilation.
949 &SCons; records these as
950 <emphasis>implicit dependencies</emphasis>
953 when the &hello_h; file changes,
954 &SCons; realizes that the &hello_c; file includes it,
955 and rebuilds the resulting &hello; program
956 that depends on both the &hello_c; and &hello_h; files.
962 Like the &cv-link-LIBPATH; variable,
963 the &cv-CPPPATH; variable
964 may be a list of directories,
965 or a string separated by
966 the system-specific path separation character
967 (':' on POSIX/Linux, ';' on Windows).
968 Either way, &SCons; creates the
969 right command-line options
970 so that the following example:
974 <scons_example name="ex5">
975 <file name="SConstruct" printme="1">
976 Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
978 <file name="hello.c">
979 int main() { printf("Hello, world!\n"); }
985 Will look like this on POSIX or Linux:
989 <scons_output example="ex5" os="posix">
990 <scons_output_command>scons -Q hello</scons_output_command>
995 And like this on Windows:
999 <scons_output example="ex5" os="win32">
1000 <scons_output_command>scons -Q hello.exe</scons_output_command>
1006 <title>Caching Implicit Dependencies</title>
1010 Scanning each file for <literal>#include</literal> lines
1011 does take some extra processing time.
1012 When you're doing a full build of a large system,
1013 the scanning time is usually a very small percentage
1014 of the overall time spent on the build.
1015 You're most likely to notice the scanning time,
1016 however, when you <emphasis>rebuild</emphasis>
1017 all or part of a large system:
1018 &SCons; will likely take some extra time to "think about"
1019 what must be built before it issues the
1021 (or decides that everything is up to date
1022 and nothing must be rebuilt).
1025 Isn't this expensive? The answer is, it depends. If you do a full build of a
1026 large system, the scanning time is insignificant. If you do a rebuild of a
1027 large system, then Cons will spend a fair amount of time thinking about it
1028 before it decides that nothing has to be done (although not necessarily more
1029 time than make!). The good news is that Cons makes it very easy to
1030 intelligently subset your build, when you are working on localized changes.
1037 In practice, having &SCons; scan files saves time
1038 relative to the amount of potential time
1039 lost to tracking down subtle problems
1040 introduced by incorrect dependencies.
1041 Nevertheless, the "waiting time"
1042 while &SCons; scans files can annoy
1043 individual developers waiting for their builds to finish.
1044 Consequently, &SCons; lets you cache
1045 the implicit dependencies
1046 that its scanners find,
1047 for use by later builds.
1048 You can do this by specifying the
1049 &implicit-cache; option on the command line:
1053 <scons_output example="ex1">
1054 <scons_output_command>scons -Q --implicit-cache hello</scons_output_command>
1055 <scons_output_command>scons -Q hello</scons_output_command>
1060 If you don't want to specify &implicit-cache;
1061 on the command line each time,
1062 you can make it the default behavior for your build
1063 by setting the &implicit_cache; option
1064 in an &SConscript; file:
1069 SetOption('implicit_cache', 1)
1074 &SCons; does not cache implicit dependencies like this by default
1075 because the &implicit-cache; causes &SCons; to simply use the implicit
1076 dependencies stored during the last run, without any checking
1077 for whether or not those dependencies are still correct.
1078 Specifically, this means &implicit-cache; instructs &SCons;
1079 to <emphasis>not</emphasis> rebuild "correctly" in the
1090 When &implicit-cache; is used, &SCons; will ignore any changes that
1091 may have been made to search paths
1092 (like &cv-CPPPATH; or &cv-LIBPATH;,).
1093 This can lead to &SCons; not rebuilding a file if a change to
1094 &cv-CPPPATH; would normally cause a different, same-named file from
1095 a different directory to be used.
1103 When &implicit-cache; is used, &SCons; will not detect if a
1104 same-named file has been added to a directory that is earlier in
1105 the search path than the directory in which the file was found
1114 <title>The &implicit-deps-changed; Option</title>
1118 When using cached implicit dependencies,
1119 sometimes you want to "start fresh"
1120 and have &SCons; re-scan the files
1121 for which it previously cached the dependencies.
1123 if you have recently installed a new version of
1124 external code that you use for compilation,
1125 the external header files will have changed
1126 and the previously-cached implicit dependencies
1127 will be out of date.
1128 You can update them by
1129 running &SCons; with the &implicit-deps-changed; option:
1133 <scons_output example="ex1">
1134 <scons_output_command>scons -Q --implicit-deps-changed hello</scons_output_command>
1135 <scons_output_command>scons -Q hello</scons_output_command>
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:
1168 <scons_output example="ex1">
1169 <scons_output_command>scons -Q --implicit-deps-unchanged hello</scons_output_command>
1170 <scons_output_command>scons -Q hello</scons_output_command>
1176 &SCons; will assume that the cached implicit
1177 dependencies are correct and
1178 will not bother to re-scan changed files.
1179 For typical builds after small,
1180 incremental changes to source files,
1181 the savings may not be very big,
1182 but sometimes every bit of
1183 improved performance counts.
1192 <title>XXX max drift</title>
1194 XXX SetOption('max_drift')
1203 <title>Explicit Dependencies: the &Depends; Function</title>
1207 Sometimes a file depends on another file
1208 that is not detected by an &SCons; scanner.
1210 &SCons; allows you to specific explicitly that one file
1211 depends on another file,
1212 and must be rebuilt whenever that file changes.
1213 This is specified using the &Depends; method:
1218 hello = Program('hello.c')
1219 Depends(hello, 'other_file')
1222 <!-- XXX mention that you can use arrays for target and source? -->
1225 % <userinput>scons -Q hello</userinput>
1226 cc -c hello.c -o hello.o
1228 % <userinput>scons -Q hello</userinput>
1229 scons: `hello' is up to date.
1230 % <userinput>edit other_file</userinput>
1231 [CHANGE THE CONTENTS OF other_file]
1232 % <userinput>scons -Q hello</userinput>
1233 cc -c hello.c -o hello.o
1239 Note that the dependency
1240 (the second argument to &Depends;)
1241 may also be a list of Node objects
1242 (for example, as returned by a call to a Builder):
1247 hello = Program('hello.c')
1248 goodbye = Program('goodbye.c')
1249 Depends(hello, goodbye)
1254 in which case the dependency or dependencies
1255 will be built before the target(s):
1260 % <userinput>scons -Q hello</userinput>
1261 cc -c goodbye.c -o goodbye.o
1262 cc -o goodbye goodbye.o
1263 cc -c hello.c -o hello.o
1270 <title>Dependencies From External Files: the &ParseDepends;
1275 &SCons; has built-in scanners for a number of languages. Sometimes
1276 these scanners fail to extract certain implicit dependencies due
1277 to limitations of the scanner implementation.
1283 The following example illustrates a case where the built-in C
1284 scanner is unable to extract the implicit dependency on a header
1289 <scons_example name="macroinc">
1290 <file name="hello.c" printme="1">
1291 #define FOO_HEADER <foo.h>
1298 <file name="SConstruct">
1299 Program('hello', 'hello.c', CPPPATH='.')
1306 <scons_output example="macroinc" os="posix">
1307 <scons_output_command>scons -Q</scons_output_command>
1308 <scons_output_command output=" [CHANGE CONTENTS OF foo.h]"
1309 >edit foo.h</scons_output_command>
1310 <scons_output_command>scons -Q</scons_output_command>
1315 Apparently, the scanner does not know about the header dependency.
1316 Being not a full-fledged C preprocessor, the scanner does not
1323 In these cases, you may also use the compiler to extract the
1324 implicit dependencies. &ParseDepends; can parse the contents of
1325 the compiler output in the style of &Make;, and explicitly
1326 establish all of the listed dependencies.
1332 The following example uses &ParseDepends; to process a compiler
1333 generated dependency file which is generated as a side effect
1334 during compilation of the object file:
1338 <!-- XXX The ParseDepends example below fakes proper working by a
1339 priori specification of the dependency file. The produced hello.d
1340 file is not found (or used) for unknown reasons. -->
1342 <scons_example name="parsedep">
1343 <file name="hello.c">
1344 #define FOO_HEADER <foo.h>
1351 <file name="SConstruct" printme="1">
1352 obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
1353 SideEffect('hello.d', obj)
1354 ParseDepends('hello.d')
1355 Program('hello', obj)
1360 <file name="hello.d">
1361 hello.o: hello.c foo.h
1365 <scons_output example="parsedep" os="posix">
1366 <scons_output_command>scons -Q</scons_output_command>
1367 <scons_output_command output=" [CHANGE CONTENTS OF foo.h]"
1368 >edit foo.h</scons_output_command>
1369 <scons_output_command>scons -Q</scons_output_command>
1374 Parsing dependencies from a compiler-generated
1375 <filename>.d</filename> file has a chicken-and-egg problem, that
1376 causes unnecessary rebuilds:
1380 <scons_example name="parsedeprebuild">
1381 <file name="hello.c">
1382 #define FOO_HEADER <foo.h>
1389 <file name="SConstruct">
1390 obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
1391 SideEffect('hello.d', obj)
1392 ParseDepends('hello.d')
1393 Program('hello', obj)
1401 <scons_output example="parsedeprebuild" os="posix">
1402 <scons_output_command>scons -Q</scons_output_command>
1403 <scons_output_command>scons -Q</scons_output_command>
1404 <scons_output_command>scons -Q</scons_output_command>
1409 % <userinput>scons -Q</userinput>
1410 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1412 % <userinput>scons -Q --debug=explain</userinput>
1413 scons: rebuilding `hello.o' because `foo.h' is a new dependency
1414 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1415 % <userinput>scons -Q</userinput>
1416 scons: `.' is up to date.
1421 In the first pass, the dependency file is generated while the
1422 object file is compiled. At that time, &SCons; does not know about
1423 the dependency on <filename>foo.h</filename>. In the second pass,
1424 the object file is regenerated because <filename>foo.h</filename>
1425 is detected as a new dependency.
1431 &ParseDepends; immediately reads the specified file at invocation
1432 time and just returns if the file does not exist. A dependency
1433 file generated during the build process is not automatically
1434 parsed again. Hence, the compiler-extracted dependencies are not
1435 stored in the signature database during the same build pass. This
1436 limitation of &ParseDepends; leads to unnecessary recompilations.
1437 Therefore, &ParseDepends; should only be used if scanners are not
1438 available for the employed language or not powerful enough for the
1446 <title>Ignoring Dependencies: the &Ignore; Function</title>
1450 Sometimes it makes sense
1451 to not rebuild a program,
1452 even if a dependency file changes.
1454 you would tell &SCons; specifically
1455 to ignore a dependency as follows:
1459 <scons_example name="ignore">
1460 <file name="SConstruct" printme="1">
1461 hello_obj=Object('hello.c')
1462 hello = Program(hello_obj)
1463 Ignore(hello_obj, 'hello.h')
1465 <file name="hello.c">
1467 int main() { printf("Hello, %s!\n", string); }
1469 <file name="hello.h">
1470 #define string "world"
1474 <!-- XXX mention that you can use lists for target and source? -->
1477 <scons_output example="ignore">
1478 <scons_output_command>scons -Q hello</scons_output_command>
1479 <scons_output_command>scons -Q hello</scons_output_command>
1480 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
1481 <scons_output_command>scons -Q hello</scons_output_command>
1482 XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
1487 % <userinput>scons -Q hello</userinput>
1488 cc -c -o hello.o hello.c
1490 % <userinput>scons -Q hello</userinput>
1491 scons: `hello' is up to date.
1492 % <userinput>edit hello.h</userinput>
1493 [CHANGE THE CONTENTS OF hello.h]
1494 % <userinput>scons -Q hello</userinput>
1495 scons: `hello' is up to date.
1500 Now, the above example is a little contrived,
1501 because it's hard to imagine a real-world situation
1502 where you wouldn't want to rebuild &hello;
1503 if the &hello_h; file changed.
1504 A more realistic example
1505 might be if the &hello;
1506 program is being built in a
1507 directory that is shared between multiple systems
1508 that have different copies of the
1509 &stdio_h; include file.
1511 &SCons; would notice the differences between
1512 the different systems' copies of &stdio_h;
1513 and would rebuild &hello;
1514 each time you change systems.
1515 You could avoid these rebuilds as follows:
1520 hello = Program('hello.c', CPPPATH=['/usr/include'])
1521 Ignore(hello, '/usr/include/stdio.h')
1525 &Ignore; can also be used to prevent a generated file from being built
1526 by default. This is due to the fact that directories depend on
1527 their contents. So to ignore a generated file from the default build,
1528 you specify that the directory should ignore the generated file.
1529 Note that the file will still be built if the user specifically
1530 requests the target on scons command line, or if the file is
1531 a dependency of another file which is requested and/or is built
1535 <scons_example name="ignore_explicit">
1536 <file name="SConstruct" printme="1">
1537 hello_obj=Object('hello.c')
1538 hello = Program(hello_obj)
1539 Ignore('.',[hello,hello_obj])
1541 <file name="hello.c">
1543 int main() { printf("Hello!\n"); }
1547 <scons_output example="ignore_explicit" os="posix">
1548 <scons_output_command>scons -Q</scons_output_command>
1549 <scons_output_command>scons -Q hello</scons_output_command>
1550 <scons_output_command>scons -Q hello</scons_output_command>
1555 <title>Order-Only Dependencies: the &Requires; Function</title>
1560 it may be useful to specify that a certain
1561 file or directory must, if necessary,
1562 be built or created before some other target is built,
1563 but that changes to that file or directory
1564 do <emphasis>not</emphasis>
1565 require that the target itself be rebuilt.
1566 Such a relationship is called an
1567 <emphasis>order-only dependency</emphasis>
1568 because it only affects the order in which
1569 things must be built--the dependency before the target--but
1570 it is not a strict dependency relationship
1571 because the target should not
1572 change in response to changes in the dependent file.
1578 For example, suppose that you want to create a file
1579 every time you run a build
1580 that identifies the time the build was performed,
1581 the version number, etc.,
1582 and which is included in every program that you build.
1583 The version file's contents will change every build.
1584 If you specify a normal dependency relationship,
1585 then every program that depends on
1586 that file would be rebuilt every time you ran &SCons;.
1587 For example, we could use some Python code in
1588 a &SConstruct; file to create a new <filename>version.c</filename> file
1589 with a string containing the current date every time
1591 and then link a program with the resulting object file
1592 by listing <filename>version.c</filename> in the sources:
1596 <scons_example name="no-Requires">
1597 <file name="SConstruct" printme="1">
1600 version_c_text = """
1602 """ % time.ctime(time.time())
1603 open('version.c', 'w').write(version_c_text)
1605 hello = Program(['hello.c', 'version.c'])
1607 <file name="hello.c">
1609 int main() { printf("Hello, %s! I was built: %s\n", date); }
1615 If we list <filename>version.c</filename> as an actual source file,
1616 though, then <filename>version.o</filename>
1617 will get rebuilt every time we run &SCons;
1618 (because the &SConstruct; file itself changes
1619 the contents of <filename>version.c</filename>)
1620 and the <filename>hello</filename> executable
1621 will get re-linked every time
1622 (because the <filename>version.o</filename> file changes):
1628 <scons_output example="no-Requires">
1629 <scons_output_command>scons -Q</scons_output_command>
1630 <scons_output_command>scons -Q</scons_output_command>
1636 % <userinput>scons -Q</userinput>
1637 gcc -o hello.o -c hello.c
1638 gcc -o version.o -c version.c
1639 gcc -o hello hello.o version.o
1640 % <userinput>scons -Q</userinput>
1641 gcc -o version.o -c version.c
1642 gcc -o hello hello.o version.o
1643 % <userinput>scons -Q</userinput>
1644 gcc -o version.o -c version.c
1645 gcc -o hello hello.o version.o
1650 One solution is to use the &Requires; function
1651 to specify that the <filename>version.o</filename>
1652 must be rebuilt before it is used by the link step,
1653 but that changes to <filename>version.o</filename>
1654 should not actually cause the <filename>hello</filename>
1655 executable to be re-linked:
1659 <scons_example name="Requires">
1660 <file name="SConstruct" printme="1">
1663 version_c_text = """
1665 """ % time.ctime(time.time())
1666 open('version.c', 'w').write(version_c_text)
1668 version_obj = Object('version.c')
1670 hello = Program('hello.c',
1671 LINKFLAGS = str(version_obj[0]))
1673 Requires(hello, version_obj)
1675 <file name="hello.c">
1677 int main() { printf("Hello, %s! I was built: %s\n", date); }
1683 Notice that because we can no longer list <filename>version.c</filename>
1684 as one of the sources for the <filename>hello</filename> program,
1685 we have to find some other way to get it into the link command line.
1686 For this example, we're cheating a bit and stuffing the
1687 object file name (extracted from <literal>version_obj</literal>
1688 list returned by the &b-Object; call)
1689 into the &cv-link-LINKFLAGS; variable,
1690 because &cv-LINKFLAGS; is already included
1691 in the &cv-link-LINKCOM; command line.
1698 we get the desired behavior of
1699 re-building the <filename>version.o</filename> file,
1700 and therefore re-linking the <filename>hello</filename> executable,
1701 only when the <filename>hello.c</filename> has changed:
1705 <scons_output example="Requires">
1706 <scons_output_command>scons -Q</scons_output_command>
1707 <scons_output_command>scons -Q</scons_output_command>
1708 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
1709 <scons_output_command>scons -Q</scons_output_command>
1710 <scons_output_command>scons -Q</scons_output_command>
1716 <title>The &AlwaysBuild; Function</title>
1720 How &SCons; handles dependencies can also be affected
1721 by the &AlwaysBuild; method.
1722 When a file is passed to the &AlwaysBuild; method,
1727 <scons_example name="AlwaysBuild">
1728 <file name="SConstruct" printme="1">
1729 hello = Program('hello.c')
1732 <file name="hello.c">
1733 int main() { printf("Hello, %s!\n", string); }
1739 Then the specified target file (&hello; in our example)
1740 will always be considered out-of-date and
1741 rebuilt whenever that target file is evaluated
1742 while walking the dependency graph:
1746 <scons_output example="AlwaysBuild">
1747 <scons_output_command>scons -Q</scons_output_command>
1748 <scons_output_command>scons -Q</scons_output_command>
1753 The &AlwaysBuild; function has a somewhat misleading name,
1754 because it does not actually mean the target file will
1755 be rebuilt every single time &SCons; is invoked.
1756 Instead, it means that the target will, in fact,
1757 be rebuilt whenever the target file is encountered
1758 while evaluating the targets specified on
1759 the command line (and their dependencies).
1760 So specifying some other target on the command line,
1761 a target that does <emphasis>not</emphasis>
1762 itself depend on the &AlwaysBuild; target,
1763 will still be rebuilt only if it's out-of-date
1764 with respect to its dependencies:
1768 <scons_output example="AlwaysBuild">
1769 <scons_output_command>scons -Q</scons_output_command>
1770 <scons_output_command>scons -Q hello.o</scons_output_command>
1775 XXX AlwaysBuild() and Alias Nodes
1777 XXX AlwaysBuild() and Dir Nodes
1779 XXX AlwaysBuild() with no sources
1788 <title>The &Salt; Method</title>
1792 XXX Salt() (are we going to implement this ?)
1794 original Cons classic POD documentation:
1796 =head2 The C<Salt> method
1798 The C<Salt> method adds a constant value to the signature calculation
1799 for every derived file. It is invoked as follows:
1803 Changing the Salt value will force a complete rebuild of every derived
1804 file. This can be used to force rebuilds in certain desired
1805 circumstances. For example,
1809 Would force a complete rebuild of every derived file whenever the
1810 operating system on which the build is performed (as reported by C<uname