Add support for --runtime-deps-list-file flag to MB.

This allows us to compute what files are needed at runtime
to run each of the specified targets while we are also
generating the .ninja files to build the targets; since GN
has integrated support for this, we don't need to build
.isolate.gen.json or .isolate files at compile time like
we do for GYP.

As far as the implementation goes, while
--runtime-deps-list-file takes a list of GN labels (like
//base:base_unittests), we actually only have a list of ninja
build targets (like 'base_unittests'). So, we need to add a
mapping of ninja target -> GN label somewhere.

I think the best place to do this is in //testing/buildbot ,
and there I've updated the manage.py presubmit checks to
make sure that we have mappings for all of the targets
listed in the *.json config files. We can't easily check
that the mapping is right, but at least we can verify
that it does exist.

[email protected], [email protected]
BUG=480053

Review URL: https://codereview.chromium.org/1169923008

Cr-Commit-Position: refs/heads/master@{#333802}
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index 0c3d4469..5b991414 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -89,6 +89,9 @@
     subp = subps.add_parser('gen',
                             help='generate a new set of build files')
     AddCommonOptions(subp)
+    subp.add_argument('--swarming-targets-file',
+                      help='save runtime dependencies for targets listed '
+                           'in file.')
     subp.add_argument('path', nargs=1,
                       help='path to generate build into')
     subp.set_defaults(func=self.CmdGen)
@@ -336,7 +339,35 @@
 
   def RunGNGen(self, path, vals):
     cmd = self.GNCmd('gen', path, vals['gn_args'])
+
+    swarming_targets = []
+    if self.args.swarming_targets_file:
+      # We need GN to generate the list of runtime dependencies for
+      # the compile targets listed (one per line) in the file so
+      # we can run them via swarming. We use ninja_to_gn.pyl to convert
+      # the compile targets to the matching GN labels.
+      contents = self.ReadFile(self.args.swarming_targets_file)
+      swarming_targets = contents.splitlines()
+      ninja_targets_to_labels = ast.literal_eval(self.ReadFile(os.path.join(
+          self.chromium_src_dir, 'testing', 'buildbot', 'ninja_to_gn.pyl')))
+      gn_labels = []
+      for target in swarming_targets:
+        if not target in ninja_targets_to_labels:
+          raise MBErr('test target "%s"  not found in %s' %
+                      (target, '//testing/buildbot/ninja_to_gn.pyl'))
+        gn_labels.append(ninja_targets_to_labels[target])
+
+      gn_runtime_deps_path = self.ToAbsPath(path, 'runtime_deps')
+      self.WriteFile(gn_runtime_deps_path, '\n'.join(gn_labels) + '\n')
+      cmd.append('--runtime-deps-list-file=%s' % gn_runtime_deps_path)
+
     ret, _, _ = self.Run(cmd)
+
+    for target in swarming_targets:
+      deps_path = self.ToAbsPath(path, target + '.runtime_deps')
+      if not self.Exists(deps_path):
+          raise MBErr('did not generate %s' % deps_path)
+
     return ret
 
   def GNCmd(self, subcommand, path, gn_args=''):
@@ -387,7 +418,7 @@
       outp = json.loads(self.ReadFile(self.args.output_path[0]))
       self.Print()
       self.Print('analyze output:')
-      self.PrintJSON(inp)
+      self.PrintJSON(outp)
       self.Print()
 
     return ret
@@ -504,10 +535,10 @@
 
     return cmdline, extra_files
 
-  def ToAbsPath(self, build_path, relpath):
+  def ToAbsPath(self, build_path, *comps):
     return os.path.join(self.chromium_src_dir,
                         self.ToSrcRelPath(build_path),
-                        relpath)
+                        *comps)
 
   def ToSrcRelPath(self, path):
     """Returns a relative path from the top of the repo."""