diff options
author | Steven Knight <knight@baldmt.com> | 2005-04-26 04:14:40 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2005-04-26 04:14:40 (GMT) |
commit | 5673cd1804e24700a0216bda0f426afeb678881a (patch) | |
tree | 4469aa200175c39f9d91eb1f655997a2aa87ced5 /src/engine | |
parent | 561e09d2d6cbda130f2af848b6ff22da1694c5e7 (diff) | |
download | SCons-5673cd1804e24700a0216bda0f426afeb678881a.zip SCons-5673cd1804e24700a0216bda0f426afeb678881a.tar.gz SCons-5673cd1804e24700a0216bda0f426afeb678881a.tar.bz2 |
More flexible (and Make-like) ignoring command exit status, and suppressing printing of a command.
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/SCons/Action.py | 49 | ||||
-rw-r--r-- | src/engine/SCons/ActionTests.py | 83 | ||||
-rw-r--r-- | src/engine/SCons/Executor.py | 10 | ||||
-rw-r--r-- | src/engine/SCons/Node/__init__.py | 8 |
4 files changed, 122 insertions, 28 deletions
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 3b0230c..353ead3 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -124,6 +124,9 @@ def rfile(n): except AttributeError: return n +def default_exitstatfunc(s): + return s + def _actionAppend(act1, act2): # This function knows how to slap two actions together. # Mainly, it handles ListActions by concatenating into @@ -245,19 +248,22 @@ if not SCons.Memoize.has_metaclass: class _ActionAction(ActionBase): """Base class for actions that create output objects.""" - def __init__(self, strfunction=_null, presub=_null, chdir=None, **kw): + def __init__(self, strfunction=_null, presub=_null, chdir=None, exitstatfunc=None, **kw): if not strfunction is _null: self.strfunction = strfunction if presub is _null: presub = print_actions_presub self.presub = presub self.chdir = chdir + if not exitstatfunc: + exitstatfunc = default_exitstatfunc + self.exitstatfunc = exitstatfunc def print_cmd_line(self, s, target, source, env): sys.stdout.write(s + "\n") def __call__(self, target, source, env, - errfunc=None, + exitstatfunc=_null, presub=_null, show=_null, execute=_null, @@ -266,6 +272,7 @@ class _ActionAction(ActionBase): target = [target] if not SCons.Util.is_List(source): source = [source] + if exitstatfunc is _null: exitstatfunc = self.exitstatfunc if presub is _null: presub = self.presub if show is _null: show = print_actions if execute is _null: execute = execute_actions @@ -304,8 +311,7 @@ class _ActionAction(ActionBase): os.chdir(chdir) try: stat = self.execute(target, source, env) - if stat and errfunc: - errfunc(stat) + stat = exitstatfunc(stat) finally: if save_cwd: os.chdir(save_cwd) @@ -350,12 +356,32 @@ class CommandAction(_ActionAction): return string.join(map(str, self.cmd_list), ' ') return str(self.cmd_list) + def process(self, target, source, env): + result = env.subst_list(self.cmd_list, 0, target, source) + silent = None + ignore = None + while 1: + try: c = result[0][0][0] + except IndexError: c = None + if c == '@': silent = 1 + elif c == '-': ignore = 1 + else: break + result[0][0] = result[0][0][1:] + try: + if not result[0][0]: + result[0] = result[0][1:] + except IndexError: + pass + return result, ignore, silent + def strfunction(self, target, source, env): if not self.cmdstr is None: c = env.subst(self.cmdstr, 0, target, source) if c: return c - cmd_list = env.subst_list(self.cmd_list, 0, target, source) + cmd_list, ignore, silent = self.process(target, source, env) + if silent: + return '' return _string_from_cmd_list(cmd_list[0]) def execute(self, target, source, env): @@ -406,15 +432,14 @@ class CommandAction(_ActionAction): # reasonable for just about everything else: ENV[key] = str(value) - cmd_list = env.subst_list(self.cmd_list, 0, target, - map(rfile, source)) + cmd_list, ignore, silent = self.process(target, map(rfile, source), env) # Use len() to filter out any "command" that's zero-length. for cmd_line in filter(len, cmd_list): # Escape the command line for the interpreter we are using. cmd_line = escape_list(cmd_line, escape) result = spawn(shell, escape, cmd_line[0], cmd_line, ENV) - if result: + if not ignore and result: return result return 0 @@ -461,10 +486,10 @@ class CommandGeneratorAction(ActionBase): def genstring(self, target, source, env): return self._generate(target, source, env, 1).genstring(target, source, env) - def __call__(self, target, source, env, errfunc=None, presub=_null, + def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, show=_null, execute=_null, chdir=_null): act = self._generate(target, source, env, 0) - return act(target, source, env, errfunc, presub, + return act(target, source, env, exitstatfunc, presub, show, execute, chdir) def get_contents(self, target, source, env): @@ -650,10 +675,10 @@ class ListAction(ActionBase): self.list), "") - def __call__(self, target, source, env, errfunc=None, presub=_null, + def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, show=_null, execute=_null, chdir=_null): for act in self.list: - stat = act(target, source, env, errfunc, presub, + stat = act(target, source, env, exitstatfunc, presub, show, execute, chdir) if stat: return stat diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 3790c8c..890abb2 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -58,7 +58,8 @@ import TestCmd # for each test, they can just use the one. test = TestCmd.TestCmd(workdir = '') -test.write('act.py', """import os, string, sys +test.write('act.py', """\ +import os, string, sys f = open(sys.argv[1], 'w') f.write("act.py: '" + string.join(sys.argv[2:], "' '") + "'\\n") try: @@ -81,7 +82,13 @@ if os.environ.has_key( 'ACTPY_PIPE' ): sys.exit(0) """) +test.write('exit.py', """\ +import sys +sys.exit(int(sys.argv[1])) +""") + act_py = test.workpath('act.py') +exit_py = test.workpath('exit.py') outfile = test.workpath('outfile') outfile2 = test.workpath('outfile2') @@ -319,7 +326,6 @@ class ActionBaseTestCase(unittest.TestCase): pass class _ActionActionTestCase(unittest.TestCase): - def test__init__(self): """Test creation of _ActionAction objects @@ -527,18 +533,19 @@ class _ActionActionTestCase(unittest.TestCase): assert s == '', s sys.stdout = save_stdout - errfunc_result = [] + exitstatfunc_result = [] - def errfunc(stat, result=errfunc_result): + def exitstatfunc(stat, result=exitstatfunc_result): result.append(stat) + return stat - result = a("out", "in", env, errfunc=errfunc) + result = a("out", "in", env, exitstatfunc=exitstatfunc) assert result == 0, result - assert errfunc_result == [], errfunc_result + assert exitstatfunc_result == [], exitstatfunc_result - result = a("out", "in", env, execute=1, errfunc=errfunc) + result = a("out", "in", env, execute=1, exitstatfunc=exitstatfunc) assert result == 7, result - assert errfunc_result == [7], errfunc_result + assert exitstatfunc_result == [7], exitstatfunc_result SCons.Action.execute_actions = 1 @@ -830,6 +837,38 @@ class CommandActionTestCase(unittest.TestCase): s = act4.strfunction([t1], [s1], env) assert s is None, s + act = SCons.Action.CommandAction("@foo bar") + s = act.strfunction([], [], env) + assert s == "", s + + act = SCons.Action.CommandAction("@-foo bar") + s = act.strfunction([], [], env) + assert s == "", s + + act = SCons.Action.CommandAction("-@foo bar") + s = act.strfunction([], [], env) + assert s == "", s + + act = SCons.Action.CommandAction("-foo bar") + s = act.strfunction([], [], env) + assert s == "foo bar", s + + act = SCons.Action.CommandAction("@ foo bar") + s = act.strfunction([], [], env) + assert s == "", s + + act = SCons.Action.CommandAction("@- foo bar") + s = act.strfunction([], [], env) + assert s == "", s + + act = SCons.Action.CommandAction("-@ foo bar") + s = act.strfunction([], [], env) + assert s == "", s + + act = SCons.Action.CommandAction("- foo bar") + s = act.strfunction([], [], env) + assert s == "foo bar", s + def test_execute(self): """Test execution of command Actions @@ -952,6 +991,34 @@ class CommandActionTestCase(unittest.TestCase): r = act([], [], env.Copy(out = outfile)) assert r == expect_nonexecutable, "r == %d" % r + act = SCons.Action.CommandAction('%s %s 1' % (python, exit_py)) + r = act([], [], env) + assert r == 1, r + + act = SCons.Action.CommandAction('@%s %s 1' % (python, exit_py)) + r = act([], [], env) + assert r == 1, r + + act = SCons.Action.CommandAction('@-%s %s 1' % (python, exit_py)) + r = act([], [], env) + assert r == 0, r + + act = SCons.Action.CommandAction('-%s %s 1' % (python, exit_py)) + r = act([], [], env) + assert r == 0, r + + act = SCons.Action.CommandAction('@ %s %s 1' % (python, exit_py)) + r = act([], [], env) + assert r == 1, r + + act = SCons.Action.CommandAction('@- %s %s 1' % (python, exit_py)) + r = act([], [], env) + assert r == 0, r + + act = SCons.Action.CommandAction('- %s %s 1' % (python, exit_py)) + r = act([], [], env) + assert r == 0, r + def _DO_NOT_EXECUTE_test_pipe_execute(self): """Test capturing piped output from an action diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index afe817a..afd6c49 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -93,21 +93,21 @@ class Executor: result.update(kw) return result - def do_nothing(self, target, errfunc, kw): + def do_nothing(self, target, exitstatfunc, kw): pass - def do_execute(self, target, errfunc, kw): + def do_execute(self, target, exitstatfunc, kw): """Actually execute the action list.""" apply(self.action, - (self.targets, self.sources, self.get_build_env(), errfunc), + (self.targets, self.sources, self.get_build_env(), exitstatfunc), self.get_kw(kw)) # use extra indirection because with new-style objects (Python 2.2 # and above) we can't override special methods, and nullify() needs # to be able to do this. - def __call__(self, target, errfunc, **kw): - self.do_execute(target, errfunc, kw) + def __call__(self, target, exitstatfunc, **kw): + self.do_execute(target, exitstatfunc, kw) def cleanup(self): "__reset_cache__" diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 28f1c19..f9390ea 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -227,10 +227,12 @@ class Node: so only do thread safe stuff here. Do thread unsafe stuff in built(). """ - def errfunc(stat, node=self): - raise SCons.Errors.BuildError(node=node, errstr="Error %d" % stat) + def exitstatfunc(stat, node=self): + if stat: + msg = "Error %d" % stat + raise SCons.Errors.BuildError(node=node, errstr=msg) executor = self.get_executor() - apply(executor, (self, errfunc), kw) + apply(executor, (self, exitstatfunc), kw) def built(self): """Called just after this node is successfully built.""" |