Create a new kati packaging step; move dist

Instead of looking at `dist` and DIST_DIR directly in the Kati Build
step, always write out information about every call to dist, then create
the rules in another ckati run.

So instead of having:

  dist:    <goal> -> <dist> -> <output>
                \______________↑

  nodist:  <goal> -----------> <output>

Always use another phony target in the Kati Build step:

   <goal> ---> <output>
        \----> _dist_<goal>

Then in the packaging step (which is much faster), choose between dist
and no dist:

  dist:   _dist_<goal> -> <dist> -> <output>

  nodist: _dist_<goal>

Bug: 117463001
Test: m dist
Change-Id: Ic96bb6356740300dd3113f6ed699e6a619360c40
diff --git a/core/distdir.mk b/core/distdir.mk
index c074186..a2eabd2 100644
--- a/core/distdir.mk
+++ b/core/distdir.mk
@@ -17,52 +17,52 @@
 # When specifying "dist", the user has asked that we copy the important
 # files from this build into DIST_DIR.
 
-ifdef dist_goal
-
-# $(1): source file
-# $(2): destination file
-# $(3): goals that should copy the file
-#
-define copy-one-dist-file
-$(3): $(2)
-$(2): $(1)
-	@echo "Dist: $$@"
-	$$(copy-file-to-new-target-with-cp)
-endef
-
-# A global variable to remember all dist'ed src:dst pairs.
-# So if a src:dst is already dist'ed by another goal,
-# we should just establish the dependency and don't really call the
-# copy-one-dist-file to avoid multiple rules for the same target.
+# list of all goals that depend on any dist files
+_all_dist_goals :=
+# pairs of goal:distfile
+_all_dist_goal_output_pairs :=
+# pairs of srcfile:distfile
 _all_dist_src_dst_pairs :=
+
 # Other parts of the system should use this function to associate
 # certain files with certain goals.  When those goals are built
 # and "dist" is specified, the marked files will be copied to DIST_DIR.
 #
-# $(1): a list of goals  (e.g. droid, sdk, pdk, ndk)
+# $(1): a list of goals  (e.g. droid, sdk, pdk, ndk). These must be PHONY
 # $(2): the dist files to add to those goals.  If the file contains ':',
 #       the text following the colon is the name that the file is copied
 #       to under the dist directory.  Subdirs are ok, and will be created
 #       at copy time if necessary.
 define dist-for-goals
+$(eval _all_dist_goals += $$(1)) \
 $(foreach file,$(2), \
-  $(eval fw := $(subst :,$(space),$(file))) \
-  $(eval src := $(word 1,$(fw))) \
-  $(eval dst := $(word 2,$(fw))) \
-  $(eval dst := $(if $(dst),$(dst),$(notdir $(src)))) \
-  $(if $(filter $(_all_dist_src_dst_pairs),$(src):$(dst)),\
-    $(eval $(call add-dependency,$(1),$(DIST_DIR)/$(dst))),\
-    $(eval $(call copy-one-dist-file,\
-      $(src),$(DIST_DIR)/$(dst),$(1)))\
-      $(eval _all_dist_src_dst_pairs += $(src):$(dst))\
-  )\
-)
+  $(eval src := $(call word-colon,1,$(file))) \
+  $(eval dst := $(call word-colon,2,$(file))) \
+  $(if $(dst),,$(eval dst := $$(notdir $$(src)))) \
+  $(eval _all_dist_src_dst_pairs += $$(src):$$(dst)) \
+  $(foreach goal,$(1), \
+    $(eval _all_dist_goal_output_pairs += $$(goal):$$(dst))))
 endef
 
-else # !dist_goal
+#------------------------------------------------------------------
+# To be used at the end of the build to collect all the uses of
+# dist-for-goals, and write them into a file for the packaging step to use.
 
-# empty definition when not building dist
-define dist-for-goals
+# $(1): The file to write
+define dist-write-file
+$(strip \
+  $(KATI_obsolete_var dist-for-goals,Cannot be used after dist-write-file) \
+  $(foreach goal,$(sort $(_all_dist_goals)), \
+    $(eval $$(goal): _dist_$$(goal))) \
+  $(shell mkdir -p $(dir $(1))) \
+  $(file >$(1).tmp, \
+    DIST_GOAL_OUTPUT_PAIRS := $(sort $(_all_dist_goal_output_pairs)) \
+    $(newline)DIST_SRC_DST_PAIRS := $(sort $(_all_dist_src_dst_pairs))) \
+  $(shell if ! cmp -s $(1).tmp $(1); then \
+            mv $(1).tmp $(1); \
+          else \
+            rm $(1).tmp; \
+          fi))
 endef
 
-endif # !dist_goal
+.KATI_READONLY := dist-for-goals dist-write-file