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

Side by Side Diff: tools/mb/mb.py

Issue 1348153003: Reland "Remove the 'gyp_config' concept from MB." (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix win32 test on non-win32 platform Created 5 years, 3 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 | « tools/mb/docs/user_guide.md ('k') | tools/mb/mb_config.pyl » ('j') | 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 2015 The Chromium Authors. All rights reserved. 2 # Copyright 2015 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 """MB - the Meta-Build wrapper around GYP and GN 6 """MB - the Meta-Build wrapper around GYP and GN
7 7
8 MB is a wrapper script for GYP and GN that can be used to generate build files 8 MB is a wrapper script for GYP and GN that can be used to generate build files
9 for sets of canned configurations and analyze them. 9 for sets of canned configurations and analyze them.
10 """ 10 """
(...skipping 19 matching lines...) Expand all
30 return mbw.args.func() 30 return mbw.args.func()
31 31
32 32
33 class MetaBuildWrapper(object): 33 class MetaBuildWrapper(object):
34 def __init__(self): 34 def __init__(self):
35 p = os.path 35 p = os.path
36 d = os.path.dirname 36 d = os.path.dirname
37 self.chromium_src_dir = p.normpath(d(d(d(p.abspath(__file__))))) 37 self.chromium_src_dir = p.normpath(d(d(d(p.abspath(__file__)))))
38 self.default_config = p.join(self.chromium_src_dir, 'tools', 'mb', 38 self.default_config = p.join(self.chromium_src_dir, 'tools', 'mb',
39 'mb_config.pyl') 39 'mb_config.pyl')
40 self.executable = sys.executable
40 self.platform = sys.platform 41 self.platform = sys.platform
42 self.sep = os.sep
41 self.args = argparse.Namespace() 43 self.args = argparse.Namespace()
42 self.configs = {} 44 self.configs = {}
43 self.masters = {} 45 self.masters = {}
44 self.mixins = {} 46 self.mixins = {}
45 self.private_configs = [] 47 self.private_configs = []
46 self.common_dev_configs = [] 48 self.common_dev_configs = []
47 self.unsupported_configs = [] 49 self.unsupported_configs = []
48 50
49 def ParseArgs(self, argv): 51 def ParseArgs(self, argv):
50 def AddCommonOptions(subp): 52 def AddCommonOptions(subp):
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 141
140 raise MBErr('Unknown meta-build type "%s"' % vals['type']) 142 raise MBErr('Unknown meta-build type "%s"' % vals['type'])
141 143
142 def CmdLookup(self): 144 def CmdLookup(self):
143 vals = self.GetConfig() 145 vals = self.GetConfig()
144 if vals['type'] == 'gn': 146 if vals['type'] == 'gn':
145 cmd = self.GNCmd('gen', '<path>', vals['gn_args']) 147 cmd = self.GNCmd('gen', '<path>', vals['gn_args'])
146 elif vals['type'] == 'gyp': 148 elif vals['type'] == 'gyp':
147 if vals['gyp_crosscompile']: 149 if vals['gyp_crosscompile']:
148 self.Print('GYP_CROSSCOMPILE=1') 150 self.Print('GYP_CROSSCOMPILE=1')
149 cmd = self.GYPCmd('<path>', vals['gyp_defines'], vals['gyp_config']) 151 cmd = self.GYPCmd('<path>', vals['gyp_defines'])
150 else: 152 else:
151 raise MBErr('Unknown meta-build type "%s"' % vals['type']) 153 raise MBErr('Unknown meta-build type "%s"' % vals['type'])
152 154
153 self.PrintCmd(cmd) 155 self.PrintCmd(cmd)
154 return 0 156 return 0
155 157
156 def CmdHelp(self): 158 def CmdHelp(self):
157 if self.args.subcommand: 159 if self.args.subcommand:
158 self.ParseArgs([self.args.subcommand, '--help']) 160 self.ParseArgs([self.args.subcommand, '--help'])
159 else: 161 else:
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 raise MBErr('Builder name "%s" not found under masters[%s] in "%s"' % 280 raise MBErr('Builder name "%s" not found under masters[%s] in "%s"' %
279 (self.args.builder, self.args.master, self.args.config_file)) 281 (self.args.builder, self.args.master, self.args.config_file))
280 282
281 return self.masters[self.args.master][self.args.builder] 283 return self.masters[self.args.master][self.args.builder]
282 284
283 def FlattenConfig(self, config): 285 def FlattenConfig(self, config):
284 mixins = self.configs[config] 286 mixins = self.configs[config]
285 vals = { 287 vals = {
286 'type': None, 288 'type': None,
287 'gn_args': [], 289 'gn_args': [],
288 'gyp_config': [],
289 'gyp_defines': '', 290 'gyp_defines': '',
290 'gyp_crosscompile': False, 291 'gyp_crosscompile': False,
291 } 292 }
292 293
293 visited = [] 294 visited = []
294 self.FlattenMixins(mixins, vals, visited) 295 self.FlattenMixins(mixins, vals, visited)
295 return vals 296 return vals
296 297
297 def FlattenMixins(self, mixins, vals, visited): 298 def FlattenMixins(self, mixins, vals, visited):
298 for m in mixins: 299 for m in mixins:
299 if m not in self.mixins: 300 if m not in self.mixins:
300 raise MBErr('Unknown mixin "%s"' % m) 301 raise MBErr('Unknown mixin "%s"' % m)
301 302
302 # TODO: check for cycles in mixins. 303 # TODO: check for cycles in mixins.
303 304
304 visited.append(m) 305 visited.append(m)
305 306
306 mixin_vals = self.mixins[m] 307 mixin_vals = self.mixins[m]
307 if 'type' in mixin_vals: 308 if 'type' in mixin_vals:
308 vals['type'] = mixin_vals['type'] 309 vals['type'] = mixin_vals['type']
309 if 'gn_args' in mixin_vals: 310 if 'gn_args' in mixin_vals:
310 if vals['gn_args']: 311 if vals['gn_args']:
311 vals['gn_args'] += ' ' + mixin_vals['gn_args'] 312 vals['gn_args'] += ' ' + mixin_vals['gn_args']
312 else: 313 else:
313 vals['gn_args'] = mixin_vals['gn_args'] 314 vals['gn_args'] = mixin_vals['gn_args']
314 if 'gyp_config' in mixin_vals:
315 vals['gyp_config'] = mixin_vals['gyp_config']
316 if 'gyp_crosscompile' in mixin_vals: 315 if 'gyp_crosscompile' in mixin_vals:
317 vals['gyp_crosscompile'] = mixin_vals['gyp_crosscompile'] 316 vals['gyp_crosscompile'] = mixin_vals['gyp_crosscompile']
318 if 'gyp_defines' in mixin_vals: 317 if 'gyp_defines' in mixin_vals:
319 if vals['gyp_defines']: 318 if vals['gyp_defines']:
320 vals['gyp_defines'] += ' ' + mixin_vals['gyp_defines'] 319 vals['gyp_defines'] += ' ' + mixin_vals['gyp_defines']
321 else: 320 else:
322 vals['gyp_defines'] = mixin_vals['gyp_defines'] 321 vals['gyp_defines'] = mixin_vals['gyp_defines']
323 if 'mixins' in mixin_vals: 322 if 'mixins' in mixin_vals:
324 self.FlattenMixins(mixin_vals['mixins'], vals, visited) 323 self.FlattenMixins(mixin_vals['mixins'], vals, visited)
325 return vals 324 return vals
326 325
327 def ClobberIfNeeded(self, vals): 326 def ClobberIfNeeded(self, vals):
328 path = self.args.path[0] 327 path = self.args.path[0]
329 build_dir = self.ToAbsPath(path) 328 build_dir = self.ToAbsPath(path)
330 mb_type_path = os.path.join(build_dir, 'mb_type') 329 mb_type_path = self.PathJoin(build_dir, 'mb_type')
331 needs_clobber = False 330 needs_clobber = False
332 new_mb_type = vals['type'] 331 new_mb_type = vals['type']
333 if self.Exists(build_dir): 332 if self.Exists(build_dir):
334 if self.Exists(mb_type_path): 333 if self.Exists(mb_type_path):
335 old_mb_type = self.ReadFile(mb_type_path) 334 old_mb_type = self.ReadFile(mb_type_path)
336 if old_mb_type != new_mb_type: 335 if old_mb_type != new_mb_type:
337 self.Print("Build type mismatch: was %s, will be %s, clobbering %s" % 336 self.Print("Build type mismatch: was %s, will be %s, clobbering %s" %
338 (old_mb_type, new_mb_type, path)) 337 (old_mb_type, new_mb_type, path))
339 needs_clobber = True 338 needs_clobber = True
340 else: 339 else:
(...skipping 16 matching lines...) Expand all
357 cmd = self.GNCmd('gen', path, vals['gn_args']) 356 cmd = self.GNCmd('gen', path, vals['gn_args'])
358 357
359 swarming_targets = [] 358 swarming_targets = []
360 if self.args.swarming_targets_file: 359 if self.args.swarming_targets_file:
361 # We need GN to generate the list of runtime dependencies for 360 # We need GN to generate the list of runtime dependencies for
362 # the compile targets listed (one per line) in the file so 361 # the compile targets listed (one per line) in the file so
363 # we can run them via swarming. We use ninja_to_gn.pyl to convert 362 # we can run them via swarming. We use ninja_to_gn.pyl to convert
364 # the compile targets to the matching GN labels. 363 # the compile targets to the matching GN labels.
365 contents = self.ReadFile(self.args.swarming_targets_file) 364 contents = self.ReadFile(self.args.swarming_targets_file)
366 swarming_targets = contents.splitlines() 365 swarming_targets = contents.splitlines()
367 gn_isolate_map = ast.literal_eval(self.ReadFile(os.path.join( 366 gn_isolate_map = ast.literal_eval(self.ReadFile(self.PathJoin(
368 self.chromium_src_dir, 'testing', 'buildbot', 'gn_isolate_map.pyl'))) 367 self.chromium_src_dir, 'testing', 'buildbot', 'gn_isolate_map.pyl')))
369 gn_labels = [] 368 gn_labels = []
370 for target in swarming_targets: 369 for target in swarming_targets:
371 if not target in gn_isolate_map: 370 if not target in gn_isolate_map:
372 raise MBErr('test target "%s" not found in %s' % 371 raise MBErr('test target "%s" not found in %s' %
373 (target, '//testing/buildbot/gn_isolate_map.pyl')) 372 (target, '//testing/buildbot/gn_isolate_map.pyl'))
374 gn_labels.append(gn_isolate_map[target]['label']) 373 gn_labels.append(gn_isolate_map[target]['label'])
375 374
376 gn_runtime_deps_path = self.ToAbsPath(path, 'runtime_deps') 375 gn_runtime_deps_path = self.ToAbsPath(path, 'runtime_deps')
377 376
(...skipping 14 matching lines...) Expand all
392 if gn_isolate_map[target]['type'] == 'gpu_browser_test': 391 if gn_isolate_map[target]['type'] == 'gpu_browser_test':
393 runtime_deps_target = 'browser_tests' 392 runtime_deps_target = 'browser_tests'
394 elif gn_isolate_map[target]['type'] == 'script': 393 elif gn_isolate_map[target]['type'] == 'script':
395 # For script targets, the build target is usually a group, 394 # For script targets, the build target is usually a group,
396 # for which gn generates the runtime_deps next to the stamp file 395 # for which gn generates the runtime_deps next to the stamp file
397 # for the label, which lives under the obj/ directory. 396 # for the label, which lives under the obj/ directory.
398 label = gn_isolate_map[target]['label'] 397 label = gn_isolate_map[target]['label']
399 runtime_deps_target = 'obj/%s.stamp' % label.replace(':', '/') 398 runtime_deps_target = 'obj/%s.stamp' % label.replace(':', '/')
400 else: 399 else:
401 runtime_deps_target = target 400 runtime_deps_target = target
402 if sys.platform == 'win32': 401 if self.platform == 'win32':
403 deps_path = self.ToAbsPath(path, 402 deps_path = self.ToAbsPath(path,
404 runtime_deps_target + '.exe.runtime_deps') 403 runtime_deps_target + '.exe.runtime_deps')
405 else: 404 else:
406 deps_path = self.ToAbsPath(path, 405 deps_path = self.ToAbsPath(path,
407 runtime_deps_target + '.runtime_deps') 406 runtime_deps_target + '.runtime_deps')
408 if not self.Exists(deps_path): 407 if not self.Exists(deps_path):
409 raise MBErr('did not generate %s' % deps_path) 408 raise MBErr('did not generate %s' % deps_path)
410 409
411 command, extra_files = self.GetIsolateCommand(target, vals, 410 command, extra_files = self.GetIsolateCommand(target, vals,
412 gn_isolate_map) 411 gn_isolate_map)
413 412
414 runtime_deps = self.ReadFile(deps_path).splitlines() 413 runtime_deps = self.ReadFile(deps_path).splitlines()
415 414
416 isolate_path = self.ToAbsPath(path, target + '.isolate') 415 isolate_path = self.ToAbsPath(path, target + '.isolate')
417 self.WriteFile(isolate_path, 416 self.WriteFile(isolate_path,
418 pprint.pformat({ 417 pprint.pformat({
419 'variables': { 418 'variables': {
420 'command': command, 419 'command': command,
421 'files': sorted(runtime_deps + extra_files), 420 'files': sorted(runtime_deps + extra_files),
422 } 421 }
423 }) + '\n') 422 }) + '\n')
424 423
425 self.WriteJSON( 424 self.WriteJSON(
426 { 425 {
427 'args': [ 426 'args': [
428 '--isolated', 427 '--isolated',
429 self.ToSrcRelPath('%s%s%s.isolated' % (path, os.sep, target)), 428 self.ToSrcRelPath('%s%s%s.isolated' % (path, self.sep, target)),
430 '--isolate', 429 '--isolate',
431 self.ToSrcRelPath('%s%s%s.isolate' % (path, os.sep, target)), 430 self.ToSrcRelPath('%s%s%s.isolate' % (path, self.sep, target)),
432 ], 431 ],
433 'dir': self.chromium_src_dir, 432 'dir': self.chromium_src_dir,
434 'version': 1, 433 'version': 1,
435 }, 434 },
436 isolate_path + 'd.gen.json', 435 isolate_path + 'd.gen.json',
437 ) 436 )
438 437
439 return ret 438 return ret
440 439
441 def GNCmd(self, subcommand, path, gn_args=''): 440 def GNCmd(self, subcommand, path, gn_args=''):
442 if self.platform == 'linux2': 441 if self.platform == 'linux2':
443 gn_path = os.path.join(self.chromium_src_dir, 'buildtools', 'linux64', 442 subdir = 'linux64'
444 'gn')
445 elif self.platform == 'darwin': 443 elif self.platform == 'darwin':
446 gn_path = os.path.join(self.chromium_src_dir, 'buildtools', 'mac', 444 subdir = 'mac'
447 'gn')
448 else: 445 else:
449 gn_path = os.path.join(self.chromium_src_dir, 'buildtools', 'win', 446 subdir = 'win'
450 'gn.exe') 447 gn_path = self.PathJoin(self.chromium_src_dir, 'buildtools', subdir, 'gn')
451 448
452 cmd = [gn_path, subcommand, path] 449 cmd = [gn_path, subcommand, path]
453 gn_args = gn_args.replace("$(goma_dir)", self.args.goma_dir) 450 gn_args = gn_args.replace("$(goma_dir)", self.args.goma_dir)
454 if gn_args: 451 if gn_args:
455 cmd.append('--args=%s' % gn_args) 452 cmd.append('--args=%s' % gn_args)
456 return cmd 453 return cmd
457 454
458 def RunGYPGen(self, vals): 455 def RunGYPGen(self, vals):
459 path = self.args.path[0] 456 path = self.args.path[0]
460 457
461 output_dir, gyp_config = self.ParseGYPConfigPath(path) 458 output_dir = self.ParseGYPConfigPath(path)
462 if gyp_config != vals['gyp_config']: 459 cmd = self.GYPCmd(output_dir, vals['gyp_defines'])
463 raise MBErr('The last component of the path (%s) must match the '
464 'GYP configuration specified in the config (%s), and '
465 'it does not.' % (gyp_config, vals['gyp_config']))
466 cmd = self.GYPCmd(output_dir, vals['gyp_defines'], config=gyp_config)
467 env = None 460 env = None
468 if vals['gyp_crosscompile']: 461 if vals['gyp_crosscompile']:
469 if self.args.verbose: 462 if self.args.verbose:
470 self.Print('Setting GYP_CROSSCOMPILE=1 in the environment') 463 self.Print('Setting GYP_CROSSCOMPILE=1 in the environment')
471 env = os.environ.copy() 464 env = os.environ.copy()
472 env['GYP_CROSSCOMPILE'] = '1' 465 env['GYP_CROSSCOMPILE'] = '1'
473 ret, _, _ = self.Run(cmd, env=env) 466 ret, _, _ = self.Run(cmd, env=env)
474 return ret 467 return ret
475 468
476 def RunGYPAnalyze(self, vals): 469 def RunGYPAnalyze(self, vals):
477 output_dir, gyp_config = self.ParseGYPConfigPath(self.args.path[0]) 470 output_dir = self.ParseGYPConfigPath(self.args.path[0])
478 if gyp_config != vals['gyp_config']:
479 raise MBErr('The last component of the path (%s) must match the '
480 'GYP configuration specified in the config (%s), and '
481 'it does not.' % (gyp_config, vals['gyp_config']))
482 if self.args.verbose: 471 if self.args.verbose:
483 inp = self.ReadInputJSON(['files', 'targets']) 472 inp = self.ReadInputJSON(['files', 'targets'])
484 self.Print() 473 self.Print()
485 self.Print('analyze input:') 474 self.Print('analyze input:')
486 self.PrintJSON(inp) 475 self.PrintJSON(inp)
487 self.Print() 476 self.Print()
488 477
489 cmd = self.GYPCmd(output_dir, vals['gyp_defines'], config=gyp_config) 478 cmd = self.GYPCmd(output_dir, vals['gyp_defines'])
490 cmd.extend(['-f', 'analyzer', 479 cmd.extend(['-f', 'analyzer',
491 '-G', 'config_path=%s' % self.args.input_path[0], 480 '-G', 'config_path=%s' % self.args.input_path[0],
492 '-G', 'analyzer_output_path=%s' % self.args.output_path[0]]) 481 '-G', 'analyzer_output_path=%s' % self.args.output_path[0]])
493 ret, _, _ = self.Run(cmd) 482 ret, _, _ = self.Run(cmd)
494 if not ret and self.args.verbose: 483 if not ret and self.args.verbose:
495 outp = json.loads(self.ReadFile(self.args.output_path[0])) 484 outp = json.loads(self.ReadFile(self.args.output_path[0]))
496 self.Print() 485 self.Print()
497 self.Print('analyze output:') 486 self.Print('analyze output:')
498 self.PrintJSON(outp) 487 self.PrintJSON(outp)
499 self.Print() 488 self.Print()
500 489
501 return ret 490 return ret
502 491
503 def GetIsolateCommand(self, target, vals, gn_isolate_map): 492 def GetIsolateCommand(self, target, vals, gn_isolate_map):
504 # This needs to mirror the settings in //build/config/ui.gni: 493 # This needs to mirror the settings in //build/config/ui.gni:
505 # use_x11 = is_linux && !use_ozone. 494 # use_x11 = is_linux && !use_ozone.
506 # TODO(dpranke): Figure out how to keep this in sync better. 495 # TODO(dpranke): Figure out how to keep this in sync better.
507 use_x11 = (sys.platform == 'linux2' and 496 use_x11 = (self.platform == 'linux2' and
508 not 'target_os="android"' in vals['gn_args'] and 497 not 'target_os="android"' in vals['gn_args'] and
509 not 'use_ozone=true' in vals['gn_args']) 498 not 'use_ozone=true' in vals['gn_args'])
510 499
511 asan = 'is_asan=true' in vals['gn_args'] 500 asan = 'is_asan=true' in vals['gn_args']
512 msan = 'is_msan=true' in vals['gn_args'] 501 msan = 'is_msan=true' in vals['gn_args']
513 tsan = 'is_tsan=true' in vals['gn_args'] 502 tsan = 'is_tsan=true' in vals['gn_args']
514 503
515 executable_suffix = '.exe' if sys.platform == 'win32' else '' 504 executable_suffix = '.exe' if self.platform == 'win32' else ''
516 505
517 test_type = gn_isolate_map[target]['type'] 506 test_type = gn_isolate_map[target]['type']
518 cmdline = [] 507 cmdline = []
519 extra_files = [] 508 extra_files = []
520 509
521 if use_x11 and test_type == 'windowed_test_launcher': 510 if use_x11 and test_type == 'windowed_test_launcher':
522 extra_files = [ 511 extra_files = [
523 'xdisplaycheck', 512 'xdisplaycheck',
524 '../../testing/test_env.py', 513 '../../testing/test_env.py',
525 '../../testing/xvfb.py', 514 '../../testing/xvfb.py',
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 './' + str(target) + executable_suffix, 562 './' + str(target) + executable_suffix,
574 ] + gn_isolate_map[target].get('args') 563 ] + gn_isolate_map[target].get('args')
575 564
576 else: 565 else:
577 self.WriteFailureAndRaise('No command line for %s found (test type %s).' 566 self.WriteFailureAndRaise('No command line for %s found (test type %s).'
578 % (target, test_type), output_path=None) 567 % (target, test_type), output_path=None)
579 568
580 return cmdline, extra_files 569 return cmdline, extra_files
581 570
582 def ToAbsPath(self, build_path, *comps): 571 def ToAbsPath(self, build_path, *comps):
583 return os.path.join(self.chromium_src_dir, 572 return self.PathJoin(self.chromium_src_dir,
584 self.ToSrcRelPath(build_path), 573 self.ToSrcRelPath(build_path),
585 *comps) 574 *comps)
586 575
587 def ToSrcRelPath(self, path): 576 def ToSrcRelPath(self, path):
588 """Returns a relative path from the top of the repo.""" 577 """Returns a relative path from the top of the repo."""
589 # TODO: Support normal paths in addition to source-absolute paths. 578 # TODO: Support normal paths in addition to source-absolute paths.
590 assert(path.startswith('//')) 579 assert(path.startswith('//'))
591 return path[2:].replace('/', os.sep) 580 return path[2:].replace('/', self.sep)
592 581
593 def ParseGYPConfigPath(self, path): 582 def ParseGYPConfigPath(self, path):
594 rpath = self.ToSrcRelPath(path) 583 rpath = self.ToSrcRelPath(path)
595 output_dir, _, config = rpath.rpartition('/') 584 output_dir, _, _ = rpath.rpartition(self.sep)
596 self.CheckGYPConfigIsSupported(config, path) 585 return output_dir
597 return output_dir, config
598 586
599 def CheckGYPConfigIsSupported(self, config, path): 587 def GYPCmd(self, output_dir, gyp_defines):
600 if config not in ('Debug', 'Release'):
601 if (sys.platform in ('win32', 'cygwin') and
602 config not in ('Debug_x64', 'Release_x64')):
603 raise MBErr('Unknown or unsupported config type "%s" in "%s"' %
604 config, path)
605
606 def GYPCmd(self, output_dir, gyp_defines, config):
607 gyp_defines = gyp_defines.replace("$(goma_dir)", self.args.goma_dir) 588 gyp_defines = gyp_defines.replace("$(goma_dir)", self.args.goma_dir)
608 cmd = [ 589 cmd = [
609 sys.executable, 590 self.executable,
610 os.path.join('build', 'gyp_chromium'), 591 self.PathJoin('build', 'gyp_chromium'),
611 '-G', 592 '-G',
612 'output_dir=' + output_dir, 593 'output_dir=' + output_dir,
613 '-G',
614 'config=' + config,
615 ] 594 ]
616 for d in shlex.split(gyp_defines): 595 for d in shlex.split(gyp_defines):
617 cmd += ['-D', d] 596 cmd += ['-D', d]
618 return cmd 597 return cmd
619 598
620 def RunGNAnalyze(self, vals): 599 def RunGNAnalyze(self, vals):
621 # analyze runs before 'gn gen' now, so we need to run gn gen 600 # analyze runs before 'gn gen' now, so we need to run gn gen
622 # in order to ensure that we have a build directory. 601 # in order to ensure that we have a build directory.
623 ret = self.RunGNGen(vals) 602 ret = self.RunGNGen(vals)
624 if ret: 603 if ret:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 response_file.close() 639 response_file.close()
661 640
662 matching_targets = [] 641 matching_targets = []
663 try: 642 try:
664 cmd = self.GNCmd('refs', self.args.path[0]) + [ 643 cmd = self.GNCmd('refs', self.args.path[0]) + [
665 '@%s' % response_file.name, '--all', '--as=output'] 644 '@%s' % response_file.name, '--all', '--as=output']
666 ret, out, _ = self.Run(cmd, force_verbose=False) 645 ret, out, _ = self.Run(cmd, force_verbose=False)
667 if ret and not 'The input matches no targets' in out: 646 if ret and not 'The input matches no targets' in out:
668 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out), 647 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out),
669 output_path) 648 output_path)
670 build_dir = self.ToSrcRelPath(self.args.path[0]) + os.sep 649 build_dir = self.ToSrcRelPath(self.args.path[0]) + self.sep
671 for output in out.splitlines(): 650 for output in out.splitlines():
672 build_output = output.replace(build_dir, '') 651 build_output = output.replace(build_dir, '')
673 if build_output in inp['targets']: 652 if build_output in inp['targets']:
674 matching_targets.append(build_output) 653 matching_targets.append(build_output)
675 654
676 cmd = self.GNCmd('refs', self.args.path[0]) + [ 655 cmd = self.GNCmd('refs', self.args.path[0]) + [
677 '@%s' % response_file.name, '--all'] 656 '@%s' % response_file.name, '--all']
678 ret, out, _ = self.Run(cmd, force_verbose=False) 657 ret, out, _ = self.Run(cmd, force_verbose=False)
679 if ret and not 'The input matches no targets' in out: 658 if ret and not 'The input matches no targets' in out:
680 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out), 659 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out),
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 718
740 def WriteJSON(self, obj, path, force_verbose=False): 719 def WriteJSON(self, obj, path, force_verbose=False):
741 try: 720 try:
742 self.WriteFile(path, json.dumps(obj, indent=2, sort_keys=True) + '\n', 721 self.WriteFile(path, json.dumps(obj, indent=2, sort_keys=True) + '\n',
743 force_verbose=force_verbose) 722 force_verbose=force_verbose)
744 except Exception as e: 723 except Exception as e:
745 raise MBErr('Error %s writing to the output path "%s"' % 724 raise MBErr('Error %s writing to the output path "%s"' %
746 (e, path)) 725 (e, path))
747 726
748 def PrintCmd(self, cmd): 727 def PrintCmd(self, cmd):
749 if cmd[0] == sys.executable: 728 if cmd[0] == self.executable:
750 cmd = ['python'] + cmd[1:] 729 cmd = ['python'] + cmd[1:]
751 self.Print(*[pipes.quote(c) for c in cmd]) 730 self.Print(*[pipes.quote(c) for c in cmd])
752 731
753 def PrintJSON(self, obj): 732 def PrintJSON(self, obj):
754 self.Print(json.dumps(obj, indent=2, sort_keys=True)) 733 self.Print(json.dumps(obj, indent=2, sort_keys=True))
755 734
756 def Print(self, *args, **kwargs): 735 def Print(self, *args, **kwargs):
757 # This function largely exists so it can be overridden for testing. 736 # This function largely exists so it can be overridden for testing.
758 print(*args, **kwargs) 737 print(*args, **kwargs)
759 738
(...skipping 27 matching lines...) Expand all
787 # This function largely exists so it can be overridden for testing. 766 # This function largely exists so it can be overridden for testing.
788 return os.path.exists(path) 767 return os.path.exists(path)
789 768
790 def MaybeMakeDirectory(self, path): 769 def MaybeMakeDirectory(self, path):
791 try: 770 try:
792 os.makedirs(path) 771 os.makedirs(path)
793 except OSError, e: 772 except OSError, e:
794 if e.errno != errno.EEXIST: 773 if e.errno != errno.EEXIST:
795 raise 774 raise
796 775
776 def PathJoin(self, *comps):
777 # This function largely exists so it can be overriden for testing.
778 return os.path.join(*comps)
779
797 def ReadFile(self, path): 780 def ReadFile(self, path):
798 # This function largely exists so it can be overriden for testing. 781 # This function largely exists so it can be overriden for testing.
799 with open(path) as fp: 782 with open(path) as fp:
800 return fp.read() 783 return fp.read()
801 784
802 def RemoveFile(self, path): 785 def RemoveFile(self, path):
803 # This function largely exists so it can be overriden for testing. 786 # This function largely exists so it can be overriden for testing.
804 os.remove(path) 787 os.remove(path)
805 788
806 def RemoveDirectory(self, abs_path): 789 def RemoveDirectory(self, abs_path):
807 if sys.platform == 'win32': 790 if self.platform == 'win32':
808 # In other places in chromium, we often have to retry this command 791 # In other places in chromium, we often have to retry this command
809 # because we're worried about other processes still holding on to 792 # because we're worried about other processes still holding on to
810 # file handles, but when MB is invoked, it will be early enough in the 793 # file handles, but when MB is invoked, it will be early enough in the
811 # build that their should be no other processes to interfere. We 794 # build that their should be no other processes to interfere. We
812 # can change this if need be. 795 # can change this if need be.
813 self.Run(['cmd.exe', '/c', 'rmdir', '/q', '/s', abs_path]) 796 self.Run(['cmd.exe', '/c', 'rmdir', '/q', '/s', abs_path])
814 else: 797 else:
815 shutil.rmtree(abs_path, ignore_errors=True) 798 shutil.rmtree(abs_path, ignore_errors=True)
816 799
817 def TempFile(self, mode='w'): 800 def TempFile(self, mode='w'):
(...skipping 14 matching lines...) Expand all
832 815
833 if __name__ == '__main__': 816 if __name__ == '__main__':
834 try: 817 try:
835 sys.exit(main(sys.argv[1:])) 818 sys.exit(main(sys.argv[1:]))
836 except MBErr as e: 819 except MBErr as e:
837 print(e) 820 print(e)
838 sys.exit(1) 821 sys.exit(1)
839 except KeyboardInterrupt: 822 except KeyboardInterrupt:
840 print("interrupted, exiting", stream=sys.stderr) 823 print("interrupted, exiting", stream=sys.stderr)
841 sys.exit(130) 824 sys.exit(130)
OLDNEW
« no previous file with comments | « tools/mb/docs/user_guide.md ('k') | tools/mb/mb_config.pyl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698