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 |