| 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 |
| 11 For a list of command-line options, call this script with '--help'. | 11 For a list of command-line options, call this script with '--help'. |
| 12 """ | 12 """ |
| 13 | 13 |
| 14 import multiprocessing | |
| 15 import optparse | 14 import optparse |
| 16 import os | 15 import os |
| 17 import re | 16 import re |
| 18 import subprocess | |
| 19 import sys | 17 import sys |
| 20 | 18 |
| 21 from common import chromium_utils | 19 from common import chromium_utils |
| 22 from slave import build_directory | 20 from slave import build_directory |
| 23 from slave import goma_utils | 21 from slave import goma_utils |
| 24 | 22 |
| 25 # Define a bunch of directory paths (same as bot_update.py) | |
| 26 CURRENT_DIR = os.path.abspath(os.getcwd()) | |
| 27 BUILDER_DIR = os.path.dirname(CURRENT_DIR) | |
| 28 SLAVE_DIR = os.path.dirname(BUILDER_DIR) | |
| 29 # GOMA_CACHE_DIR used for caching long-term data. | |
| 30 DEFAULT_GOMA_CACHE_DIR = os.path.join(SLAVE_DIR, 'goma_cache') | |
| 31 | |
| 32 # Path of the scripts/slave/ checkout on the slave, found by looking at the | |
| 33 # current compile.py script's path's dirname(). | |
| 34 SLAVE_SCRIPTS_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| 35 # Path of the build/ checkout on the slave, found relative to the | |
| 36 # scripts/slave/ directory. | |
| 37 BUILD_DIR = os.path.dirname(os.path.dirname(SLAVE_SCRIPTS_DIR)) | |
| 38 | 23 |
| 39 | 24 |
| 40 class EchoDict(dict): | 25 class EchoDict(dict): |
| 41 """Dict that remembers all modified values.""" | 26 """Dict that remembers all modified values.""" |
| 42 | 27 |
| 43 def __init__(self, *args, **kwargs): | 28 def __init__(self, *args, **kwargs): |
| 44 self.overrides = set() | 29 self.overrides = set() |
| 45 self.adds = set() | 30 self.adds = set() |
| 46 super(EchoDict, self).__init__(*args, **kwargs) | 31 super(EchoDict, self).__init__(*args, **kwargs) |
| 47 | 32 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 65 fh = sys.stdout | 50 fh = sys.stdout |
| 66 fh.write('Environment variables modified in compile.py:\n') | 51 fh.write('Environment variables modified in compile.py:\n') |
| 67 for k in sorted(list(self.overrides)): | 52 for k in sorted(list(self.overrides)): |
| 68 if k in self: | 53 if k in self: |
| 69 fh.write(' %s=%s\n' % (k, self[k])) | 54 fh.write(' %s=%s\n' % (k, self[k])) |
| 70 else: | 55 else: |
| 71 fh.write(' %s (removed)\n' % k) | 56 fh.write(' %s (removed)\n' % k) |
| 72 fh.write('\n') | 57 fh.write('\n') |
| 73 | 58 |
| 74 | 59 |
| 75 # TODO(tikuta): move to goma_utils.py | |
| 76 def goma_setup(options, env): | |
| 77 """Sets up goma if necessary. | |
| 78 | |
| 79 If using the Goma compiler, first call goma_ctl to ensure the proxy is | |
| 80 available, and returns (True, instance of cloudtail subprocess). | |
| 81 If it failed to start up compiler_proxy, modify options.compiler and | |
| 82 options.goma_dir and returns (False, None) | |
| 83 | |
| 84 """ | |
| 85 if options.compiler not in ('goma', 'goma-clang'): | |
| 86 # Unset goma_dir to make sure we'll not use goma. | |
| 87 options.goma_dir = None | |
| 88 return False, None | |
| 89 | |
| 90 hostname = goma_utils.GetShortHostname() | |
| 91 # HACK(shinyak, yyanagisawa, goma): Windows NO_NACL_GOMA (crbug.com/390764) | |
| 92 # Building NaCl untrusted code using goma brings large performance | |
| 93 # improvement but it sometimes cause build failure by race condition. | |
| 94 # Let me enable goma build on goma canary buildslaves to confirm the issue | |
| 95 # has been fixed by a workaround. | |
| 96 # vm*-m4 are trybots. build*-m1 and vm*-m1 are all goma canary bots. | |
| 97 if hostname in ['build28-m1', 'build58-m1', 'vm191-m1', 'vm480-m1', | |
| 98 'vm820-m1', 'vm821-m1', 'vm848-m1']: | |
| 99 env['NO_NACL_GOMA'] = 'false' | |
| 100 | |
| 101 if options.goma_fail_fast: | |
| 102 # startup fails when initial ping failed. | |
| 103 env['GOMA_FAIL_FAST'] = 'true' | |
| 104 else: | |
| 105 # If a network error continues 30 minutes, compiler_proxy make the compile | |
| 106 # failed. When people use goma, they expect using goma is faster than | |
| 107 # compile locally. If goma cannot guarantee that, let it make compile | |
| 108 # as error. | |
| 109 env['GOMA_ALLOWED_NETWORK_ERROR_DURATION'] = '1800' | |
| 110 | |
| 111 # HACK(yyanagisawa): reduce GOMA_BURST_MAX_PROCS crbug.com/592306 | |
| 112 # Recently, I sometimes see buildbot slave time out, one possibility I come | |
| 113 # up with is burst mode use up resource. | |
| 114 # Let me temporary set small values to GOMA_BURST_MAX_PROCS to confirm | |
| 115 # the possibility is true or false. | |
| 116 max_subprocs = '3' | |
| 117 max_heavy_subprocs = '1' | |
| 118 number_of_processors = 0 | |
| 119 try: | |
| 120 number_of_processors = multiprocessing.cpu_count() | |
| 121 except NotImplementedError: | |
| 122 print 'cpu_count() is not implemented, using default value.' | |
| 123 number_of_processors = 1 | |
| 124 if number_of_processors > 3: | |
| 125 max_subprocs = str(number_of_processors - 1) | |
| 126 max_heavy_subprocs = str(number_of_processors / 2) | |
| 127 env['GOMA_BURST_MAX_SUBPROCS'] = max_subprocs | |
| 128 env['GOMA_BURST_MAX_SUBPROCS_LOW'] = max_subprocs | |
| 129 env['GOMA_BURST_MAX_SUBPROCS_HEAVY'] = max_heavy_subprocs | |
| 130 | |
| 131 # Caches CRLs in GOMA_CACHE_DIR. | |
| 132 # Since downloading CRLs is usually slow, caching them may improves | |
| 133 # compiler_proxy start time. | |
| 134 if not os.path.exists(options.goma_cache_dir): | |
| 135 os.mkdir(options.goma_cache_dir, 0700) | |
| 136 env['GOMA_CACHE_DIR'] = options.goma_cache_dir | |
| 137 | |
| 138 # Enable DepsCache. DepsCache caches the list of files to send goma server. | |
| 139 # This will greatly improve build speed when cache is warmed. | |
| 140 # The cache file is stored in the target output directory. | |
| 141 env['GOMA_DEPS_CACHE_DIR'] = ( | |
| 142 options.goma_deps_cache_dir or options.target_output_dir) | |
| 143 | |
| 144 if not env.get('GOMA_HERMETIC'): | |
| 145 env['GOMA_HERMETIC'] = options.goma_hermetic | |
| 146 if options.goma_enable_remote_link: | |
| 147 env['GOMA_ENABLE_REMOTE_LINK'] = options.goma_enable_remote_link | |
| 148 if options.goma_store_local_run_output: | |
| 149 env['GOMA_STORE_LOCAL_RUN_OUTPUT'] = options.goma_store_local_run_output | |
| 150 if options.goma_enable_compiler_info_cache: | |
| 151 # Will be stored in GOMA_CACHE_DIR. | |
| 152 env['GOMA_COMPILER_INFO_CACHE_FILE'] = 'goma-compiler-info.cache' | |
| 153 | |
| 154 if options.build_data_dir: | |
| 155 env['GOMA_DUMP_STATS_FILE'] = os.path.join(options.build_data_dir, | |
| 156 'goma_stats_proto') | |
| 157 | |
| 158 # goma is requested. | |
| 159 goma_key = os.path.join(options.goma_dir, 'goma.key') | |
| 160 if os.path.exists(goma_key): | |
| 161 env['GOMA_API_KEY_FILE'] = goma_key | |
| 162 if options.goma_service_account_json_file: | |
| 163 env['GOMA_SERVICE_ACCOUNT_JSON_FILE'] = \ | |
| 164 options.goma_service_account_json_file | |
| 165 if chromium_utils.IsWindows(): | |
| 166 env['GOMA_RPC_EXTRA_PARAMS'] = '?win' | |
| 167 goma_start_command = ['restart'] | |
| 168 goma_ctl_cmd = [sys.executable, | |
| 169 os.path.join(options.goma_dir, 'goma_ctl.py')] | |
| 170 result = chromium_utils.RunCommand(goma_ctl_cmd + goma_start_command, env=env) | |
| 171 if not result: | |
| 172 # goma started sucessfully. | |
| 173 # Making cloudtail to upload the latest log. | |
| 174 # TODO(yyanagisawa): install cloudtail from CIPD. | |
| 175 cloudtail_path = '/opt/infra-tools/cloudtail' | |
| 176 if chromium_utils.IsWindows(): | |
| 177 cloudtail_path = 'C:\\infra-tools\\cloudtail' | |
| 178 try: | |
| 179 cloudtail_proc = subprocess.Popen( | |
| 180 [cloudtail_path, 'tail', '--log-id', 'goma_compiler_proxy', '--path', | |
| 181 goma_utils.GetLatestGomaCompilerProxyInfo()]) | |
| 182 except Exception as e: | |
| 183 print 'failed to invoke cloudtail: %s' % e | |
| 184 return True, None | |
| 185 return True, cloudtail_proc | |
| 186 | |
| 187 if options.goma_jsonstatus: | |
| 188 chromium_utils.RunCommand( | |
| 189 goma_ctl_cmd + ['jsonstatus', options.goma_jsonstatus], env=env) | |
| 190 goma_utils.SendGomaTsMon(options.goma_jsonstatus, -1) | |
| 191 | |
| 192 # Try to stop compiler_proxy so that it flushes logs and stores | |
| 193 # GomaStats. | |
| 194 if options.build_data_dir: | |
| 195 env['GOMACTL_CRASH_REPORT_ID_FILE'] = os.path.join(options.build_data_dir, | |
| 196 'crash_report_id_file') | |
| 197 chromium_utils.RunCommand(goma_ctl_cmd + ['stop'], env=env) | |
| 198 | |
| 199 override_gsutil = None | |
| 200 if options.gsutil_py_path: | |
| 201 override_gsutil = [sys.executable, options.gsutil_py_path] | |
| 202 | |
| 203 # Upload compiler_proxy.INFO to investigate the reason of compiler_proxy | |
| 204 # start-up failure. | |
| 205 goma_utils.UploadGomaCompilerProxyInfo(override_gsutil=override_gsutil) | |
| 206 # Upload GomaStats to make it monitored. | |
| 207 if env.get('GOMA_DUMP_STATS_FILE'): | |
| 208 goma_utils.SendGomaStats(env['GOMA_DUMP_STATS_FILE'], | |
| 209 env.get('GOMACTL_CRASH_REPORT_ID_FILE'), | |
| 210 options.build_data_dir) | |
| 211 | |
| 212 if options.goma_disable_local_fallback: | |
| 213 print 'error: failed to start goma; fallback has been disabled' | |
| 214 raise Exception('failed to start goma') | |
| 215 | |
| 216 print 'warning: failed to start goma. falling back to non-goma' | |
| 217 # Drop goma from options.compiler | |
| 218 options.compiler = options.compiler.replace('goma-', '') | |
| 219 if options.compiler == 'goma': | |
| 220 options.compiler = None | |
| 221 # Reset options.goma_dir. | |
| 222 options.goma_dir = None | |
| 223 env['GOMA_DISABLED'] = '1' | |
| 224 return False, None | |
| 225 | |
| 226 | |
| 227 # TODO(tikuta): move to goma_utils.py | |
| 228 def goma_teardown(options, env, exit_status, cloudtail_proc): | |
| 229 """Tears down goma if necessary. """ | |
| 230 if (options.compiler in ('goma', 'goma-clang') and | |
| 231 options.goma_dir): | |
| 232 override_gsutil = None | |
| 233 if options.gsutil_py_path: | |
| 234 override_gsutil = [sys.executable, options.gsutil_py_path] | |
| 235 | |
| 236 # If goma compiler_proxy crashes during the build, there could be crash | |
| 237 # dump. | |
| 238 if options.build_data_dir: | |
| 239 env['GOMACTL_CRASH_REPORT_ID_FILE'] = os.path.join(options.build_data_dir, | |
| 240 'crash_report_id_file') | |
| 241 goma_ctl_cmd = [sys.executable, | |
| 242 os.path.join(options.goma_dir, 'goma_ctl.py')] | |
| 243 if options.goma_jsonstatus: | |
| 244 chromium_utils.RunCommand( | |
| 245 goma_ctl_cmd + ['jsonstatus', options.goma_jsonstatus], env=env) | |
| 246 goma_utils.SendGomaTsMon(options.goma_jsonstatus, exit_status) | |
| 247 # Always stop the proxy for now to allow in-place update. | |
| 248 chromium_utils.RunCommand(goma_ctl_cmd + ['stop'], env=env) | |
| 249 goma_utils.UploadGomaCompilerProxyInfo(override_gsutil=override_gsutil) | |
| 250 if env.get('GOMA_DUMP_STATS_FILE'): | |
| 251 goma_utils.SendGomaStats(env['GOMA_DUMP_STATS_FILE'], | |
| 252 env.get('GOMACTL_CRASH_REPORT_ID_FILE'), | |
| 253 options.build_data_dir) | |
| 254 if cloudtail_proc: | |
| 255 cloudtail_proc.terminate() | |
| 256 cloudtail_proc.wait() | |
| 257 | |
| 258 | |
| 259 def maybe_set_official_build_envvars(options, env): | 60 def maybe_set_official_build_envvars(options, env): |
| 260 if options.mode == 'google_chrome' or options.mode == 'official': | 61 if options.mode == 'google_chrome' or options.mode == 'official': |
| 261 env['CHROMIUM_BUILD'] = '_google_chrome' | 62 env['CHROMIUM_BUILD'] = '_google_chrome' |
| 262 | 63 |
| 263 if options.mode == 'official': | 64 if options.mode == 'official': |
| 264 # Official builds are always Google Chrome. | 65 # Official builds are always Google Chrome. |
| 265 env['CHROME_BUILD_TYPE'] = '_official' | 66 env['CHROME_BUILD_TYPE'] = '_official' |
| 266 | 67 |
| 267 | 68 |
| 268 class EnsureUpToDateFilter(chromium_utils.RunCommandFilter): | 69 class EnsureUpToDateFilter(chromium_utils.RunCommandFilter): |
| 269 """Filter for RunCommand that checks whether the output contains ninja's | 70 """Filter for RunCommand that checks whether the output contains ninja's |
| 270 message for a no-op build.""" | 71 message for a no-op build.""" |
| 271 def __init__(self): | 72 def __init__(self): |
| 272 self.was_up_to_date = False | 73 self.was_up_to_date = False |
| 273 | 74 |
| 274 def FilterLine(self, a_line): | 75 def FilterLine(self, a_line): |
| 275 if 'ninja: no work to do.' in a_line: | 76 if 'ninja: no work to do.' in a_line: |
| 276 self.was_up_to_date = True | 77 self.was_up_to_date = True |
| 277 return a_line | 78 return a_line |
| 278 | 79 |
| 279 | 80 |
| 280 def NeedEnvFileUpdateOnWin(env): | |
| 281 """Returns true if environment file need to be updated.""" | |
| 282 # Following GOMA_* are applied to compiler_proxy not gomacc, | |
| 283 # you do not need to update environment files. | |
| 284 ignore_envs = ( | |
| 285 'GOMA_API_KEY_FILE', | |
| 286 'GOMA_DEPS_CACHE_DIR', | |
| 287 'GOMA_HERMETIC', | |
| 288 'GOMA_RPC_EXTRA_PARAMS', | |
| 289 'GOMA_ALLOWED_NETWORK_ERROR_DURATION' | |
| 290 ) | |
| 291 for key in env.overrides: | |
| 292 if key not in ignore_envs: | |
| 293 return True | |
| 294 return False | |
| 295 | |
| 296 | |
| 297 def UpdateWindowsEnvironment(envfile_dir, env): | |
| 298 """Update windows environment in environment.{x86,x64}. | |
| 299 | |
| 300 Args: | |
| 301 envfile_dir: a directory name environment.{x86,x64} are stored. | |
| 302 env: an instance of EchoDict that represents environment. | |
| 303 """ | |
| 304 # envvars_to_save come from _ExtractImportantEnvironment in | |
| 305 # https://chromium.googlesource.com/external/gyp/+/\ | |
| 306 # master/pylib/gyp/msvs_emuation.py | |
| 307 # You must update this when the original code is updated. | |
| 308 envvars_to_save = ( | |
| 309 'goma_.*', # TODO(scottmg): This is ugly, but needed for goma. | |
| 310 'include', | |
| 311 'lib', | |
| 312 'libpath', | |
| 313 'path', | |
| 314 'pathext', | |
| 315 'systemroot', | |
| 316 'temp', | |
| 317 'tmp', | |
| 318 ) | |
| 319 env_to_store = {} | |
| 320 for envvar in envvars_to_save: | |
| 321 compiled = re.compile(envvar, re.IGNORECASE) | |
| 322 for key in env.overrides: | |
| 323 if compiled.match(key): | |
| 324 if envvar == 'path': | |
| 325 env_to_store[key] = (os.path.dirname(sys.executable) + | |
| 326 os.pathsep + env[key]) | |
| 327 else: | |
| 328 env_to_store[key] = env[key] | |
| 329 | |
| 330 if not env_to_store: | |
| 331 return | |
| 332 | |
| 333 nul = '\0' | |
| 334 for arch in ['x86', 'x64']: | |
| 335 path = os.path.join(envfile_dir, 'environment.%s' % arch) | |
| 336 print '%s will be updated with %s.' % (path, env_to_store) | |
| 337 env_in_file = {} | |
| 338 with open(path) as f: | |
| 339 for entry in f.read().split(nul): | |
| 340 if not entry: | |
| 341 continue | |
| 342 key, value = entry.split('=', 1) | |
| 343 env_in_file[key] = value | |
| 344 env_in_file.update(env_to_store) | |
| 345 with open(path, 'wb') as f: | |
| 346 f.write(nul.join(['%s=%s' % (k, v) for k, v in env_in_file.iteritems()])) | |
| 347 f.write(nul * 2) | |
| 348 | |
| 349 | |
| 350 # TODO(tikuta): move to goma_utils | |
| 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 | |
| 359 | |
| 360 assert number_of_processors > 0 | |
| 361 | |
| 362 # When goma is used, 10 * number_of_processors is basically good in | |
| 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): | 81 def main_ninja(options, args, env): |
| 391 """This function calls ninja. | 82 """This function calls ninja. |
| 392 | 83 |
| 393 Args: | 84 Args: |
| 394 options (Option): options for ninja command. | 85 options (Option): options for ninja command. |
| 395 args (str): extra args for ninja command. | 86 args (str): extra args for ninja command. |
| 396 env (dict): Used when ninja command executes. | 87 env (dict): Used when ninja command executes. |
| 397 | 88 |
| 398 Returns: | 89 Returns: |
| 399 int: ninja command exit status. | 90 int: ninja command exit status. |
| 400 | 91 |
| 401 """ | 92 """ |
| 402 | 93 |
| 403 exit_status = -1 | 94 exit_status = -1 |
| 404 | 95 |
| 405 try: | 96 try: |
| 406 print 'chdir to %s' % options.src_dir | 97 print 'chdir to %s' % options.src_dir |
| 407 os.chdir(options.src_dir) | 98 os.chdir(options.src_dir) |
| 408 | 99 |
| 409 command = [options.ninja_path, '-w', 'dupbuild=err', | 100 command = [options.ninja_path, '-w', 'dupbuild=err', |
| 410 '-C', options.target_output_dir] | 101 '-C', options.target_output_dir] |
| 411 | 102 |
| 412 # HACK(yyanagisawa): update environment files on |env| update. | |
| 413 # For compiling on Windows, environment in environment files are used. | |
| 414 # It means even if enviroment such as GOMA_DISABLED is updated in | |
| 415 # compile.py, the update will be ignored. | |
| 416 # We need to update environment files to reflect the update. | |
| 417 if chromium_utils.IsWindows() and NeedEnvFileUpdateOnWin(env): | |
| 418 print 'Updating environment.{x86,x64} files.' | |
| 419 UpdateWindowsEnvironment(options.target_output_dir, env) | |
| 420 | |
| 421 if options.clobber: | 103 if options.clobber: |
| 422 print 'Removing %s' % options.target_output_dir | 104 print 'Removing %s' % options.target_output_dir |
| 423 # Deleting output_dir would also delete all the .ninja files necessary to | 105 # Deleting output_dir would also delete all the .ninja files necessary to |
| 424 # build. Clobbering should run before runhooks (which creates .ninja | 106 # build. Clobbering should run before runhooks (which creates .ninja |
| 425 # files). For now, only delete all non-.ninja files. | 107 # files). For now, only delete all non-.ninja files. |
| 426 # TODO(thakis): Make "clobber" a step that runs before "runhooks". | 108 # TODO(thakis): Make "clobber" a step that runs before "runhooks". |
| 427 # Once the master has been restarted, remove all clobber handling | 109 # Once the master has been restarted, remove all clobber handling |
| 428 # from compile.py, https://crbug.com/574557 | 110 # from compile.py, https://crbug.com/574557 |
| 429 build_directory.RmtreeExceptNinjaOrGomaFiles(options.target_output_dir) | 111 build_directory.RmtreeExceptNinjaOrGomaFiles(options.target_output_dir) |
| 430 | 112 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 # When building ChromeOS's Simple Chrome workflow, the output directory | 156 # When building ChromeOS's Simple Chrome workflow, the output directory |
| 475 # has a CROS board name suffix. | 157 # has a CROS board name suffix. |
| 476 outdir = 'out_%s' % (options.cros_board,) | 158 outdir = 'out_%s' % (options.cros_board,) |
| 477 elif options.out_dir: | 159 elif options.out_dir: |
| 478 outdir = options.out_dir | 160 outdir = options.out_dir |
| 479 else: | 161 else: |
| 480 outdir = 'out' | 162 outdir = 'out' |
| 481 return os.path.abspath(os.path.join(options.src_dir, outdir, options.target)) | 163 return os.path.abspath(os.path.join(options.src_dir, outdir, options.target)) |
| 482 | 164 |
| 483 | 165 |
| 484 def get_parsed_options(): | 166 def construct_optionparser(option_parser): |
| 485 option_parser = optparse.OptionParser() | |
| 486 option_parser.add_option('--clobber', action='store_true', default=False, | 167 option_parser.add_option('--clobber', action='store_true', default=False, |
| 487 help='delete the output directory before compiling') | 168 help='delete the output directory before compiling') |
| 488 option_parser.add_option('--target', default='Release', | 169 option_parser.add_option('--target', default='Release', |
| 489 help='build target (Debug or Release)') | 170 help='build target (Debug or Release)') |
| 490 option_parser.add_option('--src-dir', default=None, | 171 option_parser.add_option('--src-dir', default='src', |
| 491 help='path to the root of the source tree') | 172 help='path to the root of the source tree') |
| 492 option_parser.add_option('--mode', default='dev', | 173 option_parser.add_option('--mode', default='dev', |
| 493 help='build mode (dev or official) controlling ' | 174 help='build mode (dev or official) controlling ' |
| 494 'environment variables set during build') | 175 'environment variables set during build') |
| 495 # TODO(thakis): Remove this, https://crbug.com/622768 | 176 # TODO(thakis): Remove this, https://crbug.com/622768 |
| 496 option_parser.add_option('--build-tool', default=None, help='ignored') | 177 option_parser.add_option('--build-tool', default=None, help='ignored') |
| 497 option_parser.add_option('--build-args', action='append', default=[], | 178 option_parser.add_option('--build-args', action='append', default=[], |
| 498 help='arguments to pass to the build tool') | 179 help='arguments to pass to the build tool') |
| 499 option_parser.add_option('--build-data-dir', action='store', | |
| 500 help='specify a build data directory.') | |
| 501 option_parser.add_option('--compiler', default=None, | 180 option_parser.add_option('--compiler', default=None, |
| 502 help='specify alternative compiler (e.g. clang)') | 181 help='specify alternative compiler (e.g. clang)') |
| 503 if chromium_utils.IsLinux(): | 182 if chromium_utils.IsLinux(): |
| 504 option_parser.add_option('--cros-board', action='store', | 183 option_parser.add_option('--cros-board', action='store', |
| 505 help='If building for the ChromeOS Simple Chrome ' | 184 help='If building for the ChromeOS Simple Chrome ' |
| 506 'workflow, the name of the ChromeOS board.') | 185 'workflow, the name of the ChromeOS board.') |
| 507 option_parser.add_option('--out-dir', action='store', | 186 option_parser.add_option('--out-dir', action='store', |
| 508 help='Specify a custom output directory.') | 187 help='Specify a custom output directory.') |
| 509 option_parser.add_option('--goma-dir', | |
| 510 default=os.path.join(BUILD_DIR, 'goma'), | |
| 511 help='specify goma directory') | |
| 512 option_parser.add_option('--goma-cache-dir', | |
| 513 default=DEFAULT_GOMA_CACHE_DIR, | |
| 514 help='specify goma cache directory') | |
| 515 option_parser.add_option('--goma-deps-cache-dir', | |
| 516 help='specify goma deps cache directory') | |
| 517 option_parser.add_option('--goma-hermetic', default='error', | |
| 518 help='Set goma hermetic mode') | |
| 519 option_parser.add_option('--goma-enable-remote-link', default=None, | |
| 520 help='Enable goma remote link.') | |
| 521 option_parser.add_option('--goma-enable-compiler-info-cache', | |
| 522 action='store_true', | |
| 523 help='Enable goma CompilerInfo cache') | |
| 524 option_parser.add_option('--goma-store-local-run-output', default=None, | |
| 525 help='Store local run output to goma servers.') | |
| 526 option_parser.add_option('--goma-fail-fast', action='store_true') | |
| 527 option_parser.add_option('--goma-disable-local-fallback', action='store_true') | |
| 528 option_parser.add_option('--goma-jsonstatus', | |
| 529 help='Specify a file to dump goma_ctl jsonstatus.') | |
| 530 option_parser.add_option('--goma-service-account-json-file', | |
| 531 help='Specify a file containing goma service account' | |
| 532 ' credentials') | |
| 533 option_parser.add_option('--goma-jobs', default=None, | |
| 534 help='The number of jobs for ninja -j.') | |
| 535 option_parser.add_option('--gsutil-py-path', | 188 option_parser.add_option('--gsutil-py-path', |
| 536 help='Specify path to gsutil.py script.') | 189 help='Specify path to gsutil.py script.') |
| 537 option_parser.add_option('--ninja-path', default='ninja', | 190 option_parser.add_option('--ninja-path', default='ninja', |
| 538 help='Specify path to the ninja tool.') | 191 help='Specify path to the ninja tool.') |
| 539 option_parser.add_option('--ninja-ensure-up-to-date', action='store_true', | 192 option_parser.add_option('--ninja-ensure-up-to-date', action='store_true', |
| 540 help='Checks the output of the ninja builder to ' | 193 help='Checks the output of the ninja builder to ' |
| 541 'confirm that a second compile immediately ' | 194 'confirm that a second compile immediately ' |
| 542 'the first is a no-op.') | 195 'the first is a no-op.') |
| 196 option_parser.add_option('--goma-dir', |
| 197 default=os.path.join(goma_utils.BUILD_DIR, 'goma'), |
| 198 help='specify goma directory') |
| 199 option_parser.add_option('--goma-jobs', default=None, |
| 200 help='The number of jobs for ninja -j.') |
| 201 |
| 202 return option_parser |
| 203 |
| 204 |
| 205 def real_main(): |
| 206 option_parser = optparse.OptionParser() |
| 207 option_parser = construct_optionparser(option_parser) |
| 208 option_parser = goma_utils.construct_optionparser(option_parser) |
| 543 | 209 |
| 544 options, args = option_parser.parse_args() | 210 options, args = option_parser.parse_args() |
| 545 | 211 |
| 546 if not options.src_dir: | |
| 547 options.src_dir = 'src' | |
| 548 options.src_dir = os.path.abspath(options.src_dir) | 212 options.src_dir = os.path.abspath(options.src_dir) |
| 549 | 213 |
| 550 options.target_output_dir = get_target_build_dir(args, options) | 214 options.target_output_dir = get_target_build_dir(args, options) |
| 551 | 215 |
| 552 assert options.build_tool in (None, 'ninja') | 216 assert options.build_tool in (None, 'ninja') |
| 553 return options, args | |
| 554 | |
| 555 | |
| 556 def real_main(): | |
| 557 options, args = get_parsed_options() | |
| 558 | 217 |
| 559 # Prepare environment. | 218 # Prepare environment. |
| 560 env = EchoDict(os.environ) | 219 env = EchoDict(os.environ) |
| 561 | 220 |
| 562 # start goma | 221 # start goma |
| 563 goma_ready, goma_cloudtail = goma_setup(options, env) | 222 goma_ready, goma_cloudtail = goma_utils.goma_setup(options, env) |
| 564 | 223 |
| 565 if not goma_ready: | 224 if goma_ready: |
| 225 if options.goma_jobs is None: |
| 226 options.goma_jobs = goma_utils.determine_goma_jobs() |
| 227 else: |
| 566 assert options.compiler not in ('goma', 'goma-clang') | 228 assert options.compiler not in ('goma', 'goma-clang') |
| 567 assert options.goma_dir is None | 229 assert options.goma_dir is None |
| 568 elif options.goma_jobs is None: | 230 options.goma_jobs = goma_utils.determine_goma_jobs() |
| 569 options.goma_jobs = determine_goma_jobs() | 231 |
| 570 | 232 |
| 571 # build | 233 # build |
| 572 exit_status = main_ninja(options, args, env) | 234 exit_status = main_ninja(options, args, env) |
| 573 | 235 |
| 574 # stop goma | 236 # stop goma |
| 575 goma_teardown(options, env, exit_status, goma_cloudtail) | 237 goma_utils.goma_teardown(options, env, exit_status, goma_cloudtail) |
| 576 | 238 |
| 577 return exit_status | 239 return exit_status |
| 578 | 240 |
| 579 | 241 |
| 580 if '__main__' == __name__: | 242 if '__main__' == __name__: |
| 581 sys.exit(real_main()) | 243 sys.exit(real_main()) |
| OLD | NEW |