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

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: remove unnecessary return 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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.
ukai 2016/07/20 07:07:31 it does clobbers object files etc?
Nico 2016/07/20 08:30:43 It currently does (but only on the very few bots t
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 try:
356 if not goma_ready:
357 assert options.compiler not in ('goma', 'goma-clang')
358 assert options.goma_dir is None
359 355
360 # ninja is different from all the other build systems in that it requires 356 Returns:
361 # most configuration to be done at gyp time. This is why this function does 357 (int, str): first element for ninja command exit status.
362 # less than the other comparable functions in this file. 358 secont element is actual command to run ninja.
ukai 2016/07/20 07:07:31 secont?
tikuta 2016/07/21 02:44:35 Done.
363 print 'chdir to %s' % options.src_dir
364 os.chdir(options.src_dir)
365 359
366 command = [options.ninja_path, '-w', 'dupbuild=err', 360 """
367 '-C', options.target_output_dir]
368 361
369 # HACK(yyanagisawa): update environment files on |env| update. 362 # ninja is different from all the other build systems in that it requires
370 # For compiling on Windows, environment in environment files are used. 363 # most configuration to be done at gyp time. This is why this function does
371 # It means even if enviroment such as GOMA_DISABLED is updated in 364 # less than the other comparable functions in this file.
Yoshisato Yanagisawa 2016/07/20 07:31:57 Do we need this explanation? We might be only hav
tikuta 2016/07/21 02:44:35 Done.
372 # compile.py, the update will be ignored. 365 print 'chdir to %s' % options.src_dir
373 # We need to update environment files to reflect the update. 366 os.chdir(options.src_dir)
374 if chromium_utils.IsWindows() and NeedEnvFileUpdateOnWin(env):
375 print 'Updating environment.{x86,x64} files.'
376 UpdateWindowsEnvironment(options.target_output_dir, env)
377 367
378 if options.clobber: 368 command = [options.ninja_path, '-w', 'dupbuild=err',
379 print 'Removing %s' % options.target_output_dir 369 '-C', options.target_output_dir]
380 # Deleting output_dir would also delete all the .ninja files necessary to
381 # build. Clobbering should run before runhooks (which creates .ninja
382 # files). For now, only delete all non-.ninja files.
383 # TODO(thakis): Make "clobber" a step that runs before "runhooks".
384 # Once the master has been restarted, remove all clobber handling
385 # from compile.py, https://crbug.com/574557
386 build_directory.RmtreeExceptNinjaOrGomaFiles(options.target_output_dir)
387 370
388 command.extend(options.build_args) 371 # HACK(yyanagisawa): update environment files on |env| update.
389 command.extend(args) 372 # For compiling on Windows, environment in environment files are used.
373 # It means even if enviroment such as GOMA_DISABLED is updated in
374 # compile.py, the update will be ignored.
375 # We need to update environment files to reflect the update.
376 if chromium_utils.IsWindows() and NeedEnvFileUpdateOnWin(env):
377 print 'Updating environment.{x86,x64} files.'
378 UpdateWindowsEnvironment(options.target_output_dir, env)
390 379
391 maybe_set_official_build_envvars(options, env) 380 if options.clobber:
381 print 'Removing %s' % options.target_output_dir
382 # Deleting output_dir would also delete all the .ninja files necessary to
383 # build. Clobbering should run before runhooks (which creates .ninja
384 # files). For now, only delete all non-.ninja files.
385 # TODO(thakis): Make "clobber" a step that runs before "runhooks".
386 # Once the master has been restarted, remove all clobber handling
387 # from compile.py, https://crbug.com/574557
388 build_directory.RmtreeExceptNinjaOrGomaFiles(options.target_output_dir)
392 389
393 if options.compiler: 390 command.extend(options.build_args)
394 print 'using', options.compiler 391 command.extend(args)
395 392
396 if options.compiler in ('goma', 'goma-clang'): 393 maybe_set_official_build_envvars(options, env)
397 assert options.goma_dir
398 394
399 def determine_goma_jobs(): 395 if options.compiler:
400 # We would like to speed up build on Windows a bit, since it is slowest. 396 print 'using', options.compiler
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 397
408 assert number_of_processors > 0 398 if options.compiler in ('goma', 'goma-clang'):
ukai 2016/07/20 07:07:31 might be better to pass number of jobs via options
tikuta 2016/07/21 02:44:35 Done.
399 assert options.goma_dir
409 400
410 # When goma is used, 10 * number_of_processors is basically good in 401 def determine_goma_jobs():
411 # various situations according to our measurement. Build speed won't 402 # We would like to speed up build on Windows a bit, since it is slowest.
412 # be improved if -j is larger than that. 403 number_of_processors = 0
413 # 404 try:
414 # Since Mac had process number limitation before, we had to set 405 number_of_processors = multiprocessing.cpu_count()
415 # the upper limit to 50. Now that the process number limitation is 2000, 406 except NotImplementedError:
416 # so we would be able to use 10 * number_of_processors. 407 print 'cpu_count() is not implemented, using default value 50.'
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 408 return 50
436 409
437 goma_jobs = determine_goma_jobs() 410 assert number_of_processors > 0
438 command.append('-j%d' % goma_jobs)
439 411
440 # Run the build. 412 # When goma is used, 10 * number_of_processors is basically good in
441 env.print_overrides() 413 # various situations according to our measurement. Build speed won't
442 exit_status = chromium_utils.RunCommand(command, env=env) 414 # be improved if -j is larger than that.
443 if exit_status == 0 and options.ninja_ensure_up_to_date: 415 #
444 # Run the build again if we want to check that the no-op build is clean. 416 # Since Mac had process number limitation before, we had to set
445 filter_obj = EnsureUpToDateFilter() 417 # the upper limit to 50. Now that the process number limitation is 2000,
446 # Append `-d explain` to help diagnose in the failure case. 418 # so we would be able to use 10 * number_of_processors.
447 command += ['-d', 'explain'] 419 # For the safety, we'd like to set the upper limit to 200.
448 chromium_utils.RunCommand(command, env=env, filter_obj=filter_obj) 420 #
449 if not filter_obj.was_up_to_date: 421 # Note that currently most try-bot build slaves have 8 processors.
450 print 'Failing build because ninja reported work to do.' 422 if chromium_utils.IsMac() or chromium_utils.IsWindows():
451 print 'This means that after completing a compile, another was run and' 423 return min(10 * number_of_processors, 200)
452 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'
454 print 'likely culprit.'
455 return 1
456 return exit_status
457 finally:
458 goma_teardown(options, env, exit_status, goma_cloudtail)
459 424
460 override_gsutil = None 425 # For Linux, we also would like to use 10 * cpu. However, not sure
461 if options.gsutil_py_path: 426 # backend resource is enough, so let me set Linux and Linux x64 builder
462 override_gsutil = [sys.executable, options.gsutil_py_path] 427 # only for now.
428 hostname = goma_utils.GetShortHostname()
429 if hostname in (
430 ['build14-m1', 'build48-m1'] +
431 # Also increasing cpus for v8/blink trybots.
432 ['build%d-m4' % x for x in range(45, 48)] +
433 # Also increasing cpus for LTO buildbots.
434 ['slave%d-c1' % x for x in [20, 33] + range(78, 108)]):
435 return min(10 * number_of_processors, 200)
463 436
464 goma_utils.UploadNinjaLog( 437 return 50
465 options.target_output_dir, options.compiler, command, exit_status, 438
466 override_gsutil=override_gsutil) 439 goma_jobs = determine_goma_jobs()
440 command.append('-j%d' % goma_jobs)
441
442 # Run the build.
443 env.print_overrides()
444 exit_status = chromium_utils.RunCommand(command, env=env)
445 if exit_status == 0 and options.ninja_ensure_up_to_date:
446 # Run the build again if we want to check that the no-op build is clean.
447 filter_obj = EnsureUpToDateFilter()
448 # Append `-d explain` to help diagnose in the failure case.
449 command += ['-d', 'explain']
450 chromium_utils.RunCommand(command, env=env, filter_obj=filter_obj)
451 if not filter_obj.was_up_to_date:
452 print 'Failing build because ninja reported work to do.'
453 print 'This means that after completing a compile, another was run and'
454 print 'it resulted in still having work to do (that is, a no-op build'
455 print 'wasn\'t a no-op). Consult the first "ninja explain:" line for a'
456 print 'likely culprit.'
457 return 1, command
458 return exit_status, command
467 459
468 460
469 def get_target_build_dir(args, options): 461 def get_target_build_dir(args, options):
470 """Keep this function in sync with src/build/landmines.py""" 462 """Keep this function in sync with src/build/landmines.py"""
471 if chromium_utils.IsLinux() and options.cros_board: 463 if chromium_utils.IsLinux() and options.cros_board:
472 # When building ChromeOS's Simple Chrome workflow, the output directory 464 # When building ChromeOS's Simple Chrome workflow, the output directory
473 # has a CROS board name suffix. 465 # has a CROS board name suffix.
474 outdir = 'out_%s' % (options.cros_board,) 466 outdir = 'out_%s' % (options.cros_board,)
475 elif options.out_dir: 467 elif options.out_dir:
476 outdir = options.out_dir 468 outdir = options.out_dir
477 else: 469 else:
478 outdir = 'out' 470 outdir = 'out'
479 return os.path.abspath(os.path.join(options.src_dir, outdir, options.target)) 471 return os.path.abspath(os.path.join(options.src_dir, outdir, options.target))
480 472
481 473
482 def real_main(): 474 def get_parsed_options():
483 option_parser = optparse.OptionParser() 475 option_parser = optparse.OptionParser()
484 option_parser.add_option('--clobber', action='store_true', default=False, 476 option_parser.add_option('--clobber', action='store_true', default=False,
485 help='delete the output directory before compiling') 477 help='delete the output directory before compiling')
486 option_parser.add_option('--target', default='Release', 478 option_parser.add_option('--target', default='Release',
487 help='build target (Debug or Release)') 479 help='build target (Debug or Release)')
488 option_parser.add_option('--src-dir', default=None, 480 option_parser.add_option('--src-dir', default=None,
489 help='path to the root of the source tree') 481 help='path to the root of the source tree')
490 option_parser.add_option('--mode', default='dev', 482 option_parser.add_option('--mode', default='dev',
491 help='build mode (dev or official) controlling ' 483 help='build mode (dev or official) controlling '
492 'environment variables set during build') 484 'environment variables set during build')
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 531
540 options, args = option_parser.parse_args() 532 options, args = option_parser.parse_args()
541 533
542 if not options.src_dir: 534 if not options.src_dir:
543 options.src_dir = 'src' 535 options.src_dir = 'src'
544 options.src_dir = os.path.abspath(options.src_dir) 536 options.src_dir = os.path.abspath(options.src_dir)
545 537
546 options.target_output_dir = get_target_build_dir(args, options) 538 options.target_output_dir = get_target_build_dir(args, options)
547 539
548 assert options.build_tool in (None, 'ninja') 540 assert options.build_tool in (None, 'ninja')
549 return main_ninja(options, args) 541 return options, args
542
543
544 def real_main():
545 options, args = get_parsed_options()
546
547 # Prepare environment.
548 env = EchoDict(os.environ)
549
550 # start goma
551 goma_ready, goma_cloudtail = goma_setup(options, env)
552
553 if not goma_ready:
554 assert options.compiler not in ('goma', 'goma-clang')
555 assert options.goma_dir is None
556
557 # build
558 try:
559 exit_status, command = main_ninja(options, args, env)
560 except Exception as e:
561 print 'failed to build using ninja: %s' % e
562
563 # stop goma
564 goma_teardown(options, env, exit_status, goma_cloudtail)
565
566 override_gsutil = None
567 if options.gsutil_py_path:
568 override_gsutil = [sys.executable, options.gsutil_py_path]
569
570 goma_utils.UploadNinjaLog(
ukai 2016/07/20 07:07:31 upload ninja log in main_ninja?
tikuta 2016/07/21 02:44:35 Done.
571 options.target_output_dir, options.compiler, command, exit_status,
572 override_gsutil=override_gsutil)
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())
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