| OLD | NEW |
| 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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 help='path to a file containing the input arguments ' | 82 help='path to a file containing the input arguments ' |
| 83 'as a JSON object.') | 83 'as a JSON object.') |
| 84 subp.add_argument('output_path', nargs=1, | 84 subp.add_argument('output_path', nargs=1, |
| 85 help='path to a file containing the output arguments ' | 85 help='path to a file containing the output arguments ' |
| 86 'as a JSON object.') | 86 'as a JSON object.') |
| 87 subp.set_defaults(func=self.CmdAnalyze) | 87 subp.set_defaults(func=self.CmdAnalyze) |
| 88 | 88 |
| 89 subp = subps.add_parser('gen', | 89 subp = subps.add_parser('gen', |
| 90 help='generate a new set of build files') | 90 help='generate a new set of build files') |
| 91 AddCommonOptions(subp) | 91 AddCommonOptions(subp) |
| 92 subp.add_argument('--swarming-targets-file', |
| 93 help='save runtime dependencies for targets listed ' |
| 94 'in file.') |
| 92 subp.add_argument('path', nargs=1, | 95 subp.add_argument('path', nargs=1, |
| 93 help='path to generate build into') | 96 help='path to generate build into') |
| 94 subp.set_defaults(func=self.CmdGen) | 97 subp.set_defaults(func=self.CmdGen) |
| 95 | 98 |
| 96 subp = subps.add_parser('isolate', | 99 subp = subps.add_parser('isolate', |
| 97 help='build isolates') | 100 help='build isolates') |
| 98 AddCommonOptions(subp) | 101 AddCommonOptions(subp) |
| 99 subp.add_argument('path', nargs=1, | 102 subp.add_argument('path', nargs=1, |
| 100 help='path build was generated into.') | 103 help='path build was generated into.') |
| 101 subp.add_argument('input_path', nargs=1, | 104 subp.add_argument('input_path', nargs=1, |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 if vals['gyp_defines']: | 332 if vals['gyp_defines']: |
| 330 vals['gyp_defines'] += ' ' + mixin_vals['gyp_defines'] | 333 vals['gyp_defines'] += ' ' + mixin_vals['gyp_defines'] |
| 331 else: | 334 else: |
| 332 vals['gyp_defines'] = mixin_vals['gyp_defines'] | 335 vals['gyp_defines'] = mixin_vals['gyp_defines'] |
| 333 if 'mixins' in mixin_vals: | 336 if 'mixins' in mixin_vals: |
| 334 self.FlattenMixins(mixin_vals['mixins'], vals, visited) | 337 self.FlattenMixins(mixin_vals['mixins'], vals, visited) |
| 335 return vals | 338 return vals |
| 336 | 339 |
| 337 def RunGNGen(self, path, vals): | 340 def RunGNGen(self, path, vals): |
| 338 cmd = self.GNCmd('gen', path, vals['gn_args']) | 341 cmd = self.GNCmd('gen', path, vals['gn_args']) |
| 342 |
| 343 swarming_targets = [] |
| 344 if self.args.swarming_targets_file: |
| 345 # We need GN to generate the list of runtime dependencies for |
| 346 # the compile targets listed (one per line) in the file so |
| 347 # we can run them via swarming. We use ninja_to_gn.pyl to convert |
| 348 # the compile targets to the matching GN labels. |
| 349 contents = self.ReadFile(self.args.swarming_targets_file) |
| 350 swarming_targets = contents.splitlines() |
| 351 ninja_targets_to_labels = ast.literal_eval(self.ReadFile(os.path.join( |
| 352 self.chromium_src_dir, 'testing', 'buildbot', 'ninja_to_gn.pyl'))) |
| 353 gn_labels = [] |
| 354 for target in swarming_targets: |
| 355 if not target in ninja_targets_to_labels: |
| 356 raise MBErr('test target "%s" not found in %s' % |
| 357 (target, '//testing/buildbot/ninja_to_gn.pyl')) |
| 358 gn_labels.append(ninja_targets_to_labels[target]) |
| 359 |
| 360 gn_runtime_deps_path = self.ToAbsPath(path, 'runtime_deps') |
| 361 self.WriteFile(gn_runtime_deps_path, '\n'.join(gn_labels) + '\n') |
| 362 cmd.append('--runtime-deps-list-file=%s' % gn_runtime_deps_path) |
| 363 |
| 339 ret, _, _ = self.Run(cmd) | 364 ret, _, _ = self.Run(cmd) |
| 365 |
| 366 for target in swarming_targets: |
| 367 deps_path = self.ToAbsPath(path, target + '.runtime_deps') |
| 368 if not self.Exists(deps_path): |
| 369 raise MBErr('did not generate %s' % deps_path) |
| 370 |
| 340 return ret | 371 return ret |
| 341 | 372 |
| 342 def GNCmd(self, subcommand, path, gn_args=''): | 373 def GNCmd(self, subcommand, path, gn_args=''): |
| 343 if self.platform == 'linux2': | 374 if self.platform == 'linux2': |
| 344 gn_path = os.path.join(self.chromium_src_dir, 'buildtools', 'linux64', | 375 gn_path = os.path.join(self.chromium_src_dir, 'buildtools', 'linux64', |
| 345 'gn') | 376 'gn') |
| 346 elif self.platform == 'darwin': | 377 elif self.platform == 'darwin': |
| 347 gn_path = os.path.join(self.chromium_src_dir, 'buildtools', 'mac', | 378 gn_path = os.path.join(self.chromium_src_dir, 'buildtools', 'mac', |
| 348 'gn') | 379 'gn') |
| 349 else: | 380 else: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 380 self.Print() | 411 self.Print() |
| 381 | 412 |
| 382 cmd = self.GYPCmd(output_dir, vals['gyp_defines'], config=gyp_config) | 413 cmd = self.GYPCmd(output_dir, vals['gyp_defines'], config=gyp_config) |
| 383 cmd.extend(['-G', 'config_path=%s' % self.args.input_path[0], | 414 cmd.extend(['-G', 'config_path=%s' % self.args.input_path[0], |
| 384 '-G', 'analyzer_output_path=%s' % self.args.output_path[0]]) | 415 '-G', 'analyzer_output_path=%s' % self.args.output_path[0]]) |
| 385 ret, _, _ = self.Run(cmd) | 416 ret, _, _ = self.Run(cmd) |
| 386 if not ret and self.args.verbose: | 417 if not ret and self.args.verbose: |
| 387 outp = json.loads(self.ReadFile(self.args.output_path[0])) | 418 outp = json.loads(self.ReadFile(self.args.output_path[0])) |
| 388 self.Print() | 419 self.Print() |
| 389 self.Print('analyze output:') | 420 self.Print('analyze output:') |
| 390 self.PrintJSON(inp) | 421 self.PrintJSON(outp) |
| 391 self.Print() | 422 self.Print() |
| 392 | 423 |
| 393 return ret | 424 return ret |
| 394 | 425 |
| 395 def RunGNIsolate(self, vals): | 426 def RunGNIsolate(self, vals): |
| 396 build_path = self.args.path[0] | 427 build_path = self.args.path[0] |
| 397 inp = self.ReadInputJSON(['targets']) | 428 inp = self.ReadInputJSON(['targets']) |
| 398 if self.args.verbose: | 429 if self.args.verbose: |
| 399 self.Print() | 430 self.Print() |
| 400 self.Print('isolate input:') | 431 self.Print('isolate input:') |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 else: | 528 else: |
| 498 # TODO(dpranke): Handle script_tests and other types of | 529 # TODO(dpranke): Handle script_tests and other types of |
| 499 # swarmed tests. | 530 # swarmed tests. |
| 500 self.WriteFailureAndRaise('unknown test type "%s" for %s' % | 531 self.WriteFailureAndRaise('unknown test type "%s" for %s' % |
| 501 (test_type, target), | 532 (test_type, target), |
| 502 output_path) | 533 output_path) |
| 503 | 534 |
| 504 | 535 |
| 505 return cmdline, extra_files | 536 return cmdline, extra_files |
| 506 | 537 |
| 507 def ToAbsPath(self, build_path, relpath): | 538 def ToAbsPath(self, build_path, *comps): |
| 508 return os.path.join(self.chromium_src_dir, | 539 return os.path.join(self.chromium_src_dir, |
| 509 self.ToSrcRelPath(build_path), | 540 self.ToSrcRelPath(build_path), |
| 510 relpath) | 541 *comps) |
| 511 | 542 |
| 512 def ToSrcRelPath(self, path): | 543 def ToSrcRelPath(self, path): |
| 513 """Returns a relative path from the top of the repo.""" | 544 """Returns a relative path from the top of the repo.""" |
| 514 # TODO: Support normal paths in addition to source-absolute paths. | 545 # TODO: Support normal paths in addition to source-absolute paths. |
| 515 assert(path.startswith('//')) | 546 assert(path.startswith('//')) |
| 516 return path[2:] | 547 return path[2:] |
| 517 | 548 |
| 518 def ParseGYPConfigPath(self, path): | 549 def ParseGYPConfigPath(self, path): |
| 519 rpath = self.ToSrcRelPath(path) | 550 rpath = self.ToSrcRelPath(path) |
| 520 output_dir, _, config = rpath.rpartition('/') | 551 output_dir, _, config = rpath.rpartition('/') |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 | 748 |
| 718 if __name__ == '__main__': | 749 if __name__ == '__main__': |
| 719 try: | 750 try: |
| 720 sys.exit(main(sys.argv[1:])) | 751 sys.exit(main(sys.argv[1:])) |
| 721 except MBErr as e: | 752 except MBErr as e: |
| 722 print(e) | 753 print(e) |
| 723 sys.exit(1) | 754 sys.exit(1) |
| 724 except KeyboardInterrupt: | 755 except KeyboardInterrupt: |
| 725 print("interrupted, exiting", stream=sys.stderr) | 756 print("interrupted, exiting", stream=sys.stderr) |
| 726 sys.exit(130) | 757 sys.exit(130) |
| OLD | NEW |