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.
29 =head2 The Build command
31 By default, Cons does not change its working directory to the directory
32 containing a subsidiary F<Conscript> file it is including. This behavior
33 can be enabled for a build by specifying, in the top-level F<Construct>
38 When enabled, Cons will change to the subsidiary F<Conscript> file's
39 containing directory while reading in that file, and then change back
40 to the top-level directory once the file has been processed.
42 It is expected that this behavior will become the default in some future
43 version of Cons. To prepare for this transition, builds that expect
44 Cons to remain at the top of the build while it reads in a subsidiary
45 F<Conscript> file should explicitly disable this feature as follows:
49 =head2 Relative, top-relative, and absolute file names
51 (There is another file prefix, ``!'', that is interpreted specially by
52 Cons. See discussion of the C<Link> command, below, for details.)
55 =head2 Using modules in build scripts
57 You may pull modules into each F<Conscript> file using the normal Perl
58 C<use> or C<require> statements:
63 Each C<use> or C<require> only affects the one F<Conscript> file in which
64 it appears. To use a module in multiple F<Conscript> files, you must
65 put a C<use> or C<require> statement in each one that needs the module.
68 =head2 Scope of variables
70 The top-level F<Construct> file and all F<Conscript> files begin life in
71 a common, separate Perl package. B<Cons> controls the symbol table for
72 the package so that, the symbol table for each script is empty, except
73 for the F<Construct> file, which gets some of the command line arguments.
74 All of the variables that are set or used, therefore, are set by the
75 script itself, not by some external script.
77 Variables can be explicitly B<imported> by a script from its parent
78 script. To import a variable, it must have been B<exported> by the parent
79 and initialized (otherwise an error will occur).
82 =head2 The Export command
84 The C<Export> command is used as in the following example:
87 $INCLUDE = "#export/include";
89 Export qw( env INCLUDE LIB );
90 Build qw( util/Conscript );
92 The values of the simple variables mentioned in the C<Export> list will be
93 squirreled away by any subsequent C<Build> commands. The C<Export> command
94 will only export Perl B<scalar> variables, that is, variables whose name
95 begins with C<$>. Other variables, objects, etc. can be exported by
96 reference, but all scripts will refer to the same object, and this object
97 should be considered to be read-only by the subsidiary scripts and by the
98 original exporting script. It's acceptable, however, to assign a new value
99 to the exported scalar variable, that won't change the underlying variable
100 referenced. This sequence, for example, is OK:
103 Export qw( env INCLUDE LIB );
104 Build qw( util/Conscript );
105 $env = new cons(CFLAGS => '-O');
106 Build qw( other/Conscript );
108 It doesn't matter whether the variable is set before or after the C<Export>
109 command. The important thing is the value of the variable at the time the
110 C<Build> command is executed. This is what gets squirreled away. Any
111 subsequent C<Export> commands, by the way, invalidate the first: you must
112 mention all the variables you wish to export on each C<Export> command.
115 =head2 The Import command
117 Variables exported by the C<Export> command can be imported into subsidiary
118 scripts by the C<Import> command. The subsidiary script always imports
119 variables directly from the superior script. Consider this example:
121 Import qw( env INCLUDE );
123 This is only legal if the parent script exported both C<$env> and
124 C<$INCLUDE>. It also must have given each of these variables values. It is
125 OK for the subsidiary script to only import a subset of the exported
126 variables (in this example, C<$LIB>, which was exported by the previous
127 example, is not imported).
129 All the imported variables are automatically re-exported, so the sequence:
131 Import qw ( env INCLUDE );
132 Build qw ( beneath-me/Conscript );
134 will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only
135 C<$env> is to be exported, then the following will suffice:
137 Import qw ( env INCLUDE );
139 Build qw ( beneath-me/Conscript );
141 Needless to say, the variables may be modified locally before invoking
142 C<Build> on the subsidiary script.
144 =head2 Build script evaluation order
146 The only constraint on the ordering of build scripts is that superior
147 scripts are evaluated before their inferior scripts. The top-level
148 F<Construct> file, for instance, is evaluated first, followed by any
149 inferior scripts. This is all you really need to know about the evaluation
150 order, since order is generally irrelevant. Consider the following C<Build>
154 drivers/display/Conscript
155 drivers/mouse/Conscript
160 We've chosen to put the script names in alphabetical order, simply because
161 that's the most convenient for maintenance purposes. Changing the order will
162 make no difference to the build.
168 The source code for large software projects
169 rarely stays in a single directory,
170 but is nearly always divided into a
171 hierarchy of directories.
172 Organizing a large software build using &SCons;
173 involves creating a hierarchy of build scripts
174 using the &SConscript; function.
179 <title>&SConscript; Files</title>
183 As we've already seen,
184 the build script at the top of the tree is called &SConstruct;.
185 The top-level &SConstruct; file can
186 use the &SConscript; function to
187 include other subsidiary scripts in the build.
188 These subsidiary scripts can, in turn,
189 use the &SConscript; function
190 to include still other scripts in the build.
191 By convention, these subsidiary scripts are usually
193 For example, a top-level &SConstruct; file might
194 arrange for four subsidiary scripts to be included
195 in the build as follows:
200 SConscript(['drivers/display/SConscript',
201 'drivers/mouse/SConscript',
203 'utilities/SConscript'])
208 In this case, the &SConstruct; file
209 lists all of the &SConscript; files in the build explicitly.
210 (Note, however, that not every directory in the tree
211 necessarily has an &SConscript; file.)
212 Alternatively, the <literal>drivers</literal>
213 subdirectory might contain an intermediate
215 in which case the &SConscript; call in
216 the top-level &SConstruct; file
222 SConscript(['drivers/SConscript',
224 'utilities/SConscript'])
229 And the subsidiary &SConscript; file in the
230 <literal>drivers</literal> subdirectory
236 SConscript(['display/SConscript',
242 Whether you list all of the &SConscript; files in the
243 top-level &SConstruct; file,
244 or place a subsidiary &SConscript; file in
245 intervening directories,
246 or use some mix of the two schemes,
247 is up to you and the needs of your software.
254 <title>Path Names Are Relative to the &SConscript; Directory</title>
258 Subsidiary &SConscript; files make it easy to create a build
259 hierarchy because all of the file and directory names
260 in a subsidiary &SConscript; files are interpreted
261 relative to the directory in which the &SConscript; file lives.
262 Typically, this allows the &SConscript; file containing the
263 instructions to build a target file
264 to live in the same directory as the source files
265 from which the target will be built,
266 making it easy to update how the software is built
267 whenever files are added or deleted
268 (or other changes are made).
274 For example, suppose we want to build two programs
275 &prog1; and &prog2; in two separate directories
276 with the same names as the programs.
277 One typical way to do this would be
278 with a top-level &SConstruct; file like this:
283 SConscript(['prog1/SConscript',
289 And subsidiary &SConscript; files that look like this:
296 env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c'])
308 env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c'])
313 Then, when we run &SCons; in the top-level directory,
314 our build looks like:
319 % <userinput>scons -Q</userinput>
320 cc -o prog1/foo1.o -c prog1/foo1.c
321 cc -o prog1/foo2.o -c prog1/foo2.c
322 cc -o prog1/main.o -c prog1/main.c
323 cc -o prog1/prog1 prog1/main.o prog1/foo1.o prog1/foo2.o
324 cc -o prog2/bar1.o -c prog2/bar1.c
325 cc -o prog2/bar2.o -c prog2/bar2.c
326 cc -o prog2/main.o -c prog2/main.c
327 cc -o prog2/prog2 prog2/main.o prog2/bar1.o prog2/bar2.o
332 Notice the following:
334 First, you can have files with the same names
335 in multiple directories, like main.c in the above example.
337 Second, unlike standard recursive use of &Make;,
338 &SCons; stays in the top-level directory
339 (where the &SConstruct; file lives)
340 and issues commands that use the path names
341 from the top-level directory to the
342 target and source files within the hierarchy.
349 <title>Top-Level Path Names in Subsidiary &SConscript; Files</title>
353 If you need to use a file from another directory,
354 it's sometimes more convenient to specify
355 the path to a file in another directory
356 from the top-level &SConstruct; directory,
357 even when you're using that file in
358 a subsidiary &SConscript; file in a subdirectory.
359 You can tell &SCons; to interpret a path name
360 as relative to the top-level &SConstruct; directory,
361 not the local directory of the &SConscript; file,
362 by appending a &hash; (hash mark)
363 to the beginning of the path name:
369 env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c'])
375 the <literal>lib</literal> directory is
376 directly underneath the top-level &SConstruct; directory.
377 If the above &SConscript; file is in a subdirectory
378 named <literal>src/prog</literal>,
379 the output would look like:
384 % <userinput>scons -Q</userinput>
385 cc -o lib/foo1.o -c lib/foo1.c
386 cc -o src/prog/foo2.o -c src/prog/foo2.c
387 cc -o src/prog/main.o -c src/prog/main.c
388 cc -o src/prog/prog src/prog/main.o lib/foo1.o src/prog/foo2.o
393 (Notice that the <literal>lib/foo1.o</literal> object file
394 is built in the same directory as its source file.
395 See <xref linkend="chap-separate"></xref>, below,
396 for information about
397 how to build the object file in a different subdirectory.)
404 <title>Absolute Path Names</title>
408 Of course, you can always specify
409 an absolute path name for a file--for example:
415 env.Program('prog', ['main.c', '/usr/joe/lib/foo1.c', 'foo2.c'])
420 Which, when executed, would yield:
425 % <userinput>scons -Q</userinput>
426 cc -o src/prog/foo2.o -c src/prog/foo2.c
427 cc -o src/prog/main.o -c src/prog/main.c
428 cc -o /usr/joe/lib/foo1.o -c /usr/joe/lib/foo1.c
429 cc -o src/prog/prog src/prog/main.o /usr/joe/lib/foo1.o src/prog/foo2.o
434 (As was the case with top-relative path names,
435 notice that the <literal>/usr/joe/lib/foo1.o</literal> object file
436 is built in the same directory as its source file.
437 See <xref linkend="chap-separate"></xref>, below,
438 for information about
439 how to build the object file in a different subdirectory.)
446 <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title>
450 In the previous example,
451 each of the subsidiary &SConscript; files
452 created its own construction environment
453 by calling &Environment; separately.
454 This obviously works fine,
455 but if each program must be built
456 with the same construction variables,
457 it's cumbersome and error-prone to initialize
458 separate construction environments
459 in the same way over and over in each subsidiary
466 &SCons; supports the ability to <emphasis>export</emphasis> variables
467 from a parent &SConscript; file
468 to its subsidiary &SConscript; files,
469 which allows you to share common initialized
470 values throughout your build hierarchy.
475 <title>Exporting Variables</title>
479 There are two ways to export a variable,
480 such as a construction environment,
481 from an &SConscript; file,
482 so that it may be used by other &SConscript; files.
483 First, you can call the &Export;
484 function with a list of variables,
485 or a string white-space separated variable names.
486 Each call to &Export; adds one
487 or more variables to a global list
488 of variables that are available for import
489 by other &SConscript; files.
500 You may export more than one variable name at a time:
506 debug = ARGUMENTS['debug']
507 Export('env', 'debug')
512 Because white space is not legal in Python variable names,
513 the &Export; function will even automatically split
514 a string into separate names for you:
524 Second, you can specify a list of
525 variables to export as a second argument
526 to the &SConscript; function call:
531 SConscript('src/SConscript', 'env')
536 Or as the &exports; keyword argument:
541 SConscript('src/SConscript', exports='env')
546 These calls export the specified variables
547 to only the listed &SConscript; files.
548 You may, however, specify more than one
549 &SConscript; file in a list:
554 SConscript(['src1/SConscript',
555 'src2/SConscript'], exports='env')
560 This is functionally equivalent to
561 calling the &SConscript; function
562 multiple times with the same &exports; argument,
563 one per &SConscript; file.
570 <title>Importing Variables</title>
574 Once a variable has been exported from a calling
576 it may be used in other &SConscript; files
577 by calling the &Import; function:
583 env.Program('prog', ['prog.c'])
588 The &Import; call makes the <literal>env</literal> construction
589 environment available to the &SConscript; file,
590 after which the variable can be used to build
591 programs, libraries, etc.
597 Like the &Export; function,
598 the &Import; function can be used
599 with multiple variable names:
604 Import('env', 'debug')
605 env = env.Clone(DEBUG = debug)
606 env.Program('prog', ['prog.c'])
611 And the &Import; function will similarly
612 split a string along white-space
613 into separate variable names:
619 env = env.Clone(DEBUG = debug)
620 env.Program('prog', ['prog.c'])
625 Lastly, as a special case,
626 you may import all of the variables that
627 have been exported by supplying an asterisk
628 to the &Import; function:
634 env = env.Clone(DEBUG = debug)
635 env.Program('prog', ['prog.c'])
640 If you're dealing with a lot of &SConscript; files,
641 this can be a lot simpler than keeping
642 arbitrary lists of imported variables in each file.
649 <title>Returning Values From an &SConscript; File</title>
653 Sometimes, you would like to be able to
654 use information from a subsidiary
655 &SConscript; file in some way.
657 suppose that you want to create one
658 library from source files
659 scattered throughout a number
660 of subsidiary &SConscript; files.
661 You can do this by using the &Return;
662 function to return values
663 from the subsidiary &SConscript; files
670 If, for example, we have two subdirectories
672 that should each contribute a source
674 what we'd like to be able to do is
675 collect the object files
676 from the subsidiary &SConscript; calls
685 for subdir in ['foo', 'bar']:
686 o = SConscript('%s/SConscript' % subdir)
688 env.Library('prog', objs)
693 We can do this by using the &Return;
695 <literal>foo/SConscript</literal> file like this:
702 obj = env.Object('foo.c')
709 <literal>bar/SConscript</literal>
710 file should be pretty obvious.)
711 Then when we run &SCons;,
712 the object files from the subsidiary subdirectories
713 are all correctly archived in the desired library:
718 % <userinput>scons -Q</userinput>
719 cc -o bar/bar.o -c bar/bar.c
720 cc -o foo/foo.o -c foo/foo.c
721 ar rc libprog.a foo/foo.o bar/bar.o
732 <title>Executing From a Subdirectory: the -D, -u and -U Options</title>