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 the real point of a build tool like &SCons;
30 is to rebuild only the necessary things
31 when source files change--or, put another way,
32 &SCons; should <emphasis>not</emphasis>
33 waste time rebuilding things that have already been built.
34 You can see this at work simply be 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 a Source File Has Changed: the &SourceSignatures; Function</title>
81 The other side of avoiding unnecessary rebuilds
82 is the fundamental build tool behavior
83 of <emphasis>rebuilding</emphasis>
84 things when a source file changes,
85 so that the built software is up to date.
86 &SCons; keeps track of this through a
87 &signature; for each source file,
88 and allows you to configure
89 whether you want to use the source
90 file contents or the modification time (timestamp)
96 <title>MD5 Source File Signatures</title>
101 &SCons; keeps track of whether a source file has changed
102 based on the file's contents,
103 not the modification time.
104 This means that you may be surprised by the
105 default &SCons; behavior if you are used to the
106 &Make; convention of forcing
107 a rebuild by updating the file's modification time
108 (using the &touch; command, for example):
113 % <userinput>scons -Q hello</userinput>
114 cc -o hello.o -c hello.c
116 % <userinput>touch hello.c</userinput>
117 % <userinput>scons -Q hello</userinput>
118 scons: `hello' is up to date.
123 Even though the file's modification time has changed,
124 &SCons; realizes that the contents of the
125 &hello_c; file have <emphasis>not</emphasis> changed,
126 and therefore that the &hello; program
128 This avoids unnecessary rebuilds when,
129 for example, someone rewrites the
130 contents of a file without making a change.
131 But if the contents of the file really do change,
132 then &SCons; detects the change
133 and rebuilds the program as required:
138 % <userinput>scons -Q hello</userinput>
139 cc -o hello.o -c hello.c
141 % <userinput>edit hello.c</userinput>
142 [CHANGE THE CONTENTS OF hello.c]
143 % <userinput>scons -Q hello</userinput>
144 cc -o hello.o -c hello.c
150 Note that you can, if you wish,
151 specify this default behavior
152 (MD5 signatures) explicitly
153 using the &SourceSignatures; function as follows:
159 SourceSignatures('MD5')
165 <title>Source File Time Stamps</title>
169 If you prefer, you can
170 configure &SCons; to use the modification time
172 not the file contents,
173 when deciding if something needs to be rebuilt.
174 To do this, call the &SourceSignatures;
181 SourceSignatures('timestamp')
186 This makes &SCons; act like &Make;
187 when a file's modification time is updated
188 (using the &touch; command, for example):
193 % <userinput>scons -Q hello</userinput>
194 cc -o hello.o -c hello.c
196 % <userinput>touch hello.c</userinput>
197 % <userinput>scons -Q hello</userinput>
198 cc -o hello.o -c hello.c
207 <title>Deciding When a Target File Has Changed: the &TargetSignatures; Function</title>
212 &SCons; uses signatures to decide whether a
213 target file is up to date or must be rebuilt.
214 When a target file depends on another target file,
215 &SCons; allows you to configure separately
216 how the signatures of "intermediate" target files
217 are used when deciding if a dependent target file
223 <title>Build Signatures</title>
227 Modifying a source file
228 will cause not only its direct target file to be rebuilt,
229 but also the target file(s)
230 that depend on that direct target file.
232 changing the contents of the &hello_c; file causes
233 the &hello_o; file to be rebuilt,
234 which in turn causes the
235 &hello; program to be rebuilt:
240 % <userinput>scons -Q hello</userinput>
241 cc -o hello.o -c hello.c
243 % <userinput>edit hello.c</userinput>
244 [CHANGE THE CONTENTS OF hello.c]
245 % <userinput>scons -Q hello</userinput>
246 cc -o hello.o -c hello.c
252 What's not obvious, though,
253 is that &SCons; internally handles the signature of
255 (&hello_o; in the above example)
256 differently from the signature of the source file
259 &SCons; tracks whether a target file must be rebuilt
260 by using a &buildsignature;
261 that consists of the combined
262 signatures of all the files
263 that go into making the target file.
264 This is efficient because
265 the accumulated signatures
266 actually give &SCons; all of the
268 to decide if the target file is out of date.
275 specify this default behavior
276 (build signatures) explicitly
277 using the &TargetSignatures; function:
283 TargetSignatures('build')
289 <title>File Contents</title>
293 Sometimes a source file can be changed
294 in such a way that the contents of the
295 rebuilt target file(s)
296 will be exactly the same as the last time
298 If so, then any other target files
299 that depend on such a built-but-not-changed target
300 file actually need not be rebuilt.
302 realize that it does not need to rebuild
303 a dependent target file in this situation
304 using the &TargetSignatures; function as follows:
310 TargetSignatures('content')
316 a user were to only change a comment in a C file,
317 then the rebuilt &hello_o; file
318 would be exactly the same as the one previously built
319 (assuming the compiler doesn't put any build-specific
320 information in the object file).
321 &SCons; would then realize that it would not
322 need to rebuild the &hello; program as follows:
327 % <userinput>scons -Q hello</userinput>
328 cc -o hello.o -c hello.c
330 % <userinput>edit hello.c</userinput>
331 [CHANGE A COMMENT IN hello.c]
332 % <userinput>scons -Q hello</userinput>
333 cc -o hello.o -c hello.c
334 scons: `hello' is up to date.
339 In essence, &SCons; has
340 "short-circuited" any dependent builds
341 when it realizes that a target file
342 has been rebuilt to exactly the same file as the last build.
344 &SCons; does take some extra processing time
345 to scan the contents of the target (&hello_o;) file,
346 but this may save time
347 if the rebuild that was avoided
348 would have been very time-consuming and expensive.
357 <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title>
361 Now suppose that our "Hello, World!" program
362 actually has a <literal>#include</literal> line
363 to include the &hello_h; file in the compilation:
368 #include <hello.h>
372 printf("Hello, %s!\n", string);
378 And, for completeness, the &hello_h; file looks like this:
384 #define string "world"
389 In this case, we want &SCons; to recognize that,
390 if the contents of the &hello_h; file change,
391 the &hello; program must be recompiled.
392 To do this, we need to modify the
393 &SConstruct; file like so:
399 Program('hello.c', CPPPATH = '.')
404 The &cv-link-CPPPATH; value
405 tells &SCons; to look in the current directory
406 (<literal>'.'</literal>)
407 for any files included by C source files
408 (<filename>.c</filename> or <filename>.h</filename> files).
409 With this assignment in the &SConstruct; file:
414 % <userinput>scons -Q hello</userinput>
415 cc -o hello.o -c -I. hello.c
417 % <userinput>scons -Q hello</userinput>
418 scons: `hello' is up to date.
419 % <userinput>edit hello.h</userinput>
420 [CHANGE THE CONTENTS OF hello.h]
421 % <userinput>scons -Q hello</userinput>
422 cc -o hello.o -c -I. hello.c
428 First, notice that &SCons;
429 added the <literal>-I.</literal> argument
430 from the &cv-CPPPATH; variable
431 so that the compilation would find the
432 &hello_h; file in the local directory.
438 Second, realize that &SCons; knows that the &hello;
439 program must be rebuilt
440 because it scans the contents of
442 for the <literal>#include</literal> lines that indicate
443 another file is being included in the compilation.
444 &SCons; records these as
445 <emphasis>implicit dependencies</emphasis>
448 when the &hello_h; file changes,
449 &SCons; realizes that the &hello_c; file includes it,
450 and rebuilds the resulting &hello; program
451 that depends on both the &hello_c; and &hello_h; files.
457 Like the &cv-link-LIBPATH; variable,
458 the &cv-CPPPATH; variable
459 may be a list of directories,
460 or a string separated by
461 the system-specific path separate character
462 (':' on POSIX/Linux, ';' on Windows).
463 Either way, &SCons; creates the
464 right command-line options
465 so that the following example:
470 Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
475 Will look like this on POSIX or Linux:
480 % <userinput>scons -Q hello</userinput>
481 cc -o hello.o -c -Iinclude -I/home/project/inc hello.c
487 And like this on Windows:
492 C:\><userinput>scons -Q hello.exe</userinput>
493 cl /nologo /Iinclude /I\home\project\inc /c hello.c /Fohello.obj
494 link /nologo /OUT:hello.exe hello.obj
500 <title>Caching Implicit Dependencies</title>
504 Scanning each file for <literal>#include</literal> lines
505 does take some extra processing time.
506 When you're doing a full build of a large system,
507 the scanning time is usually a very small percentage
508 of the overall time spent on the build.
509 You're most likely to notice the scanning time,
510 however, when you <emphasis>rebuild</emphasis>
511 all or part of a large system:
512 &SCons; will likely take some extra time to "think about"
513 what must be built before it issues the
515 (or decides that everything is up to date
516 and nothing must be rebuilt).
519 Isn't this expensive? The answer is, it depends. If you do a full build of a
520 large system, the scanning time is insignificant. If you do a rebuild of a
521 large system, then Cons will spend a fair amount of time thinking about it
522 before it decides that nothing has to be done (although not necessarily more
523 time than make!). The good news is that Cons makes it very easy to
524 intelligently subset your build, when you are working on localized changes.
531 In practice, having &SCons; scan files saves time
532 relative to the amount of potential time
533 lost to tracking down subtle problems
534 introduced by incorrect dependencies.
535 Nevertheless, the "waiting time"
536 while &SCons; scans files can annoy
537 individual developers waiting for their builds to finish.
538 Consequently, &SCons; lets you cache
539 the implicit dependencies
540 that its scanners find,
541 for use by later builds.
542 You can do this by specifying the
543 &implicit-cache; option on the command line:
548 % <userinput>scons -Q --implicit-cache hello</userinput>
549 cc -o hello.o -c hello.c
551 % <userinput>scons -Q hello</userinput>
552 scons: `hello' is up to date.
557 If you don't want to specify &implicit-cache;
558 on the command line each time,
559 you can make it the default behavior for your build
560 by setting the &implicit_cache; option
561 in an &SConscript; file:
566 SetOption('implicit_cache', 1)
571 &SCons; does not cache implicit dependencies like this by default
572 because the &implicit-cache; causes &SCons; to simply use the implicit
573 dependencies stored during the last run, without any checking
574 for whether or not those dependencies are still correct.
575 Specifically, this means &implicit-cache; instructs &SCons;
576 to <emphasis>not</emphasis> rebuild "correctly" in the
587 When &implicit-cache; is used, &SCons; will ignore any changes that
588 may have been made to search paths
589 (like &cv-CPPPATH; or &cv-LIBPATH;,).
590 This can lead to &SCons; not rebuilding a file if a change to
591 &cv-CPPPATH; would normally cause a different, same-named file from
592 a different directory to be used.
600 When &implicit-cache; is used, &SCons; will not detect if a
601 same-named file has been added to a directory that is earlier in
602 the search path than the directory in which the file was found
611 <title>The &implicit-deps-changed; Option</title>
615 When using cached implicit dependencies,
616 sometimes you want to "start fresh"
617 and have &SCons; re-scan the files
618 for which it previously cached the dependencies.
620 if you have recently installed a new version of
621 external code that you use for compilation,
622 the external header files will have changed
623 and the previously-cached implicit dependencies
625 You can update them by
626 running &SCons; with the &implicit-deps-changed; option:
631 % <userinput>scons -Q --implicit-deps-changed hello</userinput>
632 cc -o hello.o -c hello.c
634 % <userinput>scons -Q hello</userinput>
635 scons: `hello' is up to date.
640 In this case, &SCons; will re-scan all of the implicit dependencies
641 and cache updated copies of the information.
648 <title>The &implicit-deps-unchanged; Option</title>
652 By default when caching dependencies,
653 &SCons; notices when a file has been modified
654 and re-scans the file for any updated
655 implicit dependency information.
656 Sometimes, however, you may want
657 to force &SCons; to use the cached implicit dependencies,
658 even if the source files changed.
659 This can speed up a build for example,
660 when you have changed your source files
661 but know that you haven't changed
662 any <literal>#include</literal> lines.
664 you can use the &implicit-deps-unchanged; option:
669 % <userinput>scons -Q --implicit-deps-unchanged hello</userinput>
670 cc -o hello.o -c hello.c
672 % <userinput>scons -Q hello</userinput>
673 scons: `hello' is up to date.
679 &SCons; will assume that the cached implicit
680 dependencies are correct and
681 will not bother to re-scan changed files.
682 For typical builds after small,
683 incremental changes to source files,
684 the savings may not be very big,
685 but sometimes every bit of
686 improved performance counts.
695 <title>XXX max drift</title>
697 XXX SetOption('max_drift')
706 <title>Ignoring Dependencies: the &Ignore; Method</title>
710 Sometimes it makes sense
711 to not rebuild a program,
712 even if a dependency file changes.
714 you would tell &SCons; specifically
715 to ignore a dependency as follows:
720 hello = Program('hello.c')
721 Ignore(hello, 'hello.h')
724 <!-- XXX mention that you can use arrays for target and source? -->
727 <scons_output example="ignore">
728 <scons_output_command>scons -Q hello</scons_output_command>
729 <scons_output_command>scons -Q hello</scons_output_command>
730 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
731 <scons_output_command>scons -Q hello</scons_output_command>
732 XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
737 % <userinput>scons -Q hello</userinput>
738 cc -c -o hello.o hello.c
740 % <userinput>scons -Q hello</userinput>
741 scons: `hello' is up to date.
742 % <userinput>edit hello.h</userinput>
743 [CHANGE THE CONTENTS OF hello.h]
744 % <userinput>scons -Q hello</userinput>
745 scons: `hello' is up to date.
750 Now, the above example is a little contrived,
751 because it's hard to imagine a real-world situation
752 where you wouldn't to rebuild &hello;
753 if the &hello_h; file changed.
754 A more realistic example
755 might be if the &hello;
756 program is being built in a
757 directory that is shared between multiple systems
758 that have different copies of the
759 &stdio_h; include file.
761 &SCons; would notice the differences between
762 the different systems' copies of &stdio_h;
763 and would rebuild &hello;
764 each time you change systems.
765 You could avoid these rebuilds as follows:
770 hello = Program('hello.c')
771 Ignore(hello, '/usr/include/stdio.h')
777 <title>Explicit Dependencies: the &Depends; Method</title>
782 sometimes a file depends on another file
783 that is not detected by an &SCons; scanner.
785 &SCons; allows you to specific explicitly that one file
786 depends on another file,
787 and must be rebuilt whenever that file changes.
788 This is specified using the &Depends; method:
793 hello = Program('hello.c')
794 Depends(hello, 'other_file')
797 <!-- XXX mention that you can use arrays for target and source? -->
800 % <userinput>scons -Q hello</userinput>
801 cc -c hello.c -o hello.o
803 % <userinput>scons -Q hello</userinput>
804 scons: `hello' is up to date.
805 % <userinput>edit other_file</userinput>
806 [CHANGE THE CONTENTS OF other_file]
807 % <userinput>scons -Q hello</userinput>
808 cc -c hello.c -o hello.o
815 <title>The &AlwaysBuild; Method</title>
819 How &SCons; handles dependencies can also be affected
820 by the &AlwaysBuild; method.
821 When a file is passed to the &AlwaysBuild; method,
827 hello = Program('hello.c')
833 Then the specified target file (&hello; in our example)
834 will always be considered out-of-date and
835 rebuilt whenever that target file is evaluated
836 while walking the dependency graph:
841 % <userinput>scons -Q</userinput>
842 cc -o hello.o -c hello.c
844 % <userinput>scons -Q</userinput>
850 The &AlwaysBuild; function has a somewhat misleading name,
851 because it does not actually mean the target file will
852 be rebuilt every single time &SCons; is invoked.
853 Instead, it means that the target will, in fact,
854 be rebuilt whenever the target file is encountered
855 while evaluating the targets specified on
856 the command line (and their dependencies).
857 So specifying some other target on the command line,
858 a target that does <emphasis>not</emphasis>
859 itself depend on the &AlwaysBuild; target,
860 will still be rebuilt only if it's out-of-date
861 with respect to its dependencies:
866 % <userinput>scons -Q</userinput>
867 cc -o hello.o -c hello.c
869 % <userinput>scons -Q hello.o</userinput>
870 scons: `hello.o' is up to date.
875 XXX AlwaysBuild() and Alias Nodes
877 XXX AlwaysBuild() and Dir Nodes
879 XXX AlwaysBuild() with no sources
888 <title>The &Salt; Method</title>
892 XXX Salt() (are we going to implement this ?)
894 original Cons classic POD documentation:
896 =head2 The C<Salt> method
898 The C<Salt> method adds a constant value to the signature calculation
899 for every derived file. It is invoked as follows:
903 Changing the Salt value will force a complete rebuild of every derived
904 file. This can be used to force rebuilds in certain desired
905 circumstances. For example,
909 Would force a complete rebuild of every derived file whenever the
910 operating system on which the build is performed (as reported by C<uname