.PP
.fi
-.SH Construction Variables
+.SS Construction Variables
A construction environment has an associated dictionary of construction
variables that are used by built-in or user-supplied build rules. A number
is an optional directory that will be used as the parent directory.
-.SH EXTENDING
+.SH EXTENDING SCONS
+.SS Builder Objects
.B scons
can be extended by adding new builders to a construction
environment using the
.IP action
The command line string used to build the target from the source.
.B action
-can also be a dictionary mapping source file name suffixes to command line string,
-if the builder can accept multiple source file extensions.
+can also be a dictionary
+mapping source file name suffixes to command line string
+(if the builder should accept multiple source file extensions),
+a Python function,
+or an Action object
+(see the next section).
.IP prefix
The prefix that will be prepended to the target file name.
any of the suffixes of the builder. Using this argument produces a
multi-stage builder.
-.LP
+.SS Action Objects
+The Builder function will turn its
+.B action
+keyword argument into an appropriate
+internal Action object.
+Occasionally, it may be more efficient
+to create an explicit Action object
+and use it to initialize multiple
+Builder objects,
+rather than let each separate Builder object
+create a separate Action.
+
+The Action function takes a single argument
+and returns an appropriate object for the action
+represented by the type of the argument:
+
+.IP Action
+If the argument is already an Action object,
+the object is simply returned.
+.IP String
+If the argument is a string,
+a command-line Action is returned.
+.IP Function
+If the argument is a Python function,
+a function Action is returned.
+.IP List
+If the argument is a list,
+then a list of Action objects is returned.
+An Action object is created as necessary
+for each element in the list.
+.PP
+If the action argument is not one of the above,
+None is returned.
+.SS Variable Substitution
.B scons
performs construction variable interpolation on the strings that make up
the command line of builders before executing the command.
prefix.
Besides construction variables, scons provides the following
variables for each command execution:
-
.IP TARGET
The file name of the target being built, or the file name of the first
target if multiple targets are being built.
-
.IP TARGETS
-The file names of the targets being built.
-
+The file names of all targets being built.
.IP SOURCES
The file names of the sources of the build command.
-
.LP
-
For example, given the construction variable CC='cc', targets=['foo'], and
sources=['foo.c', 'bar.c']:
-
.IP
.nf
action='$CC -c -o $TARGET $SOURCES'
.PP
.fi
-
would produce the command line:
-
.IP
.nf
cc -c -o foo foo.c bar.c
.PP
.fi
-
Variable names may be surrounded by curly braces ({})
to separate the name from the trailing characters.
Within the curly braces, a variable name may have
a Python slice subscript appended to select one
or more items from a list.
In the previous example, the string:
-
.IP
.nf
${SOURCES[1]}
.PP
.fi
-
would produce:
-
.IP
.nf
bar.c
.PP
.fi
-
Additionally, a variable name may
have the following special
modifiers appended within the enclosing curly braces
.SH EXAMPLES
-To help you get started using SCons
-(in lieu of a complete user guide),
-here is a
-brief overview of how to perform some common tasks:
+To help you get started using SCons,
+here is a brief overview of some common tasks:
.SS Basic Compilation From a Single Source File
- Collect String, Dict, and List type-checking in common utility
routines so we can accept User{String,Dict,List}s all over.
+ - Put the Action factory and classes into their own module.
+
From Anthony Roach:
- Add a "duplicate" keyword argument to BuildDir() that can be set
SCons/__init__.py
+SCons/Action.py
SCons/Builder.py
SCons/Defaults.py
SCons/Environment.py
--- /dev/null
+"""engine.SCons.Action
+
+XXX
+
+"""
+
+#
+# Copyright (c) 2001 Steven Knight
+#
+# 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__"
+
+import os
+import os.path
+import string
+import sys
+
+import SCons.Util
+
+print_actions = 1;
+execute_actions = 1;
+
+exitvalmap = {
+ 2 : 127,
+ 13 : 126,
+}
+
+if os.name == 'posix':
+
+ def spawn(cmd, args, env):
+ pid = os.fork()
+ if not pid:
+ # Child process.
+ exitval = 127
+ try:
+ os.execvpe(cmd, args, env)
+ except OSError, e:
+ exitval = exitvalmap[e[0]]
+ sys.stderr.write("scons: %s: %s\n" % (cmd, e[1]))
+ os._exit(exitval)
+ else:
+ # Parent process.
+ pid, stat = os.waitpid(pid, 0)
+ ret = stat >> 8
+ return ret
+
+elif os.name == 'nt':
+
+ def pathsearch(cmd, env):
+ # In order to deal with the fact that 1.5.2 doesn't have
+ # os.spawnvpe(), roll our own PATH search.
+ if os.path.isabs(cmd):
+ if not os.path.exists(cmd):
+ exts = env['PATHEXT']
+ if not SCons.Util.is_List(exts):
+ exts = string.split(exts, os.pathsep)
+ for e in exts:
+ f = cmd + e
+ if os.path.exists(f):
+ return f
+ else:
+ path = env['PATH']
+ if not SCons.Util.is_List(path):
+ path = string.split(path, os.pathsep)
+ exts = env['PATHEXT']
+ if not SCons.Util.is_List(exts):
+ exts = string.split(exts, os.pathsep)
+ pairs = []
+ for dir in path:
+ for e in exts:
+ pairs.append((dir, e))
+ for dir, ext in pairs:
+ f = os.path.join(dir, cmd)
+ if not ext is None:
+ f = f + ext
+ if os.path.exists(f):
+ return f
+ return cmd
+
+ def spawn(cmd, args, env):
+ try:
+ try:
+ ret = os.spawnvpe(os.P_WAIT, cmd, args, env)
+ except AttributeError:
+ cmd = pathsearch(cmd, env)
+ ret = os.spawnve(os.P_WAIT, cmd, args, env)
+ except OSError, e:
+ ret = exitvalmap[e[0]]
+ sys.stderr.write("scons: %s: %s\n" % (cmd, e[1]))
+ return ret
+
+def Action(act):
+ """A factory for action objects."""
+ if isinstance(act, ActionBase):
+ return act
+ elif callable(act):
+ return FunctionAction(act)
+ elif SCons.Util.is_String(act):
+ return CommandAction(act)
+ elif SCons.Util.is_List(act):
+ return ListAction(act)
+ else:
+ return None
+
+class ActionBase:
+ """Base class for actions that create output objects."""
+ def __cmp__(self, other):
+ return cmp(self.__dict__, other.__dict__)
+
+ def show(self, string):
+ print string
+
+ def subst_dict(self, **kw):
+ """Create a dictionary for substitution of construction
+ variables.
+
+ This translates the following special arguments:
+
+ env - the construction environment itself,
+ the values of which (CC, CCFLAGS, etc.)
+ are copied straight into the dictionary
+
+ target - the target (object or array of objects),
+ used to generate the TARGET and TARGETS
+ construction variables
+
+ source - the source (object or array of objects),
+ used to generate the SOURCES construction
+ variable
+
+ Any other keyword arguments are copied into the
+ dictionary."""
+
+ dict = {}
+ if kw.has_key('env'):
+ dict.update(kw['env'])
+ del kw['env']
+
+ try:
+ cwd = kw['dir']
+ except:
+ cwd = None
+ else:
+ del kw['dir']
+
+ if kw.has_key('target'):
+ t = kw['target']
+ del kw['target']
+ if not SCons.Util.is_List(t):
+ t = [t]
+ try:
+ cwd = t[0].cwd
+ except AttributeError:
+ pass
+ dict['TARGETS'] = SCons.Util.PathList(map(os.path.normpath, map(str, t)))
+ if dict['TARGETS']:
+ dict['TARGET'] = dict['TARGETS'][0]
+
+ if kw.has_key('source'):
+ s = kw['source']
+ del kw['source']
+ if not SCons.Util.is_List(s):
+ s = [s]
+ dict['SOURCES'] = SCons.Util.PathList(map(os.path.normpath, map(str, s)))
+
+ dict.update(kw)
+
+ # Autogenerate necessary construction variables.
+ SCons.Util.autogenerate(dict, dir = cwd)
+
+ return dict
+
+class CommandAction(ActionBase):
+ """Class for command-execution actions."""
+ def __init__(self, string):
+ self.command = string
+
+ def execute(self, **kw):
+ import SCons.Util
+ dict = apply(self.subst_dict, (), kw)
+ cmd_list = SCons.Util.scons_subst_list(self.command, dict, {})
+ for cmd_line in cmd_list:
+ if len(cmd_line):
+ if print_actions:
+ self.show(string.join(cmd_line))
+ if execute_actions:
+ try:
+ ENV = kw['env']['ENV']
+ except:
+ import SCons.Defaults
+ ENV = SCons.Defaults.ConstructionEnvironment['ENV']
+ ret = spawn(cmd_line[0], cmd_line, ENV)
+ if ret:
+ return ret
+ return 0
+
+ def get_contents(self, **kw):
+ """Return the signature contents of this action's command line.
+
+ For signature purposes, it doesn't matter what targets or
+ sources we use, so long as we use the same ones every time
+ so the signature stays the same. We supply an array of two
+ of each to allow for distinction between TARGET and TARGETS.
+ """
+ kw['target'] = ['__t1__', '__t2__']
+ kw['source'] = ['__s1__', '__s2__']
+ dict = apply(self.subst_dict, (), kw)
+ return SCons.Util.scons_subst(self.command, dict, {})
+
+class FunctionAction(ActionBase):
+ """Class for Python function actions."""
+ def __init__(self, function):
+ self.function = function
+
+ def execute(self, **kw):
+ # if print_actions:
+ # XXX: WHAT SHOULD WE PRINT HERE?
+ if execute_actions:
+ if kw.has_key('target'):
+ if SCons.Util.is_List(kw['target']):
+ kw['target'] = map(str, kw['target'])
+ else:
+ kw['target'] = str(kw['target'])
+ if kw.has_key('source'):
+ kw['source'] = map(str, kw['source'])
+ return apply(self.function, (), kw)
+
+ def get_contents(self, **kw):
+ """Return the signature contents of this callable action.
+
+ By providing direct access to the code object of the
+ function, Python makes this extremely easy. Hooray!
+ """
+ #XXX DOES NOT ACCOUNT FOR CHANGES IN ENVIRONMENT VARIABLES
+ #THE FUNCTION MAY USE
+ try:
+ # "self.function" is a function.
+ code = self.function.func_code.co_code
+ except:
+ # "self.function" is a callable object.
+ code = self.function.__call__.im_func.func_code.co_code
+ return str(code)
+
+class ListAction(ActionBase):
+ """Class for lists of other actions."""
+ def __init__(self, list):
+ self.list = map(lambda x: Action(x), list)
+
+ def execute(self, **kw):
+ for l in self.list:
+ r = apply(l.execute, (), kw)
+ if r != 0:
+ return r
+ return 0
+
+ def get_contents(self, **kw):
+ """Return the signature contents of this action list.
+
+ Simple concatenation of the signatures of the elements.
+ """
+
+ return reduce(lambda x, y: x + str(y.get_contents()), self.list, "")
--- /dev/null
+#
+# Copyright (c) 2001 Steven Knight
+#
+# 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__ = "src/engine/SCons/ActionTests.py __REVISION__ __DATE__ __DEVELOPER__"
+
+# Define a null function for use as a builder action.
+# Where this is defined in the file seems to affect its
+# byte-code contents, so try to minimize changes by
+# defining it here, before we even import anything.
+def Func():
+ pass
+
+import unittest
+
+import sys
+import unittest
+
+import SCons.Action
+import TestCmd
+
+class ActionTestCase(unittest.TestCase):
+
+ def runTest(self):
+ """Test the Action factory
+ """
+ def foo():
+ pass
+ a1 = SCons.Action.Action(foo)
+ assert isinstance(a1, SCons.Action.FunctionAction)
+
+ a2 = SCons.Action.Action("string")
+ assert isinstance(a2, SCons.Action.CommandAction)
+
+ a3 = SCons.Action.Action(["x", a2, "y"])
+ assert isinstance(a3, SCons.Action.ListAction)
+
+ a4 = SCons.Action.Action(1)
+ assert a4 is None, a4
+
+ a5 = SCons.Action.Action(a1)
+ assert a5 is a1
+
+class ActionBaseTestCase(unittest.TestCase):
+
+ def test_cmp(self):
+ """Test Action comparison
+ """
+ a1 = SCons.Action.Action("x")
+ a2 = SCons.Action.Action("x")
+ assert a1 == a2
+ a3 = SCons.Action.Action("y")
+ assert a1 != a3
+ assert a2 != a3
+
+ def test_subst_dict(self):
+ """Test substituting dictionary values in an Action
+ """
+ a = SCons.Action.Action("x")
+
+ d = a.subst_dict(env = {'a' : 'A', 'b' : 'B'})
+ assert d['a'] == 'A', d
+ assert d['b'] == 'B', d
+
+ d = a.subst_dict(target = 't', source = 's')
+ assert str(d['TARGETS']) == 't', d['TARGETS']
+ assert str(d['TARGET']) == 't', d['TARGET']
+ assert str(d['SOURCES']) == 's', d['SOURCES']
+
+ d = a.subst_dict(target = ['t1', 't2'], source = ['s1', 's2'])
+ TARGETS = map(lambda x: str(x), d['TARGETS'])
+ TARGETS.sort()
+ assert TARGETS == ['t1', 't2'], d['TARGETS']
+ assert str(d['TARGET']) == 't1', d['TARGET']
+ SOURCES = map(lambda x: str(x), d['SOURCES'])
+ SOURCES.sort()
+ assert SOURCES == ['s1', 's2'], d['SOURCES']
+
+class CommandActionTestCase(unittest.TestCase):
+
+ def test_init(self):
+ """Test creation of a command Action
+ """
+ a = SCons.Action.CommandAction("xyzzy")
+ assert a.command == "xyzzy"
+
+ def test_execute(self):
+ """Test executing a command Action
+ """
+ pass
+
+ def test_get_contents(self):
+ """Test fetching the contents of a command Action
+ """
+ a = SCons.Action.CommandAction("| $foo | $bar |")
+ c = a.get_contents(foo = 'FFF', bar = 'BBB')
+ assert c == "| FFF | BBB |"
+
+class FunctionActionTestCase(unittest.TestCase):
+
+ def test_init(self):
+ """Test creation of a function Action
+ """
+ def func():
+ pass
+ a = SCons.Action.FunctionAction(func)
+ assert a.function == func
+
+ def test_execute(self):
+ """Test executing a function Action
+ """
+ self.inc = 0
+ def f(s):
+ s.inc = s.inc + 1
+ return 0
+ a = SCons.Action.FunctionAction(f)
+ a.execute(s = self)
+ assert self.inc == 1, self.inc
+
+ def test_get_contents(self):
+ """Test fetching the contents of a function Action
+ """
+ a = SCons.Action.FunctionAction(Func)
+ c = a.get_contents()
+ assert c == "\177\036\000\177\037\000d\000\000S", repr(c)
+
+class ListActionTestCase(unittest.TestCase):
+
+ def test_init(self):
+ """Test creation of a list of subsidiary Actions
+ """
+ def func():
+ pass
+ a = SCons.Action.ListAction(["x", func, ["y", "z"]])
+ assert isinstance(a.list[0], SCons.Action.CommandAction)
+ assert isinstance(a.list[1], SCons.Action.FunctionAction)
+ assert isinstance(a.list[2], SCons.Action.ListAction)
+ assert isinstance(a.list[2].list[0], SCons.Action.CommandAction)
+ assert isinstance(a.list[2].list[1], SCons.Action.CommandAction)
+
+ def test_execute(self):
+ """Test executing a list of subsidiary Actions
+ """
+ self.inc = 0
+ def f(s):
+ s.inc = s.inc + 1
+ return 0
+ a = SCons.Action.ListAction([f, f, f])
+ a.execute(s = self)
+ assert self.inc == 3, self.inc
+
+ def test_get_contents(self):
+ """Test fetching the contents of a list of subsidiary Actions
+ """
+ a = SCons.Action.ListAction(["x", "y", "z"])
+ c = a.get_contents()
+ assert c == "xyz", c
+
+
+if __name__ == "__main__":
+ suite = unittest.TestSuite()
+ suite.addTest(ActionTestCase())
+ suite.addTest(ActionBaseTestCase("test_cmp"))
+ suite.addTest(ActionBaseTestCase("test_subst_dict"))
+ for tclass in [CommandActionTestCase,
+ FunctionActionTestCase,
+ ListActionTestCase]:
+ for func in ["test_init", "test_execute", "test_get_contents"]:
+ suite.addTest(tclass(func))
+ if not unittest.TextTestRunner().run(suite).wasSuccessful():
+ sys.exit(1)
-import os
import os.path
import string
-import sys
-import types
from Errors import UserError
+import SCons.Action
import SCons.Node.FS
import SCons.Util
-exitvalmap = {
- 2 : 127,
- 13 : 126,
-}
-
-if os.name == 'posix':
-
- def spawn(cmd, args, env):
- pid = os.fork()
- if not pid:
- # Child process.
- exitval = 127
- try:
- os.execvpe(cmd, args, env)
- except OSError, e:
- exitval = exitvalmap[e[0]]
- sys.stderr.write("scons: %s: %s\n" % (cmd, e[1]))
- os._exit(exitval)
- else:
- # Parent process.
- pid, stat = os.waitpid(pid, 0)
- ret = stat >> 8
- return ret
-
-elif os.name == 'nt':
-
- def pathsearch(cmd, env):
- # In order to deal with the fact that 1.5.2 doesn't have
- # os.spawnvpe(), roll our own PATH search.
- if os.path.isabs(cmd):
- if not os.path.exists(cmd):
- exts = env['PATHEXT']
- if not SCons.Util.is_List(exts):
- exts = string.split(exts, os.pathsep)
- for e in exts:
- f = cmd + e
- if os.path.exists(f):
- return f
- else:
- path = env['PATH']
- if not SCons.Util.is_List(path):
- path = string.split(path, os.pathsep)
- exts = env['PATHEXT']
- if not SCons.Util.is_List(exts):
- exts = string.split(exts, os.pathsep)
- pairs = []
- for dir in path:
- for e in exts:
- pairs.append((dir, e))
- for dir, ext in pairs:
- f = os.path.join(dir, cmd)
- if not ext is None:
- f = f + ext
- if os.path.exists(f):
- return f
- return cmd
-
- def spawn(cmd, args, env):
- try:
- try:
- ret = os.spawnvpe(os.P_WAIT, cmd, args, env)
- except AttributeError:
- cmd = pathsearch(cmd, env)
- ret = os.spawnve(os.P_WAIT, cmd, args, env)
- except OSError, e:
- ret = exitvalmap[e[0]]
- sys.stderr.write("scons: %s: %s\n" % (cmd, e[1]))
- return ret
-
def Builder(**kw):
node_factory = SCons.Node.FS.default_fs.File,
scanner = None):
self.name = name
- self.action = Action(action)
+ self.action = SCons.Action.Action(action)
self.prefix = prefix
self.suffix = suffix
return reduce(lambda x, y: x + y,
map(lambda b: b.src_suffixes(),
self.builder_dict.values()))
-
-print_actions = 1;
-execute_actions = 1;
-
-def Action(act):
- """A factory for action objects."""
- if callable(act):
- return FunctionAction(act)
- elif SCons.Util.is_String(act):
- return CommandAction(act)
- elif SCons.Util.is_List(act):
- return ListAction(act)
- else:
- return None
-
-class ActionBase:
- """Base class for actions that create output objects.
-
- We currently expect Actions will only be accessible through
- Builder objects, so they don't yet merit their own module."""
- def __cmp__(self, other):
- return cmp(self.__dict__, other.__dict__)
-
- def show(self, string):
- print string
-
- def subst_dict(self, **kw):
- """Create a dictionary for substitution of construction
- variables.
-
- This translates the following special arguments:
-
- env - the construction environment itself,
- the values of which (CC, CCFLAGS, etc.)
- are copied straight into the dictionary
-
- target - the target (object or array of objects),
- used to generate the TARGET and TARGETS
- construction variables
-
- source - the source (object or array of objects),
- used to generate the SOURCES construction
- variable
-
- Any other keyword arguments are copied into the
- dictionary."""
-
- dict = {}
- if kw.has_key('env'):
- dict.update(kw['env'])
- del kw['env']
-
- try:
- cwd = kw['dir']
- except:
- cwd = None
- else:
- del kw['dir']
-
- if kw.has_key('target'):
- t = kw['target']
- del kw['target']
- if not SCons.Util.is_List(t):
- t = [t]
- try:
- cwd = t[0].cwd
- except AttributeError:
- pass
- dict['TARGETS'] = SCons.Util.PathList(map(os.path.normpath, map(str, t)))
- if dict['TARGETS']:
- dict['TARGET'] = dict['TARGETS'][0]
-
- if kw.has_key('source'):
- s = kw['source']
- del kw['source']
- if not SCons.Util.is_List(s):
- s = [s]
- dict['SOURCES'] = SCons.Util.PathList(map(os.path.normpath, map(str, s)))
-
- dict.update(kw)
-
- # Autogenerate necessary construction variables.
- SCons.Util.autogenerate(dict, dir = cwd)
-
- return dict
-
-class CommandAction(ActionBase):
- """Class for command-execution actions."""
- def __init__(self, string):
- self.command = string
-
- def execute(self, **kw):
- import SCons.Util
- dict = apply(self.subst_dict, (), kw)
- cmd_list = SCons.Util.scons_subst_list(self.command, dict, {})
- for cmd_line in cmd_list:
- if len(cmd_line):
- if print_actions:
- self.show(string.join(cmd_line))
- if execute_actions:
- try:
- ENV = kw['env']['ENV']
- except:
- import SCons.Defaults
- ENV = SCons.Defaults.ConstructionEnvironment['ENV']
- ret = spawn(cmd_line[0], cmd_line, ENV)
- if ret:
- return ret
- return 0
-
- def get_contents(self, **kw):
- """Return the signature contents of this action's command line.
-
- For signature purposes, it doesn't matter what targets or
- sources we use, so long as we use the same ones every time
- so the signature stays the same. We supply an array of two
- of each to allow for distinction between TARGET and TARGETS.
- """
- kw['target'] = ['__t1__', '__t2__']
- kw['source'] = ['__s1__', '__s2__']
- dict = apply(self.subst_dict, (), kw)
- return SCons.Util.scons_subst(self.command, dict, {})
-
-class FunctionAction(ActionBase):
- """Class for Python function actions."""
- def __init__(self, function):
- self.function = function
-
- def execute(self, **kw):
- # if print_actions:
- # XXX: WHAT SHOULD WE PRINT HERE?
- if execute_actions:
- if kw.has_key('target'):
- if SCons.Util.is_List(kw['target']):
- kw['target'] = map(str, kw['target'])
- else:
- kw['target'] = str(kw['target'])
- if kw.has_key('source'):
- kw['source'] = map(str, kw['source'])
- return apply(self.function, (), kw)
-
- def get_contents(self, **kw):
- """Return the signature contents of this callable action.
-
- By providing direct access to the code object of the
- function, Python makes this extremely easy. Hooray!
- """
- #XXX DOES NOT ACCOUNT FOR CHANGES IN ENVIRONMENT VARIABLES
- #THE FUNCTION MAY USE
- try:
- # "self.function" is a function.
- code = self.function.func_code.co_code
- except:
- # "self.function" is a callable object.
- code = self.function.__call__.im_func.func_code.co_code
- return str(code)
-
-class ListAction(ActionBase):
- """Class for lists of other actions."""
- def __init__(self, list):
- self.list = map(lambda x: Action(x), list)
-
- def execute(self, **kw):
- for l in self.list:
- r = apply(l.execute, (), kw)
- if r != 0:
- return r
- return 0
-
- def get_contents(self, **kw):
- """Return the signature contents of this action list.
-
- Simple concatenation of the signatures of the elements.
- """
-
- return reduce(lambda x, y: x + str(y.get_contents()), self.list, "")
help = "Don't build; list files and where defined.")
def opt_n(opt, arg):
- SCons.Builder.execute_actions = None
+ SCons.Action.execute_actions = None
Option(func = opt_n,
short = 'n', long = ['no-exec', 'just-print', 'dry-run', 'recon'],
help = "Build dependencies in random order.")
def opt_s(opt, arg):
- SCons.Builder.print_actions = None
+ SCons.Action.print_actions = None
Option(func = opt_s,
short = 's', long = ['silent', 'quiet'],