Issue 2228: discard stderr by using os.devnull
[scons.git] / src / engine / SCons / Action.py
1 """SCons.Action
2
3 This encapsulates information about executing any sort of action that
4 can build one or more target Nodes (typically files) from one or more
5 source Nodes (also typically files) given a specific Environment.
6
7 The base class here is ActionBase.  The base class supplies just a few
8 OO utility methods and some generic methods for displaying information
9 about an Action in response to the various commands that control printing.
10
11 A second-level base class is _ActionAction.  This extends ActionBase
12 by providing the methods that can be used to show and perform an
13 action.  True Action objects will subclass _ActionAction; Action
14 factory class objects will subclass ActionBase.
15
16 The heavy lifting is handled by subclasses for the different types of
17 actions we might execute:
18
19     CommandAction
20     CommandGeneratorAction
21     FunctionAction
22     ListAction
23
24 The subclasses supply the following public interface methods used by
25 other modules:
26
27     __call__()
28         THE public interface, "calling" an Action object executes the
29         command or Python function.  This also takes care of printing
30         a pre-substitution command for debugging purposes.
31
32     get_contents()
33         Fetches the "contents" of an Action for signature calculation
34         plus the varlist.  This is what gets MD5 checksummed to decide
35         if a target needs to be rebuilt because its action changed.
36
37     genstring()
38         Returns a string representation of the Action *without*
39         command substitution, but allows a CommandGeneratorAction to
40         generate the right action based on the specified target,
41         source and env.  This is used by the Signature subsystem
42         (through the Executor) to obtain an (imprecise) representation
43         of the Action operation for informative purposes.
44
45
46 Subclasses also supply the following methods for internal use within
47 this module:
48
49     __str__()
50         Returns a string approximation of the Action; no variable
51         substitution is performed.
52
53     execute()
54         The internal method that really, truly, actually handles the
55         execution of a command or Python function.  This is used so
56         that the __call__() methods can take care of displaying any
57         pre-substitution representations, and *then* execute an action
58         without worrying about the specific Actions involved.
59
60     get_presig()
61         Fetches the "contents" of a subclass for signature calculation.
62         The varlist is added to this to produce the Action's contents.
63
64     strfunction()
65         Returns a substituted string representation of the Action.
66         This is used by the _ActionAction.show() command to display the
67         command/function that will be executed to generate the target(s).
68
69 There is a related independent ActionCaller class that looks like a
70 regular Action, and which serves as a wrapper for arbitrary functions
71 that we want to let the user specify the arguments to now, but actually
72 execute later (when an out-of-date check determines that it's needed to
73 be executed, for example).  Objects of this class are returned by an
74 ActionFactory class that provides a __call__() method as a convenient
75 way for wrapping up the functions.
76
77 """
78
79 # __COPYRIGHT__
80 #
81 # Permission is hereby granted, free of charge, to any person obtaining
82 # a copy of this software and associated documentation files (the
83 # "Software"), to deal in the Software without restriction, including
84 # without limitation the rights to use, copy, modify, merge, publish,
85 # distribute, sublicense, and/or sell copies of the Software, and to
86 # permit persons to whom the Software is furnished to do so, subject to
87 # the following conditions:
88 #
89 # The above copyright notice and this permission notice shall be included
90 # in all copies or substantial portions of the Software.
91 #
92 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
93 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
94 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
95 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
96 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
97 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
98 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
99
100 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
101
102 import cPickle
103 import dis
104 import os
105 import string
106 import sys
107 import subprocess
108
109 from SCons.Debug import logInstanceCreation
110 import SCons.Errors
111 import SCons.Executor
112 import SCons.Util
113 import SCons.Subst
114
115 # we use these a lot, so try to optimize them
116 is_String = SCons.Util.is_String
117 is_List = SCons.Util.is_List
118
119 class _null:
120     pass
121
122 print_actions = 1
123 execute_actions = 1
124 print_actions_presub = 0
125
126 def rfile(n):
127     try:
128         return n.rfile()
129     except AttributeError:
130         return n
131
132 def default_exitstatfunc(s):
133     return s
134
135 try:
136     SET_LINENO = dis.SET_LINENO
137     HAVE_ARGUMENT = dis.HAVE_ARGUMENT
138 except AttributeError:
139     remove_set_lineno_codes = lambda x: x
140 else:
141     def remove_set_lineno_codes(code):
142         result = []
143         n = len(code)
144         i = 0
145         while i < n:
146             c = code[i]
147             op = ord(c)
148             if op >= HAVE_ARGUMENT:
149                 if op != SET_LINENO:
150                     result.append(code[i:i+3])
151                 i = i+3
152             else:
153                 result.append(c)
154                 i = i+1
155         return string.join(result, '')
156
157
158 def _callable_contents(obj):
159     """Return the signature contents of a callable Python object.
160     """
161     try:
162         # Test if obj is a method.
163         return _function_contents(obj.im_func)
164
165     except AttributeError:
166         try:
167             # Test if obj is a callable object.
168             return _function_contents(obj.__call__.im_func)
169
170         except AttributeError:
171             try:
172                 # Test if obj is a code object.
173                 return _code_contents(obj)
174
175             except AttributeError:
176                     # Test if obj is a function object.
177                     return _function_contents(obj)
178
179
180 def _object_contents(obj):
181     """Return the signature contents of any Python object.
182
183     We have to handle the case where object contains a code object
184     since it can be pickled directly.
185     """
186     try:
187         # Test if obj is a method.
188         return _function_contents(obj.im_func)
189
190     except AttributeError:
191         try:
192             # Test if obj is a callable object.
193             return _function_contents(obj.__call__.im_func)
194
195         except AttributeError:
196             try:
197                 # Test if obj is a code object.
198                 return _code_contents(obj)
199
200             except AttributeError:
201                 try:
202                     # Test if obj is a function object.
203                     return _function_contents(obj)
204
205                 except AttributeError:
206                     # Should be a pickable Python object.
207                     try:
208                         return cPickle.dumps(obj)
209                     except (cPickle.PicklingError, TypeError):
210                         # This is weird, but it seems that nested classes
211                         # are unpickable. The Python docs say it should
212                         # always be a PicklingError, but some Python
213                         # versions seem to return TypeError.  Just do
214                         # the best we can.
215                         return str(obj)
216
217
218 def _code_contents(code):
219     """Return the signature contents of a code object.
220
221     By providing direct access to the code object of the
222     function, Python makes this extremely easy.  Hooray!
223
224     Unfortunately, older versions of Python include line
225     number indications in the compiled byte code.  Boo!
226     So we remove the line number byte codes to prevent
227     recompilations from moving a Python function.
228     """
229
230     contents = []
231
232     # The code contents depends on the number of local variables
233     # but not their actual names.
234     contents.append("%s,%s" % (code.co_argcount, len(code.co_varnames)))
235     try:
236         contents.append(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars)))
237     except AttributeError:
238         # Older versions of Python do not support closures.
239         contents.append(",0,0")
240
241     # The code contents depends on any constants accessed by the
242     # function. Note that we have to call _object_contents on each
243     # constants because the code object of nested functions can
244     # show-up among the constants.
245     #
246     # Note that we also always ignore the first entry of co_consts
247     # which contains the function doc string. We assume that the
248     # function does not access its doc string.
249     contents.append(',(' + string.join(map(_object_contents,code.co_consts[1:]),',') + ')')
250
251     # The code contents depends on the variable names used to
252     # accessed global variable, as changing the variable name changes
253     # the variable actually accessed and therefore changes the
254     # function result.
255     contents.append(',(' + string.join(map(_object_contents,code.co_names),',') + ')')
256
257
258     # The code contents depends on its actual code!!!
259     contents.append(',(' + str(remove_set_lineno_codes(code.co_code)) + ')')
260
261     return string.join(contents, '')
262
263
264 def _function_contents(func):
265     """Return the signature contents of a function."""
266
267     contents = [_code_contents(func.func_code)]
268
269     # The function contents depends on the value of defaults arguments
270     if func.func_defaults:
271         contents.append(',(' + string.join(map(_object_contents,func.func_defaults),',') + ')')
272     else:
273         contents.append(',()')
274
275     # The function contents depends on the closure captured cell values.
276     try:
277         closure = func.func_closure or []
278     except AttributeError:
279         # Older versions of Python do not support closures.
280         closure = []
281
282     #xxx = [_object_contents(x.cell_contents) for x in closure]
283     try:
284         xxx = map(lambda x: _object_contents(x.cell_contents), closure)
285     except AttributeError:
286         xxx = []
287     contents.append(',(' + string.join(xxx, ',') + ')')
288
289     return string.join(contents, '')
290
291
292 def _actionAppend(act1, act2):
293     # This function knows how to slap two actions together.
294     # Mainly, it handles ListActions by concatenating into
295     # a single ListAction.
296     a1 = Action(act1)
297     a2 = Action(act2)
298     if a1 is None or a2 is None:
299         raise TypeError, "Cannot append %s to %s" % (type(act1), type(act2))
300     if isinstance(a1, ListAction):
301         if isinstance(a2, ListAction):
302             return ListAction(a1.list + a2.list)
303         else:
304             return ListAction(a1.list + [ a2 ])
305     else:
306         if isinstance(a2, ListAction):
307             return ListAction([ a1 ] + a2.list)
308         else:
309             return ListAction([ a1, a2 ])
310
311 def _do_create_keywords(args, kw):
312     """This converts any arguments after the action argument into
313     their equivalent keywords and adds them to the kw argument.
314     """
315     v = kw.get('varlist', ())
316     # prevent varlist="FOO" from being interpreted as ['F', 'O', 'O']
317     if is_String(v): v = (v,)
318     kw['varlist'] = tuple(v)
319     if args:
320         # turn positional args into equivalent keywords
321         cmdstrfunc = args[0]
322         if cmdstrfunc is None or is_String(cmdstrfunc):
323             kw['cmdstr'] = cmdstrfunc
324         elif callable(cmdstrfunc):
325             kw['strfunction'] = cmdstrfunc
326         else:
327             raise SCons.Errors.UserError(
328                 'Invalid command display variable type. '
329                 'You must either pass a string or a callback which '
330                 'accepts (target, source, env) as parameters.')
331         if len(args) > 1:
332             kw['varlist'] = args[1:] + kw['varlist']
333     if kw.get('strfunction', _null) is not _null \
334                       and kw.get('cmdstr', _null) is not _null:
335         raise SCons.Errors.UserError(
336             'Cannot have both strfunction and cmdstr args to Action()')
337
338 def _do_create_action(act, kw):
339     """This is the actual "implementation" for the
340     Action factory method, below.  This handles the
341     fact that passing lists to Action() itself has
342     different semantics than passing lists as elements
343     of lists.
344
345     The former will create a ListAction, the latter
346     will create a CommandAction by converting the inner
347     list elements to strings."""
348
349     if isinstance(act, ActionBase):
350         return act
351
352     if is_List(act):
353         #TODO(1.5) return CommandAction(act, **kw)
354         return apply(CommandAction, (act,), kw)
355
356     if callable(act):
357         try:
358             gen = kw['generator']
359             del kw['generator']
360         except KeyError:
361             gen = 0
362         if gen:
363             action_type = CommandGeneratorAction
364         else:
365             action_type = FunctionAction
366         return action_type(act, kw)
367
368     if is_String(act):
369         var=SCons.Util.get_environment_var(act)
370         if var:
371             # This looks like a string that is purely an Environment
372             # variable reference, like "$FOO" or "${FOO}".  We do
373             # something special here...we lazily evaluate the contents
374             # of that Environment variable, so a user could put something
375             # like a function or a CommandGenerator in that variable
376             # instead of a string.
377             return LazyAction(var, kw)
378         commands = string.split(str(act), '\n')
379         if len(commands) == 1:
380             #TODO(1.5) return CommandAction(commands[0], **kw)
381             return apply(CommandAction, (commands[0],), kw)
382         # The list of string commands may include a LazyAction, so we
383         # reprocess them via _do_create_list_action.
384         return _do_create_list_action(commands, kw)
385     return None
386
387 def _do_create_list_action(act, kw):
388     """A factory for list actions.  Convert the input list into Actions
389     and then wrap them in a ListAction."""
390     acts = []
391     for a in act:
392         aa = _do_create_action(a, kw)
393         if aa is not None: acts.append(aa)
394     if not acts:
395         return None
396     elif len(acts) == 1:
397         return acts[0]
398     else:
399         return ListAction(acts)
400
401 def Action(act, *args, **kw):
402     """A factory for action objects."""
403     # Really simple: the _do_create_* routines do the heavy lifting.
404     _do_create_keywords(args, kw)
405     if is_List(act):
406         return _do_create_list_action(act, kw)
407     return _do_create_action(act, kw)
408
409 class ActionBase:
410     """Base class for all types of action objects that can be held by
411     other objects (Builders, Executors, etc.)  This provides the
412     common methods for manipulating and combining those actions."""
413
414     def __cmp__(self, other):
415         return cmp(self.__dict__, other)
416
417     def genstring(self, target, source, env):
418         return str(self)
419
420     def get_contents(self, target, source, env):
421         result = [ self.get_presig(target, source, env) ]
422         # This should never happen, as the Action() factory should wrap
423         # the varlist, but just in case an action is created directly,
424         # we duplicate this check here.
425         vl = self.varlist
426         if is_String(vl): vl = (vl,)
427         for v in vl:
428             result.append(env.subst('${'+v+'}'))
429         return string.join(result, '')
430
431     def __add__(self, other):
432         return _actionAppend(self, other)
433
434     def __radd__(self, other):
435         return _actionAppend(other, self)
436
437     def presub_lines(self, env):
438         # CommandGeneratorAction needs a real environment
439         # in order to return the proper string here, since
440         # it may call LazyAction, which looks up a key
441         # in that env.  So we temporarily remember the env here,
442         # and CommandGeneratorAction will use this env
443         # when it calls its _generate method.
444         self.presub_env = env
445         lines = string.split(str(self), '\n')
446         self.presub_env = None      # don't need this any more
447         return lines
448
449     def get_executor(self, env, overrides, tlist, slist, executor_kw):
450         """Return the Executor for this Action."""
451         return SCons.Executor.Executor(self, env, overrides,
452                                        tlist, slist, executor_kw)
453
454 class _ActionAction(ActionBase):
455     """Base class for actions that create output objects."""
456     def __init__(self, cmdstr=_null, strfunction=_null, varlist=(),
457                        presub=_null, chdir=None, exitstatfunc=None,
458                  **kw):
459         self.cmdstr = cmdstr
460         if strfunction is not _null:
461             if strfunction is None:
462                 self.cmdstr = None
463             else:
464                 self.strfunction = strfunction
465         self.varlist = varlist
466         self.presub = presub
467         self.chdir = chdir
468         if not exitstatfunc:
469             exitstatfunc = default_exitstatfunc
470         self.exitstatfunc = exitstatfunc
471
472     def print_cmd_line(self, s, target, source, env):
473         sys.stdout.write(s + "\n")
474
475     def __call__(self, target, source, env,
476                                exitstatfunc=_null,
477                                presub=_null,
478                                show=_null,
479                                execute=_null,
480                                chdir=_null):
481         if not is_List(target):
482             target = [target]
483         if not is_List(source):
484             source = [source]
485
486         if presub is _null:
487             presub = self.presub
488             if presub is _null:
489                 presub = print_actions_presub
490         if exitstatfunc is _null: exitstatfunc = self.exitstatfunc
491         if show is _null:  show = print_actions
492         if execute is _null:  execute = execute_actions
493         if chdir is _null: chdir = self.chdir
494         save_cwd = None
495         if chdir:
496             save_cwd = os.getcwd()
497             try:
498                 chdir = str(chdir.abspath)
499             except AttributeError:
500                 if not is_String(chdir):
501                     chdir = str(target[0].dir)
502         if presub:
503             t = string.join(map(str, target), ' and ')
504             l = string.join(self.presub_lines(env), '\n  ')
505             out = "Building %s with action:\n  %s\n" % (t, l)
506             sys.stdout.write(out)
507         s = None
508         if show and self.strfunction:
509             s = self.strfunction(target, source, env)
510             if s:
511                 if chdir:
512                     s = ('os.chdir(%s)\n' % repr(chdir)) + s
513                 try:
514                     get = env.get
515                 except AttributeError:
516                     print_func = self.print_cmd_line
517                 else:
518                     print_func = get('PRINT_CMD_LINE_FUNC')
519                     if not print_func:
520                         print_func = self.print_cmd_line
521                 print_func(s, target, source, env)
522         stat = 0
523         if execute:
524             if chdir:
525                 os.chdir(chdir)
526             try:
527                 stat = self.execute(target, source, env)
528                 if isinstance(stat, SCons.Errors.BuildError):
529                     s = exitstatfunc(stat.status)
530                     if s:
531                         stat.status = s
532                     else:
533                         stat = s
534                 else:
535                     stat = exitstatfunc(stat)
536             finally:
537                 if save_cwd:
538                     os.chdir(save_cwd)
539         if s and save_cwd:
540             print_func('os.chdir(%s)' % repr(save_cwd), target, source, env)
541
542         return stat
543
544
545 def _string_from_cmd_list(cmd_list):
546     """Takes a list of command line arguments and returns a pretty
547     representation for printing."""
548     cl = []
549     for arg in map(str, cmd_list):
550         if ' ' in arg or '\t' in arg:
551             arg = '"' + arg + '"'
552         cl.append(arg)
553     return string.join(cl)
554
555 # A fiddlin' little function that has an 'import SCons.Environment' which
556 # can't be moved to the top level without creating an import loop.  Since
557 # this import creates a local variable named 'SCons', it blocks access to
558 # the global variable, so we move it here to prevent complaints about local
559 # variables being used uninitialized.
560 default_ENV = None
561 def get_default_ENV(env):
562     global default_ENV
563     try:
564         return env['ENV']
565     except KeyError:
566         if not default_ENV:
567             import SCons.Environment
568             # This is a hideously expensive way to get a default shell
569             # environment.  What it really should do is run the platform
570             # setup to get the default ENV.  Fortunately, it's incredibly
571             # rare for an Environment not to have a shell environment, so
572             # we're not going to worry about it overmuch.
573             default_ENV = SCons.Environment.Environment()['ENV']
574         return default_ENV
575
576 # This function is still in draft mode.  We're going to need something like
577 # it in the long run as more and more places use subprocess, but I'm sure
578 # it'll have to be tweaked to get the full desired functionality.
579 # one special arg (so far?), 'error', to tell what to do with exceptions.
580 def _subproc(env, cmd, error = 'ignore', **kw):
581     """Do common setup for a subprocess.Popen() call"""
582     # allow std{in,out,err} to be "'devnull'"
583     io = kw.get('stdin')
584     if is_String(io) and io == 'devnull':
585         kw['stdin'] = open(os.devnull)
586     io = kw.get('stdout')
587     if is_String(io) and io == 'devnull':
588         kw['stdout'] = open(os.devnull, 'w')
589     io = kw.get('stderr')
590     if is_String(io) and io == 'devnull':
591         kw['stderr'] = open(os.devnull, 'w')
592
593     # Figure out what shell environment to use
594     ENV = kw.get('env', None)
595     if ENV is None: ENV = get_default_ENV(env)
596
597     # Ensure that the ENV values are all strings:
598     new_env = {}
599     for key, value in ENV.items():
600         if is_List(value):
601             # If the value is a list, then we assume it is a path list,
602             # because that's a pretty common list-like value to stick
603             # in an environment variable:
604             value = SCons.Util.flatten_sequence(value)
605             new_env[key] = string.join(map(str, value), os.pathsep)
606         else:
607             # It's either a string or something else.  If it's a string,
608             # we still want to call str() because it might be a *Unicode*
609             # string, which makes subprocess.Popen() gag.  If it isn't a
610             # string or a list, then we just coerce it to a string, which
611             # is the proper way to handle Dir and File instances and will
612             # produce something reasonable for just about everything else:
613             new_env[key] = str(value)
614     kw['env'] = new_env
615
616     try:
617         #FUTURE return subprocess.Popen(cmd, **kw)
618         return apply(subprocess.Popen, (cmd,), kw)
619     except EnvironmentError, e:
620         if error == 'raise': raise
621         # return a dummy Popen instance that only returns error
622         class dummyPopen:
623             def __init__(self, e): self.exception = e
624             def communicate(self): return ('','')
625             def wait(self): return -self.exception.errno
626             stdin = None
627             class f:
628                 def read(self): return ''
629                 def readline(self): return ''
630             stdout = stderr = f()
631         return dummyPopen(e)
632
633 class CommandAction(_ActionAction):
634     """Class for command-execution actions."""
635     def __init__(self, cmd, **kw):
636         # Cmd can actually be a list or a single item; if it's a
637         # single item it should be the command string to execute; if a
638         # list then it should be the words of the command string to
639         # execute.  Only a single command should be executed by this
640         # object; lists of commands should be handled by embedding
641         # these objects in a ListAction object (which the Action()
642         # factory above does).  cmd will be passed to
643         # Environment.subst_list() for substituting environment
644         # variables.
645         if __debug__: logInstanceCreation(self, 'Action.CommandAction')
646
647         #TODO(1.5) _ActionAction.__init__(self, **kw)
648         apply(_ActionAction.__init__, (self,), kw)
649         if is_List(cmd):
650             if filter(is_List, cmd):
651                 raise TypeError, "CommandAction should be given only " \
652                       "a single command"
653         self.cmd_list = cmd
654
655     def __str__(self):
656         if is_List(self.cmd_list):
657             return string.join(map(str, self.cmd_list), ' ')
658         return str(self.cmd_list)
659
660     def process(self, target, source, env):
661         result = env.subst_list(self.cmd_list, 0, target, source)
662         silent = None
663         ignore = None
664         while 1:
665             try: c = result[0][0][0]
666             except IndexError: c = None
667             if c == '@': silent = 1
668             elif c == '-': ignore = 1
669             else: break
670             result[0][0] = result[0][0][1:]
671         try:
672             if not result[0][0]:
673                 result[0] = result[0][1:]
674         except IndexError:
675             pass
676         return result, ignore, silent
677
678     def strfunction(self, target, source, env):
679         if self.cmdstr is None:
680             return None
681         if self.cmdstr is not _null:
682             from SCons.Subst import SUBST_RAW
683             c = env.subst(self.cmdstr, SUBST_RAW, target, source)
684             if c:
685                 return c
686         cmd_list, ignore, silent = self.process(target, source, env)
687         if silent:
688             return ''
689         return _string_from_cmd_list(cmd_list[0])
690
691     def execute(self, target, source, env):
692         """Execute a command action.
693
694         This will handle lists of commands as well as individual commands,
695         because construction variable substitution may turn a single
696         "command" into a list.  This means that this class can actually
697         handle lists of commands, even though that's not how we use it
698         externally.
699         """
700         escape_list = SCons.Subst.escape_list
701         flatten_sequence = SCons.Util.flatten_sequence
702
703         try:
704             shell = env['SHELL']
705         except KeyError:
706             raise SCons.Errors.UserError('Missing SHELL construction variable.')
707
708         try:
709             spawn = env['SPAWN']
710         except KeyError:
711             raise SCons.Errors.UserError('Missing SPAWN construction variable.')
712         else:
713             if is_String(spawn):
714                 spawn = env.subst(spawn, raw=1, conv=lambda x: x)
715
716         escape = env.get('ESCAPE', lambda x: x)
717
718         ENV = get_default_ENV(env)
719
720         # Ensure that the ENV values are all strings:
721         for key, value in ENV.items():
722             if not is_String(value):
723                 if is_List(value):
724                     # If the value is a list, then we assume it is a
725                     # path list, because that's a pretty common list-like
726                     # value to stick in an environment variable:
727                     value = flatten_sequence(value)
728                     ENV[key] = string.join(map(str, value), os.pathsep)
729                 else:
730                     # If it isn't a string or a list, then we just coerce
731                     # it to a string, which is the proper way to handle
732                     # Dir and File instances and will produce something
733                     # reasonable for just about everything else:
734                     ENV[key] = str(value)
735
736         cmd_list, ignore, silent = self.process(target, map(rfile, source), env)
737
738         # Use len() to filter out any "command" that's zero-length.
739         for cmd_line in filter(len, cmd_list):
740             # Escape the command line for the interpreter we are using.
741             cmd_line = escape_list(cmd_line, escape)
742             result = spawn(shell, escape, cmd_line[0], cmd_line, ENV)
743             if not ignore and result:
744                 msg = "Error %s" % result
745                 return SCons.Errors.BuildError(errstr=msg,
746                                                status=result,
747                                                action=self,
748                                                command=cmd_line)
749         return 0
750
751     def get_presig(self, target, source, env):
752         """Return the signature contents of this action's command line.
753
754         This strips $(-$) and everything in between the string,
755         since those parts don't affect signatures.
756         """
757         from SCons.Subst import SUBST_SIG
758         cmd = self.cmd_list
759         if is_List(cmd):
760             cmd = string.join(map(str, cmd))
761         else:
762             cmd = str(cmd)
763         return env.subst_target_source(cmd, SUBST_SIG, target, source)
764
765     def get_implicit_deps(self, target, source, env):
766         icd = env.get('IMPLICIT_COMMAND_DEPENDENCIES', True)
767         if is_String(icd) and icd[:1] == '$':
768             icd = env.subst(icd)
769         if not icd or icd in ('0', 'None'):
770             return []
771         from SCons.Subst import SUBST_SIG
772         cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, target, source)
773         res = []
774         for cmd_line in cmd_list:
775             if cmd_line:
776                 d = env.WhereIs(str(cmd_line[0]))
777                 if d:
778                     res.append(env.fs.File(d))
779         return res
780
781 class CommandGeneratorAction(ActionBase):
782     """Class for command-generator actions."""
783     def __init__(self, generator, kw):
784         if __debug__: logInstanceCreation(self, 'Action.CommandGeneratorAction')
785         self.generator = generator
786         self.gen_kw = kw
787         self.varlist = kw.get('varlist', ())
788
789     def _generate(self, target, source, env, for_signature):
790         # ensure that target is a list, to make it easier to write
791         # generator functions:
792         if not is_List(target):
793             target = [target]
794
795         ret = self.generator(target=target, source=source, env=env, for_signature=for_signature)
796         #TODO(1.5) gen_cmd = Action(ret, **self.gen_kw)
797         gen_cmd = apply(Action, (ret,), self.gen_kw)
798         if not gen_cmd:
799             raise SCons.Errors.UserError("Object returned from command generator: %s cannot be used to create an Action." % repr(ret))
800         return gen_cmd
801
802     def __str__(self):
803         try:
804             env = self.presub_env
805         except AttributeError:
806             env = None
807         if env is None:
808             env = SCons.Defaults.DefaultEnvironment()
809         act = self._generate([], [], env, 1)
810         return str(act)
811
812     def genstring(self, target, source, env):
813         return self._generate(target, source, env, 1).genstring(target, source, env)
814
815     def __call__(self, target, source, env, exitstatfunc=_null, presub=_null,
816                  show=_null, execute=_null, chdir=_null):
817         act = self._generate(target, source, env, 0)
818         return act(target, source, env, exitstatfunc, presub,
819                    show, execute, chdir)
820
821     def get_presig(self, target, source, env):
822         """Return the signature contents of this action's command line.
823
824         This strips $(-$) and everything in between the string,
825         since those parts don't affect signatures.
826         """
827         return self._generate(target, source, env, 1).get_presig(target, source, env)
828
829     def get_implicit_deps(self, target, source, env):
830         return self._generate(target, source, env, 1).get_implicit_deps(target, source, env)
831
832
833
834 # A LazyAction is a kind of hybrid generator and command action for
835 # strings of the form "$VAR".  These strings normally expand to other
836 # strings (think "$CCCOM" to "$CC -c -o $TARGET $SOURCE"), but we also
837 # want to be able to replace them with functions in the construction
838 # environment.  Consequently, we want lazy evaluation and creation of
839 # an Action in the case of the function, but that's overkill in the more
840 # normal case of expansion to other strings.
841 #
842 # So we do this with a subclass that's both a generator *and*
843 # a command action.  The overridden methods all do a quick check
844 # of the construction variable, and if it's a string we just call
845 # the corresponding CommandAction method to do the heavy lifting.
846 # If not, then we call the same-named CommandGeneratorAction method.
847 # The CommandGeneratorAction methods work by using the overridden
848 # _generate() method, that is, our own way of handling "generation" of
849 # an action based on what's in the construction variable.
850
851 class LazyAction(CommandGeneratorAction, CommandAction):
852
853     def __init__(self, var, kw):
854         if __debug__: logInstanceCreation(self, 'Action.LazyAction')
855         #FUTURE CommandAction.__init__(self, '${'+var+'}', **kw)
856         apply(CommandAction.__init__, (self, '${'+var+'}'), kw)
857         self.var = SCons.Util.to_String(var)
858         self.gen_kw = kw
859
860     def get_parent_class(self, env):
861         c = env.get(self.var)
862         if is_String(c) and not '\n' in c:
863             return CommandAction
864         return CommandGeneratorAction
865
866     def _generate_cache(self, env):
867         c = env.get(self.var, '')
868         #TODO(1.5) gen_cmd = Action(c, **self.gen_kw)
869         gen_cmd = apply(Action, (c,), self.gen_kw)
870         if not gen_cmd:
871             raise SCons.Errors.UserError("$%s value %s cannot be used to create an Action." % (self.var, repr(c)))
872         return gen_cmd
873
874     def _generate(self, target, source, env, for_signature):
875         return self._generate_cache(env)
876
877     def __call__(self, target, source, env, *args, **kw):
878         args = (self, target, source, env) + args
879         c = self.get_parent_class(env)
880         #TODO(1.5) return c.__call__(*args, **kw)
881         return apply(c.__call__, args, kw)
882
883     def get_presig(self, target, source, env):
884         c = self.get_parent_class(env)
885         return c.get_presig(self, target, source, env)
886
887
888
889 class FunctionAction(_ActionAction):
890     """Class for Python function actions."""
891
892     def __init__(self, execfunction, kw):
893         if __debug__: logInstanceCreation(self, 'Action.FunctionAction')
894
895         self.execfunction = execfunction
896         try:
897             self.funccontents = _callable_contents(execfunction)
898         except AttributeError:
899             try:
900                 # See if execfunction will do the heavy lifting for us.
901                 self.gc = execfunction.get_contents
902             except AttributeError:
903                 # This is weird, just do the best we can.
904                 self.funccontents = _object_contents(execfunction)
905
906         #TODO(1.5) _ActionAction.__init__(self, **kw)
907         apply(_ActionAction.__init__, (self,), kw)
908
909     def function_name(self):
910         try:
911             return self.execfunction.__name__
912         except AttributeError:
913             try:
914                 return self.execfunction.__class__.__name__
915             except AttributeError:
916                 return "unknown_python_function"
917
918     def strfunction(self, target, source, env):
919         if self.cmdstr is None:
920             return None
921         if self.cmdstr is not _null:
922             from SCons.Subst import SUBST_RAW
923             c = env.subst(self.cmdstr, SUBST_RAW, target, source)
924             if c:
925                 return c
926         def array(a):
927             def quote(s):
928                 try:
929                     str_for_display = s.str_for_display
930                 except AttributeError:
931                     s = repr(s)
932                 else:
933                     s = str_for_display()
934                 return s
935             return '[' + string.join(map(quote, a), ", ") + ']'
936         try:
937             strfunc = self.execfunction.strfunction
938         except AttributeError:
939             pass
940         else:
941             if strfunc is None:
942                 return None
943             if callable(strfunc):
944                 return strfunc(target, source, env)
945         name = self.function_name()
946         tstr = array(target)
947         sstr = array(source)
948         return "%s(%s, %s)" % (name, tstr, sstr)
949
950     def __str__(self):
951         name = self.function_name()
952         if name == 'ActionCaller':
953             return str(self.execfunction)
954         return "%s(target, source, env)" % name
955
956     def execute(self, target, source, env):
957         exc_info = (None,None,None)
958         try:
959             rsources = map(rfile, source)
960             try:
961                 result = self.execfunction(target=target, source=rsources, env=env)
962             except KeyboardInterrupt, e:
963                 raise
964             except SystemExit, e:
965                 raise
966             except Exception, e:
967                 result = e
968                 exc_info = sys.exc_info()
969
970             if result:
971                 result = SCons.Errors.convert_to_BuildError(result, exc_info)
972                 result.node=target
973                 result.action=self
974                 result.command=self.strfunction(target, source, env)
975
976                 # FIXME: This maintains backward compatibility with respect to
977                 # which type of exceptions were returned by raising an
978                 # exception and which ones were returned by value. It would
979                 # probably be best to always return them by value here, but
980                 # some codes do not check the return value of Actions and I do
981                 # not have the time to modify them at this point.
982                 if (exc_info[1] and
983                     not isinstance(exc_info[1],EnvironmentError)):
984                     raise result
985
986             return result
987         finally:
988             # Break the cycle between the traceback object and this
989             # function stack frame. See the sys.exc_info() doc info for
990             # more information about this issue.
991             del exc_info
992
993
994     def get_presig(self, target, source, env):
995         """Return the signature contents of this callable action."""
996         try:
997             return self.gc(target, source, env)
998         except AttributeError:
999             return self.funccontents
1000
1001     def get_implicit_deps(self, target, source, env):
1002         return []
1003
1004 class ListAction(ActionBase):
1005     """Class for lists of other actions."""
1006     def __init__(self, list):
1007         if __debug__: logInstanceCreation(self, 'Action.ListAction')
1008         def list_of_actions(x):
1009             if isinstance(x, ActionBase):
1010                 return x
1011             return Action(x)
1012         self.list = map(list_of_actions, list)
1013         # our children will have had any varlist
1014         # applied; we don't need to do it again
1015         self.varlist = ()
1016
1017     def genstring(self, target, source, env):
1018         return string.join(map(lambda a, t=target, s=source, e=env:
1019                                   a.genstring(t, s, e),
1020                                self.list),
1021                            '\n')
1022
1023     def __str__(self):
1024         return string.join(map(str, self.list), '\n')
1025
1026     def presub_lines(self, env):
1027         return SCons.Util.flatten_sequence(
1028             map(lambda a, env=env: a.presub_lines(env), self.list))
1029
1030     def get_presig(self, target, source, env):
1031         """Return the signature contents of this action list.
1032
1033         Simple concatenation of the signatures of the elements.
1034         """
1035         return string.join(map(lambda x, t=target, s=source, e=env:
1036                                       x.get_contents(t, s, e),
1037                                self.list),
1038                            "")
1039
1040     def __call__(self, target, source, env, exitstatfunc=_null, presub=_null,
1041                  show=_null, execute=_null, chdir=_null):
1042         for act in self.list:
1043             stat = act(target, source, env, exitstatfunc, presub,
1044                        show, execute, chdir)
1045             if stat:
1046                 return stat
1047         return 0
1048
1049     def get_implicit_deps(self, target, source, env):
1050         result = []
1051         for act in self.list:
1052             result.extend(act.get_implicit_deps(target, source, env))
1053         return result
1054
1055 class ActionCaller:
1056     """A class for delaying calling an Action function with specific
1057     (positional and keyword) arguments until the Action is actually
1058     executed.
1059
1060     This class looks to the rest of the world like a normal Action object,
1061     but what it's really doing is hanging on to the arguments until we
1062     have a target, source and env to use for the expansion.
1063     """
1064     def __init__(self, parent, args, kw):
1065         self.parent = parent
1066         self.args = args
1067         self.kw = kw
1068
1069     def get_contents(self, target, source, env):
1070         actfunc = self.parent.actfunc
1071         try:
1072             # "self.actfunc" is a function.
1073             contents = str(actfunc.func_code.co_code)
1074         except AttributeError:
1075             # "self.actfunc" is a callable object.
1076             try:
1077                 contents = str(actfunc.__call__.im_func.func_code.co_code)
1078             except AttributeError:
1079                 # No __call__() method, so it might be a builtin
1080                 # or something like that.  Do the best we can.
1081                 contents = str(actfunc)
1082         contents = remove_set_lineno_codes(contents)
1083         return contents
1084
1085     def subst(self, s, target, source, env):
1086         # If s is a list, recursively apply subst()
1087         # to every element in the list
1088         if is_List(s):
1089             result = []
1090             for elem in s:
1091                 result.append(self.subst(elem, target, source, env))
1092             return self.parent.convert(result)
1093
1094         # Special-case hack:  Let a custom function wrapped in an
1095         # ActionCaller get at the environment through which the action
1096         # was called by using this hard-coded value as a special return.
1097         if s == '$__env__':
1098             return env
1099         elif is_String(s):
1100             return env.subst(s, 1, target, source)
1101         return self.parent.convert(s)
1102
1103     def subst_args(self, target, source, env):
1104         return map(lambda x, self=self, t=target, s=source, e=env:
1105                           self.subst(x, t, s, e),
1106                    self.args)
1107
1108     def subst_kw(self, target, source, env):
1109         kw = {}
1110         for key in self.kw.keys():
1111             kw[key] = self.subst(self.kw[key], target, source, env)
1112         return kw
1113
1114     def __call__(self, target, source, env):
1115         args = self.subst_args(target, source, env)
1116         kw = self.subst_kw(target, source, env)
1117         #TODO(1.5) return self.parent.actfunc(*args, **kw)
1118         return apply(self.parent.actfunc, args, kw)
1119
1120     def strfunction(self, target, source, env):
1121         args = self.subst_args(target, source, env)
1122         kw = self.subst_kw(target, source, env)
1123         #TODO(1.5) return self.parent.strfunc(*args, **kw)
1124         return apply(self.parent.strfunc, args, kw)
1125
1126     def __str__(self):
1127         #TODO(1.5) return self.parent.strfunc(*self.args, **self.kw)
1128         return apply(self.parent.strfunc, self.args, self.kw)
1129
1130 class ActionFactory:
1131     """A factory class that will wrap up an arbitrary function
1132     as an SCons-executable Action object.
1133
1134     The real heavy lifting here is done by the ActionCaller class.
1135     We just collect the (positional and keyword) arguments that we're
1136     called with and give them to the ActionCaller object we create,
1137     so it can hang onto them until it needs them.
1138     """
1139     def __init__(self, actfunc, strfunc, convert=lambda x: x):
1140         self.actfunc = actfunc
1141         self.strfunc = strfunc
1142         self.convert = convert
1143
1144     def __call__(self, *args, **kw):
1145         ac = ActionCaller(self, args, kw)
1146         action = Action(ac, strfunction=ac.strfunction)
1147         return action