mirror of
https://github.com/Relintai/scons_gd.git
synced 2025-02-10 16:40:14 +01:00
2176 lines
64 KiB
XML
2176 lines
64 KiB
XML
<?xml version='1.0'?>
|
|
<!DOCTYPE sconsdoc [
|
|
<!ENTITY % scons SYSTEM "../scons.mod">
|
|
%scons;
|
|
|
|
<!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
|
|
%builders-mod;
|
|
<!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
|
|
%functions-mod;
|
|
<!ENTITY % tools-mod SYSTEM "../generated/tools.mod">
|
|
%tools-mod;
|
|
<!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
|
|
%variables-mod;
|
|
|
|
]>
|
|
|
|
<chapter id="chap-environments"
|
|
xmlns="http://www.scons.org/dbxsd/v1.0"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
|
|
<title>Environments</title>
|
|
|
|
<!--
|
|
|
|
__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.
|
|
|
|
-->
|
|
|
|
<!--
|
|
|
|
=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 an
|
|
empty 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 <firstterm>environment</firstterm>
|
|
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 <firstterm>External Environment</firstterm>
|
|
is the set of variables in the user's environment
|
|
at the time the user runs &SCons;. These variables are not
|
|
automatically part of an &SCons; build
|
|
but are available to be examined if needed.
|
|
See <xref linkend="sect-external-environments"></xref>, below.
|
|
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>Construction Environment</term>
|
|
|
|
<listitem>
|
|
<para>
|
|
|
|
A <firstterm>&ConsEnv;</firstterm>
|
|
is a distinct object created within
|
|
a &SConscript; file 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 <firstterm>Execution Environment</firstterm>
|
|
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 external environment
|
|
(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 the 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>
|
|
|
|
<sidebar>
|
|
<title>Sidebar: Python Dictionaries</title>
|
|
|
|
<para>
|
|
|
|
If you're not familiar with the &Python; programming language,
|
|
we need to talk a little bit about the &Python; dictionary data type.
|
|
A dictionary (also known by terms such as mapping, associative array
|
|
and key-value store) associates keys with values, such
|
|
that asking the dict about a key gives you back the associated value
|
|
and assigning to a key creates the association - either a new
|
|
setting if the key was unknown, or replacing the
|
|
previous association if the key was already in the dictionary.
|
|
Values can be retrieved using <firstterm>item access</firstterm>
|
|
(the key name in square brackets (<literal>[]</literal>)),
|
|
and dictionaries also provide a
|
|
method named <methodname>get</methodname> which responds
|
|
with a default value, either <constant>None</constant> or a value
|
|
you supply as the second argument, if the key is not in the dictionary,
|
|
which avoids failing in that case. The syntax
|
|
for initializing a dictionary uses curly braces (<literal>{}</literal>).
|
|
Here are some simple examples (inspired by those in the official
|
|
Python tutorial) using syntax that indicates
|
|
interacting with the &Python; interpreter
|
|
(<prompt>>>></prompt> is the interpreter prompt) -
|
|
you can try these out:
|
|
|
|
</para>
|
|
|
|
<screen>
|
|
<prompt>>>></prompt> <userinput>tel = {'jack': 4098, 'sape': 4139}</userinput>
|
|
<prompt>>>></prompt> <userinput>tel['guido'] = 4127</userinput>
|
|
<prompt>>>></prompt> <userinput>tel['jack']</userinput>
|
|
4098
|
|
<prompt>>>></prompt> <userinput>del tel['sape']</userinput>
|
|
<prompt>>>></prompt> <userinput>tel['irv'] = 4127</userinput>
|
|
<prompt>>>></prompt> <userinput>print(tel)</userinput>
|
|
{'jack': 4098, 'guido': 4127, 'irv': 4127}
|
|
<prompt>>>></prompt> <userinput>'guido' in tel</userinput>
|
|
True
|
|
<prompt>>>></prompt> <userinput>print(tel['jack'])</userinput>
|
|
Traceback (most recent call last):
|
|
File "<stdin>", line 1, in <module>
|
|
KeyError: 'jack'
|
|
<prompt>>>></prompt> <userinput>print(tel.get('jack'))</userinput>
|
|
None
|
|
</screen>
|
|
|
|
<para>
|
|
|
|
&Consenvs; are written to behave like a &Python;
|
|
dictionary, and the &cv-ENV; construction variable in
|
|
a &consenv; <emphasis>is</emphasis> a &Python; dictionary.
|
|
The <varname>os.environ</varname> value that &Python; uses
|
|
to make available the external environment is also a
|
|
dictionary. We will need these concepts in this chapter
|
|
and throughout the rest of this guide.
|
|
|
|
</para>
|
|
|
|
</sidebar>
|
|
|
|
<section id="sect-external-environments">
|
|
<title>Using Values From the External Environment</title>
|
|
|
|
<para>
|
|
|
|
The external environment
|
|
variable settings that
|
|
the user has in force
|
|
when executing &SCons;
|
|
are available in the &Python;
|
|
<varname>os.environ</varname> dictionary.
|
|
That syntax means the <varname>environ</varname>
|
|
attribute of the <systemitem>os</systemitem> module.
|
|
In Python, to access the contents of a module you must first
|
|
<literal>import</literal> it - so you would include the
|
|
<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="environments_ex1">
|
|
<file name="SConstruct" printme="1">
|
|
import os
|
|
|
|
print("Shell is", os.environ['SHELL'])
|
|
</file>
|
|
<file name="foo.c">
|
|
void main() { }
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
More usefully, you can use the
|
|
<varname>os.environ</varname>
|
|
dictionary in your &SConscript;
|
|
files to initialize &consenvs;
|
|
with values from the user's external environment.
|
|
Read on to the next section 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 exactly 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, just like a dictionary.
|
|
(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="environments_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 that the <option>-O2</option>
|
|
(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="environments_ex1" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Fetching Values From a &ConsEnv;</title>
|
|
|
|
<para>
|
|
|
|
You can fetch individual values, known as
|
|
<firstterm>Construction Variables</firstterm>,
|
|
using the same syntax used
|
|
for accessing individual named items in a &Python; dictionary:
|
|
|
|
</para>
|
|
|
|
<scons_example name="environments_ex6">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment()
|
|
print("CC is: %s" % env['CC'])
|
|
print("LATEX is: %s" % env.get('LATEX', None))
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
This example &SConstruct; file doesn't contain instructions
|
|
for building any targets, but because it's still a valid
|
|
&SConstruct; it will be evaluated and the &Python;
|
|
<function>print</function> calls will output the values
|
|
of &cv-link-CC; and &cv-link-LATEX; for us (remember using the
|
|
<methodname>.get()</methodname> method for fetching means
|
|
we get a default value back, rather than a failure,
|
|
if the variable is not set):
|
|
|
|
</para>
|
|
|
|
<scons_output example="environments_ex6" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
A &consenv;
|
|
is actually an object with associated methods and attributes.
|
|
If you want to have direct access to only the
|
|
dictionary of &consvars;
|
|
you can fetch this using the &f-link-env-Dictionary; method
|
|
(although it's rarely necessary to use this method):
|
|
|
|
</para>
|
|
|
|
<scons_example name="environments_ex6b">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment(FOO='foo', BAR='bar')
|
|
cvars = env.Dictionary()
|
|
for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
|
|
print("key = %s, value = %s" % (key, cvars[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="environments_ex6b" os="posix" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
And on Windows:
|
|
|
|
</para>
|
|
|
|
<scons_output example="environments_ex6b" os="win32" suffix="2">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
If you want to loop and print the values of
|
|
all of the &consvars; in a &consenv;,
|
|
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>
|
|
|
|
<para>
|
|
It should be noted that for the previous example, there is actually
|
|
a &consenv; method that does the same thing more simply,
|
|
and tries to format the output nicely as well:
|
|
</para>
|
|
<sconstruct>
|
|
env = Environment()
|
|
print(env.Dump())
|
|
</sconstruct>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Expanding Values From a &ConsEnv;: the &subst; Method</title>
|
|
|
|
<para>
|
|
|
|
Another way to get information from
|
|
a &consenv;
|
|
is to use the &subst; method
|
|
on a string containing <literal>$</literal> expansions
|
|
of &consvar; 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: %s" % env.subst('$CC'))
|
|
</sconstruct>
|
|
|
|
<para>
|
|
|
|
One advantage of using
|
|
&subst; to expand strings is
|
|
that &consvars;
|
|
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: %s" % 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: %s" % 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>
|
|
(an empty string), and will not cause &scons; to fail.
|
|
</para>
|
|
|
|
<scons_example name="environments_missing1">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment()
|
|
print("value is: %s"%env.subst( '->$MISSING<-' ))
|
|
</file>
|
|
</scons_example>
|
|
|
|
<scons_output example="environments_missing1" suffix="1">
|
|
<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="environments_missing2">
|
|
<file name="SConstruct" printme="1">
|
|
AllowSubstExceptions()
|
|
env = Environment()
|
|
print("value is: %s"%env.subst( '->$MISSING<-' ))
|
|
</file>
|
|
</scons_example>
|
|
|
|
<scons_output example="environments_missing2" suffix="1">
|
|
<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="environments_missing3">
|
|
<file name="SConstruct" printme="1">
|
|
AllowSubstExceptions(IndexError, NameError, ZeroDivisionError)
|
|
env = Environment()
|
|
print("value is: %s"%env.subst( '->${1 / 0}<-' ))
|
|
</file>
|
|
</scons_example>
|
|
|
|
<scons_output example="environments_missing3" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<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;, use a &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.
|
|
If not invoked as methods of a specific &consenv;,
|
|
they use the default &consenv;
|
|
The goal of the default &consenv;
|
|
is to make many configurations "just work"
|
|
to build software using readily available tools
|
|
with a minimum of configuration changes.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
If needed, you can control the default &consenv;
|
|
by using the &DefaultEnvironment; function
|
|
to initialize various settings by passing
|
|
them as keyword arguments:
|
|
|
|
</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>
|
|
|
|
The &DefaultEnvironment; function
|
|
returns the initialized default &consenv; object,
|
|
which can then be manipulated like any other &consenv;
|
|
(note that the default environment works like a singleton -
|
|
it can have only one instance - so the keyword arguments
|
|
are processed only on the first call. On any subsequent
|
|
call the existing object is returned).
|
|
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>
|
|
def_env = DefaultEnvironment()
|
|
def_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>
|
|
def_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 id='multiple_construction_envs'>
|
|
<title>Multiple &ConsEnvs;</title>
|
|
|
|
<para>
|
|
|
|
The real advantage of &consenvs;
|
|
is that you can create as many different ones 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 <option>-O2</option> flag
|
|
and another with the <option>-g</option> (debug) flag,
|
|
we would do this like so:
|
|
|
|
</para>
|
|
|
|
<scons_example name="environments_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="environments_ex2" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
We can even use multiple &consenvs; 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="environments_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="environments_ex3" suffix="1">
|
|
<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
|
|
<option>-O2</option>
|
|
and one with a &cv-link-CCFLAGS; value of
|
|
<option>-g</option>.
|
|
&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="environments_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="environments_ex4" suffix="1">
|
|
<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 &f-link-env-Clone; method
|
|
to create a copy of a construction environment.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
Like the &f-link-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="environments_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="environments_ex5" suffix="1">
|
|
<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 &f-link-env-Replace; method:
|
|
|
|
</para>
|
|
|
|
<scons_example name="environments_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="environments_Replace1" suffix="1">
|
|
<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="environments_Replace-nonexistent">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment()
|
|
env.Replace(NEW_VARIABLE='xyzzy')
|
|
print("NEW_VARIABLE = %s" % env['NEW_VARIABLE'])
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
In this case,
|
|
the construction variable simply
|
|
gets added to the construction environment:
|
|
|
|
</para>
|
|
|
|
<scons_output example="environments_Replace-nonexistent" suffix="1">
|
|
<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="environments_Replace2">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment(CCFLAGS='-DDEFINE1')
|
|
print("CCFLAGS = %s" % env['CCFLAGS'])
|
|
env.Program('foo.c')
|
|
|
|
env.Replace(CCFLAGS='-DDEFINE2')
|
|
print("CCFLAGS = %s" % 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 <option>-Q</option>
|
|
option:
|
|
|
|
</para>
|
|
|
|
<scons_output example="environments_Replace2" suffix="1">
|
|
<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 &f-link-env-SetDefault; method,
|
|
which behaves similarly to the <function>setdefault</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 &f-link-env-Append; method:
|
|
|
|
</para>
|
|
|
|
<scons_example name="environments_ex8">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment(CPPDEFINES=['MY_VALUE'])
|
|
env.Append(CPPDEFINES=['LAST'])
|
|
env.Program('foo.c')
|
|
</file>
|
|
<file name="foo.c">
|
|
int main() { }
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Note &cv-link-CPPDEFINES; is the preferred way to set preprocessor defines,
|
|
as &SCons; will generate the command line arguments using the correct
|
|
prefix/suffix for the platform, leaving the usage portable.
|
|
If you use &cv-link-CCFLAGS; and &cv-link-SHCCFLAGS;,
|
|
you need to include them in their final form, which is less portable.
|
|
|
|
</para>
|
|
|
|
<scons_output example="environments_ex8" suffix="1">
|
|
<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="environments_Append-nonexistent">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment()
|
|
env.Append(NEW_VARIABLE = 'added')
|
|
print("NEW_VARIABLE = %s"%env['NEW_VARIABLE'])
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which yields:
|
|
|
|
</para>
|
|
|
|
<scons_output example="environments_Append-nonexistent" suffix="1">
|
|
<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>
|
|
|
|
Sometimes 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 &f-link-env-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>Prepending to the Beginning of Values: the &Prepend; Method</title>
|
|
|
|
<para>
|
|
|
|
You can prepend a value to the beginning of
|
|
an existing construction variable
|
|
using the &f-link-env-Prepend; method:
|
|
|
|
</para>
|
|
|
|
<scons_example name="environments_ex9">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment(CPPDEFINES=['MY_VALUE'])
|
|
env.Prepend(CPPDEFINES=['FIRST'])
|
|
env.Program('foo.c')
|
|
</file>
|
|
<file name="foo.c">
|
|
int main() { }
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
&SCons; then generates the preprocessor define arguments from &CPPDEFINES; values with the correct
|
|
prefix/suffix. For example on Linux or POSIX, the following arguments would be generated:
|
|
<literal>-DFIRST</literal> and
|
|
<literal>-DMY_VALUE</literal>
|
|
|
|
</para>
|
|
|
|
<scons_output example="environments_ex9" suffix="1">
|
|
<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="environments_Prepend-nonexistent">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment()
|
|
env.Prepend(NEW_VARIABLE='added')
|
|
print("NEW_VARIABLE = %s" % env['NEW_VARIABLE'])
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which yields:
|
|
|
|
</para>
|
|
|
|
<scons_output example="environments_Prepend-nonexistent" suffix="1">
|
|
<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 &f-link-env-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 id="builder_overrides">
|
|
<title>Overriding Construction Variable Settings</title>
|
|
|
|
<para>
|
|
|
|
Rather than creating a cloned &consenv; for specific tasks,
|
|
you can <firstterm>override</firstterm> or add construction variables
|
|
when calling a builder method by passing them as keyword arguments.
|
|
The values of these overridden or added variables will only be in
|
|
effect when building that target, and will not affect other parts
|
|
of the build.
|
|
For example, if you want to add additional libraries for just one program:
|
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
env.Program('hello', 'hello.c', LIBS=['gl', 'glut'])
|
|
</programlisting>
|
|
|
|
<para>
|
|
|
|
or generate a shared library with a non-standard suffix:
|
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
env.SharedLibrary(
|
|
target='word',
|
|
source='word.cpp',
|
|
SHLIBSUFFIX='.ocx',
|
|
LIBSUFFIXES=['.ocx'],
|
|
)
|
|
</programlisting>
|
|
|
|
<para>
|
|
|
|
When overriding this way, the &Python; keyword arguments in
|
|
the builder call mean "set to this value".
|
|
If you want your override to augment an existing value,
|
|
you have to take some extra steps.
|
|
Inside the builder call,
|
|
it is possible to substitute in the existing value by using
|
|
a string containing the variable name prefaced by a
|
|
dollar sign (<literal>$</literal>).
|
|
|
|
</para>
|
|
|
|
<scons_example name="builders_override_ex1">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment(CPPDEFINES="FOO")
|
|
env.Object(target="foo1.o", source="foo.c")
|
|
env.Object(target="foo2.o", source="foo.c", CPPDEFINES="BAR")
|
|
env.Object(target="foo3.o", source="foo.c", CPPDEFINES=["BAR", "$CPPDEFINES"])
|
|
</file>
|
|
<file name="foo.c">
|
|
void main() { }
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which yields:
|
|
|
|
</para>
|
|
|
|
<scons_output example="builders_override_ex1" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
It is also possible to use the <parameter>parse_flags</parameter>
|
|
keyword argument in an override to merge command-line
|
|
style arguments into the appropriate construction
|
|
variables. This works like the &f-link-env-MergeFlags; method,
|
|
which will be fully described in the next chapter.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
This example adds 'include' to &cv-link-CPPPATH;,
|
|
'EBUG' to &cv-link-CPPDEFINES;, and 'm' to &cv-link-LIBS;:
|
|
|
|
</para>
|
|
|
|
<scons_example name="builders_override_ex2">
|
|
<file name="SConstruct" printme="1">
|
|
env = Environment()
|
|
env.Program('hello', 'hello.c', parse_flags='-Iinclude -DEBUG -lm')
|
|
</file>
|
|
<file name="hello.c">
|
|
#include <stdio.h>
|
|
void main() {
|
|
printf("Hello, world\n");
|
|
}
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
So when executed:
|
|
|
|
</para>
|
|
|
|
<scons_output example="builders_override_ex2" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
Using temporary overrides this way is lighter weight than making
|
|
a full construction environment, so it can help performance in
|
|
large projects which have lots of special case values to set.
|
|
However, keep in mind that this only works well when the
|
|
targets are unique. Using builder overrides to try to build
|
|
the same target with different sets of flags or other construction
|
|
variables will lead to the
|
|
<computeroutput>scons: *** Two environments with different actions...</computeroutput>
|
|
error described in <xref linkend="multiple_construction_envs"/>
|
|
above. In this case you will actually want to create separate
|
|
environments.
|
|
|
|
</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 external environment
|
|
that you used to execute &SCons;.
|
|
Instead, it builds an execution environment from the values
|
|
stored in the &cv-link-ENV; &consvar;
|
|
and uses that 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,
|
|
will almost certainly not be the same as in the external environment
|
|
from which you called &SCons;.
|
|
This means that &SCons; might not
|
|
necessarily find all of the tools
|
|
that you can successfully execute from the command line.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
The default value of the &PATH; environment variable
|
|
on a POSIX system
|
|
is <literal>/usr/local/bin:/opt/bin:/bin:/usr/bin:/snap/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>
|
|
|
|
Assigning a dictionary to the &cv-ENV;
|
|
construction variable in this way
|
|
completely resets the execution 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;, you can assign a value only
|
|
to that variable:
|
|
|
|
</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 with paths
|
|
separated by the pathname-separator character
|
|
for your system (<literal>':'</literal> on POSIX systems,
|
|
<literal>';'</literal> on Windows).
|
|
|
|
</para>
|
|
|
|
<sconstruct>
|
|
env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin'
|
|
</sconstruct>
|
|
|
|
<para>
|
|
|
|
But doing so makes your &SConscript; file less portable,
|
|
since it will be correct only for the system type that
|
|
matches the separator. You can use the &Python;
|
|
<varname>os.pathsep</varname> for for greater portability -
|
|
don't worry too much if this &Python; syntax doesn't make sense
|
|
since there are other ways available:
|
|
|
|
</para>
|
|
|
|
<sconstruct>
|
|
import os
|
|
env['ENV']['PATH'] = os.pathsep.join(['/usr/local/bin', '/bin', '/usr/bin'])
|
|
</sconstruct>
|
|
|
|
<!--
|
|
|
|
<scons_example name="environments_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="0o755">
|
|
#!/usr/bin/env python
|
|
import os
|
|
import sys
|
|
if len(sys.argv) > 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="environments_ex1" suffix="2">
|
|
<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 environment &PATH;
|
|
to the execution environment for commands.
|
|
You do this by initializing the &PATH;
|
|
variable with the &PATH; value from
|
|
the <varname>os.environ</varname>
|
|
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.copy())
|
|
</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 path search variable
|
|
like <envar>PATH</envar> on Linux or POSIX systems,
|
|
or <envar>%PATH%</envar> 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 &f-link-env-PrependENVPath;
|
|
and &f-link-env-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.copy())
|
|
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 separator character
|
|
in the string
|
|
(<literal>:</literal> on Linux or POSIX,
|
|
<literal>;</literal> on Windows, or use
|
|
<literal>os.pathsep</literal> for portability).
|
|
|
|
</para>
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
|
|
<section id="sect-environment-toolpath">
|
|
<title>Using the toolpath for external Tools</title>
|
|
|
|
<section>
|
|
<title>The default tool search path</title>
|
|
|
|
<para>
|
|
Normally when using a tool from the construction environment,
|
|
several different search locations are checked by default.
|
|
This includes the <filename>SCons/Tools/</filename> directory
|
|
that is part of the &scons; distribution
|
|
and the directory <filename>site_scons/site_tools</filename>
|
|
relative to the root &SConstruct; file.
|
|
</para>
|
|
|
|
<sconstruct>
|
|
# Builtin tool or tool located within site_tools
|
|
env = Environment(tools=['SomeTool'])
|
|
env.SomeTool(targets, sources)
|
|
|
|
# The search locations would include by default
|
|
SCons/Tool/SomeTool.py
|
|
SCons/Tool/SomeTool/__init__.py
|
|
./site_scons/site_tools/SomeTool.py
|
|
./site_scons/site_tools/SomeTool/__init__.py
|
|
</sconstruct>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Providing an external directory to toolpath</title>
|
|
|
|
<para>
|
|
In some cases you may want to specify a different location to search for tools.
|
|
The &f-link-Environment; function contains an option for this called
|
|
<parameter>toolpath</parameter>
|
|
This can be used to add additional search directories.
|
|
</para>
|
|
|
|
<sconstruct>
|
|
# Tool located within the toolpath directory option
|
|
env = Environment(
|
|
tools=['SomeTool'],
|
|
toolpath=['/opt/SomeToolPath', '/opt/SomeToolPath2']
|
|
)
|
|
env.SomeTool(targets, sources)
|
|
|
|
# The search locations in this example would include:
|
|
/opt/SomeToolPath/SomeTool.py
|
|
/opt/SomeToolPath/SomeTool/__init__.py
|
|
/opt/SomeToolPath2/SomeTool.py
|
|
/opt/SomeToolPath2/SomeTool/__init__.py
|
|
SCons/Tool/SomeTool.py
|
|
SCons/Tool/SomeTool/__init__.py
|
|
./site_scons/site_tools/SomeTool.py
|
|
./site_scons/site_tools/SomeTool/__init__.py
|
|
</sconstruct>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Nested Tools within a toolpath</title>
|
|
|
|
<para>
|
|
|
|
Since &SCons; 3.0, a Builder may be located
|
|
within a sub-directory / sub-package of the toolpath.
|
|
This is similar to namespacing within &Python;.
|
|
<!-- TODO: that was an advanced topic!!! -->
|
|
With nested or namespaced tools we can use the dot notation
|
|
to specify a sub-directory that the tool is located under.
|
|
|
|
</para>
|
|
|
|
<sconstruct>
|
|
# namespaced target
|
|
env = Environment(
|
|
tools=['SubDir1.SubDir2.SomeTool'],
|
|
toolpath=['/opt/SomeToolPath']
|
|
)
|
|
env.SomeTool(targets, sources)
|
|
|
|
# With this example the search locations would include
|
|
/opt/SomeToolPath/SubDir1/SubDir2/SomeTool.py
|
|
/opt/SomeToolPath/SubDir1/SubDir2/SomeTool/__init__.py
|
|
SCons/Tool/SubDir1/SubDir2/SomeTool.py
|
|
SCons/Tool/SubDir1/SubDir2/SomeTool/__init__.py
|
|
./site_scons/site_tools/SubDir1/SubDir2/SomeTool.py
|
|
./site_scons/site_tools/SubDir1/SubDir2/SomeTool/__init__.py
|
|
</sconstruct>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Using sys.path within the toolpath</title>
|
|
|
|
<para>
|
|
If we want to access tools external to &scons; which are findable
|
|
via <varname>sys.path</varname>
|
|
(for example, tools installed via Python's <command>pip</command> package manager),
|
|
it is possible to use <varname>sys.path</varname> with the toolpath.
|
|
|
|
One thing to watch out for with this approach is that
|
|
<varname>sys.path</varname>
|
|
can sometimes contains paths to <filename>.egg</filename>
|
|
files instead of directories.
|
|
So we need to filter those out with this approach.
|
|
</para>
|
|
|
|
<sconstruct>
|
|
# namespaced target using sys.path within toolpath
|
|
|
|
searchpaths = []
|
|
for item in sys.path:
|
|
if os.path.isdir(item):
|
|
searchpaths.append(item)
|
|
|
|
env = Environment(
|
|
tools=['someinstalledpackage.SomeTool'],
|
|
toolpath=searchpaths
|
|
)
|
|
env.SomeTool(targets, sources)
|
|
</sconstruct>
|
|
|
|
<para>
|
|
By using <varname>sys.path</varname> with the toolpath argument
|
|
and by using the nested syntax we can have &scons; search
|
|
packages installed via <command>pip</command> for Tools.
|
|
</para>
|
|
|
|
<sconstruct>
|
|
# For Windows based on the python version and install directory, this may be something like
|
|
C:\Python35\Lib\site-packages\someinstalledpackage\SomeTool.py
|
|
C:\Python35\Lib\site-packages\someinstalledpackage\SomeTool\__init__.py
|
|
|
|
# For Linux this could be something like:
|
|
/usr/lib/python3/dist-packages/someinstalledpackage/SomeTool.py
|
|
/usr/lib/python3/dist-packages/someinstalledpackage/SomeTool/__init__.py
|
|
</sconstruct>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Using the &PyPackageDir; function to add to the toolpath</title>
|
|
|
|
<para>
|
|
In some cases you may want to use a tool
|
|
located within a installed external pip package.
|
|
This is possible by the use of
|
|
<varname>sys.path</varname> with the toolpath.
|
|
However in that situation you need to provide a prefix to the toolname
|
|
to indicate where it is located within <varname>sys.path</varname>.
|
|
</para>
|
|
|
|
<sconstruct>
|
|
searchpaths = []
|
|
for item in sys.path:
|
|
if os.path.isdir(item):
|
|
searchpaths.append(item)
|
|
env = Environment(
|
|
tools=['tools_example.subdir1.subdir2.SomeTool'],
|
|
toolpath=searchpaths
|
|
)
|
|
env.SomeTool(targets, sources)
|
|
</sconstruct>
|
|
|
|
<para>
|
|
To avoid the use of a prefix within the name of the tool or filtering
|
|
<varname>sys.path</varname> for directories,
|
|
we can use &f-link-PyPackageDir; function to locate the directory of
|
|
the python package.
|
|
&f-PyPackageDir; returns a Dir object which represents the path of the
|
|
directory
|
|
for the python package / module specified as a parameter.
|
|
</para>
|
|
|
|
<sconstruct>
|
|
# namespaced target using sys.path
|
|
env = Environment(
|
|
tools=['SomeTool'],
|
|
toolpath=[PyPackageDir('tools_example.subdir1.subdir2')]
|
|
)
|
|
env.SomeTool(targets, sources)
|
|
</sconstruct>
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
</chapter>
|