summaryrefslogtreecommitdiffstats
path: root/doc/user/hierarchy.in
diff options
context:
space:
mode:
Diffstat (limited to 'doc/user/hierarchy.in')
-rw-r--r--doc/user/hierarchy.in794
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>
-
- -->