diff options
Diffstat (limited to 'doc/user/hierarchy.in')
-rw-r--r-- | doc/user/hierarchy.in | 794 |
1 files changed, 0 insertions, 794 deletions
diff --git a/doc/user/hierarchy.in b/doc/user/hierarchy.in deleted file mode 100644 index d70633d..0000000 --- a/doc/user/hierarchy.in +++ /dev/null @@ -1,794 +0,0 @@ -<!-- - - __COPYRIGHT__ - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY - KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ---> - -<!-- - - -=head2 The Build command - -By default, Cons does not change its working directory to the directory -containing a subsidiary F<Conscript> file it is including. This behavior -can be enabled for a build by specifying, in the top-level F<Construct> -file: - - Conscript_chdir 1; - -When enabled, Cons will change to the subsidiary F<Conscript> file's -containing directory while reading in that file, and then change back -to the top-level directory once the file has been processed. - -It is expected that this behavior will become the default in some future -version of Cons. To prepare for this transition, builds that expect -Cons to remain at the top of the build while it reads in a subsidiary -F<Conscript> file should explicitly disable this feature as follows: - - Conscript_chdir 0; - -=head2 Relative, top-relative, and absolute file names - -(There is another file prefix, ``!'', that is interpreted specially by -Cons. See discussion of the C<Link> command, below, for details.) - - -=head2 Using modules in build scripts - -You may pull modules into each F<Conscript> file using the normal Perl -C<use> or C<require> statements: - - use English; - require My::Module; - -Each C<use> or C<require> only affects the one F<Conscript> file in which -it appears. To use a module in multiple F<Conscript> files, you must -put a C<use> or C<require> statement in each one that needs the module. - - -=head2 Scope of variables - -The top-level F<Construct> file and all F<Conscript> files begin life in -a common, separate Perl package. B<Cons> controls the symbol table for -the package so that, the symbol table for each script is empty, except -for the F<Construct> file, which gets some of the command line arguments. -All of the variables that are set or used, therefore, are set by the -script itself, not by some external script. - -Variables can be explicitly B<imported> by a script from its parent -script. To import a variable, it must have been B<exported> by the parent -and initialized (otherwise an error will occur). - - -=head2 The Export command - -The C<Export> command is used as in the following example: - - $env = new cons(); - $INCLUDE = "#export/include"; - $LIB = "#export/lib"; - Export qw( env INCLUDE LIB ); - Build qw( util/Conscript ); - -The values of the simple variables mentioned in the C<Export> list will be -squirreled away by any subsequent C<Build> commands. The C<Export> command -will only export Perl B<scalar> variables, that is, variables whose name -begins with C<$>. Other variables, objects, etc. can be exported by -reference, but all scripts will refer to the same object, and this object -should be considered to be read-only by the subsidiary scripts and by the -original exporting script. It's acceptable, however, to assign a new value -to the exported scalar variable, that won't change the underlying variable -referenced. This sequence, for example, is OK: - - $env = new cons(); - Export qw( env INCLUDE LIB ); - Build qw( util/Conscript ); - $env = new cons(CFLAGS => '-O'); - Build qw( other/Conscript ); - -It doesn't matter whether the variable is set before or after the C<Export> -command. The important thing is the value of the variable at the time the -C<Build> command is executed. This is what gets squirreled away. Any -subsequent C<Export> commands, by the way, invalidate the first: you must -mention all the variables you wish to export on each C<Export> command. - - -=head2 The Import command - -Variables exported by the C<Export> command can be imported into subsidiary -scripts by the C<Import> command. The subsidiary script always imports -variables directly from the superior script. Consider this example: - - Import qw( env INCLUDE ); - -This is only legal if the parent script exported both C<$env> and -C<$INCLUDE>. It also must have given each of these variables values. It is -OK for the subsidiary script to only import a subset of the exported -variables (in this example, C<$LIB>, which was exported by the previous -example, is not imported). - -All the imported variables are automatically re-exported, so the sequence: - - Import qw ( env INCLUDE ); - Build qw ( beneath-me/Conscript ); - -will supply both C<$env> and C<$INCLUDE> to the subsidiary file. If only -C<$env> is to be exported, then the following will suffice: - - Import qw ( env INCLUDE ); - Export qw ( env ); - Build qw ( beneath-me/Conscript ); - -Needless to say, the variables may be modified locally before invoking -C<Build> on the subsidiary script. - -=head2 Build script evaluation order - -The only constraint on the ordering of build scripts is that superior -scripts are evaluated before their inferior scripts. The top-level -F<Construct> file, for instance, is evaluated first, followed by any -inferior scripts. This is all you really need to know about the evaluation -order, since order is generally irrelevant. Consider the following C<Build> -command: - - Build qw( - drivers/display/Conscript - drivers/mouse/Conscript - parser/Conscript - utilities/Conscript - ); - -We've chosen to put the script names in alphabetical order, simply because -that's the most convenient for maintenance purposes. Changing the order will -make no difference to the build. - ---> - - <para> - - The source code for large software projects - rarely stays in a single directory, - but is nearly always divided into a - hierarchy of directories. - Organizing a large software build using &SCons; - involves creating a hierarchy of build scripts - using the &SConscript; function. - - </para> - - <section> - <title>&SConscript; Files</title> - - <para> - - As we've already seen, - the build script at the top of the tree is called &SConstruct;. - The top-level &SConstruct; file can - use the &SConscript; function to - include other subsidiary scripts in the build. - These subsidiary scripts can, in turn, - use the &SConscript; function - to include still other scripts in the build. - By convention, these subsidiary scripts are usually - named &SConscript;. - For example, a top-level &SConstruct; file might - arrange for four subsidiary scripts to be included - in the build as follows: - - </para> - - <sconstruct> - SConscript(['drivers/display/SConscript', - 'drivers/mouse/SConscript', - 'parser/SConscript', - 'utilities/SConscript']) - </sconstruct> - - <para> - - In this case, the &SConstruct; file - lists all of the &SConscript; files in the build explicitly. - (Note, however, that not every directory in the tree - necessarily has an &SConscript; file.) - Alternatively, the <literal>drivers</literal> - subdirectory might contain an intermediate - &SConscript; file, - in which case the &SConscript; call in - the top-level &SConstruct; file - would look like: - - </para> - - <sconstruct> - SConscript(['drivers/SConscript', - 'parser/SConscript', - 'utilities/SConscript']) - </sconstruct> - - <para> - - And the subsidiary &SConscript; file in the - <literal>drivers</literal> subdirectory - would look like: - - </para> - - <sconstruct> - SConscript(['display/SConscript', - 'mouse/SConscript']) - </sconstruct> - - <para> - - Whether you list all of the &SConscript; files in the - top-level &SConstruct; file, - or place a subsidiary &SConscript; file in - intervening directories, - or use some mix of the two schemes, - is up to you and the needs of your software. - - </para> - - </section> - - <section> - <title>Path Names Are Relative to the &SConscript; Directory</title> - - <para> - - Subsidiary &SConscript; files make it easy to create a build - hierarchy because all of the file and directory names - in a subsidiary &SConscript; files are interpreted - relative to the directory in which the &SConscript; file lives. - Typically, this allows the &SConscript; file containing the - instructions to build a target file - to live in the same directory as the source files - from which the target will be built, - making it easy to update how the software is built - whenever files are added or deleted - (or other changes are made). - - </para> - - <para> - - For example, suppose we want to build two programs - &prog1; and &prog2; in two separate directories - with the same names as the programs. - One typical way to do this would be - with a top-level &SConstruct; file like this: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - SConscript(['prog1/SConscript', - 'prog2/SConscript']) - </file> - <file name="prog1/SConscript"> - env = Environment() - env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c']) - </file> - <file name="prog2/SConscript"> - env = Environment() - env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c']) - </file> - <directory name="prog1"></directory> - <file name="prog1/main.c"> - x - </file> - <file name="prog1/foo1.c"> - x - </file> - <file name="prog1/foo2.c"> - x - </file> - <directory name="prog2"></directory> - <file name="prog2/main.c"> - x - </file> - <file name="prog2/bar1.c"> - x - </file> - <file name="prog2/bar2.c"> - x - </file> - </scons_example> - - <para> - - And subsidiary &SConscript; files that look like this: - - </para> - - <scons_example_file example="ex1" name="prog1/SConscript"> - </scons_example_file> - - <para> - - And this: - - </para> - - <scons_example_file example="ex1" name="prog2/SConscript"> - </scons_example_file> - - <para> - - Then, when we run &SCons; in the top-level directory, - our build looks like: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - Notice the following: - - First, you can have files with the same names - in multiple directories, like main.c in the above example. - - Second, unlike standard recursive use of &Make;, - &SCons; stays in the top-level directory - (where the &SConstruct; file lives) - and issues commands that use the path names - from the top-level directory to the - target and source files within the hierarchy. - - </para> - - </section> - - <section> - <title>Top-Level Path Names in Subsidiary &SConscript; Files</title> - - <para> - - If you need to use a file from another directory, - it's sometimes more convenient to specify - the path to a file in another directory - from the top-level &SConstruct; directory, - even when you're using that file in - a subsidiary &SConscript; file in a subdirectory. - You can tell &SCons; to interpret a path name - as relative to the top-level &SConstruct; directory, - not the local directory of the &SConscript; file, - by appending a &hash; (hash mark) - to the beginning of the path name: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct"> - SConscript('src/prog/SConscript') - </file> - <file name="src/prog/SConscript" printme="1"> - env = Environment() - env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c']) - </file> - <file name="src/prog/main.c"> - x - </file> - <file name="lib/foo1.c"> - x - </file> - <file name="src/prog/foo2.c"> - x - </file> - </scons_example> - - <para> - - In this example, - the <literal>lib</literal> directory is - directly underneath the top-level &SConstruct; directory. - If the above &SConscript; file is in a subdirectory - named <literal>src/prog</literal>, - the output would look like: - - </para> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - (Notice that the <literal>lib/foo1.o</literal> object file - is built in the same directory as its source file. - See <xref linkend="chap-separate"></xref>, below, - for information about - how to build the object file in a different subdirectory.) - - </para> - - </section> - - <section> - <title>Absolute Path Names</title> - - <para> - - Of course, you can always specify - an absolute path name for a file--for example: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct"> - SConscript('src/prog/SConscript') - </file> - <file name="src/prog/SConscript" printme="1"> - env = Environment() - env.Program('prog', ['main.c', '__ROOT__/usr/joe/lib/foo1.c', 'foo2.c']) - </file> - <file name="src/prog/main.c"> - x - </file> - <file name="__ROOT__/usr/joe/lib/foo1.c"> - x - </file> - <file name="src/prog/foo2.c"> - x - </file> - </scons_example> - - <para> - - Which, when executed, would yield: - - </para> - - <scons_output example="ex3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - (As was the case with top-relative path names, - notice that the <literal>/usr/joe/lib/foo1.o</literal> object file - is built in the same directory as its source file. - See <xref linkend="chap-separate"></xref>, below, - for information about - how to build the object file in a different subdirectory.) - - </para> - - </section> - - <section> - <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title> - - <para> - - In the previous example, - each of the subsidiary &SConscript; files - created its own construction environment - by calling &Environment; separately. - This obviously works fine, - but if each program must be built - with the same construction variables, - it's cumbersome and error-prone to initialize - separate construction environments - in the same way over and over in each subsidiary - &SConscript; file. - - </para> - - <para> - - &SCons; supports the ability to <emphasis>export</emphasis> variables - from a parent &SConscript; file - to its subsidiary &SConscript; files, - which allows you to share common initialized - values throughout your build hierarchy. - - </para> - - <section> - <title>Exporting Variables</title> - - <para> - - There are two ways to export a variable, - such as a construction environment, - from an &SConscript; file, - so that it may be used by other &SConscript; files. - First, you can call the &Export; - function with a list of variables, - or a string of white-space separated variable names. - Each call to &Export; adds one - or more variables to a global list - of variables that are available for import - by other &SConscript; files. - - </para> - - <sconstruct> - env = Environment() - Export('env') - </sconstruct> - - <para> - - You may export more than one variable name at a time: - - </para> - - <sconstruct> - env = Environment() - debug = ARGUMENTS['debug'] - Export('env', 'debug') - </sconstruct> - - <para> - - Because white space is not legal in Python variable names, - the &Export; function will even automatically split - a string into separate names for you: - - </para> - - <sconstruct> - Export('env debug') - </sconstruct> - - <para> - - Second, you can specify a list of - variables to export as a second argument - to the &SConscript; function call: - - </para> - - <sconstruct> - SConscript('src/SConscript', 'env') - </sconstruct> - - <para> - - Or as the &exports; keyword argument: - - </para> - - <sconstruct> - SConscript('src/SConscript', exports='env') - </sconstruct> - - <para> - - These calls export the specified variables - to only the listed &SConscript; files. - You may, however, specify more than one - &SConscript; file in a list: - - </para> - - <sconstruct> - SConscript(['src1/SConscript', - 'src2/SConscript'], exports='env') - </sconstruct> - - <para> - - This is functionally equivalent to - calling the &SConscript; function - multiple times with the same &exports; argument, - one per &SConscript; file. - - </para> - - </section> - - <section> - <title>Importing Variables</title> - - <para> - - Once a variable has been exported from a calling - &SConscript; file, - it may be used in other &SConscript; files - by calling the &Import; function: - - </para> - - <sconstruct> - Import('env') - env.Program('prog', ['prog.c']) - </sconstruct> - - <para> - - The &Import; call makes the <literal>env</literal> construction - environment available to the &SConscript; file, - after which the variable can be used to build - programs, libraries, etc. - - </para> - - <para> - - Like the &Export; function, - the &Import; function can be used - with multiple variable names: - - </para> - - <sconstruct> - Import('env', 'debug') - env = env.Clone(DEBUG = debug) - env.Program('prog', ['prog.c']) - </sconstruct> - - <para> - - And the &Import; function will similarly - split a string along white-space - into separate variable names: - - </para> - - <sconstruct> - Import('env debug') - env = env.Clone(DEBUG = debug) - env.Program('prog', ['prog.c']) - </sconstruct> - - <para> - - Lastly, as a special case, - you may import all of the variables that - have been exported by supplying an asterisk - to the &Import; function: - - </para> - - <sconstruct> - Import('*') - env = env.Clone(DEBUG = debug) - env.Program('prog', ['prog.c']) - </sconstruct> - - <para> - - If you're dealing with a lot of &SConscript; files, - this can be a lot simpler than keeping - arbitrary lists of imported variables in each file. - - </para> - - </section> - - <section> - <title>Returning Values From an &SConscript; File</title> - - <para> - - Sometimes, you would like to be able to - use information from a subsidiary - &SConscript; file in some way. - For example, - suppose that you want to create one - library from source files - scattered throughout a number - of subsidiary &SConscript; files. - You can do this by using the &Return; - function to return values - from the subsidiary &SConscript; files - to the calling file. - - </para> - - <para> - - If, for example, we have two subdirectories - &foo; and &bar; - that should each contribute a source - file to a Library, - what we'd like to be able to do is - collect the object files - from the subsidiary &SConscript; calls - like this: - - </para> - - <scons_example name="Return"> - <file name="SConstruct" printme="1"> - env = Environment() - Export('env') - objs = [] - for subdir in ['foo', 'bar']: - o = SConscript('%s/SConscript' % subdir) - objs.append(o) - env.Library('prog', objs) - </file> - <directory name="foo"></directory> - <directory name="bar"></directory> - <file name="foo/SConscript"> - Import('env') - obj = env.Object('foo.c') - Return('obj') - </file> - <file name="bar/SConscript"> - Import('env') - obj = env.Object('bar.c') - Return('obj') - </file> - <file name="foo/foo.c"> - void foo(void) { printf("foo/foo.c\n"); } - </file> - <file name="bar/bar.c"> - void bar(void) { printf("bar/bar.c\n"); } - </file> - </scons_example> - - <para> - - We can do this by using the &Return; - function in the - <literal>foo/SConscript</literal> file like this: - - </para> - - <scons_example_file example="Return" name="foo/SConscript"> - </scons_example_file> - - <para> - - (The corresponding - <literal>bar/SConscript</literal> - file should be pretty obvious.) - Then when we run &SCons;, - the object files from the subsidiary subdirectories - are all correctly archived in the desired library: - - </para> - - <scons_output example="Return"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <!-- - XXX Return(stop=False) - --> - - </section> - - </section> - - <!-- - - <section> - <title>Executing From a Subdirectory: the -D, -u and -U Options</title> - - <para> - - XXX -D, -u and -U - - </para> - - </section> - - --> |