3 Copyright (c) 2001, 2002, 2003 Steven Knight
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 =head2 A hierarchy of build scripts
30 A larger build, in Cons, is organized by creating a hierarchy of B<build
31 scripts>. At the top of the tree is a script called F<Construct>. The rest
32 of the scripts, by convention, are each called F<Conscript>. These scripts
33 are connected together, very simply, by the C<Build>, C<Export>, and
37 =head2 The Build command
39 By default, Cons does not change its working directory to the directory
40 containing a subsidiary F<Conscript> file it is including. This behavior
41 can be enabled for a build by specifying, in the top-level F<Construct>
46 When enabled, Cons will change to the subsidiary F<Conscript> file's
47 containing directory while reading in that file, and then change back
48 to the top-level directory once the file has been processed.
50 It is expected that this behavior will become the default in some future
51 version of Cons. To prepare for this transition, builds that expect
52 Cons to remain at the top of the build while it reads in a subsidiary
53 F<Conscript> file should explicitly disable this feature as follows:
57 =head2 Relative, top-relative, and absolute file names
59 You may have noticed that the file names specified to the Build command are
60 relative to the location of the script it is invoked from. This is generally
61 true for other filename arguments to other commands, too, although we might
62 as well mention here that if you begin a file name with a hash mark, ``#'',
63 then that file is interpreted relative to the top-level directory (where the
64 F<Construct> file resides). And, not surprisingly, if you begin it with ``/'',
65 then it is considered to be an absolute pathname. This is true even on
66 systems which use a back slash rather than a forward slash to name absolute
69 (There is another file prefix, ``!'', that is interpreted specially by
70 Cons. See discussion of the C<Link> command, below, for details.)
73 =head2 Using modules in build scripts
75 You may pull modules into each F<Conscript> file using the normal Perl
76 C<use> or C<require> statements:
81 Each C<use> or C<require> only affects the one F<Conscript> file in which
82 it appears. To use a module in multiple F<Conscript> files, you must
83 put a C<use> or C<require> statement in each one that needs the module.
86 =head2 Scope of variables
88 The top-level F<Construct> file and all F<Conscript> files begin life in
89 a common, separate Perl package. B<Cons> controls the symbol table for
90 the package so that, the symbol table for each script is empty, except
91 for the F<Construct> file, which gets some of the command line arguments.
92 All of the variables that are set or used, therefore, are set by the
93 script itself, not by some external script.
95 Variables can be explicitly B<imported> by a script from its parent
96 script. To import a variable, it must have been B<exported> by the parent
97 and initialized (otherwise an error will occur).
100 =head2 The Export command
102 The C<Export> command is used as in the following example:
105 $INCLUDE = "#export/include";
106 $LIB = "#export/lib";
107 Export qw( env INCLUDE LIB );
108 Build qw( util/Conscript );
110 The values of the simple variables mentioned in the C<Export> list will be
111 squirreled away by any subsequent C<Build> commands. The C<Export> command
112 will only export Perl B<scalar> variables, that is, variables whose name
113 begins with C<$>. Other variables, objects, etc. can be exported by
114 reference, but all scripts will refer to the same object, and this object
115 should be considered to be read-only by the subsidiary scripts and by the
116 original exporting script. It's acceptable, however, to assign a new value
117 to the exported scalar variable, that won't change the underlying variable
118 referenced. This sequence, for example, is OK:
121 Export qw( env INCLUDE LIB );
122 Build qw( util/Conscript );
123 $env = new cons(CFLAGS => '-O');
124 Build qw( other/Conscript );
126 It doesn't matter whether the variable is set before or after the C<Export>
127 command. The important thing is the value of the variable at the time the
128 C<Build> command is executed. This is what gets squirreled away. Any
129 subsequent C<Export> commands, by the way, invalidate the first: you must
130 mention all the variables you wish to export on each C<Export> command.
133 =head2 The Import command
135 Variables exported by the C<Export> command can be imported into subsidiary
136 scripts by the C<Import> command. The subsidiary script always imports
137 variables directly from the superior script. Consider this example:
139 Import qw( env INCLUDE );
141 This is only legal if the parent script exported both C<$env> and
142 C<$INCLUDE>. It also must have given each of these variables values. It is
143 OK for the subsidiary script to only import a subset of the exported
144 variables (in this example, C<$LIB>, which was exported by the previous
145 example, is not imported).
147 All the imported variables are automatically re-exported, so the sequence:
149 Import qw ( env INCLUDE );
150 Build qw ( beneath-me/Conscript );
152 will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only
153 C<$env> is to be exported, then the following will suffice:
155 Import qw ( env INCLUDE );
157 Build qw ( beneath-me/Conscript );
159 Needless to say, the variables may be modified locally before invoking
160 C<Build> on the subsidiary script.
163 =head2 Build script evaluation order
165 The only constraint on the ordering of build scripts is that superior
166 scripts are evaluated before their inferior scripts. The top-level
167 F<Construct> file, for instance, is evaluated first, followed by any
168 inferior scripts. This is all you really need to know about the evaluation
169 order, since order is generally irrelevant. Consider the following C<Build>
173 drivers/display/Conscript
174 drivers/mouse/Conscript
179 We've chosen to put the script names in alphabetical order, simply because
180 that's the most convenient for maintenance purposes. Changing the order will
181 make no difference to the build.
187 The source code for large software projects
188 rarely stays in a single directory,
189 but is nearly always divided into a
190 hierarchy of directories.
191 Organizing a large software build using &SCons;
192 involves creating a hierarchy of build scripts
193 using the &SConscript; function.
198 <title>&SConscript; Files</title>
202 As we've already seen,
203 the build script at the top of the tree is called &SConstruct;.
204 The top-level &SConstruct; file can
205 use the &SConscript; function to
206 include other subsidiary scripts in the build.
207 These subsidiary scripts can, in turn,
208 use the &SConscript; function
209 to include still other scripts in the build.
210 By convention, these subsidiary scripts are usually
212 For example, a top-level &SConstruct; file might
213 arrange for four subsidiary scripts to be included
214 in the build as follows:
219 SConscript(['drivers/display/SConscript',
220 'drivers/mouse/SConscript',
222 'utilities/SConscript'])
227 In this case, the &SConstruct; file
228 lists all of the &SConscript; files in the build explicitly.
229 (Note, however, that not every directory in the tree
230 necessarily has an &SConscript; file.)
231 Alternatively, the <literal>drivers</literal>
232 subdirectory might contain an intermediate
234 in which case the &SConscript; call in
235 the top-level &SConstruct; file
241 SConscript(['drivers/SConscript',
243 'utilities/SConscript'])
248 And the subsidiary &SConscript; file in the
249 <literal>drivers</literal> subdirectory
255 SConscript(['display/SConscript',
261 Whether you list all of the &SConscript; files in the
262 top-level &SConstruct; file,
263 or place a subsidiary &SConscript; file in
264 intervening directories,
265 or use some mix of the two schemes,
266 is up to you and the needs of your software.
273 <title>Path Names Are Relative to the &SConscript; Directory</title>
282 SConscript(['display/SConscript',
289 <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title>
298 SConscript(['display/SConscript',
303 <title>Exporting Variables</title>
312 SConscript(['display/SConscript',
319 <title>Importing Variables</title>
328 SConscript(['display/SConscript',
335 <title>Returning Values</title>
344 SConscript(['display/SConscript',