summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CHANGES.txt17
-rw-r--r--src/engine/SCons/Action.py6
-rw-r--r--src/engine/SCons/ActionTests.py7
-rw-r--r--src/engine/SCons/Defaults.py13
-rw-r--r--src/engine/SCons/Environment.py69
-rw-r--r--src/engine/SCons/EnvironmentTests.py136
-rw-r--r--src/engine/SCons/Script/SConscript.py53
7 files changed, 235 insertions, 66 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 1706903..1ab7499 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -80,13 +80,14 @@ RELEASE X.XX - XXX
- Support arbitrary expansion of construction variables within
file and directory arguments to Builder calls and Environment methods.
- - Add Environment-method versions of the following global
- functions: Action(), AddPostAction(), AddPreAction(), Builder(),
- BuildDir(), CacheDir(), Clean(), Default(), EnsurePythonVersion(),
- EnsureSConsVersion(), Environment(), Exit(), Export(), FindFile(),
- GetBuildPath(), GetOption(), Help(), Import(), Literal(),
- Local(), Platform(), Repository(), SConsignFile(), SetOption(),
- SourceSignatures(), Split(), TargetSignatures(), Tool().
+ - Add Environment-method versions of the following global functions:
+ Action(), AddPostAction(), AddPreAction(), Alias(), Builder(),
+ BuildDir(), CacheDir(), Clean(), Configure(), Default(),
+ EnsurePythonVersion(), EnsureSConsVersion(), Environment(),
+ Exit(), Export(), FindFile(), GetBuildPath(), GetOption(), Help(),
+ Import(), Literal(), Local(), Platform(), Repository(), Scanner(),
+ SConscriptChdir(), SConsignFile(), SetOption(), SourceSignatures(),
+ Split(), TargetSignatures(), Tool(), Value().
- Add the following global functions that correspond to the same-named
Environment methods: AlwaysBuild(), Command(), Depends(), Ignore(),
@@ -115,6 +116,8 @@ RELEASE X.XX - XXX
- Allow the Environment.WhereIs() method to take explicit path and
pathext arguments (like the underlying SCons.Util.WhereIs() function).
+ - Remove the long-obsolete {Get,Set}CommandHandler() functions.
+
From Clark McGrew:
- Generalize the action for .tex files so that it will decide whether
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py
index c9186a4..633bb06 100644
--- a/src/engine/SCons/Action.py
+++ b/src/engine/SCons/Action.py
@@ -53,12 +53,6 @@ def rfile(n):
except AttributeError:
return n
-def SetCommandHandler(func, escape = lambda x: x):
- raise SCons.Errors.UserError("SetCommandHandler() is no longer supported, use the SPAWN and ESCAPE construction variables.")
-
-def GetCommandHandler():
- raise SCons.Errors.UserError("GetCommandHandler() is no longer supported, use the SPAWN construction variable.")
-
def _actionAppend(act1, act2):
# This function knows how to slap two actions together.
# Mainly, it handles ListActions by concatenating into
diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py
index be14357..53aa00a 100644
--- a/src/engine/SCons/ActionTests.py
+++ b/src/engine/SCons/ActionTests.py
@@ -616,13 +616,6 @@ class CommandActionTestCase(unittest.TestCase):
def is_literal(self):
return 1
- try:
- SCons.Action.SetCommandHandler(func)
- except SCons.Errors.UserError:
- pass
- else:
- assert 0, "should have gotten user error"
-
a = SCons.Action.CommandAction(["xyzzy"])
a([], [], Environment(SPAWN = func))
assert t.executed == [ 'xyzzy' ]
diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py
index 798abb3..aaa1aba 100644
--- a/src/engine/SCons/Defaults.py
+++ b/src/engine/SCons/Defaults.py
@@ -46,8 +46,6 @@ import types
import SCons.Action
import SCons.Builder
import SCons.Environment
-import SCons.Node.Alias
-import SCons.Node.FS
import SCons.Scanner.C
import SCons.Scanner.Fortran
import SCons.Scanner.Prog
@@ -69,15 +67,6 @@ def DefaultEnvironment(*args, **kw):
_default_env._calc_module = SCons.Sig.default_module
return _default_env
-
-def alias_builder(env, target, source):
- pass
-
-Alias = SCons.Builder.Builder(action = alias_builder,
- target_factory = SCons.Node.Alias.default_ans.Alias,
- source_factory = SCons.Node.FS.default_fs.Entry,
- multi = 1)
-
CScan = SCons.Scanner.C.CScan()
FortranScan = SCons.Scanner.Fortran.FortranScan()
@@ -264,7 +253,7 @@ class NullCmdGenerator:
return self.cmd
ConstructionEnvironment = {
- 'BUILDERS' : { 'Alias' : Alias },
+ 'BUILDERS' : {},
'SCANNERS' : [CScan, FortranScan],
'PDFPREFIX' : '',
'PDFSUFFIX' : '.pdf',
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 36be2e4..f8ff6c3 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -48,7 +48,9 @@ import SCons.Builder
import SCons.Defaults
import SCons.Errors
import SCons.Node
+import SCons.Node.Alias
import SCons.Node.FS
+import SCons.Node.Python
import SCons.Platform
import SCons.Sig
import SCons.Sig.MD5
@@ -87,6 +89,14 @@ installAction = SCons.Action.Action(installFunc, installString)
InstallBuilder = SCons.Builder.Builder(action=installAction)
+def alias_builder(env, target, source):
+ pass
+
+AliasBuilder = SCons.Builder.Builder(action = alias_builder,
+ target_factory = SCons.Node.Alias.default_ans.Alias,
+ source_factory = SCons.Node.FS.default_fs.Entry,
+ multi = 1)
+
def our_deepcopy(x):
"""deepcopy lists and dictionaries, and just copy the reference
for everything else."""
@@ -201,6 +211,7 @@ class Base:
options=None,
**kw):
self.fs = SCons.Node.FS.default_fs
+ self.ans = SCons.Node.Alias.default_ans
self.lookup_list = SCons.Node.arg2nodes_lookups
self._dict = our_deepcopy(SCons.Defaults.ConstructionEnvironment)
@@ -374,6 +385,7 @@ class Base:
mode = SCons.Util.SUBST_CMD
nkw = {}
for k, v in kw.items():
+ k = SCons.Util.scons_subst(k, self, mode, target, source)
if SCons.Util.is_String(v):
v = SCons.Util.scons_subst(v, self, mode, target, source)
nkw[k] = v
@@ -705,6 +717,32 @@ class Base:
n.add_post_action(action)
return nodes
+ def Alias(self, target, *source, **kw):
+ if not SCons.Util.is_List(target):
+ target = [target]
+ tlist = []
+ for t in target:
+ if not isinstance(t, SCons.Node.Alias.Alias):
+ t = self.arg2nodes(self.subst(t), self.ans.Alias)[0]
+ tlist.append(t)
+ try:
+ s = kw['source']
+ except KeyError:
+ try:
+ s = source[0]
+ except IndexError:
+ s = None
+ if s:
+ if not SCons.Util.is_List(s):
+ s = [s]
+ s = filter(None, s)
+ s = self.arg2nodes(s, self.fs.Entry)
+ for t in tlist:
+ AliasBuilder(self, t, s)
+ if len(tlist) == 1:
+ tlist = tlist[0]
+ return tlist
+
def AlwaysBuild(self, *targets):
tlist = []
for t in targets:
@@ -734,7 +772,7 @@ class Base:
if not isinstance(target, SCons.Node.Node):
target = self.subst(target)
- target = SCons.Node.FS.default_fs.Entry(target, create=1)
+ target = self.fs.Entry(target, create=1)
if not SCons.Util.is_List(files):
files = [files]
@@ -751,13 +789,24 @@ class Base:
except KeyError:
CleanTargets[target] = nodes
+ def Configure(self, *args, **kw):
+ nargs = [self]
+ if args:
+ nargs = nargs + self.subst_list(args)[0]
+ nkw = self.subst_kw(kw)
+ try:
+ nkw['custom_tests'] = self.subst_kw(nkw['custom_tests'])
+ except KeyError:
+ pass
+ return apply(SCons.SConf.SConf, nargs, nkw)
+
def Command(self, target, source, action):
"""Builds the supplied target files from the supplied
source files using the supplied action. Action may
be any type that the Builder constructor will accept
for an action."""
bld = SCons.Builder.Builder(action=action,
- source_factory=SCons.Node.FS.default_fs.Entry)
+ source_factory=self.fs.Entry)
return bld(self, target, source)
def Default(self, *targets):
@@ -834,7 +883,7 @@ class Base:
tgt = []
for dnode in dnodes:
for src in sources:
- target = SCons.Node.FS.default_fs.File(src.name, dnode)
+ target = self.fs.File(src.name, dnode)
tgt.append(InstallBuilder(self, target, src))
if len(tgt) == 1:
tgt = tgt[0]
@@ -882,6 +931,15 @@ class Base:
dirs = self.arg2nodes(list(dirs), self.fs.Dir)
apply(self.fs.Repository, dirs, kw)
+ def Scanner(self, *args, **kw):
+ nargs = []
+ for arg in args:
+ if SCons.Util.is_String(arg):
+ arg = self.subst(arg)
+ nargs.append(arg)
+ nkw = self.subst_kw(kw)
+ return apply(SCons.Scanner.Base, nargs, nkw)
+
def SConsignFile(self, name=".sconsign.dbm"):
name = self.subst(name)
if not os.path.isabs(name):
@@ -957,6 +1015,11 @@ class Base:
else:
raise SCons.Errors.UserError, "Unknown target signature type '%s'"%type
+ def Value(self, value):
+ """
+ """
+ return SCons.Node.Python.Value(value)
+
# The entry point that will be used by the external world
# to refer to a construction environment. This allows the wrapper
# interface to extend a construction environment for its own purposes
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index 360eb4c..49d6ac7 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -308,6 +308,36 @@ class EnvironmentTestCase(unittest.TestCase):
assert lst[0][0] == 'test', lst[0][0]
assert lst[0][1] == 'baz', lst[0][1]
+ # Test not calling callables in the Environment
+ if 0:
+ # This will take some serious surgery to subst() and
+ # subst_list(), so just leave these tests out until we can
+ # do that.
+ def bar(arg):
+ pass
+
+ env = Environment(BAR=bar, FOO='$BAR')
+
+ subst = env.subst('$BAR', call=None)
+ assert subst is bar, subst
+
+ subst = env.subst('$FOO', call=None)
+ assert subst is bar, subst
+
+ subst = env.subst_list('$BAR', call=None)
+ assert subst is bar, subst
+
+ subst = env.subst_list('$FOO', call=None)
+ assert subst is bar, subst
+
+ def test_subst_kw(self):
+ """Test substituting construction variables within dictionaries"""
+ env = Environment(AAA = 'a', BBB = 'b')
+ kw = env.subst_kw({'$AAA' : 'aaa', 'bbb' : '$BBB'})
+ assert len(kw) == 2, kw
+ assert kw['a'] == 'aaa', kw['a']
+ assert kw['bbb'] == 'b', kw['bbb']
+
def test_Builder_calls(self):
"""Test Builder calls through different environments
"""
@@ -1191,6 +1221,49 @@ class EnvironmentTestCase(unittest.TestCase):
assert str(n[0]) == 'ggg', n[0]
assert str(n[1]) == 'bbb', n[1]
+ def test_Alias(self):
+ """Test the Alias() method"""
+ env = Environment(FOO='kkk', BAR='lll', EA='export_alias')
+
+ tgt = env.Alias('new_alias')
+ assert str(tgt) == 'new_alias', tgt
+ assert tgt.sources == [], tgt.sources
+
+ tgt = env.Alias('None_alias', None)
+ assert str(tgt) == 'None_alias', tgt
+ assert tgt.sources == [], tgt.sources
+
+ tgt = env.Alias('empty_list', [])
+ assert str(tgt) == 'empty_list', tgt
+ assert tgt.sources == [], tgt.sources
+
+ tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ])
+ assert str(tgt) == 'export_alias', tgt
+ assert len(tgt.sources) == 2, map(str, tgt.sources)
+ assert str(tgt.sources[0]) == 'asrc1', map(str, tgt.sources)
+ assert str(tgt.sources[1]) == 'kkk', map(str, tgt.sources)
+
+ n = env.Alias(tgt, source = ['$BAR', 'asrc4'])
+ assert n is tgt, n
+ assert len(tgt.sources) == 4, map(str, tgt.sources)
+ assert str(tgt.sources[2]) == 'lll', map(str, tgt.sources)
+ assert str(tgt.sources[3]) == 'asrc4', map(str, tgt.sources)
+
+ n = env.Alias('$EA', 'asrc5')
+ assert n is tgt, n
+ assert len(tgt.sources) == 5, map(str, tgt.sources)
+ assert str(tgt.sources[4]) == 'asrc5', map(str, tgt.sources)
+
+ t1, t2 = env.Alias(['t1', 't2'], ['asrc6', 'asrc7'])
+ assert str(t1) == 't1', t1
+ assert str(t2) == 't2', t2
+ assert len(t1.sources) == 2, map(str, t1.sources)
+ assert str(t1.sources[0]) == 'asrc6', map(str, t1.sources)
+ assert str(t1.sources[1]) == 'asrc7', map(str, t1.sources)
+ assert len(t2.sources) == 2, map(str, t2.sources)
+ assert str(t2.sources[0]) == 'asrc6', map(str, t2.sources)
+ assert str(t2.sources[1]) == 'asrc7', map(str, t2.sources)
+
def test_AlwaysBuild(self):
"""Test the AlwaysBuild() method"""
env = Environment(FOO='fff', BAR='bbb')
@@ -1323,6 +1396,32 @@ class EnvironmentTestCase(unittest.TestCase):
assert 'foo1.in' in map(lambda x: x.path, t.sources)
assert 'foo2.in' in map(lambda x: x.path, t.sources)
+ def test_Configure(self):
+ """Test the Configure() method"""
+ # Configure() will write to a local temporary file.
+ test = TestCmd.TestCmd(workdir = '')
+ save = os.getcwd()
+
+ try:
+ os.chdir(test.workpath())
+
+ env = Environment(FOO = 'xyzzy')
+
+ def func(arg):
+ pass
+
+ c = env.Configure()
+ assert not c is None, c
+ c.Finish()
+
+ c = env.Configure(custom_tests = {'foo' : func, '$FOO' : func})
+ assert not c is None, c
+ assert hasattr(c, 'foo')
+ assert hasattr(c, 'xyzzy')
+ c.Finish()
+ finally:
+ os.chdir(save)
+
def test_Default(self):
"""Test the Default() method"""
env = Environment(FOO = 'fff', BAR = 'bbb')
@@ -1592,6 +1691,26 @@ class EnvironmentTestCase(unittest.TestCase):
expect = ['/tmp/foo', '/tmp/rrr', '/tmp/sss/foo']
assert env.fs.list == expect, env.fs.list
+ def test_Scanner(self):
+ """Test the Scanner() method"""
+ def scan(node, env, target, arg):
+ pass
+
+ env = Environment(FOO = scan)
+
+ s = env.Scanner('foo')
+ assert not s is None, s
+
+ s = env.Scanner(function = 'foo')
+ assert not s is None, s
+
+ if 0:
+ s = env.Scanner('$FOO')
+ assert not s is None, s
+
+ s = env.Scanner(function = '$FOO')
+ assert not s is None, s
+
def test_SConsignFile(self):
"""Test the SConsignFile() method"""
import SCons.Sig
@@ -1750,6 +1869,23 @@ class EnvironmentTestCase(unittest.TestCase):
env.TargetSignatures('$C')
assert env._build_signature == 0, env._build_signature
+ def test_Value(self):
+ """Test creating a Value() object
+ """
+ env = Environment()
+ v1 = env.Value('a')
+ assert v1.value == 'a', v1.value
+
+ value2 = 'a'
+ v2 = env.Value(value2)
+ assert v2.value == value2, v2.value
+ assert v2.value is value2, v2.value
+
+ assert not v1 is v2
+ assert v1.value == v2.value
+
+
+
def test_Environment_global_variable(type):
"""Test setting Environment variable to an Environment.Base subclass"""
class MyEnv(SCons.Environment.Base):
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index aed43f5..92cd68d 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -39,13 +39,12 @@ import SCons.Errors
import SCons.Node
import SCons.Node.Alias
import SCons.Node.FS
-import SCons.Node.Python
+import SCons.Options
import SCons.Platform
import SCons.SConf
import SCons.Script
import SCons.Tool
import SCons.Util
-import SCons.Options
import os
import os.path
@@ -68,10 +67,6 @@ global_exports = {}
# chdir flag
sconscript_chdir = 1
-def SConscriptChdir(flag):
- global sconscript_chdir
- sconscript_chdir = flag
-
def _scons_add_args(alist):
global arguments
for arg in alist:
@@ -365,17 +360,17 @@ class SConsEnvironment(SCons.Environment.Base):
src_dir, fname = os.path.split(str(files[0]))
else:
if not isinstance(src_dir, SCons.Node.Node):
- src_dir = SCons.Node.FS.default_fs.Dir(src_dir)
+ src_dir = self.fs.Dir(src_dir)
fn = files[0]
if not isinstance(fn, SCons.Node.Node):
- fn = SCons.Node.FS.default_fs.File(fn)
+ fn = self.fs.File(fn)
if fn.is_under(src_dir):
# Get path relative to the source directory.
fname = fn.get_path(src_dir)
else:
# Fast way to only get the terminal path component of a Node.
fname = fn.get_path(fn.dir)
- SCons.Node.FS.default_fs.BuildDir(build_dir, src_dir, duplicate)
+ self.fs.BuildDir(build_dir, src_dir, duplicate)
files = [os.path.join(str(build_dir), fname)]
return (files, exports)
@@ -446,6 +441,10 @@ class SConsEnvironment(SCons.Environment.Base):
return apply(_SConscript, [self.fs,] + files, {'exports' : exports})
+ def SConscriptChdir(self, flag):
+ global sconscript_chdir
+ sconscript_chdir = flag
+
def SetOption(self, name, value):
name = self.subst(name)
SCons.Script.ssoptions.set(name, value)
@@ -455,6 +454,9 @@ class SConsEnvironment(SCons.Environment.Base):
#
SCons.Environment.Environment = SConsEnvironment
+def Options(files=None, args=arguments):
+ return SCons.Options.Options(files, args)
+
def SetBuildSignatureType(type):
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
"The SetBuildSignatureType() function has been deprecated;\n" +\
@@ -467,10 +469,6 @@ def SetContentSignatureType(type):
"\tuse the SourceSignatures() function instead.")
SCons.Defaults.DefaultEnvironment().SourceSignatures(type)
-class Options(SCons.Options.Options):
- def __init__(self, files=None, args=arguments):
- SCons.Options.Options.__init__(self, files, args)
-
def GetJobs():
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
"The GetJobs() function has been deprecated;\n" +\
@@ -490,13 +488,6 @@ def ParseConfig(env, command, function=None):
"\tuse the env.ParseConfig() method instead.")
return env.ParseConfig(command, function)
-
-def Alias(name):
- alias = SCons.Node.Alias.default_ans.lookup(name)
- if alias is None:
- alias = SCons.Node.Alias.default_ans.Alias(name)
- return alias
-
#
_DefaultEnvironmentProxy = None
@@ -557,12 +548,14 @@ GlobalDefaultEnvironmentFunctions = [
'Help',
'Import',
'SConscript',
+ 'SConscriptChdir',
'SetOption',
# Methods from the Environment.Base class.
'Action',
'AddPostAction',
'AddPreAction',
+ 'Alias',
'AlwaysBuild',
'BuildDir',
'Builder',
@@ -583,13 +576,17 @@ GlobalDefaultEnvironmentFunctions = [
'Local',
'Precious',
'Repository',
+ 'Scanner',
'SConsignFile',
'SideEffect',
'SourceCode',
'SourceSignatures',
'Split',
'TargetSignatures',
+ 'Value',
+]
+GlobalDefaultBuilders = [
# Supported builders.
'CFile',
'CXXFile',
@@ -616,7 +613,7 @@ GlobalDefaultEnvironmentFunctions = [
'Zip',
]
-for name in GlobalDefaultEnvironmentFunctions:
+for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
GlobalDict[name] = DefaultEnvironmentCall(name)
def BuildDefaultGlobals():
@@ -626,23 +623,17 @@ def BuildDefaultGlobals():
"""
globals = {}
+ globals['ARGUMENTS'] = arguments
+ globals['Configure'] = SCons.SConf.SConf
+ globals['Options'] = Options
globals['Platform'] = SCons.Platform.Platform
+ globals['Return'] = Return
globals['Tool'] = SCons.Tool.Tool
globals['WhereIs'] = SCons.Util.WhereIs
# Functions we're in the process of converting to Environment methods.
- globals['Alias'] = Alias
- globals['ARGUMENTS'] = arguments
- globals['Configure'] = SCons.SConf.SConf
globals['CScan'] = SCons.Defaults.CScan
globals['DefaultEnvironment'] = SCons.Defaults.DefaultEnvironment
- globals['GetCommandHandler'] = SCons.Action.GetCommandHandler
- globals['Options'] = Options
- globals['Return'] = Return
- globals['SConscriptChdir'] = SConscriptChdir
- globals['Scanner'] = SCons.Scanner.Base
- globals['SetCommandHandler'] = SCons.Action.SetCommandHandler
- globals['Value'] = SCons.Node.Python.Value
# Deprecated functions, leave these here for now.
globals['GetJobs'] = GetJobs