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 Often, a software project will have
29 one or more central repositories,
30 directory trees that contain
31 source code, or derived files, or both.
32 You can eliminate additional unnecessary
33 rebuilds of files by having &SCons;
34 use files from one or more code repositories
35 to build files in your local build tree.
40 <title>The &Repository; Method</title>
44 The repository directories specified may contain source files, derived files
45 (objects, libraries and executables), or both. If there is no local file
46 (source or derived) under the directory in which Cons is executed, then the
47 first copy of a same-named file found under a repository directory will be
48 used to build any local derived files.
54 It's often useful to allow multiple programmers working
55 on a project to build software from
56 source files and/or derived files that
57 are stored in a centrally-accessible repository,
58 a directory copy of the source code tree.
59 (Note that this is not the sort of repository
60 maintained by a source code management system
61 like BitKeeper, CVS, or Subversion.)
63 For information about using &SCons;
64 with these systems, see the section,
65 "Fetching Files From Source Code Management Systems,"
68 You use the &Repository; method
69 to tell &SCons; to search one or more
70 central code repositories (in order)
71 for any source files and derived files
72 that are not present in the local build tree:
78 env.Program('hello.c')
79 Repository('/usr/repository1', '/usr/repository2')
84 Multiple calls to the &Repository; method
85 will simply add repositories to the global list
86 that &SCons; maintains,
87 with the exception that &SCons; will automatically eliminate
88 the current directory and any non-existent
89 directories from the list.
96 <title>Finding source files in repositories</title>
101 specifies that &SCons;
102 will first search for files under
103 the <filename>/usr/repository1</filename> tree
104 and next under the <filename>/usr/repository2</filename> tree.
105 &SCons; expects that any files it searches
106 for will be found in the same position
107 relative to the top-level directory.
108 In the above example, if the &hello_c; file is not
109 found in the local build tree,
110 &SCons; will search first for
111 a <filename>/usr/repository1/hello.c</filename> file
112 and then for a <filename>/usr/repository2/hello.c</filename> file
119 So given the &SConstruct; file above,
120 if the &hello_c; file exists in the local
122 &SCons; will rebuild the &hello; program
128 % <userinput>scons -Q</userinput>
129 cc -o hello.o -c hello.c
135 If, however, there is no local &hello_c; file,
136 but one exists in <filename>/usr/repository1</filename>,
137 &SCons; will recompile the &hello; program
138 from the source file it finds in the repository:
145 % <userinput>scons -Q</userinput>
146 cc -o hello.o -c /usr/repository1/hello.c
152 And similarly, if there is no local &hello_c; file
153 and no <filename>/usr/repository1/hello.c</filename>,
154 but one exists in <filename>/usr/repository2</filename>:
161 % <userinput>scons -Q</userinput>
162 cc -o hello.o -c /usr/repository2/hello.c
173 <title>Finding <literal>#include</literal> files in repositories</title>
177 We've already seen that SCons will scan the contents of
178 a source file for <literal>#include</literal> file names
179 and realize that targets built from that source file
180 also depend on the <literal>#include</literal> file(s).
181 For each directory in the &cv-link-CPPPATH; list,
182 &SCons; will actually search the corresponding directories
183 in any repository trees and establish the
184 correct dependencies on any
185 <literal>#include</literal> files that it finds
186 in repository directory.
192 Unless the C compiler also knows about these directories
193 in the repository trees, though,
194 it will be unable to find the <literal>#include</literal> files.
195 If, for example, the &hello_c; file in
196 our previous example includes the &hello;.h;
197 in its current directory,
198 and the &hello;.h; only exists in the repository:
203 % <userinput>scons -Q</userinput>
204 cc -o hello.o -c hello.c
205 hello.c:1: hello.h: No such file or directory
210 In order to inform the C compiler about the repositories,
211 &SCons; will add appropriate
212 <literal>-I</literal> flags to the compilation commands
213 for each directory in the &cv-CPPPATH; list.
214 So if we add the current directory to the
215 construction environment &cv-CPPPATH; like so:
220 env = Environment(CPPPATH = ['.'])
221 env.Program('hello.c')
222 Repository('/usr/repository1')
227 Then re-executing &SCons; yields:
232 % <userinput>scons -Q</userinput>
233 cc -o hello.o -c -I. -I/usr/repository1 hello.c
239 The order of the <literal>-I</literal> options replicates,
240 for the C preprocessor,
241 the same repository-directory search path
242 that &SCons; uses for its own dependency analysis.
243 If there are multiple repositories and multiple &cv-CPPPATH;
244 directories, &SCons; will add the repository directories
245 to the beginning of each &cv-CPPPATH; directory,
246 rapidly multiplying the number of <literal>-I</literal> flags.
247 If, for example, the &cv-CPPPATH; contains three directories
248 (and shorter repository path names!):
253 env = Environment(CPPPATH = ['dir1', 'dir2', 'dir3'])
254 env.Program('hello.c')
255 Repository('/r1', '/r2')
260 Then we'll end up with nine <literal>-I</literal> options
262 three (for each of the &cv-CPPPATH; directories)
263 times three (for the local directory plus the two repositories):
268 % <userinput>scons -Q</userinput>
269 cc -o hello.o -c -Idir1 -I/r1/dir1 -I/r2/dir1 -Idir2 -I/r1/dir2 -I/r2/dir2 -Idir3 -I/r1/dir3 -I/r2/dir3 hello.c
275 Cons classic did the following, does SCons?
277 In order to shorten the command lines as much as possible, Cons will
278 remove C<-I> flags for any directories, locally or in the repositories,
279 which do not actually exist. (Note that the C<-I> flags are not included
280 in the MD5 signature calculation for the target file, so the target will
281 not be recompiled if the compilation command changes due to a directory
282 coming into existence.)
287 <title>Limitations on <literal>#include</literal> files in repositories</title>
291 &SCons; relies on the C compiler's
292 <literal>-I</literal> options to control the order in which
293 the preprocessor will search the repository directories
294 for <literal>#include</literal> files.
295 This causes a problem, however, with how the C preprocessor
296 handles <literal>#include</literal> lines with
297 the file name included in double-quotes.
304 &SCons; will compile the &hello_c; file from
305 the repository if it doesn't exist in
307 If, however, the &hello_c; file in the repository contains
308 a <literal>#include</literal> line with the file name in
316 main(int argc, char *argv[])
318 printf(HELLO_MESSAGE);
325 Then the C preprocessor will <emphasis>always</emphasis>
326 use a &hello_h; file from the repository directory first,
327 even if there is a &hello_h; file in the local directory,
328 despite the fact that the command line specifies
329 <literal>-I</literal> as the first option:
336 % <userinput>scons -Q</userinput>
337 cc -o hello.o -c -I. -I/usr/repository1 /usr/repository1/hello.c
343 This behavior of the C preprocessor--always search
344 for a <literal>#include</literal> file in double-quotes
345 first in the same directory as the source file,
346 and only then search the <literal>-I</literal>--can
347 not, in general, be changed.
348 In other words, it's a limitation
349 that must be lived with if you want to use
350 code repositories in this way.
351 There are three ways you can possibly
352 work around this C preprocessor behavior:
361 Some modern versions of C compilers do have an option
362 to disable or control this behavior.
363 If so, add that option to &cv-link-CFLAGS;
364 (or &cv-link-CXXFLAGS; or both) in your construction environment(s).
365 Make sure the option is used for all construction
366 environments that use C preprocessing!
374 Change all occurrences of <literal>#include "file.h"</literal>
375 to <literal>#include <file.h></literal>.
376 Use of <literal>#include</literal> with angle brackets
377 does not have the same behavior--the <literal>-I</literal>
378 directories are searched first
379 for <literal>#include</literal> files--which
380 gives &SCons; direct control over the list of
381 directories the C preprocessor will search.
389 Require that everyone working with compilation from
390 repositories check out and work on entire directories of files,
391 not individual files.
392 (If you use local wrapper scripts around
393 your source code control system's command,
394 you could add logic to enforce this restriction there.
406 <title>Finding the &SConstruct; file in repositories</title>
410 &SCons; will also search in repositories
411 for the &SConstruct; file and any specified &SConscript; files.
412 This poses a problem, though: how can &SCons; search a
413 repository tree for an &SConstruct; file
414 if the &SConstruct; file itself contains the information
415 about the pathname of the repository?
416 To solve this problem, &SCons; allows you
417 to specify repository directories
418 on the command line using the <literal>-Y</literal> option:
423 % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput>
428 When looking for source or derived files,
429 &SCons; will first search the repositories
430 specified on the command line,
431 and then search the repositories
432 specified in the &SConstruct; or &SConscript; files.
439 <title>Finding derived files in repositories</title>
443 If a repository contains not only source files,
444 but also derived files (such as object files,
445 libraries, or executables), &SCons; will perform
446 its normal MD5 signature calculation to
447 decide if a derived file in a repository is up-to-date,
448 or the derived file must be rebuilt in the local build directory.
449 For the &SCons; signature calculation to work correctly,
450 a repository tree must contain the &sconsign; files
451 that &SCons; uses to keep track of signature information.
457 Usually, this would be done by a build integrator
458 who would run &SCons; in the repository
459 to create all of its derived files and &sconsign; files,
460 or who would &SCons; in a separate build directory
461 and copying the resulting tree to the desired repository:
468 % <userinput>cd /usr/repository1</userinput>
469 % <userinput>scons -Q</userinput>
470 cc -o file1.o -c file1.c
471 cc -o file2.o -c file2.c
472 cc -o hello.o -c hello.c
473 cc -o hello hello.o file1.o file2.o
478 (Note that this is safe even if the &SConstruct; file
479 lists <filename>/usr/repository1</filename> as a repository,
480 because &SCons; will remove the current build directory
481 from its repository list for that invocation.)
487 Now, with the repository populated,
488 we only need to create the one local source file
489 we're interested in working with at the moment,
490 and use the <literal>-Y</literal> option to
491 tell &SCons; to fetch any other files it needs
497 <scons_output example="ex4">
498 <scons_output_command>cd $HOME/build</scons_output_command>
499 <scons_output_command>edit hello.c</scons_output_command>
500 <scons_output_command>scons -Q -Y __ROOT__/usr/repository1</scons_output_command>
504 % <userinput>cd $HOME/build</userinput>
505 % <userinput>edit hello.c</userinput>
506 % <userinput>scons -Q -Y /usr/repository1</userinput>
507 cc -c -o hello.o hello.c
508 cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o
513 Notice that &SCons; realizes that it does not need to
514 rebuild local copies file1.o and file2.o files,
515 but instead uses the already-compiled files
523 <title>Guaranteeing local copies of files</title>
527 If the repository tree contains the complete results of a build,
528 and we try to build from the repository
529 without any files in our local tree,
530 something moderately surprising happens:
535 % <userinput>mkdir $HOME/build2</userinput>
536 % <userinput>cd $HOME/build2</userinput>
537 % <userinput>scons -Q -Y /usr/all/repository hello</userinput>
538 scons: `hello' is up-to-date.
543 Why does &SCons; say that the &hello; program
544 is up-to-date when there is no &hello; program
545 in the local build directory?
546 Because the repository (not the local directory)
547 contains the up-to-date &hello; program,
548 and &SCons; correctly determines that nothing
549 needs to be done to rebuild that
550 up-to-date copy of the file.
556 There are, however, many times when you want to ensure that a
557 local copy of a file always exists.
558 A packaging or testing script, for example,
559 may assume that certain generated files exist locally.
560 To tell &SCons; to make a copy of any up-to-date repository
561 file in the local build directory,
562 use the &Local; function:
568 hello = env.Program('hello.c')
574 If we then run the same command,
575 &SCons; will make a local copy of the program
576 from the repository copy,
577 and tell you that it is doing so:
582 % <userinput>scons -Y /usr/all/repository hello</userinput>
583 Local copy of hello from /usr/all/repository/hello
584 scons: `hello' is up-to-date.
589 (Notice that, because the act of making the local copy
590 is not considered a "build" of the &hello; file,
591 &SCons; still reports that it is up-to-date.)