summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Environment.py
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-09-07 04:14:49 (GMT)
committerSteven Knight <knight@baldmt.com>2003-09-07 04:14:49 (GMT)
commit61d018dfceac6cb9717caeeea7125d7a55b4b0eb (patch)
treea5d6529470d3797256f03ba197dedc1cac1feded /src/engine/SCons/Environment.py
parentbf221d4e593f803116af76ec3bc16514b666c9f1 (diff)
downloadSCons-61d018dfceac6cb9717caeeea7125d7a55b4b0eb.zip
SCons-61d018dfceac6cb9717caeeea7125d7a55b4b0eb.tar.gz
SCons-61d018dfceac6cb9717caeeea7125d7a55b4b0eb.tar.bz2
Rearrange the Environment methods and tests.
Diffstat (limited to 'src/engine/SCons/Environment.py')
-rw-r--r--src/engine/SCons/Environment.py552
1 files changed, 292 insertions, 260 deletions
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index f72bc95..e7407ee 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -59,6 +59,8 @@ class _Null:
_null = _Null
+DefaultTargets = None
+
def installFunc(target, source, env):
"""Install a source file into a target using the function specified
as the INSTALL construction variable."""
@@ -169,6 +171,20 @@ class Environment:
Environment.
"""
+ #######################################################################
+ # This is THE class for interacting with the SCons build engine,
+ # and it contains a lot of stuff, so we're going to try to keep this
+ # a little organized by grouping the methods.
+ #######################################################################
+
+ #######################################################################
+ # Methods that make an Environment act like a dictionary. These have
+ # the expected standard names for Python mapping objects. Note that
+ # we don't actually make an Environment a subclass of UserDict for
+ # performance reasons. Note also that we only supply methods for
+ # dictionary functionality that we actually need and use.
+ #######################################################################
+
def __init__(self,
platform=None,
tools=None,
@@ -217,6 +233,46 @@ class Environment:
def __cmp__(self, other):
return cmp(self._dict, other._dict)
+ def __getitem__(self, key):
+ return self._dict[key]
+
+ def __setitem__(self, key, value):
+ if key in ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']:
+ SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning,
+ "Ignoring attempt to set reserved variable `%s'" % key)
+ elif key == 'BUILDERS':
+ try:
+ bd = self._dict[key]
+ for k in bd.keys():
+ del bd[k]
+ except KeyError:
+ self._dict[key] = BuilderDict(kwbd, self)
+ self._dict[key].update(value)
+ else:
+ if not SCons.Util.is_valid_construction_var(key):
+ raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
+ self._dict[key] = value
+
+ def __delitem__(self, key):
+ del self._dict[key]
+
+ def items(self):
+ "Emulates the items() method of dictionaries."""
+ return self._dict.items()
+
+ def has_key(self, key):
+ return self._dict.has_key(key)
+
+ def get(self, key, default=None):
+ "Emulates the get() method of dictionaries."""
+ return self._dict.get(key, default)
+
+ #######################################################################
+ # Utility methods that are primarily for internal use by SCons.
+ # These begin with lower-case letters. Note that the subst() method
+ # is actually already out of the closet and used by people.
+ #######################################################################
+
def arg2nodes(self, args, node_factory=_null, lookup_list=_null):
if node_factory is _null:
node_factory = self.fs.File
@@ -251,8 +307,99 @@ class Environment:
return nodes
- def Builders(self):
- pass # XXX
+ def get_builder(self, name):
+ """Fetch the builder with the specified name from the environment.
+ """
+ try:
+ return self._dict['BUILDERS'][name]
+ except KeyError:
+ return None
+
+ def get_scanner(self, skey):
+ """Find the appropriate scanner given a key (usually a file suffix).
+ Does a linear search. Could be sped up by creating a dictionary if
+ this proves too slow.
+ """
+ if self._dict['SCANNERS']:
+ for scanner in self._dict['SCANNERS']:
+ if skey in scanner.skeys:
+ return scanner
+ return None
+
+ def subst(self, string, raw=0, target=None, source=None):
+ """Recursively interpolates construction variables from the
+ Environment into the specified string, returning the expanded
+ result. Construction variables are specified by a $ prefix
+ in the string and begin with an initial underscore or
+ alphabetic character followed by any number of underscores
+ or alphanumeric characters. The construction variable names
+ may be surrounded by curly braces to separate the name from
+ trailing characters.
+ """
+ if raw:
+ mode = SCons.Util.SUBST_RAW
+ else:
+ mode = SCons.Util.SUBST_CMD
+ return SCons.Util.scons_subst(string, self, mode,
+ target, source)
+
+ def subst_list(self, string, raw=0, target=None, source=None):
+ """Calls through to SCons.Util.scons_subst_list(). See
+ the documentation for that function."""
+ if raw:
+ mode = SCons.Util.SUBST_RAW
+ else:
+ mode = SCons.Util.SUBST_CMD
+ return SCons.Util.scons_subst_list(string, self, mode,
+ target, source)
+
+ #######################################################################
+ # Public methods for manipulating an Environment. These begin with
+ # upper-case letters. The essential characteristic of methods in
+ # this section is that they do *not* have corresponding same-named
+ # global functions. For example, a stand-alone Append() function
+ # makes no sense, because Append() is all about appending values to
+ # an Environment's construction variables.
+ #######################################################################
+
+ def Append(self, **kw):
+ """Append values to existing construction variables
+ in an Environment.
+ """
+ kw = our_deepcopy(kw)
+ for key in kw.keys():
+ if not self._dict.has_key(key):
+ self._dict[key] = kw[key]
+ elif SCons.Util.is_List(self._dict[key]) and not \
+ SCons.Util.is_List(kw[key]):
+ self._dict[key] = self._dict[key] + [ kw[key] ]
+ elif SCons.Util.is_List(kw[key]) and not \
+ SCons.Util.is_List(self._dict[key]):
+ self._dict[key] = [ self._dict[key] ] + kw[key]
+ elif SCons.Util.is_Dict(self._dict[key]) and \
+ SCons.Util.is_Dict(kw[key]):
+ self._dict[key].update(kw[key])
+ else:
+ self._dict[key] = self._dict[key] + kw[key]
+
+ def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
+ """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.
+ """
+
+ orig = ''
+ if self._dict.has_key(envname) and self._dict[envname].has_key(name):
+ orig = self._dict[envname][name]
+
+ nv = SCons.Util.AppendPath(orig, newpath, sep)
+
+ if not self._dict.has_key(envname):
+ self._dict[envname] = {}
+
+ self._dict[envname][name] = nv
def Copy(self, tools=None, **kw):
"""Return a copy of a construction Environment. The
@@ -276,40 +423,62 @@ class Environment:
apply(clone.Replace, (), kw)
return clone
- def Scanners(self):
- pass # XXX
+ def Detect(self, progs):
+ """Return the first available program in progs.
+ """
+ if not SCons.Util.is_List(progs):
+ progs = [ progs ]
+ for prog in progs:
+ path = self.WhereIs(prog)
+ if path: return prog
+ return None
+
+ def Dictionary(self, *args):
+ if not args:
+ return self._dict
+ dlist = map(lambda x, s=self: s._dict[x], args)
+ if len(dlist) == 1:
+ dlist = dlist[0]
+ return dlist
- def Replace(self, **kw):
- """Replace existing construction variables in an Environment
- with new construction variables and/or values.
+ def FindIxes(self, paths, prefix, suffix):
"""
- try:
- kwbd = our_deepcopy(kw['BUILDERS'])
- del kw['BUILDERS']
- self.__setitem__('BUILDERS', kwbd)
- except KeyError:
- pass
- self._dict.update(our_deepcopy(kw))
+ Search a list of paths for something that matches the prefix and suffix.
- def Append(self, **kw):
- """Append values to existing construction variables
- in an Environment.
+ paths - the list of paths or nodes.
+ prefix - construction variable for the prefix.
+ suffix - construction variable for the suffix.
"""
- kw = our_deepcopy(kw)
- for key in kw.keys():
- if not self._dict.has_key(key):
- self._dict[key] = kw[key]
- elif SCons.Util.is_List(self._dict[key]) and not \
- SCons.Util.is_List(kw[key]):
- self._dict[key] = self._dict[key] + [ kw[key] ]
- elif SCons.Util.is_List(kw[key]) and not \
- SCons.Util.is_List(self._dict[key]):
- self._dict[key] = [ self._dict[key] ] + kw[key]
- elif SCons.Util.is_Dict(self._dict[key]) and \
- SCons.Util.is_Dict(kw[key]):
- self._dict[key].update(kw[key])
- else:
- self._dict[key] = self._dict[key] + kw[key]
+
+ suffix = self.subst('$%s'%suffix)
+ prefix = self.subst('$%s'%prefix)
+
+ for path in paths:
+ dir,name = os.path.split(str(path))
+ if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
+ return path
+
+ def Override(self, overrides):
+ """
+ Produce a modified environment whose variables
+ are overriden by the overrides dictionaries.
+
+ overrides - a dictionary that will override
+ the variables of this environment.
+
+ This function is much more efficient than Copy()
+ or creating a new Environment because it doesn't do
+ a deep copy of the dictionary, and doesn't do a copy
+ at all if there are no overrides.
+ """
+
+ if overrides:
+ env = copy.copy(self)
+ env._dict = copy.copy(self._dict)
+ env._dict.update(overrides)
+ return env
+ else:
+ return self
def Prepend(self, **kw):
"""Prepend values to existing construction variables
@@ -350,47 +519,63 @@ class Environment:
self._dict[envname][name] = nv
- def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
- """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.
+ def Replace(self, **kw):
+ """Replace existing construction variables in an Environment
+ with new construction variables and/or values.
"""
+ try:
+ kwbd = our_deepcopy(kw['BUILDERS'])
+ del kw['BUILDERS']
+ self.__setitem__('BUILDERS', kwbd)
+ except KeyError:
+ pass
+ self._dict.update(our_deepcopy(kw))
- orig = ''
- if self._dict.has_key(envname) and self._dict[envname].has_key(name):
- orig = self._dict[envname][name]
-
- nv = SCons.Util.AppendPath(orig, newpath, sep)
-
- if not self._dict.has_key(envname):
- self._dict[envname] = {}
-
- self._dict[envname][name] = nv
+ def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
+ """
+ Replace old_prefix with new_prefix and old_suffix with new_suffix.
+ env - Environment used to interpolate variables.
+ path - the path that will be modified.
+ old_prefix - construction variable for the old prefix.
+ old_suffix - construction variable for the old suffix.
+ new_prefix - construction variable for the new prefix.
+ new_suffix - construction variable for the new suffix.
+ """
+ old_prefix = self.subst('$%s'%old_prefix)
+ old_suffix = self.subst('$%s'%old_suffix)
- def Depends(self, target, dependency):
- """Explicity specify that 'target's depend on 'dependency'."""
- tlist = self.arg2nodes(target, self.fs.File)
- dlist = self.arg2nodes(dependency, self.fs.File)
- for t in tlist:
- t.add_dependency(dlist)
+ new_prefix = self.subst('$%s'%new_prefix)
+ new_suffix = self.subst('$%s'%new_suffix)
- if len(tlist) == 1:
- tlist = tlist[0]
- return tlist
+ dir,name = os.path.split(str(path))
+ if name[:len(old_prefix)] == old_prefix:
+ name = name[len(old_prefix):]
+ if name[-len(old_suffix):] == old_suffix:
+ name = name[:-len(old_suffix)]
+ return os.path.join(dir, new_prefix+name+new_suffix)
- def Ignore(self, target, dependency):
- """Ignore a dependency."""
- tlist = self.arg2nodes(target, self.fs.File)
- dlist = self.arg2nodes(dependency, self.fs.File)
- for t in tlist:
- t.add_ignore(dlist)
+ def WhereIs(self, prog):
+ """Find prog in the path.
+ """
+ path = None
+ pathext = None
+ if self.has_key('ENV'):
+ if self['ENV'].has_key('PATH'):
+ path = self['ENV']['PATH']
+ if self['ENV'].has_key('PATHEXT'):
+ pathext = self['ENV']['PATHEXT']
+ path = SCons.Util.WhereIs(prog, path, pathext)
+ if path: return path
+ return None
- if len(tlist) == 1:
- tlist = tlist[0]
- return tlist
+ #######################################################################
+ # Public methods for doing real "SCons stuff" (manipulating
+ # dependencies, setting attributes on targets, etc.). These begin
+ # with upper-case letters. The essential characteristic of methods
+ # in this section is that they all *should* have corresponding
+ # same-named global functions.
+ #######################################################################
def AlwaysBuild(self, *targets):
tlist = []
@@ -404,52 +589,6 @@ class Environment:
tlist = tlist[0]
return tlist
- def Precious(self, *targets):
- tlist = []
- for t in targets:
- tlist.extend(self.arg2nodes(t, self.fs.File))
-
- for t in tlist:
- t.set_precious()
-
- if len(tlist) == 1:
- tlist = tlist[0]
- return tlist
-
- def Dictionary(self, *args):
- if not args:
- return self._dict
- dlist = map(lambda x, s=self: s._dict[x], args)
- if len(dlist) == 1:
- dlist = dlist[0]
- return dlist
-
- def __setitem__(self, key, value):
- if key in ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']:
- SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning,
- "Ignoring attempt to set reserved variable `%s'" % key)
- elif key == 'BUILDERS':
- try:
- bd = self._dict[key]
- for k in bd.keys():
- del bd[k]
- except KeyError:
- self._dict[key] = BuilderDict(kwbd, self)
- self._dict[key].update(value)
- else:
- if not SCons.Util.is_valid_construction_var(key):
- raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
- self._dict[key] = value
-
- def __getitem__(self, key):
- return self._dict[key]
-
- def __delitem__(self, key):
- del self._dict[key]
-
- def has_key(self, key):
- return self._dict.has_key(key)
-
def Command(self, target, source, action):
"""Builds the supplied target files from the supplied
source files using the supplied action. Action may
@@ -459,6 +598,28 @@ class Environment:
source_factory=SCons.Node.FS.default_fs.Entry)
return bld(self, target, source)
+ def Depends(self, target, dependency):
+ """Explicity specify that 'target's depend on 'dependency'."""
+ tlist = self.arg2nodes(target, self.fs.File)
+ dlist = self.arg2nodes(dependency, self.fs.File)
+ for t in tlist:
+ t.add_dependency(dlist)
+
+ if len(tlist) == 1:
+ tlist = tlist[0]
+ return tlist
+
+ def Ignore(self, target, dependency):
+ """Ignore a dependency."""
+ tlist = self.arg2nodes(target, self.fs.File)
+ dlist = self.arg2nodes(dependency, self.fs.File)
+ for t in tlist:
+ t.add_ignore(dlist)
+
+ if len(tlist) == 1:
+ tlist = tlist[0]
+ return tlist
+
def Install(self, dir, source):
"""Install specified files in the given directory."""
try:
@@ -492,14 +653,17 @@ class Environment:
ret = ret[0]
return ret
- def SourceCode(self, entry, builder):
- """Arrange for a source code builder for (part of) a tree."""
- entries = self.arg2nodes(entry, self.fs.Entry)
- for entry in entries:
- entry.set_src_builder(builder)
- if len(entries) == 1:
- return entries[0]
- return entries
+ def Precious(self, *targets):
+ tlist = []
+ for t in targets:
+ tlist.extend(self.arg2nodes(t, self.fs.File))
+
+ for t in tlist:
+ t.set_precious()
+
+ if len(tlist) == 1:
+ tlist = tlist[0]
+ return tlist
def SideEffect(self, side_effect, target):
"""Tell scons that side_effects are built as side
@@ -523,143 +687,11 @@ class Environment:
else:
return side_effects
- def subst(self, string, raw=0, target=None, source=None):
- """Recursively interpolates construction variables from the
- Environment into the specified string, returning the expanded
- result. Construction variables are specified by a $ prefix
- in the string and begin with an initial underscore or
- alphabetic character followed by any number of underscores
- or alphanumeric characters. The construction variable names
- may be surrounded by curly braces to separate the name from
- trailing characters.
- """
- if raw:
- mode = SCons.Util.SUBST_RAW
- else:
- mode = SCons.Util.SUBST_CMD
- return SCons.Util.scons_subst(string, self, mode,
- target, source)
-
- def subst_list(self, string, raw=0, target=None, source=None):
- """Calls through to SCons.Util.scons_subst_list(). See
- the documentation for that function."""
- if raw:
- mode = SCons.Util.SUBST_RAW
- else:
- mode = SCons.Util.SUBST_CMD
- return SCons.Util.scons_subst_list(string, self, mode,
- target, source)
-
- def get_scanner(self, skey):
- """Find the appropriate scanner given a key (usually a file suffix).
- Does a linear search. Could be sped up by creating a dictionary if
- this proves too slow.
- """
- if self._dict['SCANNERS']:
- for scanner in self._dict['SCANNERS']:
- if skey in scanner.skeys:
- return scanner
- return None
-
- def get_builder(self, name):
- """Fetch the builder with the specified name from the environment.
- """
- try:
- return self._dict['BUILDERS'][name]
- except KeyError:
- return None
-
- def Detect(self, progs):
- """Return the first available program in progs.
- """
- if not SCons.Util.is_List(progs):
- progs = [ progs ]
- for prog in progs:
- path = self.WhereIs(prog)
- if path: return prog
- return None
-
- def WhereIs(self, prog):
- """Find prog in the path.
- """
- path = None
- pathext = None
- if self.has_key('ENV'):
- if self['ENV'].has_key('PATH'):
- path = self['ENV']['PATH']
- if self['ENV'].has_key('PATHEXT'):
- pathext = self['ENV']['PATHEXT']
- path = SCons.Util.WhereIs(prog, path, pathext)
- if path: return path
- return None
-
- def Override(self, overrides):
- """
- Produce a modified environment whose variables
- are overriden by the overrides dictionaries.
-
- overrides - a dictionary that will override
- the variables of this environment.
-
- This function is much more efficient than Copy()
- or creating a new Environment because it doesn't do
- a deep copy of the dictionary, and doesn't do a copy
- at all if there are no overrides.
- """
-
- if overrides:
- env = copy.copy(self)
- env._dict = copy.copy(self._dict)
- env._dict.update(overrides)
- return env
- else:
- return self
-
- def get(self, key, default=None):
- "Emulates the get() method of dictionaries."""
- return self._dict.get(key, default)
-
- def items(self):
- "Emulates the items() method of dictionaries."""
- return self._dict.items()
-
- def FindIxes(self, paths, prefix, suffix):
- """
- Search a list of paths for something that matches the prefix and suffix.
-
- paths - the list of paths or nodes.
- prefix - construction variable for the prefix.
- suffix - construction variable for the suffix.
- """
-
- suffix = self.subst('$%s'%suffix)
- prefix = self.subst('$%s'%prefix)
-
- for path in paths:
- dir,name = os.path.split(str(path))
- if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
- return path
-
- def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
- """
- Replace old_prefix with new_prefix and old_suffix with new_suffix.
-
- env - Environment used to interpolate variables.
- path - the path that will be modified.
- old_prefix - construction variable for the old prefix.
- old_suffix - construction variable for the old suffix.
- new_prefix - construction variable for the new prefix.
- new_suffix - construction variable for the new suffix.
- """
- old_prefix = self.subst('$%s'%old_prefix)
- old_suffix = self.subst('$%s'%old_suffix)
-
- new_prefix = self.subst('$%s'%new_prefix)
- new_suffix = self.subst('$%s'%new_suffix)
-
- dir,name = os.path.split(str(path))
- if name[:len(old_prefix)] == old_prefix:
- name = name[len(old_prefix):]
- if name[-len(old_suffix):] == old_suffix:
- name = name[:-len(old_suffix)]
- return os.path.join(dir, new_prefix+name+new_suffix)
+ def SourceCode(self, entry, builder):
+ """Arrange for a source code builder for (part of) a tree."""
+ entries = self.arg2nodes(entry, self.fs.Entry)
+ for entry in entries:
+ entry.set_src_builder(builder)
+ if len(entries) == 1:
+ return entries[0]
+ return entries