Handle build errors.
[scons.git] / src / engine / SCons / Builder.py
1 """SCons.Builder
2
3 XXX
4
5 """
6
7 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
8
9
10
11 import os
12 import SCons.Node.FS
13 import SCons.Util
14 import string
15 import types
16
17
18
19 class Builder:
20     """Base class for Builders, objects that create output
21     nodes (files) from input nodes (files).
22     """
23
24     def __init__(self,  name = None,
25                         action = None,
26                         input_suffix = None,
27                         output_suffix = None,
28                         node_factory = SCons.Node.FS.default_fs.File):
29         self.name = name
30         self.action = Action(action)
31         self.insuffix = input_suffix
32         self.outsuffix = output_suffix
33         self.node_factory = node_factory
34         if not self.insuffix is None and self.insuffix[0] != '.':
35             self.insuffix = '.' + self.insuffix
36         if not self.outsuffix is None and self.outsuffix[0] != '.':
37             self.outsuffix = '.' + self.outsuffix
38
39     def __cmp__(self, other):
40         return cmp(self.__dict__, other.__dict__)
41
42     def __call__(self, env, target = None, source = None):
43         tlist = SCons.Util.scons_str2nodes(target)
44         slist = SCons.Util.scons_str2nodes(source)
45         for t in tlist:
46             t.builder_set(self)
47             t.env_set(env)
48             t.derived = 1
49             t.add_source(slist)
50
51         if len(tlist) == 1:
52             tlist = tlist[0]
53         return tlist
54
55     def execute(self, **kw):
56         """Execute a builder's action to create an output object.
57         """
58         return apply(self.action.execute, (), kw)
59
60
61
62 print_actions = 1;
63 execute_actions = 1;
64
65
66
67 def Action(act):
68     """A factory for action objects."""
69     if type(act) == types.StringType:
70         l = string.split(act, "\n")
71         if len(l) > 1:
72             act = l
73     if type(act) == types.FunctionType:
74         return FunctionAction(act)
75     elif type(act) == types.StringType:
76         return CommandAction(act)
77     elif type(act) == types.ListType:
78         return ListAction(act)
79     else:
80         return None
81
82 class ActionBase:
83     """Base class for actions that create output objects.
84     
85     We currently expect Actions will only be accessible through
86     Builder objects, so they don't yet merit their own module."""
87     def __cmp__(self, other):
88         return cmp(self.__dict__, other.__dict__)
89
90     def show(self, string):
91         print string
92
93 class CommandAction(ActionBase):
94     """Class for command-execution actions."""
95     def __init__(self, string):
96         self.command = string
97
98     def execute(self, **kw):
99         cmd = self.command % kw
100         if print_actions:
101             self.show(cmd)
102         ret = 0
103         if execute_actions:
104             pid = os.fork()
105             if not pid:
106                 # Child process.
107                 args = string.split(cmd)
108                 try:
109                     ENV = kw['ENV']
110                 except:
111                     import SCons.Defaults
112                     ENV = SCons.Defaults.ENV
113                 os.execvpe(args[0], args, ENV)
114             else:
115                 # Parent process.
116                 pid, stat = os.waitpid(pid, 0)
117                 ret = stat >> 8
118         return ret
119
120
121
122 class FunctionAction(ActionBase):
123     """Class for Python function actions."""
124     def __init__(self, function):
125         self.function = function
126
127     def execute(self, **kw):
128         # if print_actions:
129         # XXX:  WHAT SHOULD WE PRINT HERE?
130         if execute_actions:
131             return self.function(kw)
132
133 class ListAction(ActionBase):
134     """Class for lists of other actions."""
135     def __init__(self, list):
136         self.list = map(lambda x: Action(x), list)
137
138     def execute(self, **kw):
139         for l in self.list:
140             r = apply(l.execute, (), kw)
141             if r != 0:
142                 return r
143         return 0