| 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 118     subp.add_argument('target', nargs=1, | 118     subp.add_argument('target', nargs=1, | 
| 119                       help='ninja target to generate the isolate for') | 119                       help='ninja target to generate the isolate for') | 
| 120     subp.set_defaults(func=self.CmdIsolate) | 120     subp.set_defaults(func=self.CmdIsolate) | 
| 121 | 121 | 
| 122     subp = subps.add_parser('lookup', | 122     subp = subps.add_parser('lookup', | 
| 123                             help='look up the command for a given config or ' | 123                             help='look up the command for a given config or ' | 
| 124                                  'builder') | 124                                  'builder') | 
| 125     AddCommonOptions(subp) | 125     AddCommonOptions(subp) | 
| 126     subp.set_defaults(func=self.CmdLookup) | 126     subp.set_defaults(func=self.CmdLookup) | 
| 127 | 127 | 
| 128     subp = subps.add_parser('run', | 128     subp = subps.add_parser( | 
| 129                             help='build and run the isolated version of a ' | 129         'run', | 
| 130                                  'binary') | 130         help='build and run the isolated version of a ' | 
|  | 131              'binary', | 
|  | 132         formatter_class=argparse.RawDescriptionHelpFormatter) | 
|  | 133     subp.description = ( | 
|  | 134         'Build, isolate, and run the given binary with the command line\n' | 
|  | 135         'listed in the isolate. You may pass extra arguments after the\n' | 
|  | 136         'target; use "--" if the extra arguments need to include switches.\n' | 
|  | 137         '\n' | 
|  | 138         'Examples:\n' | 
|  | 139         '\n' | 
|  | 140         '  % tools/mb/mb.py run -m chromium.linux -b "Linux Builder" \\\n' | 
|  | 141         '    //out/Default content_browsertests\n' | 
|  | 142         '\n' | 
|  | 143         '  % tools/mb/mb.py run out/Default content_browsertests\n' | 
|  | 144         '\n' | 
|  | 145         '  % tools/mb/mb.py run out/Default content_browsertests -- \\\n' | 
|  | 146         '    --test-launcher-retry-limit=0' | 
|  | 147         '\n' | 
|  | 148     ) | 
|  | 149 | 
| 131     AddCommonOptions(subp) | 150     AddCommonOptions(subp) | 
| 132     subp.add_argument('-j', '--jobs', dest='jobs', type=int, | 151     subp.add_argument('-j', '--jobs', dest='jobs', type=int, | 
| 133                       help='Number of jobs to pass to ninja') | 152                       help='Number of jobs to pass to ninja') | 
| 134     subp.add_argument('--no-build', dest='build', default=True, | 153     subp.add_argument('--no-build', dest='build', default=True, | 
| 135                       action='store_false', | 154                       action='store_false', | 
| 136                       help='Do not build, just isolate and run') | 155                       help='Do not build, just isolate and run') | 
| 137     subp.add_argument('path', nargs=1, | 156     subp.add_argument('path', nargs=1, | 
| 138                       help='path to generate build into') | 157                       help=('path to generate build into (or use).' | 
|  | 158                             ' This can be either a regular path or a ' | 
|  | 159                             'GN-style source-relative path like ' | 
|  | 160                             '//out/Default.')) | 
| 139     subp.add_argument('target', nargs=1, | 161     subp.add_argument('target', nargs=1, | 
| 140                       help='ninja target to build and run') | 162                       help='ninja target to build and run') | 
|  | 163     subp.add_argument('extra_args', nargs='*', | 
|  | 164                       help=('extra args to pass to the isolate to run. Use ' | 
|  | 165                             '"--" as the first arg if you need to pass ' | 
|  | 166                             'switches')) | 
| 141     subp.set_defaults(func=self.CmdRun) | 167     subp.set_defaults(func=self.CmdRun) | 
| 142 | 168 | 
| 143     subp = subps.add_parser('validate', | 169     subp = subps.add_parser('validate', | 
| 144                             help='validate the config file') | 170                             help='validate the config file') | 
| 145     subp.add_argument('-f', '--config-file', metavar='PATH', | 171     subp.add_argument('-f', '--config-file', metavar='PATH', | 
| 146                       default=self.default_config, | 172                       default=self.default_config, | 
| 147                       help='path to config file ' | 173                       help='path to config file ' | 
| 148                           '(default is //tools/mb/mb_config.pyl)') | 174                           '(default is //tools/mb/mb_config.pyl)') | 
| 149     subp.set_defaults(func=self.CmdValidate) | 175     subp.set_defaults(func=self.CmdValidate) | 
| 150 | 176 | 
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 246         if ret: | 272         if ret: | 
| 247           return ret | 273           return ret | 
| 248       ret = self.RunGNIsolate(vals) | 274       ret = self.RunGNIsolate(vals) | 
| 249       if ret: | 275       if ret: | 
| 250         return ret | 276         return ret | 
| 251     else: | 277     else: | 
| 252       ret = self.Build('%s_run' % target) | 278       ret = self.Build('%s_run' % target) | 
| 253       if ret: | 279       if ret: | 
| 254         return ret | 280         return ret | 
| 255 | 281 | 
| 256     ret, _, _ = self.Run([ | 282     cmd = [ | 
| 257         self.executable, | 283         self.executable, | 
| 258         self.PathJoin('tools', 'swarming_client', 'isolate.py'), | 284         self.PathJoin('tools', 'swarming_client', 'isolate.py'), | 
| 259         'run', | 285         'run', | 
| 260         '-s', | 286         '-s', | 
| 261         self.ToSrcRelPath('%s/%s.isolated' % (build_dir, target))], | 287         self.ToSrcRelPath('%s/%s.isolated' % (build_dir, target)), | 
| 262         force_verbose=False, buffer_output=False) | 288     ] | 
|  | 289     if self.args.extra_args: | 
|  | 290         cmd += ['--'] + self.args.extra_args | 
|  | 291 | 
|  | 292     ret, _, _ = self.Run(cmd, force_verbose=False, buffer_output=False) | 
| 263 | 293 | 
| 264     return ret | 294     return ret | 
| 265 | 295 | 
| 266   def CmdValidate(self, print_ok=True): | 296   def CmdValidate(self, print_ok=True): | 
| 267     errs = [] | 297     errs = [] | 
| 268 | 298 | 
| 269     # Read the file to make sure it parses. | 299     # Read the file to make sure it parses. | 
| 270     self.ReadConfigFile() | 300     self.ReadConfigFile() | 
| 271 | 301 | 
| 272     # Build a list of all of the configs referenced by builders. | 302     # Build a list of all of the configs referenced by builders. | 
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 749 | 779 | 
| 750     build_dir = self.args.path[0] | 780     build_dir = self.args.path[0] | 
| 751     target = self.args.target[0] | 781     target = self.args.target[0] | 
| 752     target_name = self.GNTargetName(target) | 782     target_name = self.GNTargetName(target) | 
| 753     command, extra_files = self.GetIsolateCommand(target, vals, gn_isolate_map) | 783     command, extra_files = self.GetIsolateCommand(target, vals, gn_isolate_map) | 
| 754 | 784 | 
| 755     label = gn_isolate_map[target_name]['label'] | 785     label = gn_isolate_map[target_name]['label'] | 
| 756     cmd = self.GNCmd('desc', build_dir, extra_args=[label, 'runtime_deps']) | 786     cmd = self.GNCmd('desc', build_dir, extra_args=[label, 'runtime_deps']) | 
| 757     ret, out, _ = self.Call(cmd) | 787     ret, out, _ = self.Call(cmd) | 
| 758     if ret: | 788     if ret: | 
|  | 789       if out: | 
|  | 790         self.Print(out) | 
| 759       return ret | 791       return ret | 
| 760 | 792 | 
| 761     runtime_deps = out.splitlines() | 793     runtime_deps = out.splitlines() | 
| 762 | 794 | 
| 763     self.WriteIsolateFiles(build_dir, command, target, runtime_deps, | 795     self.WriteIsolateFiles(build_dir, command, target, runtime_deps, | 
| 764                            extra_files) | 796                            extra_files) | 
| 765 | 797 | 
| 766     ret, _, _ = self.Run([ | 798     ret, _, _ = self.Run([ | 
| 767         self.executable, | 799         self.executable, | 
| 768         self.PathJoin('tools', 'swarming_client', 'isolate.py'), | 800         self.PathJoin('tools', 'swarming_client', 'isolate.py'), | 
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 940 | 972 | 
| 941     return cmdline, extra_files | 973     return cmdline, extra_files | 
| 942 | 974 | 
| 943   def ToAbsPath(self, build_path, *comps): | 975   def ToAbsPath(self, build_path, *comps): | 
| 944     return self.PathJoin(self.chromium_src_dir, | 976     return self.PathJoin(self.chromium_src_dir, | 
| 945                          self.ToSrcRelPath(build_path), | 977                          self.ToSrcRelPath(build_path), | 
| 946                          *comps) | 978                          *comps) | 
| 947 | 979 | 
| 948   def ToSrcRelPath(self, path): | 980   def ToSrcRelPath(self, path): | 
| 949     """Returns a relative path from the top of the repo.""" | 981     """Returns a relative path from the top of the repo.""" | 
| 950     # TODO: Support normal paths in addition to source-absolute paths. | 982     if path.startswith('//'): | 
| 951     assert(path.startswith('//')) | 983       return path[2:].replace('/', self.sep) | 
| 952     return path[2:].replace('/', self.sep) | 984     return self.RelPath(path, self.chromium_src_dir) | 
| 953 | 985 | 
| 954   def ParseGYPConfigPath(self, path): | 986   def ParseGYPConfigPath(self, path): | 
| 955     rpath = self.ToSrcRelPath(path) | 987     rpath = self.ToSrcRelPath(path) | 
| 956     output_dir, _, _ = rpath.rpartition(self.sep) | 988     output_dir, _, _ = rpath.rpartition(self.sep) | 
| 957     return output_dir | 989     return output_dir | 
| 958 | 990 | 
| 959   def GYPCmd(self, output_dir, vals): | 991   def GYPCmd(self, output_dir, vals): | 
| 960     gyp_defines = vals['gyp_defines'] | 992     gyp_defines = vals['gyp_defines'] | 
| 961     goma_dir = self.args.goma_dir | 993     goma_dir = self.args.goma_dir | 
| 962 | 994 | 
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1144     print_env('GYP_CROSSCOMPILE') | 1176     print_env('GYP_CROSSCOMPILE') | 
| 1145     print_env('GYP_DEFINES') | 1177     print_env('GYP_DEFINES') | 
| 1146 | 1178 | 
| 1147     if cmd[0] == self.executable: | 1179     if cmd[0] == self.executable: | 
| 1148       cmd = ['python'] + cmd[1:] | 1180       cmd = ['python'] + cmd[1:] | 
| 1149     self.Print(*[shell_quoter(arg) for arg in cmd]) | 1181     self.Print(*[shell_quoter(arg) for arg in cmd]) | 
| 1150 | 1182 | 
| 1151   def PrintJSON(self, obj): | 1183   def PrintJSON(self, obj): | 
| 1152     self.Print(json.dumps(obj, indent=2, sort_keys=True)) | 1184     self.Print(json.dumps(obj, indent=2, sort_keys=True)) | 
| 1153 | 1185 | 
| 1154   def Print(self, *args, **kwargs): | 1186   def GNTargetName(self, target): | 
| 1155     # This function largely exists so it can be overridden for testing. | 1187     return target[:-len('_apk')] if target.endswith('_apk') else target | 
| 1156     print(*args, **kwargs) |  | 
| 1157 | 1188 | 
| 1158   def Build(self, target): | 1189   def Build(self, target): | 
| 1159     build_dir = self.ToSrcRelPath(self.args.path[0]) | 1190     build_dir = self.ToSrcRelPath(self.args.path[0]) | 
| 1160     ninja_cmd = ['ninja', '-C', build_dir] | 1191     ninja_cmd = ['ninja', '-C', build_dir] | 
| 1161     if self.args.jobs: | 1192     if self.args.jobs: | 
| 1162       ninja_cmd.extend(['-j', '%d' % self.args.jobs]) | 1193       ninja_cmd.extend(['-j', '%d' % self.args.jobs]) | 
| 1163     ninja_cmd.append(target) | 1194     ninja_cmd.append(target) | 
| 1164     ret, _, _ = self.Run(ninja_cmd, force_verbose=False, buffer_output=False) | 1195     ret, _, _ = self.Run(ninja_cmd, force_verbose=False, buffer_output=False) | 
| 1165     return ret | 1196     return ret | 
| 1166 | 1197 | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 1196 | 1227 | 
| 1197   def ExpandUser(self, path): | 1228   def ExpandUser(self, path): | 
| 1198     # This function largely exists so it can be overridden for testing. | 1229     # This function largely exists so it can be overridden for testing. | 
| 1199     return os.path.expanduser(path) | 1230     return os.path.expanduser(path) | 
| 1200 | 1231 | 
| 1201   def Exists(self, path): | 1232   def Exists(self, path): | 
| 1202     # This function largely exists so it can be overridden for testing. | 1233     # This function largely exists so it can be overridden for testing. | 
| 1203     return os.path.exists(path) | 1234     return os.path.exists(path) | 
| 1204 | 1235 | 
| 1205   def Fetch(self, url): | 1236   def Fetch(self, url): | 
| 1206 | 1237     # This function largely exists so it can be overridden for testing. | 
| 1207     f = urllib2.urlopen(url) | 1238     f = urllib2.urlopen(url) | 
| 1208     contents = f.read() | 1239     contents = f.read() | 
| 1209     f.close() | 1240     f.close() | 
| 1210     return contents | 1241     return contents | 
| 1211 | 1242 | 
| 1212   def GNTargetName(self, target): |  | 
| 1213     return target[:-len('_apk')] if target.endswith('_apk') else target |  | 
| 1214 |  | 
| 1215   def MaybeMakeDirectory(self, path): | 1243   def MaybeMakeDirectory(self, path): | 
| 1216     try: | 1244     try: | 
| 1217       os.makedirs(path) | 1245       os.makedirs(path) | 
| 1218     except OSError, e: | 1246     except OSError, e: | 
| 1219       if e.errno != errno.EEXIST: | 1247       if e.errno != errno.EEXIST: | 
| 1220         raise | 1248         raise | 
| 1221 | 1249 | 
| 1222   def PathJoin(self, *comps): | 1250   def PathJoin(self, *comps): | 
| 1223     # This function largely exists so it can be overriden for testing. | 1251     # This function largely exists so it can be overriden for testing. | 
| 1224     return os.path.join(*comps) | 1252     return os.path.join(*comps) | 
| 1225 | 1253 | 
|  | 1254   def Print(self, *args, **kwargs): | 
|  | 1255     # This function largely exists so it can be overridden for testing. | 
|  | 1256     print(*args, **kwargs) | 
|  | 1257 | 
| 1226   def ReadFile(self, path): | 1258   def ReadFile(self, path): | 
| 1227     # This function largely exists so it can be overriden for testing. | 1259     # This function largely exists so it can be overriden for testing. | 
| 1228     with open(path) as fp: | 1260     with open(path) as fp: | 
| 1229       return fp.read() | 1261       return fp.read() | 
| 1230 | 1262 | 
|  | 1263   def RelPath(self, path, start='.'): | 
|  | 1264     # This function largely exists so it can be overriden for testing. | 
|  | 1265     return os.path.relpath(path, start) | 
|  | 1266 | 
| 1231   def RemoveFile(self, path): | 1267   def RemoveFile(self, path): | 
| 1232     # This function largely exists so it can be overriden for testing. | 1268     # This function largely exists so it can be overriden for testing. | 
| 1233     os.remove(path) | 1269     os.remove(path) | 
| 1234 | 1270 | 
| 1235   def RemoveDirectory(self, abs_path): | 1271   def RemoveDirectory(self, abs_path): | 
| 1236     if self.platform == 'win32': | 1272     if self.platform == 'win32': | 
| 1237       # In other places in chromium, we often have to retry this command | 1273       # In other places in chromium, we often have to retry this command | 
| 1238       # because we're worried about other processes still holding on to | 1274       # because we're worried about other processes still holding on to | 
| 1239       # file handles, but when MB is invoked, it will be early enough in the | 1275       # file handles, but when MB is invoked, it will be early enough in the | 
| 1240       # build that their should be no other processes to interfere. We | 1276       # build that their should be no other processes to interfere. We | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1283   # Then check to see if the arg contains any metacharacters other than | 1319   # Then check to see if the arg contains any metacharacters other than | 
| 1284   # double quotes; if it does, quote everything (including the double | 1320   # double quotes; if it does, quote everything (including the double | 
| 1285   # quotes) for safety. | 1321   # quotes) for safety. | 
| 1286   if any(a in UNSAFE_FOR_CMD for a in arg): | 1322   if any(a in UNSAFE_FOR_CMD for a in arg): | 
| 1287     arg = ''.join('^' + a if a in ALL_META_CHARS else a for a in arg) | 1323     arg = ''.join('^' + a if a in ALL_META_CHARS else a for a in arg) | 
| 1288   return arg | 1324   return arg | 
| 1289 | 1325 | 
| 1290 | 1326 | 
| 1291 if __name__ == '__main__': | 1327 if __name__ == '__main__': | 
| 1292   sys.exit(main(sys.argv[1:])) | 1328   sys.exit(main(sys.argv[1:])) | 
| OLD | NEW | 
|---|