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

Side by Side Diff: toolchain_build/toolchain_main.py

Issue 1111913003: toolchain_build: Avoid python tracebacks for package build errors (Closed) Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Created 5 years, 7 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
« no previous file with comments | « toolchain_build/toolchain_build_pnacl.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Build NativeClient toolchain packages.""" 6 """Build NativeClient toolchain packages."""
7 7
8 import logging 8 import logging
9 import optparse 9 import optparse
10 import os 10 import os
11 import subprocess
11 import sys 12 import sys
12 import textwrap 13 import textwrap
13 14
14 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) 15 sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
15 import pynacl.file_tools 16 import pynacl.file_tools
16 import pynacl.gsd_storage 17 import pynacl.gsd_storage
17 import pynacl.log_tools 18 import pynacl.log_tools
18 import pynacl.local_storage_cache 19 import pynacl.local_storage_cache
19 20
20 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 21 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
(...skipping 22 matching lines...) Expand all
43 """ 44 """
44 if cloud_item.dir_item: 45 if cloud_item.dir_item:
45 url = cloud_item.dir_item.url 46 url = cloud_item.dir_item.url
46 pynacl.log_tools.WriteAnnotatorLine('@@@STEP_LINK@download@%s@@@' % url) 47 pynacl.log_tools.WriteAnnotatorLine('@@@STEP_LINK@download@%s@@@' % url)
47 48
48 if cloud_item.log_url: 49 if cloud_item.log_url:
49 log_url = cloud_item.log_url 50 log_url = cloud_item.log_url
50 pynacl.log_tools.WriteAnnotatorLine('@@@STEP_LINK@log@%s@@@' % log_url) 51 pynacl.log_tools.WriteAnnotatorLine('@@@STEP_LINK@log@%s@@@' % log_url)
51 52
52 53
54 class BuildError(Exception):
55 pass
56
53 class PackageBuilder(object): 57 class PackageBuilder(object):
54 """Module to build a setup of packages.""" 58 """Module to build a setup of packages."""
55 59
56 def __init__(self, packages, package_targets, args): 60 def __init__(self, packages, package_targets, args):
57 """Constructor. 61 """Constructor.
58 62
59 Args: 63 Args:
60 packages: A dictionary with the following format. There are two types of 64 packages: A dictionary with the following format. There are two types of
61 packages: source and build (described below). 65 packages: source and build (described below).
62 { 66 {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 def Main(self): 156 def Main(self):
153 """Main entry point.""" 157 """Main entry point."""
154 pynacl.file_tools.MakeDirectoryIfAbsent(self._options.source) 158 pynacl.file_tools.MakeDirectoryIfAbsent(self._options.source)
155 pynacl.file_tools.MakeDirectoryIfAbsent(self._options.output) 159 pynacl.file_tools.MakeDirectoryIfAbsent(self._options.output)
156 160
157 pynacl.log_tools.SetupLogging( 161 pynacl.log_tools.SetupLogging(
158 verbose=self._options.verbose, 162 verbose=self._options.verbose,
159 log_file=self._options.log_file, 163 log_file=self._options.log_file,
160 quiet=self._options.quiet, 164 quiet=self._options.quiet,
161 no_annotator=self._options.no_annotator) 165 no_annotator=self._options.no_annotator)
162 self.BuildAll() 166 try:
163 self.OutputPackagesInformation() 167 self.BuildAll()
168 self.OutputPackagesInformation()
169 except BuildError as e:
170 print e
171 return 1
172 return 0
164 173
165 def GetOutputDir(self, package, use_subdir): 174 def GetOutputDir(self, package, use_subdir):
166 # The output dir of source packages is in the source directory, and can be 175 # The output dir of source packages is in the source directory, and can be
167 # overridden. 176 # overridden.
168 if self._packages[package]['type'] == 'source': 177 if self._packages[package]['type'] == 'source':
169 dirname = self._packages[package].get('output_dirname', package) 178 dirname = self._packages[package].get('output_dirname', package)
170 return os.path.join(self._options.source, dirname) 179 return os.path.join(self._options.source, dirname)
171 else: 180 else:
172 root = os.path.join(self._options.output, package + '_install') 181 root = os.path.join(self._options.output, package + '_install')
173 if use_subdir and 'output_subdir' in self._packages[package]: 182 if use_subdir and 'output_subdir' in self._packages[package]:
174 return os.path.join(root, self._packages[package]['output_subdir']) 183 return os.path.join(root, self._packages[package]['output_subdir'])
175 return root 184 return root
176 185
177 def BuildPackage(self, package): 186 def BuildPackage(self, package):
178 """Build a single package. 187 """Build a single package.
179 188
180 Assumes dependencies of the package have been built. 189 Assumes dependencies of the package have been built.
181 Args: 190 Args:
182 package: Package to build. 191 package: Package to build.
183 """ 192 """
184 193
185 package_info = self._packages[package] 194 package_info = self._packages[package]
186 195
187 # Validate the package description. 196 # Validate the package description.
188 if 'type' not in package_info: 197 if 'type' not in package_info:
189 raise Exception('package %s does not have a type' % package) 198 raise BuildError('package %s does not have a type' % package)
190 type_text = package_info['type'] 199 type_text = package_info['type']
191 if type_text not in ('source', 'build', 'build_noncanonical', 'work'): 200 if type_text not in ('source', 'build', 'build_noncanonical', 'work'):
192 raise Exception('package %s has unrecognized type: %s' % 201 raise BuildError('package %s has unrecognized type: %s' %
193 (package, type_text)) 202 (package, type_text))
194 is_source_target = type_text == 'source' 203 is_source_target = type_text == 'source'
195 is_build_target = type_text in ('build', 'build_noncanonical') 204 is_build_target = type_text in ('build', 'build_noncanonical')
196 build_signature_key_extra = '' 205 build_signature_key_extra = ''
197 if type_text == 'build_noncanonical': 206 if type_text == 'build_noncanonical':
198 build_signature_key_extra = '_' + pynacl.gsd_storage.LegalizeName( 207 build_signature_key_extra = '_' + pynacl.gsd_storage.LegalizeName(
199 pynacl.platform.PlatformTriple()) 208 pynacl.platform.PlatformTriple())
200 209
201 if 'commands' not in package_info: 210 if 'commands' not in package_info:
202 raise Exception('package %s does not have any commands' % package) 211 raise BuildError('package %s does not have any commands' % package)
203 212
204 # Source targets are the only ones to run when doing sync-only. 213 # Source targets are the only ones to run when doing sync-only.
205 if not is_source_target and self._options.sync_sources_only: 214 if not is_source_target and self._options.sync_sources_only:
206 logging.debug('Build skipped: not running commands for %s' % package) 215 logging.debug('Build skipped: not running commands for %s' % package)
207 return 216 return
208 217
209 # Source targets do not run when skipping sync. 218 # Source targets do not run when skipping sync.
210 if is_source_target and not ( 219 if is_source_target and not (
211 self._options.sync_sources or self._options.sync_sources_only): 220 self._options.sync_sources or self._options.sync_sources_only):
212 logging.debug('Sync skipped: not running commands for %s' % package) 221 logging.debug('Sync skipped: not running commands for %s' % package)
213 return 222 return
214 223
215 if type_text == 'build_noncanonical' and self._options.canonical_only: 224 if type_text == 'build_noncanonical' and self._options.canonical_only:
216 logging.debug('Non-canonical build of %s skipped' % package) 225 logging.debug('Non-canonical build of %s skipped' % package)
217 return 226 return
218 227
219 pynacl.log_tools.WriteAnnotatorLine( 228 pynacl.log_tools.WriteAnnotatorLine(
220 '@@@BUILD_STEP %s (%s)@@@' % (package, type_text)) 229 '@@@BUILD_STEP %s (%s)@@@' % (package, type_text))
221 logging.debug('Building %s package %s' % (type_text, package)) 230 logging.debug('Building %s package %s' % (type_text, package))
222 231
223 dependencies = package_info.get('dependencies', []) 232 dependencies = package_info.get('dependencies', [])
224 233
225 # Collect a dict of all the inputs. 234 # Collect a dict of all the inputs.
226 inputs = {} 235 inputs = {}
227 # Add in explicit inputs. 236 # Add in explicit inputs.
228 if 'inputs' in package_info: 237 if 'inputs' in package_info:
229 for key, value in package_info['inputs'].iteritems(): 238 for key, value in package_info['inputs'].iteritems():
230 if key in dependencies: 239 if key in dependencies:
231 raise Exception('key "%s" found in both dependencies and inputs of ' 240 raise BuildError('key "%s" found in both dependencies and inputs of '
232 'package "%s"' % (key, package)) 241 'package "%s"' % (key, package))
233 inputs[key] = value 242 inputs[key] = value
234 elif type_text != 'source': 243 elif type_text != 'source':
235 # Non-source packages default to a particular input directory. 244 # Non-source packages default to a particular input directory.
236 inputs['src'] = os.path.join(self._options.source, package) 245 inputs['src'] = os.path.join(self._options.source, package)
237 # Add in each dependency by package name. 246 # Add in each dependency by package name.
238 for dependency in dependencies: 247 for dependency in dependencies:
239 inputs[dependency] = self.GetOutputDir(dependency, True) 248 inputs[dependency] = self.GetOutputDir(dependency, True)
240 249
241 # Each package generates intermediate into output/<PACKAGE>_work. 250 # Each package generates intermediate into output/<PACKAGE>_work.
(...skipping 16 matching lines...) Expand all
258 267
259 # Create a command option object specifying current build. 268 # Create a command option object specifying current build.
260 cmd_options = command_options.CommandOptions( 269 cmd_options = command_options.CommandOptions(
261 work_dir=work_dir, 270 work_dir=work_dir,
262 clobber_working=self._options.clobber, 271 clobber_working=self._options.clobber,
263 clobber_source=self._options.clobber_source, 272 clobber_source=self._options.clobber_source,
264 trybot=self._options.trybot, 273 trybot=self._options.trybot,
265 buildbot=self._options.buildbot) 274 buildbot=self._options.buildbot)
266 275
267 # Do it. 276 # Do it.
268 self._build_once.Run( 277 try:
278 self._build_once.Run(
269 package, inputs, output, 279 package, inputs, output,
270 commands=commands, 280 commands=commands,
271 cmd_options=cmd_options, 281 cmd_options=cmd_options,
272 working_dir=work_dir, 282 working_dir=work_dir,
273 memoize=is_build_target, 283 memoize=is_build_target,
274 signature_file=self._signature_file, 284 signature_file=self._signature_file,
275 subdir=output_subdir, 285 subdir=output_subdir,
276 bskey_extra = build_signature_key_extra) 286 bskey_extra = build_signature_key_extra)
287 except subprocess.CalledProcessError as e:
288 raise BuildError(
289 'Error building %s: %s' % (package, str(e)))
277 290
278 if not is_source_target and self._options.install: 291 if not is_source_target and self._options.install:
279 install = pynacl.platform.CygPath(self._options.install) 292 install = pynacl.platform.CygPath(self._options.install)
280 logging.debug('Installing output to %s' % install) 293 logging.debug('Installing output to %s' % install)
281 pynacl.file_tools.CopyTree(output, install) 294 pynacl.file_tools.CopyTree(output, install)
282 295
283 def BuildOrder(self, targets): 296 def BuildOrder(self, targets):
284 """Find what needs to be built in what order to build all targets. 297 """Find what needs to be built in what order to build all targets.
285 298
286 Args: 299 Args:
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 """Returns a dictionary of extra substitution paths allowed for commands.""" 530 """Returns a dictionary of extra substitution paths allowed for commands."""
518 if self._options.disable_git_cache: 531 if self._options.disable_git_cache:
519 git_cache_dir = '' 532 git_cache_dir = ''
520 else: 533 else:
521 git_cache_dir = self._options.git_cache 534 git_cache_dir = self._options.git_cache
522 535
523 return { 536 return {
524 'top_srcdir': NACL_DIR, 537 'top_srcdir': NACL_DIR,
525 'git_cache_dir': git_cache_dir, 538 'git_cache_dir': git_cache_dir,
526 } 539 }
OLDNEW
« no previous file with comments | « toolchain_build/toolchain_build_pnacl.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698