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

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

Issue 2341403004: Revert of Update MB to use `gn analyze`. (Closed)
Patch Set: Created 4 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 | « testing/buildbot/manage.py ('k') | tools/mb/mb_unittest.py » ('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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 self.mixins = {} 54 self.mixins = {}
55 55
56 def Main(self, args): 56 def Main(self, args):
57 self.ParseArgs(args) 57 self.ParseArgs(args)
58 try: 58 try:
59 ret = self.args.func() 59 ret = self.args.func()
60 if ret: 60 if ret:
61 self.DumpInputFiles() 61 self.DumpInputFiles()
62 return ret 62 return ret
63 except KeyboardInterrupt: 63 except KeyboardInterrupt:
64 self.Print('interrupted, exiting') 64 self.Print('interrupted, exiting', stream=sys.stderr)
65 return 130 65 return 130
66 except Exception: 66 except Exception:
67 self.DumpInputFiles() 67 self.DumpInputFiles()
68 s = traceback.format_exc() 68 s = traceback.format_exc()
69 for l in s.splitlines(): 69 for l in s.splitlines():
70 self.Print(l) 70 self.Print(l)
71 return 1 71 return 1
72 72
73 def ParseArgs(self, argv): 73 def ParseArgs(self, argv):
74 def AddCommonOptions(subp): 74 def AddCommonOptions(subp):
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 help='The command to get help for.') 222 help='The command to get help for.')
223 subp.set_defaults(func=self.CmdHelp) 223 subp.set_defaults(func=self.CmdHelp)
224 224
225 self.args = parser.parse_args(argv) 225 self.args = parser.parse_args(argv)
226 226
227 def DumpInputFiles(self): 227 def DumpInputFiles(self):
228 228
229 def DumpContentsOfFilePassedTo(arg_name, path): 229 def DumpContentsOfFilePassedTo(arg_name, path):
230 if path and self.Exists(path): 230 if path and self.Exists(path):
231 self.Print("\n# To recreate the file passed to %s:" % arg_name) 231 self.Print("\n# To recreate the file passed to %s:" % arg_name)
232 self.Print("%% cat > %s <<EOF" % path) 232 self.Print("%% cat > %s <<EOF)" % path)
233 contents = self.ReadFile(path) 233 contents = self.ReadFile(path)
234 self.Print(contents) 234 self.Print(contents)
235 self.Print("EOF\n%\n") 235 self.Print("EOF\n%\n")
236 236
237 if getattr(self.args, 'input_path', None): 237 if getattr(self.args, 'input_path', None):
238 DumpContentsOfFilePassedTo( 238 DumpContentsOfFilePassedTo(
239 'argv[0] (input_path)', self.args.input_path[0]) 239 'argv[0] (input_path)', self.args.input_path[0])
240 if getattr(self.args, 'swarming_targets_file', None): 240 if getattr(self.args, 'swarming_targets_file', None):
241 DumpContentsOfFilePassedTo( 241 DumpContentsOfFilePassedTo(
242 '--swarming-targets-file', self.args.swarming_targets_file) 242 '--swarming-targets-file', self.args.swarming_targets_file)
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 try: 636 try:
637 contents = ast.literal_eval(self.ReadFile(self.args.config_file)) 637 contents = ast.literal_eval(self.ReadFile(self.args.config_file))
638 except SyntaxError as e: 638 except SyntaxError as e:
639 raise MBErr('Failed to parse config file "%s": %s' % 639 raise MBErr('Failed to parse config file "%s": %s' %
640 (self.args.config_file, e)) 640 (self.args.config_file, e))
641 641
642 self.configs = contents['configs'] 642 self.configs = contents['configs']
643 self.masters = contents['masters'] 643 self.masters = contents['masters']
644 self.mixins = contents['mixins'] 644 self.mixins = contents['mixins']
645 645
646 def ReadIsolateMap(self):
647 return ast.literal_eval(self.ReadFile(self.PathJoin(
648 self.chromium_src_dir, 'testing', 'buildbot', 'gn_isolate_map.pyl')))
649
650 def ConfigFromArgs(self): 646 def ConfigFromArgs(self):
651 if self.args.config: 647 if self.args.config:
652 if self.args.master or self.args.builder: 648 if self.args.master or self.args.builder:
653 raise MBErr('Can not specific both -c/--config and -m/--master or ' 649 raise MBErr('Can not specific both -c/--config and -m/--master or '
654 '-b/--builder') 650 '-b/--builder')
655 651
656 return self.args.config 652 return self.args.config
657 653
658 if not self.args.master or not self.args.builder: 654 if not self.args.master or not self.args.builder:
659 raise MBErr('Must specify either -c/--config or ' 655 raise MBErr('Must specify either -c/--config or '
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 # Since GN hasn't run yet, the build directory may not even exist. 763 # Since GN hasn't run yet, the build directory may not even exist.
768 self.MaybeMakeDirectory(self.ToAbsPath(build_dir)) 764 self.MaybeMakeDirectory(self.ToAbsPath(build_dir))
769 765
770 gn_args_path = self.ToAbsPath(build_dir, 'args.gn') 766 gn_args_path = self.ToAbsPath(build_dir, 'args.gn')
771 self.WriteFile(gn_args_path, gn_args, force_verbose=True) 767 self.WriteFile(gn_args_path, gn_args, force_verbose=True)
772 768
773 swarming_targets = [] 769 swarming_targets = []
774 if getattr(self.args, 'swarming_targets_file', None): 770 if getattr(self.args, 'swarming_targets_file', None):
775 # We need GN to generate the list of runtime dependencies for 771 # We need GN to generate the list of runtime dependencies for
776 # the compile targets listed (one per line) in the file so 772 # the compile targets listed (one per line) in the file so
777 # we can run them via swarming. We use gn_isolate_map.pyl to convert 773 # we can run them via swarming. We use ninja_to_gn.pyl to convert
778 # the compile targets to the matching GN labels. 774 # the compile targets to the matching GN labels.
779 path = self.args.swarming_targets_file 775 path = self.args.swarming_targets_file
780 if not self.Exists(path): 776 if not self.Exists(path):
781 self.WriteFailureAndRaise('"%s" does not exist' % path, 777 self.WriteFailureAndRaise('"%s" does not exist' % path,
782 output_path=None) 778 output_path=None)
783 contents = self.ReadFile(path) 779 contents = self.ReadFile(path)
784 swarming_targets = set(contents.splitlines()) 780 swarming_targets = set(contents.splitlines())
781 gn_isolate_map = ast.literal_eval(self.ReadFile(self.PathJoin(
782 self.chromium_src_dir, 'testing', 'buildbot', 'gn_isolate_map.pyl')))
783 gn_labels = []
784 err = ''
785 for target in swarming_targets:
786 target_name = self.GNTargetName(target)
787 if not target_name in gn_isolate_map:
788 err += ('test target "%s" not found\n' % target_name)
789 elif gn_isolate_map[target_name]['type'] == 'unknown':
790 err += ('test target "%s" type is unknown\n' % target_name)
791 else:
792 gn_labels.append(gn_isolate_map[target_name]['label'])
785 793
786 isolate_map = self.ReadIsolateMap()
787 err, labels = self.MapTargetsToLabels(isolate_map, swarming_targets)
788 if err: 794 if err:
789 raise MBErr(err) 795 raise MBErr('Error: Failed to match swarming targets to %s:\n%s' %
796 ('//testing/buildbot/gn_isolate_map.pyl', err))
790 797
791 gn_runtime_deps_path = self.ToAbsPath(build_dir, 'runtime_deps') 798 gn_runtime_deps_path = self.ToAbsPath(build_dir, 'runtime_deps')
792 self.WriteFile(gn_runtime_deps_path, '\n'.join(labels) + '\n') 799 self.WriteFile(gn_runtime_deps_path, '\n'.join(gn_labels) + '\n')
793 cmd.append('--runtime-deps-list-file=%s' % gn_runtime_deps_path) 800 cmd.append('--runtime-deps-list-file=%s' % gn_runtime_deps_path)
794 801
795 ret, _, _ = self.Run(cmd) 802 ret, _, _ = self.Run(cmd)
796 if ret: 803 if ret:
797 # If `gn gen` failed, we should exit early rather than trying to 804 # If `gn gen` failed, we should exit early rather than trying to
798 # generate isolates. Run() will have already logged any error output. 805 # generate isolates. Run() will have already logged any error output.
799 self.Print('GN gen failed: %d' % ret) 806 self.Print('GN gen failed: %d' % ret)
800 return ret 807 return ret
801 808
802 android = 'target_os="android"' in vals['gn_args'] 809 android = 'target_os="android"' in vals['gn_args']
803 for target in swarming_targets: 810 for target in swarming_targets:
804 if android: 811 if android:
805 # Android targets may be either android_apk or executable. The former 812 # Android targets may be either android_apk or executable. The former
806 # will result in runtime_deps associated with the stamp file, while the 813 # will result in runtime_deps associated with the stamp file, while the
807 # latter will result in runtime_deps associated with the executable. 814 # latter will result in runtime_deps associated with the executable.
808 label = isolate_map[target]['label'] 815 target_name = self.GNTargetName(target)
816 label = gn_isolate_map[target_name]['label']
809 runtime_deps_targets = [ 817 runtime_deps_targets = [
810 target + '.runtime_deps', 818 target_name + '.runtime_deps',
811 'obj/%s.stamp.runtime_deps' % label.replace(':', '/')] 819 'obj/%s.stamp.runtime_deps' % label.replace(':', '/')]
812 elif isolate_map[target]['type'] == 'gpu_browser_test': 820 elif gn_isolate_map[target]['type'] == 'gpu_browser_test':
813 if self.platform == 'win32': 821 if self.platform == 'win32':
814 runtime_deps_targets = ['browser_tests.exe.runtime_deps'] 822 runtime_deps_targets = ['browser_tests.exe.runtime_deps']
815 else: 823 else:
816 runtime_deps_targets = ['browser_tests.runtime_deps'] 824 runtime_deps_targets = ['browser_tests.runtime_deps']
817 elif (isolate_map[target]['type'] == 'script' or 825 elif (gn_isolate_map[target]['type'] == 'script' or
818 isolate_map[target].get('label_type') == 'group'): 826 gn_isolate_map[target].get('label_type') == 'group'):
819 # For script targets, the build target is usually a group, 827 # For script targets, the build target is usually a group,
820 # for which gn generates the runtime_deps next to the stamp file 828 # for which gn generates the runtime_deps next to the stamp file
821 # for the label, which lives under the obj/ directory. 829 # for the label, which lives under the obj/ directory.
822 label = isolate_map[target]['label'] 830 label = gn_isolate_map[target]['label']
823 runtime_deps_targets = [ 831 runtime_deps_targets = [
824 'obj/%s.stamp.runtime_deps' % label.replace(':', '/')] 832 'obj/%s.stamp.runtime_deps' % label.replace(':', '/')]
825 elif self.platform == 'win32': 833 elif self.platform == 'win32':
826 runtime_deps_targets = [target + '.exe.runtime_deps'] 834 runtime_deps_targets = [target + '.exe.runtime_deps']
827 else: 835 else:
828 runtime_deps_targets = [target + '.runtime_deps'] 836 runtime_deps_targets = [target + '.runtime_deps']
829 837
830 for r in runtime_deps_targets: 838 for r in runtime_deps_targets:
831 runtime_deps_path = self.ToAbsPath(build_dir, r) 839 runtime_deps_path = self.ToAbsPath(build_dir, r)
832 if self.Exists(runtime_deps_path): 840 if self.Exists(runtime_deps_path):
833 break 841 break
834 else: 842 else:
835 raise MBErr('did not generate any of %s' % 843 raise MBErr('did not generate any of %s' %
836 ', '.join(runtime_deps_targets)) 844 ', '.join(runtime_deps_targets))
837 845
838 command, extra_files = self.GetIsolateCommand(target, vals) 846 command, extra_files = self.GetIsolateCommand(target, vals,
847 gn_isolate_map)
839 848
840 runtime_deps = self.ReadFile(runtime_deps_path).splitlines() 849 runtime_deps = self.ReadFile(runtime_deps_path).splitlines()
841 850
842 self.WriteIsolateFiles(build_dir, command, target, runtime_deps, 851 self.WriteIsolateFiles(build_dir, command, target, runtime_deps,
843 extra_files) 852 extra_files)
844 853
845 return 0 854 return 0
846 855
847 def RunGNIsolate(self, vals): 856 def RunGNIsolate(self, vals):
848 target = self.args.target[0] 857 gn_isolate_map = ast.literal_eval(self.ReadFile(self.PathJoin(
849 isolate_map = self.ReadIsolateMap() 858 self.chromium_src_dir, 'testing', 'buildbot', 'gn_isolate_map.pyl')))
850 err, labels = self.MapTargetsToLabels(isolate_map, [target])
851 if err:
852 raise MBErr(err)
853 label = labels[0]
854 859
855 build_dir = self.args.path[0] 860 build_dir = self.args.path[0]
856 command, extra_files = self.GetIsolateCommand(target, vals) 861 target = self.args.target[0]
862 target_name = self.GNTargetName(target)
863 command, extra_files = self.GetIsolateCommand(target, vals, gn_isolate_map)
857 864
865 label = gn_isolate_map[target_name]['label']
858 cmd = self.GNCmd('desc', build_dir, label, 'runtime_deps') 866 cmd = self.GNCmd('desc', build_dir, label, 'runtime_deps')
859 ret, out, _ = self.Call(cmd) 867 ret, out, _ = self.Call(cmd)
860 if ret: 868 if ret:
861 if out: 869 if out:
862 self.Print(out) 870 self.Print(out)
863 return ret 871 return ret
864 872
865 runtime_deps = out.splitlines() 873 runtime_deps = out.splitlines()
866 874
867 self.WriteIsolateFiles(build_dir, command, target, runtime_deps, 875 self.WriteIsolateFiles(build_dir, command, target, runtime_deps,
(...skipping 29 matching lines...) Expand all
897 self.ToSrcRelPath('%s/%s.isolated' % (build_dir, target)), 905 self.ToSrcRelPath('%s/%s.isolated' % (build_dir, target)),
898 '--isolate', 906 '--isolate',
899 self.ToSrcRelPath('%s/%s.isolate' % (build_dir, target)), 907 self.ToSrcRelPath('%s/%s.isolate' % (build_dir, target)),
900 ], 908 ],
901 'dir': self.chromium_src_dir, 909 'dir': self.chromium_src_dir,
902 'version': 1, 910 'version': 1,
903 }, 911 },
904 isolate_path + 'd.gen.json', 912 isolate_path + 'd.gen.json',
905 ) 913 )
906 914
907 def MapTargetsToLabels(self, isolate_map, targets):
908 labels = []
909 err = ''
910 for target in targets:
911 if target == 'all':
912 labels.append(target)
913 elif not target in isolate_map:
914 non_run_target = target[:-4]
915 if target.endswith('_run') and non_run_target in isolate_map:
916 labels.append(isolate_map[non_run_target]['label'] + '_run')
917 elif target.startswith('//'):
918 labels.append(target)
919 else:
920 err += ('target "%s" not found in '
921 '//testing/buildbot/gn_isolate_map.pyl\n' % target)
922 elif isolate_map[target]['type'] == 'unknown':
923 err += ('test target "%s" type is unknown\n' % target)
924 else:
925 labels.append(isolate_map[target]['label'])
926 return err, labels
927
928 def GNCmd(self, subcommand, path, *args): 915 def GNCmd(self, subcommand, path, *args):
929 if self.platform == 'linux2': 916 if self.platform == 'linux2':
930 subdir, exe = 'linux64', 'gn' 917 subdir, exe = 'linux64', 'gn'
931 elif self.platform == 'darwin': 918 elif self.platform == 'darwin':
932 subdir, exe = 'mac', 'gn' 919 subdir, exe = 'mac', 'gn'
933 else: 920 else:
934 subdir, exe = 'win', 'gn.exe' 921 subdir, exe = 'win', 'gn.exe'
935 922
936 gn_path = self.PathJoin(self.chromium_src_dir, 'buildtools', subdir, exe) 923 gn_path = self.PathJoin(self.chromium_src_dir, 'buildtools', subdir, exe)
924
937 return [gn_path, subcommand, path] + list(args) 925 return [gn_path, subcommand, path] + list(args)
938 926
939
940 def GNArgs(self, vals): 927 def GNArgs(self, vals):
941 if vals['cros_passthrough']: 928 if vals['cros_passthrough']:
942 if not 'GN_ARGS' in os.environ: 929 if not 'GN_ARGS' in os.environ:
943 raise MBErr('MB is expecting GN_ARGS to be in the environment') 930 raise MBErr('MB is expecting GN_ARGS to be in the environment')
944 gn_args = os.environ['GN_ARGS'] 931 gn_args = os.environ['GN_ARGS']
945 if not re.search('target_os.*=.*"chromeos"', gn_args): 932 if not re.search('target_os.*=.*"chromeos"', gn_args):
946 raise MBErr('GN_ARGS is missing target_os = "chromeos": (GN_ARGS=%s)' % 933 raise MBErr('GN_ARGS is missing target_os = "chromeos": (GN_ARGS=%s)' %
947 gn_args) 934 gn_args)
948 else: 935 else:
949 gn_args = vals['gn_args'] 936 gn_args = vals['gn_args']
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 ret, _, _ = self.Run(cmd, env=env) 981 ret, _, _ = self.Run(cmd, env=env)
995 if not ret and self.args.verbose: 982 if not ret and self.args.verbose:
996 outp = json.loads(self.ReadFile(self.args.output_path[0])) 983 outp = json.loads(self.ReadFile(self.args.output_path[0]))
997 self.Print() 984 self.Print()
998 self.Print('analyze output:') 985 self.Print('analyze output:')
999 self.PrintJSON(outp) 986 self.PrintJSON(outp)
1000 self.Print() 987 self.Print()
1001 988
1002 return ret 989 return ret
1003 990
1004 def GetIsolateCommand(self, target, vals): 991 def GetIsolateCommand(self, target, vals, gn_isolate_map):
1005 android = 'target_os="android"' in vals['gn_args'] 992 android = 'target_os="android"' in vals['gn_args']
1006 993
1007 # This needs to mirror the settings in //build/config/ui.gni: 994 # This needs to mirror the settings in //build/config/ui.gni:
1008 # use_x11 = is_linux && !use_ozone. 995 # use_x11 = is_linux && !use_ozone.
1009 use_x11 = (self.platform == 'linux2' and 996 use_x11 = (self.platform == 'linux2' and
1010 not android and 997 not android and
1011 not 'use_ozone=true' in vals['gn_args']) 998 not 'use_ozone=true' in vals['gn_args'])
1012 999
1013 asan = 'is_asan=true' in vals['gn_args'] 1000 asan = 'is_asan=true' in vals['gn_args']
1014 msan = 'is_msan=true' in vals['gn_args'] 1001 msan = 'is_msan=true' in vals['gn_args']
1015 tsan = 'is_tsan=true' in vals['gn_args'] 1002 tsan = 'is_tsan=true' in vals['gn_args']
1016 1003
1017 isolate_map = self.ReadIsolateMap() 1004 target_name = self.GNTargetName(target)
1018 test_type = isolate_map[target]['type'] 1005 test_type = gn_isolate_map[target_name]['type']
1019 1006
1020 executable = isolate_map[target].get('executable', target) 1007 executable = gn_isolate_map[target_name].get('executable', target_name)
1021 executable_suffix = '.exe' if self.platform == 'win32' else '' 1008 executable_suffix = '.exe' if self.platform == 'win32' else ''
1022 1009
1023 cmdline = [] 1010 cmdline = []
1024 extra_files = [] 1011 extra_files = []
1025 1012
1026 if test_type == 'nontest':
1027 self.WriteFailureAndRaise('We should not be isolating %s.' % target,
1028 output_path=None)
1029
1030 if android and test_type != "script": 1013 if android and test_type != "script":
1031 logdog_command = [ 1014 logdog_command = [
1032 '--logdog-bin-cmd', './../../bin/logdog_butler', 1015 '--logdog-bin-cmd', './../../bin/logdog_butler',
1033 '--project', 'chromium', 1016 '--project', 'chromium',
1034 '--service-account-json', 1017 '--service-account-json',
1035 '/creds/service_accounts/service-account-luci-logdog-publisher.json', 1018 '/creds/service_accounts/service-account-luci-logdog-publisher.json',
1036 '--prefix', 'android/swarming/logcats/${SWARMING_TASK_ID}', 1019 '--prefix', 'android/swarming/logcats/${SWARMING_TASK_ID}',
1037 '--source', '${ISOLATED_OUTDIR}/logcats', 1020 '--source', '${ISOLATED_OUTDIR}/logcats',
1038 '--name', 'unified_logcats', 1021 '--name', 'unified_logcats',
1039 ] 1022 ]
1040 test_cmdline = [ 1023 test_cmdline = [
1041 self.PathJoin('bin', 'run_%s' % target), 1024 self.PathJoin('bin', 'run_%s' % target_name),
1042 '--logcat-output-file', '${ISOLATED_OUTDIR}/logcats', 1025 '--logcat-output-file', '${ISOLATED_OUTDIR}/logcats',
1043 '--target-devices-file', '${SWARMING_BOT_FILE}', 1026 '--target-devices-file', '${SWARMING_BOT_FILE}',
1044 '-v' 1027 '-v'
1045 ] 1028 ]
1046 cmdline = (['./../../build/android/test_wrapper/logdog_wrapper.py'] 1029 cmdline = (['./../../build/android/test_wrapper/logdog_wrapper.py']
1047 + logdog_command + test_cmdline) 1030 + logdog_command + test_cmdline)
1048 elif use_x11 and test_type == 'windowed_test_launcher': 1031 elif use_x11 and test_type == 'windowed_test_launcher':
1049 extra_files = [ 1032 extra_files = [
1050 'xdisplaycheck', 1033 'xdisplaycheck',
1051 '../../testing/test_env.py', 1034 '../../testing/test_env.py',
(...skipping 19 matching lines...) Expand all
1071 '--brave-new-test-launcher', 1054 '--brave-new-test-launcher',
1072 '--test-launcher-bot-mode', 1055 '--test-launcher-bot-mode',
1073 '--asan=%d' % asan, 1056 '--asan=%d' % asan,
1074 '--msan=%d' % msan, 1057 '--msan=%d' % msan,
1075 '--tsan=%d' % tsan, 1058 '--tsan=%d' % tsan,
1076 ] 1059 ]
1077 elif test_type == 'gpu_browser_test': 1060 elif test_type == 'gpu_browser_test':
1078 extra_files = [ 1061 extra_files = [
1079 '../../testing/test_env.py' 1062 '../../testing/test_env.py'
1080 ] 1063 ]
1081 gtest_filter = isolate_map[target]['gtest_filter'] 1064 gtest_filter = gn_isolate_map[target]['gtest_filter']
1082 cmdline = [ 1065 cmdline = [
1083 '../../testing/test_env.py', 1066 '../../testing/test_env.py',
1084 './browser_tests' + executable_suffix, 1067 './browser_tests' + executable_suffix,
1085 '--test-launcher-bot-mode', 1068 '--test-launcher-bot-mode',
1086 '--enable-gpu', 1069 '--enable-gpu',
1087 '--test-launcher-jobs=1', 1070 '--test-launcher-jobs=1',
1088 '--gtest_filter=%s' % gtest_filter, 1071 '--gtest_filter=%s' % gtest_filter,
1089 ] 1072 ]
1090 elif test_type == 'script': 1073 elif test_type == 'script':
1091 extra_files = [ 1074 extra_files = [
1092 '../../testing/test_env.py' 1075 '../../testing/test_env.py'
1093 ] 1076 ]
1094 cmdline = [ 1077 cmdline = [
1095 '../../testing/test_env.py', 1078 '../../testing/test_env.py',
1096 '../../' + self.ToSrcRelPath(isolate_map[target]['script']) 1079 '../../' + self.ToSrcRelPath(gn_isolate_map[target]['script'])
1097 ] 1080 ]
1098 elif test_type in ('raw'): 1081 elif test_type in ('raw'):
1099 extra_files = [] 1082 extra_files = []
1100 cmdline = [ 1083 cmdline = [
1101 './' + str(target) + executable_suffix, 1084 './' + str(target) + executable_suffix,
1102 ] 1085 ]
1103 1086
1104 else: 1087 else:
1105 self.WriteFailureAndRaise('No command line for %s found (test type %s).' 1088 self.WriteFailureAndRaise('No command line for %s found (test type %s).'
1106 % (target, test_type), output_path=None) 1089 % (target, test_type), output_path=None)
1107 1090
1108 cmdline += isolate_map[target].get('args', []) 1091 cmdline += gn_isolate_map[target_name].get('args', [])
1109 1092
1110 return cmdline, extra_files 1093 return cmdline, extra_files
1111 1094
1112 def ToAbsPath(self, build_path, *comps): 1095 def ToAbsPath(self, build_path, *comps):
1113 return self.PathJoin(self.chromium_src_dir, 1096 return self.PathJoin(self.chromium_src_dir,
1114 self.ToSrcRelPath(build_path), 1097 self.ToSrcRelPath(build_path),
1115 *comps) 1098 *comps)
1116 1099
1117 def ToSrcRelPath(self, path): 1100 def ToSrcRelPath(self, path):
1118 """Returns a relative path from the top of the repo.""" 1101 """Returns a relative path from the top of the repo."""
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 if 'GYP_CHROMIUM_NO_ACTION' in env: 1177 if 'GYP_CHROMIUM_NO_ACTION' in env:
1195 del env['GYP_CHROMIUM_NO_ACTION'] 1178 del env['GYP_CHROMIUM_NO_ACTION']
1196 if 'GYP_CROSSCOMPILE' in env: 1179 if 'GYP_CROSSCOMPILE' in env:
1197 del env['GYP_CROSSCOMPILE'] 1180 del env['GYP_CROSSCOMPILE']
1198 env['GYP_DEFINES'] = gyp_defines 1181 env['GYP_DEFINES'] = gyp_defines
1199 if vals['gyp_crosscompile']: 1182 if vals['gyp_crosscompile']:
1200 env['GYP_CROSSCOMPILE'] = '1' 1183 env['GYP_CROSSCOMPILE'] = '1'
1201 return cmd, env 1184 return cmd, env
1202 1185
1203 def RunGNAnalyze(self, vals): 1186 def RunGNAnalyze(self, vals):
1204 # Analyze runs before 'gn gen' now, so we need to run gn gen 1187 # analyze runs before 'gn gen' now, so we need to run gn gen
1205 # in order to ensure that we have a build directory. 1188 # in order to ensure that we have a build directory.
1206 ret = self.RunGNGen(vals) 1189 ret = self.RunGNGen(vals)
1207 if ret: 1190 if ret:
1208 return ret 1191 return ret
1209 1192
1210 build_path = self.args.path[0]
1211 input_path = self.args.input_path[0]
1212 gn_input_path = input_path + '.gn'
1213 output_path = self.args.output_path[0]
1214 gn_output_path = output_path + '.gn'
1215
1216 inp = self.ReadInputJSON(['files', 'test_targets', 1193 inp = self.ReadInputJSON(['files', 'test_targets',
1217 'additional_compile_targets']) 1194 'additional_compile_targets'])
1218 if self.args.verbose: 1195 if self.args.verbose:
1219 self.Print() 1196 self.Print()
1220 self.Print('analyze input:') 1197 self.Print('analyze input:')
1221 self.PrintJSON(inp) 1198 self.PrintJSON(inp)
1222 self.Print() 1199 self.Print()
1223 1200
1201 # TODO(crbug.com/555273) - currently GN treats targets and
1202 # additional_compile_targets identically since we can't tell the
1203 # difference between a target that is a group in GN and one that isn't.
1204 # We should eventually fix this and treat the two types differently.
1205 targets = (set(inp['test_targets']) |
1206 set(inp['additional_compile_targets']))
1207
1208 output_path = self.args.output_path[0]
1209
1210 # Bail out early if a GN file was modified, since 'gn refs' won't know
1211 # what to do about it. Also, bail out early if 'all' was asked for,
1212 # since we can't deal with it yet.
1213 if (any(f.endswith('.gn') or f.endswith('.gni') for f in inp['files']) or
1214 'all' in targets):
1215 self.WriteJSON({
1216 'status': 'Found dependency (all)',
1217 'compile_targets': sorted(targets),
1218 'test_targets': sorted(targets & set(inp['test_targets'])),
1219 }, output_path)
1220 return 0
1224 1221
1225 # This shouldn't normally happen, but could due to unusual race conditions, 1222 # This shouldn't normally happen, but could due to unusual race conditions,
1226 # like a try job that gets scheduled before a patch lands but runs after 1223 # like a try job that gets scheduled before a patch lands but runs after
1227 # the patch has landed. 1224 # the patch has landed.
1228 if not inp['files']: 1225 if not inp['files']:
1229 self.Print('Warning: No files modified in patch, bailing out early.') 1226 self.Print('Warning: No files modified in patch, bailing out early.')
1230 self.WriteJSON({ 1227 self.WriteJSON({
1231 'status': 'No dependency', 1228 'status': 'No dependency',
1232 'compile_targets': [], 1229 'compile_targets': [],
1233 'test_targets': [], 1230 'test_targets': [],
1234 }, output_path) 1231 }, output_path)
1235 return 0 1232 return 0
1236 1233
1237 gn_inp = {} 1234 ret = 0
1238 gn_inp['files'] = ['//' + f for f in inp['files'] if not f.startswith('//')] 1235 response_file = self.TempFile()
1236 response_file.write('\n'.join(inp['files']) + '\n')
1237 response_file.close()
1239 1238
1240 isolate_map = self.ReadIsolateMap() 1239 matching_targets = set()
1241 err, gn_inp['additional_compile_targets'] = self.MapTargetsToLabels( 1240 try:
1242 isolate_map, inp['additional_compile_targets']) 1241 cmd = self.GNCmd('refs',
1243 if err: 1242 self.args.path[0],
1244 raise MBErr(err) 1243 '@%s' % response_file.name,
1244 '--all',
1245 '--as=output')
1246 ret, out, _ = self.Run(cmd, force_verbose=False)
1247 if ret and not 'The input matches no targets' in out:
1248 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out),
1249 output_path)
1250 build_dir = self.ToSrcRelPath(self.args.path[0]) + self.sep
1251 for output in out.splitlines():
1252 build_output = output.replace(build_dir, '')
1253 if build_output in targets:
1254 matching_targets.add(build_output)
1245 1255
1246 err, gn_inp['test_targets'] = self.MapTargetsToLabels( 1256 cmd = self.GNCmd('refs',
1247 isolate_map, inp['test_targets']) 1257 self.args.path[0],
1248 if err: 1258 '@%s' % response_file.name,
1249 raise MBErr(err) 1259 '--all')
1250 labels_to_targets = {} 1260 ret, out, _ = self.Run(cmd, force_verbose=False)
1251 for i, label in enumerate(gn_inp['test_targets']): 1261 if ret and not 'The input matches no targets' in out:
1252 labels_to_targets[label] = inp['test_targets'][i] 1262 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out),
1263 output_path)
1264 for label in out.splitlines():
1265 build_target = label[2:]
1266 # We want to accept 'chrome/android:chrome_public_apk' and
1267 # just 'chrome_public_apk'. This may result in too many targets
1268 # getting built, but we can adjust that later if need be.
1269 for input_target in targets:
1270 if (input_target == build_target or
1271 build_target.endswith(':' + input_target)):
1272 matching_targets.add(input_target)
1273 finally:
1274 self.RemoveFile(response_file.name)
1253 1275
1254 try: 1276 if matching_targets:
1255 self.WriteJSON(gn_inp, gn_input_path) 1277 self.WriteJSON({
1256 cmd = self.GNCmd('analyze', build_path, gn_input_path, gn_output_path) 1278 'status': 'Found dependency',
1257 ret, _, _ = self.Run(cmd, force_verbose=True) 1279 'compile_targets': sorted(matching_targets),
1258 if ret: 1280 'test_targets': sorted(matching_targets &
1259 return ret 1281 set(inp['test_targets'])),
1282 }, output_path)
1283 else:
1284 self.WriteJSON({
1285 'status': 'No dependency',
1286 'compile_targets': [],
1287 'test_targets': [],
1288 }, output_path)
1260 1289
1261 gn_outp_str = self.ReadFile(gn_output_path) 1290 if self.args.verbose:
1262 try: 1291 outp = json.loads(self.ReadFile(output_path))
1263 gn_outp = json.loads(gn_outp_str) 1292 self.Print()
1264 except Exception as e: 1293 self.Print('analyze output:')
1265 self.Print("Failed to parse the JSON string GN returned: %s\n%s" 1294 self.PrintJSON(outp)
1266 % (repr(gn_outp_str), str(e))) 1295 self.Print()
1267 raise
1268
1269 outp = {}
1270 if 'status' in gn_outp:
1271 outp['status'] = gn_outp['status']
1272 if 'error' in gn_outp:
1273 outp['error'] = gn_outp['error']
1274 if 'invalid_targets' in gn_outp:
1275 outp['invalid_targets'] = gn_outp['invalid_targets']
1276 if 'compile_targets' in gn_outp:
1277 outp['compile_targets'] = [
1278 label.replace('//', '') for label in gn_outp['compile_targets']]
1279 if 'test_targets' in gn_outp:
1280 outp['test_targets'] = [
1281 labels_to_targets[label] for label in gn_outp['test_targets']]
1282
1283 if self.args.verbose:
1284 self.Print()
1285 self.Print('analyze output:')
1286 self.PrintJSON(outp)
1287 self.Print()
1288
1289 self.WriteJSON(outp, output_path)
1290
1291 finally:
1292 if self.Exists(gn_input_path):
1293 self.RemoveFile(gn_input_path)
1294 if self.Exists(gn_output_path):
1295 self.RemoveFile(gn_output_path)
1296 1296
1297 return 0 1297 return 0
1298 1298
1299 def ReadInputJSON(self, required_keys): 1299 def ReadInputJSON(self, required_keys):
1300 path = self.args.input_path[0] 1300 path = self.args.input_path[0]
1301 output_path = self.args.output_path[0] 1301 output_path = self.args.output_path[0]
1302 if not self.Exists(path): 1302 if not self.Exists(path):
1303 self.WriteFailureAndRaise('"%s" does not exist' % path, output_path) 1303 self.WriteFailureAndRaise('"%s" does not exist' % path, output_path)
1304 1304
1305 try: 1305 try:
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1368 print_env('GYP_LINK_CONCURRENCY') 1368 print_env('GYP_LINK_CONCURRENCY')
1369 print_env('LLVM_FORCE_HEAD_REVISION') 1369 print_env('LLVM_FORCE_HEAD_REVISION')
1370 1370
1371 if cmd[0] == self.executable: 1371 if cmd[0] == self.executable:
1372 cmd = ['python'] + cmd[1:] 1372 cmd = ['python'] + cmd[1:]
1373 self.Print(*[shell_quoter(arg) for arg in cmd]) 1373 self.Print(*[shell_quoter(arg) for arg in cmd])
1374 1374
1375 def PrintJSON(self, obj): 1375 def PrintJSON(self, obj):
1376 self.Print(json.dumps(obj, indent=2, sort_keys=True)) 1376 self.Print(json.dumps(obj, indent=2, sort_keys=True))
1377 1377
1378 def GNTargetName(self, target):
1379 return target
1380
1378 def Build(self, target): 1381 def Build(self, target):
1379 build_dir = self.ToSrcRelPath(self.args.path[0]) 1382 build_dir = self.ToSrcRelPath(self.args.path[0])
1380 ninja_cmd = ['ninja', '-C', build_dir] 1383 ninja_cmd = ['ninja', '-C', build_dir]
1381 if self.args.jobs: 1384 if self.args.jobs:
1382 ninja_cmd.extend(['-j', '%d' % self.args.jobs]) 1385 ninja_cmd.extend(['-j', '%d' % self.args.jobs])
1383 ninja_cmd.append(target) 1386 ninja_cmd.append(target)
1384 ret, _, _ = self.Run(ninja_cmd, force_verbose=False, buffer_output=False) 1387 ret, _, _ = self.Run(ninja_cmd, force_verbose=False, buffer_output=False)
1385 return ret 1388 return ret
1386 1389
1387 def Run(self, cmd, env=None, force_verbose=True, buffer_output=True): 1390 def Run(self, cmd, env=None, force_verbose=True, buffer_output=True):
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 # Then check to see if the arg contains any metacharacters other than 1513 # Then check to see if the arg contains any metacharacters other than
1511 # double quotes; if it does, quote everything (including the double 1514 # double quotes; if it does, quote everything (including the double
1512 # quotes) for safety. 1515 # quotes) for safety.
1513 if any(a in UNSAFE_FOR_CMD for a in arg): 1516 if any(a in UNSAFE_FOR_CMD for a in arg):
1514 arg = ''.join('^' + a if a in ALL_META_CHARS else a for a in arg) 1517 arg = ''.join('^' + a if a in ALL_META_CHARS else a for a in arg)
1515 return arg 1518 return arg
1516 1519
1517 1520
1518 if __name__ == '__main__': 1521 if __name__ == '__main__':
1519 sys.exit(main(sys.argv[1:])) 1522 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « testing/buildbot/manage.py ('k') | tools/mb/mb_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698