[virtualization] Avoid rebuilding guest images when nothing changed.

Currently, a "fx build" involving the "prebuilt_image" target will
always execute the target (and all of its downstream actions), even
if nothing has changed.

The reason is as follows:

The "guest_prebuilt" action needs to perform some trickery to allow a
build to succeed even if no prebuilt image is available. It does this
by dynamically generating a depfile linking the prebuilt image to a
copy of the image in the output directory. (See added comments in this
CL for details).

The current depfile is in an incorrect format, however: GN (or, more
precisely, Ninja) expects the LHS of the depfile to have a path relative
to the output directory, while the current depfile has an absolute path.
Ninja becomes confused, and makes the conservative decision to just
execute the action again.

This CL updates the depfile to be relative to the out directory, as is
expected by Ninja. We also add some additional comments explaining some
of the tricks being carried out by the "prebuilt_image" action.

After this CL, a "fx build" on an unmodified tree performs no actions,
as expected.

Change-Id: I789a7ba7154ee40350278bcea8ad048a587ca857
diff --git a/src/virtualization/packages/check_image.sh b/src/virtualization/packages/check_image.sh
index a62c531..b0482be 100755
--- a/src/virtualization/packages/check_image.sh
+++ b/src/virtualization/packages/check_image.sh
@@ -34,4 +34,6 @@
 cp "${SOURCE_IMAGE}" "${TARGET_IMAGE}"
 
 # Write a depfile to force the copy to happen when the image file changes.
+#
+# See comments in "guest_package.gni" as to why this is required.
 echo "${TARGET_IMAGE}: ${SOURCE_IMAGE}" > $DEPFILE
diff --git a/src/virtualization/packages/guest_package.gni b/src/virtualization/packages/guest_package.gni
index 0dcb713..ce6f162 100644
--- a/src/virtualization/packages/guest_package.gni
+++ b/src/virtualization/packages/guest_package.gni
@@ -181,14 +181,30 @@
     visibility = [ ":*" ]
     script = "//src/virtualization/packages/check_image.sh"
 
+    # If the input file exists, we want to copy it to the output.
+    # Otherwise, we want to generate an empty file.
+    #
+    # GN has no way to specify an "optional input" -- we can either
+    # specify an input (causing GN to error out if the file doesn't
+    # exist); or not specify an input (meaning that GN will not rebuild
+    # when the input image changes).
+    #
+    # We work around this by not specifying the input file as
+    # a dependency explicitly, but having the "check_image.sh" script
+    # out a depfile the first time it is run. This gives the script
+    # a chance to run and generate a fake empty image file the first
+    # time it runs, and after that, GN will correctly rebuild when
+    # required.
     depfile = "${invoker.output}.d"
+
     args = [
-      rebase_path("${invoker.source}"),
-      rebase_path("${invoker.output}"),
-      rebase_path(depfile),
+      rebase_path(invoker.source, root_build_dir),
+      rebase_path(invoker.output, root_build_dir),
+      rebase_path(depfile, root_build_dir),
     ]
+
     outputs = [
-      "${invoker.output}",
+      invoker.output,
     ]
   }
 }