[zircon] [gn] build_api_module("images")

Export structured information about all the "image" files the
build can produce.

Bug: BLD-325
Test: gn gen && ninja
Change-Id: Ib6278d58a8f0b6313dbc3becc385194294ec8bbd
diff --git a/zircon/BUILD.gn b/zircon/BUILD.gn
index d15f32a..8683e8f 100644
--- a/zircon/BUILD.gn
+++ b/zircon/BUILD.gn
@@ -74,7 +74,7 @@
 group("default") {
   testonly = true
   deps = [
-    ":all-cpu",
+    ":images",
     ":tools",
   ]
 }
@@ -146,9 +146,11 @@
 # module's contents are found at "$root_build_dir/$target_name.json".
 # Type: list(string)
 build_api_module("api") {
+  testonly = true
   data_keys = [ "build_api_modules" ]
   deps = [
     ":buildargs",
+    ":images",
   ]
 }
 
@@ -171,3 +173,57 @@
                          ],
                          "scope")
 }
+
+# This describes all the "image" files the build can produce.
+#
+# Consumers of the build should look here for the images to be built.
+# The $cpu, $name, and $type fields identify the purpose of each image.
+# Consumers are expected to ignore extra images they have no use for or
+# whose fields they don't understand.
+#
+# The $path field indicates where the file is found in the build
+# directory.  The presence of an image in the list means that the build
+# *can* produce it, not that the build *will* produce it.  Hence,
+# consumers should use $path as an explicit argument to Ninja to ensure
+# that each needed image gets built.
+#
+# Type: list(scope)
+#
+#   cpu
+#     Required: CPU architecture the image is for, e.g. "arm64" or "x64".
+#     Type: string
+#
+#   name
+#     Required: The primary way that this image is known to consumers.
+#     Note that the name need not be unique within the images list.
+#     The tuple of ($name, $type, $cpu) should be unique.
+#     Type: string
+#
+#   label
+#     Required: The GN label of the image target.
+#     Type: label_with_toolchain
+#
+#   path
+#     Required: Path to where the file is found, relative to $root_build_dir.
+#     This is also the argument to Ninja that ensures this image will be built.
+#     Type: path relative to $root_build_dir
+#
+#   type
+#     Required: Type of file, e.g. "zbi".  This often corresponds to the
+#     extension used on the image file name, but not always.  For many
+#     miscellaneous formats, this is just "bin" and the consumer is
+#     expected to understand what the particular format is for particular
+#     $name, $cpu combinations.  Other types include:
+#      * "zbi": the ZBI (<zircon/boot/image.h>) format
+#      * "efi": an EFI executable that an EFI boot loader can load
+#      * "kernel": some other format loaded by a boot loader or emulator
+#      * "blk": contents to be written to a storage device or partition
+#     Type: string
+#
+build_api_module("images") {
+  testonly = true
+  data_keys = [ "images" ]
+  deps = [
+    ":all-cpu",
+  ]
+}
diff --git a/zircon/bootloader/BUILD.gn b/zircon/bootloader/BUILD.gn
index 4fcab9b..1dbafdb 100644
--- a/zircon/bootloader/BUILD.gn
+++ b/zircon/bootloader/BUILD.gn
@@ -57,14 +57,16 @@
       "-Wl,/entry:efi_main",
     ]
 
-    # TODO(mcgrathr): Temporary kludge for legacy Fuchsia GN build integration.
+    # For the //:images build_api_module().
     metadata = {
       images = [
         {
+          label = get_label_info(":$target_name", "label_with_toolchain")
           name = "bootloader"
           type = "efi"
           path = rebase_path("$root_out_dir/$output_name.$output_extension",
                              root_build_dir)
+          cpu = current_cpu
         },
       ]
     }
diff --git a/zircon/kernel/BUILD.gn b/zircon/kernel/BUILD.gn
index 6e4ddc9..9a76559 100644
--- a/zircon/kernel/BUILD.gn
+++ b/zircon/kernel/BUILD.gn
@@ -343,11 +343,14 @@
       ":image",
     ]
     metadata = {
+      # For the //:images build_api_module().
       images = [
         {
-          type = "zbi"
+          label = get_label_info(":$target_name", "label_with_toolchain")
           name = "kernel"
+          type = "zbi"
           path = output_path
+          cpu = current_cpu
         },
       ]
 
diff --git a/zircon/kernel/target/arm64/boot-shim/BUILD.gn b/zircon/kernel/target/arm64/boot-shim/BUILD.gn
index 4f882db..a00251a 100644
--- a/zircon/kernel/target/arm64/boot-shim/BUILD.gn
+++ b/zircon/kernel/target/arm64/boot-shim/BUILD.gn
@@ -109,8 +109,10 @@
       output_name = shim_name
       output_extension = "bin"
       metadata = {
+        # For the //:images build_api_module().
         images = [
           {
+            label = get_label_info(":$target_name", "label_with_toolchain")
             if (defined(invoker.image_metadata)) {
               forward_variables_from(invoker.image_metadata, "*")
             }
@@ -129,6 +131,7 @@
             }
             path = rebase_path("$output_dir/$output_name.$output_extension",
                                root_build_dir)
+            cpu = current_cpu
           },
         ]
       }
diff --git a/zircon/kernel/target/pc/multiboot/BUILD.gn b/zircon/kernel/target/pc/multiboot/BUILD.gn
index afe121b..4d251c0 100644
--- a/zircon/kernel/target/pc/multiboot/BUILD.gn
+++ b/zircon/kernel/target/pc/multiboot/BUILD.gn
@@ -54,6 +54,7 @@
     output_path = rebase_path("$output_dir/$target_name.$output_extension",
                               root_build_dir)
     metadata = {
+      # For the //:images build_api_module().
       images = []
       foreach(name,
               [
@@ -62,9 +63,11 @@
               ]) {
         images += [
           {
+            label = get_label_info(":$target_name", "label_with_toolchain")
             name = name
             type = "kernel"
             path = output_path
+            cpu = current_cpu
           },
         ]
       }
diff --git a/zircon/public/gn/zbi.gni b/zircon/public/gn/zbi.gni
index 75373e8..662ec67 100644
--- a/zircon/public/gn/zbi.gni
+++ b/zircon/public/gn/zbi.gni
@@ -177,6 +177,17 @@
       ]
       manifest_barrier = []
 
+      # For the //:images build_api_module().
+      images = [
+        {
+          label = get_label_info(":$target_name", "label_with_toolchain")
+          name = output_name
+          path = rebase_path(manifest_file, root_build_dir)
+          type = "manifest"
+          cpu = current_cpu
+        },
+      ]
+
       if (defined(invoker.metadata)) {
         forward_variables_from(invoker.metadata,
                                "*",
@@ -249,11 +260,13 @@
   }
 
   if (defined(invoker.output_name)) {
-    output_file = invoker.output_name
+    output_name = invoker.output_name
   } else {
-    output_file = target_name
+    output_name = target_name
   }
 
+  output_file = output_name
+
   if (defined(invoker.output_extension)) {
     if (invoker.output_extension != "") {
       output_file += ".${invoker.output_extension}"
@@ -330,6 +343,18 @@
     }
 
     metadata = {
+      # For the //:images build_api_module().
+      images = [
+        {
+          label = get_label_info(":$target_name", "label_with_toolchain")
+          name = output_name
+          path = rebase_path(output_file, root_build_dir)
+          type = "zbi"
+          cpu = cpu
+          compressed = !defined(invoker.compress) || invoker.compress
+        },
+      ]
+
       # Provide metadata so that a zbi() target can also act as if it were a
       # zbi_input() with `type = "zbi"` and $sources of this target's $outputs.
       # Thus a zbi() target can be a dependency of another zbi() target to
@@ -338,7 +363,12 @@
           [ "--type=container" ] + rebase_path(outputs, root_build_dir)
 
       if (defined(invoker.metadata)) {
-        forward_variables_from(invoker.metadata, "*", [ "zbi_input_args" ])
+        forward_variables_from(invoker.metadata,
+                               "*",
+                               [
+                                 "images",
+                                 "zbi_input_args",
+                               ])
       }
     }
   }