"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "SCons/Environment.py" between
SCons-4.3.0.tar.gz and SCons-4.4.0.tar.gz

About: SCons is a software construction tool (a Python script and a set of modules as a superior alternative to the classic "Make" build tool).

Environment.py  (SCons-4.3.0):Environment.py  (SCons-4.4.0)
skipping to change at line 276 skipping to change at line 276
# future, so leave it for now. # future, so leave it for now.
#def execute(self, **kw): #def execute(self, **kw):
# kw['env'] = self.env # kw['env'] = self.env
# self.builder.execute(**kw) # self.builder.execute(**kw)
class BuilderDict(UserDict): class BuilderDict(UserDict):
"""This is a dictionary-like class used by an Environment to hold """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. We need to do this because every time someone changes
the Builders in the Environment's BUILDERS dictionary, we must the Builders in the Environment's BUILDERS dictionary, we must
update the Environment's attributes.""" update the Environment's attributes."""
def __init__(self, dict, env): def __init__(self, mapping, env):
# Set self.env before calling the superclass initialization, # Set self.env before calling the superclass initialization,
# because it will end up calling our other methods, which will # because it will end up calling our other methods, which will
# need to point the values in this dictionary to self.env. # need to point the values in this dictionary to self.env.
self.env = env self.env = env
UserDict.__init__(self, dict) super().__init__(mapping)
def __semi_deepcopy__(self): def __semi_deepcopy__(self):
# These cannot be copied since they would both modify the same builder o bject, and indeed # These cannot be copied since they would both modify the same builder o bject, and indeed
# just copying would modify the original builder # just copying would modify the original builder
raise TypeError( 'cannot semi_deepcopy a BuilderDict' ) raise TypeError( 'cannot semi_deepcopy a BuilderDict' )
def __setitem__(self, item, val): def __setitem__(self, item, val):
try: try:
method = getattr(self.env, item).method method = getattr(self.env, item).method
except AttributeError: except AttributeError:
pass pass
else: else:
self.env.RemoveMethod(method) self.env.RemoveMethod(method)
UserDict.__setitem__(self, item, val) super().__setitem__(item, val)
BuilderWrapper(self.env, val, item) BuilderWrapper(self.env, val, item)
def __delitem__(self, item): def __delitem__(self, item):
UserDict.__delitem__(self, item) super().__delitem__(item)
delattr(self.env, item) delattr(self.env, item)
def update(self, dict): def update(self, mapping):
for i, v in dict.items(): for i, v in mapping.items():
self.__setitem__(i, v) self.__setitem__(i, v)
_is_valid_var = re.compile(r'[_a-zA-Z]\w*$') _is_valid_var = re.compile(r'[_a-zA-Z]\w*$')
def is_valid_construction_var(varstr): def is_valid_construction_var(varstr):
"""Return if the specified string is a legitimate construction """Return if the specified string is a legitimate construction
variable. variable.
""" """
return _is_valid_var.match(varstr) return _is_valid_var.match(varstr)
skipping to change at line 555 skipping to change at line 555
# objects that we need to smush together. No choice # objects that we need to smush together. No choice
# but to make them into a string. # but to make them into a string.
p = ''.join(map(to_String_for_subst, p)) p = ''.join(map(to_String_for_subst, p))
else: else:
p = s(p) p = s(p)
r.append(p) r.append(p)
return r return r
subst_target_source = subst subst_target_source = subst
def backtick(self, command): def backtick(self, command) -> str:
"""Emulate command substitution.
Provides behavior conceptually like POSIX Shell notation
for running a command in backquotes (backticks) by running
``command`` and returning the resulting output string.
This is not really a public API any longer, it is provided for the
use of :meth:`ParseFlags` (which supports it using a syntax of
!command) and :meth:`ParseConfig`.
Raises:
OSError: if the external command returned non-zero exit status.
"""
import subprocess import subprocess
# common arguments # common arguments
kw = { 'stdin' : 'devnull', kw = {
'stdout' : subprocess.PIPE, "stdin": "devnull",
'stderr' : subprocess.PIPE, "stdout": subprocess.PIPE,
'universal_newlines' : True, "stderr": subprocess.PIPE,
} "universal_newlines": True,
}
# if the command is a list, assume it's been quoted # if the command is a list, assume it's been quoted
# othewise force a shell # othewise force a shell
if not is_List(command): kw['shell'] = True if not is_List(command):
kw["shell"] = True
# run constructed command # run constructed command
p = SCons.Action._subproc(self, command, **kw) p = SCons.Action._subproc(self, command, **kw)
out,err = p.communicate() out, err = p.communicate()
status = p.wait() status = p.wait()
if err: if err:
sys.stderr.write("" + err) sys.stderr.write("" + err)
if status: if status:
raise OSError("'%s' exited %d" % (command, status)) raise OSError("'%s' exited %d" % (command, status))
return out return out
def AddMethod(self, function, name=None): def AddMethod(self, function, name=None):
""" """
Adds the specified function as a method of this construction Adds the specified function as a method of this construction
skipping to change at line 619 skipping to change at line 636
for key, value in o.items(): for key, value in o.items():
if key == 'parse_flags': if key == 'parse_flags':
merges = value merges = value
else: else:
overrides[key] = SCons.Subst.scons_subst_once(value, self, key) overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
env = OverrideEnvironment(self, overrides) env = OverrideEnvironment(self, overrides)
if merges: if merges:
env.MergeFlags(merges) env.MergeFlags(merges)
return env return env
def ParseFlags(self, *flags): def ParseFlags(self, *flags) -> dict:
"""Return a dict of parsed flags. """Return a dict of parsed flags.
Parse ``flags`` and return a dict with the flags distributed into Parse ``flags`` and return a dict with the flags distributed into
the appropriate construction variable names. The flags are treated the appropriate construction variable names. The flags are treated
as a typical set of command-line flags for a GNU-like toolchain, as a typical set of command-line flags for a GNU-style toolchain,
such as might have been generated by one of the {foo}-config scripts, such as might have been generated by one of the {foo}-config scripts,
and used to populate the entries based on knowledge embedded in and used to populate the entries based on knowledge embedded in
this method - the choices are not expected to be portable to other this method - the choices are not expected to be portable to other
toolchains. toolchains.
If one of the ``flags`` strings begins with a bang (exclamation mark), If one of the ``flags`` strings begins with a bang (exclamation mark),
it is assumed to be a command and the rest of the string is executed; 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. the result of that evaluation is then added to the dict.
""" """
dict = { mapping = {
'ASFLAGS' : CLVar(''), 'ASFLAGS' : CLVar(''),
'CFLAGS' : CLVar(''), 'CFLAGS' : CLVar(''),
'CCFLAGS' : CLVar(''), 'CCFLAGS' : CLVar(''),
'CXXFLAGS' : CLVar(''), 'CXXFLAGS' : CLVar(''),
'CPPDEFINES' : [], 'CPPDEFINES' : [],
'CPPFLAGS' : CLVar(''), 'CPPFLAGS' : CLVar(''),
'CPPPATH' : [], 'CPPPATH' : [],
'FRAMEWORKPATH' : CLVar(''), 'FRAMEWORKPATH' : CLVar(''),
'FRAMEWORKS' : CLVar(''), 'FRAMEWORKS' : CLVar(''),
'LIBPATH' : [], 'LIBPATH' : [],
skipping to change at line 664 skipping to change at line 681
if not is_String(arg): if not is_String(arg):
for t in arg: do_parse(t) for t in arg: do_parse(t)
return return
# if arg is a command, execute it # if arg is a command, execute it
if arg[0] == '!': if arg[0] == '!':
arg = self.backtick(arg[1:]) arg = self.backtick(arg[1:])
# utility function to deal with -D option # utility function to deal with -D option
def append_define(name, dict = dict): def append_define(name, mapping=mapping):
t = name.split('=') t = name.split('=')
if len(t) == 1: if len(t) == 1:
dict['CPPDEFINES'].append(name) mapping['CPPDEFINES'].append(name)
else: else:
dict['CPPDEFINES'].append([t[0], '='.join(t[1:])]) mapping['CPPDEFINES'].append([t[0], '='.join(t[1:])])
# Loop through the flags and add them to the appropriate option. # Loop through the flags and add them to the appropriate option.
# This tries to strike a balance between checking for all possible # This tries to strike a balance between checking for all possible
# flags and keeping the logic to a finite size, so it doesn't # 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 # 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 # 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 # 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 # flag, for example) we don't check for it. Note that most
# preprocessor options are not handled, since unhandled options # preprocessor options are not handled, since unhandled options
# are placed in CCFLAGS, so unless the preprocessor is invoked # are placed in CCFLAGS, so unless the preprocessor is invoked
skipping to change at line 699 skipping to change at line 716
# IBM compilers may also accept -qframeworkdir=foo # IBM compilers may also accept -qframeworkdir=foo
params = shlex.split(arg) params = shlex.split(arg)
append_next_arg_to = None # for multi-word args append_next_arg_to = None # for multi-word args
for arg in params: for arg in params:
if append_next_arg_to: if append_next_arg_to:
if append_next_arg_to == 'CPPDEFINES': if append_next_arg_to == 'CPPDEFINES':
append_define(arg) append_define(arg)
elif append_next_arg_to == '-include': elif append_next_arg_to == '-include':
t = ('-include', self.fs.File(arg)) t = ('-include', self.fs.File(arg))
dict['CCFLAGS'].append(t) mapping['CCFLAGS'].append(t)
elif append_next_arg_to == '-imacros': elif append_next_arg_to == '-imacros':
t = ('-imacros', self.fs.File(arg)) t = ('-imacros', self.fs.File(arg))
dict['CCFLAGS'].append(t) mapping['CCFLAGS'].append(t)
elif append_next_arg_to == '-isysroot': elif append_next_arg_to == '-isysroot':
t = ('-isysroot', arg) t = ('-isysroot', arg)
dict['CCFLAGS'].append(t) mapping['CCFLAGS'].append(t)
dict['LINKFLAGS'].append(t) mapping['LINKFLAGS'].append(t)
elif append_next_arg_to == '-isystem': elif append_next_arg_to == '-isystem':
t = ('-isystem', arg) t = ('-isystem', arg)
dict['CCFLAGS'].append(t) mapping['CCFLAGS'].append(t)
elif append_next_arg_to == '-iquote': elif append_next_arg_to == '-iquote':
t = ('-iquote', arg) t = ('-iquote', arg)
dict['CCFLAGS'].append(t) mapping['CCFLAGS'].append(t)
elif append_next_arg_to == '-idirafter': elif append_next_arg_to == '-idirafter':
t = ('-idirafter', arg) t = ('-idirafter', arg)
dict['CCFLAGS'].append(t) mapping['CCFLAGS'].append(t)
elif append_next_arg_to == '-arch': elif append_next_arg_to == '-arch':
t = ('-arch', arg) t = ('-arch', arg)
dict['CCFLAGS'].append(t) mapping['CCFLAGS'].append(t)
dict['LINKFLAGS'].append(t) mapping['LINKFLAGS'].append(t)
elif append_next_arg_to == '--param': elif append_next_arg_to == '--param':
t = ('--param', arg) t = ('--param', arg)
dict['CCFLAGS'].append(t) mapping['CCFLAGS'].append(t)
else: else:
dict[append_next_arg_to].append(arg) mapping[append_next_arg_to].append(arg)
append_next_arg_to = None append_next_arg_to = None
elif not arg[0] in ['-', '+']: elif not arg[0] in ['-', '+']:
dict['LIBS'].append(self.fs.File(arg)) mapping['LIBS'].append(self.fs.File(arg))
elif arg == '-dylib_file': elif arg == '-dylib_file':
dict['LINKFLAGS'].append(arg) mapping['LINKFLAGS'].append(arg)
append_next_arg_to = 'LINKFLAGS' append_next_arg_to = 'LINKFLAGS'
elif arg[:2] == '-L': elif arg[:2] == '-L':
if arg[2:]: if arg[2:]:
dict['LIBPATH'].append(arg[2:]) mapping['LIBPATH'].append(arg[2:])
else: else:
append_next_arg_to = 'LIBPATH' append_next_arg_to = 'LIBPATH'
elif arg[:2] == '-l': elif arg[:2] == '-l':
if arg[2:]: if arg[2:]:
dict['LIBS'].append(arg[2:]) mapping['LIBS'].append(arg[2:])
else: else:
append_next_arg_to = 'LIBS' append_next_arg_to = 'LIBS'
elif arg[:2] == '-I': elif arg[:2] == '-I':
if arg[2:]: if arg[2:]:
dict['CPPPATH'].append(arg[2:]) mapping['CPPPATH'].append(arg[2:])
else: else:
append_next_arg_to = 'CPPPATH' append_next_arg_to = 'CPPPATH'
elif arg[:4] == '-Wa,': elif arg[:4] == '-Wa,':
dict['ASFLAGS'].append(arg[4:]) mapping['ASFLAGS'].append(arg[4:])
dict['CCFLAGS'].append(arg) mapping['CCFLAGS'].append(arg)
elif arg[:4] == '-Wl,': elif arg[:4] == '-Wl,':
if arg[:11] == '-Wl,-rpath=': if arg[:11] == '-Wl,-rpath=':
dict['RPATH'].append(arg[11:]) mapping['RPATH'].append(arg[11:])
elif arg[:7] == '-Wl,-R,': elif arg[:7] == '-Wl,-R,':
dict['RPATH'].append(arg[7:]) mapping['RPATH'].append(arg[7:])
elif arg[:6] == '-Wl,-R': elif arg[:6] == '-Wl,-R':
dict['RPATH'].append(arg[6:]) mapping['RPATH'].append(arg[6:])
else: else:
dict['LINKFLAGS'].append(arg) mapping['LINKFLAGS'].append(arg)
elif arg[:4] == '-Wp,': elif arg[:4] == '-Wp,':
dict['CPPFLAGS'].append(arg) mapping['CPPFLAGS'].append(arg)
elif arg[:2] == '-D': elif arg[:2] == '-D':
if arg[2:]: if arg[2:]:
append_define(arg[2:]) append_define(arg[2:])
else: else:
append_next_arg_to = 'CPPDEFINES' append_next_arg_to = 'CPPDEFINES'
elif arg == '-framework': elif arg == '-framework':
append_next_arg_to = 'FRAMEWORKS' append_next_arg_to = 'FRAMEWORKS'
elif arg[:14] == '-frameworkdir=': elif arg[:14] == '-frameworkdir=':
dict['FRAMEWORKPATH'].append(arg[14:]) mapping['FRAMEWORKPATH'].append(arg[14:])
elif arg[:2] == '-F': elif arg[:2] == '-F':
if arg[2:]: if arg[2:]:
dict['FRAMEWORKPATH'].append(arg[2:]) mapping['FRAMEWORKPATH'].append(arg[2:])
else: else:
append_next_arg_to = 'FRAMEWORKPATH' append_next_arg_to = 'FRAMEWORKPATH'
elif arg in [ elif arg in (
'-mno-cygwin', '-mno-cygwin',
'-pthread', '-pthread',
'-openmp', '-openmp',
'-fmerge-all-constants', '-fmerge-all-constants',
'-fopenmp', '-fopenmp',
]: ):
dict['CCFLAGS'].append(arg) mapping['CCFLAGS'].append(arg)
dict['LINKFLAGS'].append(arg) mapping['LINKFLAGS'].append(arg)
elif arg == '-mwindows': elif arg == '-mwindows':
dict['LINKFLAGS'].append(arg) mapping['LINKFLAGS'].append(arg)
elif arg[:5] == '-std=': elif arg[:5] == '-std=':
if '++' in arg[5:]: if '++' in arg[5:]:
key='CXXFLAGS' key = 'CXXFLAGS'
else: else:
key='CFLAGS' key = 'CFLAGS'
dict[key].append(arg) mapping[key].append(arg)
elif arg[0] == '+': elif arg[0] == '+':
dict['CCFLAGS'].append(arg) mapping['CCFLAGS'].append(arg)
dict['LINKFLAGS'].append(arg) mapping['LINKFLAGS'].append(arg)
elif arg in [ elif arg in [
'-include', '-include',
'-imacros', '-imacros',
'-isysroot', '-isysroot',
'-isystem', '-isystem',
'-iquote', '-iquote',
'-idirafter', '-idirafter',
'-arch', '-arch',
'--param', '--param',
]: ]:
append_next_arg_to = arg append_next_arg_to = arg
else: else:
dict['CCFLAGS'].append(arg) mapping['CCFLAGS'].append(arg)
for arg in flags: for arg in flags:
do_parse(arg) do_parse(arg)
return dict return mapping
def MergeFlags(self, args, unique=True): def MergeFlags(self, args, unique=True) -> None:
"""Merge flags into construction variables. """Merge flags into construction variables.
Merges the flags from ``args`` into this construction environent. Merges the flags from ``args`` into this construction environent.
If ``args`` is not a dict, it is first converted to a dictionary with If ``args`` is not a dict, it is first converted to one with
flags distributed into appropriate construction variables. flags distributed into appropriate construction variables.
See :meth:`ParseFlags`. See :meth:`ParseFlags`.
Args: Args:
args: flags to merge args: flags to merge
unique: merge flags rather than appending (default: True) unique: merge flags rather than appending (default: True).
When merging, path variables are retained from the front,
other construction variables from the end.
""" """
if not is_Dict(args): if not is_Dict(args):
args = self.ParseFlags(args) args = self.ParseFlags(args)
if not unique: if not unique:
self.Append(**args) self.Append(**args)
return return
for key, value in args.items(): for key, value in args.items():
if not value: if not value:
skipping to change at line 1270 skipping to change at line 1288
"""Allow Dirs and strings beginning with # for top-relative. """Allow Dirs and strings beginning with # for top-relative.
Note this uses the current env's fs (in self). Note this uses the current env's fs (in self).
""" """
if not is_String(path): # typically a Dir if not is_String(path): # typically a Dir
path = str(path) path = str(path)
if path and path[0] == '#': if path and path[0] == '#':
path = str(self.fs.Dir(path)) path = str(self.fs.Dir(path))
return path return path
def AppendENVPath(self, name, newpath, envname = 'ENV', def AppendENVPath(self, name, newpath, envname='ENV',
sep = os.pathsep, delete_existing=0): sep=os.pathsep, delete_existing=False):
"""Append path elements to the path 'name' in the 'ENV' """Append path elements to the path *name* in the *envname*
dictionary for this environment. Will only add any particular dictionary for this environment. Will only add any particular
path once, and will normpath and normcase all paths to help path once, and will normpath and normcase all paths to help
assure this. This can also handle the case where the env assure this. This can also handle the case where the env
variable is a list instead of a string. variable is a list instead of a string.
If delete_existing is 0, a newpath which is already in the path If *delete_existing* is False, a *newpath* element already in the path
will not be moved to the end (it will be left where it is). will not be moved to the end (it will be left where it is).
""" """
orig = '' orig = ''
if envname in self._dict and name in self._dict[envname]: if envname in self._dict and name in self._dict[envname]:
orig = self._dict[envname][name] orig = self._dict[envname][name]
nv = AppendPath(orig, newpath, sep, delete_existing, canonicalize=self._ canonicalize) nv = AppendPath(orig, newpath, sep, delete_existing, canonicalize=self._ canonicalize)
if envname not in self._dict: if envname not in self._dict:
self._dict[envname] = {} self._dict[envname] = {}
self._dict[envname][name] = nv self._dict[envname][name] = nv
def AppendUnique(self, delete_existing=0, **kw): def AppendUnique(self, delete_existing=False, **kw):
"""Append values to existing construction variables """Append values to existing construction variables
in an Environment, if they're not already there. in an Environment, if they're not already there.
If delete_existing is 1, removes existing values first, so If delete_existing is True, removes existing values first, so
values move to end. values move to end.
""" """
kw = copy_non_reserved_keywords(kw) kw = copy_non_reserved_keywords(kw)
for key, val in kw.items(): for key, val in kw.items():
if is_List(val): if is_List(val):
val = _delete_duplicates(val, delete_existing) val = _delete_duplicates(val, delete_existing)
if key not in self._dict or self._dict[key] in ('', None): if key not in self._dict or self._dict[key] in ('', None):
self._dict[key] = val self._dict[key] = val
elif is_Dict(self._dict[key]) and is_Dict(val): elif is_Dict(self._dict[key]) and is_Dict(val):
self._dict[key].update(val) self._dict[key].update(val)
skipping to change at line 1615 skipping to change at line 1633
suffix = self.subst('$'+suffix) suffix = self.subst('$'+suffix)
prefix = self.subst('$'+prefix) prefix = self.subst('$'+prefix)
for path in paths: for path in paths:
name = os.path.basename(str(path)) name = os.path.basename(str(path))
if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix: if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
return path return path
def ParseConfig(self, command, function=None, unique=True): def ParseConfig(self, command, function=None, unique=True):
""" """Parse the result of running a command to update construction vars.
Use the specified function to parse the output of the command
in order to modify the current environment. The 'command' can Use ``function`` to parse the output of running ``command``
be a string or a list of strings representing a command and in order to modify the current environment.
its arguments. 'Function' is an optional argument that takes
the environment, the output of the command, and the unique flag. Args:
If no function is specified, MergeFlags, which treats the output command: a string or a list of strings representing a command
as the result of a typical 'X-config' command (i.e. gtk-config), and its arguments.
will merge the output into the appropriate variables. function: called to process the result of ``command``, which will
be passed as ``args``. If ``function`` is omitted or ``None``,
:meth:`MergeFlags` is used. Takes 3 args ``(env, args, unique)``
unique: whether no duplicate values are allowed (default true)
""" """
if function is None: if function is None:
def parse_conf(env, cmd, unique=unique): def parse_conf(env, cmd, unique=unique):
return env.MergeFlags(cmd, unique) return env.MergeFlags(cmd, unique)
function = parse_conf function = parse_conf
if is_List(command): if is_List(command):
command = ' '.join(command) command = ' '.join(command)
command = self.subst(command) command = self.subst(command)
return function(self, self.backtick(command)) return function(self, self.backtick(command), unique)
def ParseDepends(self, filename, must_exist=None, only_one=False): def ParseDepends(self, filename, must_exist=None, only_one=False):
""" """
Parse a mkdep-style file for explicit dependencies. This is Parse a mkdep-style file for explicit dependencies. This is
completely abusable, and should be unnecessary in the "normal" completely abusable, and should be unnecessary in the "normal"
case of proper SCons configuration, but it may help make case of proper SCons configuration, but it may help make
the transition from a Make hierarchy easier for some people the transition from a Make hierarchy easier for some people
to swallow. It can also be genuinely useful when using a tool 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 that can write a .d file, but for which writing a scanner would
be too complicated. be too complicated.
skipping to change at line 1743 skipping to change at line 1766
update_dict(val) update_dict(val)
except (AttributeError, TypeError, ValueError): except (AttributeError, TypeError, ValueError):
if is_Dict(val): if is_Dict(val):
for k, v in val.items(): for k, v in val.items():
orig[k] = v orig[k] = v
else: else:
orig[val] = None orig[val] = None
self.scanner_map_delete(kw) self.scanner_map_delete(kw)
def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, def PrependENVPath(self, name, newpath, envname='ENV',
delete_existing=1): sep=os.pathsep, delete_existing=True):
"""Prepend path elements to the path 'name' in the 'ENV' """Prepend path elements to the path *name* in the *envname*
dictionary for this environment. Will only add any particular dictionary for this environment. Will only add any particular
path once, and will normpath and normcase all paths to help path once, and will normpath and normcase all paths to help
assure this. This can also handle the case where the env assure this. This can also handle the case where the env
variable is a list instead of a string. variable is a list instead of a string.
If delete_existing is 0, a newpath which is already in the path If *delete_existing* is False, a *newpath* component already in the path
will not be moved to the front (it will be left where it is). will not be moved to the front (it will be left where it is).
""" """
orig = '' orig = ''
if envname in self._dict and name in self._dict[envname]: if envname in self._dict and name in self._dict[envname]:
orig = self._dict[envname][name] orig = self._dict[envname][name]
nv = PrependPath(orig, newpath, sep, delete_existing, nv = PrependPath(orig, newpath, sep, delete_existing,
canonicalize=self._canonicalize) canonicalize=self._canonicalize)
if envname not in self._dict: if envname not in self._dict:
self._dict[envname] = {} self._dict[envname] = {}
self._dict[envname][name] = nv self._dict[envname][name] = nv
def PrependUnique(self, delete_existing=0, **kw): def PrependUnique(self, delete_existing=False, **kw):
"""Prepend values to existing construction variables """Prepend values to existing construction variables
in an Environment, if they're not already there. in an Environment, if they're not already there.
If delete_existing is 1, removes existing values first, so If delete_existing is True, removes existing values first, so
values move to front. values move to front.
""" """
kw = copy_non_reserved_keywords(kw) kw = copy_non_reserved_keywords(kw)
for key, val in kw.items(): for key, val in kw.items():
if is_List(val): if is_List(val):
val = _delete_duplicates(val, not delete_existing) val = _delete_duplicates(val, not delete_existing)
if key not in self._dict or self._dict[key] in ('', None): if key not in self._dict or self._dict[key] in ('', None):
self._dict[key] = val self._dict[key] = val
elif is_Dict(self._dict[key]) and is_Dict(val): elif is_Dict(self._dict[key]) and is_Dict(val):
self._dict[key].update(val) self._dict[key].update(val)
skipping to change at line 2361 skipping to change at line 2384
But because we subclass SubstitutionEnvironment, this class also But because we subclass SubstitutionEnvironment, this class also
has inherited arg2nodes() and subst*() methods; those methods can't has inherited arg2nodes() and subst*() methods; those methods can't
be proxied because they need *this* object's methods to fetch the be proxied because they need *this* object's methods to fetch the
values from the overrides dictionary. values from the overrides dictionary.
""" """
def __init__(self, subject, overrides=None): def __init__(self, subject, overrides=None):
if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.O verrideEnvironment') if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.O verrideEnvironment')
self.__dict__['__subject'] = subject self.__dict__['__subject'] = subject
if overrides is None: if overrides is None:
self.__dict__['overrides'] = dict() self.__dict__['overrides'] = {}
else: else:
self.__dict__['overrides'] = overrides self.__dict__['overrides'] = overrides
# Methods that make this class act like a proxy. # Methods that make this class act like a proxy.
def __getattr__(self, name): def __getattr__(self, name):
attr = getattr(self.__dict__['__subject'], name) attr = getattr(self.__dict__['__subject'], name)
# Here we check if attr is one of the Wrapper classes. For # Here we check if attr is one of the Wrapper classes. For
# example when a pseudo-builder is being called from an # example when a pseudo-builder is being called from an
# OverrideEnvironment. # OverrideEnvironment.
# #
skipping to change at line 2458 skipping to change at line 2481
return self.__getitem__(key) return self.__getitem__(key)
except KeyError: except KeyError:
self.__dict__['overrides'][key] = default self.__dict__['overrides'][key] = default
return default return default
# Overridden private construction environment methods. # Overridden private construction environment methods.
def _update(self, other): def _update(self, other):
self.__dict__['overrides'].update(other) self.__dict__['overrides'].update(other)
def _update_onlynew(self, other): def _update_onlynew(self, other):
"""Update a dict with new keys.
Unlike the .update method, if the key is already present,
it is not replaced.
"""
for k, v in other.items(): for k, v in other.items():
if k not in self.__dict__['overrides']: if k not in self.__dict__['overrides']:
self.__dict__['overrides'][k] = v self.__dict__['overrides'][k] = v
def gvars(self): def gvars(self):
return self.__dict__['__subject'].gvars() return self.__dict__['__subject'].gvars()
def lvars(self): def lvars(self):
lvars = self.__dict__['__subject'].lvars() lvars = self.__dict__['__subject'].lvars()
lvars.update(self.__dict__['overrides']) lvars.update(self.__dict__['overrides'])
skipping to change at line 2500 skipping to change at line 2528
substitute variables if left to its own devices). substitute variables if left to its own devices).
We have to wrap this in a function that allows us to delay definition of 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 the class until it's necessary, so that when it subclasses Environment
it will pick up whatever Environment subclass the wrapper interface it will pick up whatever Environment subclass the wrapper interface
might have assigned to SCons.Environment.Environment. might have assigned to SCons.Environment.Environment.
""" """
class _NoSubstitutionProxy(Environment): class _NoSubstitutionProxy(Environment):
def __init__(self, subject): def __init__(self, subject):
self.__dict__['__subject'] = subject self.__dict__['__subject'] = subject
def __getattr__(self, name): def __getattr__(self, name):
return getattr(self.__dict__['__subject'], name) return getattr(self.__dict__['__subject'], name)
def __setattr__(self, name, value): def __setattr__(self, name, value):
return setattr(self.__dict__['__subject'], name, value) return setattr(self.__dict__['__subject'], name, value)
def executor_to_lvars(self, kwdict): def executor_to_lvars(self, kwdict):
if 'executor' in kwdict: if 'executor' in kwdict:
kwdict['lvars'] = kwdict['executor'].get_lvars() kwdict['lvars'] = kwdict['executor'].get_lvars()
del kwdict['executor'] del kwdict['executor']
else: else:
kwdict['lvars'] = {} kwdict['lvars'] = {}
def raw_to_mode(self, dict):
def raw_to_mode(self, mapping):
try: try:
raw = dict['raw'] raw = mapping['raw']
except KeyError: except KeyError:
pass pass
else: else:
del dict['raw'] del mapping['raw']
dict['mode'] = raw mapping['mode'] = raw
def subst(self, string, *args, **kwargs): def subst(self, string, *args, **kwargs):
return string return string
def subst_kw(self, kw, *args, **kwargs): def subst_kw(self, kw, *args, **kwargs):
return kw return kw
def subst_list(self, string, *args, **kwargs): def subst_list(self, string, *args, **kwargs):
nargs = (string, self,) + args nargs = (string, self,) + args
nkw = kwargs.copy() nkw = kwargs.copy()
nkw['gvars'] = {} nkw['gvars'] = {}
self.executor_to_lvars(nkw) self.executor_to_lvars(nkw)
self.raw_to_mode(nkw) self.raw_to_mode(nkw)
return SCons.Subst.scons_subst_list(*nargs, **nkw) return SCons.Subst.scons_subst_list(*nargs, **nkw)
def subst_target_source(self, string, *args, **kwargs): def subst_target_source(self, string, *args, **kwargs):
nargs = (string, self,) + args nargs = (string, self,) + args
nkw = kwargs.copy() nkw = kwargs.copy()
nkw['gvars'] = {} nkw['gvars'] = {}
self.executor_to_lvars(nkw) self.executor_to_lvars(nkw)
self.raw_to_mode(nkw) self.raw_to_mode(nkw)
return SCons.Subst.scons_subst(*nargs, **nkw) return SCons.Subst.scons_subst(*nargs, **nkw)
return _NoSubstitutionProxy(subject) return _NoSubstitutionProxy(subject)
# Local Variables: # Local Variables:
# tab-width:4 # tab-width:4
# indent-tabs-mode:nil # indent-tabs-mode:nil
# End: # End:
# vim: set expandtab tabstop=4 shiftwidth=4: # vim: set expandtab tabstop=4 shiftwidth=4:
 End of changes. 73 change blocks. 
88 lines changed or deleted 125 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)