| Index: third_party/scons/scons-local/SCons/Environment.py
 | 
| ===================================================================
 | 
| --- third_party/scons/scons-local/SCons/Environment.py	(revision 7290)
 | 
| +++ third_party/scons/scons-local/SCons/Environment.py	(working copy)
 | 
| @@ -1,2252 +1,2253 @@
 | 
| -"""SCons.Environment
 | 
| -
 | 
| -Base class for construction Environments.  These are
 | 
| -the primary objects used to communicate dependency and
 | 
| -construction information to the build engine.
 | 
| -
 | 
| -Keyword arguments supplied when the construction Environment
 | 
| -is created are construction variables used to initialize the
 | 
| -Environment
 | 
| -"""
 | 
| -
 | 
| -#
 | 
| -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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.
 | 
| -#
 | 
| -
 | 
| -__revision__ = "src/engine/SCons/Environment.py 3603 2008/10/10 05:46:45 scons"
 | 
| -
 | 
| -
 | 
| -import copy
 | 
| -import os
 | 
| -import sys
 | 
| -import re
 | 
| -import shlex
 | 
| -import string
 | 
| -from UserDict import UserDict
 | 
| -
 | 
| -import SCons.Action
 | 
| -import SCons.Builder
 | 
| -from SCons.Debug import logInstanceCreation
 | 
| -import SCons.Defaults
 | 
| -import SCons.Errors
 | 
| -import SCons.Memoize
 | 
| -import SCons.Node
 | 
| -import SCons.Node.Alias
 | 
| -import SCons.Node.FS
 | 
| -import SCons.Node.Python
 | 
| -import SCons.Platform
 | 
| -import SCons.SConsign
 | 
| -import SCons.Subst
 | 
| -import SCons.Tool
 | 
| -import SCons.Util
 | 
| -import SCons.Warnings
 | 
| -
 | 
| -class _Null:
 | 
| -    pass
 | 
| -
 | 
| -_null = _Null
 | 
| -
 | 
| -_warn_copy_deprecated = True
 | 
| -_warn_source_signatures_deprecated = True
 | 
| -_warn_target_signatures_deprecated = True
 | 
| -
 | 
| -CleanTargets = {}
 | 
| -CalculatorArgs = {}
 | 
| -
 | 
| -semi_deepcopy = SCons.Util.semi_deepcopy
 | 
| -
 | 
| -# Pull UserError into the global name space for the benefit of
 | 
| -# Environment().SourceSignatures(), which has some import statements
 | 
| -# which seem to mess up its ability to reference SCons directly.
 | 
| -UserError = SCons.Errors.UserError
 | 
| -
 | 
| -def alias_builder(env, target, source):
 | 
| -    pass
 | 
| -
 | 
| -AliasBuilder = SCons.Builder.Builder(action = alias_builder,
 | 
| -                                     target_factory = SCons.Node.Alias.default_ans.Alias,
 | 
| -                                     source_factory = SCons.Node.FS.Entry,
 | 
| -                                     multi = 1,
 | 
| -                                     is_explicit = None,
 | 
| -                                     name='AliasBuilder')
 | 
| -
 | 
| -def apply_tools(env, tools, toolpath):
 | 
| -    # Store the toolpath in the Environment.
 | 
| -    if toolpath is not None:
 | 
| -        env['toolpath'] = toolpath
 | 
| -
 | 
| -    if not tools:
 | 
| -        return
 | 
| -    # Filter out null tools from the list.
 | 
| -    for tool in filter(None, tools):
 | 
| -        if SCons.Util.is_List(tool) or type(tool)==type(()):
 | 
| -            toolname = tool[0]
 | 
| -            toolargs = tool[1] # should be a dict of kw args
 | 
| -            tool = apply(env.Tool, [toolname], toolargs)
 | 
| -        else:
 | 
| -            env.Tool(tool)
 | 
| -
 | 
| -# These names are controlled by SCons; users should never set or override
 | 
| -# them.  This warning can optionally be turned off, but scons will still
 | 
| -# ignore the illegal variable names even if it's off.
 | 
| -reserved_construction_var_names = \
 | 
| -    ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']
 | 
| -
 | 
| -def copy_non_reserved_keywords(dict):
 | 
| -    result = semi_deepcopy(dict)
 | 
| -    for k in result.keys():
 | 
| -        if k in reserved_construction_var_names:
 | 
| -            SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning,
 | 
| -                                "Ignoring attempt to set reserved variable `%s'" % k)
 | 
| -            del result[k]
 | 
| -    return result
 | 
| -
 | 
| -def _set_reserved(env, key, value):
 | 
| -    msg = "Ignoring attempt to set reserved variable `%s'" % key
 | 
| -    SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg)
 | 
| -
 | 
| -def _set_BUILDERS(env, key, value):
 | 
| -    try:
 | 
| -        bd = env._dict[key]
 | 
| -        for k in bd.keys():
 | 
| -            del bd[k]
 | 
| -    except KeyError:
 | 
| -        bd = BuilderDict(kwbd, env)
 | 
| -        env._dict[key] = bd
 | 
| -    bd.update(value)
 | 
| -
 | 
| -def _del_SCANNERS(env, key):
 | 
| -    del env._dict[key]
 | 
| -    env.scanner_map_delete()
 | 
| -
 | 
| -def _set_SCANNERS(env, key, value):
 | 
| -    env._dict[key] = value
 | 
| -    env.scanner_map_delete()
 | 
| -
 | 
| -
 | 
| -
 | 
| -# The following is partly based on code in a comment added by Peter
 | 
| -# Shannon at the following page (there called the "transplant" class):
 | 
| -#
 | 
| -# ASPN : Python Cookbook : Dynamically added methods to a class
 | 
| -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732
 | 
| -#
 | 
| -# We had independently been using the idiom as BuilderWrapper, but
 | 
| -# factoring out the common parts into this base class, and making
 | 
| -# BuilderWrapper a subclass that overrides __call__() to enforce specific
 | 
| -# Builder calling conventions, simplified some of our higher-layer code.
 | 
| -
 | 
| -class MethodWrapper:
 | 
| -    """
 | 
| -    A generic Wrapper class that associates a method (which can
 | 
| -    actually be any callable) with an object.  As part of creating this
 | 
| -    MethodWrapper object an attribute with the specified (by default,
 | 
| -    the name of the supplied method) is added to the underlying object.
 | 
| -    When that new "method" is called, our __call__() method adds the
 | 
| -    object as the first argument, simulating the Python behavior of
 | 
| -    supplying "self" on method calls.
 | 
| -
 | 
| -    We hang on to the name by which the method was added to the underlying
 | 
| -    base class so that we can provide a method to "clone" ourselves onto
 | 
| -    a new underlying object being copied (without which we wouldn't need
 | 
| -    to save that info).
 | 
| -    """
 | 
| -    def __init__(self, object, method, name=None):
 | 
| -        if name is None:
 | 
| -            name = method.__name__
 | 
| -        self.object = object
 | 
| -        self.method = method
 | 
| -        self.name = name
 | 
| -        setattr(self.object, name, self)
 | 
| -
 | 
| -    def __call__(self, *args, **kwargs):
 | 
| -        nargs = (self.object,) + args
 | 
| -        return apply(self.method, nargs, kwargs)
 | 
| -
 | 
| -    def clone(self, new_object):
 | 
| -        """
 | 
| -        Returns an object that re-binds the underlying "method" to
 | 
| -        the specified new object.
 | 
| -        """
 | 
| -        return self.__class__(new_object, self.method, self.name)
 | 
| -
 | 
| -class BuilderWrapper(MethodWrapper):
 | 
| -    """
 | 
| -    A MethodWrapper subclass that that associates an environment with
 | 
| -    a Builder.
 | 
| -
 | 
| -    This mainly exists to wrap the __call__() function so that all calls
 | 
| -    to Builders can have their argument lists massaged in the same way
 | 
| -    (treat a lone argument as the source, treat two arguments as target
 | 
| -    then source, make sure both target and source are lists) without
 | 
| -    having to have cut-and-paste code to do it.
 | 
| -
 | 
| -    As a bit of obsessive backwards compatibility, we also intercept
 | 
| -    attempts to get or set the "env" or "builder" attributes, which were
 | 
| -    the names we used before we put the common functionality into the
 | 
| -    MethodWrapper base class.  We'll keep this around for a while in case
 | 
| -    people shipped Tool modules that reached into the wrapper (like the
 | 
| -    Tool/qt.py module does, or did).  There shouldn't be a lot attribute
 | 
| -    fetching or setting on these, so a little extra work shouldn't hurt.
 | 
| -    """
 | 
| -    def __call__(self, target=None, source=_null, *args, **kw):
 | 
| -        if source is _null:
 | 
| -            source = target
 | 
| -            target = None
 | 
| -        if not target is None and not SCons.Util.is_List(target):
 | 
| -            target = [target]
 | 
| -        if not source is None and not SCons.Util.is_List(source):
 | 
| -            source = [source]
 | 
| -        return apply(MethodWrapper.__call__, (self, target, source) + args, kw)
 | 
| -
 | 
| -    def __repr__(self):
 | 
| -        return '<BuilderWrapper %s>' % repr(self.name)
 | 
| -
 | 
| -    def __str__(self):
 | 
| -        return self.__repr__()
 | 
| -
 | 
| -    def __getattr__(self, name):
 | 
| -        if name == 'env':
 | 
| -            return self.object
 | 
| -        elif name == 'builder':
 | 
| -            return self.method
 | 
| -        else:
 | 
| -            raise AttributeError, name
 | 
| -
 | 
| -    def __setattr__(self, name, value):
 | 
| -        if name == 'env':
 | 
| -            self.object = value
 | 
| -        elif name == 'builder':
 | 
| -            self.method = value
 | 
| -        else:
 | 
| -            self.__dict__[name] = value
 | 
| -
 | 
| -    # This allows a Builder to be executed directly
 | 
| -    # through the Environment to which it's attached.
 | 
| -    # In practice, we shouldn't need this, because
 | 
| -    # builders actually get executed through a Node.
 | 
| -    # But we do have a unit test for this, and can't
 | 
| -    # yet rule out that it would be useful in the
 | 
| -    # future, so leave it for now.
 | 
| -    #def execute(self, **kw):
 | 
| -    #    kw['env'] = self.env
 | 
| -    #    apply(self.builder.execute, (), kw)
 | 
| -
 | 
| -class BuilderDict(UserDict):
 | 
| -    """This is a dictionary-like class used by an Environment to hold
 | 
| -    the Builders.  We need to do this because every time someone changes
 | 
| -    the Builders in the Environment's BUILDERS dictionary, we must
 | 
| -    update the Environment's attributes."""
 | 
| -    def __init__(self, dict, env):
 | 
| -        # Set self.env before calling the superclass initialization,
 | 
| -        # because it will end up calling our other methods, which will
 | 
| -        # need to point the values in this dictionary to self.env.
 | 
| -        self.env = env
 | 
| -        UserDict.__init__(self, dict)
 | 
| -
 | 
| -    def __semi_deepcopy__(self):
 | 
| -        return self.__class__(self.data, self.env)
 | 
| -
 | 
| -    def __setitem__(self, item, val):
 | 
| -        try:
 | 
| -            method = getattr(self.env, item).method
 | 
| -        except AttributeError:
 | 
| -            pass
 | 
| -        else:
 | 
| -            self.env.RemoveMethod(method)
 | 
| -        UserDict.__setitem__(self, item, val)
 | 
| -        BuilderWrapper(self.env, val, item)
 | 
| -
 | 
| -    def __delitem__(self, item):
 | 
| -        UserDict.__delitem__(self, item)
 | 
| -        delattr(self.env, item)
 | 
| -
 | 
| -    def update(self, dict):
 | 
| -        for i, v in dict.items():
 | 
| -            self.__setitem__(i, v)
 | 
| -
 | 
| -
 | 
| -
 | 
| -_is_valid_var = re.compile(r'[_a-zA-Z]\w*$')
 | 
| -
 | 
| -def is_valid_construction_var(varstr):
 | 
| -    """Return if the specified string is a legitimate construction
 | 
| -    variable.
 | 
| -    """
 | 
| -    return _is_valid_var.match(varstr)
 | 
| -
 | 
| -
 | 
| -
 | 
| -class SubstitutionEnvironment:
 | 
| -    """Base class for different flavors of construction environments.
 | 
| -
 | 
| -    This class contains a minimal set of methods that handle contruction
 | 
| -    variable expansion and conversion of strings to Nodes, which may or
 | 
| -    may not be actually useful as a stand-alone class.  Which methods
 | 
| -    ended up in this class is pretty arbitrary right now.  They're
 | 
| -    basically the ones which we've empirically determined are common to
 | 
| -    the different construction environment subclasses, and most of the
 | 
| -    others that use or touch the underlying dictionary of construction
 | 
| -    variables.
 | 
| -
 | 
| -    Eventually, this class should contain all the methods that we
 | 
| -    determine are necessary for a "minimal" interface to the build engine.
 | 
| -    A full "native Python" SCons environment has gotten pretty heavyweight
 | 
| -    with all of the methods and Tools and construction variables we've
 | 
| -    jammed in there, so it would be nice to have a lighter weight
 | 
| -    alternative for interfaces that don't need all of the bells and
 | 
| -    whistles.  (At some point, we'll also probably rename this class
 | 
| -    "Base," since that more reflects what we want this class to become,
 | 
| -    but because we've released comments that tell people to subclass
 | 
| -    Environment.Base to create their own flavors of construction
 | 
| -    environment, we'll save that for a future refactoring when this
 | 
| -    class actually becomes useful.)
 | 
| -    """
 | 
| -
 | 
| -    if SCons.Memoize.use_memoizer:
 | 
| -        __metaclass__ = SCons.Memoize.Memoized_Metaclass
 | 
| -
 | 
| -    def __init__(self, **kw):
 | 
| -        """Initialization of an underlying SubstitutionEnvironment class.
 | 
| -        """
 | 
| -        if __debug__: logInstanceCreation(self, 'Environment.SubstitutionEnvironment')
 | 
| -        self.fs = SCons.Node.FS.get_default_fs()
 | 
| -        self.ans = SCons.Node.Alias.default_ans
 | 
| -        self.lookup_list = SCons.Node.arg2nodes_lookups
 | 
| -        self._dict = kw.copy()
 | 
| -        self._init_special()
 | 
| -        self.added_methods = []
 | 
| -        #self._memo = {}
 | 
| -
 | 
| -    def _init_special(self):
 | 
| -        """Initial the dispatch tables for special handling of
 | 
| -        special construction variables."""
 | 
| -        self._special_del = {}
 | 
| -        self._special_del['SCANNERS'] = _del_SCANNERS
 | 
| -
 | 
| -        self._special_set = {}
 | 
| -        for key in reserved_construction_var_names:
 | 
| -            self._special_set[key] = _set_reserved
 | 
| -        self._special_set['BUILDERS'] = _set_BUILDERS
 | 
| -        self._special_set['SCANNERS'] = _set_SCANNERS
 | 
| -
 | 
| -        # Freeze the keys of self._special_set in a list for use by
 | 
| -        # methods that need to check.  (Empirically, list scanning has
 | 
| -        # gotten better than dict.has_key() in Python 2.5.)
 | 
| -        self._special_set_keys = self._special_set.keys()
 | 
| -
 | 
| -    def __cmp__(self, other):
 | 
| -        return cmp(self._dict, other._dict)
 | 
| -
 | 
| -    def __delitem__(self, key):
 | 
| -        special = self._special_del.get(key)
 | 
| -        if special:
 | 
| -            special(self, key)
 | 
| -        else:
 | 
| -            del self._dict[key]
 | 
| -
 | 
| -    def __getitem__(self, key):
 | 
| -        return self._dict[key]
 | 
| -
 | 
| -    def __setitem__(self, key, value):
 | 
| -        # This is heavily used.  This implementation is the best we have
 | 
| -        # according to the timings in bench/env.__setitem__.py.
 | 
| -        #
 | 
| -        # The "key in self._special_set_keys" test here seems to perform
 | 
| -        # pretty well for the number of keys we have.  A hard-coded
 | 
| -        # list works a little better in Python 2.5, but that has the
 | 
| -        # disadvantage of maybe getting out of sync if we ever add more
 | 
| -        # variable names.  Using self._special_set.has_key() works a
 | 
| -        # little better in Python 2.4, but is worse then this test.
 | 
| -        # So right now it seems like a good trade-off, but feel free to
 | 
| -        # revisit this with bench/env.__setitem__.py as needed (and
 | 
| -        # as newer versions of Python come out).
 | 
| -        if key in self._special_set_keys:
 | 
| -            self._special_set[key](self, key, value)
 | 
| -        else:
 | 
| -            # If we already have the entry, then it's obviously a valid
 | 
| -            # key and we don't need to check.  If we do check, using a
 | 
| -            # global, pre-compiled regular expression directly is more
 | 
| -            # efficient than calling another function or a method.
 | 
| -            if not self._dict.has_key(key) \
 | 
| -               and not _is_valid_var.match(key):
 | 
| -                    raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
 | 
| -            self._dict[key] = value
 | 
| -
 | 
| -    def get(self, key, default=None):
 | 
| -        "Emulates the get() method of dictionaries."""
 | 
| -        return self._dict.get(key, default)
 | 
| -
 | 
| -    def has_key(self, key):
 | 
| -        return self._dict.has_key(key)
 | 
| -
 | 
| -    def items(self):
 | 
| -        return self._dict.items()
 | 
| -
 | 
| -    def arg2nodes(self, args, node_factory=_null, lookup_list=_null, **kw):
 | 
| -        if node_factory is _null:
 | 
| -            node_factory = self.fs.File
 | 
| -        if lookup_list is _null:
 | 
| -            lookup_list = self.lookup_list
 | 
| -
 | 
| -        if not args:
 | 
| -            return []
 | 
| -
 | 
| -        args = SCons.Util.flatten(args)
 | 
| -
 | 
| -        nodes = []
 | 
| -        for v in args:
 | 
| -            if SCons.Util.is_String(v):
 | 
| -                n = None
 | 
| -                for l in lookup_list:
 | 
| -                    n = l(v)
 | 
| -                    if not n is None:
 | 
| -                        break
 | 
| -                if not n is None:
 | 
| -                    if SCons.Util.is_String(n):
 | 
| -                        # n = self.subst(n, raw=1, **kw)
 | 
| -                        kw['raw'] = 1
 | 
| -                        n = apply(self.subst, (n,), kw)
 | 
| -                        if node_factory:
 | 
| -                            n = node_factory(n)
 | 
| -                    if SCons.Util.is_List(n):
 | 
| -                        nodes.extend(n)
 | 
| -                    else:
 | 
| -                        nodes.append(n)
 | 
| -                elif node_factory:
 | 
| -                    # v = node_factory(self.subst(v, raw=1, **kw))
 | 
| -                    kw['raw'] = 1
 | 
| -                    v = node_factory(apply(self.subst, (v,), kw))
 | 
| -                    if SCons.Util.is_List(v):
 | 
| -                        nodes.extend(v)
 | 
| -                    else:
 | 
| -                        nodes.append(v)
 | 
| -            else:
 | 
| -                nodes.append(v)
 | 
| -
 | 
| -        return nodes
 | 
| -
 | 
| -    def gvars(self):
 | 
| -        return self._dict
 | 
| -
 | 
| -    def lvars(self):
 | 
| -        return {}
 | 
| -
 | 
| -    def subst(self, string, raw=0, target=None, source=None, conv=None):
 | 
| -        """Recursively interpolates construction variables from the
 | 
| -        Environment into the specified string, returning the expanded
 | 
| -        result.  Construction variables are specified by a $ prefix
 | 
| -        in the string and begin with an initial underscore or
 | 
| -        alphabetic character followed by any number of underscores
 | 
| -        or alphanumeric characters.  The construction variable names
 | 
| -        may be surrounded by curly braces to separate the name from
 | 
| -        trailing characters.
 | 
| -        """
 | 
| -        gvars = self.gvars()
 | 
| -        lvars = self.lvars()
 | 
| -        lvars['__env__'] = self
 | 
| -        return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv)
 | 
| -
 | 
| -    def subst_kw(self, kw, raw=0, target=None, source=None):
 | 
| -        nkw = {}
 | 
| -        for k, v in kw.items():
 | 
| -            k = self.subst(k, raw, target, source)
 | 
| -            if SCons.Util.is_String(v):
 | 
| -                v = self.subst(v, raw, target, source)
 | 
| -            nkw[k] = v
 | 
| -        return nkw
 | 
| -
 | 
| -    def subst_list(self, string, raw=0, target=None, source=None, conv=None):
 | 
| -        """Calls through to SCons.Subst.scons_subst_list().  See
 | 
| -        the documentation for that function."""
 | 
| -        gvars = self.gvars()
 | 
| -        lvars = self.lvars()
 | 
| -        lvars['__env__'] = self
 | 
| -        return SCons.Subst.scons_subst_list(string, self, raw, target, source, gvars, lvars, conv)
 | 
| -
 | 
| -    def subst_path(self, path, target=None, source=None):
 | 
| -        """Substitute a path list, turning EntryProxies into Nodes
 | 
| -        and leaving Nodes (and other objects) as-is."""
 | 
| -
 | 
| -        if not SCons.Util.is_List(path):
 | 
| -            path = [path]
 | 
| -
 | 
| -        def s(obj):
 | 
| -            """This is the "string conversion" routine that we have our
 | 
| -            substitutions use to return Nodes, not strings.  This relies
 | 
| -            on the fact that an EntryProxy object has a get() method that
 | 
| -            returns the underlying Node that it wraps, which is a bit of
 | 
| -            architectural dependence that we might need to break or modify
 | 
| -            in the future in response to additional requirements."""
 | 
| -            try:
 | 
| -                get = obj.get
 | 
| -            except AttributeError:
 | 
| -                obj = SCons.Util.to_String_for_subst(obj)
 | 
| -            else:
 | 
| -                obj = get()
 | 
| -            return obj
 | 
| -
 | 
| -        r = []
 | 
| -        for p in path:
 | 
| -            if SCons.Util.is_String(p):
 | 
| -                p = self.subst(p, target=target, source=source, conv=s)
 | 
| -                if SCons.Util.is_List(p):
 | 
| -                    if len(p) == 1:
 | 
| -                        p = p[0]
 | 
| -                    else:
 | 
| -                        # We have an object plus a string, or multiple
 | 
| -                        # objects that we need to smush together.  No choice
 | 
| -                        # but to make them into a string.
 | 
| -                        p = string.join(map(SCons.Util.to_String_for_subst, p), '')
 | 
| -            else:
 | 
| -                p = s(p)
 | 
| -            r.append(p)
 | 
| -        return r
 | 
| -
 | 
| -    subst_target_source = subst
 | 
| -
 | 
| -    def backtick(self, command):
 | 
| -        import subprocess
 | 
| -        # common arguments
 | 
| -        kw = { 'stdout' : subprocess.PIPE,
 | 
| -               'stderr' : subprocess.PIPE,
 | 
| -               'universal_newlines' : True,
 | 
| -             }
 | 
| -        # if the command is a list, assume it's been quoted
 | 
| -        # othewise force a shell
 | 
| -        if not SCons.Util.is_List(command): kw['shell'] = True
 | 
| -        # run constructed command
 | 
| -        #TODO(1.5) p = SCons.Action._subproc(self, command, **kw)
 | 
| -        p = apply(SCons.Action._subproc, (self, command), kw)
 | 
| -        out,err = p.communicate()
 | 
| -        status = p.wait()
 | 
| -        if err:
 | 
| -            sys.stderr.write(err)
 | 
| -        if status:
 | 
| -            raise OSError("'%s' exited %d" % (command, status))
 | 
| -        return out
 | 
| -
 | 
| -    def AddMethod(self, function, name=None):
 | 
| -        """
 | 
| -        Adds the specified function as a method of this construction
 | 
| -        environment with the specified name.  If the name is omitted,
 | 
| -        the default name is the name of the function itself.
 | 
| -        """
 | 
| -        method = MethodWrapper(self, function, name)
 | 
| -        self.added_methods.append(method)
 | 
| -
 | 
| -    def RemoveMethod(self, function):
 | 
| -        """
 | 
| -        Removes the specified function's MethodWrapper from the
 | 
| -        added_methods list, so we don't re-bind it when making a clone.
 | 
| -        """
 | 
| -        is_not_func = lambda dm, f=function: not dm.method is f
 | 
| -        self.added_methods = filter(is_not_func, self.added_methods)
 | 
| -
 | 
| -    def Override(self, overrides):
 | 
| -        """
 | 
| -        Produce a modified environment whose variables are overriden by
 | 
| -        the overrides dictionaries.  "overrides" is a dictionary that
 | 
| -        will override the variables of this environment.
 | 
| -
 | 
| -        This function is much more efficient than Clone() or creating
 | 
| -        a new Environment because it doesn't copy the construction
 | 
| -        environment dictionary, it just wraps the underlying construction
 | 
| -        environment, and doesn't even create a wrapper object if there
 | 
| -        are no overrides.
 | 
| -        """
 | 
| -        if not overrides: return self
 | 
| -        o = copy_non_reserved_keywords(overrides)
 | 
| -        if not o: return self
 | 
| -        overrides = {}
 | 
| -        merges = None
 | 
| -        for key, value in o.items():
 | 
| -            if key == 'parse_flags':
 | 
| -                merges = value
 | 
| -            else:
 | 
| -                overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
 | 
| -        env = OverrideEnvironment(self, overrides)
 | 
| -        if merges: env.MergeFlags(merges)
 | 
| -        return env
 | 
| -
 | 
| -    def ParseFlags(self, *flags):
 | 
| -        """
 | 
| -        Parse the set of flags and return a dict with the flags placed
 | 
| -        in the appropriate entry.  The flags are treated as a typical
 | 
| -        set of command-line flags for a GNU-like toolchain and used to
 | 
| -        populate the entries in the dict immediately below.  If one of
 | 
| -        the flag strings begins with a bang (exclamation mark), it is
 | 
| -        assumed to be a command and the rest of the string is executed;
 | 
| -        the result of that evaluation is then added to the dict.
 | 
| -        """
 | 
| -        dict = {
 | 
| -            'ASFLAGS'       : SCons.Util.CLVar(''),
 | 
| -            'CFLAGS'        : SCons.Util.CLVar(''),
 | 
| -            'CCFLAGS'       : SCons.Util.CLVar(''),
 | 
| -            'CPPDEFINES'    : [],
 | 
| -            'CPPFLAGS'      : SCons.Util.CLVar(''),
 | 
| -            'CPPPATH'       : [],
 | 
| -            'FRAMEWORKPATH' : SCons.Util.CLVar(''),
 | 
| -            'FRAMEWORKS'    : SCons.Util.CLVar(''),
 | 
| -            'LIBPATH'       : [],
 | 
| -            'LIBS'          : [],
 | 
| -            'LINKFLAGS'     : SCons.Util.CLVar(''),
 | 
| -            'RPATH'         : [],
 | 
| -        }
 | 
| -
 | 
| -        # The use of the "me" parameter to provide our own name for
 | 
| -        # recursion is an egregious hack to support Python 2.1 and before.
 | 
| -        def do_parse(arg, me, self = self, dict = dict):
 | 
| -            # if arg is a sequence, recurse with each element
 | 
| -            if not arg:
 | 
| -                return
 | 
| -
 | 
| -            if not SCons.Util.is_String(arg):
 | 
| -                for t in arg: me(t, me)
 | 
| -                return
 | 
| -
 | 
| -            # if arg is a command, execute it
 | 
| -            if arg[0] == '!':
 | 
| -                arg = self.backtick(arg[1:])
 | 
| -
 | 
| -            # utility function to deal with -D option
 | 
| -            def append_define(name, dict = dict):
 | 
| -                t = string.split(name, '=')
 | 
| -                if len(t) == 1:
 | 
| -                    dict['CPPDEFINES'].append(name)
 | 
| -                else:
 | 
| -                    dict['CPPDEFINES'].append([t[0], string.join(t[1:], '=')])
 | 
| -
 | 
| -            # Loop through the flags and add them to the appropriate option.
 | 
| -            # This tries to strike a balance between checking for all possible
 | 
| -            # flags and keeping the logic to a finite size, so it doesn't
 | 
| -            # check for some that don't occur often.  It particular, if the
 | 
| -            # flag is not known to occur in a config script and there's a way
 | 
| -            # of passing the flag to the right place (by wrapping it in a -W
 | 
| -            # flag, for example) we don't check for it.  Note that most
 | 
| -            # preprocessor options are not handled, since unhandled options
 | 
| -            # are placed in CCFLAGS, so unless the preprocessor is invoked
 | 
| -            # separately, these flags will still get to the preprocessor.
 | 
| -            # Other options not currently handled:
 | 
| -            #  -iqoutedir      (preprocessor search path)
 | 
| -            #  -u symbol       (linker undefined symbol)
 | 
| -            #  -s              (linker strip files)
 | 
| -            #  -static*        (linker static binding)
 | 
| -            #  -shared*        (linker dynamic binding)
 | 
| -            #  -symbolic       (linker global binding)
 | 
| -            #  -R dir          (deprecated linker rpath)
 | 
| -            # IBM compilers may also accept -qframeworkdir=foo
 | 
| -    
 | 
| -            params = shlex.split(arg)
 | 
| -            append_next_arg_to = None   # for multi-word args
 | 
| -            for arg in params:
 | 
| -                if append_next_arg_to:
 | 
| -                   if append_next_arg_to == 'CPPDEFINES':
 | 
| -                       append_define(arg)
 | 
| -                   elif append_next_arg_to == '-include':
 | 
| -                       t = ('-include', self.fs.File(arg))
 | 
| -                       dict['CCFLAGS'].append(t)
 | 
| -                   elif append_next_arg_to == '-isysroot':
 | 
| -                       t = ('-isysroot', arg)
 | 
| -                       dict['CCFLAGS'].append(t)
 | 
| -                       dict['LINKFLAGS'].append(t)
 | 
| -                   elif append_next_arg_to == '-arch':
 | 
| -                       t = ('-arch', arg)
 | 
| -                       dict['CCFLAGS'].append(t)
 | 
| -                       dict['LINKFLAGS'].append(t)
 | 
| -                   else:
 | 
| -                       dict[append_next_arg_to].append(arg)
 | 
| -                   append_next_arg_to = None
 | 
| -                elif not arg[0] in ['-', '+']:
 | 
| -                    dict['LIBS'].append(self.fs.File(arg))
 | 
| -                elif arg[:2] == '-L':
 | 
| -                    if arg[2:]:
 | 
| -                        dict['LIBPATH'].append(arg[2:])
 | 
| -                    else:
 | 
| -                        append_next_arg_to = 'LIBPATH'
 | 
| -                elif arg[:2] == '-l':
 | 
| -                    if arg[2:]:
 | 
| -                        dict['LIBS'].append(arg[2:])
 | 
| -                    else:
 | 
| -                        append_next_arg_to = 'LIBS'
 | 
| -                elif arg[:2] == '-I':
 | 
| -                    if arg[2:]:
 | 
| -                        dict['CPPPATH'].append(arg[2:])
 | 
| -                    else:
 | 
| -                        append_next_arg_to = 'CPPPATH'
 | 
| -                elif arg[:4] == '-Wa,':
 | 
| -                    dict['ASFLAGS'].append(arg[4:])
 | 
| -                    dict['CCFLAGS'].append(arg)
 | 
| -                elif arg[:4] == '-Wl,':
 | 
| -                    if arg[:11] == '-Wl,-rpath=':
 | 
| -                        dict['RPATH'].append(arg[11:])
 | 
| -                    elif arg[:7] == '-Wl,-R,':
 | 
| -                        dict['RPATH'].append(arg[7:])
 | 
| -                    elif arg[:6] == '-Wl,-R':
 | 
| -                        dict['RPATH'].append(arg[6:])
 | 
| -                    else:
 | 
| -                        dict['LINKFLAGS'].append(arg)
 | 
| -                elif arg[:4] == '-Wp,':
 | 
| -                    dict['CPPFLAGS'].append(arg)
 | 
| -                elif arg[:2] == '-D':
 | 
| -                    if arg[2:]:
 | 
| -                        append_define(arg[2:])
 | 
| -                    else:
 | 
| -                        append_next_arg_to = 'CPPDEFINES'
 | 
| -                elif arg == '-framework':
 | 
| -                    append_next_arg_to = 'FRAMEWORKS'
 | 
| -                elif arg[:14] == '-frameworkdir=':
 | 
| -                    dict['FRAMEWORKPATH'].append(arg[14:])
 | 
| -                elif arg[:2] == '-F':
 | 
| -                    if arg[2:]:
 | 
| -                        dict['FRAMEWORKPATH'].append(arg[2:])
 | 
| -                    else:
 | 
| -                        append_next_arg_to = 'FRAMEWORKPATH'
 | 
| -                elif arg == '-mno-cygwin':
 | 
| -                    dict['CCFLAGS'].append(arg)
 | 
| -                    dict['LINKFLAGS'].append(arg)
 | 
| -                elif arg == '-mwindows':
 | 
| -                    dict['LINKFLAGS'].append(arg)
 | 
| -                elif arg == '-pthread':
 | 
| -                    dict['CCFLAGS'].append(arg)
 | 
| -                    dict['LINKFLAGS'].append(arg)
 | 
| -                elif arg[:5] == '-std=':
 | 
| -                    dict['CFLAGS'].append(arg) # C only
 | 
| -                elif arg[0] == '+':
 | 
| -                    dict['CCFLAGS'].append(arg)
 | 
| -                    dict['LINKFLAGS'].append(arg)
 | 
| -                elif arg in ['-include', '-isysroot', '-arch']:
 | 
| -                    append_next_arg_to = arg
 | 
| -                else:
 | 
| -                    dict['CCFLAGS'].append(arg)
 | 
| -    
 | 
| -        for arg in flags:
 | 
| -            do_parse(arg, do_parse)
 | 
| -        return dict
 | 
| -
 | 
| -    def MergeFlags(self, args, unique=1, dict=None):
 | 
| -        """
 | 
| -        Merge the dict in args into the construction variables of this
 | 
| -        env, or the passed-in dict.  If args is not a dict, it is
 | 
| -        converted into a dict using ParseFlags.  If unique is not set,
 | 
| -        the flags are appended rather than merged.
 | 
| -        """
 | 
| -
 | 
| -        if dict is None:
 | 
| -            dict = self
 | 
| -        if not SCons.Util.is_Dict(args):
 | 
| -            args = self.ParseFlags(args)
 | 
| -        if not unique:
 | 
| -            apply(self.Append, (), args)
 | 
| -            return self
 | 
| -        for key, value in args.items():
 | 
| -            if not value:
 | 
| -                continue
 | 
| -            try:
 | 
| -                orig = self[key]
 | 
| -            except KeyError:
 | 
| -                orig = value
 | 
| -            else:
 | 
| -                if not orig:
 | 
| -                    orig = value
 | 
| -                elif value:
 | 
| -                    # Add orig and value.  The logic here was lifted from
 | 
| -                    # part of env.Append() (see there for a lot of comments
 | 
| -                    # about the order in which things are tried) and is
 | 
| -                    # used mainly to handle coercion of strings to CLVar to
 | 
| -                    # "do the right thing" given (e.g.) an original CCFLAGS
 | 
| -                    # string variable like '-pipe -Wall'.
 | 
| -                    try:
 | 
| -                        orig = orig + value
 | 
| -                    except (KeyError, TypeError):
 | 
| -                        try:
 | 
| -                            add_to_orig = orig.append
 | 
| -                        except AttributeError:
 | 
| -                            value.insert(0, orig)
 | 
| -                            orig = value
 | 
| -                        else:
 | 
| -                            add_to_orig(value)
 | 
| -            t = []
 | 
| -            if key[-4:] == 'PATH':
 | 
| -                ### keep left-most occurence
 | 
| -                for v in orig:
 | 
| -                    if v not in t:
 | 
| -                        t.append(v)
 | 
| -            else:
 | 
| -                ### keep right-most occurence
 | 
| -                orig.reverse()
 | 
| -                for v in orig:
 | 
| -                    if v not in t:
 | 
| -                        t.insert(0, v)
 | 
| -            self[key] = t
 | 
| -        return self
 | 
| -
 | 
| -#     def MergeShellPaths(self, args, prepend=1):
 | 
| -#         """
 | 
| -#         Merge the dict in args into the shell environment in env['ENV'].  
 | 
| -#         Shell path elements are appended or prepended according to prepend.
 | 
| -
 | 
| -#         Uses Pre/AppendENVPath, so it always appends or prepends uniquely.
 | 
| -
 | 
| -#         Example: env.MergeShellPaths({'LIBPATH': '/usr/local/lib'})
 | 
| -#         prepends /usr/local/lib to env['ENV']['LIBPATH'].
 | 
| -#         """
 | 
| -
 | 
| -#         for pathname, pathval in args.items():
 | 
| -#             if not pathval:
 | 
| -#                 continue
 | 
| -#             if prepend:
 | 
| -#                 apply(self.PrependENVPath, (pathname, pathval))
 | 
| -#             else:
 | 
| -#                 apply(self.AppendENVPath, (pathname, pathval))
 | 
| -
 | 
| -
 | 
| -# Used by the FindSourceFiles() method, below.
 | 
| -# Stuck here for support of pre-2.2 Python versions.
 | 
| -def build_source(ss, result):
 | 
| -    for s in ss:
 | 
| -        if isinstance(s, SCons.Node.FS.Dir):
 | 
| -            build_source(s.all_children(), result)
 | 
| -        elif s.has_builder():
 | 
| -            build_source(s.sources, result)
 | 
| -        elif isinstance(s.disambiguate(), SCons.Node.FS.File):
 | 
| -            result.append(s)
 | 
| -
 | 
| -def default_decide_source(dependency, target, prev_ni):
 | 
| -    f = SCons.Defaults.DefaultEnvironment().decide_source
 | 
| -    return f(dependency, target, prev_ni)
 | 
| -
 | 
| -def default_decide_target(dependency, target, prev_ni):
 | 
| -    f = SCons.Defaults.DefaultEnvironment().decide_target
 | 
| -    return f(dependency, target, prev_ni)
 | 
| -
 | 
| -def default_copy_from_cache(src, dst):
 | 
| -    f = SCons.Defaults.DefaultEnvironment().copy_from_cache
 | 
| -    return f(src, dst)
 | 
| -
 | 
| -class Base(SubstitutionEnvironment):
 | 
| -    """Base class for "real" construction Environments.  These are the
 | 
| -    primary objects used to communicate dependency and construction
 | 
| -    information to the build engine.
 | 
| -
 | 
| -    Keyword arguments supplied when the construction Environment
 | 
| -    is created are construction variables used to initialize the
 | 
| -    Environment.
 | 
| -    """
 | 
| -
 | 
| -    if SCons.Memoize.use_memoizer:
 | 
| -        __metaclass__ = SCons.Memoize.Memoized_Metaclass
 | 
| -
 | 
| -    memoizer_counters = []
 | 
| -
 | 
| -    #######################################################################
 | 
| -    # This is THE class for interacting with the SCons build engine,
 | 
| -    # and it contains a lot of stuff, so we're going to try to keep this
 | 
| -    # a little organized by grouping the methods.
 | 
| -    #######################################################################
 | 
| -
 | 
| -    #######################################################################
 | 
| -    # Methods that make an Environment act like a dictionary.  These have
 | 
| -    # the expected standard names for Python mapping objects.  Note that
 | 
| -    # we don't actually make an Environment a subclass of UserDict for
 | 
| -    # performance reasons.  Note also that we only supply methods for
 | 
| -    # dictionary functionality that we actually need and use.
 | 
| -    #######################################################################
 | 
| -
 | 
| -    def __init__(self,
 | 
| -                 platform=None,
 | 
| -                 tools=None,
 | 
| -                 toolpath=None,
 | 
| -                 variables=None,
 | 
| -                 parse_flags = None,
 | 
| -                 **kw):
 | 
| -        """
 | 
| -        Initialization of a basic SCons construction environment,
 | 
| -        including setting up special construction variables like BUILDER,
 | 
| -        PLATFORM, etc., and searching for and applying available Tools.
 | 
| -
 | 
| -        Note that we do *not* call the underlying base class
 | 
| -        (SubsitutionEnvironment) initialization, because we need to
 | 
| -        initialize things in a very specific order that doesn't work
 | 
| -        with the much simpler base class initialization.
 | 
| -        """
 | 
| -        if __debug__: logInstanceCreation(self, 'Environment.Base')
 | 
| -        self._memo = {}
 | 
| -        self.fs = SCons.Node.FS.get_default_fs()
 | 
| -        self.ans = SCons.Node.Alias.default_ans
 | 
| -        self.lookup_list = SCons.Node.arg2nodes_lookups
 | 
| -        self._dict = semi_deepcopy(SCons.Defaults.ConstructionEnvironment)
 | 
| -        self._init_special()
 | 
| -        self.added_methods = []
 | 
| -
 | 
| -        # We don't use AddMethod, or define these as methods in this
 | 
| -        # class, because we *don't* want these functions to be bound
 | 
| -        # methods.  They need to operate independently so that the
 | 
| -        # settings will work properly regardless of whether a given
 | 
| -        # target ends up being built with a Base environment or an
 | 
| -        # OverrideEnvironment or what have you.
 | 
| -        self.decide_target = default_decide_target
 | 
| -        self.decide_source = default_decide_source
 | 
| -
 | 
| -        self.copy_from_cache = default_copy_from_cache
 | 
| -
 | 
| -        self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
 | 
| -
 | 
| -        if platform is None:
 | 
| -            platform = self._dict.get('PLATFORM', None)
 | 
| -            if platform is None:
 | 
| -                platform = SCons.Platform.Platform()
 | 
| -        if SCons.Util.is_String(platform):
 | 
| -            platform = SCons.Platform.Platform(platform)
 | 
| -        self._dict['PLATFORM'] = str(platform)
 | 
| -        platform(self)
 | 
| -
 | 
| -        # Apply the passed-in and customizable variables to the
 | 
| -        # environment before calling the tools, because they may use
 | 
| -        # some of them during initialization.
 | 
| -        if kw.has_key('options'):
 | 
| -            # Backwards compatibility:  they may stll be using the
 | 
| -            # old "options" keyword.
 | 
| -            variables = kw['options']
 | 
| -            del kw['options']
 | 
| -        apply(self.Replace, (), kw)
 | 
| -        keys = kw.keys()
 | 
| -        if variables:
 | 
| -            keys = keys + variables.keys()
 | 
| -            variables.Update(self)
 | 
| -
 | 
| -        save = {}
 | 
| -        for k in keys:
 | 
| -            try:
 | 
| -                save[k] = self._dict[k]
 | 
| -            except KeyError:
 | 
| -                # No value may have been set if they tried to pass in a
 | 
| -                # reserved variable name like TARGETS.
 | 
| -                pass
 | 
| -
 | 
| -        SCons.Tool.Initializers(self)
 | 
| -
 | 
| -        if tools is None:
 | 
| -            tools = self._dict.get('TOOLS', None)
 | 
| -            if tools is None:
 | 
| -                tools = ['default']
 | 
| -        apply_tools(self, tools, toolpath)
 | 
| -
 | 
| -        # Now restore the passed-in and customized variables
 | 
| -        # to the environment, since the values the user set explicitly
 | 
| -        # should override any values set by the tools.
 | 
| -        for key, val in save.items():
 | 
| -            self._dict[key] = val
 | 
| -
 | 
| -        # Finally, apply any flags to be merged in
 | 
| -        if parse_flags: self.MergeFlags(parse_flags)
 | 
| -
 | 
| -    #######################################################################
 | 
| -    # Utility methods that are primarily for internal use by SCons.
 | 
| -    # These begin with lower-case letters.
 | 
| -    #######################################################################
 | 
| -
 | 
| -    def get_builder(self, name):
 | 
| -        """Fetch the builder with the specified name from the environment.
 | 
| -        """
 | 
| -        try:
 | 
| -            return self._dict['BUILDERS'][name]
 | 
| -        except KeyError:
 | 
| -            return None
 | 
| -
 | 
| -    def get_CacheDir(self):
 | 
| -        try:
 | 
| -            path = self._CacheDir_path
 | 
| -        except AttributeError:
 | 
| -            path = SCons.Defaults.DefaultEnvironment()._CacheDir_path
 | 
| -        try:
 | 
| -            if path == self._last_CacheDir_path:
 | 
| -                return self._last_CacheDir
 | 
| -        except AttributeError:
 | 
| -            pass
 | 
| -        cd = SCons.CacheDir.CacheDir(path)
 | 
| -        self._last_CacheDir_path = path
 | 
| -        self._last_CacheDir = cd
 | 
| -        return cd
 | 
| -
 | 
| -    def get_factory(self, factory, default='File'):
 | 
| -        """Return a factory function for creating Nodes for this
 | 
| -        construction environment.
 | 
| -        """
 | 
| -        name = default
 | 
| -        try:
 | 
| -            is_node = issubclass(factory, SCons.Node.Node)
 | 
| -        except TypeError:
 | 
| -            # The specified factory isn't a Node itself--it's
 | 
| -            # most likely None, or possibly a callable.
 | 
| -            pass
 | 
| -        else:
 | 
| -            if is_node:
 | 
| -                # The specified factory is a Node (sub)class.  Try to
 | 
| -                # return the FS method that corresponds to the Node's
 | 
| -                # name--that is, we return self.fs.Dir if they want a Dir,
 | 
| -                # self.fs.File for a File, etc.
 | 
| -                try: name = factory.__name__
 | 
| -                except AttributeError: pass
 | 
| -                else: factory = None
 | 
| -        if not factory:
 | 
| -            # They passed us None, or we picked up a name from a specified
 | 
| -            # class, so return the FS method.  (Note that we *don't*
 | 
| -            # use our own self.{Dir,File} methods because that would
 | 
| -            # cause env.subst() to be called twice on the file name,
 | 
| -            # interfering with files that have $$ in them.)
 | 
| -            factory = getattr(self.fs, name)
 | 
| -        return factory
 | 
| -
 | 
| -    memoizer_counters.append(SCons.Memoize.CountValue('_gsm'))
 | 
| -
 | 
| -    def _gsm(self):
 | 
| -        try:
 | 
| -            return self._memo['_gsm']
 | 
| -        except KeyError:
 | 
| -            pass
 | 
| -
 | 
| -        result = {}
 | 
| -
 | 
| -        try:
 | 
| -            scanners = self._dict['SCANNERS']
 | 
| -        except KeyError:
 | 
| -            pass
 | 
| -        else:
 | 
| -            # Reverse the scanner list so that, if multiple scanners
 | 
| -            # claim they can scan the same suffix, earlier scanners
 | 
| -            # in the list will overwrite later scanners, so that
 | 
| -            # the result looks like a "first match" to the user.
 | 
| -            if not SCons.Util.is_List(scanners):
 | 
| -                scanners = [scanners]
 | 
| -            else:
 | 
| -                scanners = scanners[:] # copy so reverse() doesn't mod original
 | 
| -            scanners.reverse()
 | 
| -            for scanner in scanners:
 | 
| -                for k in scanner.get_skeys(self):
 | 
| -                    result[k] = scanner
 | 
| -
 | 
| -        self._memo['_gsm'] = result
 | 
| -
 | 
| -        return result
 | 
| -
 | 
| -    def get_scanner(self, skey):
 | 
| -        """Find the appropriate scanner given a key (usually a file suffix).
 | 
| -        """
 | 
| -        return self._gsm().get(skey)
 | 
| -
 | 
| -    def scanner_map_delete(self, kw=None):
 | 
| -        """Delete the cached scanner map (if we need to).
 | 
| -        """
 | 
| -        try:
 | 
| -            del self._memo['_gsm']
 | 
| -        except KeyError:
 | 
| -            pass
 | 
| -
 | 
| -    def _update(self, dict):
 | 
| -        """Update an environment's values directly, bypassing the normal
 | 
| -        checks that occur when users try to set items.
 | 
| -        """
 | 
| -        self._dict.update(dict)
 | 
| -
 | 
| -    def get_src_sig_type(self):
 | 
| -        try:
 | 
| -            return self.src_sig_type
 | 
| -        except AttributeError:
 | 
| -            t = SCons.Defaults.DefaultEnvironment().src_sig_type
 | 
| -            self.src_sig_type = t
 | 
| -            return t
 | 
| -
 | 
| -    def get_tgt_sig_type(self):
 | 
| -        try:
 | 
| -            return self.tgt_sig_type
 | 
| -        except AttributeError:
 | 
| -            t = SCons.Defaults.DefaultEnvironment().tgt_sig_type
 | 
| -            self.tgt_sig_type = t
 | 
| -            return t
 | 
| -
 | 
| -    #######################################################################
 | 
| -    # Public methods for manipulating an Environment.  These begin with
 | 
| -    # upper-case letters.  The essential characteristic of methods in
 | 
| -    # this section is that they do *not* have corresponding same-named
 | 
| -    # global functions.  For example, a stand-alone Append() function
 | 
| -    # makes no sense, because Append() is all about appending values to
 | 
| -    # an Environment's construction variables.
 | 
| -    #######################################################################
 | 
| -
 | 
| -    def Append(self, **kw):
 | 
| -        """Append values to existing construction variables
 | 
| -        in an Environment.
 | 
| -        """
 | 
| -        kw = copy_non_reserved_keywords(kw)
 | 
| -        for key, val in kw.items():
 | 
| -            # It would be easier on the eyes to write this using
 | 
| -            # "continue" statements whenever we finish processing an item,
 | 
| -            # but Python 1.5.2 apparently doesn't let you use "continue"
 | 
| -            # within try:-except: blocks, so we have to nest our code.
 | 
| -            try:
 | 
| -                orig = self._dict[key]
 | 
| -            except KeyError:
 | 
| -                # No existing variable in the environment, so just set
 | 
| -                # it to the new value.
 | 
| -                self._dict[key] = val
 | 
| -            else:
 | 
| -                try:
 | 
| -                    # Check if the original looks like a dictionary.
 | 
| -                    # If it is, we can't just try adding the value because
 | 
| -                    # dictionaries don't have __add__() methods, and
 | 
| -                    # things like UserList will incorrectly coerce the
 | 
| -                    # original dict to a list (which we don't want).
 | 
| -                    update_dict = orig.update
 | 
| -                except AttributeError:
 | 
| -                    try:
 | 
| -                        # Most straightforward:  just try to add them
 | 
| -                        # together.  This will work in most cases, when the
 | 
| -                        # original and new values are of compatible types.
 | 
| -                        self._dict[key] = orig + val
 | 
| -                    except (KeyError, TypeError):
 | 
| -                        try:
 | 
| -                            # Check if the original is a list.
 | 
| -                            add_to_orig = orig.append
 | 
| -                        except AttributeError:
 | 
| -                            # The original isn't a list, but the new
 | 
| -                            # value is (by process of elimination),
 | 
| -                            # so insert the original in the new value
 | 
| -                            # (if there's one to insert) and replace
 | 
| -                            # the variable with it.
 | 
| -                            if orig:
 | 
| -                                val.insert(0, orig)
 | 
| -                            self._dict[key] = val
 | 
| -                        else:
 | 
| -                            # The original is a list, so append the new
 | 
| -                            # value to it (if there's a value to append).
 | 
| -                            if val:
 | 
| -                                add_to_orig(val)
 | 
| -                else:
 | 
| -                    # The original looks like a dictionary, so update it
 | 
| -                    # based on what we think the value looks like.
 | 
| -                    if SCons.Util.is_List(val):
 | 
| -                        for v in val:
 | 
| -                            orig[v] = None
 | 
| -                    else:
 | 
| -                        try:
 | 
| -                            update_dict(val)
 | 
| -                        except (AttributeError, TypeError, ValueError):
 | 
| -                            if SCons.Util.is_Dict(val):
 | 
| -                                for k, v in val.items():
 | 
| -                                    orig[k] = v
 | 
| -                            else:
 | 
| -                                orig[val] = None
 | 
| -        self.scanner_map_delete(kw)
 | 
| -
 | 
| -    def AppendENVPath(self, name, newpath, envname = 'ENV', 
 | 
| -                      sep = os.pathsep, delete_existing=1):
 | 
| -        """Append path elements to the path 'name' in the 'ENV'
 | 
| -        dictionary for this environment.  Will only add any particular
 | 
| -        path once, and will normpath and normcase all paths to help
 | 
| -        assure this.  This can also handle the case where the env
 | 
| -        variable is a list instead of a string.
 | 
| -
 | 
| -        If delete_existing is 0, a newpath which is already in the path
 | 
| -        will not be moved to the end (it will be left where it is).
 | 
| -        """
 | 
| -
 | 
| -        orig = ''
 | 
| -        if self._dict.has_key(envname) and self._dict[envname].has_key(name):
 | 
| -            orig = self._dict[envname][name]
 | 
| -
 | 
| -        nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing)
 | 
| -
 | 
| -        if not self._dict.has_key(envname):
 | 
| -            self._dict[envname] = {}
 | 
| -
 | 
| -        self._dict[envname][name] = nv
 | 
| -
 | 
| -    def AppendUnique(self, delete_existing=0, **kw):
 | 
| -        """Append values to existing construction variables
 | 
| -        in an Environment, if they're not already there.
 | 
| -        If delete_existing is 1, removes existing values first, so
 | 
| -        values move to end.
 | 
| -        """
 | 
| -        kw = copy_non_reserved_keywords(kw)
 | 
| -        for key, val in kw.items():
 | 
| -            if not self._dict.has_key(key) or self._dict[key] in ('', None):
 | 
| -                self._dict[key] = val
 | 
| -            elif SCons.Util.is_Dict(self._dict[key]) and \
 | 
| -                 SCons.Util.is_Dict(val):
 | 
| -                self._dict[key].update(val)
 | 
| -            elif SCons.Util.is_List(val):
 | 
| -                dk = self._dict[key]
 | 
| -                if not SCons.Util.is_List(dk):
 | 
| -                    dk = [dk]
 | 
| -                if delete_existing:
 | 
| -                    dk = filter(lambda x, val=val: x not in val, dk)
 | 
| -                else:
 | 
| -                    val = filter(lambda x, dk=dk: x not in dk, val)
 | 
| -                self._dict[key] = dk + val
 | 
| -            else:
 | 
| -                dk = self._dict[key]
 | 
| -                if SCons.Util.is_List(dk):
 | 
| -                    # By elimination, val is not a list.  Since dk is a
 | 
| -                    # list, wrap val in a list first.
 | 
| -                    if delete_existing:
 | 
| -                        dk = filter(lambda x, val=val: x not in val, dk)
 | 
| -                        self._dict[key] = dk + [val]
 | 
| -                    else:
 | 
| -                        if not val in dk:
 | 
| -                            self._dict[key] = dk + [val]
 | 
| -                else:
 | 
| -                    if delete_existing:
 | 
| -                        dk = filter(lambda x, val=val: x not in val, dk)
 | 
| -                    self._dict[key] = dk + val
 | 
| -        self.scanner_map_delete(kw)
 | 
| -
 | 
| -    def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw):
 | 
| -        """Return a copy of a construction Environment.  The
 | 
| -        copy is like a Python "deep copy"--that is, independent
 | 
| -        copies are made recursively of each objects--except that
 | 
| -        a reference is copied when an object is not deep-copyable
 | 
| -        (like a function).  There are no references to any mutable
 | 
| -        objects in the original Environment.
 | 
| -        """
 | 
| -        clone = copy.copy(self)
 | 
| -        clone._dict = semi_deepcopy(self._dict)
 | 
| -
 | 
| -        try:
 | 
| -            cbd = clone._dict['BUILDERS']
 | 
| -        except KeyError:
 | 
| -            pass
 | 
| -        else:
 | 
| -            clone._dict['BUILDERS'] = BuilderDict(cbd, clone)
 | 
| -
 | 
| -        # Check the methods added via AddMethod() and re-bind them to
 | 
| -        # the cloned environment.  Only do this if the attribute hasn't
 | 
| -        # been overwritten by the user explicitly and still points to
 | 
| -        # the added method.
 | 
| -        clone.added_methods = []
 | 
| -        for mw in self.added_methods:
 | 
| -            if mw == getattr(self, mw.name):
 | 
| -                clone.added_methods.append(mw.clone(clone))
 | 
| -
 | 
| -        clone._memo = {}
 | 
| -
 | 
| -        # Apply passed-in variables before the tools
 | 
| -        # so the tools can use the new variables
 | 
| -        kw = copy_non_reserved_keywords(kw)
 | 
| -        new = {}
 | 
| -        for key, value in kw.items():
 | 
| -            new[key] = SCons.Subst.scons_subst_once(value, self, key)
 | 
| -        apply(clone.Replace, (), new)
 | 
| -
 | 
| -        apply_tools(clone, tools, toolpath)
 | 
| -
 | 
| -        # apply them again in case the tools overwrote them
 | 
| -        apply(clone.Replace, (), new)        
 | 
| -
 | 
| -        # Finally, apply any flags to be merged in
 | 
| -        if parse_flags: clone.MergeFlags(parse_flags)
 | 
| -
 | 
| -        if __debug__: logInstanceCreation(self, 'Environment.EnvironmentClone')
 | 
| -        return clone
 | 
| -
 | 
| -    def Copy(self, *args, **kw):
 | 
| -        global _warn_copy_deprecated
 | 
| -        if _warn_copy_deprecated:
 | 
| -            msg = "The env.Copy() method is deprecated; use the env.Clone() method instead."
 | 
| -            SCons.Warnings.warn(SCons.Warnings.DeprecatedCopyWarning, msg)
 | 
| -            _warn_copy_deprecated = False
 | 
| -        return apply(self.Clone, args, kw)
 | 
| -
 | 
| -    def _changed_build(self, dependency, target, prev_ni):
 | 
| -        if dependency.changed_state(target, prev_ni):
 | 
| -            return 1
 | 
| -        return self.decide_source(dependency, target, prev_ni)
 | 
| -
 | 
| -    def _changed_content(self, dependency, target, prev_ni):
 | 
| -        return dependency.changed_content(target, prev_ni)
 | 
| -
 | 
| -    def _changed_source(self, dependency, target, prev_ni):
 | 
| -        target_env = dependency.get_build_env()
 | 
| -        type = target_env.get_tgt_sig_type()
 | 
| -        if type == 'source':
 | 
| -            return target_env.decide_source(dependency, target, prev_ni)
 | 
| -        else:
 | 
| -            return target_env.decide_target(dependency, target, prev_ni)
 | 
| -
 | 
| -    def _changed_timestamp_then_content(self, dependency, target, prev_ni):
 | 
| -        return dependency.changed_timestamp_then_content(target, prev_ni)
 | 
| -
 | 
| -    def _changed_timestamp_newer(self, dependency, target, prev_ni):
 | 
| -        return dependency.changed_timestamp_newer(target, prev_ni)
 | 
| -
 | 
| -    def _changed_timestamp_match(self, dependency, target, prev_ni):
 | 
| -        return dependency.changed_timestamp_match(target, prev_ni)
 | 
| -
 | 
| -    def _copy_from_cache(self, src, dst):
 | 
| -        return self.fs.copy(src, dst)
 | 
| -
 | 
| -    def _copy2_from_cache(self, src, dst):
 | 
| -        return self.fs.copy2(src, dst)
 | 
| -
 | 
| -    def Decider(self, function):
 | 
| -        copy_function = self._copy2_from_cache
 | 
| -        if function in ('MD5', 'content'):
 | 
| -            if not SCons.Util.md5:
 | 
| -                raise UserError, "MD5 signatures are not available in this version of Python."
 | 
| -            function = self._changed_content
 | 
| -        elif function == 'MD5-timestamp':
 | 
| -            function = self._changed_timestamp_then_content
 | 
| -        elif function in ('timestamp-newer', 'make'):
 | 
| -            function = self._changed_timestamp_newer
 | 
| -            copy_function = self._copy_from_cache
 | 
| -        elif function == 'timestamp-match':
 | 
| -            function = self._changed_timestamp_match
 | 
| -        elif not callable(function):
 | 
| -            raise UserError, "Unknown Decider value %s" % repr(function)
 | 
| -
 | 
| -        # We don't use AddMethod because we don't want to turn the
 | 
| -        # function, which only expects three arguments, into a bound
 | 
| -        # method, which would add self as an initial, fourth argument.
 | 
| -        self.decide_target = function
 | 
| -        self.decide_source = function
 | 
| -
 | 
| -        self.copy_from_cache = copy_function
 | 
| -
 | 
| -    def Detect(self, progs):
 | 
| -        """Return the first available program in progs.
 | 
| -        """
 | 
| -        if not SCons.Util.is_List(progs):
 | 
| -            progs = [ progs ]
 | 
| -        for prog in progs:
 | 
| -            path = self.WhereIs(prog)
 | 
| -            if path: return prog
 | 
| -        return None
 | 
| -
 | 
| -    def Dictionary(self, *args):
 | 
| -        if not args:
 | 
| -            return self._dict
 | 
| -        dlist = map(lambda x, s=self: s._dict[x], args)
 | 
| -        if len(dlist) == 1:
 | 
| -            dlist = dlist[0]
 | 
| -        return dlist
 | 
| -
 | 
| -    def Dump(self, key = None):
 | 
| -        """
 | 
| -        Using the standard Python pretty printer, dump the contents of the
 | 
| -        scons build environment to stdout.
 | 
| -
 | 
| -        If the key passed in is anything other than None, then that will
 | 
| -        be used as an index into the build environment dictionary and
 | 
| -        whatever is found there will be fed into the pretty printer. Note
 | 
| -        that this key is case sensitive.
 | 
| -        """
 | 
| -        import pprint
 | 
| -        pp = pprint.PrettyPrinter(indent=2)
 | 
| -        if key:
 | 
| -            dict = self.Dictionary(key)
 | 
| -        else:
 | 
| -            dict = self.Dictionary()
 | 
| -        return pp.pformat(dict)
 | 
| -
 | 
| -    def FindIxes(self, paths, prefix, suffix):
 | 
| -        """
 | 
| -        Search a list of paths for something that matches the prefix and suffix.
 | 
| -
 | 
| -        paths - the list of paths or nodes.
 | 
| -        prefix - construction variable for the prefix.
 | 
| -        suffix - construction variable for the suffix.
 | 
| -        """
 | 
| -
 | 
| -        suffix = self.subst('$'+suffix)
 | 
| -        prefix = self.subst('$'+prefix)
 | 
| -
 | 
| -        for path in paths:
 | 
| -            dir,name = os.path.split(str(path))
 | 
| -            if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
 | 
| -                return path
 | 
| -
 | 
| -    def ParseConfig(self, command, function=None, unique=1):
 | 
| -        """
 | 
| -        Use the specified function to parse the output of the command
 | 
| -        in order to modify the current environment.  The 'command' can
 | 
| -        be a string or a list of strings representing a command and
 | 
| -        its arguments.  'Function' is an optional argument that takes
 | 
| -        the environment, the output of the command, and the unique flag.
 | 
| -        If no function is specified, MergeFlags, which treats the output
 | 
| -        as the result of a typical 'X-config' command (i.e. gtk-config),
 | 
| -        will merge the output into the appropriate variables.
 | 
| -        """
 | 
| -        if function is None:
 | 
| -            def parse_conf(env, cmd, unique=unique):
 | 
| -                return env.MergeFlags(cmd, unique)
 | 
| -            function = parse_conf
 | 
| -        if SCons.Util.is_List(command):
 | 
| -            command = string.join(command)
 | 
| -        command = self.subst(command)
 | 
| -        return function(self, self.backtick(command))
 | 
| -
 | 
| -    def ParseDepends(self, filename, must_exist=None, only_one=0):
 | 
| -        """
 | 
| -        Parse a mkdep-style file for explicit dependencies.  This is
 | 
| -        completely abusable, and should be unnecessary in the "normal"
 | 
| -        case of proper SCons configuration, but it may help make
 | 
| -        the transition from a Make hierarchy easier for some people
 | 
| -        to swallow.  It can also be genuinely useful when using a tool
 | 
| -        that can write a .d file, but for which writing a scanner would
 | 
| -        be too complicated.
 | 
| -        """
 | 
| -        filename = self.subst(filename)
 | 
| -        try:
 | 
| -            fp = open(filename, 'r')
 | 
| -        except IOError:
 | 
| -            if must_exist:
 | 
| -                raise
 | 
| -            return
 | 
| -        lines = SCons.Util.LogicalLines(fp).readlines()
 | 
| -        lines = filter(lambda l: l[0] != '#', lines)
 | 
| -        tdlist = []
 | 
| -        for line in lines:
 | 
| -            try:
 | 
| -                target, depends = string.split(line, ':', 1)
 | 
| -            except (AttributeError, TypeError, ValueError):
 | 
| -                # Python 1.5.2 throws TypeError if line isn't a string,
 | 
| -                # Python 2.x throws AttributeError because it tries
 | 
| -                # to call line.split().  Either can throw ValueError
 | 
| -                # if the line doesn't split into two or more elements.
 | 
| -                pass
 | 
| -            else:
 | 
| -                tdlist.append((string.split(target), string.split(depends)))
 | 
| -        if only_one:
 | 
| -            targets = reduce(lambda x, y: x+y, map(lambda p: p[0], tdlist))
 | 
| -            if len(targets) > 1:
 | 
| -                raise SCons.Errors.UserError, "More than one dependency target found in `%s':  %s" % (filename, targets)
 | 
| -        for target, depends in tdlist:
 | 
| -            self.Depends(target, depends)
 | 
| -
 | 
| -    def Platform(self, platform):
 | 
| -        platform = self.subst(platform)
 | 
| -        return SCons.Platform.Platform(platform)(self)
 | 
| -
 | 
| -    def Prepend(self, **kw):
 | 
| -        """Prepend values to existing construction variables
 | 
| -        in an Environment.
 | 
| -        """
 | 
| -        kw = copy_non_reserved_keywords(kw)
 | 
| -        for key, val in kw.items():
 | 
| -            # It would be easier on the eyes to write this using
 | 
| -            # "continue" statements whenever we finish processing an item,
 | 
| -            # but Python 1.5.2 apparently doesn't let you use "continue"
 | 
| -            # within try:-except: blocks, so we have to nest our code.
 | 
| -            try:
 | 
| -                orig = self._dict[key]
 | 
| -            except KeyError:
 | 
| -                # No existing variable in the environment, so just set
 | 
| -                # it to the new value.
 | 
| -                self._dict[key] = val
 | 
| -            else:
 | 
| -                try:
 | 
| -                    # Check if the original looks like a dictionary.
 | 
| -                    # If it is, we can't just try adding the value because
 | 
| -                    # dictionaries don't have __add__() methods, and
 | 
| -                    # things like UserList will incorrectly coerce the
 | 
| -                    # original dict to a list (which we don't want).
 | 
| -                    update_dict = orig.update
 | 
| -                except AttributeError:
 | 
| -                    try:
 | 
| -                        # Most straightforward:  just try to add them
 | 
| -                        # together.  This will work in most cases, when the
 | 
| -                        # original and new values are of compatible types.
 | 
| -                        self._dict[key] = val + orig
 | 
| -                    except (KeyError, TypeError):
 | 
| -                        try:
 | 
| -                            # Check if the added value is a list.
 | 
| -                            add_to_val = val.append
 | 
| -                        except AttributeError:
 | 
| -                            # The added value isn't a list, but the
 | 
| -                            # original is (by process of elimination),
 | 
| -                            # so insert the the new value in the original
 | 
| -                            # (if there's one to insert).
 | 
| -                            if val:
 | 
| -                                orig.insert(0, val)
 | 
| -                        else:
 | 
| -                            # The added value is a list, so append
 | 
| -                            # the original to it (if there's a value
 | 
| -                            # to append).
 | 
| -                            if orig:
 | 
| -                                add_to_val(orig)
 | 
| -                            self._dict[key] = val
 | 
| -                else:
 | 
| -                    # The original looks like a dictionary, so update it
 | 
| -                    # based on what we think the value looks like.
 | 
| -                    if SCons.Util.is_List(val):
 | 
| -                        for v in val:
 | 
| -                            orig[v] = None
 | 
| -                    else:
 | 
| -                        try:
 | 
| -                            update_dict(val)
 | 
| -                        except (AttributeError, TypeError, ValueError):
 | 
| -                            if SCons.Util.is_Dict(val):
 | 
| -                                for k, v in val.items():
 | 
| -                                    orig[k] = v
 | 
| -                            else:
 | 
| -                                orig[val] = None
 | 
| -        self.scanner_map_delete(kw)
 | 
| -
 | 
| -    def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep,
 | 
| -                       delete_existing=1):
 | 
| -        """Prepend path elements to the path 'name' in the 'ENV'
 | 
| -        dictionary for this environment.  Will only add any particular
 | 
| -        path once, and will normpath and normcase all paths to help
 | 
| -        assure this.  This can also handle the case where the env
 | 
| -        variable is a list instead of a string.
 | 
| -
 | 
| -        If delete_existing is 0, a newpath which is already in the path
 | 
| -        will not be moved to the front (it will be left where it is).
 | 
| -        """
 | 
| -
 | 
| -        orig = ''
 | 
| -        if self._dict.has_key(envname) and self._dict[envname].has_key(name):
 | 
| -            orig = self._dict[envname][name]
 | 
| -
 | 
| -        nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing)
 | 
| -
 | 
| -        if not self._dict.has_key(envname):
 | 
| -            self._dict[envname] = {}
 | 
| -
 | 
| -        self._dict[envname][name] = nv
 | 
| -
 | 
| -    def PrependUnique(self, delete_existing=0, **kw):
 | 
| -        """Prepend values to existing construction variables
 | 
| -        in an Environment, if they're not already there.
 | 
| -        If delete_existing is 1, removes existing values first, so
 | 
| -        values move to front.
 | 
| -        """
 | 
| -        kw = copy_non_reserved_keywords(kw)
 | 
| -        for key, val in kw.items():
 | 
| -            if not self._dict.has_key(key) or self._dict[key] in ('', None):
 | 
| -                self._dict[key] = val
 | 
| -            elif SCons.Util.is_Dict(self._dict[key]) and \
 | 
| -                 SCons.Util.is_Dict(val):
 | 
| -                self._dict[key].update(val)
 | 
| -            elif SCons.Util.is_List(val):
 | 
| -                dk = self._dict[key]
 | 
| -                if not SCons.Util.is_List(dk):
 | 
| -                    dk = [dk]
 | 
| -                if delete_existing:
 | 
| -                    dk = filter(lambda x, val=val: x not in val, dk)
 | 
| -                else:
 | 
| -                    val = filter(lambda x, dk=dk: x not in dk, val)
 | 
| -                self._dict[key] = val + dk
 | 
| -            else:
 | 
| -                dk = self._dict[key]
 | 
| -                if SCons.Util.is_List(dk):
 | 
| -                    # By elimination, val is not a list.  Since dk is a
 | 
| -                    # list, wrap val in a list first.
 | 
| -                    if delete_existing:
 | 
| -                        dk = filter(lambda x, val=val: x not in val, dk)
 | 
| -                        self._dict[key] = [val] + dk
 | 
| -                    else:
 | 
| -                        if not val in dk:
 | 
| -                            self._dict[key] = [val] + dk
 | 
| -                else:
 | 
| -                    if delete_existing:
 | 
| -                        dk = filter(lambda x, val=val: x not in val, dk)
 | 
| -                    self._dict[key] = val + dk
 | 
| -        self.scanner_map_delete(kw)
 | 
| -
 | 
| -    def Replace(self, **kw):
 | 
| -        """Replace existing construction variables in an Environment
 | 
| -        with new construction variables and/or values.
 | 
| -        """
 | 
| -        try:
 | 
| -            kwbd = kw['BUILDERS']
 | 
| -        except KeyError:
 | 
| -            pass
 | 
| -        else:
 | 
| -            kwbd = semi_deepcopy(kwbd)
 | 
| -            del kw['BUILDERS']
 | 
| -            self.__setitem__('BUILDERS', kwbd)
 | 
| -        kw = copy_non_reserved_keywords(kw)
 | 
| -        self._update(semi_deepcopy(kw))
 | 
| -        self.scanner_map_delete(kw)
 | 
| -
 | 
| -    def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
 | 
| -        """
 | 
| -        Replace old_prefix with new_prefix and old_suffix with new_suffix.
 | 
| -
 | 
| -        env - Environment used to interpolate variables.
 | 
| -        path - the path that will be modified.
 | 
| -        old_prefix - construction variable for the old prefix.
 | 
| -        old_suffix - construction variable for the old suffix.
 | 
| -        new_prefix - construction variable for the new prefix.
 | 
| -        new_suffix - construction variable for the new suffix.
 | 
| -        """
 | 
| -        old_prefix = self.subst('$'+old_prefix)
 | 
| -        old_suffix = self.subst('$'+old_suffix)
 | 
| -
 | 
| -        new_prefix = self.subst('$'+new_prefix)
 | 
| -        new_suffix = self.subst('$'+new_suffix)
 | 
| -
 | 
| -        dir,name = os.path.split(str(path))
 | 
| -        if name[:len(old_prefix)] == old_prefix:
 | 
| -            name = name[len(old_prefix):]
 | 
| -        if name[-len(old_suffix):] == old_suffix:
 | 
| -            name = name[:-len(old_suffix)]
 | 
| -        return os.path.join(dir, new_prefix+name+new_suffix)
 | 
| -
 | 
| -    def SetDefault(self, **kw):
 | 
| -        for k in kw.keys():
 | 
| -            if self._dict.has_key(k):
 | 
| -                del kw[k]
 | 
| -        apply(self.Replace, (), kw)
 | 
| -
 | 
| -    def _find_toolpath_dir(self, tp):
 | 
| -        return self.fs.Dir(self.subst(tp)).srcnode().abspath
 | 
| -
 | 
| -    def Tool(self, tool, toolpath=None, **kw):
 | 
| -        if SCons.Util.is_String(tool):
 | 
| -            tool = self.subst(tool)
 | 
| -            if toolpath is None:
 | 
| -                toolpath = self.get('toolpath', [])
 | 
| -            toolpath = map(self._find_toolpath_dir, toolpath)
 | 
| -            tool = apply(SCons.Tool.Tool, (tool, toolpath), kw)
 | 
| -        tool(self)
 | 
| -
 | 
| -    def WhereIs(self, prog, path=None, pathext=None, reject=[]):
 | 
| -        """Find prog in the path.
 | 
| -        """
 | 
| -        if path is None:
 | 
| -            try:
 | 
| -                path = self['ENV']['PATH']
 | 
| -            except KeyError:
 | 
| -                pass
 | 
| -        elif SCons.Util.is_String(path):
 | 
| -            path = self.subst(path)
 | 
| -        if pathext is None:
 | 
| -            try:
 | 
| -                pathext = self['ENV']['PATHEXT']
 | 
| -            except KeyError:
 | 
| -                pass
 | 
| -        elif SCons.Util.is_String(pathext):
 | 
| -            pathext = self.subst(pathext)
 | 
| -        prog = self.subst(prog)
 | 
| -        path = SCons.Util.WhereIs(prog, path, pathext, reject)
 | 
| -        if path: return path
 | 
| -        return None
 | 
| -
 | 
| -    #######################################################################
 | 
| -    # Public methods for doing real "SCons stuff" (manipulating
 | 
| -    # dependencies, setting attributes on targets, etc.).  These begin
 | 
| -    # with upper-case letters.  The essential characteristic of methods
 | 
| -    # in this section is that they all *should* have corresponding
 | 
| -    # same-named global functions.
 | 
| -    #######################################################################
 | 
| -
 | 
| -    def Action(self, *args, **kw):
 | 
| -        def subst_string(a, self=self):
 | 
| -            if SCons.Util.is_String(a):
 | 
| -                a = self.subst(a)
 | 
| -            return a
 | 
| -        nargs = map(subst_string, args)
 | 
| -        nkw = self.subst_kw(kw)
 | 
| -        return apply(SCons.Action.Action, nargs, nkw)
 | 
| -
 | 
| -    def AddPreAction(self, files, action):
 | 
| -        nodes = self.arg2nodes(files, self.fs.Entry)
 | 
| -        action = SCons.Action.Action(action)
 | 
| -        uniq = {}
 | 
| -        for executor in map(lambda n: n.get_executor(), nodes):
 | 
| -            uniq[executor] = 1
 | 
| -        for executor in uniq.keys():
 | 
| -            executor.add_pre_action(action)
 | 
| -        return nodes
 | 
| -
 | 
| -    def AddPostAction(self, files, action):
 | 
| -        nodes = self.arg2nodes(files, self.fs.Entry)
 | 
| -        action = SCons.Action.Action(action)
 | 
| -        uniq = {}
 | 
| -        for executor in map(lambda n: n.get_executor(), nodes):
 | 
| -            uniq[executor] = 1
 | 
| -        for executor in uniq.keys():
 | 
| -            executor.add_post_action(action)
 | 
| -        return nodes
 | 
| -
 | 
| -    def Alias(self, target, source=[], action=None, **kw):
 | 
| -        tlist = self.arg2nodes(target, self.ans.Alias)
 | 
| -        if not SCons.Util.is_List(source):
 | 
| -            source = [source]
 | 
| -        source = filter(None, source)
 | 
| -
 | 
| -        if not action:
 | 
| -            if not source:
 | 
| -                # There are no source files and no action, so just
 | 
| -                # return a target list of classic Alias Nodes, without
 | 
| -                # any builder.  The externally visible effect is that
 | 
| -                # this will make the wrapping Script.BuildTask class
 | 
| -                # say that there's "Nothing to be done" for this Alias,
 | 
| -                # instead of that it's "up to date."
 | 
| -                return tlist
 | 
| -
 | 
| -            # No action, but there are sources.  Re-call all the target
 | 
| -            # builders to add the sources to each target.
 | 
| -            result = []
 | 
| -            for t in tlist:
 | 
| -                bld = t.get_builder(AliasBuilder)
 | 
| -                result.extend(bld(self, t, source))
 | 
| -            return result
 | 
| -
 | 
| -        nkw = self.subst_kw(kw)
 | 
| -        nkw.update({
 | 
| -            'action'            : SCons.Action.Action(action),
 | 
| -            'source_factory'    : self.fs.Entry,
 | 
| -            'multi'             : 1,
 | 
| -            'is_explicit'       : None,
 | 
| -        })
 | 
| -        bld = apply(SCons.Builder.Builder, (), nkw)
 | 
| -
 | 
| -        # Apply the Builder separately to each target so that the Aliases
 | 
| -        # stay separate.  If we did one "normal" Builder call with the
 | 
| -        # whole target list, then all of the target Aliases would be
 | 
| -        # associated under a single Executor.
 | 
| -        result = []
 | 
| -        for t in tlist:
 | 
| -            # Calling the convert() method will cause a new Executor to be
 | 
| -            # created from scratch, so we have to explicitly initialize
 | 
| -            # it with the target's existing sources, plus our new ones,
 | 
| -            # so nothing gets lost.
 | 
| -            b = t.get_builder()
 | 
| -            if b is None or b is AliasBuilder:
 | 
| -                b = bld
 | 
| -            else:
 | 
| -                nkw['action'] = b.action + action
 | 
| -                b = apply(SCons.Builder.Builder, (), nkw)
 | 
| -            t.convert()
 | 
| -            result.extend(b(self, t, t.sources + source))
 | 
| -        return result
 | 
| -
 | 
| -    def AlwaysBuild(self, *targets):
 | 
| -        tlist = []
 | 
| -        for t in targets:
 | 
| -            tlist.extend(self.arg2nodes(t, self.fs.Entry))
 | 
| -        for t in tlist:
 | 
| -            t.set_always_build()
 | 
| -        return tlist
 | 
| -
 | 
| -    def BuildDir(self, *args, **kw):
 | 
| -        if kw.has_key('build_dir'):
 | 
| -            kw['variant_dir'] = kw['build_dir']
 | 
| -            del kw['build_dir']
 | 
| -        return apply(self.VariantDir, args, kw)
 | 
| -
 | 
| -    def Builder(self, **kw):
 | 
| -        nkw = self.subst_kw(kw)
 | 
| -        return apply(SCons.Builder.Builder, [], nkw)
 | 
| -
 | 
| -    def CacheDir(self, path):
 | 
| -        import SCons.CacheDir
 | 
| -        if not path is None:
 | 
| -            path = self.subst(path)
 | 
| -        self._CacheDir_path = path
 | 
| -
 | 
| -    def Clean(self, targets, files):
 | 
| -        global CleanTargets
 | 
| -        tlist = self.arg2nodes(targets, self.fs.Entry)
 | 
| -        flist = self.arg2nodes(files, self.fs.Entry)
 | 
| -        for t in tlist:
 | 
| -            try:
 | 
| -                CleanTargets[t].extend(flist)
 | 
| -            except KeyError:
 | 
| -                CleanTargets[t] = flist
 | 
| -
 | 
| -    def Configure(self, *args, **kw):
 | 
| -        nargs = [self]
 | 
| -        if args:
 | 
| -            nargs = nargs + self.subst_list(args)[0]
 | 
| -        nkw = self.subst_kw(kw)
 | 
| -        nkw['_depth'] = kw.get('_depth', 0) + 1
 | 
| -        try:
 | 
| -            nkw['custom_tests'] = self.subst_kw(nkw['custom_tests'])
 | 
| -        except KeyError:
 | 
| -            pass
 | 
| -        return apply(SCons.SConf.SConf, nargs, nkw)
 | 
| -
 | 
| -    def Command(self, target, source, action, **kw):
 | 
| -        """Builds the supplied target files from the supplied
 | 
| -        source files using the supplied action.  Action may
 | 
| -        be any type that the Builder constructor will accept
 | 
| -        for an action."""
 | 
| -        bkw = {
 | 
| -            'action' : action,
 | 
| -            'target_factory' : self.fs.Entry,
 | 
| -            'source_factory' : self.fs.Entry,
 | 
| -        }
 | 
| -        try: bkw['source_scanner'] = kw['source_scanner']
 | 
| -        except KeyError: pass
 | 
| -        else: del kw['source_scanner']
 | 
| -        bld = apply(SCons.Builder.Builder, (), bkw)
 | 
| -        return apply(bld, (self, target, source), kw)
 | 
| -
 | 
| -    def Depends(self, target, dependency):
 | 
| -        """Explicity specify that 'target's depend on 'dependency'."""
 | 
| -        tlist = self.arg2nodes(target, self.fs.Entry)
 | 
| -        dlist = self.arg2nodes(dependency, self.fs.Entry)
 | 
| -        for t in tlist:
 | 
| -            t.add_dependency(dlist)
 | 
| -        return tlist
 | 
| -
 | 
| -    def Dir(self, name, *args, **kw):
 | 
| -        """
 | 
| -        """
 | 
| -        s = self.subst(name)
 | 
| -        if SCons.Util.is_Sequence(s):
 | 
| -            result=[]
 | 
| -            for e in s:
 | 
| -                result.append(apply(self.fs.Dir, (e,) + args, kw))
 | 
| -            return result
 | 
| -        return apply(self.fs.Dir, (s,) + args, kw)
 | 
| -
 | 
| -    def NoClean(self, *targets):
 | 
| -        """Tags a target so that it will not be cleaned by -c"""
 | 
| -        tlist = []
 | 
| -        for t in targets:
 | 
| -            tlist.extend(self.arg2nodes(t, self.fs.Entry))
 | 
| -        for t in tlist:
 | 
| -            t.set_noclean()
 | 
| -        return tlist
 | 
| -
 | 
| -    def NoCache(self, *targets):
 | 
| -        """Tags a target so that it will not be cached"""
 | 
| -        tlist = []
 | 
| -        for t in targets:
 | 
| -            tlist.extend(self.arg2nodes(t, self.fs.Entry))
 | 
| -        for t in tlist:
 | 
| -            t.set_nocache()
 | 
| -        return tlist
 | 
| -
 | 
| -    def Entry(self, name, *args, **kw):
 | 
| -        """
 | 
| -        """
 | 
| -        s = self.subst(name)
 | 
| -        if SCons.Util.is_Sequence(s):
 | 
| -            result=[]
 | 
| -            for e in s:
 | 
| -                result.append(apply(self.fs.Entry, (e,) + args, kw))
 | 
| -            return result
 | 
| -        return apply(self.fs.Entry, (s,) + args, kw)
 | 
| -
 | 
| -    def Environment(self, **kw):
 | 
| -        return apply(SCons.Environment.Environment, [], self.subst_kw(kw))
 | 
| -
 | 
| -    def Execute(self, action, *args, **kw):
 | 
| -        """Directly execute an action through an Environment
 | 
| -        """
 | 
| -        action = apply(self.Action, (action,) + args, kw)
 | 
| -        result = action([], [], self)
 | 
| -        if isinstance(result, SCons.Errors.BuildError):
 | 
| -            errstr = result.errstr
 | 
| -            if result.filename:
 | 
| -                errstr = result.filename + ': ' + errstr
 | 
| -            sys.stderr.write("scons: *** %s\n" % errstr)
 | 
| -            return result.status
 | 
| -        else:
 | 
| -            return result
 | 
| -
 | 
| -    def File(self, name, *args, **kw):
 | 
| -        """
 | 
| -        """
 | 
| -        s = self.subst(name)
 | 
| -        if SCons.Util.is_Sequence(s):
 | 
| -            result=[]
 | 
| -            for e in s:
 | 
| -                result.append(apply(self.fs.File, (e,) + args, kw))
 | 
| -            return result
 | 
| -        return apply(self.fs.File, (s,) + args, kw)
 | 
| -
 | 
| -    def FindFile(self, file, dirs):
 | 
| -        file = self.subst(file)
 | 
| -        nodes = self.arg2nodes(dirs, self.fs.Dir)
 | 
| -        return SCons.Node.FS.find_file(file, tuple(nodes))
 | 
| -
 | 
| -    def Flatten(self, sequence):
 | 
| -        return SCons.Util.flatten(sequence)
 | 
| -
 | 
| -    def GetBuildPath(self, files):
 | 
| -        result = map(str, self.arg2nodes(files, self.fs.Entry))
 | 
| -        if SCons.Util.is_List(files):
 | 
| -            return result
 | 
| -        else:
 | 
| -            return result[0]
 | 
| -
 | 
| -    def Glob(self, pattern, ondisk=True, source=False, strings=False):
 | 
| -        return self.fs.Glob(self.subst(pattern), ondisk, source, strings)
 | 
| -
 | 
| -    def Ignore(self, target, dependency):
 | 
| -        """Ignore a dependency."""
 | 
| -        tlist = self.arg2nodes(target, self.fs.Entry)
 | 
| -        dlist = self.arg2nodes(dependency, self.fs.Entry)
 | 
| -        for t in tlist:
 | 
| -            t.add_ignore(dlist)
 | 
| -        return tlist
 | 
| -
 | 
| -    def Literal(self, string):
 | 
| -        return SCons.Subst.Literal(string)
 | 
| -
 | 
| -    def Local(self, *targets):
 | 
| -        ret = []
 | 
| -        for targ in targets:
 | 
| -            if isinstance(targ, SCons.Node.Node):
 | 
| -                targ.set_local()
 | 
| -                ret.append(targ)
 | 
| -            else:
 | 
| -                for t in self.arg2nodes(targ, self.fs.Entry):
 | 
| -                   t.set_local()
 | 
| -                   ret.append(t)
 | 
| -        return ret
 | 
| -
 | 
| -    def Precious(self, *targets):
 | 
| -        tlist = []
 | 
| -        for t in targets:
 | 
| -            tlist.extend(self.arg2nodes(t, self.fs.Entry))
 | 
| -        for t in tlist:
 | 
| -            t.set_precious()
 | 
| -        return tlist
 | 
| -
 | 
| -    def Repository(self, *dirs, **kw):
 | 
| -        dirs = self.arg2nodes(list(dirs), self.fs.Dir)
 | 
| -        apply(self.fs.Repository, dirs, kw)
 | 
| -
 | 
| -    def Requires(self, target, prerequisite):
 | 
| -        """Specify that 'prerequisite' must be built before 'target',
 | 
| -        (but 'target' does not actually depend on 'prerequisite'
 | 
| -        and need not be rebuilt if it changes)."""
 | 
| -        tlist = self.arg2nodes(target, self.fs.Entry)
 | 
| -        plist = self.arg2nodes(prerequisite, self.fs.Entry)
 | 
| -        for t in tlist:
 | 
| -            t.add_prerequisite(plist)
 | 
| -        return tlist
 | 
| -
 | 
| -    def Scanner(self, *args, **kw):
 | 
| -        nargs = []
 | 
| -        for arg in args:
 | 
| -            if SCons.Util.is_String(arg):
 | 
| -                arg = self.subst(arg)
 | 
| -            nargs.append(arg)
 | 
| -        nkw = self.subst_kw(kw)
 | 
| -        return apply(SCons.Scanner.Base, nargs, nkw)
 | 
| -
 | 
| -    def SConsignFile(self, name=".sconsign", dbm_module=None):
 | 
| -        if not name is None:
 | 
| -            name = self.subst(name)
 | 
| -            if not os.path.isabs(name):
 | 
| -                name = os.path.join(str(self.fs.SConstruct_dir), name)
 | 
| -        if name:
 | 
| -            name = os.path.normpath(name)
 | 
| -            sconsign_dir = os.path.dirname(name)
 | 
| -            if sconsign_dir and not os.path.exists(sconsign_dir):
 | 
| -                self.Execute(SCons.Defaults.Mkdir(sconsign_dir))
 | 
| -        SCons.SConsign.File(name, dbm_module)
 | 
| -
 | 
| -    def SideEffect(self, side_effect, target):
 | 
| -        """Tell scons that side_effects are built as side
 | 
| -        effects of building targets."""
 | 
| -        side_effects = self.arg2nodes(side_effect, self.fs.Entry)
 | 
| -        targets = self.arg2nodes(target, self.fs.Entry)
 | 
| -
 | 
| -        for side_effect in side_effects:
 | 
| -            if side_effect.multiple_side_effect_has_builder():
 | 
| -                raise SCons.Errors.UserError, "Multiple ways to build the same target were specified for: %s" % str(side_effect)
 | 
| -            side_effect.add_source(targets)
 | 
| -            side_effect.side_effect = 1
 | 
| -            self.Precious(side_effect)
 | 
| -            for target in targets:
 | 
| -                target.side_effects.append(side_effect)
 | 
| -        return side_effects
 | 
| -
 | 
| -    def SourceCode(self, entry, builder):
 | 
| -        """Arrange for a source code builder for (part of) a tree."""
 | 
| -        entries = self.arg2nodes(entry, self.fs.Entry)
 | 
| -        for entry in entries:
 | 
| -            entry.set_src_builder(builder)
 | 
| -        return entries
 | 
| -
 | 
| -    def SourceSignatures(self, type):
 | 
| -        global _warn_source_signatures_deprecated
 | 
| -        if _warn_source_signatures_deprecated:
 | 
| -            msg = "The env.SourceSignatures() method is deprecated;\n" + \
 | 
| -                  "\tconvert your build to use the env.Decider() method instead."
 | 
| -            SCons.Warnings.warn(SCons.Warnings.DeprecatedSourceSignaturesWarning, msg)
 | 
| -            _warn_source_signatures_deprecated = False
 | 
| -        type = self.subst(type)
 | 
| -        self.src_sig_type = type
 | 
| -        if type == 'MD5':
 | 
| -            if not SCons.Util.md5:
 | 
| -                raise UserError, "MD5 signatures are not available in this version of Python."
 | 
| -            self.decide_source = self._changed_content
 | 
| -        elif type == 'timestamp':
 | 
| -            self.decide_source = self._changed_timestamp_match
 | 
| -        else:
 | 
| -            raise UserError, "Unknown source signature type '%s'" % type
 | 
| -
 | 
| -    def Split(self, arg):
 | 
| -        """This function converts a string or list into a list of strings
 | 
| -        or Nodes.  This makes things easier for users by allowing files to
 | 
| -        be specified as a white-space separated list to be split.
 | 
| -        The input rules are:
 | 
| -            - A single string containing names separated by spaces. These will be
 | 
| -              split apart at the spaces.
 | 
| -            - A single Node instance
 | 
| -            - A list containing either strings or Node instances. Any strings
 | 
| -              in the list are not split at spaces.
 | 
| -        In all cases, the function returns a list of Nodes and strings."""
 | 
| -        if SCons.Util.is_List(arg):
 | 
| -            return map(self.subst, arg)
 | 
| -        elif SCons.Util.is_String(arg):
 | 
| -            return string.split(self.subst(arg))
 | 
| -        else:
 | 
| -            return [self.subst(arg)]
 | 
| -
 | 
| -    def TargetSignatures(self, type):
 | 
| -        global _warn_target_signatures_deprecated
 | 
| -        if _warn_target_signatures_deprecated:
 | 
| -            msg = "The env.TargetSignatures() method is deprecated;\n" + \
 | 
| -                  "\tconvert your build to use the env.Decider() method instead."
 | 
| -            SCons.Warnings.warn(SCons.Warnings.DeprecatedTargetSignaturesWarning, msg)
 | 
| -            _warn_target_signatures_deprecated = False
 | 
| -        type = self.subst(type)
 | 
| -        self.tgt_sig_type = type
 | 
| -        if type in ('MD5', 'content'):
 | 
| -            if not SCons.Util.md5:
 | 
| -                raise UserError, "MD5 signatures are not available in this version of Python."
 | 
| -            self.decide_target = self._changed_content
 | 
| -        elif type == 'timestamp':
 | 
| -            self.decide_target = self._changed_timestamp_match
 | 
| -        elif type == 'build':
 | 
| -            self.decide_target = self._changed_build
 | 
| -        elif type == 'source':
 | 
| -            self.decide_target = self._changed_source
 | 
| -        else:
 | 
| -            raise UserError, "Unknown target signature type '%s'"%type
 | 
| -
 | 
| -    def Value(self, value, built_value=None):
 | 
| -        """
 | 
| -        """
 | 
| -        return SCons.Node.Python.Value(value, built_value)
 | 
| -
 | 
| -    def VariantDir(self, variant_dir, src_dir, duplicate=1):
 | 
| -        variant_dir = self.arg2nodes(variant_dir, self.fs.Dir)[0]
 | 
| -        src_dir = self.arg2nodes(src_dir, self.fs.Dir)[0]
 | 
| -        self.fs.VariantDir(variant_dir, src_dir, duplicate)
 | 
| -
 | 
| -    def FindSourceFiles(self, node='.'):
 | 
| -        """ returns a list of all source files.
 | 
| -        """
 | 
| -        node = self.arg2nodes(node, self.fs.Entry)[0]
 | 
| -
 | 
| -        sources = []
 | 
| -        # Uncomment this and get rid of the global definition when we
 | 
| -        # drop support for pre-2.2 Python versions.
 | 
| -        #def build_source(ss, result):
 | 
| -        #    for s in ss:
 | 
| -        #        if isinstance(s, SCons.Node.FS.Dir):
 | 
| -        #            build_source(s.all_children(), result)
 | 
| -        #        elif s.has_builder():
 | 
| -        #            build_source(s.sources, result)
 | 
| -        #        elif isinstance(s.disambiguate(), SCons.Node.FS.File):
 | 
| -        #            result.append(s)
 | 
| -        build_source(node.all_children(), sources)
 | 
| -
 | 
| -        # now strip the build_node from the sources by calling the srcnode
 | 
| -        # function
 | 
| -        def get_final_srcnode(file):
 | 
| -            srcnode = file.srcnode()
 | 
| -            while srcnode != file.srcnode():
 | 
| -                srcnode = file.srcnode()
 | 
| -            return srcnode
 | 
| -
 | 
| -        # get the final srcnode for all nodes, this means stripping any
 | 
| -        # attached build node.
 | 
| -        map( get_final_srcnode, sources )
 | 
| -
 | 
| -        # remove duplicates
 | 
| -        return list(set(sources))
 | 
| -
 | 
| -    def FindInstalledFiles(self):
 | 
| -        """ returns the list of all targets of the Install and InstallAs Builder.
 | 
| -        """
 | 
| -        from SCons.Tool import install
 | 
| -        if install._UNIQUE_INSTALLED_FILES is None:
 | 
| -            install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES)
 | 
| -        return install._UNIQUE_INSTALLED_FILES
 | 
| -
 | 
| -class OverrideEnvironment(Base):
 | 
| -    """A proxy that overrides variables in a wrapped construction
 | 
| -    environment by returning values from an overrides dictionary in
 | 
| -    preference to values from the underlying subject environment.
 | 
| -
 | 
| -    This is a lightweight (I hope) proxy that passes through most use of
 | 
| -    attributes to the underlying Environment.Base class, but has just
 | 
| -    enough additional methods defined to act like a real construction
 | 
| -    environment with overridden values.  It can wrap either a Base
 | 
| -    construction environment, or another OverrideEnvironment, which
 | 
| -    can in turn nest arbitrary OverrideEnvironments...
 | 
| -
 | 
| -    Note that we do *not* call the underlying base class
 | 
| -    (SubsitutionEnvironment) initialization, because we get most of those
 | 
| -    from proxying the attributes of the subject construction environment.
 | 
| -    But because we subclass SubstitutionEnvironment, this class also
 | 
| -    has inherited arg2nodes() and subst*() methods; those methods can't
 | 
| -    be proxied because they need *this* object's methods to fetch the
 | 
| -    values from the overrides dictionary.
 | 
| -    """
 | 
| -
 | 
| -    if SCons.Memoize.use_memoizer:
 | 
| -        __metaclass__ = SCons.Memoize.Memoized_Metaclass
 | 
| -
 | 
| -    def __init__(self, subject, overrides={}):
 | 
| -        if __debug__: logInstanceCreation(self, 'Environment.OverrideEnvironment')
 | 
| -        self.__dict__['__subject'] = subject
 | 
| -        self.__dict__['overrides'] = overrides
 | 
| -
 | 
| -    # Methods that make this class act like a proxy.
 | 
| -    def __getattr__(self, name):
 | 
| -        return getattr(self.__dict__['__subject'], name)
 | 
| -    def __setattr__(self, name, value):
 | 
| -        setattr(self.__dict__['__subject'], name, value)
 | 
| -
 | 
| -    # Methods that make this class act like a dictionary.
 | 
| -    def __getitem__(self, key):
 | 
| -        try:
 | 
| -            return self.__dict__['overrides'][key]
 | 
| -        except KeyError:
 | 
| -            return self.__dict__['__subject'].__getitem__(key)
 | 
| -    def __setitem__(self, key, value):
 | 
| -        if not is_valid_construction_var(key):
 | 
| -            raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
 | 
| -        self.__dict__['overrides'][key] = value
 | 
| -    def __delitem__(self, key):
 | 
| -        try:
 | 
| -            del self.__dict__['overrides'][key]
 | 
| -        except KeyError:
 | 
| -            deleted = 0
 | 
| -        else:
 | 
| -            deleted = 1
 | 
| -        try:
 | 
| -            result = self.__dict__['__subject'].__delitem__(key)
 | 
| -        except KeyError:
 | 
| -            if not deleted:
 | 
| -                raise
 | 
| -            result = None
 | 
| -        return result
 | 
| -    def get(self, key, default=None):
 | 
| -        """Emulates the get() method of dictionaries."""
 | 
| -        try:
 | 
| -            return self.__dict__['overrides'][key]
 | 
| -        except KeyError:
 | 
| -            return self.__dict__['__subject'].get(key, default)
 | 
| -    def has_key(self, key):
 | 
| -        try:
 | 
| -            self.__dict__['overrides'][key]
 | 
| -            return 1
 | 
| -        except KeyError:
 | 
| -            return self.__dict__['__subject'].has_key(key)
 | 
| -    def Dictionary(self):
 | 
| -        """Emulates the items() method of dictionaries."""
 | 
| -        d = self.__dict__['__subject'].Dictionary().copy()
 | 
| -        d.update(self.__dict__['overrides'])
 | 
| -        return d
 | 
| -    def items(self):
 | 
| -        """Emulates the items() method of dictionaries."""
 | 
| -        return self.Dictionary().items()
 | 
| -
 | 
| -    # Overridden private construction environment methods.
 | 
| -    def _update(self, dict):
 | 
| -        """Update an environment's values directly, bypassing the normal
 | 
| -        checks that occur when users try to set items.
 | 
| -        """
 | 
| -        self.__dict__['overrides'].update(dict)
 | 
| -
 | 
| -    def gvars(self):
 | 
| -        return self.__dict__['__subject'].gvars()
 | 
| -
 | 
| -    def lvars(self):
 | 
| -        lvars = self.__dict__['__subject'].lvars()
 | 
| -        lvars.update(self.__dict__['overrides'])
 | 
| -        return lvars
 | 
| -
 | 
| -    # Overridden public construction environment methods.
 | 
| -    def Replace(self, **kw):
 | 
| -        kw = copy_non_reserved_keywords(kw)
 | 
| -        self.__dict__['overrides'].update(semi_deepcopy(kw))
 | 
| -
 | 
| -# The entry point that will be used by the external world
 | 
| -# to refer to a construction environment.  This allows the wrapper
 | 
| -# interface to extend a construction environment for its own purposes
 | 
| -# by subclassing SCons.Environment.Base and then assigning the
 | 
| -# class to SCons.Environment.Environment.
 | 
| -
 | 
| -Environment = Base
 | 
| -
 | 
| -# An entry point for returning a proxy subclass instance that overrides
 | 
| -# the subst*() methods so they don't actually perform construction
 | 
| -# variable substitution.  This is specifically intended to be the shim
 | 
| -# layer in between global function calls (which don't want construction
 | 
| -# variable substitution) and the DefaultEnvironment() (which would
 | 
| -# substitute variables if left to its own devices)."""
 | 
| -#
 | 
| -# We have to wrap this in a function that allows us to delay definition of
 | 
| -# the class until it's necessary, so that when it subclasses Environment
 | 
| -# it will pick up whatever Environment subclass the wrapper interface
 | 
| -# might have assigned to SCons.Environment.Environment.
 | 
| -
 | 
| -def NoSubstitutionProxy(subject):
 | 
| -    class _NoSubstitutionProxy(Environment):
 | 
| -        def __init__(self, subject):
 | 
| -            self.__dict__['__subject'] = subject
 | 
| -        def __getattr__(self, name):
 | 
| -            return getattr(self.__dict__['__subject'], name)
 | 
| -        def __setattr__(self, name, value):
 | 
| -            return setattr(self.__dict__['__subject'], name, value)
 | 
| -        def raw_to_mode(self, dict):
 | 
| -            try:
 | 
| -                raw = dict['raw']
 | 
| -            except KeyError:
 | 
| -                pass
 | 
| -            else:
 | 
| -                del dict['raw']
 | 
| -                dict['mode'] = raw
 | 
| -        def subst(self, string, *args, **kwargs):
 | 
| -            return string
 | 
| -        def subst_kw(self, kw, *args, **kwargs):
 | 
| -            return kw
 | 
| -        def subst_list(self, string, *args, **kwargs):
 | 
| -            nargs = (string, self,) + args
 | 
| -            nkw = kwargs.copy()
 | 
| -            nkw['gvars'] = {}
 | 
| -            self.raw_to_mode(nkw)
 | 
| -            return apply(SCons.Subst.scons_subst_list, nargs, nkw)
 | 
| -        def subst_target_source(self, string, *args, **kwargs):
 | 
| -            nargs = (string, self,) + args
 | 
| -            nkw = kwargs.copy()
 | 
| -            nkw['gvars'] = {}
 | 
| -            self.raw_to_mode(nkw)
 | 
| -            return apply(SCons.Subst.scons_subst, nargs, nkw)
 | 
| -    return _NoSubstitutionProxy(subject)
 | 
| +"""SCons.Environment
 | 
| +
 | 
| +Base class for construction Environments.  These are
 | 
| +the primary objects used to communicate dependency and
 | 
| +construction information to the build engine.
 | 
| +
 | 
| +Keyword arguments supplied when the construction Environment
 | 
| +is created are construction variables used to initialize the
 | 
| +Environment
 | 
| +"""
 | 
| +
 | 
| +#
 | 
| +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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.
 | 
| +#
 | 
| +
 | 
| +__revision__ = "src/engine/SCons/Environment.py 3603 2008/10/10 05:46:45 scons"
 | 
| +
 | 
| +
 | 
| +import copy
 | 
| +import os
 | 
| +import sys
 | 
| +import re
 | 
| +import shlex
 | 
| +import string
 | 
| +from UserDict import UserDict
 | 
| +
 | 
| +import SCons.Action
 | 
| +import SCons.Builder
 | 
| +from SCons.Debug import logInstanceCreation
 | 
| +import SCons.Defaults
 | 
| +import SCons.Errors
 | 
| +import SCons.Memoize
 | 
| +import SCons.Node
 | 
| +import SCons.Node.Alias
 | 
| +import SCons.Node.FS
 | 
| +import SCons.Node.Python
 | 
| +import SCons.Platform
 | 
| +import SCons.SConsign
 | 
| +import SCons.Subst
 | 
| +import SCons.Tool
 | 
| +import SCons.Util
 | 
| +import SCons.Warnings
 | 
| +
 | 
| +class _Null:
 | 
| +    pass
 | 
| +
 | 
| +_null = _Null
 | 
| +
 | 
| +_warn_copy_deprecated = True
 | 
| +_warn_source_signatures_deprecated = True
 | 
| +_warn_target_signatures_deprecated = True
 | 
| +
 | 
| +CleanTargets = {}
 | 
| +CalculatorArgs = {}
 | 
| +
 | 
| +semi_deepcopy = SCons.Util.semi_deepcopy
 | 
| +
 | 
| +# Pull UserError into the global name space for the benefit of
 | 
| +# Environment().SourceSignatures(), which has some import statements
 | 
| +# which seem to mess up its ability to reference SCons directly.
 | 
| +UserError = SCons.Errors.UserError
 | 
| +
 | 
| +def alias_builder(env, target, source):
 | 
| +    pass
 | 
| +
 | 
| +AliasBuilder = SCons.Builder.Builder(action = alias_builder,
 | 
| +                                     target_factory = SCons.Node.Alias.default_ans.Alias,
 | 
| +                                     source_factory = SCons.Node.FS.Entry,
 | 
| +                                     multi = 1,
 | 
| +                                     is_explicit = None,
 | 
| +                                     name='AliasBuilder')
 | 
| +
 | 
| +def apply_tools(env, tools, toolpath):
 | 
| +    # Store the toolpath in the Environment.
 | 
| +    if toolpath is not None:
 | 
| +        env['toolpath'] = toolpath
 | 
| +
 | 
| +    if not tools:
 | 
| +        return
 | 
| +    # Filter out null tools from the list.
 | 
| +    for tool in filter(None, tools):
 | 
| +        if SCons.Util.is_List(tool) or type(tool)==type(()):
 | 
| +            toolname = tool[0]
 | 
| +            toolargs = tool[1] # should be a dict of kw args
 | 
| +            tool = apply(env.Tool, [toolname], toolargs)
 | 
| +        else:
 | 
| +            env.Tool(tool)
 | 
| +
 | 
| +# These names are controlled by SCons; users should never set or override
 | 
| +# them.  This warning can optionally be turned off, but scons will still
 | 
| +# ignore the illegal variable names even if it's off.
 | 
| +reserved_construction_var_names = \
 | 
| +    ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']
 | 
| +
 | 
| +def copy_non_reserved_keywords(dict):
 | 
| +    result = semi_deepcopy(dict)
 | 
| +    for k in result.keys():
 | 
| +        if k in reserved_construction_var_names:
 | 
| +            SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning,
 | 
| +                                "Ignoring attempt to set reserved variable `%s'" % k)
 | 
| +            del result[k]
 | 
| +    return result
 | 
| +
 | 
| +def _set_reserved(env, key, value):
 | 
| +    msg = "Ignoring attempt to set reserved variable `%s'" % key
 | 
| +    SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg)
 | 
| +
 | 
| +def _set_BUILDERS(env, key, value):
 | 
| +    try:
 | 
| +        bd = env._dict[key]
 | 
| +        for k in bd.keys():
 | 
| +            del bd[k]
 | 
| +    except KeyError:
 | 
| +        bd = BuilderDict(kwbd, env)
 | 
| +        env._dict[key] = bd
 | 
| +    bd.update(value)
 | 
| +
 | 
| +def _del_SCANNERS(env, key):
 | 
| +    del env._dict[key]
 | 
| +    env.scanner_map_delete()
 | 
| +
 | 
| +def _set_SCANNERS(env, key, value):
 | 
| +    env._dict[key] = value
 | 
| +    env.scanner_map_delete()
 | 
| +
 | 
| +
 | 
| +
 | 
| +# The following is partly based on code in a comment added by Peter
 | 
| +# Shannon at the following page (there called the "transplant" class):
 | 
| +#
 | 
| +# ASPN : Python Cookbook : Dynamically added methods to a class
 | 
| +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732
 | 
| +#
 | 
| +# We had independently been using the idiom as BuilderWrapper, but
 | 
| +# factoring out the common parts into this base class, and making
 | 
| +# BuilderWrapper a subclass that overrides __call__() to enforce specific
 | 
| +# Builder calling conventions, simplified some of our higher-layer code.
 | 
| +
 | 
| +class MethodWrapper:
 | 
| +    """
 | 
| +    A generic Wrapper class that associates a method (which can
 | 
| +    actually be any callable) with an object.  As part of creating this
 | 
| +    MethodWrapper object an attribute with the specified (by default,
 | 
| +    the name of the supplied method) is added to the underlying object.
 | 
| +    When that new "method" is called, our __call__() method adds the
 | 
| +    object as the first argument, simulating the Python behavior of
 | 
| +    supplying "self" on method calls.
 | 
| +
 | 
| +    We hang on to the name by which the method was added to the underlying
 | 
| +    base class so that we can provide a method to "clone" ourselves onto
 | 
| +    a new underlying object being copied (without which we wouldn't need
 | 
| +    to save that info).
 | 
| +    """
 | 
| +    def __init__(self, object, method, name=None):
 | 
| +        if name is None:
 | 
| +            name = method.__name__
 | 
| +        self.object = object
 | 
| +        self.method = method
 | 
| +        self.name = name
 | 
| +        setattr(self.object, name, self)
 | 
| +
 | 
| +    def __call__(self, *args, **kwargs):
 | 
| +        nargs = (self.object,) + args
 | 
| +        return apply(self.method, nargs, kwargs)
 | 
| +
 | 
| +    def clone(self, new_object):
 | 
| +        """
 | 
| +        Returns an object that re-binds the underlying "method" to
 | 
| +        the specified new object.
 | 
| +        """
 | 
| +        return self.__class__(new_object, self.method, self.name)
 | 
| +
 | 
| +class BuilderWrapper(MethodWrapper):
 | 
| +    """
 | 
| +    A MethodWrapper subclass that that associates an environment with
 | 
| +    a Builder.
 | 
| +
 | 
| +    This mainly exists to wrap the __call__() function so that all calls
 | 
| +    to Builders can have their argument lists massaged in the same way
 | 
| +    (treat a lone argument as the source, treat two arguments as target
 | 
| +    then source, make sure both target and source are lists) without
 | 
| +    having to have cut-and-paste code to do it.
 | 
| +
 | 
| +    As a bit of obsessive backwards compatibility, we also intercept
 | 
| +    attempts to get or set the "env" or "builder" attributes, which were
 | 
| +    the names we used before we put the common functionality into the
 | 
| +    MethodWrapper base class.  We'll keep this around for a while in case
 | 
| +    people shipped Tool modules that reached into the wrapper (like the
 | 
| +    Tool/qt.py module does, or did).  There shouldn't be a lot attribute
 | 
| +    fetching or setting on these, so a little extra work shouldn't hurt.
 | 
| +    """
 | 
| +    def __call__(self, target=None, source=_null, *args, **kw):
 | 
| +        if source is _null:
 | 
| +            source = target
 | 
| +            target = None
 | 
| +        if not target is None and not SCons.Util.is_List(target):
 | 
| +            target = [target]
 | 
| +        if not source is None and not SCons.Util.is_List(source):
 | 
| +            source = [source]
 | 
| +        return apply(MethodWrapper.__call__, (self, target, source) + args, kw)
 | 
| +
 | 
| +    def __repr__(self):
 | 
| +        fmt = '<BuilderWrapper %s instance at 0x%08X>'
 | 
| +        return fmt % (repr(self.name), id(self))
 | 
| +
 | 
| +    def __str__(self):
 | 
| +        return self.__repr__()
 | 
| +
 | 
| +    def __getattr__(self, name):
 | 
| +        if name == 'env':
 | 
| +            return self.object
 | 
| +        elif name == 'builder':
 | 
| +            return self.method
 | 
| +        else:
 | 
| +            raise AttributeError, name
 | 
| +
 | 
| +    def __setattr__(self, name, value):
 | 
| +        if name == 'env':
 | 
| +            self.object = value
 | 
| +        elif name == 'builder':
 | 
| +            self.method = value
 | 
| +        else:
 | 
| +            self.__dict__[name] = value
 | 
| +
 | 
| +    # This allows a Builder to be executed directly
 | 
| +    # through the Environment to which it's attached.
 | 
| +    # In practice, we shouldn't need this, because
 | 
| +    # builders actually get executed through a Node.
 | 
| +    # But we do have a unit test for this, and can't
 | 
| +    # yet rule out that it would be useful in the
 | 
| +    # future, so leave it for now.
 | 
| +    #def execute(self, **kw):
 | 
| +    #    kw['env'] = self.env
 | 
| +    #    apply(self.builder.execute, (), kw)
 | 
| +
 | 
| +class BuilderDict(UserDict):
 | 
| +    """This is a dictionary-like class used by an Environment to hold
 | 
| +    the Builders.  We need to do this because every time someone changes
 | 
| +    the Builders in the Environment's BUILDERS dictionary, we must
 | 
| +    update the Environment's attributes."""
 | 
| +    def __init__(self, dict, env):
 | 
| +        # Set self.env before calling the superclass initialization,
 | 
| +        # because it will end up calling our other methods, which will
 | 
| +        # need to point the values in this dictionary to self.env.
 | 
| +        self.env = env
 | 
| +        UserDict.__init__(self, dict)
 | 
| +
 | 
| +    def __semi_deepcopy__(self):
 | 
| +        return self.__class__(self.data, self.env)
 | 
| +
 | 
| +    def __setitem__(self, item, val):
 | 
| +        try:
 | 
| +            method = getattr(self.env, item).method
 | 
| +        except AttributeError:
 | 
| +            pass
 | 
| +        else:
 | 
| +            self.env.RemoveMethod(method)
 | 
| +        UserDict.__setitem__(self, item, val)
 | 
| +        BuilderWrapper(self.env, val, item)
 | 
| +
 | 
| +    def __delitem__(self, item):
 | 
| +        UserDict.__delitem__(self, item)
 | 
| +        delattr(self.env, item)
 | 
| +
 | 
| +    def update(self, dict):
 | 
| +        for i, v in dict.items():
 | 
| +            self.__setitem__(i, v)
 | 
| +
 | 
| +
 | 
| +
 | 
| +_is_valid_var = re.compile(r'[_a-zA-Z]\w*$')
 | 
| +
 | 
| +def is_valid_construction_var(varstr):
 | 
| +    """Return if the specified string is a legitimate construction
 | 
| +    variable.
 | 
| +    """
 | 
| +    return _is_valid_var.match(varstr)
 | 
| +
 | 
| +
 | 
| +
 | 
| +class SubstitutionEnvironment:
 | 
| +    """Base class for different flavors of construction environments.
 | 
| +
 | 
| +    This class contains a minimal set of methods that handle contruction
 | 
| +    variable expansion and conversion of strings to Nodes, which may or
 | 
| +    may not be actually useful as a stand-alone class.  Which methods
 | 
| +    ended up in this class is pretty arbitrary right now.  They're
 | 
| +    basically the ones which we've empirically determined are common to
 | 
| +    the different construction environment subclasses, and most of the
 | 
| +    others that use or touch the underlying dictionary of construction
 | 
| +    variables.
 | 
| +
 | 
| +    Eventually, this class should contain all the methods that we
 | 
| +    determine are necessary for a "minimal" interface to the build engine.
 | 
| +    A full "native Python" SCons environment has gotten pretty heavyweight
 | 
| +    with all of the methods and Tools and construction variables we've
 | 
| +    jammed in there, so it would be nice to have a lighter weight
 | 
| +    alternative for interfaces that don't need all of the bells and
 | 
| +    whistles.  (At some point, we'll also probably rename this class
 | 
| +    "Base," since that more reflects what we want this class to become,
 | 
| +    but because we've released comments that tell people to subclass
 | 
| +    Environment.Base to create their own flavors of construction
 | 
| +    environment, we'll save that for a future refactoring when this
 | 
| +    class actually becomes useful.)
 | 
| +    """
 | 
| +
 | 
| +    if SCons.Memoize.use_memoizer:
 | 
| +        __metaclass__ = SCons.Memoize.Memoized_Metaclass
 | 
| +
 | 
| +    def __init__(self, **kw):
 | 
| +        """Initialization of an underlying SubstitutionEnvironment class.
 | 
| +        """
 | 
| +        if __debug__: logInstanceCreation(self, 'Environment.SubstitutionEnvironment')
 | 
| +        self.fs = SCons.Node.FS.get_default_fs()
 | 
| +        self.ans = SCons.Node.Alias.default_ans
 | 
| +        self.lookup_list = SCons.Node.arg2nodes_lookups
 | 
| +        self._dict = kw.copy()
 | 
| +        self._init_special()
 | 
| +        self.added_methods = []
 | 
| +        #self._memo = {}
 | 
| +
 | 
| +    def _init_special(self):
 | 
| +        """Initial the dispatch tables for special handling of
 | 
| +        special construction variables."""
 | 
| +        self._special_del = {}
 | 
| +        self._special_del['SCANNERS'] = _del_SCANNERS
 | 
| +
 | 
| +        self._special_set = {}
 | 
| +        for key in reserved_construction_var_names:
 | 
| +            self._special_set[key] = _set_reserved
 | 
| +        self._special_set['BUILDERS'] = _set_BUILDERS
 | 
| +        self._special_set['SCANNERS'] = _set_SCANNERS
 | 
| +
 | 
| +        # Freeze the keys of self._special_set in a list for use by
 | 
| +        # methods that need to check.  (Empirically, list scanning has
 | 
| +        # gotten better than dict.has_key() in Python 2.5.)
 | 
| +        self._special_set_keys = self._special_set.keys()
 | 
| +
 | 
| +    def __cmp__(self, other):
 | 
| +        return cmp(self._dict, other._dict)
 | 
| +
 | 
| +    def __delitem__(self, key):
 | 
| +        special = self._special_del.get(key)
 | 
| +        if special:
 | 
| +            special(self, key)
 | 
| +        else:
 | 
| +            del self._dict[key]
 | 
| +
 | 
| +    def __getitem__(self, key):
 | 
| +        return self._dict[key]
 | 
| +
 | 
| +    def __setitem__(self, key, value):
 | 
| +        # This is heavily used.  This implementation is the best we have
 | 
| +        # according to the timings in bench/env.__setitem__.py.
 | 
| +        #
 | 
| +        # The "key in self._special_set_keys" test here seems to perform
 | 
| +        # pretty well for the number of keys we have.  A hard-coded
 | 
| +        # list works a little better in Python 2.5, but that has the
 | 
| +        # disadvantage of maybe getting out of sync if we ever add more
 | 
| +        # variable names.  Using self._special_set.has_key() works a
 | 
| +        # little better in Python 2.4, but is worse then this test.
 | 
| +        # So right now it seems like a good trade-off, but feel free to
 | 
| +        # revisit this with bench/env.__setitem__.py as needed (and
 | 
| +        # as newer versions of Python come out).
 | 
| +        if key in self._special_set_keys:
 | 
| +            self._special_set[key](self, key, value)
 | 
| +        else:
 | 
| +            # If we already have the entry, then it's obviously a valid
 | 
| +            # key and we don't need to check.  If we do check, using a
 | 
| +            # global, pre-compiled regular expression directly is more
 | 
| +            # efficient than calling another function or a method.
 | 
| +            if not self._dict.has_key(key) \
 | 
| +               and not _is_valid_var.match(key):
 | 
| +                    raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
 | 
| +            self._dict[key] = value
 | 
| +
 | 
| +    def get(self, key, default=None):
 | 
| +        "Emulates the get() method of dictionaries."""
 | 
| +        return self._dict.get(key, default)
 | 
| +
 | 
| +    def has_key(self, key):
 | 
| +        return self._dict.has_key(key)
 | 
| +
 | 
| +    def items(self):
 | 
| +        return self._dict.items()
 | 
| +
 | 
| +    def arg2nodes(self, args, node_factory=_null, lookup_list=_null, **kw):
 | 
| +        if node_factory is _null:
 | 
| +            node_factory = self.fs.File
 | 
| +        if lookup_list is _null:
 | 
| +            lookup_list = self.lookup_list
 | 
| +
 | 
| +        if not args:
 | 
| +            return []
 | 
| +
 | 
| +        args = SCons.Util.flatten(args)
 | 
| +
 | 
| +        nodes = []
 | 
| +        for v in args:
 | 
| +            if SCons.Util.is_String(v):
 | 
| +                n = None
 | 
| +                for l in lookup_list:
 | 
| +                    n = l(v)
 | 
| +                    if not n is None:
 | 
| +                        break
 | 
| +                if not n is None:
 | 
| +                    if SCons.Util.is_String(n):
 | 
| +                        # n = self.subst(n, raw=1, **kw)
 | 
| +                        kw['raw'] = 1
 | 
| +                        n = apply(self.subst, (n,), kw)
 | 
| +                        if node_factory:
 | 
| +                            n = node_factory(n)
 | 
| +                    if SCons.Util.is_List(n):
 | 
| +                        nodes.extend(n)
 | 
| +                    else:
 | 
| +                        nodes.append(n)
 | 
| +                elif node_factory:
 | 
| +                    # v = node_factory(self.subst(v, raw=1, **kw))
 | 
| +                    kw['raw'] = 1
 | 
| +                    v = node_factory(apply(self.subst, (v,), kw))
 | 
| +                    if SCons.Util.is_List(v):
 | 
| +                        nodes.extend(v)
 | 
| +                    else:
 | 
| +                        nodes.append(v)
 | 
| +            else:
 | 
| +                nodes.append(v)
 | 
| +
 | 
| +        return nodes
 | 
| +
 | 
| +    def gvars(self):
 | 
| +        return self._dict
 | 
| +
 | 
| +    def lvars(self):
 | 
| +        return {}
 | 
| +
 | 
| +    def subst(self, string, raw=0, target=None, source=None, conv=None):
 | 
| +        """Recursively interpolates construction variables from the
 | 
| +        Environment into the specified string, returning the expanded
 | 
| +        result.  Construction variables are specified by a $ prefix
 | 
| +        in the string and begin with an initial underscore or
 | 
| +        alphabetic character followed by any number of underscores
 | 
| +        or alphanumeric characters.  The construction variable names
 | 
| +        may be surrounded by curly braces to separate the name from
 | 
| +        trailing characters.
 | 
| +        """
 | 
| +        gvars = self.gvars()
 | 
| +        lvars = self.lvars()
 | 
| +        lvars['__env__'] = self
 | 
| +        return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv)
 | 
| +
 | 
| +    def subst_kw(self, kw, raw=0, target=None, source=None):
 | 
| +        nkw = {}
 | 
| +        for k, v in kw.items():
 | 
| +            k = self.subst(k, raw, target, source)
 | 
| +            if SCons.Util.is_String(v):
 | 
| +                v = self.subst(v, raw, target, source)
 | 
| +            nkw[k] = v
 | 
| +        return nkw
 | 
| +
 | 
| +    def subst_list(self, string, raw=0, target=None, source=None, conv=None):
 | 
| +        """Calls through to SCons.Subst.scons_subst_list().  See
 | 
| +        the documentation for that function."""
 | 
| +        gvars = self.gvars()
 | 
| +        lvars = self.lvars()
 | 
| +        lvars['__env__'] = self
 | 
| +        return SCons.Subst.scons_subst_list(string, self, raw, target, source, gvars, lvars, conv)
 | 
| +
 | 
| +    def subst_path(self, path, target=None, source=None):
 | 
| +        """Substitute a path list, turning EntryProxies into Nodes
 | 
| +        and leaving Nodes (and other objects) as-is."""
 | 
| +
 | 
| +        if not SCons.Util.is_List(path):
 | 
| +            path = [path]
 | 
| +
 | 
| +        def s(obj):
 | 
| +            """This is the "string conversion" routine that we have our
 | 
| +            substitutions use to return Nodes, not strings.  This relies
 | 
| +            on the fact that an EntryProxy object has a get() method that
 | 
| +            returns the underlying Node that it wraps, which is a bit of
 | 
| +            architectural dependence that we might need to break or modify
 | 
| +            in the future in response to additional requirements."""
 | 
| +            try:
 | 
| +                get = obj.get
 | 
| +            except AttributeError:
 | 
| +                obj = SCons.Util.to_String_for_subst(obj)
 | 
| +            else:
 | 
| +                obj = get()
 | 
| +            return obj
 | 
| +
 | 
| +        r = []
 | 
| +        for p in path:
 | 
| +            if SCons.Util.is_String(p):
 | 
| +                p = self.subst(p, target=target, source=source, conv=s)
 | 
| +                if SCons.Util.is_List(p):
 | 
| +                    if len(p) == 1:
 | 
| +                        p = p[0]
 | 
| +                    else:
 | 
| +                        # We have an object plus a string, or multiple
 | 
| +                        # objects that we need to smush together.  No choice
 | 
| +                        # but to make them into a string.
 | 
| +                        p = string.join(map(SCons.Util.to_String_for_subst, p), '')
 | 
| +            else:
 | 
| +                p = s(p)
 | 
| +            r.append(p)
 | 
| +        return r
 | 
| +
 | 
| +    subst_target_source = subst
 | 
| +
 | 
| +    def backtick(self, command):
 | 
| +        import subprocess
 | 
| +        # common arguments
 | 
| +        kw = { 'stdout' : subprocess.PIPE,
 | 
| +               'stderr' : subprocess.PIPE,
 | 
| +               'universal_newlines' : True,
 | 
| +             }
 | 
| +        # if the command is a list, assume it's been quoted
 | 
| +        # othewise force a shell
 | 
| +        if not SCons.Util.is_List(command): kw['shell'] = True
 | 
| +        # run constructed command
 | 
| +        #TODO(1.5) p = SCons.Action._subproc(self, command, **kw)
 | 
| +        p = apply(SCons.Action._subproc, (self, command), kw)
 | 
| +        out,err = p.communicate()
 | 
| +        status = p.wait()
 | 
| +        if err:
 | 
| +            sys.stderr.write(err)
 | 
| +        if status:
 | 
| +            raise OSError("'%s' exited %d" % (command, status))
 | 
| +        return out
 | 
| +
 | 
| +    def AddMethod(self, function, name=None):
 | 
| +        """
 | 
| +        Adds the specified function as a method of this construction
 | 
| +        environment with the specified name.  If the name is omitted,
 | 
| +        the default name is the name of the function itself.
 | 
| +        """
 | 
| +        method = MethodWrapper(self, function, name)
 | 
| +        self.added_methods.append(method)
 | 
| +
 | 
| +    def RemoveMethod(self, function):
 | 
| +        """
 | 
| +        Removes the specified function's MethodWrapper from the
 | 
| +        added_methods list, so we don't re-bind it when making a clone.
 | 
| +        """
 | 
| +        is_not_func = lambda dm, f=function: not dm.method is f
 | 
| +        self.added_methods = filter(is_not_func, self.added_methods)
 | 
| +
 | 
| +    def Override(self, overrides):
 | 
| +        """
 | 
| +        Produce a modified environment whose variables are overriden by
 | 
| +        the overrides dictionaries.  "overrides" is a dictionary that
 | 
| +        will override the variables of this environment.
 | 
| +
 | 
| +        This function is much more efficient than Clone() or creating
 | 
| +        a new Environment because it doesn't copy the construction
 | 
| +        environment dictionary, it just wraps the underlying construction
 | 
| +        environment, and doesn't even create a wrapper object if there
 | 
| +        are no overrides.
 | 
| +        """
 | 
| +        if not overrides: return self
 | 
| +        o = copy_non_reserved_keywords(overrides)
 | 
| +        if not o: return self
 | 
| +        overrides = {}
 | 
| +        merges = None
 | 
| +        for key, value in o.items():
 | 
| +            if key == 'parse_flags':
 | 
| +                merges = value
 | 
| +            else:
 | 
| +                overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
 | 
| +        env = OverrideEnvironment(self, overrides)
 | 
| +        if merges: env.MergeFlags(merges)
 | 
| +        return env
 | 
| +
 | 
| +    def ParseFlags(self, *flags):
 | 
| +        """
 | 
| +        Parse the set of flags and return a dict with the flags placed
 | 
| +        in the appropriate entry.  The flags are treated as a typical
 | 
| +        set of command-line flags for a GNU-like toolchain and used to
 | 
| +        populate the entries in the dict immediately below.  If one of
 | 
| +        the flag strings begins with a bang (exclamation mark), it is
 | 
| +        assumed to be a command and the rest of the string is executed;
 | 
| +        the result of that evaluation is then added to the dict.
 | 
| +        """
 | 
| +        dict = {
 | 
| +            'ASFLAGS'       : SCons.Util.CLVar(''),
 | 
| +            'CFLAGS'        : SCons.Util.CLVar(''),
 | 
| +            'CCFLAGS'       : SCons.Util.CLVar(''),
 | 
| +            'CPPDEFINES'    : [],
 | 
| +            'CPPFLAGS'      : SCons.Util.CLVar(''),
 | 
| +            'CPPPATH'       : [],
 | 
| +            'FRAMEWORKPATH' : SCons.Util.CLVar(''),
 | 
| +            'FRAMEWORKS'    : SCons.Util.CLVar(''),
 | 
| +            'LIBPATH'       : [],
 | 
| +            'LIBS'          : [],
 | 
| +            'LINKFLAGS'     : SCons.Util.CLVar(''),
 | 
| +            'RPATH'         : [],
 | 
| +        }
 | 
| +
 | 
| +        # The use of the "me" parameter to provide our own name for
 | 
| +        # recursion is an egregious hack to support Python 2.1 and before.
 | 
| +        def do_parse(arg, me, self = self, dict = dict):
 | 
| +            # if arg is a sequence, recurse with each element
 | 
| +            if not arg:
 | 
| +                return
 | 
| +
 | 
| +            if not SCons.Util.is_String(arg):
 | 
| +                for t in arg: me(t, me)
 | 
| +                return
 | 
| +
 | 
| +            # if arg is a command, execute it
 | 
| +            if arg[0] == '!':
 | 
| +                arg = self.backtick(arg[1:])
 | 
| +
 | 
| +            # utility function to deal with -D option
 | 
| +            def append_define(name, dict = dict):
 | 
| +                t = string.split(name, '=')
 | 
| +                if len(t) == 1:
 | 
| +                    dict['CPPDEFINES'].append(name)
 | 
| +                else:
 | 
| +                    dict['CPPDEFINES'].append([t[0], string.join(t[1:], '=')])
 | 
| +
 | 
| +            # Loop through the flags and add them to the appropriate option.
 | 
| +            # This tries to strike a balance between checking for all possible
 | 
| +            # flags and keeping the logic to a finite size, so it doesn't
 | 
| +            # check for some that don't occur often.  It particular, if the
 | 
| +            # flag is not known to occur in a config script and there's a way
 | 
| +            # of passing the flag to the right place (by wrapping it in a -W
 | 
| +            # flag, for example) we don't check for it.  Note that most
 | 
| +            # preprocessor options are not handled, since unhandled options
 | 
| +            # are placed in CCFLAGS, so unless the preprocessor is invoked
 | 
| +            # separately, these flags will still get to the preprocessor.
 | 
| +            # Other options not currently handled:
 | 
| +            #  -iqoutedir      (preprocessor search path)
 | 
| +            #  -u symbol       (linker undefined symbol)
 | 
| +            #  -s              (linker strip files)
 | 
| +            #  -static*        (linker static binding)
 | 
| +            #  -shared*        (linker dynamic binding)
 | 
| +            #  -symbolic       (linker global binding)
 | 
| +            #  -R dir          (deprecated linker rpath)
 | 
| +            # IBM compilers may also accept -qframeworkdir=foo
 | 
| +    
 | 
| +            params = shlex.split(arg)
 | 
| +            append_next_arg_to = None   # for multi-word args
 | 
| +            for arg in params:
 | 
| +                if append_next_arg_to:
 | 
| +                   if append_next_arg_to == 'CPPDEFINES':
 | 
| +                       append_define(arg)
 | 
| +                   elif append_next_arg_to == '-include':
 | 
| +                       t = ('-include', self.fs.File(arg))
 | 
| +                       dict['CCFLAGS'].append(t)
 | 
| +                   elif append_next_arg_to == '-isysroot':
 | 
| +                       t = ('-isysroot', arg)
 | 
| +                       dict['CCFLAGS'].append(t)
 | 
| +                       dict['LINKFLAGS'].append(t)
 | 
| +                   elif append_next_arg_to == '-arch':
 | 
| +                       t = ('-arch', arg)
 | 
| +                       dict['CCFLAGS'].append(t)
 | 
| +                       dict['LINKFLAGS'].append(t)
 | 
| +                   else:
 | 
| +                       dict[append_next_arg_to].append(arg)
 | 
| +                   append_next_arg_to = None
 | 
| +                elif not arg[0] in ['-', '+']:
 | 
| +                    dict['LIBS'].append(self.fs.File(arg))
 | 
| +                elif arg[:2] == '-L':
 | 
| +                    if arg[2:]:
 | 
| +                        dict['LIBPATH'].append(arg[2:])
 | 
| +                    else:
 | 
| +                        append_next_arg_to = 'LIBPATH'
 | 
| +                elif arg[:2] == '-l':
 | 
| +                    if arg[2:]:
 | 
| +                        dict['LIBS'].append(arg[2:])
 | 
| +                    else:
 | 
| +                        append_next_arg_to = 'LIBS'
 | 
| +                elif arg[:2] == '-I':
 | 
| +                    if arg[2:]:
 | 
| +                        dict['CPPPATH'].append(arg[2:])
 | 
| +                    else:
 | 
| +                        append_next_arg_to = 'CPPPATH'
 | 
| +                elif arg[:4] == '-Wa,':
 | 
| +                    dict['ASFLAGS'].append(arg[4:])
 | 
| +                    dict['CCFLAGS'].append(arg)
 | 
| +                elif arg[:4] == '-Wl,':
 | 
| +                    if arg[:11] == '-Wl,-rpath=':
 | 
| +                        dict['RPATH'].append(arg[11:])
 | 
| +                    elif arg[:7] == '-Wl,-R,':
 | 
| +                        dict['RPATH'].append(arg[7:])
 | 
| +                    elif arg[:6] == '-Wl,-R':
 | 
| +                        dict['RPATH'].append(arg[6:])
 | 
| +                    else:
 | 
| +                        dict['LINKFLAGS'].append(arg)
 | 
| +                elif arg[:4] == '-Wp,':
 | 
| +                    dict['CPPFLAGS'].append(arg)
 | 
| +                elif arg[:2] == '-D':
 | 
| +                    if arg[2:]:
 | 
| +                        append_define(arg[2:])
 | 
| +                    else:
 | 
| +                        append_next_arg_to = 'CPPDEFINES'
 | 
| +                elif arg == '-framework':
 | 
| +                    append_next_arg_to = 'FRAMEWORKS'
 | 
| +                elif arg[:14] == '-frameworkdir=':
 | 
| +                    dict['FRAMEWORKPATH'].append(arg[14:])
 | 
| +                elif arg[:2] == '-F':
 | 
| +                    if arg[2:]:
 | 
| +                        dict['FRAMEWORKPATH'].append(arg[2:])
 | 
| +                    else:
 | 
| +                        append_next_arg_to = 'FRAMEWORKPATH'
 | 
| +                elif arg == '-mno-cygwin':
 | 
| +                    dict['CCFLAGS'].append(arg)
 | 
| +                    dict['LINKFLAGS'].append(arg)
 | 
| +                elif arg == '-mwindows':
 | 
| +                    dict['LINKFLAGS'].append(arg)
 | 
| +                elif arg == '-pthread':
 | 
| +                    dict['CCFLAGS'].append(arg)
 | 
| +                    dict['LINKFLAGS'].append(arg)
 | 
| +                elif arg[:5] == '-std=':
 | 
| +                    dict['CFLAGS'].append(arg) # C only
 | 
| +                elif arg[0] == '+':
 | 
| +                    dict['CCFLAGS'].append(arg)
 | 
| +                    dict['LINKFLAGS'].append(arg)
 | 
| +                elif arg in ['-include', '-isysroot', '-arch']:
 | 
| +                    append_next_arg_to = arg
 | 
| +                else:
 | 
| +                    dict['CCFLAGS'].append(arg)
 | 
| +    
 | 
| +        for arg in flags:
 | 
| +            do_parse(arg, do_parse)
 | 
| +        return dict
 | 
| +
 | 
| +    def MergeFlags(self, args, unique=1, dict=None):
 | 
| +        """
 | 
| +        Merge the dict in args into the construction variables of this
 | 
| +        env, or the passed-in dict.  If args is not a dict, it is
 | 
| +        converted into a dict using ParseFlags.  If unique is not set,
 | 
| +        the flags are appended rather than merged.
 | 
| +        """
 | 
| +
 | 
| +        if dict is None:
 | 
| +            dict = self
 | 
| +        if not SCons.Util.is_Dict(args):
 | 
| +            args = self.ParseFlags(args)
 | 
| +        if not unique:
 | 
| +            apply(self.Append, (), args)
 | 
| +            return self
 | 
| +        for key, value in args.items():
 | 
| +            if not value:
 | 
| +                continue
 | 
| +            try:
 | 
| +                orig = self[key]
 | 
| +            except KeyError:
 | 
| +                orig = value
 | 
| +            else:
 | 
| +                if not orig:
 | 
| +                    orig = value
 | 
| +                elif value:
 | 
| +                    # Add orig and value.  The logic here was lifted from
 | 
| +                    # part of env.Append() (see there for a lot of comments
 | 
| +                    # about the order in which things are tried) and is
 | 
| +                    # used mainly to handle coercion of strings to CLVar to
 | 
| +                    # "do the right thing" given (e.g.) an original CCFLAGS
 | 
| +                    # string variable like '-pipe -Wall'.
 | 
| +                    try:
 | 
| +                        orig = orig + value
 | 
| +                    except (KeyError, TypeError):
 | 
| +                        try:
 | 
| +                            add_to_orig = orig.append
 | 
| +                        except AttributeError:
 | 
| +                            value.insert(0, orig)
 | 
| +                            orig = value
 | 
| +                        else:
 | 
| +                            add_to_orig(value)
 | 
| +            t = []
 | 
| +            if key[-4:] == 'PATH':
 | 
| +                ### keep left-most occurence
 | 
| +                for v in orig:
 | 
| +                    if v not in t:
 | 
| +                        t.append(v)
 | 
| +            else:
 | 
| +                ### keep right-most occurence
 | 
| +                orig.reverse()
 | 
| +                for v in orig:
 | 
| +                    if v not in t:
 | 
| +                        t.insert(0, v)
 | 
| +            self[key] = t
 | 
| +        return self
 | 
| +
 | 
| +#     def MergeShellPaths(self, args, prepend=1):
 | 
| +#         """
 | 
| +#         Merge the dict in args into the shell environment in env['ENV'].  
 | 
| +#         Shell path elements are appended or prepended according to prepend.
 | 
| +
 | 
| +#         Uses Pre/AppendENVPath, so it always appends or prepends uniquely.
 | 
| +
 | 
| +#         Example: env.MergeShellPaths({'LIBPATH': '/usr/local/lib'})
 | 
| +#         prepends /usr/local/lib to env['ENV']['LIBPATH'].
 | 
| +#         """
 | 
| +
 | 
| +#         for pathname, pathval in args.items():
 | 
| +#             if not pathval:
 | 
| +#                 continue
 | 
| +#             if prepend:
 | 
| +#                 apply(self.PrependENVPath, (pathname, pathval))
 | 
| +#             else:
 | 
| +#                 apply(self.AppendENVPath, (pathname, pathval))
 | 
| +
 | 
| +
 | 
| +# Used by the FindSourceFiles() method, below.
 | 
| +# Stuck here for support of pre-2.2 Python versions.
 | 
| +def build_source(ss, result):
 | 
| +    for s in ss:
 | 
| +        if isinstance(s, SCons.Node.FS.Dir):
 | 
| +            build_source(s.all_children(), result)
 | 
| +        elif s.has_builder():
 | 
| +            build_source(s.sources, result)
 | 
| +        elif isinstance(s.disambiguate(), SCons.Node.FS.File):
 | 
| +            result.append(s)
 | 
| +
 | 
| +def default_decide_source(dependency, target, prev_ni):
 | 
| +    f = SCons.Defaults.DefaultEnvironment().decide_source
 | 
| +    return f(dependency, target, prev_ni)
 | 
| +
 | 
| +def default_decide_target(dependency, target, prev_ni):
 | 
| +    f = SCons.Defaults.DefaultEnvironment().decide_target
 | 
| +    return f(dependency, target, prev_ni)
 | 
| +
 | 
| +def default_copy_from_cache(src, dst):
 | 
| +    f = SCons.Defaults.DefaultEnvironment().copy_from_cache
 | 
| +    return f(src, dst)
 | 
| +
 | 
| +class Base(SubstitutionEnvironment):
 | 
| +    """Base class for "real" construction Environments.  These are the
 | 
| +    primary objects used to communicate dependency and construction
 | 
| +    information to the build engine.
 | 
| +
 | 
| +    Keyword arguments supplied when the construction Environment
 | 
| +    is created are construction variables used to initialize the
 | 
| +    Environment.
 | 
| +    """
 | 
| +
 | 
| +    if SCons.Memoize.use_memoizer:
 | 
| +        __metaclass__ = SCons.Memoize.Memoized_Metaclass
 | 
| +
 | 
| +    memoizer_counters = []
 | 
| +
 | 
| +    #######################################################################
 | 
| +    # This is THE class for interacting with the SCons build engine,
 | 
| +    # and it contains a lot of stuff, so we're going to try to keep this
 | 
| +    # a little organized by grouping the methods.
 | 
| +    #######################################################################
 | 
| +
 | 
| +    #######################################################################
 | 
| +    # Methods that make an Environment act like a dictionary.  These have
 | 
| +    # the expected standard names for Python mapping objects.  Note that
 | 
| +    # we don't actually make an Environment a subclass of UserDict for
 | 
| +    # performance reasons.  Note also that we only supply methods for
 | 
| +    # dictionary functionality that we actually need and use.
 | 
| +    #######################################################################
 | 
| +
 | 
| +    def __init__(self,
 | 
| +                 platform=None,
 | 
| +                 tools=None,
 | 
| +                 toolpath=None,
 | 
| +                 variables=None,
 | 
| +                 parse_flags = None,
 | 
| +                 **kw):
 | 
| +        """
 | 
| +        Initialization of a basic SCons construction environment,
 | 
| +        including setting up special construction variables like BUILDER,
 | 
| +        PLATFORM, etc., and searching for and applying available Tools.
 | 
| +
 | 
| +        Note that we do *not* call the underlying base class
 | 
| +        (SubsitutionEnvironment) initialization, because we need to
 | 
| +        initialize things in a very specific order that doesn't work
 | 
| +        with the much simpler base class initialization.
 | 
| +        """
 | 
| +        if __debug__: logInstanceCreation(self, 'Environment.Base')
 | 
| +        self._memo = {}
 | 
| +        self.fs = SCons.Node.FS.get_default_fs()
 | 
| +        self.ans = SCons.Node.Alias.default_ans
 | 
| +        self.lookup_list = SCons.Node.arg2nodes_lookups
 | 
| +        self._dict = semi_deepcopy(SCons.Defaults.ConstructionEnvironment)
 | 
| +        self._init_special()
 | 
| +        self.added_methods = []
 | 
| +
 | 
| +        # We don't use AddMethod, or define these as methods in this
 | 
| +        # class, because we *don't* want these functions to be bound
 | 
| +        # methods.  They need to operate independently so that the
 | 
| +        # settings will work properly regardless of whether a given
 | 
| +        # target ends up being built with a Base environment or an
 | 
| +        # OverrideEnvironment or what have you.
 | 
| +        self.decide_target = default_decide_target
 | 
| +        self.decide_source = default_decide_source
 | 
| +
 | 
| +        self.copy_from_cache = default_copy_from_cache
 | 
| +
 | 
| +        self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
 | 
| +
 | 
| +        if platform is None:
 | 
| +            platform = self._dict.get('PLATFORM', None)
 | 
| +            if platform is None:
 | 
| +                platform = SCons.Platform.Platform()
 | 
| +        if SCons.Util.is_String(platform):
 | 
| +            platform = SCons.Platform.Platform(platform)
 | 
| +        self._dict['PLATFORM'] = str(platform)
 | 
| +        platform(self)
 | 
| +
 | 
| +        # Apply the passed-in and customizable variables to the
 | 
| +        # environment before calling the tools, because they may use
 | 
| +        # some of them during initialization.
 | 
| +        if kw.has_key('options'):
 | 
| +            # Backwards compatibility:  they may stll be using the
 | 
| +            # old "options" keyword.
 | 
| +            variables = kw['options']
 | 
| +            del kw['options']
 | 
| +        apply(self.Replace, (), kw)
 | 
| +        keys = kw.keys()
 | 
| +        if variables:
 | 
| +            keys = keys + variables.keys()
 | 
| +            variables.Update(self)
 | 
| +
 | 
| +        save = {}
 | 
| +        for k in keys:
 | 
| +            try:
 | 
| +                save[k] = self._dict[k]
 | 
| +            except KeyError:
 | 
| +                # No value may have been set if they tried to pass in a
 | 
| +                # reserved variable name like TARGETS.
 | 
| +                pass
 | 
| +
 | 
| +        SCons.Tool.Initializers(self)
 | 
| +
 | 
| +        if tools is None:
 | 
| +            tools = self._dict.get('TOOLS', None)
 | 
| +            if tools is None:
 | 
| +                tools = ['default']
 | 
| +        apply_tools(self, tools, toolpath)
 | 
| +
 | 
| +        # Now restore the passed-in and customized variables
 | 
| +        # to the environment, since the values the user set explicitly
 | 
| +        # should override any values set by the tools.
 | 
| +        for key, val in save.items():
 | 
| +            self._dict[key] = val
 | 
| +
 | 
| +        # Finally, apply any flags to be merged in
 | 
| +        if parse_flags: self.MergeFlags(parse_flags)
 | 
| +
 | 
| +    #######################################################################
 | 
| +    # Utility methods that are primarily for internal use by SCons.
 | 
| +    # These begin with lower-case letters.
 | 
| +    #######################################################################
 | 
| +
 | 
| +    def get_builder(self, name):
 | 
| +        """Fetch the builder with the specified name from the environment.
 | 
| +        """
 | 
| +        try:
 | 
| +            return self._dict['BUILDERS'][name]
 | 
| +        except KeyError:
 | 
| +            return None
 | 
| +
 | 
| +    def get_CacheDir(self):
 | 
| +        try:
 | 
| +            path = self._CacheDir_path
 | 
| +        except AttributeError:
 | 
| +            path = SCons.Defaults.DefaultEnvironment()._CacheDir_path
 | 
| +        try:
 | 
| +            if path == self._last_CacheDir_path:
 | 
| +                return self._last_CacheDir
 | 
| +        except AttributeError:
 | 
| +            pass
 | 
| +        cd = SCons.CacheDir.CacheDir(path)
 | 
| +        self._last_CacheDir_path = path
 | 
| +        self._last_CacheDir = cd
 | 
| +        return cd
 | 
| +
 | 
| +    def get_factory(self, factory, default='File'):
 | 
| +        """Return a factory function for creating Nodes for this
 | 
| +        construction environment.
 | 
| +        """
 | 
| +        name = default
 | 
| +        try:
 | 
| +            is_node = issubclass(factory, SCons.Node.Node)
 | 
| +        except TypeError:
 | 
| +            # The specified factory isn't a Node itself--it's
 | 
| +            # most likely None, or possibly a callable.
 | 
| +            pass
 | 
| +        else:
 | 
| +            if is_node:
 | 
| +                # The specified factory is a Node (sub)class.  Try to
 | 
| +                # return the FS method that corresponds to the Node's
 | 
| +                # name--that is, we return self.fs.Dir if they want a Dir,
 | 
| +                # self.fs.File for a File, etc.
 | 
| +                try: name = factory.__name__
 | 
| +                except AttributeError: pass
 | 
| +                else: factory = None
 | 
| +        if not factory:
 | 
| +            # They passed us None, or we picked up a name from a specified
 | 
| +            # class, so return the FS method.  (Note that we *don't*
 | 
| +            # use our own self.{Dir,File} methods because that would
 | 
| +            # cause env.subst() to be called twice on the file name,
 | 
| +            # interfering with files that have $$ in them.)
 | 
| +            factory = getattr(self.fs, name)
 | 
| +        return factory
 | 
| +
 | 
| +    memoizer_counters.append(SCons.Memoize.CountValue('_gsm'))
 | 
| +
 | 
| +    def _gsm(self):
 | 
| +        try:
 | 
| +            return self._memo['_gsm']
 | 
| +        except KeyError:
 | 
| +            pass
 | 
| +
 | 
| +        result = {}
 | 
| +
 | 
| +        try:
 | 
| +            scanners = self._dict['SCANNERS']
 | 
| +        except KeyError:
 | 
| +            pass
 | 
| +        else:
 | 
| +            # Reverse the scanner list so that, if multiple scanners
 | 
| +            # claim they can scan the same suffix, earlier scanners
 | 
| +            # in the list will overwrite later scanners, so that
 | 
| +            # the result looks like a "first match" to the user.
 | 
| +            if not SCons.Util.is_List(scanners):
 | 
| +                scanners = [scanners]
 | 
| +            else:
 | 
| +                scanners = scanners[:] # copy so reverse() doesn't mod original
 | 
| +            scanners.reverse()
 | 
| +            for scanner in scanners:
 | 
| +                for k in scanner.get_skeys(self):
 | 
| +                    result[k] = scanner
 | 
| +
 | 
| +        self._memo['_gsm'] = result
 | 
| +
 | 
| +        return result
 | 
| +
 | 
| +    def get_scanner(self, skey):
 | 
| +        """Find the appropriate scanner given a key (usually a file suffix).
 | 
| +        """
 | 
| +        return self._gsm().get(skey)
 | 
| +
 | 
| +    def scanner_map_delete(self, kw=None):
 | 
| +        """Delete the cached scanner map (if we need to).
 | 
| +        """
 | 
| +        try:
 | 
| +            del self._memo['_gsm']
 | 
| +        except KeyError:
 | 
| +            pass
 | 
| +
 | 
| +    def _update(self, dict):
 | 
| +        """Update an environment's values directly, bypassing the normal
 | 
| +        checks that occur when users try to set items.
 | 
| +        """
 | 
| +        self._dict.update(dict)
 | 
| +
 | 
| +    def get_src_sig_type(self):
 | 
| +        try:
 | 
| +            return self.src_sig_type
 | 
| +        except AttributeError:
 | 
| +            t = SCons.Defaults.DefaultEnvironment().src_sig_type
 | 
| +            self.src_sig_type = t
 | 
| +            return t
 | 
| +
 | 
| +    def get_tgt_sig_type(self):
 | 
| +        try:
 | 
| +            return self.tgt_sig_type
 | 
| +        except AttributeError:
 | 
| +            t = SCons.Defaults.DefaultEnvironment().tgt_sig_type
 | 
| +            self.tgt_sig_type = t
 | 
| +            return t
 | 
| +
 | 
| +    #######################################################################
 | 
| +    # Public methods for manipulating an Environment.  These begin with
 | 
| +    # upper-case letters.  The essential characteristic of methods in
 | 
| +    # this section is that they do *not* have corresponding same-named
 | 
| +    # global functions.  For example, a stand-alone Append() function
 | 
| +    # makes no sense, because Append() is all about appending values to
 | 
| +    # an Environment's construction variables.
 | 
| +    #######################################################################
 | 
| +
 | 
| +    def Append(self, **kw):
 | 
| +        """Append values to existing construction variables
 | 
| +        in an Environment.
 | 
| +        """
 | 
| +        kw = copy_non_reserved_keywords(kw)
 | 
| +        for key, val in kw.items():
 | 
| +            # It would be easier on the eyes to write this using
 | 
| +            # "continue" statements whenever we finish processing an item,
 | 
| +            # but Python 1.5.2 apparently doesn't let you use "continue"
 | 
| +            # within try:-except: blocks, so we have to nest our code.
 | 
| +            try:
 | 
| +                orig = self._dict[key]
 | 
| +            except KeyError:
 | 
| +                # No existing variable in the environment, so just set
 | 
| +                # it to the new value.
 | 
| +                self._dict[key] = val
 | 
| +            else:
 | 
| +                try:
 | 
| +                    # Check if the original looks like a dictionary.
 | 
| +                    # If it is, we can't just try adding the value because
 | 
| +                    # dictionaries don't have __add__() methods, and
 | 
| +                    # things like UserList will incorrectly coerce the
 | 
| +                    # original dict to a list (which we don't want).
 | 
| +                    update_dict = orig.update
 | 
| +                except AttributeError:
 | 
| +                    try:
 | 
| +                        # Most straightforward:  just try to add them
 | 
| +                        # together.  This will work in most cases, when the
 | 
| +                        # original and new values are of compatible types.
 | 
| +                        self._dict[key] = orig + val
 | 
| +                    except (KeyError, TypeError):
 | 
| +                        try:
 | 
| +                            # Check if the original is a list.
 | 
| +                            add_to_orig = orig.append
 | 
| +                        except AttributeError:
 | 
| +                            # The original isn't a list, but the new
 | 
| +                            # value is (by process of elimination),
 | 
| +                            # so insert the original in the new value
 | 
| +                            # (if there's one to insert) and replace
 | 
| +                            # the variable with it.
 | 
| +                            if orig:
 | 
| +                                val.insert(0, orig)
 | 
| +                            self._dict[key] = val
 | 
| +                        else:
 | 
| +                            # The original is a list, so append the new
 | 
| +                            # value to it (if there's a value to append).
 | 
| +                            if val:
 | 
| +                                add_to_orig(val)
 | 
| +                else:
 | 
| +                    # The original looks like a dictionary, so update it
 | 
| +                    # based on what we think the value looks like.
 | 
| +                    if SCons.Util.is_List(val):
 | 
| +                        for v in val:
 | 
| +                            orig[v] = None
 | 
| +                    else:
 | 
| +                        try:
 | 
| +                            update_dict(val)
 | 
| +                        except (AttributeError, TypeError, ValueError):
 | 
| +                            if SCons.Util.is_Dict(val):
 | 
| +                                for k, v in val.items():
 | 
| +                                    orig[k] = v
 | 
| +                            else:
 | 
| +                                orig[val] = None
 | 
| +        self.scanner_map_delete(kw)
 | 
| +
 | 
| +    def AppendENVPath(self, name, newpath, envname = 'ENV', 
 | 
| +                      sep = os.pathsep, delete_existing=1):
 | 
| +        """Append path elements to the path 'name' in the 'ENV'
 | 
| +        dictionary for this environment.  Will only add any particular
 | 
| +        path once, and will normpath and normcase all paths to help
 | 
| +        assure this.  This can also handle the case where the env
 | 
| +        variable is a list instead of a string.
 | 
| +
 | 
| +        If delete_existing is 0, a newpath which is already in the path
 | 
| +        will not be moved to the end (it will be left where it is).
 | 
| +        """
 | 
| +
 | 
| +        orig = ''
 | 
| +        if self._dict.has_key(envname) and self._dict[envname].has_key(name):
 | 
| +            orig = self._dict[envname][name]
 | 
| +
 | 
| +        nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing)
 | 
| +
 | 
| +        if not self._dict.has_key(envname):
 | 
| +            self._dict[envname] = {}
 | 
| +
 | 
| +        self._dict[envname][name] = nv
 | 
| +
 | 
| +    def AppendUnique(self, delete_existing=0, **kw):
 | 
| +        """Append values to existing construction variables
 | 
| +        in an Environment, if they're not already there.
 | 
| +        If delete_existing is 1, removes existing values first, so
 | 
| +        values move to end.
 | 
| +        """
 | 
| +        kw = copy_non_reserved_keywords(kw)
 | 
| +        for key, val in kw.items():
 | 
| +            if not self._dict.has_key(key) or self._dict[key] in ('', None):
 | 
| +                self._dict[key] = val
 | 
| +            elif SCons.Util.is_Dict(self._dict[key]) and \
 | 
| +                 SCons.Util.is_Dict(val):
 | 
| +                self._dict[key].update(val)
 | 
| +            elif SCons.Util.is_List(val):
 | 
| +                dk = self._dict[key]
 | 
| +                if not SCons.Util.is_List(dk):
 | 
| +                    dk = [dk]
 | 
| +                if delete_existing:
 | 
| +                    dk = filter(lambda x, val=val: x not in val, dk)
 | 
| +                else:
 | 
| +                    val = filter(lambda x, dk=dk: x not in dk, val)
 | 
| +                self._dict[key] = dk + val
 | 
| +            else:
 | 
| +                dk = self._dict[key]
 | 
| +                if SCons.Util.is_List(dk):
 | 
| +                    # By elimination, val is not a list.  Since dk is a
 | 
| +                    # list, wrap val in a list first.
 | 
| +                    if delete_existing:
 | 
| +                        dk = filter(lambda x, val=val: x not in val, dk)
 | 
| +                        self._dict[key] = dk + [val]
 | 
| +                    else:
 | 
| +                        if not val in dk:
 | 
| +                            self._dict[key] = dk + [val]
 | 
| +                else:
 | 
| +                    if delete_existing:
 | 
| +                        dk = filter(lambda x, val=val: x not in val, dk)
 | 
| +                    self._dict[key] = dk + val
 | 
| +        self.scanner_map_delete(kw)
 | 
| +
 | 
| +    def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw):
 | 
| +        """Return a copy of a construction Environment.  The
 | 
| +        copy is like a Python "deep copy"--that is, independent
 | 
| +        copies are made recursively of each objects--except that
 | 
| +        a reference is copied when an object is not deep-copyable
 | 
| +        (like a function).  There are no references to any mutable
 | 
| +        objects in the original Environment.
 | 
| +        """
 | 
| +        clone = copy.copy(self)
 | 
| +        clone._dict = semi_deepcopy(self._dict)
 | 
| +
 | 
| +        try:
 | 
| +            cbd = clone._dict['BUILDERS']
 | 
| +        except KeyError:
 | 
| +            pass
 | 
| +        else:
 | 
| +            clone._dict['BUILDERS'] = BuilderDict(cbd, clone)
 | 
| +
 | 
| +        # Check the methods added via AddMethod() and re-bind them to
 | 
| +        # the cloned environment.  Only do this if the attribute hasn't
 | 
| +        # been overwritten by the user explicitly and still points to
 | 
| +        # the added method.
 | 
| +        clone.added_methods = []
 | 
| +        for mw in self.added_methods:
 | 
| +            if mw == getattr(self, mw.name):
 | 
| +                clone.added_methods.append(mw.clone(clone))
 | 
| +
 | 
| +        clone._memo = {}
 | 
| +
 | 
| +        # Apply passed-in variables before the tools
 | 
| +        # so the tools can use the new variables
 | 
| +        kw = copy_non_reserved_keywords(kw)
 | 
| +        new = {}
 | 
| +        for key, value in kw.items():
 | 
| +            new[key] = SCons.Subst.scons_subst_once(value, self, key)
 | 
| +        apply(clone.Replace, (), new)
 | 
| +
 | 
| +        apply_tools(clone, tools, toolpath)
 | 
| +
 | 
| +        # apply them again in case the tools overwrote them
 | 
| +        apply(clone.Replace, (), new)        
 | 
| +
 | 
| +        # Finally, apply any flags to be merged in
 | 
| +        if parse_flags: clone.MergeFlags(parse_flags)
 | 
| +
 | 
| +        if __debug__: logInstanceCreation(self, 'Environment.EnvironmentClone')
 | 
| +        return clone
 | 
| +
 | 
| +    def Copy(self, *args, **kw):
 | 
| +        global _warn_copy_deprecated
 | 
| +        if _warn_copy_deprecated:
 | 
| +            msg = "The env.Copy() method is deprecated; use the env.Clone() method instead."
 | 
| +            SCons.Warnings.warn(SCons.Warnings.DeprecatedCopyWarning, msg)
 | 
| +            _warn_copy_deprecated = False
 | 
| +        return apply(self.Clone, args, kw)
 | 
| +
 | 
| +    def _changed_build(self, dependency, target, prev_ni):
 | 
| +        if dependency.changed_state(target, prev_ni):
 | 
| +            return 1
 | 
| +        return self.decide_source(dependency, target, prev_ni)
 | 
| +
 | 
| +    def _changed_content(self, dependency, target, prev_ni):
 | 
| +        return dependency.changed_content(target, prev_ni)
 | 
| +
 | 
| +    def _changed_source(self, dependency, target, prev_ni):
 | 
| +        target_env = dependency.get_build_env()
 | 
| +        type = target_env.get_tgt_sig_type()
 | 
| +        if type == 'source':
 | 
| +            return target_env.decide_source(dependency, target, prev_ni)
 | 
| +        else:
 | 
| +            return target_env.decide_target(dependency, target, prev_ni)
 | 
| +
 | 
| +    def _changed_timestamp_then_content(self, dependency, target, prev_ni):
 | 
| +        return dependency.changed_timestamp_then_content(target, prev_ni)
 | 
| +
 | 
| +    def _changed_timestamp_newer(self, dependency, target, prev_ni):
 | 
| +        return dependency.changed_timestamp_newer(target, prev_ni)
 | 
| +
 | 
| +    def _changed_timestamp_match(self, dependency, target, prev_ni):
 | 
| +        return dependency.changed_timestamp_match(target, prev_ni)
 | 
| +
 | 
| +    def _copy_from_cache(self, src, dst):
 | 
| +        return self.fs.copy(src, dst)
 | 
| +
 | 
| +    def _copy2_from_cache(self, src, dst):
 | 
| +        return self.fs.copy2(src, dst)
 | 
| +
 | 
| +    def Decider(self, function):
 | 
| +        copy_function = self._copy2_from_cache
 | 
| +        if function in ('MD5', 'content'):
 | 
| +            if not SCons.Util.md5:
 | 
| +                raise UserError, "MD5 signatures are not available in this version of Python."
 | 
| +            function = self._changed_content
 | 
| +        elif function == 'MD5-timestamp':
 | 
| +            function = self._changed_timestamp_then_content
 | 
| +        elif function in ('timestamp-newer', 'make'):
 | 
| +            function = self._changed_timestamp_newer
 | 
| +            copy_function = self._copy_from_cache
 | 
| +        elif function == 'timestamp-match':
 | 
| +            function = self._changed_timestamp_match
 | 
| +        elif not callable(function):
 | 
| +            raise UserError, "Unknown Decider value %s" % repr(function)
 | 
| +
 | 
| +        # We don't use AddMethod because we don't want to turn the
 | 
| +        # function, which only expects three arguments, into a bound
 | 
| +        # method, which would add self as an initial, fourth argument.
 | 
| +        self.decide_target = function
 | 
| +        self.decide_source = function
 | 
| +
 | 
| +        self.copy_from_cache = copy_function
 | 
| +
 | 
| +    def Detect(self, progs):
 | 
| +        """Return the first available program in progs.
 | 
| +        """
 | 
| +        if not SCons.Util.is_List(progs):
 | 
| +            progs = [ progs ]
 | 
| +        for prog in progs:
 | 
| +            path = self.WhereIs(prog)
 | 
| +            if path: return prog
 | 
| +        return None
 | 
| +
 | 
| +    def Dictionary(self, *args):
 | 
| +        if not args:
 | 
| +            return self._dict
 | 
| +        dlist = map(lambda x, s=self: s._dict[x], args)
 | 
| +        if len(dlist) == 1:
 | 
| +            dlist = dlist[0]
 | 
| +        return dlist
 | 
| +
 | 
| +    def Dump(self, key = None):
 | 
| +        """
 | 
| +        Using the standard Python pretty printer, dump the contents of the
 | 
| +        scons build environment to stdout.
 | 
| +
 | 
| +        If the key passed in is anything other than None, then that will
 | 
| +        be used as an index into the build environment dictionary and
 | 
| +        whatever is found there will be fed into the pretty printer. Note
 | 
| +        that this key is case sensitive.
 | 
| +        """
 | 
| +        import pprint
 | 
| +        pp = pprint.PrettyPrinter(indent=2)
 | 
| +        if key:
 | 
| +            dict = self.Dictionary(key)
 | 
| +        else:
 | 
| +            dict = self.Dictionary()
 | 
| +        return pp.pformat(dict)
 | 
| +
 | 
| +    def FindIxes(self, paths, prefix, suffix):
 | 
| +        """
 | 
| +        Search a list of paths for something that matches the prefix and suffix.
 | 
| +
 | 
| +        paths - the list of paths or nodes.
 | 
| +        prefix - construction variable for the prefix.
 | 
| +        suffix - construction variable for the suffix.
 | 
| +        """
 | 
| +
 | 
| +        suffix = self.subst('$'+suffix)
 | 
| +        prefix = self.subst('$'+prefix)
 | 
| +
 | 
| +        for path in paths:
 | 
| +            dir,name = os.path.split(str(path))
 | 
| +            if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
 | 
| +                return path
 | 
| +
 | 
| +    def ParseConfig(self, command, function=None, unique=1):
 | 
| +        """
 | 
| +        Use the specified function to parse the output of the command
 | 
| +        in order to modify the current environment.  The 'command' can
 | 
| +        be a string or a list of strings representing a command and
 | 
| +        its arguments.  'Function' is an optional argument that takes
 | 
| +        the environment, the output of the command, and the unique flag.
 | 
| +        If no function is specified, MergeFlags, which treats the output
 | 
| +        as the result of a typical 'X-config' command (i.e. gtk-config),
 | 
| +        will merge the output into the appropriate variables.
 | 
| +        """
 | 
| +        if function is None:
 | 
| +            def parse_conf(env, cmd, unique=unique):
 | 
| +                return env.MergeFlags(cmd, unique)
 | 
| +            function = parse_conf
 | 
| +        if SCons.Util.is_List(command):
 | 
| +            command = string.join(command)
 | 
| +        command = self.subst(command)
 | 
| +        return function(self, self.backtick(command))
 | 
| +
 | 
| +    def ParseDepends(self, filename, must_exist=None, only_one=0):
 | 
| +        """
 | 
| +        Parse a mkdep-style file for explicit dependencies.  This is
 | 
| +        completely abusable, and should be unnecessary in the "normal"
 | 
| +        case of proper SCons configuration, but it may help make
 | 
| +        the transition from a Make hierarchy easier for some people
 | 
| +        to swallow.  It can also be genuinely useful when using a tool
 | 
| +        that can write a .d file, but for which writing a scanner would
 | 
| +        be too complicated.
 | 
| +        """
 | 
| +        filename = self.subst(filename)
 | 
| +        try:
 | 
| +            fp = open(filename, 'r')
 | 
| +        except IOError:
 | 
| +            if must_exist:
 | 
| +                raise
 | 
| +            return
 | 
| +        lines = SCons.Util.LogicalLines(fp).readlines()
 | 
| +        lines = filter(lambda l: l[0] != '#', lines)
 | 
| +        tdlist = []
 | 
| +        for line in lines:
 | 
| +            try:
 | 
| +                target, depends = string.split(line, ':', 1)
 | 
| +            except (AttributeError, TypeError, ValueError):
 | 
| +                # Python 1.5.2 throws TypeError if line isn't a string,
 | 
| +                # Python 2.x throws AttributeError because it tries
 | 
| +                # to call line.split().  Either can throw ValueError
 | 
| +                # if the line doesn't split into two or more elements.
 | 
| +                pass
 | 
| +            else:
 | 
| +                tdlist.append((string.split(target), string.split(depends)))
 | 
| +        if only_one:
 | 
| +            targets = reduce(lambda x, y: x+y, map(lambda p: p[0], tdlist))
 | 
| +            if len(targets) > 1:
 | 
| +                raise SCons.Errors.UserError, "More than one dependency target found in `%s':  %s" % (filename, targets)
 | 
| +        for target, depends in tdlist:
 | 
| +            self.Depends(target, depends)
 | 
| +
 | 
| +    def Platform(self, platform):
 | 
| +        platform = self.subst(platform)
 | 
| +        return SCons.Platform.Platform(platform)(self)
 | 
| +
 | 
| +    def Prepend(self, **kw):
 | 
| +        """Prepend values to existing construction variables
 | 
| +        in an Environment.
 | 
| +        """
 | 
| +        kw = copy_non_reserved_keywords(kw)
 | 
| +        for key, val in kw.items():
 | 
| +            # It would be easier on the eyes to write this using
 | 
| +            # "continue" statements whenever we finish processing an item,
 | 
| +            # but Python 1.5.2 apparently doesn't let you use "continue"
 | 
| +            # within try:-except: blocks, so we have to nest our code.
 | 
| +            try:
 | 
| +                orig = self._dict[key]
 | 
| +            except KeyError:
 | 
| +                # No existing variable in the environment, so just set
 | 
| +                # it to the new value.
 | 
| +                self._dict[key] = val
 | 
| +            else:
 | 
| +                try:
 | 
| +                    # Check if the original looks like a dictionary.
 | 
| +                    # If it is, we can't just try adding the value because
 | 
| +                    # dictionaries don't have __add__() methods, and
 | 
| +                    # things like UserList will incorrectly coerce the
 | 
| +                    # original dict to a list (which we don't want).
 | 
| +                    update_dict = orig.update
 | 
| +                except AttributeError:
 | 
| +                    try:
 | 
| +                        # Most straightforward:  just try to add them
 | 
| +                        # together.  This will work in most cases, when the
 | 
| +                        # original and new values are of compatible types.
 | 
| +                        self._dict[key] = val + orig
 | 
| +                    except (KeyError, TypeError):
 | 
| +                        try:
 | 
| +                            # Check if the added value is a list.
 | 
| +                            add_to_val = val.append
 | 
| +                        except AttributeError:
 | 
| +                            # The added value isn't a list, but the
 | 
| +                            # original is (by process of elimination),
 | 
| +                            # so insert the the new value in the original
 | 
| +                            # (if there's one to insert).
 | 
| +                            if val:
 | 
| +                                orig.insert(0, val)
 | 
| +                        else:
 | 
| +                            # The added value is a list, so append
 | 
| +                            # the original to it (if there's a value
 | 
| +                            # to append).
 | 
| +                            if orig:
 | 
| +                                add_to_val(orig)
 | 
| +                            self._dict[key] = val
 | 
| +                else:
 | 
| +                    # The original looks like a dictionary, so update it
 | 
| +                    # based on what we think the value looks like.
 | 
| +                    if SCons.Util.is_List(val):
 | 
| +                        for v in val:
 | 
| +                            orig[v] = None
 | 
| +                    else:
 | 
| +                        try:
 | 
| +                            update_dict(val)
 | 
| +                        except (AttributeError, TypeError, ValueError):
 | 
| +                            if SCons.Util.is_Dict(val):
 | 
| +                                for k, v in val.items():
 | 
| +                                    orig[k] = v
 | 
| +                            else:
 | 
| +                                orig[val] = None
 | 
| +        self.scanner_map_delete(kw)
 | 
| +
 | 
| +    def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep,
 | 
| +                       delete_existing=1):
 | 
| +        """Prepend path elements to the path 'name' in the 'ENV'
 | 
| +        dictionary for this environment.  Will only add any particular
 | 
| +        path once, and will normpath and normcase all paths to help
 | 
| +        assure this.  This can also handle the case where the env
 | 
| +        variable is a list instead of a string.
 | 
| +
 | 
| +        If delete_existing is 0, a newpath which is already in the path
 | 
| +        will not be moved to the front (it will be left where it is).
 | 
| +        """
 | 
| +
 | 
| +        orig = ''
 | 
| +        if self._dict.has_key(envname) and self._dict[envname].has_key(name):
 | 
| +            orig = self._dict[envname][name]
 | 
| +
 | 
| +        nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing)
 | 
| +
 | 
| +        if not self._dict.has_key(envname):
 | 
| +            self._dict[envname] = {}
 | 
| +
 | 
| +        self._dict[envname][name] = nv
 | 
| +
 | 
| +    def PrependUnique(self, delete_existing=0, **kw):
 | 
| +        """Prepend values to existing construction variables
 | 
| +        in an Environment, if they're not already there.
 | 
| +        If delete_existing is 1, removes existing values first, so
 | 
| +        values move to front.
 | 
| +        """
 | 
| +        kw = copy_non_reserved_keywords(kw)
 | 
| +        for key, val in kw.items():
 | 
| +            if not self._dict.has_key(key) or self._dict[key] in ('', None):
 | 
| +                self._dict[key] = val
 | 
| +            elif SCons.Util.is_Dict(self._dict[key]) and \
 | 
| +                 SCons.Util.is_Dict(val):
 | 
| +                self._dict[key].update(val)
 | 
| +            elif SCons.Util.is_List(val):
 | 
| +                dk = self._dict[key]
 | 
| +                if not SCons.Util.is_List(dk):
 | 
| +                    dk = [dk]
 | 
| +                if delete_existing:
 | 
| +                    dk = filter(lambda x, val=val: x not in val, dk)
 | 
| +                else:
 | 
| +                    val = filter(lambda x, dk=dk: x not in dk, val)
 | 
| +                self._dict[key] = val + dk
 | 
| +            else:
 | 
| +                dk = self._dict[key]
 | 
| +                if SCons.Util.is_List(dk):
 | 
| +                    # By elimination, val is not a list.  Since dk is a
 | 
| +                    # list, wrap val in a list first.
 | 
| +                    if delete_existing:
 | 
| +                        dk = filter(lambda x, val=val: x not in val, dk)
 | 
| +                        self._dict[key] = [val] + dk
 | 
| +                    else:
 | 
| +                        if not val in dk:
 | 
| +                            self._dict[key] = [val] + dk
 | 
| +                else:
 | 
| +                    if delete_existing:
 | 
| +                        dk = filter(lambda x, val=val: x not in val, dk)
 | 
| +                    self._dict[key] = val + dk
 | 
| +        self.scanner_map_delete(kw)
 | 
| +
 | 
| +    def Replace(self, **kw):
 | 
| +        """Replace existing construction variables in an Environment
 | 
| +        with new construction variables and/or values.
 | 
| +        """
 | 
| +        try:
 | 
| +            kwbd = kw['BUILDERS']
 | 
| +        except KeyError:
 | 
| +            pass
 | 
| +        else:
 | 
| +            kwbd = semi_deepcopy(kwbd)
 | 
| +            del kw['BUILDERS']
 | 
| +            self.__setitem__('BUILDERS', kwbd)
 | 
| +        kw = copy_non_reserved_keywords(kw)
 | 
| +        self._update(semi_deepcopy(kw))
 | 
| +        self.scanner_map_delete(kw)
 | 
| +
 | 
| +    def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
 | 
| +        """
 | 
| +        Replace old_prefix with new_prefix and old_suffix with new_suffix.
 | 
| +
 | 
| +        env - Environment used to interpolate variables.
 | 
| +        path - the path that will be modified.
 | 
| +        old_prefix - construction variable for the old prefix.
 | 
| +        old_suffix - construction variable for the old suffix.
 | 
| +        new_prefix - construction variable for the new prefix.
 | 
| +        new_suffix - construction variable for the new suffix.
 | 
| +        """
 | 
| +        old_prefix = self.subst('$'+old_prefix)
 | 
| +        old_suffix = self.subst('$'+old_suffix)
 | 
| +
 | 
| +        new_prefix = self.subst('$'+new_prefix)
 | 
| +        new_suffix = self.subst('$'+new_suffix)
 | 
| +
 | 
| +        dir,name = os.path.split(str(path))
 | 
| +        if name[:len(old_prefix)] == old_prefix:
 | 
| +            name = name[len(old_prefix):]
 | 
| +        if name[-len(old_suffix):] == old_suffix:
 | 
| +            name = name[:-len(old_suffix)]
 | 
| +        return os.path.join(dir, new_prefix+name+new_suffix)
 | 
| +
 | 
| +    def SetDefault(self, **kw):
 | 
| +        for k in kw.keys():
 | 
| +            if self._dict.has_key(k):
 | 
| +                del kw[k]
 | 
| +        apply(self.Replace, (), kw)
 | 
| +
 | 
| +    def _find_toolpath_dir(self, tp):
 | 
| +        return self.fs.Dir(self.subst(tp)).srcnode().abspath
 | 
| +
 | 
| +    def Tool(self, tool, toolpath=None, **kw):
 | 
| +        if SCons.Util.is_String(tool):
 | 
| +            tool = self.subst(tool)
 | 
| +            if toolpath is None:
 | 
| +                toolpath = self.get('toolpath', [])
 | 
| +            toolpath = map(self._find_toolpath_dir, toolpath)
 | 
| +            tool = apply(SCons.Tool.Tool, (tool, toolpath), kw)
 | 
| +        tool(self)
 | 
| +
 | 
| +    def WhereIs(self, prog, path=None, pathext=None, reject=[]):
 | 
| +        """Find prog in the path.
 | 
| +        """
 | 
| +        if path is None:
 | 
| +            try:
 | 
| +                path = self['ENV']['PATH']
 | 
| +            except KeyError:
 | 
| +                pass
 | 
| +        elif SCons.Util.is_String(path):
 | 
| +            path = self.subst(path)
 | 
| +        if pathext is None:
 | 
| +            try:
 | 
| +                pathext = self['ENV']['PATHEXT']
 | 
| +            except KeyError:
 | 
| +                pass
 | 
| +        elif SCons.Util.is_String(pathext):
 | 
| +            pathext = self.subst(pathext)
 | 
| +        prog = self.subst(prog)
 | 
| +        path = SCons.Util.WhereIs(prog, path, pathext, reject)
 | 
| +        if path: return path
 | 
| +        return None
 | 
| +
 | 
| +    #######################################################################
 | 
| +    # Public methods for doing real "SCons stuff" (manipulating
 | 
| +    # dependencies, setting attributes on targets, etc.).  These begin
 | 
| +    # with upper-case letters.  The essential characteristic of methods
 | 
| +    # in this section is that they all *should* have corresponding
 | 
| +    # same-named global functions.
 | 
| +    #######################################################################
 | 
| +
 | 
| +    def Action(self, *args, **kw):
 | 
| +        def subst_string(a, self=self):
 | 
| +            if SCons.Util.is_String(a):
 | 
| +                a = self.subst(a)
 | 
| +            return a
 | 
| +        nargs = map(subst_string, args)
 | 
| +        nkw = self.subst_kw(kw)
 | 
| +        return apply(SCons.Action.Action, nargs, nkw)
 | 
| +
 | 
| +    def AddPreAction(self, files, action):
 | 
| +        nodes = self.arg2nodes(files, self.fs.Entry)
 | 
| +        action = SCons.Action.Action(action)
 | 
| +        uniq = {}
 | 
| +        for executor in map(lambda n: n.get_executor(), nodes):
 | 
| +            uniq[executor] = 1
 | 
| +        for executor in uniq.keys():
 | 
| +            executor.add_pre_action(action)
 | 
| +        return nodes
 | 
| +
 | 
| +    def AddPostAction(self, files, action):
 | 
| +        nodes = self.arg2nodes(files, self.fs.Entry)
 | 
| +        action = SCons.Action.Action(action)
 | 
| +        uniq = {}
 | 
| +        for executor in map(lambda n: n.get_executor(), nodes):
 | 
| +            uniq[executor] = 1
 | 
| +        for executor in uniq.keys():
 | 
| +            executor.add_post_action(action)
 | 
| +        return nodes
 | 
| +
 | 
| +    def Alias(self, target, source=[], action=None, **kw):
 | 
| +        tlist = self.arg2nodes(target, self.ans.Alias)
 | 
| +        if not SCons.Util.is_List(source):
 | 
| +            source = [source]
 | 
| +        source = filter(None, source)
 | 
| +
 | 
| +        if not action:
 | 
| +            if not source:
 | 
| +                # There are no source files and no action, so just
 | 
| +                # return a target list of classic Alias Nodes, without
 | 
| +                # any builder.  The externally visible effect is that
 | 
| +                # this will make the wrapping Script.BuildTask class
 | 
| +                # say that there's "Nothing to be done" for this Alias,
 | 
| +                # instead of that it's "up to date."
 | 
| +                return tlist
 | 
| +
 | 
| +            # No action, but there are sources.  Re-call all the target
 | 
| +            # builders to add the sources to each target.
 | 
| +            result = []
 | 
| +            for t in tlist:
 | 
| +                bld = t.get_builder(AliasBuilder)
 | 
| +                result.extend(bld(self, t, source))
 | 
| +            return result
 | 
| +
 | 
| +        nkw = self.subst_kw(kw)
 | 
| +        nkw.update({
 | 
| +            'action'            : SCons.Action.Action(action),
 | 
| +            'source_factory'    : self.fs.Entry,
 | 
| +            'multi'             : 1,
 | 
| +            'is_explicit'       : None,
 | 
| +        })
 | 
| +        bld = apply(SCons.Builder.Builder, (), nkw)
 | 
| +
 | 
| +        # Apply the Builder separately to each target so that the Aliases
 | 
| +        # stay separate.  If we did one "normal" Builder call with the
 | 
| +        # whole target list, then all of the target Aliases would be
 | 
| +        # associated under a single Executor.
 | 
| +        result = []
 | 
| +        for t in tlist:
 | 
| +            # Calling the convert() method will cause a new Executor to be
 | 
| +            # created from scratch, so we have to explicitly initialize
 | 
| +            # it with the target's existing sources, plus our new ones,
 | 
| +            # so nothing gets lost.
 | 
| +            b = t.get_builder()
 | 
| +            if b is None or b is AliasBuilder:
 | 
| +                b = bld
 | 
| +            else:
 | 
| +                nkw['action'] = b.action + action
 | 
| +                b = apply(SCons.Builder.Builder, (), nkw)
 | 
| +            t.convert()
 | 
| +            result.extend(b(self, t, t.sources + source))
 | 
| +        return result
 | 
| +
 | 
| +    def AlwaysBuild(self, *targets):
 | 
| +        tlist = []
 | 
| +        for t in targets:
 | 
| +            tlist.extend(self.arg2nodes(t, self.fs.Entry))
 | 
| +        for t in tlist:
 | 
| +            t.set_always_build()
 | 
| +        return tlist
 | 
| +
 | 
| +    def BuildDir(self, *args, **kw):
 | 
| +        if kw.has_key('build_dir'):
 | 
| +            kw['variant_dir'] = kw['build_dir']
 | 
| +            del kw['build_dir']
 | 
| +        return apply(self.VariantDir, args, kw)
 | 
| +
 | 
| +    def Builder(self, **kw):
 | 
| +        nkw = self.subst_kw(kw)
 | 
| +        return apply(SCons.Builder.Builder, [], nkw)
 | 
| +
 | 
| +    def CacheDir(self, path):
 | 
| +        import SCons.CacheDir
 | 
| +        if not path is None:
 | 
| +            path = self.subst(path)
 | 
| +        self._CacheDir_path = path
 | 
| +
 | 
| +    def Clean(self, targets, files):
 | 
| +        global CleanTargets
 | 
| +        tlist = self.arg2nodes(targets, self.fs.Entry)
 | 
| +        flist = self.arg2nodes(files, self.fs.Entry)
 | 
| +        for t in tlist:
 | 
| +            try:
 | 
| +                CleanTargets[t].extend(flist)
 | 
| +            except KeyError:
 | 
| +                CleanTargets[t] = flist
 | 
| +
 | 
| +    def Configure(self, *args, **kw):
 | 
| +        nargs = [self]
 | 
| +        if args:
 | 
| +            nargs = nargs + self.subst_list(args)[0]
 | 
| +        nkw = self.subst_kw(kw)
 | 
| +        nkw['_depth'] = kw.get('_depth', 0) + 1
 | 
| +        try:
 | 
| +            nkw['custom_tests'] = self.subst_kw(nkw['custom_tests'])
 | 
| +        except KeyError:
 | 
| +            pass
 | 
| +        return apply(SCons.SConf.SConf, nargs, nkw)
 | 
| +
 | 
| +    def Command(self, target, source, action, **kw):
 | 
| +        """Builds the supplied target files from the supplied
 | 
| +        source files using the supplied action.  Action may
 | 
| +        be any type that the Builder constructor will accept
 | 
| +        for an action."""
 | 
| +        bkw = {
 | 
| +            'action' : action,
 | 
| +            'target_factory' : self.fs.Entry,
 | 
| +            'source_factory' : self.fs.Entry,
 | 
| +        }
 | 
| +        try: bkw['source_scanner'] = kw['source_scanner']
 | 
| +        except KeyError: pass
 | 
| +        else: del kw['source_scanner']
 | 
| +        bld = apply(SCons.Builder.Builder, (), bkw)
 | 
| +        return apply(bld, (self, target, source), kw)
 | 
| +
 | 
| +    def Depends(self, target, dependency):
 | 
| +        """Explicity specify that 'target's depend on 'dependency'."""
 | 
| +        tlist = self.arg2nodes(target, self.fs.Entry)
 | 
| +        dlist = self.arg2nodes(dependency, self.fs.Entry)
 | 
| +        for t in tlist:
 | 
| +            t.add_dependency(dlist)
 | 
| +        return tlist
 | 
| +
 | 
| +    def Dir(self, name, *args, **kw):
 | 
| +        """
 | 
| +        """
 | 
| +        s = self.subst(name)
 | 
| +        if SCons.Util.is_Sequence(s):
 | 
| +            result=[]
 | 
| +            for e in s:
 | 
| +                result.append(apply(self.fs.Dir, (e,) + args, kw))
 | 
| +            return result
 | 
| +        return apply(self.fs.Dir, (s,) + args, kw)
 | 
| +
 | 
| +    def NoClean(self, *targets):
 | 
| +        """Tags a target so that it will not be cleaned by -c"""
 | 
| +        tlist = []
 | 
| +        for t in targets:
 | 
| +            tlist.extend(self.arg2nodes(t, self.fs.Entry))
 | 
| +        for t in tlist:
 | 
| +            t.set_noclean()
 | 
| +        return tlist
 | 
| +
 | 
| +    def NoCache(self, *targets):
 | 
| +        """Tags a target so that it will not be cached"""
 | 
| +        tlist = []
 | 
| +        for t in targets:
 | 
| +            tlist.extend(self.arg2nodes(t, self.fs.Entry))
 | 
| +        for t in tlist:
 | 
| +            t.set_nocache()
 | 
| +        return tlist
 | 
| +
 | 
| +    def Entry(self, name, *args, **kw):
 | 
| +        """
 | 
| +        """
 | 
| +        s = self.subst(name)
 | 
| +        if SCons.Util.is_Sequence(s):
 | 
| +            result=[]
 | 
| +            for e in s:
 | 
| +                result.append(apply(self.fs.Entry, (e,) + args, kw))
 | 
| +            return result
 | 
| +        return apply(self.fs.Entry, (s,) + args, kw)
 | 
| +
 | 
| +    def Environment(self, **kw):
 | 
| +        return apply(SCons.Environment.Environment, [], self.subst_kw(kw))
 | 
| +
 | 
| +    def Execute(self, action, *args, **kw):
 | 
| +        """Directly execute an action through an Environment
 | 
| +        """
 | 
| +        action = apply(self.Action, (action,) + args, kw)
 | 
| +        result = action([], [], self)
 | 
| +        if isinstance(result, SCons.Errors.BuildError):
 | 
| +            errstr = result.errstr
 | 
| +            if result.filename:
 | 
| +                errstr = result.filename + ': ' + errstr
 | 
| +            sys.stderr.write("scons: *** %s\n" % errstr)
 | 
| +            return result.status
 | 
| +        else:
 | 
| +            return result
 | 
| +
 | 
| +    def File(self, name, *args, **kw):
 | 
| +        """
 | 
| +        """
 | 
| +        s = self.subst(name)
 | 
| +        if SCons.Util.is_Sequence(s):
 | 
| +            result=[]
 | 
| +            for e in s:
 | 
| +                result.append(apply(self.fs.File, (e,) + args, kw))
 | 
| +            return result
 | 
| +        return apply(self.fs.File, (s,) + args, kw)
 | 
| +
 | 
| +    def FindFile(self, file, dirs):
 | 
| +        file = self.subst(file)
 | 
| +        nodes = self.arg2nodes(dirs, self.fs.Dir)
 | 
| +        return SCons.Node.FS.find_file(file, tuple(nodes))
 | 
| +
 | 
| +    def Flatten(self, sequence):
 | 
| +        return SCons.Util.flatten(sequence)
 | 
| +
 | 
| +    def GetBuildPath(self, files):
 | 
| +        result = map(str, self.arg2nodes(files, self.fs.Entry))
 | 
| +        if SCons.Util.is_List(files):
 | 
| +            return result
 | 
| +        else:
 | 
| +            return result[0]
 | 
| +
 | 
| +    def Glob(self, pattern, ondisk=True, source=False, strings=False):
 | 
| +        return self.fs.Glob(self.subst(pattern), ondisk, source, strings)
 | 
| +
 | 
| +    def Ignore(self, target, dependency):
 | 
| +        """Ignore a dependency."""
 | 
| +        tlist = self.arg2nodes(target, self.fs.Entry)
 | 
| +        dlist = self.arg2nodes(dependency, self.fs.Entry)
 | 
| +        for t in tlist:
 | 
| +            t.add_ignore(dlist)
 | 
| +        return tlist
 | 
| +
 | 
| +    def Literal(self, string):
 | 
| +        return SCons.Subst.Literal(string)
 | 
| +
 | 
| +    def Local(self, *targets):
 | 
| +        ret = []
 | 
| +        for targ in targets:
 | 
| +            if isinstance(targ, SCons.Node.Node):
 | 
| +                targ.set_local()
 | 
| +                ret.append(targ)
 | 
| +            else:
 | 
| +                for t in self.arg2nodes(targ, self.fs.Entry):
 | 
| +                   t.set_local()
 | 
| +                   ret.append(t)
 | 
| +        return ret
 | 
| +
 | 
| +    def Precious(self, *targets):
 | 
| +        tlist = []
 | 
| +        for t in targets:
 | 
| +            tlist.extend(self.arg2nodes(t, self.fs.Entry))
 | 
| +        for t in tlist:
 | 
| +            t.set_precious()
 | 
| +        return tlist
 | 
| +
 | 
| +    def Repository(self, *dirs, **kw):
 | 
| +        dirs = self.arg2nodes(list(dirs), self.fs.Dir)
 | 
| +        apply(self.fs.Repository, dirs, kw)
 | 
| +
 | 
| +    def Requires(self, target, prerequisite):
 | 
| +        """Specify that 'prerequisite' must be built before 'target',
 | 
| +        (but 'target' does not actually depend on 'prerequisite'
 | 
| +        and need not be rebuilt if it changes)."""
 | 
| +        tlist = self.arg2nodes(target, self.fs.Entry)
 | 
| +        plist = self.arg2nodes(prerequisite, self.fs.Entry)
 | 
| +        for t in tlist:
 | 
| +            t.add_prerequisite(plist)
 | 
| +        return tlist
 | 
| +
 | 
| +    def Scanner(self, *args, **kw):
 | 
| +        nargs = []
 | 
| +        for arg in args:
 | 
| +            if SCons.Util.is_String(arg):
 | 
| +                arg = self.subst(arg)
 | 
| +            nargs.append(arg)
 | 
| +        nkw = self.subst_kw(kw)
 | 
| +        return apply(SCons.Scanner.Base, nargs, nkw)
 | 
| +
 | 
| +    def SConsignFile(self, name=".sconsign", dbm_module=None):
 | 
| +        if not name is None:
 | 
| +            name = self.subst(name)
 | 
| +            if not os.path.isabs(name):
 | 
| +                name = os.path.join(str(self.fs.SConstruct_dir), name)
 | 
| +        if name:
 | 
| +            name = os.path.normpath(name)
 | 
| +            sconsign_dir = os.path.dirname(name)
 | 
| +            if sconsign_dir and not os.path.exists(sconsign_dir):
 | 
| +                self.Execute(SCons.Defaults.Mkdir(sconsign_dir))
 | 
| +        SCons.SConsign.File(name, dbm_module)
 | 
| +
 | 
| +    def SideEffect(self, side_effect, target):
 | 
| +        """Tell scons that side_effects are built as side
 | 
| +        effects of building targets."""
 | 
| +        side_effects = self.arg2nodes(side_effect, self.fs.Entry)
 | 
| +        targets = self.arg2nodes(target, self.fs.Entry)
 | 
| +
 | 
| +        for side_effect in side_effects:
 | 
| +            if side_effect.multiple_side_effect_has_builder():
 | 
| +                raise SCons.Errors.UserError, "Multiple ways to build the same target were specified for: %s" % str(side_effect)
 | 
| +            side_effect.add_source(targets)
 | 
| +            side_effect.side_effect = 1
 | 
| +            self.Precious(side_effect)
 | 
| +            for target in targets:
 | 
| +                target.side_effects.append(side_effect)
 | 
| +        return side_effects
 | 
| +
 | 
| +    def SourceCode(self, entry, builder):
 | 
| +        """Arrange for a source code builder for (part of) a tree."""
 | 
| +        entries = self.arg2nodes(entry, self.fs.Entry)
 | 
| +        for entry in entries:
 | 
| +            entry.set_src_builder(builder)
 | 
| +        return entries
 | 
| +
 | 
| +    def SourceSignatures(self, type):
 | 
| +        global _warn_source_signatures_deprecated
 | 
| +        if _warn_source_signatures_deprecated:
 | 
| +            msg = "The env.SourceSignatures() method is deprecated;\n" + \
 | 
| +                  "\tconvert your build to use the env.Decider() method instead."
 | 
| +            SCons.Warnings.warn(SCons.Warnings.DeprecatedSourceSignaturesWarning, msg)
 | 
| +            _warn_source_signatures_deprecated = False
 | 
| +        type = self.subst(type)
 | 
| +        self.src_sig_type = type
 | 
| +        if type == 'MD5':
 | 
| +            if not SCons.Util.md5:
 | 
| +                raise UserError, "MD5 signatures are not available in this version of Python."
 | 
| +            self.decide_source = self._changed_content
 | 
| +        elif type == 'timestamp':
 | 
| +            self.decide_source = self._changed_timestamp_match
 | 
| +        else:
 | 
| +            raise UserError, "Unknown source signature type '%s'" % type
 | 
| +
 | 
| +    def Split(self, arg):
 | 
| +        """This function converts a string or list into a list of strings
 | 
| +        or Nodes.  This makes things easier for users by allowing files to
 | 
| +        be specified as a white-space separated list to be split.
 | 
| +        The input rules are:
 | 
| +            - A single string containing names separated by spaces. These will be
 | 
| +              split apart at the spaces.
 | 
| +            - A single Node instance
 | 
| +            - A list containing either strings or Node instances. Any strings
 | 
| +              in the list are not split at spaces.
 | 
| +        In all cases, the function returns a list of Nodes and strings."""
 | 
| +        if SCons.Util.is_List(arg):
 | 
| +            return map(self.subst, arg)
 | 
| +        elif SCons.Util.is_String(arg):
 | 
| +            return string.split(self.subst(arg))
 | 
| +        else:
 | 
| +            return [self.subst(arg)]
 | 
| +
 | 
| +    def TargetSignatures(self, type):
 | 
| +        global _warn_target_signatures_deprecated
 | 
| +        if _warn_target_signatures_deprecated:
 | 
| +            msg = "The env.TargetSignatures() method is deprecated;\n" + \
 | 
| +                  "\tconvert your build to use the env.Decider() method instead."
 | 
| +            SCons.Warnings.warn(SCons.Warnings.DeprecatedTargetSignaturesWarning, msg)
 | 
| +            _warn_target_signatures_deprecated = False
 | 
| +        type = self.subst(type)
 | 
| +        self.tgt_sig_type = type
 | 
| +        if type in ('MD5', 'content'):
 | 
| +            if not SCons.Util.md5:
 | 
| +                raise UserError, "MD5 signatures are not available in this version of Python."
 | 
| +            self.decide_target = self._changed_content
 | 
| +        elif type == 'timestamp':
 | 
| +            self.decide_target = self._changed_timestamp_match
 | 
| +        elif type == 'build':
 | 
| +            self.decide_target = self._changed_build
 | 
| +        elif type == 'source':
 | 
| +            self.decide_target = self._changed_source
 | 
| +        else:
 | 
| +            raise UserError, "Unknown target signature type '%s'"%type
 | 
| +
 | 
| +    def Value(self, value, built_value=None):
 | 
| +        """
 | 
| +        """
 | 
| +        return SCons.Node.Python.Value(value, built_value)
 | 
| +
 | 
| +    def VariantDir(self, variant_dir, src_dir, duplicate=1):
 | 
| +        variant_dir = self.arg2nodes(variant_dir, self.fs.Dir)[0]
 | 
| +        src_dir = self.arg2nodes(src_dir, self.fs.Dir)[0]
 | 
| +        self.fs.VariantDir(variant_dir, src_dir, duplicate)
 | 
| +
 | 
| +    def FindSourceFiles(self, node='.'):
 | 
| +        """ returns a list of all source files.
 | 
| +        """
 | 
| +        node = self.arg2nodes(node, self.fs.Entry)[0]
 | 
| +
 | 
| +        sources = []
 | 
| +        # Uncomment this and get rid of the global definition when we
 | 
| +        # drop support for pre-2.2 Python versions.
 | 
| +        #def build_source(ss, result):
 | 
| +        #    for s in ss:
 | 
| +        #        if isinstance(s, SCons.Node.FS.Dir):
 | 
| +        #            build_source(s.all_children(), result)
 | 
| +        #        elif s.has_builder():
 | 
| +        #            build_source(s.sources, result)
 | 
| +        #        elif isinstance(s.disambiguate(), SCons.Node.FS.File):
 | 
| +        #            result.append(s)
 | 
| +        build_source(node.all_children(), sources)
 | 
| +
 | 
| +        # now strip the build_node from the sources by calling the srcnode
 | 
| +        # function
 | 
| +        def get_final_srcnode(file):
 | 
| +            srcnode = file.srcnode()
 | 
| +            while srcnode != file.srcnode():
 | 
| +                srcnode = file.srcnode()
 | 
| +            return srcnode
 | 
| +
 | 
| +        # get the final srcnode for all nodes, this means stripping any
 | 
| +        # attached build node.
 | 
| +        map( get_final_srcnode, sources )
 | 
| +
 | 
| +        # remove duplicates
 | 
| +        return list(set(sources))
 | 
| +
 | 
| +    def FindInstalledFiles(self):
 | 
| +        """ returns the list of all targets of the Install and InstallAs Builder.
 | 
| +        """
 | 
| +        from SCons.Tool import install
 | 
| +        if install._UNIQUE_INSTALLED_FILES is None:
 | 
| +            install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES)
 | 
| +        return install._UNIQUE_INSTALLED_FILES
 | 
| +
 | 
| +class OverrideEnvironment(Base):
 | 
| +    """A proxy that overrides variables in a wrapped construction
 | 
| +    environment by returning values from an overrides dictionary in
 | 
| +    preference to values from the underlying subject environment.
 | 
| +
 | 
| +    This is a lightweight (I hope) proxy that passes through most use of
 | 
| +    attributes to the underlying Environment.Base class, but has just
 | 
| +    enough additional methods defined to act like a real construction
 | 
| +    environment with overridden values.  It can wrap either a Base
 | 
| +    construction environment, or another OverrideEnvironment, which
 | 
| +    can in turn nest arbitrary OverrideEnvironments...
 | 
| +
 | 
| +    Note that we do *not* call the underlying base class
 | 
| +    (SubsitutionEnvironment) initialization, because we get most of those
 | 
| +    from proxying the attributes of the subject construction environment.
 | 
| +    But because we subclass SubstitutionEnvironment, this class also
 | 
| +    has inherited arg2nodes() and subst*() methods; those methods can't
 | 
| +    be proxied because they need *this* object's methods to fetch the
 | 
| +    values from the overrides dictionary.
 | 
| +    """
 | 
| +
 | 
| +    if SCons.Memoize.use_memoizer:
 | 
| +        __metaclass__ = SCons.Memoize.Memoized_Metaclass
 | 
| +
 | 
| +    def __init__(self, subject, overrides={}):
 | 
| +        if __debug__: logInstanceCreation(self, 'Environment.OverrideEnvironment')
 | 
| +        self.__dict__['__subject'] = subject
 | 
| +        self.__dict__['overrides'] = overrides
 | 
| +
 | 
| +    # Methods that make this class act like a proxy.
 | 
| +    def __getattr__(self, name):
 | 
| +        return getattr(self.__dict__['__subject'], name)
 | 
| +    def __setattr__(self, name, value):
 | 
| +        setattr(self.__dict__['__subject'], name, value)
 | 
| +
 | 
| +    # Methods that make this class act like a dictionary.
 | 
| +    def __getitem__(self, key):
 | 
| +        try:
 | 
| +            return self.__dict__['overrides'][key]
 | 
| +        except KeyError:
 | 
| +            return self.__dict__['__subject'].__getitem__(key)
 | 
| +    def __setitem__(self, key, value):
 | 
| +        if not is_valid_construction_var(key):
 | 
| +            raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
 | 
| +        self.__dict__['overrides'][key] = value
 | 
| +    def __delitem__(self, key):
 | 
| +        try:
 | 
| +            del self.__dict__['overrides'][key]
 | 
| +        except KeyError:
 | 
| +            deleted = 0
 | 
| +        else:
 | 
| +            deleted = 1
 | 
| +        try:
 | 
| +            result = self.__dict__['__subject'].__delitem__(key)
 | 
| +        except KeyError:
 | 
| +            if not deleted:
 | 
| +                raise
 | 
| +            result = None
 | 
| +        return result
 | 
| +    def get(self, key, default=None):
 | 
| +        """Emulates the get() method of dictionaries."""
 | 
| +        try:
 | 
| +            return self.__dict__['overrides'][key]
 | 
| +        except KeyError:
 | 
| +            return self.__dict__['__subject'].get(key, default)
 | 
| +    def has_key(self, key):
 | 
| +        try:
 | 
| +            self.__dict__['overrides'][key]
 | 
| +            return 1
 | 
| +        except KeyError:
 | 
| +            return self.__dict__['__subject'].has_key(key)
 | 
| +    def Dictionary(self):
 | 
| +        """Emulates the items() method of dictionaries."""
 | 
| +        d = self.__dict__['__subject'].Dictionary().copy()
 | 
| +        d.update(self.__dict__['overrides'])
 | 
| +        return d
 | 
| +    def items(self):
 | 
| +        """Emulates the items() method of dictionaries."""
 | 
| +        return self.Dictionary().items()
 | 
| +
 | 
| +    # Overridden private construction environment methods.
 | 
| +    def _update(self, dict):
 | 
| +        """Update an environment's values directly, bypassing the normal
 | 
| +        checks that occur when users try to set items.
 | 
| +        """
 | 
| +        self.__dict__['overrides'].update(dict)
 | 
| +
 | 
| +    def gvars(self):
 | 
| +        return self.__dict__['__subject'].gvars()
 | 
| +
 | 
| +    def lvars(self):
 | 
| +        lvars = self.__dict__['__subject'].lvars()
 | 
| +        lvars.update(self.__dict__['overrides'])
 | 
| +        return lvars
 | 
| +
 | 
| +    # Overridden public construction environment methods.
 | 
| +    def Replace(self, **kw):
 | 
| +        kw = copy_non_reserved_keywords(kw)
 | 
| +        self.__dict__['overrides'].update(semi_deepcopy(kw))
 | 
| +
 | 
| +# The entry point that will be used by the external world
 | 
| +# to refer to a construction environment.  This allows the wrapper
 | 
| +# interface to extend a construction environment for its own purposes
 | 
| +# by subclassing SCons.Environment.Base and then assigning the
 | 
| +# class to SCons.Environment.Environment.
 | 
| +
 | 
| +Environment = Base
 | 
| +
 | 
| +# An entry point for returning a proxy subclass instance that overrides
 | 
| +# the subst*() methods so they don't actually perform construction
 | 
| +# variable substitution.  This is specifically intended to be the shim
 | 
| +# layer in between global function calls (which don't want construction
 | 
| +# variable substitution) and the DefaultEnvironment() (which would
 | 
| +# substitute variables if left to its own devices)."""
 | 
| +#
 | 
| +# We have to wrap this in a function that allows us to delay definition of
 | 
| +# the class until it's necessary, so that when it subclasses Environment
 | 
| +# it will pick up whatever Environment subclass the wrapper interface
 | 
| +# might have assigned to SCons.Environment.Environment.
 | 
| +
 | 
| +def NoSubstitutionProxy(subject):
 | 
| +    class _NoSubstitutionProxy(Environment):
 | 
| +        def __init__(self, subject):
 | 
| +            self.__dict__['__subject'] = subject
 | 
| +        def __getattr__(self, name):
 | 
| +            return getattr(self.__dict__['__subject'], name)
 | 
| +        def __setattr__(self, name, value):
 | 
| +            return setattr(self.__dict__['__subject'], name, value)
 | 
| +        def raw_to_mode(self, dict):
 | 
| +            try:
 | 
| +                raw = dict['raw']
 | 
| +            except KeyError:
 | 
| +                pass
 | 
| +            else:
 | 
| +                del dict['raw']
 | 
| +                dict['mode'] = raw
 | 
| +        def subst(self, string, *args, **kwargs):
 | 
| +            return string
 | 
| +        def subst_kw(self, kw, *args, **kwargs):
 | 
| +            return kw
 | 
| +        def subst_list(self, string, *args, **kwargs):
 | 
| +            nargs = (string, self,) + args
 | 
| +            nkw = kwargs.copy()
 | 
| +            nkw['gvars'] = {}
 | 
| +            self.raw_to_mode(nkw)
 | 
| +            return apply(SCons.Subst.scons_subst_list, nargs, nkw)
 | 
| +        def subst_target_source(self, string, *args, **kwargs):
 | 
| +            nargs = (string, self,) + args
 | 
| +            nkw = kwargs.copy()
 | 
| +            nkw['gvars'] = {}
 | 
| +            self.raw_to_mode(nkw)
 | 
| +            return apply(SCons.Subst.scons_subst, nargs, nkw)
 | 
| +    return _NoSubstitutionProxy(subject)
 | 
| 
 |