4 SPDX-FileCopyrightText: Copyright The SCons Foundation (https://scons.org)
5 SPDX-License-Identifier: MIT
6 SPDX-FileType: DOCUMENTATION
8 This file is processed by the bin/SConsDoc.py module.
12 <!ENTITY % scons SYSTEM "../scons.mod">
15 <!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
17 <!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
19 <!ENTITY % tools-mod SYSTEM "../generated/tools.mod">
21 <!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
26 <chapter id="chap-depends"
27 xmlns="http://www.scons.org/dbxsd/v1.0"
28 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
29 xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
30 <title>Dependencies</title>
34 So far we've seen how &SCons; handles one-time builds.
35 But one of the main functions of a build tool like &SCons;
36 is to rebuild only what is necessary
37 when source files change--or, put another way,
38 &SCons; should <emphasis>not</emphasis>
39 waste time rebuilding things that don't need to be rebuilt.
40 You can see this at work simply by re-invoking &SCons;
41 after building our simple &hello; example:
45 <scons_example name="depends_ex1">
46 <file name="SConstruct">
50 int main() { printf("Hello, world!\n"); }
54 <scons_output example="depends_ex1" os="posix" suffix="1">
55 <scons_output_command>scons -Q</scons_output_command>
56 <scons_output_command>scons -Q</scons_output_command>
61 The second time it is executed,
62 &SCons; realizes that the &hello; program
63 is up-to-date with respect to the current &hello_c; source file,
64 and avoids rebuilding it.
65 You can see this more clearly by naming
66 the &hello; program explicitly on the command line:
70 <scons_output example="depends_ex1" os="posix" suffix="2">
71 <scons_output_command>scons -Q hello</scons_output_command>
72 <scons_output_command>scons -Q hello</scons_output_command>
77 Note that &SCons; reports <literal>"...is up to date"</literal>
78 only for target files named explicitly on the command line,
79 to avoid cluttering the output.
84 <title>Deciding When an Input File Has Changed: the &Decider; Function</title>
88 Another aspect of avoiding unnecessary rebuilds
89 is the fundamental build tool behavior
90 of <emphasis>rebuilding</emphasis>
91 things when an input file changes,
92 so that the built software is up to date.
94 &SCons; keeps track of this through a
95 <firstterm>&contentsig;</firstterm>,
96 or hash, of the contents of each file,
97 although you can easily configure
99 modification times (or time stamps) instead.
100 You can even write your own Python function
101 for deciding if an input file should trigger a rebuild.
106 <title>Using Content Signatures to Decide if a File Has Changed</title>
111 uses a cryptographic hash of the file's contents,
112 not the file's modification time,
113 to decide whether a file has changed.
114 This means that you may be surprised by the
115 default &SCons; behavior if you are used to the
116 &Make; convention of forcing
117 a rebuild by updating the file's modification time
118 (using the &touch; command, for example):
122 <scons_output example="depends_ex1" os="posix" suffix="3">
123 <scons_output_command>scons -Q hello</scons_output_command>
124 <scons_output_command>touch hello.c</scons_output_command>
125 <scons_output_command>scons -Q hello</scons_output_command>
130 Even though the file's modification time has changed,
131 &SCons; realizes that the contents of the
132 &hello_c; file have <emphasis>not</emphasis> changed,
133 and therefore that the &hello; program
135 This avoids unnecessary rebuilds when,
136 for example, someone rewrites the
137 contents of a file without making a change.
138 But if the contents of the file really do change,
139 then &SCons; detects the change
140 and rebuilds the program as required:
144 <scons_output example="depends_ex1" os="posix" suffix="4">
145 <scons_output_command>scons -Q hello</scons_output_command>
146 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
147 <scons_output_command>scons -Q hello</scons_output_command>
152 Note that you can, if you wish,
153 specify the default behavior of using
154 &contentsigs; explicitly,
155 using the &f-link-Decider; function as follows:
166 You can also use the string <literal>'MD5'</literal>
167 as a synonym for <literal>'content'</literal>
168 when calling the &f-Decider; function - this older
169 name is deprecated since &SCons; now supports a
170 choice of hash functions, not just the MD5 function.
175 <title>Ramifications of Using Content Signatures</title>
179 Using &contentsigs; to decide if an input file has changed
180 has one surprising benefit:
181 if a source file has been changed
182 in such a way that the contents of the
183 rebuilt target file(s)
184 will be exactly the same as the last time
186 then any "downstream" target files
187 that depend on the rebuilt-but-not-changed target
188 file actually need not be rebuilt.
195 a user were to only change a comment in a &hello_c; file,
196 then the rebuilt &hello_o; file
197 would be exactly the same as the one previously built
198 (assuming the compiler doesn't put any build-specific
199 information in the object file).
200 &SCons; would then realize that it would not
201 need to rebuild the &hello; program as follows:
205 <scons_output example="depends_ex1" os="posix" suffix="5">
206 <scons_output_command>scons -Q hello</scons_output_command>
207 <scons_output_command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</scons_output_command>
208 <scons_output_command>scons -Q hello</scons_output_command>
214 "short-circuits" any dependent builds
215 when it realizes that a target file
216 has been rebuilt to exactly the same file as the last build.
217 This does take some extra processing time
218 to read the contents of the target (&hello_o;) file,
219 but often saves time when the rebuild that was avoided
220 would have been time-consuming and expensive.
229 <title>Using Time Stamps to Decide If a File Has Changed</title>
233 If you prefer, you can
234 configure &SCons; to use the modification time
235 of a file, not the file contents,
236 when deciding if a target needs to be rebuilt.
237 &SCons; gives you two ways to use time stamps
238 to decide if an input file has changed
239 since the last time a target has been built.
245 The most familiar way to use time stamps
246 is the way &Make; does:
247 that is, have &SCons; decide
248 that a target must be rebuilt
249 if a source file's modification time is
250 <emphasis>newer</emphasis>
251 than the target file.
252 To do this, call the &f-link-Decider;
257 <scons_example name="depends_newer">
258 <file name="SConstruct" printme="1">
260 Decider('timestamp-newer')
262 <file name="hello.c">
263 int main() { printf("Hello, world!\n"); }
269 This makes &SCons; act like &Make;
270 when a file's modification time is updated
271 (using the &touch; command, for example):
275 <scons_output example="depends_newer" os="posix" suffix="1">
276 <scons_output_command>scons -Q hello.o</scons_output_command>
277 <scons_output_command>touch hello.c</scons_output_command>
278 <scons_output_command>scons -Q hello.o</scons_output_command>
283 And, in fact, because this behavior is the same
284 as the behavior of &Make;,
285 you can also use the string <literal>'make'</literal>
286 as a synonym for <literal>'timestamp-newer'</literal>
287 when calling the &f-Decider; function:
298 One drawback to using times stamps exactly like &Make;
299 is that if an input file's modification time suddenly
300 becomes <emphasis>older</emphasis> than a target file,
301 the target file will not be rebuilt.
302 This can happen if an old copy of a source file is restored
303 from a backup archive, for example.
304 The contents of the restored file will likely be different
305 than they were the last time a dependent target was built,
306 but the target won't be rebuilt
307 because the modification time of the source file
308 is not newer than the target.
314 Because &SCons; actually stores information
315 about the source files' time stamps whenever a target is built,
316 it can handle this situation by checking for
317 an exact match of the source file time stamp,
318 instead of just whether or not the source file
319 is newer than the target file.
320 To do this, specify the argument
321 <literal>'timestamp-match'</literal>
322 when calling the &f-Decider; function:
326 <scons_example name="depends_match">
327 <file name="SConstruct" printme="1">
329 Decider('timestamp-match')
331 <file name="hello.c">
332 int main() { printf("Hello, world!\n"); }
338 When configured this way,
339 &SCons; will rebuild a target whenever
340 a source file's modification time has changed.
341 So if we use the <literal>touch -t</literal>
342 option to change the modification time of
343 &hello_c; to an old date (January 1, 1989),
344 &SCons; will still rebuild the target file:
348 <scons_output example="depends_match" os="posix" suffix="1">
349 <scons_output_command>scons -Q hello.o</scons_output_command>
350 <scons_output_command>touch -t 198901010000 hello.c</scons_output_command>
351 <scons_output_command>scons -Q hello.o</scons_output_command>
356 In general, the only reason to prefer
357 <literal>timestamp-newer</literal>
359 <literal>timestamp-match</literal>,
360 would be if you have some specific reason
361 to require this &Make;-like behavior of
362 not rebuilding a target when an otherwise-modified
363 source file is older.
370 <title>Deciding If a File Has Changed Using Both MD Signatures and Time Stamps</title>
374 As a performance enhancement,
375 &SCons; provides a way to use
376 a file's &contentsig;,
377 but to read those contents
378 only when the file's timestamp has changed.
379 To do this, call the &f-link-Decider;
380 function with <literal>'content-timestamp'</literal>
385 <scons_example name="depends_MD5-timestamp">
386 <file name="SConstruct" printme="1">
388 Decider('content-timestamp')
390 <file name="hello.c">
391 int main() { printf("Hello, world!\n"); }
397 So configured, &SCons; will still behave like
398 it does when using <literal>Decider('content')</literal>:
404 We want to generate the output as follows,
405 but our "surrogate" system for generating the
406 output seems to get this wrong.
407 Just in-line the output for now.
409 <scons_output example="depends_MD5-timestamp" os="posix" suffix="1">
410 <scons_output_command>scons -Q hello</scons_output_command>
411 <scons_output_command>touch hello.c</scons_output_command>
412 <scons_output_command>scons -Q hello</scons_output_command>
413 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
414 <scons_output_command>scons -Q hello</scons_output_command>
420 % <userinput>scons -Q hello</userinput>
421 cc -o hello.o -c hello.c
423 % <userinput>touch hello.c</userinput>
424 % <userinput>scons -Q hello</userinput>
425 scons: `hello' is up to date.
426 % <userinput>edit hello.c</userinput>
427 [CHANGE THE CONTENTS OF hello.c]
428 % <userinput>scons -Q hello</userinput>
429 cc -o hello.o -c hello.c
435 However, the second call to &SCons; in the above output,
436 when the build is up-to-date,
437 will have been performed by simply looking at the
438 modification time of the &hello_c; file,
439 not by opening it and performing
440 a signature calculation on its contents.
441 This can significantly speed up many up-to-date builds.
447 The only drawback to using
448 <literal>Decider('content-timestamp')</literal>
449 is that &SCons; will <emphasis>not</emphasis>
450 rebuild a target file if a source file was modified
451 within one second of the last time &SCons; built the file.
452 While most developers are programming,
453 this isn't a problem in practice,
454 since it's unlikely that someone will have built
455 and then thought quickly enough to make a substantive
456 change to a source file within one second.
457 Certain build scripts or
458 continuous integration tools may, however,
459 rely on the ability to apply changes to files
460 automatically and then rebuild as quickly as possible,
462 <literal>Decider('content-timestamp')</literal>
463 may not be appropriate.
470 <title>Extending &SCons;: Writing Your Own Custom &Decider; Function</title>
474 The different string values that we've passed to
475 the &f-link-Decider; function are essentially used by &SCons;
476 to pick one of several specific internal functions
477 that implement various ways of deciding if a dependency
478 (usually a source file)
479 has changed since a target file has been built.
481 you can also supply your own function
482 to decide if a dependency has changed.
488 For example, suppose we have an input file
489 that contains a lot of data,
490 in some specific regular format,
491 that is used to rebuild a lot of different target files,
492 but each target file really only depends on
493 one particular section of the input file.
494 We'd like to have each target file depend on
495 only its section of the input file.
496 However, since the input file may contain a lot of data,
497 we want to open the input file only if its timestamp has changed.
498 This could be done with a custom
499 &Decider; function that might look something like this:
503 <scons_example name="depends_function">
504 <file name="SConstruct" printme="1">
506 def decide_if_changed(dependency, target, prev_ni, repo_node=None):
507 if dependency.get_timestamp() != prev_ni.timestamp:
508 dep = str(dependency)
510 if specific_part_of_file_has_changed(dep, tgt):
513 Decider(decide_if_changed)
515 <file name="hello.c">
516 int main() { printf("Hello, world!\n"); }
522 Note that in the function definition,
523 the <varname>dependency</varname>
524 (input file) is the first argument,
525 and then the ⌖.
526 Both of these are passed to the functions as
527 SCons &Node; objects,
528 which we convert to strings using the Python
529 <function>str()</function>.
535 The third argument, <varname>prev_ni</varname>,
536 is an object that holds the
537 &contentsig; and/or timestamp information
538 that was recorded about the dependency
539 the last time the target was built.
540 A <varname>prev_ni</varname> object can hold
541 different information,
542 depending on the type of thing that the
543 <varname>dependency</varname> argument represents.
545 the <varname>prev_ni</varname> object
546 has the following attributes:
553 <term><literal>csig</literal></term>
558 a cryptographic hash, or checksum, of the file contents
559 of the <varname>dependency</varname>
560 file the last time the ⌖ was built.
567 <term><literal>size</literal></term>
571 The size in bytes of the <varname>dependency</varname>
572 file the last time the target was built.
579 <term><literal>timestamp</literal></term>
583 The modification time of the <varname>dependency</varname>
584 file the last time the ⌖ was built.
594 These attributes may not be present at the time of the
595 first run. Without any prior build, no targets have been
596 created and no <filename>.sconsign</filename> DB file exists yet.
597 So you should always check whether the
598 <varname>prev_ni</varname> attribute in question is available
599 (use the Python <function>hasattr</function> method or a
600 <literal>try</literal>-<literal>except</literal> block).
607 The fourth argument <varname>repo_node</varname>
608 is the &Node; to use if it is not None when comparing &BuildInfo;.
609 This is typically only set when the target node only exists in a
616 Note that ignoring some of the arguments
617 in your custom &Decider; function
618 is a perfectly normal thing to do,
619 if they don't impact the way you want to
620 decide if the dependency file has changed.
626 We finally present a small example for a
627 <varname>csig</varname>-based decider function. Note how the
628 signature information for the <varname>dependency</varname> file
629 has to get initialized via <function>get_csig</function>
630 during each function call (this is mandatory!).
638 def config_file_decider(dependency, target, prev_ni, repo_node=None):
641 # We always have to init the .csig value...
642 dep_csig = dependency.get_csig()
643 # .csig may not exist, because no target was built yet...
644 if not prev_ni.hasattr("csig"):
646 # Target file may not exist yet
647 if not os.path.exists(str(target.abspath)):
649 if dep_csig != prev_ni.csig:
650 # Some change on source file => update installed one
656 with open("test.txt", "a") as f:
657 f.write("some line\n")
662 # Activate our own decider function
663 env.Decider(config_file_decider)
665 env.Install("install", "test.txt")
671 <title>Mixing Different Ways of Deciding If a File Has Changed</title>
675 The previous examples have all demonstrated calling
676 the global &f-link-Decider; function
677 to configure all dependency decisions that &SCons; makes.
678 Sometimes, however, you want to be able to configure
679 different decision-making for different targets.
680 When that's necessary, you can use the &f-env-Decider;
681 method to affect only the configuration
682 decisions for targets built with a
689 For example, if we arbitrarily want to build
690 one program using &contentsigs;
691 and another using file modification times
693 we might configure it this way:
697 <scons_example name="depends_mixing">
698 <file name="SConstruct" printme="1">
699 env1 = Environment(CPPPATH = ['.'])
701 env2.Decider('timestamp-match')
702 env1.Program('prog-content', 'program1.c')
703 env2.Program('prog-timestamp', 'program2.c')
705 <file name="program1.c">
707 int main() { printf("Hello, world!\n"); }
709 <file name="program2.c">
711 int main() { printf("Hello, world!\n"); }
720 If both of the programs include the same
721 <filename>inc.h</filename> file,
722 then updating the modification time of
723 <filename>inc.h</filename>
724 (using the &touch; command)
725 will cause only <filename>prog-timestamp</filename>
730 <scons_output example="depends_mixing" os="posix" suffix="1">
731 <scons_output_command>scons -Q</scons_output_command>
732 <scons_output_command>touch inc.h</scons_output_command>
733 <scons_output_command>scons -Q</scons_output_command>
741 <title>Implicit Dependencies: The &cv-CPPPATH; Construction Variable</title>
745 Now suppose that our "Hello, World!" program
746 actually has an <literal>#include</literal> line
747 to include the &hello_h; file in the compilation:
751 <scons_example name="depends_include">
752 <file name="SConstruct">
753 Program('hello.c', CPPPATH='.')
755 <file name="hello.c" printme="1">
756 #include <hello.h>
760 printf("Hello, %s!\n", string);
763 <file name="hello.h">
764 #define string "world"
770 And, for completeness, the &hello_h; file looks like this:
774 <scons_example_file example="depends_include" name="hello.h">
775 </scons_example_file>
779 In this case, we want &SCons; to recognize that,
780 if the contents of the &hello_h; file change,
781 the &hello; program must be recompiled.
782 To do this, we need to modify the
783 &SConstruct; file like so:
787 <scons_example_file example="depends_include" name="SConstruct">
788 </scons_example_file>
792 The &cv-link-CPPPATH; value
793 tells &SCons; to look in the current directory
794 (<literal>'.'</literal>)
795 for any files included by C source files
796 (<filename>.c</filename> or <filename>.h</filename> files).
797 With this assignment in the &SConstruct; file:
801 <scons_output example="depends_include" os="posix" suffix="1">
802 <scons_output_command>scons -Q hello</scons_output_command>
803 <scons_output_command>scons -Q hello</scons_output_command>
804 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
805 <scons_output_command>scons -Q hello</scons_output_command>
810 First, notice that &SCons;
811 constructed the <literal>-I.</literal> argument
812 from the <literal>'.'</literal> in the &cv-CPPPATH; variable
813 so that the compilation would find the
814 &hello_h; file in the local directory.
820 Second, realize that &SCons; knows that the &hello;
821 program must be rebuilt
822 because it scans the contents of
824 for the <literal>#include</literal> lines that indicate
825 another file is being included in the compilation.
826 &SCons; records these as
827 <emphasis>implicit dependencies</emphasis>
830 when the &hello_h; file changes,
831 &SCons; realizes that the &hello_c; file includes it,
832 and rebuilds the resulting &hello; program
833 that depends on both the &hello_c; and &hello_h; files.
839 Like the &cv-link-LIBPATH; variable,
840 the &cv-CPPPATH; variable
841 may be a list of directories,
842 or a string separated by
843 the system-specific path separation character
844 (':' on POSIX/Linux, ';' on Windows).
845 Either way, &SCons; creates the
846 right command-line options
847 so that the following example:
851 <scons_example name="depends_ex5">
852 <file name="SConstruct" printme="1">
853 Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
855 <file name="hello.c">
856 int main() { printf("Hello, world!\n"); }
862 Will look like this on POSIX or Linux:
866 <scons_output example="depends_ex5" os="posix" suffix="1">
867 <scons_output_command>scons -Q hello</scons_output_command>
872 And like this on Windows:
876 <scons_output example="depends_ex5" os="win32" suffix="2">
877 <scons_output_command>scons -Q hello.exe</scons_output_command>
883 <title>Caching Implicit Dependencies</title>
887 Scanning each file for <literal>#include</literal> lines
888 does take some extra processing time.
889 When you're doing a full build of a large system,
890 the scanning time is usually a very small percentage
891 of the overall time spent on the build.
892 You're most likely to notice the scanning time,
893 however, when you <emphasis>rebuild</emphasis>
894 all or part of a large system:
895 &SCons; will likely take some extra time to "think about"
896 what must be built before it issues the
898 (or decides that everything is up to date
899 and nothing must be rebuilt).
902 Isn't this expensive? The answer is, it depends. If you do a full build of a
903 large system, the scanning time is insignificant. If you do a rebuild of a
904 large system, then Cons will spend a fair amount of time thinking about it
905 before it decides that nothing has to be done (although not necessarily more
906 time than make!). The good news is that Cons makes it very easy to
907 intelligently subset your build, when you are working on localized changes.
914 In practice, having &SCons; scan files saves time
915 relative to the amount of potential time
916 lost to tracking down subtle problems
917 introduced by incorrect dependencies.
918 Nevertheless, the "waiting time"
919 while &SCons; scans files can annoy
920 individual developers waiting for their builds to finish.
921 Consequently, &SCons; lets you cache
922 the implicit dependencies
923 that its scanners find,
924 for use by later builds.
925 You can do this by specifying the
926 &implicit-cache; option on the command line:
930 <scons_output example="depends_ex1" suffix="6">
931 <scons_output_command>scons -Q --implicit-cache hello</scons_output_command>
932 <scons_output_command>scons -Q hello</scons_output_command>
937 If you don't want to specify &implicit-cache;
938 on the command line each time,
939 you can make it the default behavior for your build
940 by setting the &implicit_cache; option
941 in an &SConscript; file:
946 SetOption('implicit_cache', 1)
951 &SCons; does not cache implicit dependencies like this by default
952 because the &implicit-cache; causes &SCons; to simply use the implicit
953 dependencies stored during the last run, without any checking
954 for whether or not those dependencies are still correct.
955 Specifically, this means &implicit-cache; instructs &SCons;
956 to <emphasis>not</emphasis> rebuild "correctly" in the
967 When &implicit-cache; is used, &SCons; will ignore any changes that
968 may have been made to search paths
969 (like &cv-CPPPATH; or &cv-LIBPATH;).
970 This can lead to &SCons; not rebuilding a file if a change to
971 &cv-CPPPATH; would normally cause a different, same-named file from
972 a different directory to be used.
980 When &implicit-cache; is used, &SCons; will not detect if a
981 same-named file has been added to a directory that is earlier in
982 the search path than the directory in which the file was found
991 <title>The &implicit-deps-changed; Option</title>
995 When using cached implicit dependencies,
996 sometimes you want to "start fresh"
997 and have &SCons; re-scan the files
998 for which it previously cached the dependencies.
1000 if you have recently installed a new version of
1001 external code that you use for compilation,
1002 the external header files will have changed
1003 and the previously-cached implicit dependencies
1004 will be out-of-date.
1005 You can update them by
1006 running &SCons; with the &implicit-deps-changed; option:
1010 <scons_output example="depends_ex1" suffix="7">
1011 <scons_output_command>scons -Q --implicit-deps-changed hello</scons_output_command>
1012 <scons_output_command>scons -Q hello</scons_output_command>
1017 In this case, &SCons; will re-scan all of the implicit dependencies
1018 and cache updated copies of the information.
1025 <title>The &implicit-deps-unchanged; Option</title>
1029 By default, when caching dependencies,
1030 &SCons; notices when a file has been modified
1031 and re-scans the file for any updated
1032 implicit dependency information.
1033 Sometimes, however, you may want
1034 to force &SCons; to use the cached implicit dependencies,
1035 even if the source files changed.
1036 This can speed up a build for example,
1037 when you have changed your source files
1038 but know that you haven't changed
1039 any <literal>#include</literal> lines.
1041 you can use the &implicit-deps-unchanged; option:
1045 <scons_output example="depends_ex1" suffix="8">
1046 <scons_output_command>scons -Q --implicit-deps-unchanged hello</scons_output_command>
1047 <scons_output_command>scons -Q hello</scons_output_command>
1053 &SCons; will assume that the cached implicit
1054 dependencies are correct and
1055 will not bother to re-scan changed files.
1056 For typical builds after small,
1057 incremental changes to source files,
1058 the savings may not be very big,
1059 but sometimes every bit of
1060 improved performance counts.
1069 <title>XXX max drift</title>
1071 XXX SetOption('max_drift')
1080 <title>Explicit Dependencies: the &Depends; Function</title>
1084 Sometimes a file depends on another file
1085 that is not detected by an &SCons; scanner.
1087 &SCons; allows you to specific explicitly that one file
1088 depends on another file,
1089 and must be rebuilt whenever that file changes.
1090 This is specified using the &f-link-Depends; method:
1095 hello = Program('hello.c')
1096 Depends(hello, 'other_file')
1099 <!-- XXX mention that you can use arrays for target and source? -->
1102 % <userinput>scons -Q hello</userinput>
1103 cc -c hello.c -o hello.o
1105 % <userinput>scons -Q hello</userinput>
1106 scons: `hello' is up to date.
1107 % <userinput>edit other_file</userinput>
1108 [CHANGE THE CONTENTS OF other_file]
1109 % <userinput>scons -Q hello</userinput>
1110 cc -c hello.c -o hello.o
1116 Note that the dependency
1117 (the second argument to &f-Depends;)
1118 may also be a list of Node objects
1119 (for example, as returned by a call to a Builder):
1124 hello = Program('hello.c')
1125 goodbye = Program('goodbye.c')
1126 Depends(hello, goodbye)
1131 in which case the dependency or dependencies
1132 will be built before the target(s):
1137 % <userinput>scons -Q hello</userinput>
1138 cc -c goodbye.c -o goodbye.o
1139 cc -o goodbye goodbye.o
1140 cc -c hello.c -o hello.o
1147 <title>Dependencies From External Files: the &ParseDepends;
1152 &SCons; has built-in scanners for a number of languages. Sometimes
1153 these scanners fail to extract certain implicit dependencies due
1154 to limitations of the scanner implementation.
1160 The following example illustrates a case where the built-in C
1161 scanner is unable to extract the implicit dependency on a header
1166 <scons_example name="depends_macroinc">
1167 <file name="hello.c" printme="1">
1168 #define FOO_HEADER <foo.h>
1175 <file name="SConstruct">
1176 Program('hello', 'hello.c', CPPPATH='.')
1183 <scons_output example="depends_macroinc" os="posix" suffix="1">
1184 <scons_output_command>scons -Q</scons_output_command>
1185 <scons_output_command output=" [CHANGE CONTENTS OF foo.h]">edit foo.h</scons_output_command>
1186 <scons_output_command>scons -Q</scons_output_command>
1191 Apparently, the scanner does not know about the header dependency.
1192 Not being a full-fledged C preprocessor, the scanner does not
1199 In these cases, you may also use the compiler to extract the
1200 implicit dependencies. &f-link-ParseDepends; can parse the contents of
1201 the compiler output in the style of &Make;, and explicitly
1202 establish all of the listed dependencies.
1208 The following example uses &f-ParseDepends; to process a compiler
1209 generated dependency file which is generated as a side effect
1210 during compilation of the object file:
1214 <!-- XXX The ParseDepends example below fakes proper working by a
1215 priori specification of the dependency file. The produced hello.d
1216 file is not found (or used) for unknown reasons. -->
1218 <scons_example name="depends_parsedep">
1219 <file name="hello.c">
1220 #define FOO_HEADER <foo.h>
1227 <file name="SConstruct" printme="1">
1228 obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
1229 SideEffect('hello.d', obj)
1230 ParseDepends('hello.d')
1231 Program('hello', obj)
1236 <file name="hello.d">
1237 hello.o: hello.c foo.h
1241 <scons_output example="depends_parsedep" os="posix" suffix="1">
1242 <scons_output_command>scons -Q</scons_output_command>
1243 <scons_output_command output=" [CHANGE CONTENTS OF foo.h]">edit foo.h</scons_output_command>
1244 <scons_output_command>scons -Q</scons_output_command>
1249 Parsing dependencies from a compiler-generated
1250 <filename>.d</filename> file has a chicken-and-egg problem, that
1251 causes unnecessary rebuilds:
1255 <scons_example name="depends_parsedeprebuild">
1256 <file name="hello.c">
1257 #define FOO_HEADER <foo.h>
1264 <file name="SConstruct">
1265 obj = Object('hello.c', CCFLAGS='-MD -MF hello.d', CPPPATH='.')
1266 SideEffect('hello.d', obj)
1267 ParseDepends('hello.d')
1268 Program('hello', obj)
1276 <scons_output example="depends_parsedeprebuild" os="posix" suffix="1">
1277 <scons_output_command>scons -Q</scons_output_command>
1278 <scons_output_command>scons -Q</scons_output_command>
1279 <scons_output_command>scons -Q</scons_output_command>
1284 % <userinput>scons -Q</userinput>
1285 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1287 % <userinput>scons -Q --debug=explain</userinput>
1288 scons: rebuilding `hello.o' because `foo.h' is a new dependency
1289 cc -o hello.o -c -MD -MF hello.d -I. hello.c
1290 % <userinput>scons -Q</userinput>
1291 scons: `.' is up to date.
1296 In the first pass, the dependency file is generated while the
1297 object file is compiled. At that time, &SCons; does not know about
1298 the dependency on <filename>foo.h</filename>. In the second pass,
1299 the object file is regenerated because <filename>foo.h</filename>
1300 is detected as a new dependency.
1306 &f-ParseDepends; immediately reads the specified file at invocation
1307 time and just returns if the file does not exist. A dependency
1308 file generated during the build process is not automatically
1309 parsed again. Hence, the compiler-extracted dependencies are not
1310 stored in the signature database during the same build pass. This
1311 limitation of &f-ParseDepends; leads to unnecessary recompilations.
1312 Therefore, &f-ParseDepends; should only be used if scanners are not
1313 available for the employed language or not powerful enough for the
1321 <title>Ignoring Dependencies: the &Ignore; Function</title>
1325 Sometimes it makes sense
1326 to not rebuild a program,
1327 even if a dependency file changes.
1329 you would tell &SCons; specifically
1330 to ignore a dependency using the
1331 &f-link-Ignore; function as follows:
1335 <scons_example name="depends_ignore">
1336 <file name="SConstruct" printme="1">
1337 hello_obj=Object('hello.c')
1338 hello = Program(hello_obj)
1339 Ignore(hello_obj, 'hello.h')
1341 <file name="hello.c">
1343 int main() { printf("Hello, %s!\n", string); }
1345 <file name="hello.h">
1346 #define string "world"
1350 <!-- XXX mention that you can use lists for target and source? -->
1353 <scons_output example="depends_ignore" suffix="1">
1354 <scons_output_command>scons -Q hello</scons_output_command>
1355 <scons_output_command>scons -Q hello</scons_output_command>
1356 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</scons_output_command>
1357 <scons_output_command>scons -Q hello</scons_output_command>
1358 XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
1363 % <userinput>scons -Q hello</userinput>
1364 cc -c -o hello.o hello.c
1366 % <userinput>scons -Q hello</userinput>
1367 scons: `hello' is up to date.
1368 % <userinput>edit hello.h</userinput>
1369 [CHANGE THE CONTENTS OF hello.h]
1370 % <userinput>scons -Q hello</userinput>
1371 scons: `hello' is up to date.
1376 Now, the above example is a little contrived,
1377 because it's hard to imagine a real-world situation
1378 where you wouldn't want to rebuild &hello;
1379 if the &hello_h; file changed.
1380 A more realistic example
1381 might be if the &hello;
1382 program is being built in a
1383 directory that is shared between multiple systems
1384 that have different copies of the
1385 &stdio_h; include file.
1387 &SCons; would notice the differences between
1388 the different systems' copies of &stdio_h;
1389 and would rebuild &hello;
1390 each time you change systems.
1391 You could avoid these rebuilds as follows:
1396 hello = Program('hello.c', CPPPATH=['/usr/include'])
1397 Ignore(hello, '/usr/include/stdio.h')
1401 &f-Ignore; can also be used to prevent a generated file from being built
1402 by default. This is due to the fact that directories depend on
1403 their contents. So to ignore a generated file from the default build,
1404 you specify that the directory should ignore the generated file.
1405 Note that the file will still be built if the user specifically
1406 requests the target on scons command line, or if the file is
1407 a dependency of another file which is requested and/or is built
1411 <scons_example name="depends_ignore_explicit">
1412 <file name="SConstruct" printme="1">
1413 hello_obj=Object('hello.c')
1414 hello = Program(hello_obj)
1415 Ignore('.',[hello,hello_obj])
1417 <file name="hello.c">
1419 int main() { printf("Hello!\n"); }
1423 <scons_output example="depends_ignore_explicit" os="posix" suffix="1">
1424 <scons_output_command>scons -Q</scons_output_command>
1425 <scons_output_command>scons -Q hello</scons_output_command>
1426 <scons_output_command>scons -Q hello</scons_output_command>
1431 <title>Order-Only Dependencies: the &Requires; Function</title>
1436 it may be useful to specify that a certain
1437 file or directory must, if necessary,
1438 be built or created before some other target is built,
1439 but that changes to that file or directory
1440 do <emphasis>not</emphasis>
1441 require that the target itself be rebuilt.
1442 Such a relationship is called an
1443 <emphasis>order-only dependency</emphasis>
1444 because it only affects the order in which
1445 things must be built--the dependency before the target--but
1446 it is not a strict dependency relationship
1447 because the target should not
1448 change in response to changes in the dependent file.
1454 For example, suppose that you want to create a file
1455 every time you run a build
1456 that identifies the time the build was performed,
1457 the version number, etc.,
1458 and which is included in every program that you build.
1459 The version file's contents will change every build.
1460 If you specify a normal dependency relationship,
1461 then every program that depends on
1462 that file would be rebuilt every time you ran &SCons;.
1463 For example, we could use some Python code in
1464 a &SConstruct; file to create a new <filename>version.c</filename> file
1465 with a string containing the current date every time
1467 and then link a program with the resulting object file
1468 by listing <filename>version.c</filename> in the sources:
1472 <scons_example name="depends_no-Requires">
1473 <file name="SConstruct" printme="1">
1476 version_c_text = """
1478 """ % time.ctime(time.time())
1479 open('version.c', 'w').write(version_c_text)
1481 hello = Program(['hello.c', 'version.c'])
1483 <file name="hello.c">
1485 int main() { printf("Hello, %s! I was built: %s\n", date); }
1491 If we list <filename>version.c</filename> as an actual source file,
1492 though, then the <filename>version.o</filename> file
1493 will get rebuilt every time we run &SCons;
1494 (because the &SConstruct; file itself changes
1495 the contents of <filename>version.c</filename>)
1496 and the <filename>hello</filename> executable
1497 will get re-linked every time
1498 (because the <filename>version.o</filename> file changes):
1502 <scons_output example="depends_no-Requires" suffix="1">
1503 <scons_output_command>scons -Q hello</scons_output_command>
1504 <scons_output_command>sleep 1</scons_output_command>
1505 <scons_output_command>scons -Q hello</scons_output_command>
1506 <scons_output_command>sleep 1</scons_output_command>
1507 <scons_output_command>scons -Q hello</scons_output_command>
1512 (Note that for the above example to work,
1513 we &sleep; for one second in between each run,
1514 so that the &SConstruct; file will create a
1515 <filename>version.c</filename> file with a time string
1516 that's one second later than the previous run.)
1522 One solution is to use the &f-link-Requires; function
1523 to specify that the <filename>version.o</filename>
1524 must be rebuilt before it is used by the link step,
1525 but that changes to <filename>version.o</filename>
1526 should not actually cause the <filename>hello</filename>
1527 executable to be re-linked:
1531 <scons_example name="depends_Requires">
1532 <file name="SConstruct" printme="1">
1535 version_c_text = """
1537 """ % time.ctime(time.time())
1538 open('version.c', 'w').write(version_c_text)
1540 version_obj = Object('version.c')
1542 hello = Program('hello.c',
1543 LINKFLAGS = str(version_obj[0]))
1545 Requires(hello, version_obj)
1547 <file name="hello.c">
1549 int main() { printf("Hello, %s! I was built: %s\n", date); }
1555 Notice that because we can no longer list <filename>version.c</filename>
1556 as one of the sources for the <filename>hello</filename> program,
1557 we have to find some other way to get it into the link command line.
1558 For this example, we're cheating a bit and stuffing the
1559 object file name (extracted from <literal>version_obj</literal>
1560 list returned by the &b-Object; builder call)
1561 into the &cv-link-LINKFLAGS; variable,
1562 because &cv-LINKFLAGS; is already included
1563 in the &cv-link-LINKCOM; command line.
1570 we get the desired behavior of only
1571 re-linking the <filename>hello</filename> executable
1572 when the <filename>hello.c</filename> has changed,
1573 even though the <filename>version.o</filename> is rebuilt
1574 (because the &SConstruct; file still changes the
1575 <filename>version.c</filename> contents directly each run):
1579 <scons_output example="depends_Requires" suffix="1">
1580 <scons_output_command>scons -Q hello</scons_output_command>
1581 <scons_output_command>sleep 1</scons_output_command>
1582 <scons_output_command>scons -Q hello</scons_output_command>
1583 <scons_output_command>sleep 1</scons_output_command>
1584 <scons_output_command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</scons_output_command>
1585 <scons_output_command>scons -Q hello</scons_output_command>
1586 <scons_output_command>sleep 1</scons_output_command>
1587 <scons_output_command>scons -Q hello</scons_output_command>
1593 <title>The &AlwaysBuild; Function</title>
1597 How &SCons; handles dependencies can also be affected
1598 by the &f-link-AlwaysBuild; method.
1599 When a file is passed to the &f-AlwaysBuild; method,
1604 <scons_example name="depends_AlwaysBuild">
1605 <file name="SConstruct" printme="1">
1606 hello = Program('hello.c')
1609 <file name="hello.c">
1610 int main() { printf("Hello, %s!\n", string); }
1616 Then the specified target file (&hello; in our example)
1617 will always be considered out-of-date and
1618 rebuilt whenever that target file is evaluated
1619 while walking the dependency graph:
1623 <scons_output example="depends_AlwaysBuild" suffix="1">
1624 <scons_output_command>scons -Q</scons_output_command>
1625 <scons_output_command>scons -Q</scons_output_command>
1630 The &f-AlwaysBuild; function has a somewhat misleading name,
1631 because it does not actually mean the target file will
1632 be rebuilt every single time &SCons; is invoked.
1633 Instead, it means that the target will, in fact,
1634 be rebuilt whenever the target file is encountered
1635 while evaluating the targets specified on
1636 the command line (and their dependencies).
1637 So specifying some other target on the command line,
1638 a target that does <emphasis>not</emphasis>
1639 itself depend on the &f-AlwaysBuild; target,
1640 will still be rebuilt only if it's out-of-date
1641 with respect to its dependencies:
1645 <scons_output example="depends_AlwaysBuild" suffix="2">
1646 <scons_output_command>scons -Q</scons_output_command>
1647 <scons_output_command>scons -Q hello.o</scons_output_command>
1652 XXX AlwaysBuild() and Alias Nodes
1654 XXX AlwaysBuild() and Dir Nodes
1656 XXX AlwaysBuild() with no sources
1665 <title>The &Salt; Method</title>
1669 XXX Salt() (are we going to implement this ?)
1671 original Cons classic POD documentation:
1673 =head2 The C<Salt> method
1675 The C<Salt> method adds a constant value to the signature calculation
1676 for every derived file. It is invoked as follows:
1680 Changing the Salt value will force a complete rebuild of every derived
1681 file. This can be used to force rebuilds in certain desired
1682 circumstances. For example,
1686 Would force a complete rebuild of every derived file whenever the
1687 operating system on which the build is performed (as reported by C<uname