Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 tool to build chrome, executed by buildbot. | 6 """A tool to build chrome, executed by buildbot. |
| 7 | 7 |
| 8 When this is run, the current directory (cwd) should be the outer build | 8 When this is run, the current directory (cwd) should be the outer build |
| 9 directory (e.g., chrome-release/build/). | 9 directory (e.g., chrome-release/build/). |
| 10 | 10 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 if not fh: | 64 if not fh: |
| 65 fh = sys.stdout | 65 fh = sys.stdout |
| 66 fh.write('Environment variables modified in compile.py:\n') | 66 fh.write('Environment variables modified in compile.py:\n') |
| 67 for k in sorted(list(self.overrides)): | 67 for k in sorted(list(self.overrides)): |
| 68 if k in self: | 68 if k in self: |
| 69 fh.write(' %s=%s\n' % (k, self[k])) | 69 fh.write(' %s=%s\n' % (k, self[k])) |
| 70 else: | 70 else: |
| 71 fh.write(' %s (removed)\n' % k) | 71 fh.write(' %s (removed)\n' % k) |
| 72 fh.write('\n') | 72 fh.write('\n') |
| 73 | 73 |
| 74 | 74 # TODO(tikuta): move to goma_utils.py |
|
shinyak
2016/07/21 02:53:07
nit: Two blank lines between top-level definitions
tikuta
2016/07/21 03:34:35
Done.
| |
| 75 def goma_setup(options, env): | 75 def goma_setup(options, env): |
| 76 """Sets up goma if necessary. | 76 """Sets up goma if necessary. |
| 77 | 77 |
| 78 If using the Goma compiler, first call goma_ctl to ensure the proxy is | 78 If using the Goma compiler, first call goma_ctl to ensure the proxy is |
| 79 available, and returns (True, instance of cloudtail subprocess). | 79 available, and returns (True, instance of cloudtail subprocess). |
| 80 If it failed to start up compiler_proxy, modify options.compiler and | 80 If it failed to start up compiler_proxy, modify options.compiler and |
| 81 options.goma_dir and returns (False, None) | 81 options.goma_dir and returns (False, None) |
| 82 | 82 |
| 83 """ | 83 """ |
| 84 if options.compiler not in ('goma', 'goma-clang'): | 84 if options.compiler not in ('goma', 'goma-clang'): |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 215 print 'warning: failed to start goma. falling back to non-goma' | 215 print 'warning: failed to start goma. falling back to non-goma' |
| 216 # Drop goma from options.compiler | 216 # Drop goma from options.compiler |
| 217 options.compiler = options.compiler.replace('goma-', '') | 217 options.compiler = options.compiler.replace('goma-', '') |
| 218 if options.compiler == 'goma': | 218 if options.compiler == 'goma': |
| 219 options.compiler = None | 219 options.compiler = None |
| 220 # Reset options.goma_dir. | 220 # Reset options.goma_dir. |
| 221 options.goma_dir = None | 221 options.goma_dir = None |
| 222 env['GOMA_DISABLED'] = '1' | 222 env['GOMA_DISABLED'] = '1' |
| 223 return False, None | 223 return False, None |
| 224 | 224 |
| 225 | 225 # TODO(tikuta): move to goma_utils.py |
|
shinyak
2016/07/21 02:53:07
ditto
tikuta
2016/07/21 03:34:35
Done.
| |
| 226 def goma_teardown(options, env, exit_status, cloudtail_proc): | 226 def goma_teardown(options, env, exit_status, cloudtail_proc): |
| 227 """Tears down goma if necessary. """ | 227 """Tears down goma if necessary. """ |
| 228 if (options.compiler in ('goma', 'goma-clang') and | 228 if (options.compiler in ('goma', 'goma-clang') and |
| 229 options.goma_dir): | 229 options.goma_dir): |
| 230 override_gsutil = None | 230 override_gsutil = None |
| 231 if options.gsutil_py_path: | 231 if options.gsutil_py_path: |
| 232 override_gsutil = [sys.executable, options.gsutil_py_path] | 232 override_gsutil = [sys.executable, options.gsutil_py_path] |
| 233 | 233 |
| 234 # If goma compiler_proxy crashes during the build, there could be crash | 234 # If goma compiler_proxy crashes during the build, there could be crash |
| 235 # dump. | 235 # dump. |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 if not entry: | 338 if not entry: |
| 339 continue | 339 continue |
| 340 key, value = entry.split('=', 1) | 340 key, value = entry.split('=', 1) |
| 341 env_in_file[key] = value | 341 env_in_file[key] = value |
| 342 env_in_file.update(env_to_store) | 342 env_in_file.update(env_to_store) |
| 343 with open(path, 'wb') as f: | 343 with open(path, 'wb') as f: |
| 344 f.write(nul.join(['%s=%s' % (k, v) for k, v in env_in_file.iteritems()])) | 344 f.write(nul.join(['%s=%s' % (k, v) for k, v in env_in_file.iteritems()])) |
| 345 f.write(nul * 2) | 345 f.write(nul * 2) |
| 346 | 346 |
| 347 | 347 |
| 348 def main_ninja(options, args): | 348 def main_ninja(options, args, env): |
| 349 """Interprets options, clobbers object files, and calls ninja.""" | 349 """This function calls ninja. |
| 350 | 350 |
| 351 # Prepare environment. | 351 Args: |
| 352 env = EchoDict(os.environ) | 352 options (Option): options for ninja command. |
| 353 goma_ready, goma_cloudtail = goma_setup(options, env) | 353 args (str): extra args for ninja command. |
| 354 exit_status = -1 | 354 env (dict): Used when ninja command executes. |
| 355 | |
| 356 Returns: | |
| 357 (int, str): first element for ninja command exit status. | |
| 358 second element is actual command to run ninja. | |
| 359 | |
| 360 """ | |
| 361 | |
| 355 try: | 362 try: |
| 356 if not goma_ready: | |
| 357 assert options.compiler not in ('goma', 'goma-clang') | |
| 358 assert options.goma_dir is None | |
| 359 | |
| 360 # ninja is different from all the other build systems in that it requires | |
| 361 # most configuration to be done at gyp time. This is why this function does | |
| 362 # less than the other comparable functions in this file. | |
| 363 print 'chdir to %s' % options.src_dir | 363 print 'chdir to %s' % options.src_dir |
| 364 os.chdir(options.src_dir) | 364 os.chdir(options.src_dir) |
| 365 | 365 |
| 366 command = [options.ninja_path, '-w', 'dupbuild=err', | 366 command = [options.ninja_path, '-w', 'dupbuild=err', |
| 367 '-C', options.target_output_dir] | 367 '-C', options.target_output_dir] |
| 368 | 368 |
| 369 # HACK(yyanagisawa): update environment files on |env| update. | 369 # HACK(yyanagisawa): update environment files on |env| update. |
| 370 # For compiling on Windows, environment in environment files are used. | 370 # For compiling on Windows, environment in environment files are used. |
| 371 # It means even if enviroment such as GOMA_DISABLED is updated in | 371 # It means even if enviroment such as GOMA_DISABLED is updated in |
| 372 # compile.py, the update will be ignored. | 372 # compile.py, the update will be ignored. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 if chromium_utils.IsMac() or chromium_utils.IsWindows(): | 420 if chromium_utils.IsMac() or chromium_utils.IsWindows(): |
| 421 return min(10 * number_of_processors, 200) | 421 return min(10 * number_of_processors, 200) |
| 422 | 422 |
| 423 # For Linux, we also would like to use 10 * cpu. However, not sure | 423 # For Linux, we also would like to use 10 * cpu. However, not sure |
| 424 # backend resource is enough, so let me set Linux and Linux x64 builder | 424 # backend resource is enough, so let me set Linux and Linux x64 builder |
| 425 # only for now. | 425 # only for now. |
| 426 hostname = goma_utils.GetShortHostname() | 426 hostname = goma_utils.GetShortHostname() |
| 427 if hostname in ( | 427 if hostname in ( |
| 428 ['build14-m1', 'build48-m1'] + | 428 ['build14-m1', 'build48-m1'] + |
| 429 # Also increasing cpus for v8/blink trybots. | 429 # Also increasing cpus for v8/blink trybots. |
| 430 ['build%d-m4' % x for x in xrange(45, 48)] + | 430 ['build%d-m4' % x for x in range(45, 48)] + |
| 431 # Also increasing cpus for LTO buildbots. | 431 # Also increasing cpus for LTO buildbots. |
| 432 ['slave%d-c1' % x for x in [20, 33] + range(78, 108)]): | 432 ['slave%d-c1' % x for x in [20, 33] + range(78, 108)]): |
| 433 return min(10 * number_of_processors, 200) | 433 return min(10 * number_of_processors, 200) |
| 434 | 434 |
| 435 return 50 | 435 return 50 |
| 436 | 436 |
| 437 goma_jobs = determine_goma_jobs() | 437 if not options.goma_jobs: |
| 438 goma_jobs = determine_goma_jobs() | |
| 439 else: | |
| 440 goma_jobs = options.goma_jobs | |
| 438 command.append('-j%d' % goma_jobs) | 441 command.append('-j%d' % goma_jobs) |
| 439 | 442 |
| 440 # Run the build. | 443 # Run the build. |
| 441 env.print_overrides() | 444 env.print_overrides() |
| 442 exit_status = chromium_utils.RunCommand(command, env=env) | 445 exit_status = chromium_utils.RunCommand(command, env=env) |
| 443 if exit_status == 0 and options.ninja_ensure_up_to_date: | 446 if exit_status == 0 and options.ninja_ensure_up_to_date: |
| 444 # Run the build again if we want to check that the no-op build is clean. | 447 # Run the build again if we want to check that the no-op build is clean. |
| 445 filter_obj = EnsureUpToDateFilter() | 448 filter_obj = EnsureUpToDateFilter() |
| 446 # Append `-d explain` to help diagnose in the failure case. | 449 # Append `-d explain` to help diagnose in the failure case. |
| 447 command += ['-d', 'explain'] | 450 command += ['-d', 'explain'] |
| 448 chromium_utils.RunCommand(command, env=env, filter_obj=filter_obj) | 451 chromium_utils.RunCommand(command, env=env, filter_obj=filter_obj) |
| 449 if not filter_obj.was_up_to_date: | 452 if not filter_obj.was_up_to_date: |
| 450 print 'Failing build because ninja reported work to do.' | 453 print 'Failing build because ninja reported work to do.' |
| 451 print 'This means that after completing a compile, another was run and' | 454 print 'This means that after completing a compile, another was run and' |
| 452 print 'it resulted in still having work to do (that is, a no-op build' | 455 print 'it resulted in still having work to do (that is, a no-op build' |
| 453 print 'wasn\'t a no-op). Consult the first "ninja explain:" line for a' | 456 print 'wasn\'t a no-op). Consult the first "ninja explain:" line for a' |
| 454 print 'likely culprit.' | 457 print 'likely culprit.' |
| 455 return 1 | 458 return 1 |
| 456 return exit_status | 459 return exit_status |
| 457 finally: | 460 finally: |
| 458 goma_teardown(options, env, exit_status, goma_cloudtail) | |
| 459 | |
| 460 override_gsutil = None | 461 override_gsutil = None |
| 461 if options.gsutil_py_path: | 462 if options.gsutil_py_path: |
| 462 override_gsutil = [sys.executable, options.gsutil_py_path] | 463 override_gsutil = [sys.executable, options.gsutil_py_path] |
| 463 | 464 |
| 464 goma_utils.UploadNinjaLog( | 465 goma_utils.UploadNinjaLog( |
| 465 options.target_output_dir, options.compiler, command, exit_status, | 466 options.target_output_dir, options.compiler, command, exit_status, |
| 466 override_gsutil=override_gsutil) | 467 override_gsutil=override_gsutil) |
| 467 | 468 |
| 468 | 469 |
| 469 def get_target_build_dir(args, options): | 470 def get_target_build_dir(args, options): |
| 470 """Keep this function in sync with src/build/landmines.py""" | 471 """Keep this function in sync with src/build/landmines.py""" |
| 471 if chromium_utils.IsLinux() and options.cros_board: | 472 if chromium_utils.IsLinux() and options.cros_board: |
| 472 # When building ChromeOS's Simple Chrome workflow, the output directory | 473 # When building ChromeOS's Simple Chrome workflow, the output directory |
| 473 # has a CROS board name suffix. | 474 # has a CROS board name suffix. |
| 474 outdir = 'out_%s' % (options.cros_board,) | 475 outdir = 'out_%s' % (options.cros_board,) |
| 475 elif options.out_dir: | 476 elif options.out_dir: |
| 476 outdir = options.out_dir | 477 outdir = options.out_dir |
| 477 else: | 478 else: |
| 478 outdir = 'out' | 479 outdir = 'out' |
| 479 return os.path.abspath(os.path.join(options.src_dir, outdir, options.target)) | 480 return os.path.abspath(os.path.join(options.src_dir, outdir, options.target)) |
| 480 | 481 |
| 481 | 482 |
| 482 def real_main(): | 483 def get_parsed_options(): |
| 483 option_parser = optparse.OptionParser() | 484 option_parser = optparse.OptionParser() |
| 484 option_parser.add_option('--clobber', action='store_true', default=False, | 485 option_parser.add_option('--clobber', action='store_true', default=False, |
| 485 help='delete the output directory before compiling') | 486 help='delete the output directory before compiling') |
| 486 option_parser.add_option('--target', default='Release', | 487 option_parser.add_option('--target', default='Release', |
| 487 help='build target (Debug or Release)') | 488 help='build target (Debug or Release)') |
| 488 option_parser.add_option('--src-dir', default=None, | 489 option_parser.add_option('--src-dir', default=None, |
| 489 help='path to the root of the source tree') | 490 help='path to the root of the source tree') |
| 490 option_parser.add_option('--mode', default='dev', | 491 option_parser.add_option('--mode', default='dev', |
| 491 help='build mode (dev or official) controlling ' | 492 help='build mode (dev or official) controlling ' |
| 492 'environment variables set during build') | 493 'environment variables set during build') |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 521 help='Enable goma CompilerInfo cache') | 522 help='Enable goma CompilerInfo cache') |
| 522 option_parser.add_option('--goma-store-local-run-output', default=None, | 523 option_parser.add_option('--goma-store-local-run-output', default=None, |
| 523 help='Store local run output to goma servers.') | 524 help='Store local run output to goma servers.') |
| 524 option_parser.add_option('--goma-fail-fast', action='store_true') | 525 option_parser.add_option('--goma-fail-fast', action='store_true') |
| 525 option_parser.add_option('--goma-disable-local-fallback', action='store_true') | 526 option_parser.add_option('--goma-disable-local-fallback', action='store_true') |
| 526 option_parser.add_option('--goma-jsonstatus', | 527 option_parser.add_option('--goma-jsonstatus', |
| 527 help='Specify a file to dump goma_ctl jsonstatus.') | 528 help='Specify a file to dump goma_ctl jsonstatus.') |
| 528 option_parser.add_option('--goma-service-account-json-file', | 529 option_parser.add_option('--goma-service-account-json-file', |
| 529 help='Specify a file containing goma service account' | 530 help='Specify a file containing goma service account' |
| 530 ' credentials') | 531 ' credentials') |
| 532 option_parser.add_option('--goma-jobs', default=None, | |
| 533 help='The number of jobs for ninja -j.') | |
| 531 option_parser.add_option('--gsutil-py-path', | 534 option_parser.add_option('--gsutil-py-path', |
| 532 help='Specify path to gsutil.py script.') | 535 help='Specify path to gsutil.py script.') |
| 533 option_parser.add_option('--ninja-path', default='ninja', | 536 option_parser.add_option('--ninja-path', default='ninja', |
| 534 help='Specify path to the ninja tool.') | 537 help='Specify path to the ninja tool.') |
| 535 option_parser.add_option('--ninja-ensure-up-to-date', action='store_true', | 538 option_parser.add_option('--ninja-ensure-up-to-date', action='store_true', |
| 536 help='Checks the output of the ninja builder to ' | 539 help='Checks the output of the ninja builder to ' |
| 537 'confirm that a second compile immediately ' | 540 'confirm that a second compile immediately ' |
| 538 'the first is a no-op.') | 541 'the first is a no-op.') |
| 539 | 542 |
| 540 options, args = option_parser.parse_args() | 543 options, args = option_parser.parse_args() |
| 541 | 544 |
| 542 if not options.src_dir: | 545 if not options.src_dir: |
| 543 options.src_dir = 'src' | 546 options.src_dir = 'src' |
| 544 options.src_dir = os.path.abspath(options.src_dir) | 547 options.src_dir = os.path.abspath(options.src_dir) |
| 545 | 548 |
| 546 options.target_output_dir = get_target_build_dir(args, options) | 549 options.target_output_dir = get_target_build_dir(args, options) |
| 547 | 550 |
| 548 assert options.build_tool in (None, 'ninja') | 551 assert options.build_tool in (None, 'ninja') |
| 549 return main_ninja(options, args) | 552 return options, args |
| 553 | |
| 554 | |
| 555 def real_main(): | |
| 556 options, args = get_parsed_options() | |
| 557 | |
| 558 # Prepare environment. | |
| 559 env = EchoDict(os.environ) | |
| 560 | |
| 561 # start goma | |
| 562 goma_ready, goma_cloudtail = goma_setup(options, env) | |
| 563 | |
| 564 if not goma_ready: | |
| 565 assert options.compiler not in ('goma', 'goma-clang') | |
| 566 assert options.goma_dir is None | |
| 567 | |
| 568 # build | |
| 569 exit_status = main_ninja(options, args, env) | |
| 570 | |
| 571 # stop goma | |
| 572 goma_teardown(options, env, exit_status, goma_cloudtail) | |
| 573 | |
| 574 return exit_status | |
| 550 | 575 |
| 551 | 576 |
| 552 if '__main__' == __name__: | 577 if '__main__' == __name__: |
| 553 sys.exit(real_main()) | 578 sys.exit(real_main()) |
| OLD | NEW |