diff options
Diffstat (limited to 'src/engine/SCons/Action.py')
-rw-r--r-- | src/engine/SCons/Action.py | 125 |
1 files changed, 66 insertions, 59 deletions
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 3d52142..38b5413 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -38,6 +38,7 @@ import sys import UserDict import SCons.Util +import SCons.Errors print_actions = 1; execute_actions = 1; @@ -171,28 +172,53 @@ def GetCommandHandler(): class CommandGenerator: """ - Wrappes a command generator function so the Action() factory + Wraps a command generator function so the Action() factory function can tell a generator function from a function action. """ def __init__(self, generator): self.generator = generator +def _do_create_action(act): + """This is the actual "implementation" for the + Action factory method, below. This handles the + fact that passing lists to Action() itself has + different semantics than passing lists as elements + of lists. + + The former will create a ListAction, the latter + will create a CommandAction by converting the inner + list elements to strings.""" -def Action(act): - """A factory for action objects.""" if isinstance(act, ActionBase): return act + elif SCons.Util.is_List(act): + return CommandAction(act) elif isinstance(act, CommandGenerator): return CommandGeneratorAction(act.generator) elif callable(act): return FunctionAction(act) elif SCons.Util.is_String(act): - return CommandAction(act) - elif SCons.Util.is_List(act): - return ListAction(act) + listCmds = map(lambda x: CommandAction(string.split(x)), + string.split(act, '\n')) + if len(listCmds) == 1: + return listCmds[0] + else: + return ListAction(listCmds) else: return None +def Action(act): + """A factory for action objects.""" + if SCons.Util.is_List(act): + acts = filter(lambda x: not x is None, + map(_do_create_action, act)) + if len(acts) == 1: + return acts[0] + else: + return ListAction(acts) + else: + return _do_create_action(act) + class ActionBase: """Base class for actions that create output objects.""" def __cmp__(self, other): @@ -241,7 +267,7 @@ class ActionBase: t = [t] try: cwd = t[0].cwd - except AttributeError: + except (IndexError, AttributeError): pass dict['TARGETS'] = SCons.Util.PathList(map(os.path.normpath, map(str, t))) if dict['TARGETS']: @@ -260,6 +286,16 @@ class ActionBase: return dict +def _string_from_cmd_list(cmd_list): + """Takes a list of command line arguments and returns a pretty + representation for printing.""" + cl = [] + for arg in cmd_list: + if ' ' in arg or '\t' in arg: + arg = '"' + arg + '"' + cl.append(arg) + return string.join(cl) + _rm = re.compile(r'\$[()]') _remove = re.compile(r'\$\(([^\$]|\$[^\(])*?\$\)') @@ -286,22 +322,19 @@ class EnvDictProxy(UserDict.UserDict): class CommandAction(ActionBase): """Class for command-execution actions.""" - def __init__(self, string): - self.command = string + def __init__(self, cmd): + import SCons.Util + + self.cmd_list = map(SCons.Util.to_String, cmd) def execute(self, **kw): dict = apply(self.subst_dict, (), kw) import SCons.Util - cmd_list = SCons.Util.scons_subst_list(self.command, dict, {}, _rm) + cmd_list = SCons.Util.scons_subst_list(self.cmd_list, dict, {}, _rm) for cmd_line in cmd_list: if len(cmd_line): if print_actions: - cl = [] - for arg in cmd_line: - if ' ' in arg or '\t' in arg: - arg = '"' + arg + '"' - cl.append(arg) - self.show(string.join(cl)) + self.show(_string_from_cmd_list(cmd_line)) if execute_actions: try: ENV = kw['env']['ENV'] @@ -328,7 +361,8 @@ class CommandAction(ActionBase): def get_raw_contents(self, **kw): """Return the complete contents of this action's command line. """ - return SCons.Util.scons_subst(self.command, self._sig_dict(kw), {}) + return SCons.Util.scons_subst(string.join(self.cmd_list), + self._sig_dict(kw), {}) def get_contents(self, **kw): """Return the signature contents of this action's command line. @@ -336,19 +370,16 @@ class CommandAction(ActionBase): This strips $(-$) and everything in between the string, since those parts don't affect signatures. """ - return SCons.Util.scons_subst(self.command, self._sig_dict(kw), {}, _remove) + return SCons.Util.scons_subst(string.join(self.cmd_list), + self._sig_dict(kw), {}, _remove) class CommandGeneratorAction(ActionBase): """Class for command-generator actions.""" def __init__(self, generator): self.generator = generator - def execute(self, **kw): - # ensure that target is a list, to make it easier to write - # generator functions: + def __generate(self, kw): import SCons.Util - if kw.has_key("target") and not SCons.Util.is_List(kw["target"]): - kw["target"] = [kw["target"]] # Wrap the environment dictionary in an EnvDictProxy # object to make variable interpolation easier for the @@ -357,36 +388,19 @@ class CommandGeneratorAction(ActionBase): if args.has_key("env") and not isinstance(args["env"], EnvDictProxy): args["env"] = EnvDictProxy(args["env"]) - gen_list = apply(self.generator, (), args) - gen_list = map(lambda x: map(str, x), gen_list) + # ensure that target is a list, to make it easier to write + # generator functions: + if args.has_key("target") and not SCons.Util.is_List(args["target"]): + args["target"] = [args["target"]] - # Do environment variable substitution on returned command list - dict = apply(self.subst_dict, (), kw) - cmd_list = [ ] - for gen_line in gen_list: - cmd_list.append([]) - curr_line = cmd_list[-1] - for gen_arg in gen_line: - arg_list = SCons.Util.scons_subst_list(gen_arg, dict, {}) - curr_line.extend(arg_list[0]) - if(len(arg_list) > 1): - cmd_list.extend(arg_list[1:]) - curr_line = cmd_list[-1] - - for cmd_line in filter(lambda x: x, cmd_list): - if print_actions: - self.show(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 + ret = apply(self.generator, (), args) + gen_cmd = Action(ret) + if not gen_cmd: + raise SCons.Errors.UserError("Object returned from command generator: %s cannot be used to create an Action." % repr(ret)) + return gen_cmd - return 0 + def execute(self, **kw): + return apply(self.__generate(kw).execute, (), kw) def get_contents(self, **kw): """Return the signature contents of this action's command line. @@ -394,14 +408,7 @@ class CommandGeneratorAction(ActionBase): This strips $(-$) and everything in between the string, since those parts don't affect signatures. """ - kw['source'] = ["__s1__", "__s2__"] - kw['target'] = ["__t1__", "__t2__"] - cmd_list = apply(self.generator, (), kw) - cmd_list = map(lambda x: map(str, x), cmd_list) - cmd_list = map(lambda x: string.join(x, "\0"), cmd_list) - cmd_list = map(lambda x: _remove.sub('', x), cmd_list) - cmd_list = map(lambda x: filter(lambda y: y, string.split(x, "\0")), cmd_list) - return cmd_list + return apply(self.__generate(kw).get_contents, (), kw) class FunctionAction(ActionBase): """Class for Python function actions.""" |