e39da8f2d7929c49b0749d552f9a7263b76b92c2
[scons.git] / doc / user / hierarchy.sgml
1 <!--
2
3   Copyright (c) 2001, 2002, 2003 Steven Knight
4
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:
12
13   The above copyright notice and this permission notice shall be included
14   in all copies or substantial portions of the Software.
15
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.
23
24 -->
25
26 <!--
27
28 =head2 A hierarchy of build scripts
29
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
34 C<Import> commands.
35
36
37 =head2 The Build command
38
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>
42 file:
43
44   Conscript_chdir 1;
45
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.
49
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:
54
55   Conscript_chdir 0;
56
57 =head2 Relative, top-relative, and absolute file names
58
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
67 paths.
68
69 (There is another file prefix, ``!'', that is interpreted specially by
70 Cons.  See discussion of the C<Link> command, below, for details.)
71
72
73 =head2 Using modules in build scripts
74
75 You may pull modules into each F<Conscript> file using the normal Perl
76 C<use> or C<require> statements:
77
78   use English;
79   require My::Module;
80
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.
84
85
86 =head2 Scope of variables
87
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.
94
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).
98
99
100 =head2 The Export command
101
102 The C<Export> command is used as in the following example:
103
104   $env = new cons();
105   $INCLUDE = "#export/include";
106   $LIB = "#export/lib";
107   Export qw( env INCLUDE LIB );
108   Build qw( util/Conscript );
109
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:
119
120   $env = new cons();
121   Export qw( env INCLUDE LIB );
122   Build qw( util/Conscript );
123   $env = new cons(CFLAGS => '-O');
124   Build qw( other/Conscript );
125
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.
131
132
133 =head2 The Import command
134
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:
138
139   Import qw( env INCLUDE );
140
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).
146
147 All the imported variables are automatically re-exported, so the sequence:
148
149   Import qw ( env INCLUDE );
150   Build qw ( beneath-me/Conscript );
151
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:
154
155   Import qw ( env INCLUDE );
156   Export qw ( env );
157   Build qw ( beneath-me/Conscript );
158
159 Needless to say, the variables may be modified locally before invoking
160 C<Build> on the subsidiary script.
161
162
163 =head2 Build script evaluation order
164
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>
170 command:
171
172   Build qw(
173         drivers/display/Conscript
174         drivers/mouse/Conscript
175         parser/Conscript
176         utilities/Conscript
177   );
178
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.
182
183 -->
184
185   <para>
186
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.
194
195   </para>
196
197   <section>
198   <title>&SConscript; Files</title>
199
200     <para>
201
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
211     named &SConscript;.
212     For example, a top-level &SConstruct; file might
213     arrange for four subsidiary scripts to be included
214     in the build as follows:
215
216     </para>
217
218     <programlisting>
219       SConscript(['drivers/display/SConscript',
220                   'drivers/mouse/SConscript',
221                   'parser/SConscript',
222                   'utilities/SConscript'])
223     </programlisting>
224
225     <para>
226
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
233     &SConscript; file,
234     in which case the &SConscript; call in
235     the top-level &SConstruct; file
236     would look like:
237
238     </para>
239
240     <programlisting>
241       SConscript(['drivers/SConscript',
242                   'parser/SConscript',
243                   'utilities/SConscript'])
244     </programlisting>
245
246     <para>
247
248     And the subsidiary &SConscript; file in the
249     <literal>drivers</literal> subdirectory
250     would look like:
251
252     </para>
253
254     <programlisting>
255       SConscript(['display/SConscript',
256                   'mouse/SConscript'])
257     </programlisting>
258
259     <para>
260
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.
267
268     </para>
269
270   </section>
271
272   <section>
273   <title>Path Names Are Relative to the &SConscript; Directory</title>
274
275     <para>
276
277     XXX
278
279     </para>
280
281     <programlisting>
282       SConscript(['display/SConscript',
283                   'mouse/SConscript'])
284     </programlisting>
285
286   </section>
287
288   <section>
289   <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title>
290
291     <para>
292
293     XXX
294
295     </para>
296
297     <programlisting>
298       SConscript(['display/SConscript',
299                   'mouse/SConscript'])
300     </programlisting>
301
302     <section>
303     <title>Exporting Variables</title>
304
305       <para>
306
307       XXX
308
309       </para>
310
311       <programlisting>
312         SConscript(['display/SConscript',
313                     'mouse/SConscript'])
314       </programlisting>
315
316     </section>
317
318     <section>
319     <title>Importing Variables</title>
320
321       <para>
322
323       XXX
324
325       </para>
326
327       <programlisting>
328         SConscript(['display/SConscript',
329                    'mouse/SConscript'])
330       </programlisting>
331
332     </section>
333
334     <section>
335     <title>Returning Values</title>
336
337       <para>
338
339       XXX
340
341       </para>
342
343       <programlisting>
344         SConscript(['display/SConscript',
345                     'mouse/SConscript'])
346       </programlisting>
347
348     </section>
349
350   </section>