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

Side by Side Diff: scripts/slave/compile.py

Issue 2155413003: Refactoring: separate build steps in real_main for compile.py (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: fix docstring in main_ninja Created 4 years, 5 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 | « no previous file | 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/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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
75 # TODO(tikuta): move to goma_utils.py
75 def goma_setup(options, env): 76 def goma_setup(options, env):
76 """Sets up goma if necessary. 77 """Sets up goma if necessary.
77 78
78 If using the Goma compiler, first call goma_ctl to ensure the proxy is 79 If using the Goma compiler, first call goma_ctl to ensure the proxy is
79 available, and returns (True, instance of cloudtail subprocess). 80 available, and returns (True, instance of cloudtail subprocess).
80 If it failed to start up compiler_proxy, modify options.compiler and 81 If it failed to start up compiler_proxy, modify options.compiler and
81 options.goma_dir and returns (False, None) 82 options.goma_dir and returns (False, None)
82 83
83 """ 84 """
84 if options.compiler not in ('goma', 'goma-clang'): 85 if options.compiler not in ('goma', 'goma-clang'):
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 # Drop goma from options.compiler 217 # Drop goma from options.compiler
217 options.compiler = options.compiler.replace('goma-', '') 218 options.compiler = options.compiler.replace('goma-', '')
218 if options.compiler == 'goma': 219 if options.compiler == 'goma':
219 options.compiler = None 220 options.compiler = None
220 # Reset options.goma_dir. 221 # Reset options.goma_dir.
221 options.goma_dir = None 222 options.goma_dir = None
222 env['GOMA_DISABLED'] = '1' 223 env['GOMA_DISABLED'] = '1'
223 return False, None 224 return False, None
224 225
225 226
227 # TODO(tikuta): move to goma_utils.py
226 def goma_teardown(options, env, exit_status, cloudtail_proc): 228 def goma_teardown(options, env, exit_status, cloudtail_proc):
227 """Tears down goma if necessary. """ 229 """Tears down goma if necessary. """
228 if (options.compiler in ('goma', 'goma-clang') and 230 if (options.compiler in ('goma', 'goma-clang') and
229 options.goma_dir): 231 options.goma_dir):
230 override_gsutil = None 232 override_gsutil = None
231 if options.gsutil_py_path: 233 if options.gsutil_py_path:
232 override_gsutil = [sys.executable, options.gsutil_py_path] 234 override_gsutil = [sys.executable, options.gsutil_py_path]
233 235
234 # If goma compiler_proxy crashes during the build, there could be crash 236 # If goma compiler_proxy crashes during the build, there could be crash
235 # dump. 237 # dump.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 if not entry: 340 if not entry:
339 continue 341 continue
340 key, value = entry.split('=', 1) 342 key, value = entry.split('=', 1)
341 env_in_file[key] = value 343 env_in_file[key] = value
342 env_in_file.update(env_to_store) 344 env_in_file.update(env_to_store)
343 with open(path, 'wb') as f: 345 with open(path, 'wb') as f:
344 f.write(nul.join(['%s=%s' % (k, v) for k, v in env_in_file.iteritems()])) 346 f.write(nul.join(['%s=%s' % (k, v) for k, v in env_in_file.iteritems()]))
345 f.write(nul * 2) 347 f.write(nul * 2)
346 348
347 349
348 def main_ninja(options, args): 350 # TODO(tikuta): move to goma_utils
349 """Interprets options, clobbers object files, and calls ninja.""" 351 def determine_goma_jobs():
352 # We would like to speed up build on Windows a bit, since it is slowest.
353 number_of_processors = 0
354 try:
355 number_of_processors = multiprocessing.cpu_count()
356 except NotImplementedError:
357 print 'cpu_count() is not implemented, using default value 50.'
358 return 50
350 359
351 # Prepare environment. 360 assert number_of_processors > 0
352 env = EchoDict(os.environ) 361
353 goma_ready, goma_cloudtail = goma_setup(options, env) 362 # When goma is used, 10 * number_of_processors is basically good in
354 exit_status = -1 363 # various situations according to our measurement. Build speed won't
364 # be improved if -j is larger than that.
365 #
366 # Since Mac had process number limitation before, we had to set
367 # the upper limit to 50. Now that the process number limitation is 2000,
368 # so we would be able to use 10 * number_of_processors.
369 # For the safety, we'd like to set the upper limit to 200.
370 #
371 # Note that currently most try-bot build slaves have 8 processors.
372 if chromium_utils.IsMac() or chromium_utils.IsWindows():
373 return min(10 * number_of_processors, 200)
374
375 # For Linux, we also would like to use 10 * cpu. However, not sure
376 # backend resource is enough, so let me set Linux and Linux x64 builder
377 # only for now.
378 hostname = goma_utils.GetShortHostname()
379 if hostname in (
380 ['build14-m1', 'build48-m1'] +
381 # Also increasing cpus for v8/blink trybots.
382 ['build%d-m4' % x for x in xrange(45, 48)] +
383 # Also increasing cpus for LTO buildbots.
384 ['slave%d-c1' % x for x in [20, 33] + range(78, 108)]):
385 return min(10 * number_of_processors, 200)
386
387 return 50
388
389
390 def main_ninja(options, args, env):
391 """This function calls ninja.
392
393 Args:
394 options (Option): options for ninja command.
395 args (str): extra args for ninja command.
396 env (dict): Used when ninja command executes.
397
398 Returns:
399 int: ninja command exit status.
400
401 """
402
355 try: 403 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 404 print 'chdir to %s' % options.src_dir
364 os.chdir(options.src_dir) 405 os.chdir(options.src_dir)
365 406
366 command = [options.ninja_path, '-w', 'dupbuild=err', 407 command = [options.ninja_path, '-w', 'dupbuild=err',
367 '-C', options.target_output_dir] 408 '-C', options.target_output_dir]
368 409
369 # HACK(yyanagisawa): update environment files on |env| update. 410 # HACK(yyanagisawa): update environment files on |env| update.
370 # For compiling on Windows, environment in environment files are used. 411 # For compiling on Windows, environment in environment files are used.
371 # It means even if enviroment such as GOMA_DISABLED is updated in 412 # It means even if enviroment such as GOMA_DISABLED is updated in
372 # compile.py, the update will be ignored. 413 # compile.py, the update will be ignored.
(...skipping 15 matching lines...) Expand all
388 command.extend(options.build_args) 429 command.extend(options.build_args)
389 command.extend(args) 430 command.extend(args)
390 431
391 maybe_set_official_build_envvars(options, env) 432 maybe_set_official_build_envvars(options, env)
392 433
393 if options.compiler: 434 if options.compiler:
394 print 'using', options.compiler 435 print 'using', options.compiler
395 436
396 if options.compiler in ('goma', 'goma-clang'): 437 if options.compiler in ('goma', 'goma-clang'):
397 assert options.goma_dir 438 assert options.goma_dir
398 439 assert options.goma_jobs
399 def determine_goma_jobs(): 440 command.append('-j%d' % options.goma_jobs)
400 # We would like to speed up build on Windows a bit, since it is slowest.
401 number_of_processors = 0
402 try:
403 number_of_processors = multiprocessing.cpu_count()
404 except NotImplementedError:
405 print 'cpu_count() is not implemented, using default value 50.'
406 return 50
407
408 assert number_of_processors > 0
409
410 # When goma is used, 10 * number_of_processors is basically good in
411 # various situations according to our measurement. Build speed won't
412 # be improved if -j is larger than that.
413 #
414 # Since Mac had process number limitation before, we had to set
415 # the upper limit to 50. Now that the process number limitation is 2000,
416 # so we would be able to use 10 * number_of_processors.
417 # For the safety, we'd like to set the upper limit to 200.
418 #
419 # Note that currently most try-bot build slaves have 8 processors.
420 if chromium_utils.IsMac() or chromium_utils.IsWindows():
421 return min(10 * number_of_processors, 200)
422
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
425 # only for now.
426 hostname = goma_utils.GetShortHostname()
427 if hostname in (
428 ['build14-m1', 'build48-m1'] +
429 # Also increasing cpus for v8/blink trybots.
430 ['build%d-m4' % x for x in xrange(45, 48)] +
431 # Also increasing cpus for LTO buildbots.
432 ['slave%d-c1' % x for x in [20, 33] + range(78, 108)]):
433 return min(10 * number_of_processors, 200)
434
435 return 50
436
437 goma_jobs = determine_goma_jobs()
438 command.append('-j%d' % goma_jobs)
439 441
440 # Run the build. 442 # Run the build.
441 env.print_overrides() 443 env.print_overrides()
442 exit_status = chromium_utils.RunCommand(command, env=env) 444 exit_status = chromium_utils.RunCommand(command, env=env)
443 if exit_status == 0 and options.ninja_ensure_up_to_date: 445 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. 446 # Run the build again if we want to check that the no-op build is clean.
445 filter_obj = EnsureUpToDateFilter() 447 filter_obj = EnsureUpToDateFilter()
446 # Append `-d explain` to help diagnose in the failure case. 448 # Append `-d explain` to help diagnose in the failure case.
447 command += ['-d', 'explain'] 449 command += ['-d', 'explain']
448 chromium_utils.RunCommand(command, env=env, filter_obj=filter_obj) 450 chromium_utils.RunCommand(command, env=env, filter_obj=filter_obj)
449 if not filter_obj.was_up_to_date: 451 if not filter_obj.was_up_to_date:
450 print 'Failing build because ninja reported work to do.' 452 print 'Failing build because ninja reported work to do.'
451 print 'This means that after completing a compile, another was run and' 453 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' 454 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' 455 print 'wasn\'t a no-op). Consult the first "ninja explain:" line for a'
454 print 'likely culprit.' 456 print 'likely culprit.'
455 return 1 457 return 1
456 return exit_status 458 return exit_status
457 finally: 459 finally:
458 goma_teardown(options, env, exit_status, goma_cloudtail)
459
460 override_gsutil = None 460 override_gsutil = None
461 if options.gsutil_py_path: 461 if options.gsutil_py_path:
462 override_gsutil = [sys.executable, options.gsutil_py_path] 462 override_gsutil = [sys.executable, options.gsutil_py_path]
463 463
464 goma_utils.UploadNinjaLog( 464 goma_utils.UploadNinjaLog(
465 options.target_output_dir, options.compiler, command, exit_status, 465 options.target_output_dir, options.compiler, command, exit_status,
466 override_gsutil=override_gsutil) 466 override_gsutil=override_gsutil)
467 467
468 468
469 def get_target_build_dir(args, options): 469 def get_target_build_dir(args, options):
470 """Keep this function in sync with src/build/landmines.py""" 470 """Keep this function in sync with src/build/landmines.py"""
471 if chromium_utils.IsLinux() and options.cros_board: 471 if chromium_utils.IsLinux() and options.cros_board:
472 # When building ChromeOS's Simple Chrome workflow, the output directory 472 # When building ChromeOS's Simple Chrome workflow, the output directory
473 # has a CROS board name suffix. 473 # has a CROS board name suffix.
474 outdir = 'out_%s' % (options.cros_board,) 474 outdir = 'out_%s' % (options.cros_board,)
475 elif options.out_dir: 475 elif options.out_dir:
476 outdir = options.out_dir 476 outdir = options.out_dir
477 else: 477 else:
478 outdir = 'out' 478 outdir = 'out'
479 return os.path.abspath(os.path.join(options.src_dir, outdir, options.target)) 479 return os.path.abspath(os.path.join(options.src_dir, outdir, options.target))
480 480
481 481
482 def real_main(): 482 def get_parsed_options():
483 option_parser = optparse.OptionParser() 483 option_parser = optparse.OptionParser()
484 option_parser.add_option('--clobber', action='store_true', default=False, 484 option_parser.add_option('--clobber', action='store_true', default=False,
485 help='delete the output directory before compiling') 485 help='delete the output directory before compiling')
486 option_parser.add_option('--target', default='Release', 486 option_parser.add_option('--target', default='Release',
487 help='build target (Debug or Release)') 487 help='build target (Debug or Release)')
488 option_parser.add_option('--src-dir', default=None, 488 option_parser.add_option('--src-dir', default=None,
489 help='path to the root of the source tree') 489 help='path to the root of the source tree')
490 option_parser.add_option('--mode', default='dev', 490 option_parser.add_option('--mode', default='dev',
491 help='build mode (dev or official) controlling ' 491 help='build mode (dev or official) controlling '
492 'environment variables set during build') 492 'environment variables set during build')
(...skipping 28 matching lines...) Expand all
521 help='Enable goma CompilerInfo cache') 521 help='Enable goma CompilerInfo cache')
522 option_parser.add_option('--goma-store-local-run-output', default=None, 522 option_parser.add_option('--goma-store-local-run-output', default=None,
523 help='Store local run output to goma servers.') 523 help='Store local run output to goma servers.')
524 option_parser.add_option('--goma-fail-fast', action='store_true') 524 option_parser.add_option('--goma-fail-fast', action='store_true')
525 option_parser.add_option('--goma-disable-local-fallback', action='store_true') 525 option_parser.add_option('--goma-disable-local-fallback', action='store_true')
526 option_parser.add_option('--goma-jsonstatus', 526 option_parser.add_option('--goma-jsonstatus',
527 help='Specify a file to dump goma_ctl jsonstatus.') 527 help='Specify a file to dump goma_ctl jsonstatus.')
528 option_parser.add_option('--goma-service-account-json-file', 528 option_parser.add_option('--goma-service-account-json-file',
529 help='Specify a file containing goma service account' 529 help='Specify a file containing goma service account'
530 ' credentials') 530 ' credentials')
531 option_parser.add_option('--goma-jobs', default=None,
532 help='The number of jobs for ninja -j.')
531 option_parser.add_option('--gsutil-py-path', 533 option_parser.add_option('--gsutil-py-path',
532 help='Specify path to gsutil.py script.') 534 help='Specify path to gsutil.py script.')
533 option_parser.add_option('--ninja-path', default='ninja', 535 option_parser.add_option('--ninja-path', default='ninja',
534 help='Specify path to the ninja tool.') 536 help='Specify path to the ninja tool.')
535 option_parser.add_option('--ninja-ensure-up-to-date', action='store_true', 537 option_parser.add_option('--ninja-ensure-up-to-date', action='store_true',
536 help='Checks the output of the ninja builder to ' 538 help='Checks the output of the ninja builder to '
537 'confirm that a second compile immediately ' 539 'confirm that a second compile immediately '
538 'the first is a no-op.') 540 'the first is a no-op.')
539 541
540 options, args = option_parser.parse_args() 542 options, args = option_parser.parse_args()
541 543
542 if not options.src_dir: 544 if not options.src_dir:
543 options.src_dir = 'src' 545 options.src_dir = 'src'
544 options.src_dir = os.path.abspath(options.src_dir) 546 options.src_dir = os.path.abspath(options.src_dir)
545 547
546 options.target_output_dir = get_target_build_dir(args, options) 548 options.target_output_dir = get_target_build_dir(args, options)
547 549
548 assert options.build_tool in (None, 'ninja') 550 assert options.build_tool in (None, 'ninja')
549 return main_ninja(options, args) 551 return options, args
552
553
554 def real_main():
555 options, args = get_parsed_options()
556
557 # Prepare environment.
558 env = EchoDict(os.environ)
559
560 # start goma
561 goma_ready, goma_cloudtail = goma_setup(options, env)
562
563 if not goma_ready:
564 assert options.compiler not in ('goma', 'goma-clang')
565 assert options.goma_dir is None
566 elif options.goma_jobs is None:
567 options.goma_jobs = determine_goma_jobs()
568
569 # build
570 exit_status = main_ninja(options, args, env)
571
572 # stop goma
573 goma_teardown(options, env, exit_status, goma_cloudtail)
574
575 return exit_status
550 576
551 577
552 if '__main__' == __name__: 578 if '__main__' == __name__:
553 sys.exit(real_main()) 579 sys.exit(real_main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698