Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: third_party/scons/scons-local/SCons/Builder.py

Issue 20025: Update SCons to latest checkpoint release, 1.2.0.d20090113.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 """SCons.Builder 1 """SCons.Builder
2 2
3 Builder object subsystem. 3 Builder object subsystem.
4 4
5 A Builder object is a callable that encapsulates information about how 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 6 to execute actions to create a target Node (file) from source Nodes
7 (files), and how to create those dependencies for tracking. 7 (files), and how to create those dependencies for tracking.
8 8
9 The main entry point here is the Builder() factory method. This provides 9 The main entry point here is the Builder() factory method. This provides
10 a procedural interface that creates the right underlying Builder object 10 a procedural interface that creates the right underlying Builder object
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 get_suffix() 69 get_suffix()
70 get_src_suffix() 70 get_src_suffix()
71 set_src_suffix() 71 set_src_suffix()
72 Miscellaneous stuff for handling the prefix and suffix 72 Miscellaneous stuff for handling the prefix and suffix
73 manipulation we use in turning source file names into target 73 manipulation we use in turning source file names into target
74 file names. 74 file names.
75 75
76 """ 76 """
77 77
78 # 78 #
79 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundat ion 79 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons F oundation
80 # 80 #
81 # Permission is hereby granted, free of charge, to any person obtaining 81 # Permission is hereby granted, free of charge, to any person obtaining
82 # a copy of this software and associated documentation files (the 82 # a copy of this software and associated documentation files (the
83 # "Software"), to deal in the Software without restriction, including 83 # "Software"), to deal in the Software without restriction, including
84 # without limitation the rights to use, copy, modify, merge, publish, 84 # without limitation the rights to use, copy, modify, merge, publish,
85 # distribute, sublicense, and/or sell copies of the Software, and to 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 86 # permit persons to whom the Software is furnished to do so, subject to
87 # the following conditions: 87 # the following conditions:
88 # 88 #
89 # The above copyright notice and this permission notice shall be included 89 # The above copyright notice and this permission notice shall be included
90 # in all copies or substantial portions of the Software. 90 # in all copies or substantial portions of the Software.
91 # 91 #
92 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 92 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
93 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 93 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
94 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 94 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
95 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 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 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 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. 98 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
99 # 99 #
100 100
101 __revision__ = "src/engine/SCons/Builder.py 3842 2008/12/20 22:59:52 scons" 101 __revision__ = "src/engine/SCons/Builder.py 3897 2009/01/13 06:45:54 scons"
102 102
103 import UserDict 103 import UserDict
104 import UserList 104 import UserList
105 105
106 import SCons.Action 106 import SCons.Action
107 from SCons.Debug import logInstanceCreation 107 from SCons.Debug import logInstanceCreation
108 from SCons.Errors import InternalError, UserError 108 from SCons.Errors import InternalError, UserError
109 import SCons.Executor 109 import SCons.Executor
110 import SCons.Memoize 110 import SCons.Memoize
111 import SCons.Node 111 import SCons.Node
112 import SCons.Node.FS 112 import SCons.Node.FS
113 import SCons.Util 113 import SCons.Util
114 import SCons.Warnings 114 import SCons.Warnings
115 115
116 class _Null: 116 class _Null:
117 pass 117 pass
118 118
119 _null = _Null 119 _null = _Null
120 120
121 def match_splitext(path, suffixes = []):
122 if suffixes:
123 matchsuf = filter(lambda S,path=path: path[-len(S):] == S,
124 suffixes)
125 if matchsuf:
126 suf = max(map(None, map(len, matchsuf), matchsuf))[1]
127 return [path[:-len(suf)], path[-len(suf):]]
128 return SCons.Util.splitext(path)
129
121 class DictCmdGenerator(SCons.Util.Selector): 130 class DictCmdGenerator(SCons.Util.Selector):
122 """This is a callable class that can be used as a 131 """This is a callable class that can be used as a
123 command generator function. It holds on to a dictionary 132 command generator function. It holds on to a dictionary
124 mapping file suffixes to Actions. It uses that dictionary 133 mapping file suffixes to Actions. It uses that dictionary
125 to return the proper action based on the file suffix of 134 to return the proper action based on the file suffix of
126 the source file.""" 135 the source file."""
127 136
128 def __init__(self, dict=None, source_ext_match=1): 137 def __init__(self, dict=None, source_ext_match=1):
129 SCons.Util.Selector.__init__(self, dict) 138 SCons.Util.Selector.__init__(self, dict)
130 self.source_ext_match = source_ext_match 139 self.source_ext_match = source_ext_match
131 140
132 def src_suffixes(self): 141 def src_suffixes(self):
133 return self.keys() 142 return self.keys()
134 143
135 def add_action(self, suffix, action): 144 def add_action(self, suffix, action):
136 """Add a suffix-action pair to the mapping. 145 """Add a suffix-action pair to the mapping.
137 """ 146 """
138 self[suffix] = action 147 self[suffix] = action
139 148
140 def __call__(self, target, source, env, for_signature): 149 def __call__(self, target, source, env, for_signature):
141 if not source: 150 if not source:
142 return [] 151 return []
143 152
144 if self.source_ext_match: 153 if self.source_ext_match:
154 suffixes = self.src_suffixes()
145 ext = None 155 ext = None
146 for src in map(str, source): 156 for src in map(str, source):
147 my_ext = SCons.Util.splitext(src)[1] 157 my_ext = match_splitext(src, suffixes)[1]
148 if ext and my_ext != ext: 158 if ext and my_ext != ext:
149 raise UserError("While building `%s' from `%s': Cannot build multiple sources with different extensions: %s, %s" % (repr(map(str, target)), src, ext, my_ext)) 159 raise UserError("While building `%s' from `%s': Cannot build multiple sources with different extensions: %s, %s" % (repr(map(str, target)), src, ext, my_ext))
150 ext = my_ext 160 ext = my_ext
151 else: 161 else:
152 ext = SCons.Util.splitext(str(source[0]))[1] 162 ext = match_splitext(str(source[0]), self.src_suffixes())[1]
153 163
154 if not ext: 164 if not ext:
165 #return ext
155 raise UserError("While building `%s': Cannot deduce file extension f rom source files: %s" % (repr(map(str, target)), repr(map(str, source)))) 166 raise UserError("While building `%s': Cannot deduce file extension f rom source files: %s" % (repr(map(str, target)), repr(map(str, source))))
156 167
157 try: 168 try:
158 ret = SCons.Util.Selector.__call__(self, env, source) 169 ret = SCons.Util.Selector.__call__(self, env, source, ext)
159 except KeyError, e: 170 except KeyError, e:
160 raise UserError("Ambiguous suffixes after environment substitution: %s == %s == %s" % (e[0], e[1], e[2])) 171 raise UserError("Ambiguous suffixes after environment substitution: %s == %s == %s" % (e[0], e[1], e[2]))
161 if ret is None: 172 if ret is None:
162 raise UserError("While building `%s' from `%s': Don't know how to bu ild from a source file with suffix `%s'. Expected a suffix in this list: %s." % \ 173 raise UserError("While building `%s' from `%s': Don't know how to bu ild from a source file with suffix `%s'. Expected a suffix in this list: %s." % \
163 (repr(map(str, target)), repr(map(str, source)), ext , repr(self.keys()))) 174 (repr(map(str, target)), repr(map(str, source)), ext , repr(self.keys())))
164 return ret 175 return ret
165 176
166 class CallableSelector(SCons.Util.Selector): 177 class CallableSelector(SCons.Util.Selector):
167 """A callable dictionary that will, in turn, call the value it 178 """A callable dictionary that will, in turn, call the value it
168 finds if it can.""" 179 finds if it can."""
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 if t_contents == contents: 299 if t_contents == contents:
289 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)) 300 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))
290 SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarni ng, msg) 301 SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarni ng, msg)
291 else: 302 else:
292 msg = "Two environments with different actions were specifie d for the same target: %s" % t 303 msg = "Two environments with different actions were specifie d for the same target: %s" % t
293 raise UserError, msg 304 raise UserError, msg
294 if builder.multi: 305 if builder.multi:
295 if t.builder != builder: 306 if t.builder != builder:
296 msg = "Two different builders (%s and %s) were specified for the same target: %s" % (t.builder.get_name(env), builder.get_name(env), t) 307 msg = "Two different builders (%s and %s) were specified for the same target: %s" % (t.builder.get_name(env), builder.get_name(env), t)
297 raise UserError, msg 308 raise UserError, msg
298 if t.get_executor().targets != tlist: 309 # TODO(batch): list constructed each time!
299 msg = "Two different target lists have a target in common: % s (from %s and from %s)" % (t, map(str, t.get_executor().targets), map(str, tli st)) 310 if t.get_executor().get_all_targets() != tlist:
311 msg = "Two different target lists have a target in common: % s (from %s and from %s)" % (t, map(str, t.get_executor().get_all_targets()), ma p(str, tlist))
300 raise UserError, msg 312 raise UserError, msg
301 elif t.sources != slist: 313 elif t.sources != slist:
302 msg = "Multiple ways to build the same target were specified for : %s (from %s and from %s)" % (t, map(str, t.sources), map(str, slist)) 314 msg = "Multiple ways to build the same target were specified for : %s (from %s and from %s)" % (t, map(str, t.sources), map(str, slist))
303 raise UserError, msg 315 raise UserError, msg
304 316
305 if builder.single_source: 317 if builder.single_source:
306 if len(slist) > 1: 318 if len(slist) > 1:
307 raise UserError, "More than one source given for single-source build er: targets=%s sources=%s" % (map(str,tlist), map(str,slist)) 319 raise UserError, "More than one source given for single-source build er: targets=%s sources=%s" % (map(str,tlist), map(str,slist))
308 320
309 class EmitterProxy: 321 class EmitterProxy:
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 except AttributeError: 446 except AttributeError:
435 return str(self.__class__) 447 return str(self.__class__)
436 448
437 def __cmp__(self, other): 449 def __cmp__(self, other):
438 return cmp(self.__dict__, other.__dict__) 450 return cmp(self.__dict__, other.__dict__)
439 451
440 def splitext(self, path, env=None): 452 def splitext(self, path, env=None):
441 if not env: 453 if not env:
442 env = self.env 454 env = self.env
443 if env: 455 if env:
444 matchsuf = filter(lambda S,path=path: path[-len(S):] == S, 456 suffixes = self.src_suffixes(env)
445 self.src_suffixes(env))
446 if matchsuf:
447 suf = max(map(None, map(len, matchsuf), matchsuf))[1]
448 return [path[:-len(suf)], path[-len(suf):]]
449 return SCons.Util.splitext(path)
450
451 def get_single_executor(self, env, tlist, slist, executor_kw):
452 if not self.action:
453 raise UserError, "Builder %s must have an action to build %s."%(self .get_name(env or self.env), map(str,tlist))
454 return self.action.get_executor(env or self.env,
455 [], # env already has overrides
456 tlist,
457 slist,
458 executor_kw)
459
460 def get_multi_executor(self, env, tlist, slist, executor_kw):
461 try:
462 executor = tlist[0].get_executor(create = 0)
463 except (AttributeError, IndexError):
464 return self.get_single_executor(env, tlist, slist, executor_kw)
465 else: 457 else:
466 executor.add_sources(slist) 458 suffixes = []
467 return executor 459 return match_splitext(path, suffixes)
468 460
469 def _adjustixes(self, files, pre, suf, ensure_suffix=False): 461 def _adjustixes(self, files, pre, suf, ensure_suffix=False):
470 if not files: 462 if not files:
471 return [] 463 return []
472 result = [] 464 result = []
473 if not SCons.Util.is_List(files): 465 if not SCons.Util.is_List(files):
474 files = [files] 466 files = [files]
475 467
476 for f in files: 468 for f in files:
477 if SCons.Util.is_String(f): 469 if SCons.Util.is_String(f):
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 overwarn.warn() 551 overwarn.warn()
560 552
561 tlist, slist = self._create_nodes(env, target, source) 553 tlist, slist = self._create_nodes(env, target, source)
562 554
563 # Check for errors with the specified target/source lists. 555 # Check for errors with the specified target/source lists.
564 _node_errors(self, env, tlist, slist) 556 _node_errors(self, env, tlist, slist)
565 557
566 # The targets are fine, so find or make the appropriate Executor to 558 # The targets are fine, so find or make the appropriate Executor to
567 # build this particular list of targets from this particular list of 559 # build this particular list of targets from this particular list of
568 # sources. 560 # sources.
561
562 executor = None
563 key = None
564
569 if self.multi: 565 if self.multi:
570 get_executor = self.get_multi_executor 566 try:
571 else: 567 executor = tlist[0].get_executor(create = 0)
572 get_executor = self.get_single_executor 568 except (AttributeError, IndexError):
573 executor = get_executor(env, tlist, slist, executor_kw) 569 pass
570 else:
571 executor.add_sources(slist)
572
573 if executor is None:
574 if not self.action:
575 fmt = "Builder %s must have an action to build %s."
576 raise UserError, fmt % (self.get_name(env or self.env),
577 map(str,tlist))
578 key = self.action.batch_key(env or self.env, tlist, slist)
579 if key:
580 try:
581 executor = SCons.Executor.GetBatchExecutor(key)
582 except KeyError:
583 pass
584 else:
585 executor.add_batch(tlist, slist)
586
587 if executor is None:
588 executor = SCons.Executor.Executor(self.action, env, [],
589 tlist, slist, executor_kw)
590 if key:
591 SCons.Executor.AddBatchExecutor(key, executor)
574 592
575 # Now set up the relevant information in the target Nodes themselves. 593 # Now set up the relevant information in the target Nodes themselves.
576 for t in tlist: 594 for t in tlist:
577 t.cwd = env.fs.getcwd() 595 t.cwd = env.fs.getcwd()
578 t.builder_set(self) 596 t.builder_set(self)
579 t.env_set(env) 597 t.env_set(env)
580 t.add_source(slist) 598 t.add_source(slist)
581 t.set_executor(executor) 599 t.set_executor(executor)
582 t.set_explicit(self.is_explicit) 600 t.set_explicit(self.is_explicit)
583 601
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 if __debug__: logInstanceCreation(self, 'Builder.CompositeBuilder') 853 if __debug__: logInstanceCreation(self, 'Builder.CompositeBuilder')
836 SCons.Util.Proxy.__init__(self, builder) 854 SCons.Util.Proxy.__init__(self, builder)
837 855
838 # cmdgen should always be an instance of DictCmdGenerator. 856 # cmdgen should always be an instance of DictCmdGenerator.
839 self.cmdgen = cmdgen 857 self.cmdgen = cmdgen
840 self.builder = builder 858 self.builder = builder
841 859
842 def add_action(self, suffix, action): 860 def add_action(self, suffix, action):
843 self.cmdgen.add_action(suffix, action) 861 self.cmdgen.add_action(suffix, action)
844 self.set_src_suffix(self.cmdgen.src_suffixes()) 862 self.set_src_suffix(self.cmdgen.src_suffixes())
OLDNEW
« no previous file with comments | « third_party/scons/scons-local/SCons/Action.py ('k') | third_party/scons/scons-local/SCons/CacheDir.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698