summaryrefslogtreecommitdiff
path: root/doc/user/environments.xml
diff options
context:
space:
mode:
authorLuca Falavigna <dktrkranz@debian.org>2010-01-02 20:56:35 +0100
committerLuca Falavigna <dktrkranz@debian.org>2010-01-02 20:56:35 +0100
commit64c458487151933ee0ba093cf4ac69e177d9be37 (patch)
treef6e3755704f53406eea85532e4ffe5d5ef50b7f0 /doc/user/environments.xml
parent2aec9cc58398cac1376509a7d75edb83b41f984e (diff)
parent72c578fd4b0b4a5a43e18594339ac4ff26c376dc (diff)
Merge commit 'upstream/1.2.0.d20091224'
Diffstat (limited to 'doc/user/environments.xml')
-rw-r--r--doc/user/environments.xml1684
1 files changed, 1684 insertions, 0 deletions
diff --git a/doc/user/environments.xml b/doc/user/environments.xml
new file mode 100644
index 0000000..b9a60b9
--- /dev/null
+++ b/doc/user/environments.xml
@@ -0,0 +1,1684 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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>
+
+ <programlisting>
+ import os
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ import os
+
+ env = Environment(CC = 'gcc',
+ CCFLAGS = '-O2')
+
+ env.Program('foo.c')
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ gcc -o foo.o -c -O2 foo.c
+ gcc -o foo foo.o
+ </screen>
+
+ </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>
+
+ <programlisting>
+ env = Environment()
+ print "CC is:", env['CC']
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ CC is: cc
+ scons: `.' is up to date.
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env = Environment(FOO = 'foo', BAR = 'bar')
+ dict = env.Dictionary()
+ for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
+ print "key = %s, value = %s" % (key, dict[key])
+ </programlisting>
+
+ <para>
+
+ This &SConstruct; file
+ will print the specified dictionary items for us on POSIX
+ systems as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ key = OBJSUFFIX, value = .o
+ key = LIBSUFFIX, value = .a
+ key = PROGSUFFIX, value =
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ And on Windows:
+
+ </para>
+
+ <screen>
+ C:\><userinput>scons -Q</userinput>
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No installed VCs
+ File "&lt;stdin&gt;", line 67, in __call__
+
+ scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
+ File "&lt;stdin&gt;", line 67, in __call__
+ key = OBJSUFFIX, value = .obj
+ key = LIBSUFFIX, value = .lib
+ key = PROGSUFFIX, value = .exe
+ scons: `.' is up to date.
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env = Environment()
+ dict = env.Dictionary()
+ keys = dict.keys()
+ keys.sort()
+ for key in keys:
+ print "construction variable = '%s', value = '%s'" % (key, dict[key])
+ </programlisting>
+
+ </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>
+
+ <programlisting>
+ env = Environment()
+ print "CC is:", env.subst('$CC')
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ env = Environment(CCFLAGS = '-DFOO')
+ print "CCCOM is:", env['CCCOM']
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ env = Environment(CCFLAGS = '-DFOO')
+ print "CCCOM is:", env.subst('$CCCOM')
+ </programlisting>
+
+ <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>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 contstruction environment
+ by using the &DefaultEnvironment; function
+ to initialize various settings:
+
+ </para>
+
+ <programlisting>
+
+ DefaultEnvironment(CC = '/usr/local/bin/gcc')
+
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+
+ env = DefaultEnvironment()
+ env['CC'] = '/usr/local/bin/gcc'
+
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+
+ env = DefaultEnvironment(tools = ['gcc', 'gnulink'],
+ CC = '/usr/local/bin/gcc')
+
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
+
+ opt.Program('foo', 'foo.c')
+
+ dbg.Program('bar', 'bar.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o bar.o -c -g bar.c
+ cc -o bar bar.o
+ cc -o foo.o -c -O2 foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <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>
+
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
+
+ opt.Program('foo', 'foo.c')
+
+ dbg.Program('foo', 'foo.c')
+ </programlisting>
+
+ <para>
+
+ Then &SCons; generates the following error:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+
+ scons: warning: Two different environments were specified for target foo.o,
+ but they appear to have the same action: CCCom(target, source, env)
+ File "/home/my/project/SConstruct", line 6, in ?
+
+ scons: warning: Two different environments were specified for target foo,
+ but they appear to have the same action: Cat(target, source, env)
+ File "/home/my/project/SConstruct", line 6, in ?
+ cc -o foo.o -c -g foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <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>
+
+ <programlisting>
+ 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)
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o foo-dbg.o -c -g foo.c
+ cc -o foo-dbg foo-dbg.o
+ cc -o foo-opt.o -c -O2 foo.c
+ cc -o foo-opt foo-opt.o
+ </screen>
+
+ </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>
+
+ <programlisting>
+ 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)
+ </programlisting>
+
+ <para>
+
+ Then our output would look like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ gcc -o foo.o -c foo.c
+ gcc -o foo foo.o
+ gcc -o foo-dbg.o -c -g foo.c
+ gcc -o foo-dbg foo-dbg.o
+ gcc -o foo-opt.o -c -O2 foo.c
+ gcc -o foo-opt foo-opt.o
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Replacing Values: the &Replace; Method</title>
+
+ <para>
+
+ You can replace existing construction variable values
+ using the &Replace; method:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CCFLAGS = '-DDEFINE1')
+ env.Replace(CCFLAGS = '-DDEFINE2')
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ The replacing value
+ (<literal>-DDEFINE2</literal> in the above example)
+ completely replaces the value in the
+ construction environment:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o foo.o -c -DDEFINE2 foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <para>
+
+ You can safely call &Replace;
+ for construction variables that
+ don't exist in the construction environment:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Replace(NEW_VARIABLE = 'xyzzy')
+ print "NEW_VARIABLE =", env['NEW_VARIABLE']
+ </programlisting>
+
+ <para>
+
+ In this case,
+ the construction variable simply
+ gets added to the construction environment:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ NEW_VARIABLE = xyzzy
+ scons: `.' is up to date.
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env = Environment(CCFLAGS = '-DDEFINE1')
+ print "CCFLAGS =", env['CCFLAGS']
+ env.Program('foo.c')
+
+ env.Replace(CCFLAGS = '-DDEFINE2')
+ print "CCFLAGS =", env['CCFLAGS']
+ env.Program('bar.c')
+ </programlisting>
+
+ <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>
+
+ <screen>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ CCFLAGS = -DDEFINE1
+ CCFLAGS = -DDEFINE2
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -o bar.o -c -DDEFINE2 bar.c
+ cc -o bar bar.o
+ cc -o foo.o -c -DDEFINE2 foo.c
+ cc -o foo foo.o
+ scons: done building targets.
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env.SetDefault(SPECIAL_FLAG = '-extra-option')
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ env = Environment(CCFLAGS = ['-DMY_VALUE'])
+ env.Append(CCFLAGS = ['-DLAST'])
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ &SCons; then supplies both the <literal>-DMY_VALUE</literal> and
+ <literal>-DLAST</literal> flags when compiling the object file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o foo.o -c -DMY_VALUE -DLAST foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <para>
+
+ If the construction variable doesn't already exist,
+ the &Append; method will create it:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Append(NEW_VARIABLE = 'added')
+ print "NEW_VARIABLE =", env['NEW_VARIABLE']
+ </programlisting>
+
+ <para>
+
+ Which yields:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ NEW_VARIABLE = added
+ scons: `.' is up to date.
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env.AppendUnique(CCFLAGS=['-g'])
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ env = Environment(CCFLAGS = ['-DMY_VALUE'])
+ env.Prepend(CCFLAGS = ['-DFIRST'])
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ &SCons; then supplies both the <literal>-DFIRST</literal> and
+ <literal>-DMY_VALUE</literal> flags when compiling the object file:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o foo.o -c -DFIRST -DMY_VALUE foo.c
+ cc -o foo foo.o
+ </screen>
+
+ <para>
+
+ If the construction variable doesn't already exist,
+ the &Prepend; method will create it:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Prepend(NEW_VARIABLE = 'added')
+ print "NEW_VARIABLE =", env['NEW_VARIABLE']
+ </programlisting>
+
+ <para>
+
+ Which yields:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ NEW_VARIABLE = added
+ scons: `.' is up to date.
+ </screen>
+
+ <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>
+
+ <programlisting>
+ env.PrependUnique(CCFLAGS=['-g'])
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ path = ['/usr/local/bin', '/bin', '/usr/bin']
+ env = Environment(ENV = {'PATH' : path})
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin']
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin'
+ </programlisting>
+
+ <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) > 1:
+ keys = sys.argv[1:]
+ else:
+ keys = os.environ.keys()
+ keys.sort()
+ 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>
+
+ <programlisting>
+ import os
+ env = Environment(ENV = {'PATH' : os.environ['PATH']})
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ import os
+ env = Environment(ENV = os.environ)
+ </programlisting>
+
+ <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>
+
+ <programlisting>
+ env = Environment(ENV = os.environ)
+ env.PrependENVPath('PATH', '/usr/local/bin')
+ env.AppendENVPath('LIB', '/usr/local/lib')
+ </programlisting>
+
+ <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>