Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium 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 """A utility script for downloading versioned Syzygy binaries.""" | 6 """A utility script for downloading versioned Syzygy binaries.""" |
| 7 | 7 |
| 8 import hashlib | 8 import hashlib |
| 9 import errno | 9 import errno |
| 10 import fnmatch | |
| 10 import json | 11 import json |
| 11 import logging | 12 import logging |
| 12 import optparse | 13 import optparse |
| 13 import os | 14 import os |
| 14 import re | 15 import re |
| 15 import shutil | 16 import shutil |
| 16 import stat | 17 import stat |
| 17 import sys | 18 import sys |
| 18 import subprocess | 19 import subprocess |
| 19 import tempfile | 20 import tempfile |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 41 # List of reources to be downloaded and installed. These are tuples with the | 42 # List of reources to be downloaded and installed. These are tuples with the |
| 42 # following format: | 43 # following format: |
| 43 # (basename, logging name, relative installation path, extraction filter) | 44 # (basename, logging name, relative installation path, extraction filter) |
| 44 _RESOURCES = [ | 45 _RESOURCES = [ |
| 45 ('benchmark.zip', 'benchmark', '', None), | 46 ('benchmark.zip', 'benchmark', '', None), |
| 46 ('binaries.zip', 'binaries', 'exe', None), | 47 ('binaries.zip', 'binaries', 'exe', None), |
| 47 ('symbols.zip', 'symbols', 'exe', | 48 ('symbols.zip', 'symbols', 'exe', |
| 48 lambda x: x.filename.endswith('.dll.pdb'))] | 49 lambda x: x.filename.endswith('.dll.pdb'))] |
| 49 | 50 |
| 50 | 51 |
| 52 # Name of the MS DIA dll that we need to copy to the binaries directory. | |
| 53 _DIA_DLL_NAME = "msdia140.dll" | |
| 54 | |
| 55 | |
| 51 def _LoadState(output_dir): | 56 def _LoadState(output_dir): |
| 52 """Loads the contents of the state file for a given |output_dir|, returning | 57 """Loads the contents of the state file for a given |output_dir|, returning |
| 53 None if it doesn't exist. | 58 None if it doesn't exist. |
| 54 """ | 59 """ |
| 55 path = os.path.join(output_dir, _STATE) | 60 path = os.path.join(output_dir, _STATE) |
| 56 if not os.path.exists(path): | 61 if not os.path.exists(path): |
| 57 _LOGGER.debug('No state file found.') | 62 _LOGGER.debug('No state file found.') |
| 58 return None | 63 return None |
| 59 with open(path, 'rb') as f: | 64 with open(path, 'rb') as f: |
| 60 _LOGGER.debug('Reading state file: %s', path) | 65 _LOGGER.debug('Reading state file: %s', path) |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 275 | 280 |
| 276 def _Download(resource): | 281 def _Download(resource): |
| 277 """Downloads the given GS resource to a temporary file, returning its path.""" | 282 """Downloads the given GS resource to a temporary file, returning its path.""" |
| 278 tmp = tempfile.mkstemp(suffix='syzygy_archive') | 283 tmp = tempfile.mkstemp(suffix='syzygy_archive') |
| 279 os.close(tmp[0]) | 284 os.close(tmp[0]) |
| 280 url = 'gs://syzygy-archive' + resource | 285 url = 'gs://syzygy-archive' + resource |
| 281 _GsUtil('cp', url, tmp[1]) | 286 _GsUtil('cp', url, tmp[1]) |
| 282 return tmp[1] | 287 return tmp[1] |
| 283 | 288 |
| 284 | 289 |
| 290 def _MaybeCopyDIABinaries(options, contents): | |
| 291 """Try to copy the DIA DLL to the binaries exe directory. | |
| 292 | |
| 293 This doesn't check if the toolchain version of this DLL is the same as the | |
| 294 one used by the Syzygy binaries, so this will only be useful if Chrome and | |
| 295 Syzygy are using the same revision of the toolchain. | |
| 296 """ | |
| 297 toolchain_data_file = os.path.join(os.path.dirname(__file__), | |
| 298 'win_toolchain.json') | |
| 299 if not os.path.exists(toolchain_data_file): | |
| 300 _LOGGER.debug('Toolchain JSON data file doesn\'t exist.') | |
| 301 return | |
| 302 _LOGGER.debug('%s exists' % toolchain_data_file) | |
| 303 with open(toolchain_data_file) as temp_f: | |
| 304 toolchain_data = json.load(temp_f) | |
| 305 if not os.path.isdir(toolchain_data['path']): | |
| 306 _LOGGER.error('The toolchain JSON file is invalid.') | |
| 307 return | |
| 308 dia_sdk_binaries_dir = os.path.join(toolchain_data['path'], 'DIA SDK', 'bin') | |
| 309 dia_dll = os.path.join(dia_sdk_binaries_dir, _DIA_DLL_NAME) | |
| 310 if not os.path.exists(dia_dll): | |
| 311 raise Exception('%s is missing.') | |
| 312 dia_dll_dest = os.path.join(options.output_dir, 'exe', binary) | |
|
scottmg
2016/10/03 20:49:28
binary -> _DIA_DLL_NAME
| |
| 313 _LOGGER.debug('Copying %s to %s.' % (dia_dll, dia_dll_dest)) | |
| 314 if not options.dry_run: | |
| 315 shutil.copy(dia_dll, dia_dll_dest) | |
| 316 contents[os.path.relpath(dia_dll_dest, options.output_dir)] = ( | |
| 317 _Md5(dia_dll_dest)) | |
| 318 return | |
|
scottmg
2016/10/03 20:49:28
Remove 'return'
| |
| 319 | |
| 320 | |
| 285 def _InstallBinaries(options, deleted={}): | 321 def _InstallBinaries(options, deleted={}): |
| 286 """Installs Syzygy binaries. This assumes that the output directory has | 322 """Installs Syzygy binaries. This assumes that the output directory has |
| 287 already been cleaned, as it will refuse to overwrite existing files.""" | 323 already been cleaned, as it will refuse to overwrite existing files.""" |
| 288 contents = {} | 324 contents = {} |
| 289 state = { 'revision': options.revision, 'contents': contents } | 325 state = { 'revision': options.revision, 'contents': contents } |
| 290 archive_path = _SYZYGY_ARCHIVE_PATH % { 'revision': options.revision } | 326 archive_path = _SYZYGY_ARCHIVE_PATH % { 'revision': options.revision } |
| 291 if options.resources: | 327 if options.resources: |
| 292 resources = [(resource, resource, '', None) | 328 resources = [(resource, resource, '', None) |
| 293 for resource in options.resources] | 329 for resource in options.resources] |
| 294 else: | 330 else: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 if not options.dry_run: | 365 if not options.dry_run: |
| 330 archive.extract(entry.filename, fulldir) | 366 archive.extract(entry.filename, fulldir) |
| 331 md5 = _Md5(fullpath) | 367 md5 = _Md5(fullpath) |
| 332 contents[relpath] = md5 | 368 contents[relpath] = md5 |
| 333 if sys.platform == 'cygwin': | 369 if sys.platform == 'cygwin': |
| 334 os.chmod(fullpath, os.stat(fullpath).st_mode | stat.S_IXUSR) | 370 os.chmod(fullpath, os.stat(fullpath).st_mode | stat.S_IXUSR) |
| 335 | 371 |
| 336 _LOGGER.debug('Removing temporary file "%s".', path) | 372 _LOGGER.debug('Removing temporary file "%s".', path) |
| 337 os.remove(path) | 373 os.remove(path) |
| 338 | 374 |
| 375 if options.copy_dia_binaries: | |
| 376 # Try to copy the DIA binaries to the binaries directory. | |
| 377 _MaybeCopyDIABinaries(options, contents) | |
| 378 | |
| 339 return state | 379 return state |
| 340 | 380 |
| 341 | 381 |
| 342 def _ParseCommandLine(): | 382 def _ParseCommandLine(): |
| 343 """Parses the command-line and returns an options structure.""" | 383 """Parses the command-line and returns an options structure.""" |
| 344 option_parser = optparse.OptionParser() | 384 option_parser = optparse.OptionParser() |
| 345 option_parser.add_option('--dry-run', action='store_true', default=False, | 385 option_parser.add_option('--dry-run', action='store_true', default=False, |
| 346 help='If true then will simply list actions that would be performed.') | 386 help='If true then will simply list actions that would be performed.') |
| 347 option_parser.add_option('--force', action='store_true', default=False, | 387 option_parser.add_option('--force', action='store_true', default=False, |
| 348 help='Force an installation even if the binaries are up to date.') | 388 help='Force an installation even if the binaries are up to date.') |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 360 option_parser.add_option('--revision-file', type='string', | 400 option_parser.add_option('--revision-file', type='string', |
| 361 help='A text file containing an SVN revision or GIT hash.') | 401 help='A text file containing an SVN revision or GIT hash.') |
| 362 option_parser.add_option('--resource', type='string', action='append', | 402 option_parser.add_option('--resource', type='string', action='append', |
| 363 dest='resources', help='A resource to be downloaded.') | 403 dest='resources', help='A resource to be downloaded.') |
| 364 option_parser.add_option('--verbose', dest='log_level', action='store_const', | 404 option_parser.add_option('--verbose', dest='log_level', action='store_const', |
| 365 default=logging.INFO, const=logging.DEBUG, | 405 default=logging.INFO, const=logging.DEBUG, |
| 366 help='Enables verbose logging.') | 406 help='Enables verbose logging.') |
| 367 option_parser.add_option('--quiet', dest='log_level', action='store_const', | 407 option_parser.add_option('--quiet', dest='log_level', action='store_const', |
| 368 default=logging.INFO, const=logging.ERROR, | 408 default=logging.INFO, const=logging.ERROR, |
| 369 help='Disables all output except for errors.') | 409 help='Disables all output except for errors.') |
| 410 option_parser.add_option('--copy-dia-binaries', action='store_true', | |
| 411 default=False, help='If true then the DIA dll will get copied into the ' | |
| 412 'binaries directory if it\'s available.') | |
| 370 options, args = option_parser.parse_args() | 413 options, args = option_parser.parse_args() |
| 371 if args: | 414 if args: |
| 372 option_parser.error('Unexpected arguments: %s' % args) | 415 option_parser.error('Unexpected arguments: %s' % args) |
| 373 if not options.output_dir: | 416 if not options.output_dir: |
| 374 option_parser.error('Must specify --output-dir.') | 417 option_parser.error('Must specify --output-dir.') |
| 375 if not options.revision and not options.revision_file: | 418 if not options.revision and not options.revision_file: |
| 376 option_parser.error('Must specify one of --revision or --revision-file.') | 419 option_parser.error('Must specify one of --revision or --revision-file.') |
| 377 if options.revision and options.revision_file: | 420 if options.revision and options.revision_file: |
| 378 option_parser.error('Must not specify both --revision and --revision-file.') | 421 option_parser.error('Must not specify both --revision and --revision-file.') |
| 379 | 422 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 # Install the new binaries. In a dry-run this will actually download the | 521 # Install the new binaries. In a dry-run this will actually download the |
| 479 # archives, but it won't write anything to disk. | 522 # archives, but it won't write anything to disk. |
| 480 state = _InstallBinaries(options, deleted) | 523 state = _InstallBinaries(options, deleted) |
| 481 | 524 |
| 482 # Build and save the state for the directory. | 525 # Build and save the state for the directory. |
| 483 _SaveState(options.output_dir, state, options.dry_run) | 526 _SaveState(options.output_dir, state, options.dry_run) |
| 484 | 527 |
| 485 | 528 |
| 486 if __name__ == '__main__': | 529 if __name__ == '__main__': |
| 487 main() | 530 main() |
| OLD | NEW |