Updating licensing.
[scons.git] / src / engine / SCons / Builder.py
1 """SCons.Builder
2
3 XXX
4
5 """
6
7 #
8 # Copyright (c) 2001 Steven Knight
9 #
10 # Permission is hereby granted, free of charge, to any person obtaining
11 # a copy of this software and associated documentation files (the
12 # "Software"), to deal in the Software without restriction, including
13 # without limitation the rights to use, copy, modify, merge, publish,
14 # distribute, sublicense, and/or sell copies of the Software, and to
15 # permit persons to whom the Software is furnished to do so, subject to
16 # the following conditions:
17 #
18 # The above copyright notice and this permission notice shall be included
19 # in all copies or substantial portions of the Software.
20 #
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #
29
30 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
31
32
33
34 import os
35 import SCons.Node.FS
36 import SCons.Util
37 import string
38 import types
39
40
41
42 class Builder:
43     """Base class for Builders, objects that create output
44     nodes (files) from input nodes (files).
45     """
46
47     def __init__(self,  name = None,
48                         action = None,
49                         input_suffix = None,
50                         output_suffix = None,
51                         node_factory = SCons.Node.FS.default_fs.File):
52         self.name = name
53         self.action = Action(action)
54         self.insuffix = input_suffix
55         self.outsuffix = output_suffix
56         self.node_factory = node_factory
57         if not self.insuffix is None and self.insuffix[0] != '.':
58             self.insuffix = '.' + self.insuffix
59         if not self.outsuffix is None and self.outsuffix[0] != '.':
60             self.outsuffix = '.' + self.outsuffix
61
62     def __cmp__(self, other):
63         return cmp(self.__dict__, other.__dict__)
64
65     def __call__(self, env, target = None, source = None):
66         tlist = SCons.Util.scons_str2nodes(target)
67         slist = SCons.Util.scons_str2nodes(source)
68         for t in tlist:
69             t.builder_set(self)
70             t.env_set(env)
71             t.derived = 1
72             t.add_source(slist)
73
74         if len(tlist) == 1:
75             tlist = tlist[0]
76         return tlist
77
78     def execute(self, **kw):
79         """Execute a builder's action to create an output object.
80         """
81         return apply(self.action.execute, (), kw)
82
83
84
85 print_actions = 1;
86 execute_actions = 1;
87
88
89
90 def Action(act):
91     """A factory for action objects."""
92     if type(act) == types.StringType:
93         l = string.split(act, "\n")
94         if len(l) > 1:
95             act = l
96     if callable(act):
97         return FunctionAction(act)
98     elif type(act) == types.StringType:
99         return CommandAction(act)
100     elif type(act) == types.ListType:
101         return ListAction(act)
102     else:
103         return None
104
105 class ActionBase:
106     """Base class for actions that create output objects.
107     
108     We currently expect Actions will only be accessible through
109     Builder objects, so they don't yet merit their own module."""
110     def __cmp__(self, other):
111         return cmp(self.__dict__, other.__dict__)
112
113     def show(self, string):
114         print string
115
116 class CommandAction(ActionBase):
117     """Class for command-execution actions."""
118     def __init__(self, string):
119         self.command = string
120
121     def execute(self, **kw):
122         cmd = self.command % kw
123         if print_actions:
124             self.show(cmd)
125         ret = 0
126         if execute_actions:
127             pid = os.fork()
128             if not pid:
129                 # Child process.
130                 args = string.split(cmd)
131                 try:
132                     ENV = kw['ENV']
133                 except:
134                     import SCons.Defaults
135                     ENV = SCons.Defaults.ENV
136                 os.execvpe(args[0], args, ENV)
137             else:
138                 # Parent process.
139                 pid, stat = os.waitpid(pid, 0)
140                 ret = stat >> 8
141         return ret
142
143
144
145 class FunctionAction(ActionBase):
146     """Class for Python function actions."""
147     def __init__(self, function):
148         self.function = function
149
150     def execute(self, **kw):
151         # if print_actions:
152         # XXX:  WHAT SHOULD WE PRINT HERE?
153         if execute_actions:
154             return self.function(kw)
155
156 class ListAction(ActionBase):
157     """Class for lists of other actions."""
158     def __init__(self, list):
159         self.list = map(lambda x: Action(x), list)
160
161     def execute(self, **kw):
162         for l in self.list:
163             r = apply(l.execute, (), kw)
164             if r != 0:
165                 return r
166         return 0