1 """SCons.Builder
2
3 Builder object subsystem.
4
5 A Builder object is a callable that encapsulates information about how
6 to execute actions to create a target Node (file) from source Nodes
7 (files), and how to create those dependencies for tracking.
8
9 The main entry point here is the Builder() factory method. This provides
10 a procedural interface that creates the right underlying Builder object
11 based on the keyword arguments supplied and the types of the arguments.
12
13 The goal is for this external interface to be simple enough that the
14 vast majority of users can create new Builders as necessary to support
15 building new types of files in their configurations, without having to
16 dive any deeper into this subsystem.
17
18 The base class here is BuilderBase. This is a concrete base class which
19 does, in fact, represent the Builder objects that we (or users) create.
20
21 There is also a proxy that looks like a Builder:
22
23 CompositeBuilder
24
25 This proxies for a Builder with an action that is actually a
26 dictionary that knows how to map file suffixes to a specific
27 action. This is so that we can invoke different actions
28 (compilers, compile options) for different flavors of source
29 files.
30
31 Builders and their proxies have the following public interface methods
32 used by other modules:
33
34 __call__()
35 THE public interface. Calling a Builder object (with the
36 use of internal helper methods) sets up the target and source
37 dependencies, appropriate mapping to a specific action, and the
38 environment manipulation necessary for overridden construction
39 variable. This also takes care of warning about possible mistakes
40 in keyword arguments.
41
42 add_emitter()
43 Adds an emitter for a specific file suffix, used by some Tool
44 modules to specify that (for example) a yacc invocation on a .y
45 can create a .h *and* a .c file.
46
47 add_action()
48 Adds an action for a specific file suffix, heavily used by
49 Tool modules to add their specific action(s) for turning
50 a source file into an object file to the global static
51 and shared object file Builders.
52
53 There are the following methods for internal use within this module:
54
55 _execute()
56 The internal method that handles the heavily lifting when a
57 Builder is called. This is used so that the __call__() methods
58 can set up warning about possible mistakes in keyword-argument
59 overrides, and *then* execute all of the steps necessary so that
60 the warnings only occur once.
61
62 get_name()
63 Returns the Builder's name within a specific Environment,
64 primarily used to try to return helpful information in error
65 messages.
66
67 adjust_suffix()
68 get_prefix()
69 get_suffix()
70 get_src_suffix()
71 set_src_suffix()
72 Miscellaneous stuff for handling the prefix and suffix
73 manipulation we use in turning source file names into target
74 file names.
75
76 """
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 __revision__ = "src/engine/SCons/Builder.py 2928 2008/04/29 22:44:09 knight"
102
103 import SCons.compat
104
105 import UserDict
106 import UserList
107
108 import SCons.Action
109 from SCons.Debug import logInstanceCreation
110 from SCons.Errors import InternalError, UserError
111 import SCons.Executor
112 import SCons.Memoize
113 import SCons.Node
114 import SCons.Node.FS
115 import SCons.Util
116 import SCons.Warnings
117
120
121 _null = _Null
122
124 """This is a callable class that can be used as a
125 command generator function. It holds on to a dictionary
126 mapping file suffixes to Actions. It uses that dictionary
127 to return the proper action based on the file suffix of
128 the source file."""
129
130 - def __init__(self, dict=None, source_ext_match=1):
133
136
138 """Add a suffix-action pair to the mapping.
139 """
140 self[suffix] = action
141
142 - def __call__(self, target, source, env, for_signature):
143 if not source:
144 return []
145
146 if self.source_ext_match:
147 ext = None
148 for src in map(str, source):
149 my_ext = SCons.Util.splitext(src)[1]
150 if ext and my_ext != ext:
151 raise UserError("While building `%s' from `%s': Cannot build multiple sources with different extensions: %s, %s" % (repr(map(str, target)), src, ext, my_ext))
152 ext = my_ext
153 else:
154 ext = SCons.Util.splitext(str(source[0]))[1]
155
156 if not ext:
157 raise UserError("While building `%s': Cannot deduce file extension from source files: %s" % (repr(map(str, target)), repr(map(str, source))))
158
159 try:
160 ret = SCons.Util.Selector.__call__(self, env, source)
161 except KeyError, e:
162 raise UserError("Ambiguous suffixes after environment substitution: %s == %s == %s" % (e[0], e[1], e[2]))
163 if ret is None:
164 raise UserError("While building `%s' from `%s': Don't know how to build from a source file with suffix `%s'. Expected a suffix in this list: %s." % \
165 (repr(map(str, target)), repr(map(str, source)), ext, repr(self.keys())))
166 return ret
167
169 """A callable dictionary that will, in turn, call the value it
170 finds if it can."""
172 value = SCons.Util.Selector.__call__(self, env, source)
173 if callable(value):
174 value = value(env, source)
175 return value
176
178 """A callable dictionary that maps file suffixes to emitters.
179 When called, it finds the right emitter in its dictionary for the
180 suffix of the first source file, and calls that emitter to get the
181 right lists of targets and sources to return. If there's no emitter
182 for the suffix in its dictionary, the original target and source are
183 returned.
184 """
185 - def __call__(self, target, source, env):
186 emitter = SCons.Util.Selector.__call__(self, env, source)
187 if emitter:
188 target, source = emitter(target, source, env)
189 return (target, source)
190
192 """A callable list of emitters that calls each in sequence,
193 returning the result.
194 """
195 - def __call__(self, target, source, env):
196 for e in self.data:
197 target, source = e(target, source, env)
198 return (target, source)
199
200
201
202
203
204 misleading_keywords = {
205 'targets' : 'target',
206 'sources' : 'source',
207 }
208
210 """A class for warning about keyword arguments that we use as
211 overrides in a Builder call.
212
213 This class exists to handle the fact that a single Builder call
214 can actually invoke multiple builders. This class only emits the
215 warnings once, no matter how many Builders are invoked.
216 """
230
272
274 """Validate that the lists of target and source nodes are
275 legal for this builder and environment. Raise errors or
276 issue warnings as appropriate.
277 """
278
279
280
281 for t in tlist:
282 if t.side_effect:
283 raise UserError, "Multiple ways to build the same target were specified for: %s" % t
284 if t.has_explicit_builder():
285 if not t.env is None and not t.env is env:
286 action = t.builder.action
287 t_contents = action.get_contents(tlist, slist, t.env)
288 contents = action.get_contents(tlist, slist, env)
289
290 if t_contents == contents:
291 msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (t, action.genstring(tlist, slist, t.env))
292 SCons.Warnings.warn(SCons.Warnin