如何执行scons中的executor内部执行过程的action

Module&Environment
Source Code for
"""SCons.Environment
Base class for construction Environments.
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
= "src/engine/SCons/Environment.py
09:42:21 garyo"
import sys
import shlex
from collections import UserDict
from . import
63 class (object):
semi_deepcopy = ..semi_deepcopy
semi_deepcopy_dict = ..semi_deepcopy_dict
83 def (env, target, source):
= ..(action = ,
target_factory = ....,
source_factory = ...,
multi = 1,
is_explicit = None,
name='AliasBuilder')
93 def (env, tools, toolpath):
if toolpath is not None:
env['toolpath'] = toolpath
if not tools:
for tool in [_f for _f in tools if _f]:
if ..is_List(tool) or isinstance(tool, tuple):
toolname = tool[0]
toolargs = tool[1]
tool = env.(toolname, **toolargs)
env.(tool)
'CHANGED_SOURCES',
'CHANGED_TARGETS',
'SOURCES',
'TARGETS',
'UNCHANGED_SOURCES',
'UNCHANGED_TARGETS',
129 def (dict):
= semi_deepcopy(dict)
for k in .():
= "Ignoring attempt to set reserved variable `$%s'"
138 def (env, key, value):
= "Ignoring attempt to set reserved variable `$%s'"
142 def (env, key, value):
env._dict[key] = value
= "`$%s' will be reserved in a future release and setting it will become ignored"
147 def (env, key, value):
bd = env._dict[key]
for k in bd.():
except KeyError:
bd = (kwbd, env)
env._dict[key] = bd
for k, v in value.():
if not ..(v):
raise ..('%s is not a Builder.' % repr(v))
bd.(value)
160 def (env, key):
del env._dict[key]
164 def (env, key, value):
env._dict[key] = value
168 def (l, keep_last):
"""Delete duplicates from a sequence, keeping the first or last."""
if keep_last:
for i in l:
if i not in seen:
except TypeError:
if keep_last:
199 class (object):
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 (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 (self, *args, **kwargs):
nargs = (self.object,) + args
return self.method(*nargs, **kwargs)
def (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)
233 class (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 (self, target=None, source=, *args, **kw):
if source is :
source = target
target = None
if target is not None and not ..is_List(target):
target = [target]
if source is not None and not ..is_List(source):
source = [source]
return .(self, target, source, *args, **kw)
def (self):
return '&BuilderWrapper %s&' % repr(self.name)
def (self):
return self.()
def (self, name):
if name == 'env':
return self.object
elif name == 'builder':
return self.method
raise AttributeError(name)
def (self, name, value):
if name == 'env':
self.object = value
elif name == 'builder':
self.method = value
self.__dict__[name] = value
295 class (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 (self, dict, env):
self.env = env
UserDict.(self, dict)
def (self):
raise TypeError( 'cannot semi_deepcopy a BuilderDict' )
def (self, item, val):
method = getattr(self.env, item).method
except AttributeError:
self.env.(method)
UserDict.(self, item, val)
(self.env, val, item)
def (self, item):
UserDict.(self, item)
delattr(self.env, item)
= re.compile(r'[_a-zA-Z]\w*$')
334 def (varstr):
"""Return if the specified string is a legitimate construction
return .match(varstr)
342 class (object):
"""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.
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
(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.)
def (self, **kw):
"""Initialization of an underlying SubstitutionEnvironment class.
if ..: (self, 'Environment.SubstitutionEnvironment')
self. = ...()
self.ans = ...
self.lookup_list = ..
self._dict = kw.()
self.added_methods = []
def (self):
"""Initial the dispatch tables for special handling of
special construction variables."""
self._special_del = {}
self._special_del['SCANNERS'] =
self._special_set = {}
for key in :
self._special_set[key] =
for key in :
self._special_set[key] =
self._special_set['BUILDERS'] =
self._special_set['SCANNERS'] =
self._special_set_keys = list(self._special_set.())
def (self, other):
return cmp(self._dict, other._dict)
def (self, key):
special = self._special_del.(key)
if special:
special(self, key)
del self._dict[key]
def (self, key):
return self._dict[key]
def (self, key, value):
if key in self._special_set_keys:
self._special_set[key](self, key, value)
if key not in self._dict \
and not .match(key):
raise ..("Illegal construction variable `%s'" % key)
self._dict[key] = value
def (self, key, default=None):
"""Emulates the get() method of dictionaries."""
return self._dict.(key, )
def (self, key):
return key in self._dict
def (self, key):
return self._dict.(key)
def (self):
return list(self._dict.())
def (self, args, node_factory=, lookup_list=, **kw):
if node_factory is :
node_factory = self..
if lookup_list is :
lookup_list = self.lookup_list
if not args:
args = ..flatten(args)
nodes = []
for v in args:
if ..is_String(v):
for l in lookup_list:
if n is not None:
if n is not None:
if ..is_String(n):
kw['raw'] = 1
n = self.(n, **kw)
if node_factory:
n = node_factory(n)
if ..is_List(n):
elif node_factory:
kw['raw'] = 1
v = node_factory(self.(v, **kw))
if ..is_List(v):
return nodes
def (self):
return self._dict
def (self):
def (self, string, raw=0, target=None, source=None, conv=None, executor=None):
"""Recursively interpolates construction variables from the
Environment into the specified string, returning the expanded
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.
['__env__'] = self
if executor:
.(executor.())
return ..scons_subst(, self, raw, target, source, , , conv)
def (self, kw, raw=0, target=None, source=None):
for k, v in kw.():
k = self.(k, raw, target, source)
if ..is_String(v):
v = self.(v, raw, target, source)
nkw[k] = v
return nkw
def (self, string, raw=0, target=None, source=None, conv=None, executor=None):
"""Calls through to SCons.Subst.scons_subst_list().
the documentation for that function."""
['__env__'] = self
if executor:
.(executor.())
return ..scons_subst_list(, self, raw, target, source, , , conv)
def (self, path, target=None, source=None):
"""Substitute a path list, turning EntryProxies into Nodes
and leaving Nodes (and other objects) as-is."""
if not ..is_List():
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."""
except AttributeError:
obj = ..to_String_for_subst(obj)
return obj
for p in :
if ..is_String(p):
p = self.(p, target=target, source=source, conv=s)
if ..is_List(p):
if len(p) == 1:
p = ''.join(map(..to_String_for_subst, p))
subst_target_source =
def (self, command):
import subprocess
kw = { 'stdin' : 'devnull',
'stdout' : subprocess.PIPE,
'stderr' : subprocess.PIPE,
'universal_newlines' : True,
if not ..is_List(command): kw['shell'] = True
p = .._subproc(self, command, **kw)
out,err = p.communicate()
status = p.wait()
sys.stderr.((err))
if status:
raise OSError("'%s' exited %d" % (command, status))
return out
def (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 = (self, function, name)
self.added_methods.(method)
def (self, function):
Removes the specified function's MethodWrapper from the
added_methods list, so we don't re-bind it when making a clone.
self.added_methods = [dm for dm in self.added_methods if not dm.method is function]
def (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 = (overrides)
if not o: return self
overrides = {}
merges = None
for key, value in o.():
if key == 'parse_flags':
merges = value
overrides[key] = ..scons_subst_once(value, self, key)
env = (self, overrides)
if merges: env.(merges)
return env
def (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.
the flag strings begins with a bang (exclamation mark), it is
assumed to be a command and the rest of th
the result of that evaluation is then added to the dict.
'CXXFLAGS'
'CPPDEFINES'
'CPPFLAGS'
'FRAMEWORKPATH' : ..(''),
'FRAMEWORKS'
'LINKFLAGS'
def do_parse(arg):
if not arg:
if not ..is_String(arg):
for t in arg: do_parse(t)
if arg[0] == '!':
arg = self.(arg[1:])
def append_define(name, dict = dict):
t = name.split('=')
if len(t) == 1:
dict['CPPDEFINES'].(name)
dict['CPPDEFINES'].([t[0], '='.join(t[1:])])
params = shlex.split(arg)
append_next_arg_to = None
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..(arg))
dict['CCFLAGS'].(t)
elif append_next_arg_to == '-isysroot':
t = ('-isysroot', arg)
dict['CCFLAGS'].(t)
dict['LINKFLAGS'].(t)
elif append_next_arg_to == '-arch':
t = ('-arch', arg)
dict['CCFLAGS'].(t)
dict['LINKFLAGS'].(t)
dict[append_next_arg_to].(arg)
append_next_arg_to = None
elif not arg[0] in ['-', '+']:
dict['LIBS'].(self..(arg))
elif arg == '-dylib_file':
dict['LINKFLAGS'].(arg)
append_next_arg_to = 'LINKFLAGS'
elif arg[:2] == '-L':
if arg[2:]:
dict['LIBPATH'].(arg[2:])
append_next_arg_to = 'LIBPATH'
elif arg[:2] == '-l':
if arg[2:]:
dict['LIBS'].(arg[2:])
append_next_arg_to = 'LIBS'
elif arg[:2] == '-I':
if arg[2:]:
dict['CPPPATH'].(arg[2:])
append_next_arg_to = 'CPPPATH'
elif arg[:4] == '-Wa,':
dict['ASFLAGS'].(arg[4:])
dict['CCFLAGS'].(arg)
elif arg[:4] == '-Wl,':
if arg[:11] == '-Wl,-rpath=':
dict['RPATH'].(arg[11:])
elif arg[:7] == '-Wl,-R,':
dict['RPATH'].(arg[7:])
elif arg[:6] == '-Wl,-R':
dict['RPATH'].(arg[6:])
dict['LINKFLAGS'].(arg)
elif arg[:4] == '-Wp,':
dict['CPPFLAGS'].(arg)
elif arg[:2] == '-D':
if arg[2:]:
append_define(arg[2:])
append_next_arg_to = 'CPPDEFINES'
elif arg == '-framework':
append_next_arg_to = 'FRAMEWORKS'
elif arg[:14] == '-frameworkdir=':
dict['FRAMEWORKPATH'].(arg[14:])
elif arg[:2] == '-F':
if arg[2:]:
dict['FRAMEWORKPATH'].(arg[2:])
append_next_arg_to = 'FRAMEWORKPATH'
elif arg in ['-mno-cygwin',
'-pthread',
'-openmp',
'-fopenmp']:
dict['CCFLAGS'].(arg)
dict['LINKFLAGS'].(arg)
elif arg == '-mwindows':
dict['LINKFLAGS'].(arg)
elif arg[:5] == '-std=':
if arg[5:].find('++')!=-1:
key='CXXFLAGS'
key='CFLAGS'
dict[key].(arg)
elif arg[0] == '+':
dict['CCFLAGS'].(arg)
dict['LINKFLAGS'].(arg)
elif arg in ['-include', '-isysroot', '-arch']:
append_next_arg_to = arg
dict['CCFLAGS'].(arg)
for arg in flags:
do_parse(arg)
return dict
def (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 ..is_Dict(args):
args = self.(args)
if not unique:
self.(**args)
return self
for key, value in args.():
if not value:
orig = self[key]
except KeyError:
orig = value
if not orig:
orig = value
elif value:
orig = orig + value
except (KeyError, TypeError):
add_to_orig = orig.
except AttributeError:
value.(0, orig)
orig = value
add_to_orig(value)
if key[-4:] == 'PATH':
for v in orig:
if v not in t:
for v in orig:
if v not in t:
self[key] = t
return self
880 def (dependency, target, prev_ni):
f = ..DefaultEnvironment().
return f(dependency, target, prev_ni)
884 def (dependency, target, prev_ni):
f = ..DefaultEnvironment().
return f(dependency, target, prev_ni)
888 def (src, dst):
f = ..DefaultEnvironment().copy_from_cache
return f(src, dst)
892 class (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.
def (self,
platform=None,
tools=None,
toolpath=None,
variables=None,
parse_flags = None,
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 ..: (self, 'Environment.Base')
self._memo = {}
self. = ...()
self.ans = ...
self.lookup_list = ..
self._dict = semi_deepcopy(..)
self.added_methods = []
self.copy_from_cache =
self._dict['BUILDERS'] = (self._dict['BUILDERS'], self)
if platform is None:
platform = self._dict.('PLATFORM', None)
if platform is None:
platform = ..()
if ..is_String(platform):
platform = ..(platform)
self._dict['PLATFORM'] = str(platform)
platform(self)
self._dict['HOST_OS']
= self._dict.('HOST_OS',None)
self._dict['HOST_ARCH']
= self._dict.('HOST_ARCH',None)
self._dict['TARGET_OS']
= self._dict.('TARGET_OS',None)
self._dict['TARGET_ARCH']
= self._dict.('TARGET_ARCH',None)
if 'options' in kw:
variables = kw['options']
del kw['options']
self.(**kw)
= list(kw.())
if variables:
+ list(variables.())
variables.(self)
for k in :
[k] = self._dict[k]
except KeyError:
..Initializers(self)
if tools is None:
tools = self._dict.('TOOLS', None)
if tools is None:
tools = ['default']
(self, tools, toolpath)
for key, val in .():
self._dict[key] = val
if parse_flags: self.(parse_flags)
def (self, name):
"""Fetch the builder with the specified name from the environment.
return self._dict['BUILDERS'][name]
except KeyError:
return None
def (self):
= self._CacheDir_path
except AttributeError:
= ..DefaultEnvironment()._CacheDir_path
== self._last_CacheDir_path:
return self._last_CacheDir
except AttributeError:
self._last_CacheDir_path =
self._last_CacheDir = cd
def (self, factory, default='File'):
"""Return a factory function for creating Nodes for this
construction environment.
is_node = issubclass(factory, ...)
except TypeError:
if is_node:
try: name = factory.__name__
except AttributeError: pass
else: factory = None
if not factory:
factory = getattr(self., name)
return factory
.(..('_gsm'))
def (self):
return self._memo['_gsm']
except KeyError:
scanners = self._dict['SCANNERS']
except KeyError:
if not ..is_List(scanners):
scanners = [scanners]
scanners = scanners[:]
scanners.()
for scanner in scanners:
for k in scanner.(self):
if k and self['PLATFORM'] == 'win32':
k = k.lower()
[k] = scanner
self._memo['_gsm'] =
def (self, skey):
"""Find the appropriate scanner given a key (usually a file suffix).
if skey and self['PLATFORM'] == 'win32':
skey = skey.lower()
return self.().(skey)
def (self, kw=None):
"""Delete the cached scanner map (if we need to).
del self._memo['_gsm']
except KeyError:
def (self):
return self.src_sig_type
except AttributeError:
t = ..DefaultEnvironment().src_sig_type
self.src_sig_type = t
def (self):
return self.tgt_sig_type
except AttributeError:
t = ..DefaultEnvironment().tgt_sig_type
self.tgt_sig_type = t
def (self, **kw):
"""Append values to existing construction variables
in an Environment.
for key, val in kw.():
if key == 'CPPDEFINES' and ..is_String(self._dict[key]):
self._dict[key] = [self._dict[key]]
orig = self._dict[key]
except KeyError:
if key == 'CPPDEFINES' and ..is_String(val):
self._dict[key] = [val]
self._dict[key] = val
update_dict = orig.
except AttributeError:
self._dict[key] = orig + val
except (KeyError, TypeError):
add_to_orig = orig.
except AttributeError:
val.(0, orig)
self._dict[key] = val
add_to_orig(val)
if ..is_List(val):
if key == 'CPPDEFINES':
orig = orig.()
orig += val
self._dict[key] = orig
for v in val:
orig[v] = None
update_dict(val)
except (AttributeError, TypeError, ValueError):
if ..is_Dict(val):
for k, v in val.():
orig[k] = v
orig[val] = None
def (self, path):
if not ..is_String():
and [0] == '#':
= str(self..())
def (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).
if envname in self._dict and name in self._dict[envname]:
orig = self._dict[envname][name]
nv = ..AppendPath(orig, newpath, sep, delete_existing,
canonicalize=self.)
if envname not in self._dict:
self._dict[envname] = {}
self._dict[envname][name] = nv
def (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.
for key, val in kw.():
if ..is_List(val):
val = (val, delete_existing)
if key not in self._dict or self._dict[key] in ('', None):
self._dict[key] = val
elif ..is_Dict(self._dict[key]) and \
..is_Dict(val):
self._dict[key].(val)
elif ..is_List(val):
dk = self._dict[key]
if key == 'CPPDEFINES':
for i in val:
if ..is_List(i):
if len(i) &= 2:
tmp.((i[0], i[1]))
tmp.((i[0],))
elif ..is_Tuple(i):
tmp.((i,))
if ..is_Dict(dk):
dk = dk.()
elif ..is_String(dk):
dk = [(dk,)]
for i in dk:
if ..is_List(i):
if len(i) &= 2:
tmp.((i[0], i[1]))
tmp.((i[0],))
elif ..is_Tuple(i):
tmp.((i,))
if not ..is_List(dk):
if delete_existing:
dk = [ for
not in val]
val = [ for
not in dk]
self._dict[key] = dk + val
dk = self._dict[key]
if ..is_List(dk):
if key == 'CPPDEFINES':
for i in dk:
if ..is_List(i):
if len(i) &= 2:
tmp.((i[0], i[1]))
tmp.((i[0],))
elif ..is_Tuple(i):
tmp.((i,))
if ..is_Dict(val):
val = val.()
elif ..is_String(val):
val = [(val,)]
if delete_existing:
dk = filter(lambda , val=val:
not in val, dk)
self._dict[key] = dk + val
dk = [ for
not in val]
self._dict[key] = dk + val
if delete_existing:
dk = filter(lambda , val=val:
not in val, dk)
self._dict[key] = dk + [val]
if not val in dk:
self._dict[key] = dk + [val]
if key == 'CPPDEFINES':
if ..is_String(dk):
elif ..is_Dict(dk):
dk = dk.()
if ..is_String(val):
if val in dk:
val = [val]
elif ..is_Dict(val):
for i,j in val.iteritems():
if j is not None:
tmp.((i,j))
if delete_existing:
dk = [ for
not in val]
self._dict[key] = dk + val
def (self, tools=[], toolpath=None, parse_flags = None, **kw):
"""Return a copy of a construction Environment.
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.
builders = self._dict['BUILDERS']
except KeyError:
._dict = semi_deepcopy_dict(self._dict, ['BUILDERS'])
._dict['BUILDERS'] = (builders, )
.added_methods = []
for mw in self.added_methods:
if mw == getattr(self, mw.name):
.added_methods.(mw.())
._memo = {}
for key, value in kw.():
new[key] = ..scons_subst_once(value, self, key)
(, tools, toolpath)
if parse_flags: .(parse_flags)
if ..: (self, 'Environment.EnvironmentClone')
def (self, *args, **kw):
= "The env.Copy()
use the env.Clone() method instead."
return self.(*args, **kw)
def (self, dependency, target, prev_ni):
if dependency.(target, prev_ni):
return self.(dependency, target, prev_ni)
def (self, dependency, target, prev_ni):
return dependency.(target, prev_ni)
def (self, dependency, target, prev_ni):
target_env = dependency.()
type = target_env.()
if type == 'source':
return target_env.(dependency, target, prev_ni)
return target_env.(dependency, target, prev_ni)
def (self, src, dst):
return self..(src, dst)
def (self, src, dst):
return self..(src, dst)
def (self, function):
copy_function = self.
if function in ('MD5', 'content'):
if not ..:
raise ("MD5 signatures are not available in this version of Python.")
function = self.
elif function == 'MD5-timestamp':
function = self.
elif function in ('timestamp-newer', 'make'):
function = self.
copy_function = self.
elif function == 'timestamp-match':
function = self.
elif not callable(function):
raise ("Unknown Decider value %s" % repr(function))
self. = function
self. = function
self.copy_from_cache = copy_function
def (self, progs):
"""Return the first available program in progs.
if not ..is_List(progs):
progs = [ progs ]
for prog in progs:
= self.(prog)
if : return prog
return None
def (self, *args):
if not args:
return self._dict
dlist = [self._dict[] for
if len(dlist) == 1:
dlist = dlist[0]
return dlist
def (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)
dict = self.(key)
dict = self.()
return pp.pformat(dict)
def (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.('$'+suffix)
prefix = self.('$'+prefix)
dir,name = os..split(str())
if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
def (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.(cmd, unique)
function = parse_conf
if ..is_List(command):
command = ' '.join(command)
command = self.(command)
return function(self, self.(command))
def (self, filename, must_exist=None, only_one=0):
Parse a mkdep-style file for explicit dependencies.
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.(filename)
fp = (filename, 'r')
except IOError:
if must_exist:
lines = ..(fp).()
lines = [l for l in lines if l[0] != '#']
tdlist = []
for line in lines:
target, depends = line.split(':', 1)
except (AttributeError, ValueError):
tdlist.((target.split(), depends.split()))
if only_one:
targets = []
for td in tdlist:
targets.(td[0])
if len(targets) & 1:
"More than one dependency target found in `%s':
% (filename, targets))
for target, depends in tdlist:
self.(target, depends)
def (self, platform):
platform = self.(platform)
return ..(platform)(self)
def (self, **kw):
"""Prepend values to existing construction variables
in an Environment.
for key, val in kw.():
orig = self._dict[key]
except KeyError:
self._dict[key] = val
update_dict = orig.
except AttributeError:
self._dict[key] = val + orig
except (KeyError, TypeError):
add_to_val = val.
except AttributeError:
orig.(0, val)
add_to_val(orig)
self._dict[key] = val
if ..is_List(val):
for v in val:
orig[v] = None
update_dict(val)
except (AttributeError, TypeError, ValueError):
if ..is_Dict(val):
for k, v in val.():
orig[k] = v
orig[val] = None
def (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).
if envname in self._dict and name in self._dict[envname]:
orig = self._dict[envname][name]
nv = ..PrependPath(orig, newpath, sep, delete_existing,
canonicalize=self.)
if envname not in self._dict:
self._dict[envname] = {}
self._dict[envname][name] = nv
def (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.
for key, val in kw.():
if ..is_List(val):
val = (val, not delete_existing)
if key not in self._dict or self._dict[key] in ('', None):
self._dict[key] = val
elif ..is_Dict(self._dict[key]) and \
..is_Dict(val):
self._dict[key].(val)
elif ..is_List(val):
dk = self._dict[key]
if not ..is_List(dk):
if delete_existing:
dk = [ for
not in val]
val = [ for
not in dk]
self._dict[key] = val + dk
dk = self._dict[key]
if ..is_List(dk):
if delete_existing:
dk = [ for
not in val]
self._dict[key] = [val] + dk
if not val in dk:
self._dict[key] = [val] + dk
if delete_existing:
dk = [ for
not in val]
self._dict[key] = val + dk
def (self, **kw):
"""Replace existing construction variables in an Environment
with new construction variables and/or values.
kwbd = kw['BUILDERS']
except KeyError:
kwbd = (kwbd,self)
del kw['BUILDERS']
self.('BUILDERS', kwbd)
self.(semi_deepcopy(kw))
def (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.('$'+old_prefix)
old_suffix = self.('$'+old_suffix)
new_prefix = self.('$'+new_prefix)
new_suffix = self.('$'+new_suffix)
dir,name = os..split(str())
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..join(dir, new_prefix+name+new_suffix)
def (self, **kw):
for k in kw.():
if k in self._dict:
self.(**kw)
def (self, tp):
return self..(self.(tp)).().abspath
def (self, tool, toolpath=None, **kw):
if ..is_String(tool):
tool = self.(tool)
if toolpath is None:
toolpath = self.('toolpath', [])
toolpath = list(map(self., toolpath))
tool = ..(tool, toolpath, **kw)
tool(self)
def (self, prog, path=None, pathext=None, reject=[]):
"""Find prog in the path.
= self['ENV']['PATH']
except KeyError:
elif ..is_String():
if pathext is None:
pathext = self['ENV']['PATHEXT']
except KeyError:
elif ..is_String(pathext):
pathext = self.(pathext)
prog = ..(self.(prog))
= ..(prog[0], , pathext, reject)
if : return
return None
def (self, *args, **kw):
def subst_string(a, self=self):
if ..is_String(a):
a = self.(a)
nargs = list(map(subst_string, args))
nkw = self.(kw)
return ..(*nargs, **nkw)
def (self, files, action):
nodes = self.(files, self..)
action = ..(action)
for executor in [n.() for n in nodes]:
uniq[executor] = 1
for executor in uniq.():
executor.(action)
return nodes
def (self, files, action):
nodes = self.(files, self..)
action = ..(action)
for executor in [n.() for n in nodes]:
uniq[executor] = 1
for executor in uniq.():
executor.(action)
return nodes
def (self, target, source=[], action=None, **kw):
tlist = self.(target, self.ans.)
if not ..is_List(source):
source = [source]
source = [_f for _f in source if _f]
if not action:
if not source:
return tlist
for t in tlist:
bld = t.()
.(bld(self, t, source))
nkw = self.(kw)
: ..(action),
'source_factory'
'is_explicit'
bld = ..(**nkw)
for t in tlist:
if b is None or b is :
nkw['action'] = b.action + action
b = ..(**nkw)
.(b(self, t, t.sources + source))
def (self, *targets):
tlist = []
for t in targets:
tlist.(self.(t, self..))
for t in tlist:
return tlist
def (self, *args, **kw):
= """BuildDir() and the build_dir keyword \n\tuse VariantDir() and the variant_dir keyword instead."""
if 'build_dir' in kw:
kw['variant_dir'] = kw['build_dir']
del kw['build_dir']
return self.(*args, **kw)
def (self, **kw):
nkw = self.(kw)
return ..(**nkw)
def (self, path):
is not None:
self._CacheDir_path =
def (self, targets, files):
tlist = self.(targets, self..)
flist = self.(files, self..)
for t in tlist:
[t].(flist)
except KeyError:
[t] = flist
def (self, *args, **kw):
nargs = [self]
nargs = nargs + self.(args)[0]
nkw = self.(kw)
nkw['_depth'] = kw.('_depth', 0) + 1
nkw['custom_tests'] = self.(nkw['custom_tests'])
except KeyError:
return ..(*nargs, **nkw)
def (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."""
'action' : action,
'target_factory' : self..,
'source_factory' : self..,
try: bkw['source_scanner'] = kw['source_scanner']
except KeyError: pass
else: del kw['source_scanner']
bld = ..(**bkw)
return bld(self, target, source, **kw)
def (self, target, dependency):
"""Explicity specify that 'target's depend on 'dependency'."""
tlist = self.(target, self..)
dlist = self.(dependency, self..)
for t in tlist:
return tlist
def (self, name, *args, **kw):
s = self.(name)
if ..is_Sequence(s):
.(self..(, *args, **kw))
return self..(s, *args, **kw)
def (self, *targets):
"""Tags a target so that it will not be cleaned by -c"""
tlist = []
for t in targets:
tlist.(self.(t, self..))
for t in tlist:
return tlist
def (self, *targets):
"""Tags a target so that it will not be cached"""
tlist = []
for t in targets:
tlist.(self.(t, self..))
for t in tlist:
return tlist
def (self, name, *args, **kw):
s = self.(name)
if ..is_Sequence(s):
.(self..(, *args, **kw))
return self..(s, *args, **kw)
def (self, **kw):
return ..(**self.(kw))
def (self, action, *args, **kw):
"""Directly execute an action through an Environment
action = self.(action, *args, **kw)
= action([], [], self)
if isinstance(, ..):
errstr = .errstr
if .filename:
errstr = .filename + ': ' + errstr
sys.stderr.("scons: *** %s\n" % errstr)
return .status
def (self, name, *args, **kw):
s = self.(name)
if ..is_Sequence(s):
.(self..(, *args, **kw))
return self..(s, *args, **kw)
def (self, file, dirs):
file = self.(file)
nodes = self.(dirs, self..)
return ...(file, tuple(nodes))
def (self, sequence):
return ..flatten(sequence)
def (self, files):
= list(map(str, self.(files, self..)))
if ..is_List(files):
return [0]
def (self, pattern, ondisk=True, source=False, strings=False):
return self..(self.(pattern), ondisk, source, strings)
def (self, target, dependency):
"""Ignore a dependency."""
tlist = self.(target, self..)
dlist = self.(dependency, self..)
for t in tlist:
return tlist
def (self, string):
return ..()
def (self, *targets):
for targ in targets:
if isinstance(targ, ..):
ret.(targ)
for t in self.(targ, self..):
return ret
def (self, *targets):
tlist = []
for t in targets:
tlist.(self.(t, self..))
for t in tlist:
return tlist
def (self, *targets):
tlist = []
for t in targets:
tlist.(self.(t, self..))
for t in tlist:
return tlist
def (self, *dirs, **kw):
dirs = self.(list(dirs), self..)
self..(*dirs, **kw)
def (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.(target, self..)
plist = self.(prerequisite, self..)
for t in tlist:
return tlist
def (self, *args, **kw):
nargs = []
for arg in args:
if ..is_String(arg):
arg = self.(arg)
nargs.(arg)
nkw = self.(kw)
return ..(*nargs, **nkw)
def (self, name=".sconsign", dbm_module=None):
if name is not None:
name = self.(name)
if not os..isabs(name):
name = os..join(str(self..SConstruct_dir), name)
name = os..normpath(name)
sconsign_dir = os..dirname(name)
if sconsign_dir and not os..(sconsign_dir):
self.(..(sconsign_dir))
..(name, dbm_module)
def (self, entry, builder):
"""Arrange for a source code builder for (part of) a tree."""
= """SourceCode() has been deprecated and there is no replacement.
\tIf you need this function, please contact scons-dev@scons.org"""
entries = self.(entry, self..)
for entry in entries:
entry.(builder)
return entries
def (self, type):
= "The env.SourceSignatures() \n" + \
"\tconvert your build to use the env.Decider() method instead."
type = self.(type)
self.src_sig_type = type
if type == 'MD5':
if not ..:
raise ("MD5 signatures are not available in this version of Python.")
self. = self.
elif type == 'timestamp':
self. = self.
raise ("Unknown source signature type '%s'" % type)
def (self, arg):
"""This function converts a string or list into a list of strings
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 ..is_List(arg):
return list(map(self., arg))
elif ..is_String(arg):
return self.(arg).split()
return [self.(arg)]
def (self, type):
= "The env.TargetSignatures() \n" + \
"\tconvert your build to use the env.Decider() method instead."
type = self.(type)
self.tgt_sig_type = type
if type in ('MD5', 'content'):
if not ..:
raise ("MD5 signatures are not available in this version of Python.")
self. = self.
elif type == 'timestamp':
self. = self.
elif type == 'build':
self. = self.
elif type == 'source':
self. = self.
raise ("Unknown target signature type '%s'"%type)
def (self, value, built_value=None):
return ...(value, built_value)
def (self, variant_dir, src_dir, duplicate=1):
variant_dir = self.(variant_dir, self..)[0]
src_dir = self.(src_dir, self..)[0]
self..(variant_dir, src_dir, duplicate)
def (self, node='.'):
""" returns a list of all source files.
node = self.(node, self..)[0]
sources = []
def build_source(ss):
for s in ss:
if isinstance(s, ...):
build_source(s.())
elif s.():
build_source(s.sources)
elif isinstance(s.(), ...):
sources.(s)
build_source(node.())
def final_source(node):
while (node != node.()):
node = node.()
return node
sources = map( final_source, sources );
return list((sources))
def (self):
""" returns the list of all targets of the Install and InstallAs Builder.
from . import install
if install._UNIQUE_INSTALLED_FILES is None:
install._UNIQUE_INSTALLED_FILES = ..uniquer_hashables(install._INSTALLED_FILES)
return install._UNIQUE_INSTALLED_FILES
2260 class (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*() those methods can't
be proxied because they need *this* object's methods to fetch the
values from the overrides dictionary.
def (self, subject, overrides={}):
if ..: (self, 'Environment.OverrideEnvironment')
self.__dict__['__subject'] = subject
self.__dict__['overrides'] = overrides
def (self, name):
return getattr(self.__dict__['__subject'], name)
def (self, name, value):
setattr(self.__dict__['__subject'], name, value)
def (self, key):
return self.__dict__['overrides'][key]
except KeyError:
return self.__dict__['__subject'].(key)
def (self, key, value):
if not (key):
raise ..("Illegal construction variable `%s'" % key)
self.__dict__['overrides'][key] = value
def (self, key):
del self.__dict__['overrides'][key]
except KeyError:
deleted = 0
deleted = 1
= self.__dict__['__subject'].(key)
except KeyError:
if not deleted:
def (self, key, default=None):
"""Emulates the get() method of dictionaries."""
return self.__dict__['overrides'][key]
except KeyError:
return self.__dict__['__subject'].(key, )
def (self, key):
self.__dict__['overrides'][key]
except KeyError:
return key in self.__dict__['__subject']
def (self, key):
if self.__dict__['overrides'].(key):
return self.__dict__['__subject'].(key)
def (self):
"""Emulates the items() method of dictionaries."""
= self.__dict__['__subject'].().()
.(self.__dict__['overrides'])
def (self):
"""Emulates the items() method of dictionaries."""
return list(self.().())
def (self):
return self.__dict__['__subject'].()
def (self):
= self.__dict__['__subject'].()
.(self.__dict__['overrides'])
def (self, **kw):
self.__dict__['overrides'].(semi_deepcopy(kw))
2381 def (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 executor_to_lvars(self, kwdict):
if kwdict.('executor'):
kwdict['lvars'] = kwdict['executor'].()
del kwdict['executor']
kwdict['lvars'] = {}
def raw_to_mode(self, dict):
raw = dict['raw']
except KeyError:
del dict['raw']
dict['mode'] = raw
def subst(self, string, *args, **kwargs):
def subst_kw(self, kw, *args, **kwargs):
def subst_list(self, string, *args, **kwargs):
nargs = (, self,) + args
nkw = kwargs.()
nkw['gvars'] = {}
self.executor_to_lvars(nkw)
self.raw_to_mode(nkw)
return ..scons_subst_list(*nargs, **nkw)
def subst_target_source(self, string, *args, **kwargs):
nargs = (, self,) + args
nkw = kwargs.()
nkw['gvars'] = {}
self.executor_to_lvars(nkw)
self.raw_to_mode(nkw)
return ..scons_subst(*nargs, **nkw)
return _NoSubstitutionProxy(subject)

我要回帖

更多关于 页面加载时执行action 的文章

 

随机推荐