summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-10-30 05:39:49 (GMT)
committerSteven Knight <knight@baldmt.com>2003-10-30 05:39:49 (GMT)
commit64c0acf336168c457512863a0428630b084cc47e (patch)
tree59498e64cfb463de720383ad2584345940d06ff4
parentc0859da6b4fe678bab39caf47a628719fc6ff0b6 (diff)
downloadSCons-64c0acf336168c457512863a0428630b084cc47e.zip
SCons-64c0acf336168c457512863a0428630b084cc47e.tar.gz
SCons-64c0acf336168c457512863a0428630b084cc47e.tar.bz2
Fix subclassing of the Environment and Scanner classes.
-rw-r--r--src/CHANGES.txt2
-rw-r--r--src/engine/SCons/Script/SConscript.py624
-rw-r--r--test/subclassing.py60
3 files changed, 398 insertions, 288 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 367b54a..7b5a93b 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -17,6 +17,8 @@ RELEASE X.XX - XXX, XX XXX XXXX XX:XX:XX -XXXX
- Fix env.Append() when the operand is an object with a __cmp__()
method (like a Scanner instance).
+ - Fix subclassing the Environment and Scanner classes.
+
From Gary Oberbrunner:
- Fix how the man page un-indents after examples in some browsers.
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index 1c17ee2..924ddf3 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -30,21 +30,21 @@ files.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import SCons
import SCons.Action
import SCons.Builder
import SCons.Defaults
import SCons.Environment
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 SCons
-import SCons.Node.Alias
import os
import os.path
@@ -52,13 +52,13 @@ import re
import string
import sys
import traceback
+import types
def do_nothing(text): pass
HelpFunction = do_nothing
-default_targets = None
-clean_targets = {}
arguments = {}
+GlobalDict = {}
launch_dir = os.path.abspath(os.curdir)
# global exports set by Export():
@@ -67,9 +67,8 @@ global_exports = {}
# chdir flag
sconscript_chdir = 1
-def SConscriptChdir(flag):
- global sconscript_chdir
- sconscript_chdir = flag
+# will be set to 1, if we are reading a SConscript
+sconscript_reading = 0
def _scons_add_args(alist):
global arguments
@@ -81,7 +80,7 @@ def get_calling_namespaces():
"""Return the locals and globals for the function that called
into this module in the current callstack."""
try: 1/0
- except: frame = sys.exc_info()[2].tb_frame
+ except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame
while frame.f_globals.get("__name__") == __name__: frame = frame.f_back
@@ -92,7 +91,6 @@ def compute_exports(exports):
"""Compute a dictionary of exports given one of the parameters
to the Export() function or the exports argument to SConscript()."""
- exports = SCons.Util.Split(exports)
loc, glob = get_calling_namespaces()
retval = {}
@@ -143,82 +141,12 @@ def Return(*vars):
else:
stack[-1].retval = tuple(retval)
-# This function is responsible for converting the parameters passed to
-# SConscript() calls into a list of files and export variables. If the
-# parameters are invalid, throws SCons.Errors.UserError. Returns a tuple
-# (l, e) where l is a list of SConscript filenames and e is a list of
-# exports.
-
-def GetSConscriptFilenames(ls, kw):
- exports = []
-
- if len(ls) == 0:
- try:
- dirs = kw["dirs"]
- except KeyError:
- raise SCons.Errors.UserError, \
- "Invalid SConscript usage - no parameters"
-
- if not SCons.Util.is_List(dirs):
- dirs = [ dirs ]
- dirs = map(str, dirs)
-
- name = kw.get('name', 'SConscript')
-
- files = map(lambda n, name = name: os.path.join(n, name), dirs)
-
- elif len(ls) == 1:
-
- files = ls[0]
-
- elif len(ls) == 2:
-
- files = ls[0]
- exports = SCons.Util.Split(ls[1])
-
- else:
-
- raise SCons.Errors.UserError, \
- "Invalid SConscript() usage - too many arguments"
-
- if not SCons.Util.is_List(files):
- files = [ files ]
-
- if kw.get('exports'):
- exports.extend(SCons.Util.Split(kw['exports']))
-
- build_dir = kw.get('build_dir')
- if build_dir:
- if len(files) != 1:
- raise SCons.Errors.UserError, \
- "Invalid SConscript() usage - can only specify one SConscript with a build_dir"
- duplicate = kw.get('duplicate', 1)
- src_dir = kw.get('src_dir')
- if not src_dir:
- 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)
- fn = files[0]
- if not isinstance(fn, SCons.Node.Node):
- fn = SCons.Node.FS.default_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)
- BuildDir(build_dir, src_dir, duplicate)
- files = [os.path.join(str(build_dir), fname)]
-
- return (files, exports)
-
-def SConscript(*ls, **kw):
- files, exports = GetSConscriptFilenames(ls, kw)
-
- default_fs = SCons.Node.FS.default_fs
- top = default_fs.Top
- sd = default_fs.SConstruct_dir.rdir()
+def _SConscript(fs, *files, **kw):
+ global sconscript_reading
+ sconscript_reading = 1
+ top = fs.Top
+ sd = fs.SConstruct_dir.rdir()
+ exports = kw.get('exports', [])
# evaluate each SConscript file
results = []
@@ -232,14 +160,13 @@ def SConscript(*ls, **kw):
if isinstance(fn, SCons.Node.Node):
f = fn
else:
- f = default_fs.File(str(fn))
+ f = fs.File(str(fn))
_file_ = None
# Change directory to the top of the source
# tree to make sure the os's cwd and the cwd of
- # SCons.Node.FS.default_fs match so we can open the
- # SConscript.
- default_fs.chdir(top, change_os_dir=1)
+ # fs match so we can open the SConscript.
+ fs.chdir(top, change_os_dir=1)
if f.rexists():
_file_ = open(f.rstr(), "r")
elif f.has_src_builder():
@@ -263,17 +190,17 @@ def SConscript(*ls, **kw):
# where the SConstruct and SConscript files might be
# in different Repositories. For now, cross that
# bridge when someone comes to it.
- ldir = default_fs.Dir(f.dir.get_path(sd))
+ ldir = fs.Dir(f.dir.get_path(sd))
try:
- default_fs.chdir(ldir, change_os_dir=sconscript_chdir)
+ fs.chdir(ldir, change_os_dir=sconscript_chdir)
except OSError:
# There was no local directory, so we should be
# able to chdir to the Repository directory.
# Note that we do this directly, not through
- # default_fs.chdir(), because we still need to
+ # fs.chdir(), because we still need to
# interpret the stuff within the SConscript file
# relative to where we are logically.
- default_fs.chdir(ldir, change_os_dir=0)
+ fs.chdir(ldir, change_os_dir=0)
os.chdir(f.rfile().dir.get_abspath())
# Append the SConscript directory to the beginning
@@ -293,15 +220,16 @@ def SConscript(*ls, **kw):
f.path)
finally:
+ sconscript_reading = 0
sys.path = old_sys_path
frame = stack.pop()
try:
- default_fs.chdir(frame.prev_dir, change_os_dir=sconscript_chdir)
+ fs.chdir(frame.prev_dir, change_os_dir=sconscript_chdir)
except OSError:
# There was no local directory, so chdir to the
# Repository directory. Like above, we do this
# directly.
- default_fs.chdir(frame.prev_dir, change_os_dir=0)
+ fs.chdir(frame.prev_dir, change_os_dir=0)
os.chdir(frame.prev_dir.rdir().get_abspath())
results.append(frame.retval)
@@ -356,129 +284,196 @@ def annotate(node):
# leave this disabled until we find a more efficient mechanism.
#SCons.Node.Annotate = annotate
-def Default(*targets):
- global default_targets
- if default_targets is None:
- default_targets = []
- for t in targets:
- if t is None:
- default_targets = []
- elif isinstance(t, SCons.Node.Node):
- default_targets.append(t)
- else:
- default_targets.extend(SCons.Node.arg2nodes(t,
- SCons.Node.FS.default_fs.Entry))
+class SConsEnvironment(SCons.Environment.Base):
+ """An Environment subclass that contains all of the methods that
+ are particular to the wrapper SCons interface and which aren't
+ (or shouldn't be) part of the build engine itself.
+
+ Note that not all of the methods of this class have corresponding
+ global functions, there are some private methods.
+ """
+
+ #
+ # Private methods of an SConsEnvironment.
+ #
-def Local(*targets):
- for targ in targets:
- if isinstance(targ, SCons.Node.Node):
- targ.set_local()
+ def _check_version(self, major, minor, version_string):
+ """Return 0 if 'major' and 'minor' are greater than the version
+ in 'version_string', and 1 otherwise."""
+ try:
+ v_major, v_minor, v_micro, release, serial = sys.version_info
+ except AttributeError:
+ version = string.split(string.split(version_string, ' ')[0], '.')
+ v_major = int(version[0])
+ v_minor = int(re.match('\d+', version[1]).group())
+ if major > v_major or (major == v_major and minor > v_minor):
+ return 0
else:
- for t in SCons.Node.arg2nodes(targ, SCons.Node.FS.default_fs.Entry):
- t.set_local()
+ return 1
+
+ def _get_SConscript_filenames(self, ls, kw):
+ """
+ Convert the parameters passed to # SConscript() calls into a list
+ of files and export variables. If the parameters are invalid,
+ throws SCons.Errors.UserError. Returns a tuple (l, e) where l
+ is a list of SConscript filenames and e is a list of exports.
+ """
+ exports = []
+
+ if len(ls) == 0:
+ try:
+ dirs = kw["dirs"]
+ except KeyError:
+ raise SCons.Errors.UserError, \
+ "Invalid SConscript usage - no parameters"
-def Help(text):
- HelpFunction(text)
+ if not SCons.Util.is_List(dirs):
+ dirs = [ dirs ]
+ dirs = map(str, dirs)
-def BuildDir(build_dir, src_dir, duplicate=1):
- SCons.Node.FS.default_fs.BuildDir(build_dir, src_dir, duplicate)
+ name = kw.get('name', 'SConscript')
-def GetBuildPath(files):
- nodes = SCons.Node.arg2nodes(files, SCons.Node.FS.default_fs.Entry)
- ret = map(str, nodes)
- if len(ret) == 1:
- return ret[0]
- return ret
+ files = map(lambda n, name = name: os.path.join(n, name), dirs)
-def FindFile(file, dirs):
- nodes = SCons.Node.arg2nodes(dirs, SCons.Node.FS.default_fs.Dir)
- return SCons.Node.FS.find_file(file, nodes)
+ elif len(ls) == 1:
-def Export(*vars):
- for var in vars:
- global_exports.update(compute_exports(var))
+ files = ls[0]
-def Import(*vars):
- try:
- for var in vars:
- var = SCons.Util.Split(var)
- for v in var:
- if v == '*':
- stack[-1].globals.update(global_exports)
- stack[-1].globals.update(stack[-1].exports)
+ elif len(ls) == 2:
+
+ files = ls[0]
+ exports = self.Split(ls[1])
+
+ else:
+
+ raise SCons.Errors.UserError, \
+ "Invalid SConscript() usage - too many arguments"
+
+ if not SCons.Util.is_List(files):
+ files = [ files ]
+
+ if kw.get('exports'):
+ exports.extend(self.Split(kw['exports']))
+
+ build_dir = kw.get('build_dir')
+ if build_dir:
+ if len(files) != 1:
+ raise SCons.Errors.UserError, \
+ "Invalid SConscript() usage - can only specify one SConscript with a build_dir"
+ duplicate = kw.get('duplicate', 1)
+ src_dir = kw.get('src_dir')
+ if not src_dir:
+ src_dir, fname = os.path.split(str(files[0]))
+ else:
+ if not isinstance(src_dir, SCons.Node.Node):
+ src_dir = self.fs.Dir(src_dir)
+ fn = files[0]
+ if not isinstance(fn, SCons.Node.Node):
+ 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:
- if stack[-1].exports.has_key(v):
- stack[-1].globals[v] = stack[-1].exports[v]
+ # Fast way to only get the terminal path component of a Node.
+ fname = fn.get_path(fn.dir)
+ self.fs.BuildDir(build_dir, src_dir, duplicate)
+ files = [os.path.join(str(build_dir), fname)]
+
+ return (files, exports)
+
+ #
+ # Public methods of an SConsEnvironment. These get
+ # entry points in the global name space so they can be called
+ # as global functions.
+ #
+
+ def EnsureSConsVersion(self, major, minor):
+ """Exit abnormally if the SCons version is not late enough."""
+ if not self._check_version(major,minor,SCons.__version__):
+ print "SCons %d.%d or greater required, but you have SCons %s" %(major,minor,SCons.__version__)
+ sys.exit(2)
+
+ def EnsurePythonVersion(self, major, minor):
+ """Exit abnormally if the Python version is not late enough."""
+ if not self._check_version(major,minor,sys.version):
+ v = string.split(sys.version, " ", 1)[0]
+ print "Python %d.%d or greater required, but you have Python %s" %(major,minor,v)
+ sys.exit(2)
+
+ def Exit(self, value=0):
+ sys.exit(value)
+
+ def Export(self, *vars):
+ for var in vars:
+ global_exports.update(compute_exports(self.Split(var)))
+
+ def GetLaunchDir(self):
+ global launch_dir
+ return launch_dir
+
+ def GetOption(self, name):
+ name = self.subst(name)
+ return SCons.Script.ssoptions.get(name)
+
+ def Help(self, text):
+ text = self.subst(text, raw=1)
+ HelpFunction(text)
+
+ def Import(self, *vars):
+ try:
+ for var in vars:
+ var = self.Split(var)
+ for v in var:
+ if v == '*':
+ stack[-1].globals.update(global_exports)
+ stack[-1].globals.update(stack[-1].exports)
else:
- stack[-1].globals[v] = global_exports[v]
- except KeyError,x:
- raise SCons.Errors.UserError, "Import of non-existant variable '%s'"%x
+ if stack[-1].exports.has_key(v):
+ stack[-1].globals[v] = stack[-1].exports[v]
+ else:
+ stack[-1].globals[v] = global_exports[v]
+ except KeyError,x:
+ raise SCons.Errors.UserError, "Import of non-existant variable '%s'"%x
-def GetLaunchDir():
- return launch_dir
+ def SConscript(self, *ls, **kw):
+ ls = map(lambda l, self=self: self.subst(l), ls)
+ subst_kw = {}
+ for key, val in kw.items():
+ if SCons.Util.is_String(val):
+ val = self.subst(val)
+ subst_kw[key] = val
+
+ files, exports = self._get_SConscript_filenames(ls, subst_kw)
+
+ 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)
+
+#
+#
+#
+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" +\
"\tuse the TargetSignatures() function instead.")
- TargetSignatures(type)
-
-def TargetSignatures(type):
- import SCons.Sig
- if type == 'build':
- SCons.Sig.build_signature = 1
- elif type == 'content':
- SCons.Sig.build_signature = 0
- else:
- raise SCons.Errors.UserError, "Unknown build signature type '%s'"%type
+ SCons.Defaults.DefaultEnvironment().TargetSignatures(type)
def SetContentSignatureType(type):
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
"The SetContentSignatureType() function has been deprecated;\n" +\
"\tuse the SourceSignatures() function instead.")
- SourceSignatures(type)
-
-def SourceSignatures(type):
- if type == 'MD5':
- import SCons.Sig.MD5
- SCons.Script.sig_module = SCons.Sig.MD5
- elif type == 'timestamp':
- import SCons.Sig.TimeStamp
- SCons.Script.sig_module = SCons.Sig.TimeStamp
- else:
- raise SCons.Errors.UserError, "Unknown content signature type '%s'"%type
-
-
-class Options(SCons.Options.Options):
- def __init__(self, files=None, args=arguments):
- SCons.Options.Options.__init__(self, files, args)
-
-def CheckVersion(major, minor, version_string):
- """Return 0 if 'major' and 'minor' are greater than the version
- in 'version_string', and 1 otherwise."""
- try:
- v_major, v_minor, v_micro, release, serial = sys.version_info
- except AttributeError:
- version = string.split(string.split(version_string, ' ')[0], '.')
- v_major = int(version[0])
- v_minor = int(re.match('\d+', version[1]).group())
- if major > v_major or (major == v_major and minor > v_minor):
- return 0
- else:
- return 1
-
-def EnsureSConsVersion(major, minor):
- """Exit abnormally if the SCons version is not late enough."""
- if not CheckVersion(major,minor,SCons.__version__):
- print "SCons %d.%d or greater required, but you have SCons %s" %(major,minor,SCons.__version__)
- sys.exit(2)
-
-def EnsurePythonVersion(major, minor):
- """Exit abnormally if the Python version is not late enough."""
- if not CheckVersion(major,minor,sys.version):
- v = string.split(sys.version, " ", 1)[0]
- print "Python %d.%d or greater required, but you have Python %s" %(major,minor,v)
- sys.exit(2)
+ SCons.Defaults.DefaultEnvironment().SourceSignatures(type)
def GetJobs():
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
@@ -492,58 +487,136 @@ def SetJobs(num):
"The SetJobs() function has been deprecated;\n" +\
"\tuse SetOption('num_jobs', num) instead.")
SetOption('num_jobs', num)
+
+def ParseConfig(env, command, function=None):
+ SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
+ "The ParseConfig() function has been deprecated;\n" +\
+ "\tuse the env.ParseConfig() method instead.")
+ return env.ParseConfig(command, function)
-def Clean(target, files):
- if not isinstance(target, SCons.Node.Node):
- target = SCons.Node.FS.default_fs.Entry(target, create=1)
-
- if not SCons.Util.is_List(files):
- files = [files]
-
- nodes = []
- for f in files:
- if isinstance(f, SCons.Node.Node):
- nodes.append(f)
- else:
- nodes.extend(SCons.Node.arg2nodes(f, SCons.Node.FS.default_fs.Entry))
-
- try:
- clean_targets[target].extend(nodes)
- except KeyError:
- clean_targets[target] = nodes
-
-def AddPreAction(files, action):
- nodes = SCons.Node.arg2nodes(files, SCons.Node.FS.default_fs.Entry)
- for n in nodes:
- n.add_pre_action(SCons.Action.Action(action))
-
-def AddPostAction(files, action):
- nodes = SCons.Node.arg2nodes(files, SCons.Node.FS.default_fs.Entry)
- for n in nodes:
- n.add_post_action(SCons.Action.Action(action))
-
-def Exit(value=0):
- sys.exit(value)
-
-
-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
-
-def SetOption(name, value):
- SCons.Script.ssoptions.set(name, value)
-
-def GetOption(name):
- return SCons.Script.ssoptions.get(name)
-
-def SConsignFile(name=".sconsign.dbm"):
- import SCons.Sig
- if not os.path.isabs(name):
- sd = str(SCons.Node.FS.default_fs.SConstruct_dir)
- name = os.path.join(sd, name)
- SCons.Sig.SConsignFile(name)
+#
+_DefaultEnvironmentProxy = None
+
+def get_DefaultEnvironmentProxy():
+ global _DefaultEnvironmentProxy
+ if not _DefaultEnvironmentProxy:
+ class EnvironmentProxy(SCons.Environment.Environment):
+ """A proxy subclass for an environment instance that overrides
+ the subst() and subst_list() methods so they don't actually
+ actually perform construction variable substitution. This is
+ specifically intended to be the shim layer in between global
+ function calls (which don't want want construction variable
+ substitution) and the DefaultEnvironment() (which would
+ substitute variables if left to its own devices)."""
+ def __init__(self, subject):
+ self.__dict__['__subject'] = subject
+ def __getattr__(self, name):
+ return getattr(self.__dict__['__subject'], name)
+ def __setattr__(self, name, value):
+ return setattr(self.__dict__['__subject'], name, value)
+ def subst(self, string, raw=0, target=None, source=None):
+ return string
+ def subst_kw(self, kw, raw=0, target=None, source=None):
+ return kw
+ def subst_list(self, string, raw=0, target=None, source=None):
+ return string
+ default_env = SCons.Defaults.DefaultEnvironment()
+ _DefaultEnvironmentProxy = EnvironmentProxy(default_env)
+ return _DefaultEnvironmentProxy
+
+class DefaultEnvironmentCall:
+ """A class that implements "global function" calls of
+ Environment methods by fetching the specified method from the
+ DefaultEnvironment's class. Note that this uses an intermediate
+ proxy class instead of calling the DefaultEnvironment method
+ directly so that the proxy can override the subst() method and
+ thereby prevent expansion of construction variables (since from
+ the user's point of view this was called as a global function,
+ with no associated construction environment)."""
+ def __init__(self, method_name):
+ self.method_name = method_name
+ def __call__(self, *args, **kw):
+ proxy = get_DefaultEnvironmentProxy()
+ method = getattr(proxy, self.method_name)
+ return apply(method, args, kw)
+
+# The list of global functions to add to the SConscript name space
+# that end up calling corresponding methods or Builders in the
+# DefaultEnvironment().
+GlobalDefaultEnvironmentFunctions = [
+ # Methods from the SConsEnvironment class, above.
+ 'EnsurePythonVersion',
+ 'EnsureSConsVersion',
+ 'Exit',
+ 'Export',
+ 'GetLaunchDir',
+ 'GetOption',
+ 'Help',
+ 'Import',
+ 'SConscript',
+ 'SConscriptChdir',
+ 'SetOption',
+
+ # Methods from the Environment.Base class.
+ 'AddPostAction',
+ 'AddPreAction',
+ 'Alias',
+ 'AlwaysBuild',
+ 'BuildDir',
+ 'CacheDir',
+ 'Clean',
+ 'Command',
+ 'Default',
+ 'Depends',
+ 'Dir',
+ 'File',
+ 'FindFile',
+ 'GetBuildPath',
+ 'Ignore',
+ 'Install',
+ 'InstallAs',
+ 'Literal',
+ 'Local',
+ 'Precious',
+ 'Repository',
+ 'SConsignFile',
+ 'SideEffect',
+ 'SourceCode',
+ 'SourceSignatures',
+ 'Split',
+ 'TargetSignatures',
+ 'Value',
+]
+
+GlobalDefaultBuilders = [
+ # Supported builders.
+ 'CFile',
+ 'CXXFile',
+ 'DVI',
+ 'Jar',
+ 'Java',
+ 'JavaH',
+ 'Library',
+ 'M4',
+ 'MSVSProject',
+ 'Object',
+ 'PCH',
+ 'PDF',
+ 'PostScript',
+ 'Program',
+ 'RES',
+ 'RMIC',
+ 'SharedLibrary',
+ 'SharedObject',
+ 'StaticLibrary',
+ 'StaticObject',
+ 'Tar',
+ 'TypeLibrary',
+ 'Zip',
+]
+
+for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
+ GlobalDict[name] = DefaultEnvironmentCall(name)
def BuildDefaultGlobals():
"""
@@ -553,53 +626,28 @@ def BuildDefaultGlobals():
globals = {}
globals['Action'] = SCons.Action.Action
- globals['AddPostAction'] = AddPostAction
- globals['AddPreAction'] = AddPreAction
- globals['Alias'] = Alias
globals['ARGUMENTS'] = arguments
- globals['BuildDir'] = BuildDir
globals['Builder'] = SCons.Builder.Builder
- globals['CacheDir'] = SCons.Node.FS.default_fs.CacheDir
- globals['Clean'] = Clean
globals['Configure'] = SCons.SConf.SConf
- globals['CScan'] = SCons.Defaults.CScan
- globals['Default'] = Default
- globals['DefaultEnvironment'] = SCons.Defaults.DefaultEnvironment
- globals['Dir'] = SCons.Node.FS.default_fs.Dir
- globals['EnsurePythonVersion'] = EnsurePythonVersion
- globals['EnsureSConsVersion'] = EnsureSConsVersion
globals['Environment'] = SCons.Environment.Environment
- globals['Exit'] = Exit
- globals['Export'] = Export
- globals['File'] = SCons.Node.FS.default_fs.File
- globals['FindFile'] = FindFile
- globals['GetBuildPath'] = GetBuildPath
- globals['GetCommandHandler'] = SCons.Action.GetCommandHandler
- globals['GetJobs'] = GetJobs
- globals['GetLaunchDir'] = GetLaunchDir
- globals['GetOption'] = GetOption
- globals['Help'] = Help
- globals['Import'] = Import
- globals['Literal'] = SCons.Util.Literal
- globals['Local'] = Local
globals['Options'] = Options
- globals['ParseConfig'] = SCons.Util.ParseConfig
globals['Platform'] = SCons.Platform.Platform
- globals['Repository'] = SCons.Node.FS.default_fs.Repository
globals['Return'] = Return
- globals['SConscript'] = SConscript
- globals['SConscriptChdir'] = SConscriptChdir
- globals['SConsignFile'] = SConsignFile
globals['Scanner'] = SCons.Scanner.Base
+ globals['Tool'] = SCons.Tool.Tool
+ globals['WhereIs'] = SCons.Util.WhereIs
+
+ # Functions we're in the process of converting to Environment methods.
+ globals['CScan'] = SCons.Defaults.CScan
+ globals['DefaultEnvironment'] = SCons.Defaults.DefaultEnvironment
+
+ # Deprecated functions, leave these here for now.
+ globals['GetJobs'] = GetJobs
+ globals['ParseConfig'] = ParseConfig
globals['SetBuildSignatureType'] = SetBuildSignatureType
- globals['SetCommandHandler'] = SCons.Action.SetCommandHandler
globals['SetContentSignatureType'] = SetContentSignatureType
globals['SetJobs'] = SetJobs
- globals['SetOption'] = SetOption
- globals['SourceSignatures'] = SourceSignatures
- globals['Split'] = SCons.Util.Split
- globals['TargetSignatures'] = TargetSignatures
- globals['Tool'] = SCons.Tool.Tool
- globals['Value'] = SCons.Node.Python.Value
- globals['WhereIs'] = SCons.Util.WhereIs
+
+ globals.update(GlobalDict)
+
return globals
diff --git a/test/subclassing.py b/test/subclassing.py
new file mode 100644
index 0000000..a040dd4
--- /dev/null
+++ b/test/subclassing.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that we can trivially subclass our "public" classes.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+# Some day, we'd probably like people to be able to subclass Action and
+# Builder, but that's going to take some serious class-hackery to turn
+# our factory function into the class itself.
+#class my_Action(Action):
+# pass
+#class my_Builder(Builder):
+# pass
+class my_Scanner(Scanner):
+ pass
+class my_Environment(Environment):
+ pass
+env = my_Environment()
+env.Program('hello', 'hello.c')
+""")
+
+test.write('hello.c', """\
+int
+main(int argc, char *argv[]) {
+ printf("hello.c\\n");
+}
+""")
+
+test.run(arguments = '.')
+
+test.pass_test()