| Index: scons-2.0.1/engine/SCons/PathList.py
|
| ===================================================================
|
| --- scons-2.0.1/engine/SCons/PathList.py (revision 0)
|
| +++ scons-2.0.1/engine/SCons/PathList.py (revision 0)
|
| @@ -0,0 +1,231 @@
|
| +#
|
| +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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/PathList.py 5134 2010/08/16 23:02:40 bdeegan"
|
| +
|
| +__doc__ = """SCons.PathList
|
| +
|
| +A module for handling lists of directory paths (the sort of things
|
| +that get set as CPPPATH, LIBPATH, etc.) with as much caching of data and
|
| +efficiency as we can while still keeping the evaluation delayed so that we
|
| +Do the Right Thing (almost) regardless of how the variable is specified.
|
| +
|
| +"""
|
| +
|
| +import os
|
| +
|
| +import SCons.Memoize
|
| +import SCons.Node
|
| +import SCons.Util
|
| +
|
| +#
|
| +# Variables to specify the different types of entries in a PathList object:
|
| +#
|
| +
|
| +TYPE_STRING_NO_SUBST = 0 # string with no '$'
|
| +TYPE_STRING_SUBST = 1 # string containing '$'
|
| +TYPE_OBJECT = 2 # other object
|
| +
|
| +def node_conv(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:
|
| + if isinstance(obj, SCons.Node.Node) or SCons.Util.is_Sequence( obj ):
|
| + result = obj
|
| + else:
|
| + result = str(obj)
|
| + else:
|
| + result = get()
|
| + return result
|
| +
|
| +class _PathList(object):
|
| + """
|
| + An actual PathList object.
|
| + """
|
| + def __init__(self, pathlist):
|
| + """
|
| + Initializes a PathList object, canonicalizing the input and
|
| + pre-processing it for quicker substitution later.
|
| +
|
| + The stored representation of the PathList is a list of tuples
|
| + containing (type, value), where the "type" is one of the TYPE_*
|
| + variables defined above. We distinguish between:
|
| +
|
| + strings that contain no '$' and therefore need no
|
| + delayed-evaluation string substitution (we expect that there
|
| + will be many of these and that we therefore get a pretty
|
| + big win from avoiding string substitution)
|
| +
|
| + strings that contain '$' and therefore need substitution
|
| + (the hard case is things like '${TARGET.dir}/include',
|
| + which require re-evaluation for every target + source)
|
| +
|
| + other objects (which may be something like an EntryProxy
|
| + that needs a method called to return a Node)
|
| +
|
| + Pre-identifying the type of each element in the PathList up-front
|
| + and storing the type in the list of tuples is intended to reduce
|
| + the amount of calculation when we actually do the substitution
|
| + over and over for each target.
|
| + """
|
| + if SCons.Util.is_String(pathlist):
|
| + pathlist = pathlist.split(os.pathsep)
|
| + elif not SCons.Util.is_Sequence(pathlist):
|
| + pathlist = [pathlist]
|
| +
|
| + pl = []
|
| + for p in pathlist:
|
| + try:
|
| + index = p.find('$')
|
| + except (AttributeError, TypeError):
|
| + type = TYPE_OBJECT
|
| + else:
|
| + if index == -1:
|
| + type = TYPE_STRING_NO_SUBST
|
| + else:
|
| + type = TYPE_STRING_SUBST
|
| + pl.append((type, p))
|
| +
|
| + self.pathlist = tuple(pl)
|
| +
|
| + def __len__(self): return len(self.pathlist)
|
| +
|
| + def __getitem__(self, i): return self.pathlist[i]
|
| +
|
| + def subst_path(self, env, target, source):
|
| + """
|
| + Performs construction variable substitution on a pre-digested
|
| + PathList for a specific target and source.
|
| + """
|
| + result = []
|
| + for type, value in self.pathlist:
|
| + if type == TYPE_STRING_SUBST:
|
| + value = env.subst(value, target=target, source=source,
|
| + conv=node_conv)
|
| + if SCons.Util.is_Sequence(value):
|
| + result.extend(value)
|
| + continue
|
| +
|
| + elif type == TYPE_OBJECT:
|
| + value = node_conv(value)
|
| + if value:
|
| + result.append(value)
|
| + return tuple(result)
|
| +
|
| +
|
| +class PathListCache(object):
|
| + """
|
| + A class to handle caching of PathList lookups.
|
| +
|
| + This class gets instantiated once and then deleted from the namespace,
|
| + so it's used as a Singleton (although we don't enforce that in the
|
| + usual Pythonic ways). We could have just made the cache a dictionary
|
| + in the module namespace, but putting it in this class allows us to
|
| + use the same Memoizer pattern that we use elsewhere to count cache
|
| + hits and misses, which is very valuable.
|
| +
|
| + Lookup keys in the cache are computed by the _PathList_key() method.
|
| + Cache lookup should be quick, so we don't spend cycles canonicalizing
|
| + all forms of the same lookup key. For example, 'x:y' and ['x',
|
| + 'y'] logically represent the same list, but we don't bother to
|
| + split string representations and treat those two equivalently.
|
| + (Note, however, that we do, treat lists and tuples the same.)
|
| +
|
| + The main type of duplication we're trying to catch will come from
|
| + looking up the same path list from two different clones of the
|
| + same construction environment. That is, given
|
| +
|
| + env2 = env1.Clone()
|
| +
|
| + both env1 and env2 will have the same CPPPATH value, and we can
|
| + cheaply avoid re-parsing both values of CPPPATH by using the
|
| + common value from this cache.
|
| + """
|
| + if SCons.Memoize.use_memoizer:
|
| + __metaclass__ = SCons.Memoize.Memoized_Metaclass
|
| +
|
| + memoizer_counters = []
|
| +
|
| + def __init__(self):
|
| + self._memo = {}
|
| +
|
| + def _PathList_key(self, pathlist):
|
| + """
|
| + Returns the key for memoization of PathLists.
|
| +
|
| + Note that we want this to be pretty quick, so we don't completely
|
| + canonicalize all forms of the same list. For example,
|
| + 'dir1:$ROOT/dir2' and ['$ROOT/dir1', 'dir'] may logically
|
| + represent the same list if you're executing from $ROOT, but
|
| + we're not going to bother splitting strings into path elements,
|
| + or massaging strings into Nodes, to identify that equivalence.
|
| + We just want to eliminate obvious redundancy from the normal
|
| + case of re-using exactly the same cloned value for a path.
|
| + """
|
| + if SCons.Util.is_Sequence(pathlist):
|
| + pathlist = tuple(SCons.Util.flatten(pathlist))
|
| + return pathlist
|
| +
|
| + memoizer_counters.append(SCons.Memoize.CountDict('PathList', _PathList_key))
|
| +
|
| + def PathList(self, pathlist):
|
| + """
|
| + Returns the cached _PathList object for the specified pathlist,
|
| + creating and caching a new object as necessary.
|
| + """
|
| + pathlist = self._PathList_key(pathlist)
|
| + try:
|
| + memo_dict = self._memo['PathList']
|
| + except KeyError:
|
| + memo_dict = {}
|
| + self._memo['PathList'] = memo_dict
|
| + else:
|
| + try:
|
| + return memo_dict[pathlist]
|
| + except KeyError:
|
| + pass
|
| +
|
| + result = _PathList(pathlist)
|
| +
|
| + memo_dict[pathlist] = result
|
| +
|
| + return result
|
| +
|
| +PathList = PathListCache().PathList
|
| +
|
| +
|
| +del PathListCache
|
| +
|
| +# Local Variables:
|
| +# tab-width:4
|
| +# indent-tabs-mode:nil
|
| +# End:
|
| +# vim: set expandtab tabstop=4 shiftwidth=4:
|
|
|
| Property changes on: scons-2.0.1/engine/SCons/PathList.py
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|