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 =head2 The C<Salt> method
30 The C<Salt> method adds a constant value to the signature calculation
31 for every derived file. It is invoked as follows:
35 Changing the Salt value will force a complete rebuild of every derived
36 file. This can be used to force rebuilds in certain desired
37 circumstances. For example,
41 Would force a complete rebuild of every derived file whenever the
42 operating system on which the build is performed (as reported by C<uname
49 So far we've seen how &SCons; handles one-time builds.
50 But the real point of a build tool like &SCons;
51 is to rebuild only the necessary things
52 when source files change--or, put another way,
53 &SCons; should <emphasis>not</emphasis>
54 waste time rebuilding things that have already been built.
55 You can see this at work simply be re-invoking &SCons;
56 after building our simple &hello; example:
60 <scons_example name="ex1">
61 <file name="SConstruct">
65 int main() { printf("Hello, world!\n"); }
69 <scons_output example="ex1" os="posix">
70 <scons_output_command>scons -Q</scons_output_command>
71 <scons_output_command>scons -Q</scons_output_command>
76 The second time it is executed,
77 &SCons; realizes that the &hello; program
78 is up-to-date with respect to the current &hello_c; source file,
79 and avoids rebuilding it.
80 You can see this more clearly by naming
81 the &hello; program explicitly on the command line:
85 <scons_output example="ex1" os="posix">
86 <scons_output_command>scons -Q hello</scons_output_command>
87 <scons_output_command>scons -Q hello</scons_output_command>
92 Note that &SCons; reports <literal>"...is up to date"</literal>
93 only for target files named explicitly on the command line,
94 to avoid cluttering the output.
99 <title>Deciding When a Source File Has Changed: the &SourceSignatures; Function</title>
103 The other side of avoiding unnecessary rebuilds
104 is the fundamental build tool behavior
105 of <emphasis>rebuilding</emphasis>
106 things when a source file changes,
107 so that the built software is up to date.
108 &SCons; keeps track of this through a
109 &signature; for each source file,
110 and allows you to configure
111 whether you want to use the source
112 file contents or the modification time (timestamp)
118 <title>MD5 Source File Signatures</title>
123 &SCons; keeps track of whether a source file has changed
124 based on the file's contents,
125 not the modification time.
126 This means that you may be surprised by the
127 default &SCons; behavior if you are used to the
128 &Make; convention of forcing
129 a rebuild by updating the file's modification time
130 (using the &touch; command, for example):
134 <scons_output example="ex1" os="posix">
135 <scons_output_command>scons -Q hello</scons_output_command>
136 <scons_output_command>touch hello.c</scons_output_command>
137 <scons_output_command>scons -Q hello</scons_output_command>
142 Even though the file's modification time has changed,
143 &SCons; realizes that the contents of the
144 &hello_c; file have <emphasis>not</emphasis> changed,
145 and therefore that the &hello; program
147 This avoids unnecessary rebuilds when,
148 for example, someone rewrites the
149 contents of a file without making a change.
150 But if the contents of the file really do change,
151 then &SCons; detects the change
152 and rebuilds the program as required:
156 <scons_output example="ex1" os="posix">
157 <scons_output_command>scons -Q hello</scons_output_command>
158 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
159 <scons_output_command>scons -Q hello</scons_output_command>
164 Note that you can, if you wish,
165 specify this default behavior
166 (MD5 signatures) explicitly
167 using the &SourceSignatures; function as follows:
173 SourceSignatures('MD5')
179 <title>Source File Time Stamps</title>
183 If you prefer, you can
184 configure &SCons; to use the modification time
186 not the file contents,
187 when deciding if something needs to be rebuilt.
188 To do this, call the &SourceSignatures;
193 <scons_example name="ex2">
194 <file name="SConstruct" printme="1">
196 SourceSignatures('timestamp')
198 <file name="hello.c">
199 int main() { printf("Hello, world!\n"); }
205 This makes &SCons; act like &Make;
206 when a file's modification time is updated
207 (using the &touch; command, for example):
211 <scons_output example="ex2" os="posix">
212 <scons_output_command>scons -Q hello</scons_output_command>
213 <scons_output_command>touch hello.c</scons_output_command>
214 <scons_output_command>scons -Q hello</scons_output_command>
222 <title>Deciding When a Target File Has Changed: the &TargetSignatures; Function</title>
227 &SCons; uses signatures to decide whether a
228 target file is up to date or must be rebuilt.
229 When a target file depends on another target file,
230 &SCons; allows you to configure separately
231 how the signatures of "intermediate" target files
232 are used when deciding if a dependent target file
238 <title>Build Signatures</title>
242 Modifying a source file
243 will cause not only its direct target file to be rebuilt,
244 but also the target file(s)
245 that depend on that direct target file.
247 changing the contents of the &hello_c; file causes
248 the &hello_o; file to be rebuilt,
249 which in turn causes the
250 &hello; program to be rebuilt:
254 <scons_output example="ex1" os="posix">
255 <scons_output_command>scons -Q hello</scons_output_command>
256 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
257 <scons_output_command>scons -Q hello</scons_output_command>
262 What's not obvious, though,
263 is that &SCons; internally handles the signature of
265 (&hello_o; in the above example)
266 differently from the signature of the source file
269 &SCons; tracks whether a target file must be rebuilt
270 by using a &buildsignature;
271 that consists of the combined
272 signatures of all the files
273 that go into making the target file.
274 This is efficient because
275 the accumulated signatures
276 actually give &SCons; all of the
278 to decide if the target file is out of date.
285 specify this default behavior
286 (build signatures) explicitly
287 using the &TargetSignatures; function:
293 TargetSignatures('build')
299 <title>File Contents</title>
303 Sometimes a source file can be changed
304 in such a way that the contents of the
305 rebuilt target file(s)
306 will be exactly the same as the last time
308 If so, then any other target files
309 that depend on such a built-but-not-changed target
310 file actually need not be rebuilt.
312 realize that it does not need to rebuild
313 a dependent target file in this situation
314 using the &TargetSignatures; function as follows:
318 <scons_example name="ex3">
319 <file name="SConstruct" printme="1">
321 TargetSignatures('content')
323 <file name="hello.c">
324 int main() { printf("Hello, world!\n"); }
331 a user were to only change a comment in a C file,
332 then the rebuilt &hello_o; file
333 would be exactly the same as the one previously built
334 (assuming the compiler doesn't put any build-specific
335 information in the object file).
336 &SCons; would then realize that it would not
337 need to rebuild the &hello; program as follows:
341 <scons_output example="ex3" os="posix">
342 <scons_output_command>scons -Q hello</scons_output_command>
343 <scons_output_command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command>
344 <scons_output_command>scons -Q hello</scons_output_command>
349 In essence, &SCons; has
350 "short-circuited" any dependent builds
351 when it realizes that a target file
352 has been rebuilt to exactly the same file as the last build.
354 &SCons; does take some extra processing time
355 to scan the contents of the target (&hello_o;) file,
356 but this may save time
357 if the rebuild that was avoided
358 would have been very time-consuming and expensive.
367 <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title>
371 Now suppose that our "Hello, World!" program
372 actually has a <literal>#include</literal> line
373 to include the &hello_h; file in the compilation:
377 <scons_example name="ex4">
378 <file name="SConstruct">
379 Program('hello.c', CPPPATH = '.')
381 <file name="hello.c" printme="1">
382 #include <hello.h>
386 printf("Hello, %s!\n", string);
389 <file name="hello.h">
390 #define string "world"
396 And, for completeness, the &hello_h; file looks like this:
400 <scons_example_file example="ex4" name="hello.h">
401 </scons_example_file>
405 In this case, we want &SCons; to recognize that,
406 if the contents of the &hello_h; file change,
407 the &hello; program must be recompiled.
408 To do this, we need to modify the
409 &SConstruct; file like so:
413 <scons_example_file example="ex4" name="SConstruct">
414 </scons_example_file>
418 The &cv-CPPPATH; value
419 tells &SCons; to look in the current directory
420 (<literal>'.'</literal>)
421 for any files included by C source files
422 (<filename>.c</filename> or <filename>.h</filename> files).
423 With this assignment in the &SConstruct; file:
427 <scons_output example="ex4" os="posix">
428 <scons_output_command>scons -Q hello</scons_output_command>
429 <scons_output_command>scons -Q hello</scons_output_command>
430 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
431 <scons_output_command>scons -Q hello</scons_output_command>
436 First, notice that &SCons;
437 added the <literal>-I.</literal> argument
438 from the &cv-CPPPATH; variable
439 so that the compilation would find the
440 &hello_h; file in the local directory.
446 Second, realize that &SCons; knows that the &hello;
447 program must be rebuilt
448 because it scans the contents of
450 for the <literal>#include</literal> lines that indicate
451 another file is being included in the compilation.
452 &SCons; records these as
453 <emphasis>implicit dependencies</emphasis>
456 when the &hello_h; file changes,
457 &SCons; realizes that the &hello_c; file includes it,
458 and rebuilds the resulting &hello; program
459 that depends on both the &hello_c; and &hello_h; files.
465 Like the &cv-LIBPATH; variable,
466 the &cv-CPPPATH; variable
467 may be a list of directories,
468 or a string separated by
469 the system-specific path separate character
470 (':' on POSIX/Linux, ';' on Windows).
471 Either way, &SCons; creates the
472 right command-line options
473 so that the following example:
477 <scons_example name="ex5">
478 <file name="SConstruct" printme="1">
479 Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
481 <file name="hello.c">
482 int main() { printf("Hello, world!\n"); }
488 Will look like this on POSIX or Linux:
492 <scons_output example="ex5" os="posix">
493 <scons_output_command>scons -Q hello</scons_output_command>
498 And like this on Windows:
502 <scons_output example="ex5" os="win32">
503 <scons_output_command>scons -Q hello.exe</scons_output_command>
509 <title>Caching Implicit Dependencies</title>
513 Scanning each file for <literal>#include</literal> lines
514 does take some extra processing time.
515 When you're doing a full build of a large system,
516 the scanning time is usually a very small percentage
517 of the overall time spent on the build.
518 You're most likely to notice the scanning time,
519 however, when you <emphasis>rebuild</emphasis>
520 all or part of a large system:
521 &SCons; will likely take some extra time to "think about"
522 what must be built before it issues the
524 (or decides that everything is up to date
525 and nothing must be rebuilt).
528 Isn't this expensive? The answer is, it depends. If you do a full build of a
529 large system, the scanning time is insignificant. If you do a rebuild of a
530 large system, then Cons will spend a fair amount of time thinking about it
531 before it decides that nothing has to be done (although not necessarily more
532 time than make!). The good news is that Cons makes it very easy to
533 intelligently subset your build, when you are working on localized changes.
540 In practice, having &SCons; scan files saves time
541 relative to the amount of potential time
542 lost to tracking down subtle problems
543 introduced by incorrect dependencies.
544 Nevertheless, the "waiting time"
545 while &SCons; scans files can annoy
546 individual developers waiting for their builds to finish.
547 Consequently, &SCons; lets you cache
548 the implicit dependencies
549 that its scanners find,
550 for use by later builds.
551 You can do this by specifying the
552 &implicit-cache; option on the command line:
556 <scons_output example="ex1">
557 <scons_output_command>scons -Q --implicit-cache hello</scons_output_command>
558 <scons_output_command>scons -Q hello</scons_output_command>
563 If you don't want to specify &implicit-cache;
564 on the command line each time,
565 you can make it the default behavior for your build
566 by setting the &implicit_cache; option
567 in an &SConscript; file:
572 SetOption('implicit_cache', 1)
585 &SCons; does not cache implicit dependencies like this by default
593 <title>The &implicit-deps-changed; Option</title>
597 When using cached implicit dependencies,
598 sometimes you want to "start fresh"
599 and have &SCons; re-scan the files
600 for which it previously cached the dependencies.
602 if you have recently installed a new version of
603 external code that you use for compilation,
604 the external header files will have changed
605 and the previously-cached implicit dependencies
607 You can update them by
608 running &SCons; with the &implicit-deps-changed; option:
612 <scons_output example="ex1">
613 <scons_output_command>scons -Q --implicit-deps-changed hello</scons_output_command>
614 <scons_output_command>scons -Q hello</scons_output_command>
619 In this case, &SCons; will re-scan all of the implicit dependencies
620 and cache updated copies of the information.
627 <title>The &implicit-deps-unchanged; Option</title>
631 By default when caching dependencies,
632 &SCons; notices when a file has been modified
633 and re-scans the file for any updated
634 implicit dependency information.
635 Sometimes, however, you may want
636 to force &SCons; to use the cached implicit dependencies,
637 even if the source files changed.
638 This can speed up a build for example,
639 when you have changed your source files
640 but know that you haven't changed
641 any <literal>#include</literal> lines.
643 you can use the &implicit-deps-unchanged; option:
647 <scons_output example="ex1">
648 <scons_output_command>scons -Q --implicit-deps-unchanged hello</scons_output_command>
649 <scons_output_command>scons -Q hello</scons_output_command>
655 &SCons; will assume that the cached implicit
656 dependencies are correct and
657 will not bother to re-scan changed files.
658 For typical builds after small,
659 incremental changes to source files,
660 the savings may not be very big,
661 but sometimes every bit of
662 improved performance counts.
671 <title>Ignoring Dependencies: the &Ignore; Method</title>
675 Sometimes it makes sense
676 to not rebuild a program,
677 even if a dependency file changes.
679 you would tell &SCons; specifically
680 to ignore a dependency as follows:
684 <scons_example name="ignore">
685 <file name="SConstruct" printme="1">
686 hello = Program('hello.c')
687 Ignore(hello, 'hello.h')
689 <file name="hello.c">
691 int main() { printf("Hello, %s!\n", string); }
693 <file name="hello.h">
694 #define string "world"
698 <!-- XXX mention that you can use arrays for target and source? -->
701 <scons_output example="ignore">
702 <scons_output_command>scons -Q hello</scons_output_command>
703 <scons_output_command>scons -Q hello</scons_output_command>
704 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
705 <scons_output_command>scons -Q hello</scons_output_command>
706 XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
711 % <userinput>scons -Q hello</userinput>
712 cc -c -o hello.o hello.c
714 % <userinput>scons -Q hello</userinput>
715 scons: `hello' is up to date.
716 % <userinput>edit hello.h</userinput>
717 [CHANGE THE CONTENTS OF hello.h]
718 % <userinput>scons -Q hello</userinput>
719 scons: `hello' is up to date.
724 Now, the above example is a little contrived,
725 because it's hard to imagine a real-world situation
726 where you wouldn't to rebuild &hello;
727 if the &hello_h; file changed.
728 A more realistic example
729 might be if the &hello;
730 program is being built in a
731 directory that is shared between multiple systems
732 that have different copies of the
733 &stdio_h; include file.
735 &SCons; would notice the differences between
736 the different systems' copies of &stdio_h;
737 and would rebuild &hello;
738 each time you change systems.
739 You could avoid these rebuilds as follows:
744 hello = Program('hello.c')
745 Ignore(hello, '/usr/include/stdio.h')
751 <title>Explicit Dependencies: the &Depends; Method</title>
756 sometimes a file depends on another file
757 that is not detected by an &SCons; scanner.
759 &SCons; allows you to specific explicitly that one file
760 depends on another file,
761 and must be rebuilt whenever that file changes.
762 This is specified using the &Depends; method:
767 hello = Program('hello.c')
768 Depends(hello, 'other_file')
771 <!-- XXX mention that you can use arrays for target and source? -->
774 % <userinput>scons -Q hello</userinput>
775 cc -c hello.c -o hello.o
777 % <userinput>scons -Q hello</userinput>
778 scons: `hello' is up to date.
779 % <userinput>edit other_file</userinput>
780 [CHANGE THE CONTENTS OF other_file]
781 % <userinput>scons -Q hello</userinput>
782 cc -c hello.c -o hello.o
791 <title>The &Salt; Method</title>