_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."""
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,
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
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
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
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] = {}
+ def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
+ """
+ Replace old_prefix with new_prefix and old_suffix with new_suffix.
- self._dict[envname][name] = nv
+ 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)
- 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)
+ 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)
- 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)
+ 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 = []
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
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:
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
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
class EnvironmentTestCase(unittest.TestCase):
- def test_Override(self):
- "Test overriding construction variables"
- env = Environment(ONE=1, TWO=2)
- assert env['ONE'] == 1
- assert env['TWO'] == 2
- env2 = env.Override({'TWO':'10'})
- assert env2['ONE'] == 1
- assert env2['TWO'] == '10'
- assert env['TWO'] == 2
- env2.Replace(ONE = "won")
- assert env2['ONE'] == "won"
- assert env['ONE'] == 1
+ def test___init__(self):
+ """Test construction Environments creation
+
+ Create two with identical arguments and check that
+ they compare the same.
+ """
+ env1 = Environment(XXX = 'x', YYY = 'y')
+ env2 = Environment(XXX = 'x', YYY = 'y')
+ assert env1 == env2, diff_env(env1, env2)
+
+ def test_get(self):
+ """Test the get() method."""
+ env = Environment(aaa = 'AAA')
+
+ x = env.get('aaa')
+ assert x == 'AAA', x
+ x = env.get('aaa', 'XXX')
+ assert x == 'AAA', x
+ x = env.get('bbb')
+ assert x is None, x
+ x = env.get('bbb', 'XXX')
+ assert x == 'XXX', x
def test_arg2nodes(self):
"""Test the arg2nodes method
assert not hasattr(nodes[1], 'bbbb'), nodes[0]
assert nodes[1].c == 1, nodes[1]
+ def test_subst(self):
+ """Test substituting construction variables within strings
+
+ Check various combinations, including recursive expansion
+ of variables into other variables.
+ """
+ env = Environment(AAA = 'a', BBB = 'b')
+ mystr = env.subst("$AAA ${AAA}A $BBBB $BBB")
+ assert mystr == "a aA b", str
+
+ # Changed the tests below to reflect a bug fix in
+ # subst()
+ env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
+ mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
+ assert mystr == "b bA bB b", str
+ env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
+ mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
+ assert mystr == "c cA cB c", str
+
+ env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ])
+ lst = env.subst_list([ "$AAA", "B $CCC" ])
+ assert lst == [ [ "a", "b" ], [ "c", "B a", "b" ], [ "c" ] ], lst
+
+ class DummyNode:
+ def __init__(self, name):
+ self.name = name
+ def __str__(self):
+ return self.name
+ def rfile(self):
+ return self
+ def get_subst_proxy(self):
+ return self
+
+ # Test callables in the Environment
+ def foo(target, source, env, for_signature):
+ assert str(target) == 't', target
+ assert str(source) == 's', source
+ return env["FOO"]
+
+ env = Environment(BAR=foo, FOO='baz')
+
+ subst = env.subst('test $BAR', target=DummyNode('t'), source=DummyNode('s'))
+ assert subst == 'test baz', subst
+
+ lst = env.subst_list('test $BAR', target=DummyNode('t'), source=DummyNode('s'))
+ assert lst[0][0] == 'test', lst[0][0]
+ assert lst[0][1] == 'baz', lst[0][1]
+
def test_Builder_calls(self):
"""Test Builder calls through different environments
"""
assert not called_it.has_key('target')
assert not called_it.has_key('source')
+
+
def test_Builder_execs(self):
"""Test Builder execution through different environments
# s = env3.get_scanner(".cxx")
# assert s == None, s
- def test_Copy(self):
- """Test construction Environment copying
-
- Update the copy independently afterwards and check that
- the original remains intact (that is, no dangling
- references point to objects in the copied environment).
- Copy the original with some construction variable
- updates and check that the original remains intact
- and the copy has the updated values.
- """
- env1 = Environment(XXX = 'x', YYY = 'y')
- env2 = env1.Copy()
- env1copy = env1.Copy()
- env2.Replace(YYY = 'yyy')
- assert env1 != env2
- assert env1 == env1copy
-
- env3 = env1.Copy(XXX = 'x3', ZZZ = 'z3')
- assert env3.Dictionary('XXX') == 'x3'
- assert env3.Dictionary('YYY') == 'y'
- assert env3.Dictionary('ZZZ') == 'z3'
- assert env1 == env1copy
-
- # Ensure that lists and dictionaries are
- # deep copied, but not instances.
- class TestA:
- pass
- env1 = Environment(XXX=TestA(), YYY = [ 1, 2, 3 ],
- ZZZ = { 1:2, 3:4 })
- env2=env1.Copy()
- env2.Dictionary('YYY').append(4)
- env2.Dictionary('ZZZ')[5] = 6
- assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
- assert 4 in env2.Dictionary('YYY')
- assert not 4 in env1.Dictionary('YYY')
- assert env2.Dictionary('ZZZ').has_key(5)
- assert not env1.Dictionary('ZZZ').has_key(5)
-
- #
- env1 = Environment(BUILDERS = {'b1' : 1})
- assert hasattr(env1, 'b1'), "env1.b1 was not set"
- assert env1.b1.env == env1, "b1.env doesn't point to env1"
- env2 = env1.Copy(BUILDERS = {'b2' : 2})
- assert hasattr(env1, 'b1'), "b1 was mistakenly cleared from env1"
- assert env1.b1.env == env1, "b1.env was changed"
- assert not hasattr(env2, 'b1'), "b1 was not cleared from env2"
- assert hasattr(env2, 'b2'), "env2.b2 was not set"
- assert env2.b2.env == env2, "b2.env doesn't point to env2"
-
- # Ensure that specifying new tools in a copied environment
- # works.
- def foo(env): env['FOO'] = 1
- def bar(env): env['BAR'] = 2
- def baz(env): env['BAZ'] = 3
- env1 = Environment(tools=[foo])
- env2 = env1.Copy()
- env3 = env1.Copy(tools=[bar, baz])
-
- assert env1.get('FOO') is 1
- assert env1.get('BAR') is None
- assert env1.get('BAZ') is None
- assert env2.get('FOO') is 1
- assert env2.get('BAR') is None
- assert env2.get('BAZ') is None
- assert env3.get('FOO') is 1
- assert env3.get('BAR') is 2
- assert env3.get('BAZ') is 3
-
- def test_Dictionary(self):
- """Test retrieval of known construction variables
-
- Fetch them from the Dictionary and check for well-known
- defaults that get inserted.
- """
- env = Environment(XXX = 'x', YYY = 'y', ZZZ = 'z')
- assert env.Dictionary('XXX') == 'x'
- assert env.Dictionary('YYY') == 'y'
- assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z']
- xxx, zzz = env.Dictionary('XXX', 'ZZZ')
- assert xxx == 'x'
- assert zzz == 'z'
- assert env.Dictionary().has_key('BUILDERS')
- assert env.Dictionary().has_key('CC')
- assert env.Dictionary().has_key('CCFLAGS')
- assert env.Dictionary().has_key('ENV')
-
- assert env['XXX'] == 'x'
- env['XXX'] = 'foo'
- assert env.Dictionary('XXX') == 'foo'
- del env['XXX']
- assert not env.Dictionary().has_key('XXX')
-
def test_ENV(self):
"""Test setting the external ENV in Environments
"""
env = Environment(ENV = { 'PATH' : '/foo:/bar' })
assert env.Dictionary('ENV')['PATH'] == '/foo:/bar'
- def test_Environment(self):
- """Test construction Environments creation
-
- Create two with identical arguments and check that
- they compare the same.
- """
- env1 = Environment(XXX = 'x', YYY = 'y')
- env2 = Environment(XXX = 'x', YYY = 'y')
- assert env1 == env2, diff_env(env1, env2)
-
- def test_Install(self):
- """Test Install and InstallAs methods"""
- env = Environment(FOO='iii', BAR='jjj')
-
- tgt = env.Install('export', [ 'build/foo1', 'build/foo2' ])
- paths = map(str, tgt)
- paths.sort()
- expect = map(os.path.normpath, [ 'export/foo1', 'export/foo2' ])
- assert paths == expect, paths
- for tnode in tgt:
- assert tnode.builder == InstallBuilder
-
- tgt = env.Install('$FOO', [ 'build/${BAR}1', 'build/${BAR}2' ])
- paths = map(str, tgt)
- paths.sort()
- expect = map(os.path.normpath, [ 'iii/jjj1', 'iii/jjj2' ])
- assert paths == expect, paths
- for tnode in tgt:
- assert tnode.builder == InstallBuilder
-
- exc_caught = None
- try:
- tgt = env.Install('export', 'export')
- except SCons.Errors.UserError, e:
- exc_caught = 1
- assert exc_caught, "UserError should be thrown when Install() target is not a file."
- match = str(e) == "Source `export' of Install() is not a file. Install() source must be one or more files."
- assert match, e
-
- exc_caught = None
- try:
- tgt = env.Install('export', ['export', 'build/foo1'])
- except SCons.Errors.UserError, e:
- exc_caught = 1
- assert exc_caught, "UserError should be thrown when Install() target containins non-files."
- match = str(e) == "Source `['export', 'build/foo1']' of Install() contains one or more non-files. Install() source must be one or more files."
- assert match, e
-
- exc_caught = None
- try:
- tgt = env.Install('export/foo1', 'build/foo1')
- except SCons.Errors.UserError, e:
- exc_caught = 1
- assert exc_caught, "UserError should be thrown reversing the order of Install() targets."
- match = str(e) == "Target `export/foo1' of Install() is a file, but should be a directory. Perhaps you have the Install() arguments backwards?"
- assert match, e
-
- tgt = env.InstallAs(target=string.split('foo1 foo2'),
- source=string.split('bar1 bar2'))
- assert len(tgt) == 2, len(tgt)
- paths = map(lambda x: str(x.sources[0]), tgt)
- paths.sort()
- expect = map(os.path.normpath, [ 'bar1', 'bar2' ])
- assert paths == expect, paths
- for tnode in tgt:
- assert tnode.builder == InstallBuilder
-
- tgt = env.InstallAs(target='${FOO}.t', source='${BAR}.s')
- assert tgt.path == 'iii.t'
- assert tgt.sources[0].path == 'jjj.s'
- assert tgt.builder == InstallBuilder
-
def test_ReservedVariables(self):
"""Test generation of warnings when reserved variable names
are set in an environment."""
test_it('foo.bar')
test_it('foo-bar')
- def test_Replace(self):
- """Test replacing construction variables in an Environment
-
- After creation of the Environment, of course.
- """
- env1 = Environment(AAA = 'a', BBB = 'b')
- env1.Replace(BBB = 'bbb', CCC = 'ccc')
+ def test_autogenerate(dict):
+ """Test autogenerating variables in a dictionary."""
+
+ def RDirs(pathlist):
+ return SCons.Node.FS.default_fs.Rsearchall(pathlist,
+ clazz=SCons.Node.FS.Dir,
+ must_exist=0,
+ cwd=SCons.Node.FS.default_fs.Dir('xx'))
+
+ env = Environment(LIBS = [ 'foo', 'bar', 'baz' ],
+ LIBLINKPREFIX = 'foo',
+ LIBLINKSUFFIX = 'bar',
+ RDirs=RDirs)
+ flags = env.subst_list('$_LIBFLAGS', 1)[0]
+ assert len(flags) == 3, flags
+ assert flags[0] == 'foofoobar', \
+ flags[0]
+ assert flags[1] == 'foobarbar', \
+ flags[1]
+ assert flags[2] == 'foobazbar', \
+ flags[2]
+
+ blat = SCons.Node.FS.default_fs.Dir('blat')
+
+ env = Environment(CPPPATH = [ 'foo', '$FOO/bar', blat ],
+ INCPREFIX = 'foo ',
+ INCSUFFIX = 'bar',
+ FOO = 'baz',
+ RDirs=RDirs)
+ flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
+ assert len(flags) == 8, flags
+ assert flags[0] == '$(', \
+ flags[0]
+ assert flags[1] == os.path.normpath('foo'), \
+ flags[1]
+ assert flags[2] == os.path.normpath('xx/foobar'), \
+ flags[2]
+ assert flags[3] == os.path.normpath('foo'), \
+ flags[3]
+ assert flags[4] == os.path.normpath('xx/baz/barbar'), \
+ flags[4]
+ assert flags[5] == os.path.normpath('foo'), \
+ flags[5]
+ assert flags[6] == os.path.normpath('blatbar'), \
+ flags[6]
+ assert flags[7] == '$)', \
+ flags[7]
+
+ env = Environment(F77PATH = [ 'foo', '$FOO/bar', blat ],
+ INCPREFIX = 'foo ',
+ INCSUFFIX = 'bar',
+ FOO = 'baz',
+ RDirs=RDirs)
+ flags = env.subst_list('$_F77INCFLAGS', 1)[0]
+ assert len(flags) == 8, flags
+ assert flags[0] == '$(', \
+ flags[0]
+ assert flags[1] == os.path.normpath('foo'), \
+ flags[1]
+ assert flags[2] == os.path.normpath('xx/foobar'), \
+ flags[2]
+ assert flags[3] == os.path.normpath('foo'), \
+ flags[3]
+ assert flags[4] == os.path.normpath('xx/baz/barbar'), \
+ flags[4]
+ assert flags[5] == os.path.normpath('foo'), \
+ flags[5]
+ assert flags[6] == os.path.normpath('blatbar'), \
+ flags[6]
+ assert flags[7] == '$)', \
+ flags[7]
+
+ env = Environment(CPPPATH = '', F77PATH = '', LIBPATH = '',
+ RDirs=RDirs)
+ assert len(env.subst_list('$_CPPINCFLAGS')[0]) == 0
+ assert len(env.subst_list('$_F77INCFLAGS')[0]) == 0
+ assert len(env.subst_list('$_LIBDIRFLAGS')[0]) == 0
+
+ SCons.Node.FS.default_fs.Repository('/rep1')
+ SCons.Node.FS.default_fs.Repository('/rep2')
+ env = Environment(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat],
+ INCPREFIX = '-I ',
+ INCSUFFIX = 'XXX',
+ FOO = 'baz',
+ RDirs=RDirs)
+ flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
+ assert flags[0] == '$(', \
+ flags[0]
+ assert flags[1] == '-I', \
+ flags[1]
+ assert flags[2] == os.path.normpath('xx/fooXXX'), \
+ flags[2]
+ assert flags[3] == '-I', \
+ flags[3]
+ assert flags[4] == os.path.normpath('/rep1/xx/fooXXX'), \
+ flags[4]
+ assert flags[5] == '-I', \
+ flags[5]
+ assert flags[6] == os.path.normpath('/rep2/xx/fooXXX'), \
+ flags[6]
+ assert flags[7] == '-I', \
+ flags[7]
+ assert flags[8] == os.path.normpath('/a/bXXX'), \
+ flags[8]
+ assert flags[9] == '-I', \
+ flags[9]
+ assert flags[10] == os.path.normpath('xx/baz/barXXX'), \
+ flags[10]
+ assert flags[11] == '-I', \
+ flags[11]
+ assert flags[12] == os.path.normpath('/rep1/xx/baz/barXXX'), \
+ flags[12]
+ assert flags[13] == '-I', \
+ flags[13]
+ assert flags[14] == os.path.normpath('/rep2/xx/baz/barXXX'), \
+ flags[14]
+ assert flags[15] == '-I', \
+ flags[15]
+ assert flags[16] == os.path.normpath('blatXXX'), \
+ flags[16]
+ assert flags[17] == '$)', \
+ flags[17]
+
+ def test_platform(self):
+ """Test specifying a platform callable when instantiating."""
+ class platform:
+ def __str__(self): return "TestPlatform"
+ def __call__(self, env): env['XYZZY'] = 777
+
+ def tool(env):
+ env['SET_TOOL'] = 'initialized'
+ assert env['PLATFORM'] == "TestPlatform"
+
+ env = Environment(platform = platform(), tools = [tool])
+ assert env['XYZZY'] == 777, env
+ assert env['PLATFORM'] == "TestPlatform"
+ assert env['SET_TOOL'] == "initialized"
+
+ def test_Default_PLATFORM(self):
+ """Test overriding the default PLATFORM variable"""
+ class platform:
+ def __str__(self): return "DefaultTestPlatform"
+ def __call__(self, env): env['XYZZY'] = 888
+
+ def tool(env):
+ env['SET_TOOL'] = 'abcde'
+ assert env['PLATFORM'] == "DefaultTestPlatform"
+
+ import SCons.Defaults
+ save = SCons.Defaults.ConstructionEnvironment.copy()
+ try:
+ import SCons.Defaults
+ SCons.Defaults.ConstructionEnvironment.update({
+ 'PLATFORM' : platform(),
+ })
+ env = Environment(tools = [tool])
+ assert env['XYZZY'] == 888, env
+ assert env['PLATFORM'] == "DefaultTestPlatform"
+ assert env['SET_TOOL'] == "abcde"
+ finally:
+ SCons.Defaults.ConstructionEnvironment = save
+
+ def test_tools(self):
+ """Test specifying a tool callable when instantiating."""
+ def t1(env):
+ env['TOOL1'] = 111
+ def t2(env):
+ env['TOOL2'] = 222
+ def t3(env):
+ env['AAA'] = env['XYZ']
+ def t4(env):
+ env['TOOL4'] = 444
+ env = Environment(tools = [t1, t2, t3], XYZ = 'aaa')
+ assert env['TOOL1'] == 111, env['TOOL1']
+ assert env['TOOL2'] == 222, env
+ assert env['AAA'] == 'aaa', env
+ t4(env)
+ assert env['TOOL4'] == 444, env
+
+ def test_Default_TOOLS(self):
+ """Test overriding the default TOOLS variable"""
+ def t5(env):
+ env['TOOL5'] = 555
+ def t6(env):
+ env['TOOL6'] = 666
+ def t7(env):
+ env['BBB'] = env['XYZ']
+ def t8(env):
+ env['TOOL8'] = 888
+
+ import SCons.Defaults
+ save = SCons.Defaults.ConstructionEnvironment.copy()
+ try:
+ SCons.Defaults.ConstructionEnvironment.update({
+ 'TOOLS' : [t5, t6, t7],
+ })
+ env = Environment(XYZ = 'bbb')
+ assert env['TOOL5'] == 555, env['TOOL5']
+ assert env['TOOL6'] == 666, env
+ assert env['BBB'] == 'bbb', env
+ t8(env)
+ assert env['TOOL8'] == 888, env
+ finally:
+ SCons.Defaults.ConstructionEnvironment = save
+
+ def test_concat(self):
+ "Test _concat()"
+ e1 = Environment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b'])
+ s = e1.subst
+ assert s("${_concat('', '', '', __env__)}") == ''
+ assert s("${_concat('', [], '', __env__)}") == ''
+ assert s("${_concat(PRE, '', SUF, __env__)}") == ''
+ assert s("${_concat(PRE, STR, SUF, __env__)}") == 'prea bsuf'
+ assert s("${_concat(PRE, LIST, SUF, __env__)}") == 'preasuf prebsuf'
- env2 = Environment(AAA = 'a', BBB = 'bbb', CCC = 'ccc')
- assert env1 == env2, diff_env(env1, env2)
- env3 = Environment(BUILDERS = {'b1' : 1})
- assert hasattr(env3, 'b1'), "b1 was not set"
- env3.Replace(BUILDERS = {'b2' : 2})
- assert not hasattr(env3, 'b1'), "b1 was not cleared"
- assert hasattr(env3, 'b2'), "b2 was not set"
def test_Append(self):
"""Test appending to construction variables in an Environment
assert hasattr(env4, 'z1')
assert hasattr(env4, 'z2')
- def test_Prepend(self):
- """Test prepending to construction variables in an Environment
- """
- import UserList
- UL = UserList.UserList
- env1 = Environment(AAA = 'a', BBB = 'b', CCC = 'c', DDD = 'd',
- EEE = ['e'], FFF = ['f'], GGG = ['g'], HHH = ['h'],
- III = UL(['i']), JJJ = UL(['j']),
- KKK = UL(['k']), LLL = UL(['l']))
- env1.Prepend(BBB = 'B', CCC = ['C'], DDD = UL(['D']),
- FFF = 'F', GGG = ['G'], HHH = UL(['H']),
- JJJ = 'J', KKK = ['K'], LLL = UL(['L']))
- env2 = Environment(AAA = 'a', BBB = 'Bb',
- CCC = ['C', 'c'], DDD = UL(['D', 'd']),
- EEE = ['e'], FFF = ['F', 'f'],
- GGG = ['G', 'g'], HHH = UL(['H', 'h']),
- III = UL(['i']), JJJ = UL(['J', 'j']),
- KKK = UL(['K', 'k']), LLL = UL(['L', 'l']))
- assert env1 == env2, diff_env(env1, env2)
-
- env3 = Environment(X = {'x1' : 7})
- env3.Prepend(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
- assert env3['X'] == {'x1': 8, 'x2' : 9}, env3['X']
- assert env3['Y'] == {'y1': 10}, env3['Y']
-
- env4 = Environment(BUILDERS = {'z1' : 11})
- env4.Prepend(BUILDERS = {'z2' : 12})
- assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
- assert hasattr(env4, 'z1')
- assert hasattr(env4, 'z2')
-
- def test_PrependENVPath(self):
- """Test prepending to an ENV path."""
- env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
- MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
- # have to include the pathsep here so that the test will work on UNIX too.
- env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
- env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
- env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
- env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
- assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
- assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
-
- def test_AppendENVPath(self):
- """Test appending to an ENV path."""
- env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
- MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
- # have to include the pathsep here so that the test will work on UNIX too.
- env1.AppendENVPath('PATH',r'C:\dir\num\two', sep = ';')
- env1.AppendENVPath('PATH',r'C:\dir\num\three', sep = ';')
- env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';')
- env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';')
- assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
- assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
-
- def test_AppendENVPath(self):
- """Test prepending to an ENV path."""
- env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
- MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
- # have to include the pathsep here so that the test will work on UNIX too.
- env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
- env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
- env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
- env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
- assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
- assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
-
- def test_AppendENVPath(self):
- """Test appending to an ENV path."""
+ def test_AppendENVPath(self):
+ """Test appending to an ENV path."""
env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
# have to include the pathsep here so that the test will work on UNIX too.
assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
- def test_Depends(self):
- """Test the explicit Depends method."""
- env = Environment(FOO = 'xxx', BAR='yyy')
- t = env.Depends(target='EnvironmentTest.py', dependency='Environment.py')
- assert t.__class__.__name__ == 'File'
- assert t.path == 'EnvironmentTest.py'
- assert len(t.depends) == 1
- d = t.depends[0]
- assert d.__class__.__name__ == 'File'
- assert d.path == 'Environment.py'
-
- t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')
- assert t.__class__.__name__ == 'File'
- assert t.path == 'xxx.py'
- assert len(t.depends) == 1
- d = t.depends[0]
- assert d.__class__.__name__ == 'File'
- assert d.path == 'yyy.py'
-
- def test_Ignore(self):
- """Test the explicit Ignore method."""
- env = Environment(FOO='yyy', BAR='zzz')
- t = env.Ignore(target='targ.py', dependency='dep.py')
- assert t.__class__.__name__ == 'File'
- assert t.path == 'targ.py'
- assert len(t.ignore) == 1
- i = t.ignore[0]
- assert i.__class__.__name__ == 'File'
- assert i.path == 'dep.py'
- t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')
- assert t.__class__.__name__ == 'File'
- assert t.path == 'yyyzzz'
- assert len(t.ignore) == 1
- i = t.ignore[0]
- assert i.__class__.__name__ == 'File'
- assert i.path == 'zzzyyy'
-
- def test_AlwaysBuild(self):
- """Test the AlwaysBuild() method"""
- env = Environment(FOO='fff', BAR='bbb')
- t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR')
- assert t[0].__class__.__name__ == 'File'
- assert t[0].path == 'a'
- assert t[0].always_build
- assert t[1].__class__.__name__ == 'File'
- assert t[1].path == 'bfff'
- assert t[1].always_build
- assert t[2].__class__.__name__ == 'File'
- assert t[2].path == 'c'
- assert t[2].always_build
- assert t[3].__class__.__name__ == 'File'
- assert t[3].path == 'd'
- assert t[3].always_build
- assert t[4].__class__.__name__ == 'File'
- assert t[4].path == 'bbb'
- assert t[4].always_build
-
- def test_Precious(self):
- """Test the Precious() method."""
- env = Environment(FOO='ggg', BAR='hhh')
- t = env.Precious('a', '${BAR}b', ['c', 'd'], '$FOO')
- assert t[0].__class__.__name__ == 'File'
- assert t[0].path == 'a'
- assert t[0].precious
- assert t[1].__class__.__name__ == 'File'
- assert t[1].path == 'hhhb'
- assert t[1].precious
- assert t[2].__class__.__name__ == 'File'
- assert t[2].path == 'c'
- assert t[2].precious
- assert t[3].__class__.__name__ == 'File'
- assert t[3].path == 'd'
- assert t[3].precious
- assert t[4].__class__.__name__ == 'File'
- assert t[4].path == 'ggg'
- assert t[4].precious
-
- def test_Command(self):
- """Test the Command() method."""
- env = Environment()
- t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'],
- action='buildfoo $target $source')
- assert not t.builder is None
- assert t.builder.action.__class__.__name__ == 'CommandAction'
- assert t.builder.action.cmd_list == 'buildfoo $target $source'
- assert 'foo1.in' in map(lambda x: x.path, t.sources)
- assert 'foo2.in' in map(lambda x: x.path, t.sources)
-
- sub = SCons.Node.FS.default_fs.Dir('sub')
- t = env.Command(target='bar.out', source='sub',
- action='buildbar $target $source')
- assert 'sub' in map(lambda x: x.path, t.sources)
-
- def testFunc(env, target, source):
- assert str(target[0]) == 'foo.out'
- assert 'foo1.in' in map(str, source) and 'foo2.in' in map(str, source), map(str, source)
- return 0
- t = env.Command(target='foo.out', source=['foo1.in','foo2.in'],
- action=testFunc)
- assert not t.builder is None
- assert t.builder.action.__class__.__name__ == 'FunctionAction'
- t.build()
- assert 'foo1.in' in map(lambda x: x.path, t.sources)
- assert 'foo2.in' in map(lambda x: x.path, t.sources)
-
- def test_SourceCode(self):
- """Test the SourceCode() method."""
- env = Environment(FOO='mmm', BAR='nnn')
- e = env.SourceCode('foo', None)
- assert e.path == 'foo'
- s = e.src_builder()
- assert s is None, s
-
- b = Builder()
- e = env.SourceCode(e, b)
- assert e.path == 'foo'
- s = e.src_builder()
- assert s is b, s
-
- e = env.SourceCode('$BAR$FOO', None)
- assert e.path == 'nnnmmm'
- s = e.src_builder()
- assert s is None, s
-
- def test_SideEffect(self):
- """Test the SideEffect() method"""
- env = Environment(LIB='lll', FOO='fff', BAR='bbb')
-
- foo = env.Object('foo.obj', 'foo.cpp')
- bar = env.Object('bar.obj', 'bar.cpp')
- s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj'])
- assert s.path == 'mylib.pdb'
- assert s.side_effect
- assert foo.side_effects == [s]
- assert bar.side_effects == [s]
- assert s.depends_on([bar])
- assert s.depends_on([foo])
-
- fff = env.Object('fff.obj', 'fff.cpp')
- bbb = env.Object('bbb.obj', 'bbb.cpp')
- s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj'])
- assert s.path == 'mylll.pdb'
- assert s.side_effect
- assert fff.side_effects == [s], fff.side_effects
- assert bbb.side_effects == [s], bbb.side_effects
- assert s.depends_on([bbb])
- assert s.depends_on([fff])
+ def test_Copy(self):
+ """Test construction Environment copying
- def test_subst(self):
- """Test substituting construction variables within strings
-
- Check various combinations, including recursive expansion
- of variables into other variables.
+ Update the copy independently afterwards and check that
+ the original remains intact (that is, no dangling
+ references point to objects in the copied environment).
+ Copy the original with some construction variable
+ updates and check that the original remains intact
+ and the copy has the updated values.
"""
- env = Environment(AAA = 'a', BBB = 'b')
- mystr = env.subst("$AAA ${AAA}A $BBBB $BBB")
- assert mystr == "a aA b", str
-
- # Changed the tests below to reflect a bug fix in
- # subst()
- env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
- mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
- assert mystr == "b bA bB b", str
- env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
- mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
- assert mystr == "c cA cB c", str
-
- env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ])
- lst = env.subst_list([ "$AAA", "B $CCC" ])
- assert lst == [ [ "a", "b" ], [ "c", "B a", "b" ], [ "c" ] ], lst
-
- class DummyNode:
- def __init__(self, name):
- self.name = name
- def __str__(self):
- return self.name
- def rfile(self):
- return self
- def get_subst_proxy(self):
- return self
-
- # Test callables in the Environment
- def foo(target, source, env, for_signature):
- assert str(target) == 't', target
- assert str(source) == 's', source
- return env["FOO"]
-
- env = Environment(BAR=foo, FOO='baz')
-
- subst = env.subst('test $BAR', target=DummyNode('t'), source=DummyNode('s'))
- assert subst == 'test baz', subst
-
- lst = env.subst_list('test $BAR', target=DummyNode('t'), source=DummyNode('s'))
- assert lst[0][0] == 'test', lst[0][0]
- assert lst[0][1] == 'baz', lst[0][1]
-
- def test_autogenerate(dict):
- """Test autogenerating variables in a dictionary."""
-
- def RDirs(pathlist):
- return SCons.Node.FS.default_fs.Rsearchall(pathlist,
- clazz=SCons.Node.FS.Dir,
- must_exist=0,
- cwd=SCons.Node.FS.default_fs.Dir('xx'))
-
- env = Environment(LIBS = [ 'foo', 'bar', 'baz' ],
- LIBLINKPREFIX = 'foo',
- LIBLINKSUFFIX = 'bar',
- RDirs=RDirs)
- flags = env.subst_list('$_LIBFLAGS', 1)[0]
- assert len(flags) == 3, flags
- assert flags[0] == 'foofoobar', \
- flags[0]
- assert flags[1] == 'foobarbar', \
- flags[1]
- assert flags[2] == 'foobazbar', \
- flags[2]
-
- blat = SCons.Node.FS.default_fs.Dir('blat')
+ env1 = Environment(XXX = 'x', YYY = 'y')
+ env2 = env1.Copy()
+ env1copy = env1.Copy()
+ env2.Replace(YYY = 'yyy')
+ assert env1 != env2
+ assert env1 == env1copy
- env = Environment(CPPPATH = [ 'foo', '$FOO/bar', blat ],
- INCPREFIX = 'foo ',
- INCSUFFIX = 'bar',
- FOO = 'baz',
- RDirs=RDirs)
- flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
- assert len(flags) == 8, flags
- assert flags[0] == '$(', \
- flags[0]
- assert flags[1] == os.path.normpath('foo'), \
- flags[1]
- assert flags[2] == os.path.normpath('xx/foobar'), \
- flags[2]
- assert flags[3] == os.path.normpath('foo'), \
- flags[3]
- assert flags[4] == os.path.normpath('xx/baz/barbar'), \
- flags[4]
- assert flags[5] == os.path.normpath('foo'), \
- flags[5]
- assert flags[6] == os.path.normpath('blatbar'), \
- flags[6]
- assert flags[7] == '$)', \
- flags[7]
+ env3 = env1.Copy(XXX = 'x3', ZZZ = 'z3')
+ assert env3.Dictionary('XXX') == 'x3'
+ assert env3.Dictionary('YYY') == 'y'
+ assert env3.Dictionary('ZZZ') == 'z3'
+ assert env1 == env1copy
- env = Environment(F77PATH = [ 'foo', '$FOO/bar', blat ],
- INCPREFIX = 'foo ',
- INCSUFFIX = 'bar',
- FOO = 'baz',
- RDirs=RDirs)
- flags = env.subst_list('$_F77INCFLAGS', 1)[0]
- assert len(flags) == 8, flags
- assert flags[0] == '$(', \
- flags[0]
- assert flags[1] == os.path.normpath('foo'), \
- flags[1]
- assert flags[2] == os.path.normpath('xx/foobar'), \
- flags[2]
- assert flags[3] == os.path.normpath('foo'), \
- flags[3]
- assert flags[4] == os.path.normpath('xx/baz/barbar'), \
- flags[4]
- assert flags[5] == os.path.normpath('foo'), \
- flags[5]
- assert flags[6] == os.path.normpath('blatbar'), \
- flags[6]
- assert flags[7] == '$)', \
- flags[7]
+ # Ensure that lists and dictionaries are
+ # deep copied, but not instances.
+ class TestA:
+ pass
+ env1 = Environment(XXX=TestA(), YYY = [ 1, 2, 3 ],
+ ZZZ = { 1:2, 3:4 })
+ env2=env1.Copy()
+ env2.Dictionary('YYY').append(4)
+ env2.Dictionary('ZZZ')[5] = 6
+ assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
+ assert 4 in env2.Dictionary('YYY')
+ assert not 4 in env1.Dictionary('YYY')
+ assert env2.Dictionary('ZZZ').has_key(5)
+ assert not env1.Dictionary('ZZZ').has_key(5)
- env = Environment(CPPPATH = '', F77PATH = '', LIBPATH = '',
- RDirs=RDirs)
- assert len(env.subst_list('$_CPPINCFLAGS')[0]) == 0
- assert len(env.subst_list('$_F77INCFLAGS')[0]) == 0
- assert len(env.subst_list('$_LIBDIRFLAGS')[0]) == 0
+ #
+ env1 = Environment(BUILDERS = {'b1' : 1})
+ assert hasattr(env1, 'b1'), "env1.b1 was not set"
+ assert env1.b1.env == env1, "b1.env doesn't point to env1"
+ env2 = env1.Copy(BUILDERS = {'b2' : 2})
+ assert hasattr(env1, 'b1'), "b1 was mistakenly cleared from env1"
+ assert env1.b1.env == env1, "b1.env was changed"
+ assert not hasattr(env2, 'b1'), "b1 was not cleared from env2"
+ assert hasattr(env2, 'b2'), "env2.b2 was not set"
+ assert env2.b2.env == env2, "b2.env doesn't point to env2"
- SCons.Node.FS.default_fs.Repository('/rep1')
- SCons.Node.FS.default_fs.Repository('/rep2')
- env = Environment(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat],
- INCPREFIX = '-I ',
- INCSUFFIX = 'XXX',
- FOO = 'baz',
- RDirs=RDirs)
- flags = env.subst_list('$_CPPINCFLAGS', 1)[0]
- assert flags[0] == '$(', \
- flags[0]
- assert flags[1] == '-I', \
- flags[1]
- assert flags[2] == os.path.normpath('xx/fooXXX'), \
- flags[2]
- assert flags[3] == '-I', \
- flags[3]
- assert flags[4] == os.path.normpath('/rep1/xx/fooXXX'), \
- flags[4]
- assert flags[5] == '-I', \
- flags[5]
- assert flags[6] == os.path.normpath('/rep2/xx/fooXXX'), \
- flags[6]
- assert flags[7] == '-I', \
- flags[7]
- assert flags[8] == os.path.normpath('/a/bXXX'), \
- flags[8]
- assert flags[9] == '-I', \
- flags[9]
- assert flags[10] == os.path.normpath('xx/baz/barXXX'), \
- flags[10]
- assert flags[11] == '-I', \
- flags[11]
- assert flags[12] == os.path.normpath('/rep1/xx/baz/barXXX'), \
- flags[12]
- assert flags[13] == '-I', \
- flags[13]
- assert flags[14] == os.path.normpath('/rep2/xx/baz/barXXX'), \
- flags[14]
- assert flags[15] == '-I', \
- flags[15]
- assert flags[16] == os.path.normpath('blatXXX'), \
- flags[16]
- assert flags[17] == '$)', \
- flags[17]
+ # Ensure that specifying new tools in a copied environment
+ # works.
+ def foo(env): env['FOO'] = 1
+ def bar(env): env['BAR'] = 2
+ def baz(env): env['BAZ'] = 3
+ env1 = Environment(tools=[foo])
+ env2 = env1.Copy()
+ env3 = env1.Copy(tools=[bar, baz])
+
+ assert env1.get('FOO') is 1
+ assert env1.get('BAR') is None
+ assert env1.get('BAZ') is None
+ assert env2.get('FOO') is 1
+ assert env2.get('BAR') is None
+ assert env2.get('BAZ') is None
+ assert env3.get('FOO') is 1
+ assert env3.get('BAR') is 2
+ assert env3.get('BAZ') is 3
def test_Detect(self):
"""Test Detect()ing tools"""
x = env.Detect('xxx.exe')
assert x is None, x
- def test_platform(self):
- """Test specifying a platform callable when instantiating."""
- class platform:
- def __str__(self): return "TestPlatform"
- def __call__(self, env): env['XYZZY'] = 777
+ def test_Dictionary(self):
+ """Test retrieval of known construction variables
- def tool(env):
- env['SET_TOOL'] = 'initialized'
- assert env['PLATFORM'] == "TestPlatform"
+ Fetch them from the Dictionary and check for well-known
+ defaults that get inserted.
+ """
+ env = Environment(XXX = 'x', YYY = 'y', ZZZ = 'z')
+ assert env.Dictionary('XXX') == 'x'
+ assert env.Dictionary('YYY') == 'y'
+ assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z']
+ xxx, zzz = env.Dictionary('XXX', 'ZZZ')
+ assert xxx == 'x'
+ assert zzz == 'z'
+ assert env.Dictionary().has_key('BUILDERS')
+ assert env.Dictionary().has_key('CC')
+ assert env.Dictionary().has_key('CCFLAGS')
+ assert env.Dictionary().has_key('ENV')
- env = Environment(platform = platform(), tools = [tool])
- assert env['XYZZY'] == 777, env
- assert env['PLATFORM'] == "TestPlatform"
- assert env['SET_TOOL'] == "initialized"
+ assert env['XXX'] == 'x'
+ env['XXX'] = 'foo'
+ assert env.Dictionary('XXX') == 'foo'
+ del env['XXX']
+ assert not env.Dictionary().has_key('XXX')
- def test_Default_PLATFORM(self):
- """Test overriding the default PLATFORM variable"""
- class platform:
- def __str__(self): return "DefaultTestPlatform"
- def __call__(self, env): env['XYZZY'] = 888
+ def test_FindIxes(self):
+ "Test FindIxes()"
+ env = Environment(LIBPREFIX='lib',
+ LIBSUFFIX='.a',
+ SHLIBPREFIX='lib',
+ SHLIBSUFFIX='.so',
+ PREFIX='pre',
+ SUFFIX='post')
- def tool(env):
- env['SET_TOOL'] = 'abcde'
- assert env['PLATFORM'] == "DefaultTestPlatform"
+ paths = [os.path.join('dir', 'libfoo.a'),
+ os.path.join('dir', 'libfoo.so')]
- import SCons.Defaults
- save = SCons.Defaults.ConstructionEnvironment.copy()
- try:
- import SCons.Defaults
- SCons.Defaults.ConstructionEnvironment.update({
- 'PLATFORM' : platform(),
- })
- env = Environment(tools = [tool])
- assert env['XYZZY'] == 888, env
- assert env['PLATFORM'] == "DefaultTestPlatform"
- assert env['SET_TOOL'] == "abcde"
- finally:
- SCons.Defaults.ConstructionEnvironment = save
+ assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
+ assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+ assert None == env.FindIxes(paths, 'PREFIX', 'POST')
- def test_tools(self):
- """Test specifying a tool callable when instantiating."""
- def t1(env):
- env['TOOL1'] = 111
- def t2(env):
- env['TOOL2'] = 222
- def t3(env):
- env['AAA'] = env['XYZ']
- def t4(env):
- env['TOOL4'] = 444
- env = Environment(tools = [t1, t2, t3], XYZ = 'aaa')
- assert env['TOOL1'] == 111, env['TOOL1']
- assert env['TOOL2'] == 222, env
- assert env['AAA'] == 'aaa', env
- t4(env)
- assert env['TOOL4'] == 444, env
-
- def test_Default_TOOLS(self):
- """Test overriding the default TOOLS variable"""
- def t5(env):
- env['TOOL5'] = 555
- def t6(env):
- env['TOOL6'] = 666
- def t7(env):
- env['BBB'] = env['XYZ']
- def t8(env):
- env['TOOL8'] = 888
+ paths = ['libfoo.a', 'prefoopost']
- import SCons.Defaults
- save = SCons.Defaults.ConstructionEnvironment.copy()
- try:
- SCons.Defaults.ConstructionEnvironment.update({
- 'TOOLS' : [t5, t6, t7],
- })
- env = Environment(XYZ = 'bbb')
- assert env['TOOL5'] == 555, env['TOOL5']
- assert env['TOOL6'] == 666, env
- assert env['BBB'] == 'bbb', env
- t8(env)
- assert env['TOOL8'] == 888, env
- finally:
- SCons.Defaults.ConstructionEnvironment = save
+ assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
+ assert None == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+ assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX')
- def test_get(self):
- """Test the get() method."""
- env = Environment(aaa = 'AAA')
+ def test_Override(self):
+ "Test overriding construction variables"
+ env = Environment(ONE=1, TWO=2)
+ assert env['ONE'] == 1
+ assert env['TWO'] == 2
+ env2 = env.Override({'TWO':'10'})
+ assert env2['ONE'] == 1
+ assert env2['TWO'] == '10'
+ assert env['TWO'] == 2
+ env2.Replace(ONE = "won")
+ assert env2['ONE'] == "won"
+ assert env['ONE'] == 1
- x = env.get('aaa')
- assert x == 'AAA', x
- x = env.get('aaa', 'XXX')
- assert x == 'AAA', x
- x = env.get('bbb')
- assert x is None, x
- x = env.get('bbb', 'XXX')
- assert x == 'XXX', x
+ def test_Prepend(self):
+ """Test prepending to construction variables in an Environment
+ """
+ import UserList
+ UL = UserList.UserList
+ env1 = Environment(AAA = 'a', BBB = 'b', CCC = 'c', DDD = 'd',
+ EEE = ['e'], FFF = ['f'], GGG = ['g'], HHH = ['h'],
+ III = UL(['i']), JJJ = UL(['j']),
+ KKK = UL(['k']), LLL = UL(['l']))
+ env1.Prepend(BBB = 'B', CCC = ['C'], DDD = UL(['D']),
+ FFF = 'F', GGG = ['G'], HHH = UL(['H']),
+ JJJ = 'J', KKK = ['K'], LLL = UL(['L']))
+ env2 = Environment(AAA = 'a', BBB = 'Bb',
+ CCC = ['C', 'c'], DDD = UL(['D', 'd']),
+ EEE = ['e'], FFF = ['F', 'f'],
+ GGG = ['G', 'g'], HHH = UL(['H', 'h']),
+ III = UL(['i']), JJJ = UL(['J', 'j']),
+ KKK = UL(['K', 'k']), LLL = UL(['L', 'l']))
+ assert env1 == env2, diff_env(env1, env2)
- def test_concat(self):
- "Test _concat()"
- e1 = Environment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b'])
- s = e1.subst
- assert s("${_concat('', '', '', __env__)}") == ''
- assert s("${_concat('', [], '', __env__)}") == ''
- assert s("${_concat(PRE, '', SUF, __env__)}") == ''
- assert s("${_concat(PRE, STR, SUF, __env__)}") == 'prea bsuf'
- assert s("${_concat(PRE, LIST, SUF, __env__)}") == 'preasuf prebsuf'
+ env3 = Environment(X = {'x1' : 7})
+ env3.Prepend(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
+ assert env3['X'] == {'x1': 8, 'x2' : 9}, env3['X']
+ assert env3['Y'] == {'y1': 10}, env3['Y']
+
+ env4 = Environment(BUILDERS = {'z1' : 11})
+ env4.Prepend(BUILDERS = {'z2' : 12})
+ assert env4['BUILDERS'] == {'z1' : 11, 'z2' : 12}, env4['BUILDERS']
+ assert hasattr(env4, 'z1')
+ assert hasattr(env4, 'z2')
- def test_FindIxes(self):
- "Test FindIxes()"
- env = Environment(LIBPREFIX='lib',
- LIBSUFFIX='.a',
- SHLIBPREFIX='lib',
- SHLIBSUFFIX='.so',
- PREFIX='pre',
- SUFFIX='post')
+ def test_PrependENVPath(self):
+ """Test prepending to an ENV path."""
+ env1 = Environment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'},
+ MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'})
+ # have to include the pathsep here so that the test will work on UNIX too.
+ env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';')
+ env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
+ env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
+ env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
+ assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
+ assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
- paths = [os.path.join('dir', 'libfoo.a'),
- os.path.join('dir', 'libfoo.so')]
+ def test_Replace(self):
+ """Test replacing construction variables in an Environment
- assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
- assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
- assert None == env.FindIxes(paths, 'PREFIX', 'POST')
+ After creation of the Environment, of course.
+ """
+ env1 = Environment(AAA = 'a', BBB = 'b')
+ env1.Replace(BBB = 'bbb', CCC = 'ccc')
- paths = ['libfoo.a', 'prefoopost']
+ env2 = Environment(AAA = 'a', BBB = 'bbb', CCC = 'ccc')
+ assert env1 == env2, diff_env(env1, env2)
- assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX')
- assert None == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX')
- assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX')
+ env3 = Environment(BUILDERS = {'b1' : 1})
+ assert hasattr(env3, 'b1'), "b1 was not set"
+ env3.Replace(BUILDERS = {'b2' : 2})
+ assert not hasattr(env3, 'b1'), "b1 was not cleared"
+ assert hasattr(env3, 'b2'), "b2 was not set"
def test_ReplaceIxes(self):
"Test ReplaceIxes()"
'PREFIX', 'SUFFIX',
'LIBPREFIX', 'LIBSUFFIX')
+
+
+ def test_AlwaysBuild(self):
+ """Test the AlwaysBuild() method"""
+ env = Environment(FOO='fff', BAR='bbb')
+ t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR')
+ assert t[0].__class__.__name__ == 'File'
+ assert t[0].path == 'a'
+ assert t[0].always_build
+ assert t[1].__class__.__name__ == 'File'
+ assert t[1].path == 'bfff'
+ assert t[1].always_build
+ assert t[2].__class__.__name__ == 'File'
+ assert t[2].path == 'c'
+ assert t[2].always_build
+ assert t[3].__class__.__name__ == 'File'
+ assert t[3].path == 'd'
+ assert t[3].always_build
+ assert t[4].__class__.__name__ == 'File'
+ assert t[4].path == 'bbb'
+ assert t[4].always_build
+
+ def test_Command(self):
+ """Test the Command() method."""
+ env = Environment()
+ t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'],
+ action='buildfoo $target $source')
+ assert not t.builder is None
+ assert t.builder.action.__class__.__name__ == 'CommandAction'
+ assert t.builder.action.cmd_list == 'buildfoo $target $source'
+ assert 'foo1.in' in map(lambda x: x.path, t.sources)
+ assert 'foo2.in' in map(lambda x: x.path, t.sources)
+
+ sub = SCons.Node.FS.default_fs.Dir('sub')
+ t = env.Command(target='bar.out', source='sub',
+ action='buildbar $target $source')
+ assert 'sub' in map(lambda x: x.path, t.sources)
+
+ def testFunc(env, target, source):
+ assert str(target[0]) == 'foo.out'
+ assert 'foo1.in' in map(str, source) and 'foo2.in' in map(str, source), map(str, source)
+ return 0
+ t = env.Command(target='foo.out', source=['foo1.in','foo2.in'],
+ action=testFunc)
+ assert not t.builder is None
+ assert t.builder.action.__class__.__name__ == 'FunctionAction'
+ t.build()
+ assert 'foo1.in' in map(lambda x: x.path, t.sources)
+ assert 'foo2.in' in map(lambda x: x.path, t.sources)
+
+ def test_Depends(self):
+ """Test the explicit Depends method."""
+ env = Environment(FOO = 'xxx', BAR='yyy')
+ t = env.Depends(target='EnvironmentTest.py', dependency='Environment.py')
+ assert t.__class__.__name__ == 'File'
+ assert t.path == 'EnvironmentTest.py'
+ assert len(t.depends) == 1
+ d = t.depends[0]
+ assert d.__class__.__name__ == 'File'
+ assert d.path == 'Environment.py'
+
+ t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')
+ assert t.__class__.__name__ == 'File'
+ assert t.path == 'xxx.py'
+ assert len(t.depends) == 1
+ d = t.depends[0]
+ assert d.__class__.__name__ == 'File'
+ assert d.path == 'yyy.py'
+
+ def test_Ignore(self):
+ """Test the explicit Ignore method."""
+ env = Environment(FOO='yyy', BAR='zzz')
+ t = env.Ignore(target='targ.py', dependency='dep.py')
+ assert t.__class__.__name__ == 'File'
+ assert t.path == 'targ.py'
+ assert len(t.ignore) == 1
+ i = t.ignore[0]
+ assert i.__class__.__name__ == 'File'
+ assert i.path == 'dep.py'
+ t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')
+ assert t.__class__.__name__ == 'File'
+ assert t.path == 'yyyzzz'
+ assert len(t.ignore) == 1
+ i = t.ignore[0]
+ assert i.__class__.__name__ == 'File'
+ assert i.path == 'zzzyyy'
+
+ def test_Install(self):
+ """Test Install and InstallAs methods"""
+ env = Environment(FOO='iii', BAR='jjj')
+
+ tgt = env.Install('export', [ 'build/foo1', 'build/foo2' ])
+ paths = map(str, tgt)
+ paths.sort()
+ expect = map(os.path.normpath, [ 'export/foo1', 'export/foo2' ])
+ assert paths == expect, paths
+ for tnode in tgt:
+ assert tnode.builder == InstallBuilder
+
+ tgt = env.Install('$FOO', [ 'build/${BAR}1', 'build/${BAR}2' ])
+ paths = map(str, tgt)
+ paths.sort()
+ expect = map(os.path.normpath, [ 'iii/jjj1', 'iii/jjj2' ])
+ assert paths == expect, paths
+ for tnode in tgt:
+ assert tnode.builder == InstallBuilder
+
+ exc_caught = None
+ try:
+ tgt = env.Install('export', 'export')
+ except SCons.Errors.UserError, e:
+ exc_caught = 1
+ assert exc_caught, "UserError should be thrown when Install() target is not a file."
+ match = str(e) == "Source `export' of Install() is not a file. Install() source must be one or more files."
+ assert match, e
+
+ exc_caught = None
+ try:
+ tgt = env.Install('export', ['export', 'build/foo1'])
+ except SCons.Errors.UserError, e:
+ exc_caught = 1
+ assert exc_caught, "UserError should be thrown when Install() target containins non-files."
+ match = str(e) == "Source `['export', 'build/foo1']' of Install() contains one or more non-files. Install() source must be one or more files."
+ assert match, e
+
+ exc_caught = None
+ try:
+ tgt = env.Install('export/foo1', 'build/foo1')
+ except SCons.Errors.UserError, e:
+ exc_caught = 1
+ assert exc_caught, "UserError should be thrown reversing the order of Install() targets."
+ match = str(e) == "Target `export/foo1' of Install() is a file, but should be a directory. Perhaps you have the Install() arguments backwards?"
+ assert match, e
+
+ tgt = env.InstallAs(target=string.split('foo1 foo2'),
+ source=string.split('bar1 bar2'))
+ assert len(tgt) == 2, len(tgt)
+ paths = map(lambda x: str(x.sources[0]), tgt)
+ paths.sort()
+ expect = map(os.path.normpath, [ 'bar1', 'bar2' ])
+ assert paths == expect, paths
+ for tnode in tgt:
+ assert tnode.builder == InstallBuilder
+
+ tgt = env.InstallAs(target='${FOO}.t', source='${BAR}.s')
+ assert tgt.path == 'iii.t'
+ assert tgt.sources[0].path == 'jjj.s'
+ assert tgt.builder == InstallBuilder
+
+ def test_Precious(self):
+ """Test the Precious() method."""
+ env = Environment(FOO='ggg', BAR='hhh')
+ t = env.Precious('a', '${BAR}b', ['c', 'd'], '$FOO')
+ assert t[0].__class__.__name__ == 'File'
+ assert t[0].path == 'a'
+ assert t[0].precious
+ assert t[1].__class__.__name__ == 'File'
+ assert t[1].path == 'hhhb'
+ assert t[1].precious
+ assert t[2].__class__.__name__ == 'File'
+ assert t[2].path == 'c'
+ assert t[2].precious
+ assert t[3].__class__.__name__ == 'File'
+ assert t[3].path == 'd'
+ assert t[3].precious
+ assert t[4].__class__.__name__ == 'File'
+ assert t[4].path == 'ggg'
+ assert t[4].precious
+
+ def test_SideEffect(self):
+ """Test the SideEffect() method"""
+ env = Environment(LIB='lll', FOO='fff', BAR='bbb')
+
+ foo = env.Object('foo.obj', 'foo.cpp')
+ bar = env.Object('bar.obj', 'bar.cpp')
+ s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj'])
+ assert s.path == 'mylib.pdb'
+ assert s.side_effect
+ assert foo.side_effects == [s]
+ assert bar.side_effects == [s]
+ assert s.depends_on([bar])
+ assert s.depends_on([foo])
+
+ fff = env.Object('fff.obj', 'fff.cpp')
+ bbb = env.Object('bbb.obj', 'bbb.cpp')
+ s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj'])
+ assert s.path == 'mylll.pdb'
+ assert s.side_effect
+ assert fff.side_effects == [s], fff.side_effects
+ assert bbb.side_effects == [s], bbb.side_effects
+ assert s.depends_on([bbb])
+ assert s.depends_on([fff])
+
+ def test_SourceCode(self):
+ """Test the SourceCode() method."""
+ env = Environment(FOO='mmm', BAR='nnn')
+ e = env.SourceCode('foo', None)
+ assert e.path == 'foo'
+ s = e.src_builder()
+ assert s is None, s
+
+ b = Builder()
+ e = env.SourceCode(e, b)
+ assert e.path == 'foo'
+ s = e.src_builder()
+ assert s is b, s
+
+ e = env.SourceCode('$BAR$FOO', None)
+ assert e.path == 'nnnmmm'
+ s = e.src_builder()
+ assert s is None, s
+
if __name__ == "__main__":
suite = unittest.makeSuite(EnvironmentTestCase, 'test_')