[zircon][gn] Use shared source_set() for FIDL tables

Factor out the FIDL --tables generation into a source_set() that is
shared by both C and LLCPP bindings (and others in the future).  This
avoids generating and compiling the same tables twice.

Bug: BLD-470 #done
Change-Id: If02249cc7a5ff6626109ecdd78c7ec543846252d
diff --git a/zircon/public/gn/fidl.gni b/zircon/public/gn/fidl.gni
index 38bdc31..43d8fd7 100644
--- a/zircon/public/gn/fidl.gni
+++ b/zircon/public/gn/fidl.gni
@@ -89,6 +89,7 @@
 fidl_support = [
   "$zx/public/gn/fidl/c.gni",
   "$zx/public/gn/fidl/llcpp.gni",
+  "$zx/public/gn/fidl/tables.gni",
 ]
 
 # Each support module defines $fidl_support_fidlc and
diff --git a/zircon/public/gn/fidl/c.gni b/zircon/public/gn/fidl/c.gni
index 7d7850b..05d9101 100644
--- a/zircon/public/gn/fidl/c.gni
+++ b/zircon/public/gn/fidl/c.gni
@@ -34,10 +34,6 @@
         switch = "--c-server"
         path = "server.c"
       },
-      {
-        switch = "--tables"
-        path = "tables.cpp"
-      },
     ]
   },
 ]
@@ -90,6 +86,7 @@
 
       # The generated code uses these.
       deps += [
+        ":$fidl_target.tables",
         "$zx/system/ulib/fidl",
         "$zx/system/ulib/zircon",
       ]
diff --git a/zircon/public/gn/fidl/llcpp.gni b/zircon/public/gn/fidl/llcpp.gni
index d0b6505..5296288 100644
--- a/zircon/public/gn/fidl/llcpp.gni
+++ b/zircon/public/gn/fidl/llcpp.gni
@@ -22,18 +22,10 @@
   {
     name = "llcpp"
     files = [
-      # TODO(BLD-470): Refactor fidl.gni to better support multiple bindings
-      # using tables.cpp.
-      # First item must be json, because the fidl_llcpp_library
-      # exposes the first item to fidlgen_llcpp_zircon in the Fuchsia build.
       {
         switch = "--json"
         path = "fidl.json"
       },
-      {
-        switch = "--tables"
-        path = "tables.cpp"
-      },
     ]
   },
 ]
@@ -73,7 +65,6 @@
       sources = [
         "gen/llcpp/fidl.cc",
       ]
-      sources += invoker.fidlc_outputs
 
       configs += [ "$zx/public/gn/config:visibility_hidden" ]
 
@@ -98,7 +89,10 @@
         "$zx/system/ulib/fidl:fidl-llcpp.headers",
         "$zx/system/ulib/fit:fit.headers",
       ]
-      deps += [ "$zx/system/ulib/fidl:fidl-llcpp" ]
+      deps += [
+        ":$fidl_target.tables",
+        "$zx/system/ulib/fidl:fidl-llcpp",
+      ]
 
       # TODO(BLD-441): Get the metadata below into the dependency graph.
       # Putting the metadata here directly would duplicate the information
@@ -128,8 +122,9 @@
     # informs the //tool/fidlgen_llcpp_zircon scripts what generated sources
     # need to be updated.
     # This will go away when the bindings generation is done directly here.
-    fidlc_outputs = invoker.fidlc_outputs
     group(library_target) {
+      fidlc_outputs = invoker.fidlc_outputs
+      assert(fidlc_outputs == [ fidlc_outputs[0] ])
       metadata = {
         fidl_gen = [
           {
@@ -156,7 +151,7 @@
               "-header",
               header,
               "-source",
-              source
+              source,
             ]
           },
         ]
diff --git a/zircon/public/gn/fidl/tables.gni b/zircon/public/gn/fidl/tables.gni
new file mode 100644
index 0000000..856ca78
--- /dev/null
+++ b/zircon/public/gn/fidl/tables.gni
@@ -0,0 +1,62 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This is the $fidl_support module for the C/C++ FIDL tables, which are
+# required by C and C++ bindings (and maybe others).  See fidl_library() for
+# details.  This file should not normally be imported by other code.
+
+# This tells fidl_library() to invoke fidl_tables().
+fidl_support_templates = [
+  {
+    import = "$zx/public/gn/fidl/tables.gni"
+    target = "fidl_tables"
+    fidlc = "tables"
+  },
+]
+
+# This tells fidl_library() what fidlc outputs fidl_tables() requires.
+fidl_support_fidlc = [
+  {
+    name = "tables"
+    files = [
+      {
+        switch = "--tables"
+        path = "tables.cpp"
+      },
+    ]
+  },
+]
+
+# Provide C/C++ FIDL tables for fidl_library().  **Do not use directly!**
+#
+# This is never used directly, but only indirectly by fidl_library().
+# See there for details.
+#
+# This produces source_set("$target_name.tables").  Other bindings targets
+# depend on it.
+template("fidl_tables") {
+  not_needed([ "target_name" ])
+  not_needed(invoker, "*")
+  if (current_toolchain != default_toolchain) {
+    fidl_target = target_name
+    tables_target = "$fidl_target.tables"
+
+    source_set(tables_target) {
+      forward_variables_from(invoker,
+                             [
+                               "visibility",
+                               "testonly",
+                             ])
+
+      configs += [ "$zx/public/gn/config:visibility_hidden" ]
+
+      # Depend on the fidlc generation step and compile what it produces.
+      deps = invoker.fidlc_deps
+      sources = invoker.fidlc_outputs
+
+      # The generated code uses this.
+      deps += [ "$zx/system/ulib/fidl" ]
+    }
+  }
+}