summaryrefslogtreecommitdiff
path: root/doc/user/environments.in
diff options
context:
space:
mode:
Diffstat (limited to 'doc/user/environments.in')
-rw-r--r--doc/user/environments.in1752
1 files changed, 0 insertions, 1752 deletions
diff --git a/doc/user/environments.in b/doc/user/environments.in
deleted file mode 100644
index eebc486..0000000
--- a/doc/user/environments.in
+++ /dev/null
@@ -1,1752 +0,0 @@
-<!--
-
- Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 The SCons Foundation
-
- 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.
-
--->
-
-<!--
-
-=head1 More on construction environments
-
-As previously mentioned, a B<construction environment> is an object that
-has a set of keyword/value pairs and a set of methods, and which is used
-to tell Cons how target files should be built. This section describes
-how Cons uses and expands construction environment values to control its
-build behavior.
-
-=head2 Construction variable expansion
-
-Construction variables from a construction environment are expanded
-by preceding the keyword with a C<%> (percent sign):
-
- Construction variables:
- XYZZY => 'abracadabra',
-
- The string: "The magic word is: %XYZZY!"
- expands to: "The magic word is: abracadabra!"
-
-A construction variable name may be surrounded by C<{> and C<}> (curly
-braces), which are stripped as part of the expansion. This can
-sometimes be necessary to separate a variable expansion from trailing
-alphanumeric characters:
-
- Construction variables:
- OPT => 'value1',
- OPTION => 'value2',
-
- The string: "%OPT %{OPT}ION %OPTION %{OPTION}"
- expands to: "value1 value1ION value2 value2"
-
-Construction variable expansion is recursive, that is, a string
-containing C<%->expansions after substitution will be re-expanded until
-no further substitutions can be made:
-
- Construction variables:
- STRING => 'The result is: %FOO',
- FOO => '%BAR',
- BAR => 'final value',
-
- The string: "The string says: %STRING"
- expands to: "The string says: The result is: final value"
-
-If a construction variable is not defined in an environment, then the
-null string is substituted:
-
- Construction variables:
- FOO => 'value1',
- BAR => 'value2',
-
- The string: "%FOO <%NO_VARIABLE> %BAR"
- expands to: "value1 <> value2"
-
-A doubled C<%%> will be replaced by a single C<%>:
-
- The string: "Here is a percent sign: %%"
- expands to: "Here is a percent sign: %"
-
-=head2 Default construction variables
-
-When you specify no arguments when creating a new construction
-environment:
-
- $env = new cons();
-
-Cons creates a reference to a new, default construction
-environment. This contains a number of construction variables and some
-methods. At the present writing, the default construction variables on a
-UNIX system are:
-
- CC => 'cc',
- CFLAGS => '',
- CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
- CXX => '%CC',
- CXXFLAGS => '%CFLAGS',
- CXXCOM => '%CXX %CXXFLAGS %_IFLAGS -c %< -o %>',
- INCDIRPREFIX => '-I',
- INCDIRSUFFIX => '',
- LINK => '%CXX',
- LINKCOM => '%LINK %LDFLAGS -o %> %< %_LDIRS %LIBS',
- LINKMODULECOM => '%LD -r -o %> %<',
- LIBDIRPREFIX => '-L',
- LIBDIRSUFFIX => '',
- AR => 'ar',
- ARFLAGS => 'r',
- ARCOM => ['%AR %ARFLAGS %> %<', '%RANLIB %>'],
- RANLIB => 'ranlib',
- AS => 'as',
- ASFLAGS => '',
- ASCOM => '%AS %ASFLAGS %< -o %>',
- LD => 'ld',
- LDFLAGS => '',
- PREFLIB => 'lib',
- SUFLIB => '.a',
- SUFLIBS => '.so:.a',
- SUFOBJ => '.o',
- SIGNATURE => [ '*' => 'build' ],
- ENV => { 'PATH' => '/bin:/usr/bin' },
-
-
-And on a Windows system (Windows NT), the default construction variables
-are (unless the default rule style is set using the B<DefaultRules>
-method):
-
- CC => 'cl',
- CFLAGS => '/nologo',
- CCCOM => '%CC %CFLAGS %_IFLAGS /c %< /Fo%>',
- CXXCOM => '%CXX %CXXFLAGS %_IFLAGS /c %< /Fo%>',
- INCDIRPREFIX => '/I',
- INCDIRSUFFIX => '',
- LINK => 'link',
- LINKCOM => '%LINK %LDFLAGS /out:%> %< %_LDIRS %LIBS',
- LINKMODULECOM => '%LD /r /o %> %<',
- LIBDIRPREFIX => '/LIBPATH:',
- LIBDIRSUFFIX => '',
- AR => 'lib',
- ARFLAGS => '/nologo ',
- ARCOM => "%AR %ARFLAGS /out:%> %<",
- RANLIB => '',
- LD => 'link',
- LDFLAGS => '/nologo ',
- PREFLIB => '',
- SUFEXE => '.exe',
- SUFLIB => '.lib',
- SUFLIBS => '.dll:.lib',
- SUFOBJ => '.obj',
- SIGNATURE => [ '*' => 'build' ],
-
-These variables are used by the various methods associated with the
-environment. In particular, any method that ultimately invokes an external
-command will substitute these variables into the final command, as
-appropriate. For example, the C<Objects> method takes a number of source
-files and arranges to derive, if necessary, the corresponding object
-files:
-
- Objects $env 'foo.c', 'bar.c';
-
-This will arrange to produce, if necessary, F<foo.o> and F<bar.o>. The
-command invoked is simply C<%CCCOM>, which expands, through substitution,
-to the appropriate external command required to build each object. The
-substitution rules will be discussed in detail in the next section.
-
-The construction variables are also used for other purposes. For example,
-C<CPPPATH> is used to specify a colon-separated path of include
-directories. These are intended to be passed to the C preprocessor and are
-also used by the C-file scanning machinery to determine the dependencies
-involved in a C Compilation.
-
-Variables beginning with underscore are created by various methods,
-and should normally be considered ``internal'' variables. For example,
-when a method is called which calls for the creation of an object from
-a C source, the variable C<_IFLAGS> is created: this corresponds to the
-C<-I> switches required by the C compiler to represent the directories
-specified by C<CPPPATH>.
-
-Note that, for any particular environment, the value of a variable is set
-once, and then never reset (to change a variable, you must create a new
-environment. Methods are provided for copying existing environments for this
-purpose). Some internal variables, such as C<_IFLAGS> are created on demand,
-but once set, they remain fixed for the life of the environment.
-
-The C<CFLAGS>, C<LDFLAGS>, and C<ARFLAGS> variables all supply a place
-for passing options to the compiler, loader, and archiver, respectively.
-
-The C<INCDIRPREFIX> and C<INCDIRSUFFIX> variables specify option
-strings to be appended to the beginning and end, respectively, of each
-include directory so that the compiler knows where to find F<.h> files.
-Similarly, the C<LIBDIRPREFIX> and C<LIBDIRSUFFIX> variables specify the
-option string to be appended to the beginning of and end, respectively,
-of each directory that the linker should search for libraries.
-
-Another variable, C<ENV>, is used to determine the system environment during
-the execution of an external command. By default, the only environment
-variable that is set is C<PATH>, which is the execution path for a UNIX
-command. For the utmost reproducibility, you should really arrange to set
-your own execution path, in your top-level F<Construct> file (or perhaps by
-importing an appropriate construction package with the Perl C<use>
-command). The default variables are intended to get you off the ground.
-
-=head2 Expanding variables in construction commands
-
-Within a construction command, construction variables will be expanded
-according to the rules described above. In addition to normal variable
-expansion from the construction environment, construction commands also
-expand the following pseudo-variables to insert the specific input and
-output files in the command line that will be executed:
-
-=over 10
-
-=item %>
-
-The target file name. In a multi-target command, this expands to the
-first target mentioned.)
-
-=item %0
-
-Same as C<%E<gt>>.
-
-=item %1, %2, ..., %9
-
-These refer to the first through ninth input file, respectively.
-
-=item %E<lt>
-
-The full set of input file names. If any of these have been used
-anywhere else in the current command line (via C<%1>, C<%2>, etc.), then
-those will be deleted from the list provided by C<%E<lt>>. Consider the
-following command found in a F<Conscript> file in the F<test> directory:
-
- Command $env 'tgt', qw(foo bar baz), qq(
- echo %< -i %1 > %>
- echo %< -i %2 >> %>
- echo %< -i %3 >> %>
- );
-
-If F<tgt> needed to be updated, then this would result in the execution of
-the following commands, assuming that no remapping has been established for
-the F<test> directory:
-
- echo test/bar test/baz -i test/foo > test/tgt
- echo test/foo test/baz -i test/bar >> test/tgt
- echo test/foo test/bar -i test/baz >> test/tgt
-
-=back
-
-Any of the above pseudo-variables may be followed immediately by one of
-the following suffixes to select a portion of the expanded path name:
-
- :a the absolute path to the file name
- :b the directory plus the file name stripped of any suffix
- :d the directory
- :f the file name
- :s the file name suffix
- :F the file name stripped of any suffix
- :S the absolute path path to a Linked source file
-
-Continuing with the above example, C<%E<lt>:f> would expand to C<foo bar baz>,
-and C<%E<gt>:d> would expand to C<test>.
-
-There are additional C<%> elements which affect the command line(s):
-
-=over 10
-
-=item %[ %]
-
-It is possible to programmatically rewrite part of the command by
-enclosing part of it between C<%[> and C<%]>. This will call the
-construction variable named as the first word enclosed in the brackets
-as a Perl code reference; the results of this call will be used to
-replace the contents of the brackets in the command line. For example,
-given an existing input file named F<tgt.in>:
-
- @keywords = qw(foo bar baz);
- $env = new cons(X_COMMA => sub { join(",", @_) });
- Command $env 'tgt', 'tgt.in', qq(
- echo '# Keywords: %[X_COMMA @keywords %]' > %>
- cat %< >> %>
- );
-
-This will execute:
-
- echo '# Keywords: foo,bar,baz' > tgt
- cat tgt.in >> tgt
-
-=item %( %)
-
-Cons includes the text of the command line in the MD5 signature for a
-build, so that targets get rebuilt if you change the command line (to
-add or remove an option, for example). Command-line text in between
-C<%(> and C<%)>, however, will be ignored for MD5 signature calculation.
-
-Internally, Cons uses C<%(> and C<%)> around include and library
-directory options (C<-I> and C<-L> on UNIX systems, C</I> and
-C</LIBPATH> on Windows NT) to avoid rebuilds just because the directory
-list changes. Rebuilds occur only if the changed directory list causes
-any included I<files> to change, and a changed include file is detected
-by the MD5 signature calculation on the actual file contents.
-
-=back
-
-XXX DESCRIBE THE Literal() FUNCTION, TOO XXX
-
-=head2 Expanding construction variables in file names
-
-Cons expands construction variables in the source and target file names
-passed to the various construction methods according to the expansion
-rules described above:
-
- $env = new cons(
- DESTDIR => 'programs',
- SRCDIR => 'src',
- );
- Program $env '%DESTDIR/hello', '%SRCDIR/hello.c';
-
-This allows for flexible configuration, through the construction
-environment, of directory names, suffixes, etc.
-
--->
-
- <para>
-
- An <literal>environment</literal>
- is a collection of values that
- can affect how a program executes.
- &SCons; distinguishes between three
- different types of environments
- that can affect the behavior of &SCons; itself
- (subject to the configuration in the &SConscript; files),
- as well as the compilers and other tools it executes:
-
- </para>
-
- <variablelist>
-
- <varlistentry>
- <term>External Environment</term>
-
- <listitem>
- <para>
-
- The <literal>external environment</literal>
- is the set of variables in the user's environment
- at the time the user runs &SCons;.
- These variables are available within the &SConscript; files
- through the Python <literal>os.environ</literal> dictionary.
- See <xref linkend="sect-external-environments"></xref>, below.
-
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>&ConsEnv;</term>
-
- <listitem>
- <para>
-
- A &consenv;
- is a distinct object creating within
- a &SConscript; file and
- and which contains values that
- affect how &SCons; decides
- what action to use to build a target,
- and even to define which targets
- should be built from which sources.
- One of the most powerful features of &SCons;
- is the ability to create multiple &consenvs;,
- including the ability to clone a new, customized
- &consenv; from an existing &consenv;.
- See <xref linkend="sect-construction-environments"></xref>, below.
-
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>Execution Environment</term>
-
- <listitem>
- <para>
-
- An <literal>execution environment</literal>
- is the values that &SCons; sets
- when executing an external
- command (such as a compiler or linker)
- to build one or more targets.
- Note that this is not the same as
- the <literal>external environment</literal>
- (see above).
- See <xref linkend="sect-execution-environments"></xref>, below.
-
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- <para>
-
- Unlike &Make;, &SCons; does not automatically
- copy or import values between different environments
- (with the exception of explicit clones of &consenvs;,
- which inherit values from their parent).
- This is a deliberate design choice
- to make sure that builds are,
- by default, repeatable regardless of
- the values in the user's external environment.
- This avoids a whole class of problems with builds
- where a developer's local build works
- because a custom variable setting
- causes a different compiler or build option to be used,
- but the checked-in change breaks the official build
- because it uses different environment variable settings.
-
- </para>
-
- <para>
-
- Note that the &SConscript; writer can
- easily arrange for variables to be
- copied or imported between environments,
- and this is often very useful
- (or even downright necessary)
- to make it easy for developers
- to customize the build in appropriate ways.
- The point is <emphasis>not</emphasis>
- that copying variables between different environments
- is evil and must always be avoided.
- Instead, it should be up to the
- implementer of the build system
- to make conscious choices
- about how and when to import
- a variable from one environment to another,
- making informed decisions about
- striking the right balance
- between making the build
- repeatable on the one hand
- and convenient to use on the other.
-
- </para>
-
- <section id="sect-external-environments">
- <title>Using Values From the External Environment</title>
-
- <para>
-
- The <literal>external environment</literal>
- variable settings that
- the user has in force
- when executing &SCons;
- are available through the normal Python
- <envar>os.environ</envar>
- dictionary.
- This means that you must add an
- <literal>import os</literal> statement
- to any &SConscript; file
- in which you want to use
- values from the user's external environment.
-
- </para>
-
- <scons_example name="ex1">
- <file name="SConstruct" printme="1">
- import os
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- </scons_example>
-
- <para>
-
- More usefully, you can use the
- <envar>os.environ</envar>
- dictionary in your &SConscript;
- files to initialize &consenvs;
- with values from the user's external environment.
- See the next section,
- <xref linkend="sect-construction-environments"></xref>,
- for information on how to do this.
-
- </para>
-
- </section>
-
- <section id="sect-construction-environments">
- <title>Construction Environments</title>
-
- <para>
-
- It is rare that all of the software in a large,
- complicated system needs to be built the same way.
- For example, different source files may need different options
- enabled on the command line,
- or different executable programs need to be linked
- with different libraries.
- &SCons; accommodates these different build
- requirements by allowing you to create and
- configure multiple &consenvs;
- that control how the software is built.
- A &consenv; is an object
- that has a number of associated
- &consvars;, each with a name and a value.
- (A construction environment also has an attached
- set of &Builder; methods,
- about which we'll learn more later.)
-
- </para>
-
- <section>
- <title>Creating a &ConsEnv;: the &Environment; Function</title>
-
- <para>
-
- A &consenv; is created by the &Environment; method:
-
- </para>
-
- <sconstruct>
- env = Environment()
- </sconstruct>
-
- <para>
-
- By default, &SCons; initializes every
- new construction environment
- with a set of &consvars;
- based on the tools that it finds on your system,
- plus the default set of builder methods
- necessary for using those tools.
- The construction variables
- are initialized with values describing
- the C compiler,
- the Fortran compiler,
- the linker,
- etc.,
- as well as the command lines to invoke them.
-
- </para>
-
- <para>
-
- When you initialize a construction environment
- you can set the values of the
- environment's &consvars;
- to control how a program is built.
- For example:
-
- </para>
-
- <scons_example name="ex1">
- <file name="SConstruct" printme="1">
- env = Environment(CC = 'gcc',
- CCFLAGS = '-O2')
-
- env.Program('foo.c')
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- </scons_example>
-
- <para>
-
- The construction environment in this example
- is still initialized with the same default
- construction variable values,
- except that the user has explicitly specified use of the
- GNU C compiler &gcc;,
- and further specifies that the <literal>-O2</literal>
- (optimization level two)
- flag should be used when compiling the object file.
- In other words, the explicit initializations of
- &cv-link-CC; and &cv-link-CCFLAGS;
- override the default values in the newly-created
- construction environment.
- So a run from this example would look like:
-
- </para>
-
- <scons_output example="ex1">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- </section>
-
- <section>
- <title>Fetching Values From a &ConsEnv;</title>
-
- <para>
-
- You can fetch individual construction variables
- using the normal syntax
- for accessing individual named items in a Python dictionary:
-
- </para>
-
- <scons_example name="ex6">
- <file name="SConstruct" printme="1">
- env = Environment()
- print "CC is:", env['CC']
- </file>
- </scons_example>
-
- <para>
-
- This example &SConstruct; file doesn't build anything,
- but because it's actually a Python script,
- it will print the value of &cv-link-CC; for us:
-
- </para>
-
- <scons_output example="ex6">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- A construction environment, however,
- is actually an object with associated methods, etc.
- If you want to have direct access to only the
- dictionary of construction variables,
- you can fetch this using the &Dictionary; method:
-
- </para>
-
- <scons_example name="ex6b">
- <file name="SConstruct" printme="1">
- env = Environment(FOO = 'foo', BAR = 'bar')
- dict = env.Dictionary()
- for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
- print "key = %s, value = %s" % (key, dict[key])
- </file>
- </scons_example>
-
- <para>
-
- This &SConstruct; file
- will print the specified dictionary items for us on POSIX
- systems as follows:
-
- </para>
-
- <scons_output example="ex6b" os="posix">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- And on Windows:
-
- </para>
-
- <scons_output example="ex6b" os="win32">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- If you want to loop and print the values of
- all of the construction variables in a construction environment,
- the Python code to do that in sorted order might look something like:
-
- </para>
-
- <sconstruct>
- env = Environment()
- for item in sorted(env.Dictionary().items()):
- print "construction variable = '%s', value = '%s'" % item
- </sconstruct>
-
- </section>
-
- <section>
- <title>Expanding Values From a &ConsEnv;: the &subst; Method</title>
-
- <para>
-
- Another way to get information from
- a construction environment
- is to use the &subst; method
- on a string containing <literal>$</literal> expansions
- of construction variable names.
- As a simple example,
- the example from the previous
- section that used
- <literal>env['CC']</literal>
- to fetch the value of &cv-link-CC;
- could also be written as:
-
- </para>
-
- <sconstruct>
- env = Environment()
- print "CC is:", env.subst('$CC')
- </sconstruct>
-
- <para>
-
- One advantage of using
- &subst; to expand strings is
- that construction variables
- in the result get re-expanded until
- there are no expansions left in the string.
- So a simple fetch of a value like
- &cv-link-CCCOM;:
-
- </para>
-
- <sconstruct>
- env = Environment(CCFLAGS = '-DFOO')
- print "CCCOM is:", env['CCCOM']
- </sconstruct>
-
- <para>
-
- Will print the unexpanded value of &cv-CCCOM;,
- showing us the construction
- variables that still need to be expanded:
-
- </para>
-
- <screen>
- % <userinput>scons -Q</userinput>
- CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES
- scons: `.' is up to date.
- </screen>
-
- <para>
-
- Calling the &subst; method on <varname>$CCOM</varname>,
- however:
-
- </para>
-
- <sconstruct>
- env = Environment(CCFLAGS = '-DFOO')
- print "CCCOM is:", env.subst('$CCCOM')
- </sconstruct>
-
- <para>
-
- Will recursively expand all of
- the construction variables prefixed
- with <literal>$</literal> (dollar signs),
- showing us the final output:
-
- </para>
-
- <screen>
- % <userinput>scons -Q</userinput>
- CCCOM is: gcc -DFOO -c -o
- scons: `.' is up to date.
- </screen>
-
- <para>
-
- Note that because we're not expanding this
- in the context of building something
- there are no target or source files
- for &cv-link-TARGET; and &cv-link-SOURCES; to expand.
-
- </para>
-
- </section>
-
- <section>
- <title>Handling Problems With Value Expansion</title>
-
- <para>
-
- If a problem occurs when expanding a construction variable,
- by default it is expanded to <literal>''</literal>
- (a null string), and will not cause scons to fail.
- </para>
-
- <scons_example name="missing1">
- <file name="SConstruct" printme="1">
- env = Environment()
- print "value is:", env.subst( '->$MISSING&lt;-' )
- </file>
- </scons_example>
-
- <scons_output example="missing1">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
- This default behaviour can be changed using the &AllowSubstExceptions;
- function.
- When a problem occurs with a variable expansion it generates
- an exception, and the &AllowSubstExceptions; function controls
- which of these exceptions are actually fatal and which are
- allowed to occur safely. By default, &NameError; and &IndexError;
- are the two exceptions that are allowed to occur: so instead of
- causing scons to fail, these are caught, the variable expanded to
- <literal>''</literal>
- and scons execution continues.
- To require that all construction variable names exist, and that
- indexes out of range are not allowed, call &AllowSubstExceptions;
- with no extra arguments.
- </para>
-
- <scons_example name="missing2">
- <file name="SConstruct" printme="1">
- AllowSubstExceptions()
- env = Environment()
- print "value is:", env.subst( '->$MISSING&lt;-' )
- </file>
- </scons_example>
-
- <scons_output example="missing2">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
- This can also be used to allow other exceptions that might occur,
- most usefully with the <literal>${...}</literal> construction
- variable syntax. For example, this would allow zero-division to
- occur in a variable expansion in addition to the default exceptions
- allowed
- </para>
-
- <scons_example name="missing3">
- <file name="SConstruct" printme="1">
- AllowSubstExceptions(IndexError, NameError, ZeroDivisionError)
- env = Environment()
- print "value is:", env.subst( '->${1 / 0}&lt;-' )
- </file>
- </scons_example>
-
- <scons_output example="missing3">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
- <sconstruct>
- </sconstruct>
-
- <para>
- If &AllowSubstExceptions; is called multiple times, each call
- completely overwrites the previous list of allowed exceptions.
- </para>
-
- </section>
-
- <section>
- <title>Controlling the Default &ConsEnv;: the &DefaultEnvironment; Function</title>
-
- <para>
-
- All of the &Builder; functions that we've introduced so far,
- like &Program; and &Library;,
- actually use a default &consenv;
- that contains settings
- for the various compilers
- and other tools that
- &SCons; configures by default,
- or otherwise knows about
- and has discovered on your system.
- The goal of the default construction environment
- is to make many configurations to "just work"
- to build software using
- readily available tools
- with a minimum of configuration changes.
-
- </para>
-
- <para>
-
- You can, however, control the settings
- in the default construction environment
- by using the &DefaultEnvironment; function
- to initialize various settings:
-
- </para>
-
- <sconstruct>
-
- DefaultEnvironment(CC = '/usr/local/bin/gcc')
-
- </sconstruct>
-
- <para>
-
- When configured as above,
- all calls to the &Program;
- or &Object; Builder
- will build object files with the
- <filename>/usr/local/bin/gcc</filename>
- compiler.
-
- </para>
-
- <para>
-
- Note that the &DefaultEnvironment; function
- returns the initialized
- default construction environment object,
- which can then be manipulated like any
- other construction environment.
- So the following
- would be equivalent to the
- previous example,
- setting the &cv-CC;
- variable to <filename>/usr/local/bin/gcc</filename>
- but as a separate step after
- the default construction environment has been initialized:
-
- </para>
-
- <sconstruct>
-
- env = DefaultEnvironment()
- env['CC'] = '/usr/local/bin/gcc'
-
- </sconstruct>
-
- <para>
-
- One very common use of the &DefaultEnvironment; function
- is to speed up &SCons; initialization.
- As part of trying to make most default
- configurations "just work,"
- &SCons; will actually
- search the local system for installed
- compilers and other utilities.
- This search can take time,
- especially on systems with
- slow or networked file systems.
- If you know which compiler(s) and/or
- other utilities you want to configure,
- you can control the search
- that &SCons; performs
- by specifying some specific
- tool modules with which to
- initialize the default construction environment:
-
- </para>
-
- <sconstruct>
-
- env = DefaultEnvironment(tools = ['gcc', 'gnulink'],
- CC = '/usr/local/bin/gcc')
-
- </sconstruct>
-
- <para>
-
- So the above example would tell &SCons;
- to explicitly configure the default environment
- to use its normal GNU Compiler and GNU Linker settings
- (without having to search for them,
- or any other utilities for that matter),
- and specifically to use the compiler found at
- <filename>/usr/local/bin/gcc</filename>.
-
- </para>
-
- </section>
-
- <section>
- <title>Multiple &ConsEnvs;</title>
-
- <para>
-
- The real advantage of construction environments
- is that you can create as many different construction
- environments as you need,
- each tailored to a different way to build
- some piece of software or other file.
- If, for example, we need to build
- one program with the <literal>-O2</literal> flag
- and another with the <literal>-g</literal> (debug) flag,
- we would do this like so:
-
- </para>
-
- <scons_example name="ex2">
- <file name="SConstruct" printme="1">
- opt = Environment(CCFLAGS = '-O2')
- dbg = Environment(CCFLAGS = '-g')
-
- opt.Program('foo', 'foo.c')
-
- dbg.Program('bar', 'bar.c')
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- <file name="bar.c">
- int main() { }
- </file>
- </scons_example>
-
- <scons_output example="ex2">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- We can even use multiple construction environments to build
- multiple versions of a single program.
- If you do this by simply trying to use the
- &b-link-Program; builder with both environments, though,
- like this:
-
- </para>
-
- <scons_example name="ex3">
- <file name="SConstruct" printme="1">
- opt = Environment(CCFLAGS = '-O2')
- dbg = Environment(CCFLAGS = '-g')
-
- opt.Program('foo', 'foo.c')
-
- dbg.Program('foo', 'foo.c')
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- </scons_example>
-
- <para>
-
- Then &SCons; generates the following error:
-
- </para>
-
- <scons_output example="ex3">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- This is because the two &b-Program; calls have
- each implicitly told &SCons; to generate an object file named
- <filename>foo.o</filename>,
- one with a &cv-link-CCFLAGS; value of
- <literal>-O2</literal>
- and one with a &cv-link-CCFLAGS; value of
- <literal>-g</literal>.
- &SCons; can't just decide that one of them
- should take precedence over the other,
- so it generates the error.
- To avoid this problem,
- we must explicitly specify
- that each environment compile
- <filename>foo.c</filename>
- to a separately-named object file
- using the &b-link-Object; builder, like so:
-
- </para>
-
- <scons_example name="ex4">
- <file name="SConstruct" printme="1">
- opt = Environment(CCFLAGS = '-O2')
- dbg = Environment(CCFLAGS = '-g')
-
- o = opt.Object('foo-opt', 'foo.c')
- opt.Program(o)
-
- d = dbg.Object('foo-dbg', 'foo.c')
- dbg.Program(d)
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- </scons_example>
-
- <para>
-
- Notice that each call to the &b-Object; builder
- returns a value,
- an internal &SCons; object that
- represents the object file that will be built.
- We then use that object
- as input to the &b-Program; builder.
- This avoids having to specify explicitly
- the object file name in multiple places,
- and makes for a compact, readable
- &SConstruct; file.
- Our &SCons; output then looks like:
-
- </para>
-
- <scons_output example="ex4">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- </section>
-
- <section>
- <title>Making Copies of &ConsEnvs;: the &Clone; Method</title>
-
- <para>
-
- Sometimes you want more than one construction environment
- to share the same values for one or more variables.
- Rather than always having to repeat all of the common
- variables when you create each construction environment,
- you can use the &Clone; method
- to create a copy of a construction environment.
-
- </para>
-
- <para>
-
- Like the &Environment; call that creates a construction environment,
- the &Clone; method takes &consvar; assignments,
- which will override the values in the copied construction environment.
- For example, suppose we want to use &gcc;
- to create three versions of a program,
- one optimized, one debug, and one with neither.
- We could do this by creating a "base" construction environment
- that sets &cv-link-CC; to &gcc;,
- and then creating two copies,
- one which sets &cv-link-CCFLAGS; for optimization
- and the other which sets &cv-CCFLAGS; for debugging:
-
- </para>
-
- <scons_example name="ex5">
- <file name="SConstruct" printme="1">
- env = Environment(CC = 'gcc')
- opt = env.Clone(CCFLAGS = '-O2')
- dbg = env.Clone(CCFLAGS = '-g')
-
- env.Program('foo', 'foo.c')
-
- o = opt.Object('foo-opt', 'foo.c')
- opt.Program(o)
-
- d = dbg.Object('foo-dbg', 'foo.c')
- dbg.Program(d)
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- </scons_example>
-
- <para>
-
- Then our output would look like:
-
- </para>
-
- <scons_output example="ex5">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- </section>
-
- <section>
- <title>Replacing Values: the &Replace; Method</title>
-
- <para>
-
- You can replace existing construction variable values
- using the &Replace; method:
-
- </para>
-
- <scons_example name="Replace1">
- <file name="SConstruct" printme="1">
- env = Environment(CCFLAGS = '-DDEFINE1')
- env.Replace(CCFLAGS = '-DDEFINE2')
- env.Program('foo.c')
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- </scons_example>
-
- <para>
-
- The replacing value
- (<literal>-DDEFINE2</literal> in the above example)
- completely replaces the value in the
- construction environment:
-
- </para>
-
- <scons_output example="Replace1">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- You can safely call &Replace;
- for construction variables that
- don't exist in the construction environment:
-
- </para>
-
- <scons_example name="Replace-nonexistent">
- <file name="SConstruct" printme="1">
- env = Environment()
- env.Replace(NEW_VARIABLE = 'xyzzy')
- print "NEW_VARIABLE =", env['NEW_VARIABLE']
- </file>
- </scons_example>
-
- <para>
-
- In this case,
- the construction variable simply
- gets added to the construction environment:
-
- </para>
-
- <scons_output example="Replace-nonexistent">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- Because the variables
- aren't expanded until the construction environment
- is actually used to build the targets,
- and because &SCons; function and method calls
- are order-independent,
- the last replacement "wins"
- and is used to build all targets,
- regardless of the order in which
- the calls to Replace() are
- interspersed with calls to
- builder methods:
-
- </para>
-
- <scons_example name="Replace2">
- <file name="SConstruct" printme="1">
- env = Environment(CCFLAGS = '-DDEFINE1')
- print "CCFLAGS =", env['CCFLAGS']
- env.Program('foo.c')
-
- env.Replace(CCFLAGS = '-DDEFINE2')
- print "CCFLAGS =", env['CCFLAGS']
- env.Program('bar.c')
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- <file name="bar.c">
- int main() { }
- </file>
- </scons_example>
-
- <para>
-
- The timing of when the replacement
- actually occurs relative
- to when the targets get built
- becomes apparent
- if we run &scons; without the <literal>-Q</literal>
- option:
-
- </para>
-
- <scons_output example="Replace2">
- <scons_output_command>scons</scons_output_command>
- </scons_output>
-
- <para>
-
- Because the replacement occurs while
- the &SConscript; files are being read,
- the &cv-link-CCFLAGS;
- variable has already been set to
- <literal>-DDEFINE2</literal>
- by the time the &foo_o; target is built,
- even though the call to the &Replace;
- method does not occur until later in
- the &SConscript; file.
-
- </para>
-
- </section>
-
- <section>
- <title>Setting Values Only If They're Not Already Defined: the &SetDefault; Method</title>
-
- <para>
-
- Sometimes it's useful to be able to specify
- that a construction variable should be
- set to a value only if the construction environment
- does not already have that variable defined
- You can do this with the &SetDefault; method,
- which behaves similarly to the <function>set_default</function>
- method of Python dictionary objects:
-
- </para>
-
- <sconstruct>
- env.SetDefault(SPECIAL_FLAG = '-extra-option')
- </sconstruct>
-
- <para>
-
- This is especially useful
- when writing your own <literal>Tool</literal> modules
- to apply variables to construction environments.
- <!--
- See <xref linkend="chap-tool-modules"></xref>
- for more information about writing
- Tool modules.
- -->
-
- </para>
-
- </section>
-
- <section>
- <title>Appending to the End of Values: the &Append; Method</title>
-
- <para>
-
- You can append a value to
- an existing construction variable
- using the &Append; method:
-
- </para>
-
- <scons_example name="ex8">
- <file name="SConstruct" printme="1">
- env = Environment(CCFLAGS = ['-DMY_VALUE'])
- env.Append(CCFLAGS = ['-DLAST'])
- env.Program('foo.c')
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- </scons_example>
-
- <para>
-
- &SCons; then supplies both the <literal>-DMY_VALUE</literal> and
- <literal>-DLAST</literal> flags when compiling the object file:
-
- </para>
-
- <scons_output example="ex8">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- If the construction variable doesn't already exist,
- the &Append; method will create it:
-
- </para>
-
- <scons_example name="Append-nonexistent">
- <file name="SConstruct" printme="1">
- env = Environment()
- env.Append(NEW_VARIABLE = 'added')
- print "NEW_VARIABLE =", env['NEW_VARIABLE']
- </file>
- </scons_example>
-
- <para>
-
- Which yields:
-
- </para>
-
- <scons_output example="Append-nonexistent">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- Note that the &Append; function tries to be "smart"
- about how the new value is appended to the old value.
- If both are strings, the previous and new strings
- are simply concatenated.
- Similarly, if both are lists,
- the lists are concatenated.
- If, however, one is a string and the other is a list,
- the string is added as a new element to the list.
-
- </para>
-
- </section>
-
- <section>
- <title>Appending Unique Values: the &AppendUnique; Method</title>
-
- <para>
-
- Some times it's useful to add a new value
- only if the existing construction variable
- doesn't already contain the value.
- This can be done using the &AppendUnique; method:
-
- </para>
-
- <sconstruct>
- env.AppendUnique(CCFLAGS=['-g'])
- </sconstruct>
-
- <para>
-
- In the above example,
- the <literal>-g</literal> would be added
- only if the &cv-CCFLAGS; variable
- does not already contain a <literal>-g</literal> value.
-
- </para>
-
- </section>
-
- <section>
- <title>Appending to the Beginning of Values: the &Prepend; Method</title>
-
- <para>
-
- You can append a value to the beginning of
- an existing construction variable
- using the &Prepend; method:
-
- </para>
-
- <scons_example name="ex9">
- <file name="SConstruct" printme="1">
- env = Environment(CCFLAGS = ['-DMY_VALUE'])
- env.Prepend(CCFLAGS = ['-DFIRST'])
- env.Program('foo.c')
- </file>
- <file name="foo.c">
- int main() { }
- </file>
- </scons_example>
-
- <para>
-
- &SCons; then supplies both the <literal>-DFIRST</literal> and
- <literal>-DMY_VALUE</literal> flags when compiling the object file:
-
- </para>
-
- <scons_output example="ex9">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- If the construction variable doesn't already exist,
- the &Prepend; method will create it:
-
- </para>
-
- <scons_example name="Prepend-nonexistent">
- <file name="SConstruct" printme="1">
- env = Environment()
- env.Prepend(NEW_VARIABLE = 'added')
- print "NEW_VARIABLE =", env['NEW_VARIABLE']
- </file>
- </scons_example>
-
- <para>
-
- Which yields:
-
- </para>
-
- <scons_output example="Prepend-nonexistent">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- <para>
-
- Like the &Append; function,
- the &Prepend; function tries to be "smart"
- about how the new value is appended to the old value.
- If both are strings, the previous and new strings
- are simply concatenated.
- Similarly, if both are lists,
- the lists are concatenated.
- If, however, one is a string and the other is a list,
- the string is added as a new element to the list.
-
- </para>
-
- </section>
-
- <section>
- <title>Prepending Unique Values: the &PrependUnique; Method</title>
-
- <para>
-
- Some times it's useful to add a new value
- to the beginning of a construction variable
- only if the existing value
- doesn't already contain the to-be-added value.
- This can be done using the &PrependUnique; method:
-
- </para>
-
- <sconstruct>
- env.PrependUnique(CCFLAGS=['-g'])
- </sconstruct>
-
- <para>
-
- In the above example,
- the <literal>-g</literal> would be added
- only if the &cv-CCFLAGS; variable
- does not already contain a <literal>-g</literal> value.
-
- </para>
-
- </section>
-
- </section>
-
- <section id="sect-execution-environments">
- <title>Controlling the Execution Environment for Issued Commands</title>
-
- <para>
-
- When &SCons; builds a target file,
- it does not execute the commands with
- the same external environment
- that you used to execute &SCons;.
- Instead, it uses the dictionary
- stored in the &cv-link-ENV; construction variable
- as the external environment
- for executing commands.
-
- </para>
-
- <para>
-
- The most important ramification of this behavior
- is that the &PATH; environment variable,
- which controls where the operating system
- will look for commands and utilities,
- is not the same as in the external environment
- from which you called &SCons;.
- This means that &SCons; will not, by default,
- necessarily find all of the tools
- that you can execute from the command line.
-
- </para>
-
- <para>
-
- The default value of the &PATH; environment variable
- on a POSIX system
- is <literal>/usr/local/bin:/bin:/usr/bin</literal>.
- The default value of the &PATH; environment variable
- on a Windows system comes from the Windows registry
- value for the command interpreter.
- If you want to execute any commands--compilers, linkers, etc.--that
- are not in these default locations,
- you need to set the &PATH; value
- in the &cv-ENV; dictionary
- in your construction environment.
-
- </para>
-
- <para>
-
- The simplest way to do this is to initialize explicitly
- the value when you create the construction environment;
- this is one way to do that:
-
- </para>
-
- <sconstruct>
- path = ['/usr/local/bin', '/bin', '/usr/bin']
- env = Environment(ENV = {'PATH' : path})
- </sconstruct>
-
- <para>
-
- Assign a dictionary to the &cv-ENV;
- construction variable in this way
- completely resets the external environment
- so that the only variable that will be
- set when external commands are executed
- will be the &PATH; value.
- If you want to use the rest of
- the values in &cv-ENV; and only
- set the value of &PATH;,
- the most straightforward way is probably:
-
- </para>
-
- <sconstruct>
- env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin']
- </sconstruct>
-
- <para>
-
- Note that &SCons; does allow you to define
- the directories in the &PATH; in a string,
- separated by the pathname-separator character
- for your system (':' on POSIX systems, ';' on Windows):
-
- </para>
-
- <sconstruct>
- env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin'
- </sconstruct>
-
- <para>
-
- But doing so makes your &SConscript; file less portable,
- (although in this case that may not be a huge concern
- since the directories you list are likley system-specific, anyway).
-
- </para>
-
- <!--
-
- <scons_example name="ex1">
- <file name="SConstruct" printme="1">
- env = Environment()
- env.Command('foo', [], '__ROOT__/usr/bin/printenv.py')
- </file>
- <file name="__ROOT__/usr/bin/printenv.py" chmod="0755">
- #!/usr/bin/env python
- import os
- import sys
- if len(sys.argv) &gt; 1:
- keys = sys.argv[1:]
- else:
- keys = sorted(os.environ.keys())
- for key in keys:
- print " " + key + "=" + os.environ[key]
- </file>
- </scons_example>
-
- <para>
-
- </para>
-
- <scons_output example="ex1">
- <scons_output_command>scons -Q</scons_output_command>
- </scons_output>
-
- -->
-
- <section>
- <title>Propagating &PATH; From the External Environment</title>
-
- <para>
-
- You may want to propagate the external &PATH;
- to the execution environment for commands.
- You do this by initializing the &PATH;
- variable with the &PATH; value from
- the <literal>os.environ</literal>
- dictionary,
- which is Python's way of letting you
- get at the external environment:
-
- </para>
-
- <sconstruct>
- import os
- env = Environment(ENV = {'PATH' : os.environ['PATH']})
- </sconstruct>
-
- <para>
-
- Alternatively, you may find it easier
- to just propagate the entire external
- environment to the execution environment
- for commands.
- This is simpler to code than explicity
- selecting the &PATH; value:
-
- </para>
-
- <sconstruct>
- import os
- env = Environment(ENV = os.environ)
- </sconstruct>
-
- <para>
-
- Either of these will guarantee that
- &SCons; will be able to execute
- any command that you can execute from the command line.
- The drawback is that the build can behave
- differently if it's run by people with
- different &PATH; values in their environment--for example,
- if both the <literal>/bin</literal> and
- <literal>/usr/local/bin</literal> directories
- have different &cc; commands,
- then which one will be used to compile programs
- will depend on which directory is listed
- first in the user's &PATH; variable.
-
- </para>
-
- </section>
-
- <section>
- <title>Adding to <varname>PATH</varname> Values in the Execution Environment</title>
-
- <para>
-
- One of the most common requirements
- for manipulating a variable in the execution environment
- is to add one or more custom directories to a search
- like the <envar>$PATH</envar> variable on Linux or POSIX systems,
- or the <envar>%PATH%</envar> variable on Windows,
- so that a locally-installed compiler or other utility
- can be found when &SCons; tries to execute it to update a target.
- &SCons; provides &PrependENVPath; and &AppendENVPath; functions
- to make adding things to execution variables convenient.
- You call these functions by specifying the variable
- to which you want the value added,
- and then value itself.
- So to add some <filename>/usr/local</filename> directories
- to the <envar>$PATH</envar> and <envar>$LIB</envar> variables,
- you might:
-
- </para>
-
- <sconstruct>
- env = Environment(ENV = os.environ)
- env.PrependENVPath('PATH', '/usr/local/bin')
- env.AppendENVPath('LIB', '/usr/local/lib')
- </sconstruct>
-
- <para>
-
- Note that the added values are strings,
- and if you want to add multiple directories to
- a variable like <envar>$PATH</envar>,
- you must include the path separate character
- (<literal>:</literal> on Linux or POSIX,
- <literal>;</literal> on Windows)
- in the string.
-
- </para>
-
- </section>
-
- </section>