Add support for single-value product variables

Prior to this change, all PRODUCT_* variables are inherited with
list semantics, meaning the variable value in the current makefile
as well as all the makefiles it inherits are concatenated together.

Many of these variables are not lists, so this change adds the
ability to classify a variable as a single-value variable, which
will inherit at most one value (the first one), unless the variable
is already defined in the current file.

This change also marks all current variables as list variables.
A future change will re-classify the single-value variables as such.

Bug: 116769560
Test: presubmit
Change-Id: I57719a5eefd0749e92c08b1773b6f929629267a3
diff --git a/core/node_fns.mk b/core/node_fns.mk
index ccfcc25..b81d60c 100644
--- a/core/node_fns.mk
+++ b/core/node_fns.mk
@@ -142,7 +142,8 @@
 #
 # $(1): context prefix
 # $(2): name of this node
-# $(3): list of variable names
+# $(3): list of node variable names
+# $(4): list of single value variable names (subset of $(3))
 #
 define _expand-inherited-values
   $(foreach v,$(3), \
@@ -154,15 +155,21 @@
             $(patsubst $(INHERIT_TAG)%,%, \
                 $(filter $(INHERIT_TAG)%, $($(_eiv_tv)) \
      )))) \
+    $(eval ### "Whether this variable should only take a single value") \
+    $(eval _eiv_sv := $(filter $(v),$(4))) \
     $(foreach i,$(_eiv_i), \
       $(eval ### "Make sure that this inherit appears only once") \
       $(eval $(_eiv_tv) := \
           $(call uniq-word,$($(_eiv_tv)),$(INHERIT_TAG)$(i))) \
+      $(eval ### "The expanded value, empty if we want a single value and have one") \
+      $(eval _eiv_ev := \
+        $(if $(and $(_eiv_sv),$(filter-out $(INHERIT_TAG)%,$($(_eiv_tv)))),,\
+          $($(1).$(i).$(v)) \
+        ) \
+      ) \
       $(eval ### "Expand the inherit tag") \
       $(eval $(_eiv_tv) := \
-          $(strip \
-              $(patsubst $(INHERIT_TAG)$(i),$($(1).$(i).$(v)), \
-                  $($(_eiv_tv))))) \
+          $(strip $(patsubst $(INHERIT_TAG)$(i),$(_eiv_ev),$($(_eiv_tv))))) \
       $(eval ### "Clear the child so DAGs don't create duplicate entries" ) \
       $(eval $(1).$(i).$(v) :=) \
       $(eval ### "If we just inherited ourselves, it's a cycle.") \
@@ -180,6 +187,7 @@
 # $(1): context prefix
 # $(2): makefile representing this node
 # $(3): list of node variable names
+# $(4): list of single value variable names (subset of $(3))
 #
 # _include_stack contains the list of included files, with the most recent files first.
 define _import-node
@@ -198,7 +206,7 @@
       $(call get-inherited-nodes,$(1).$(2),$(3)))
   $(call _import-nodes-inner,$(1),$($(1).$(2).inherited),$(3))
 
-  $(call _expand-inherited-values,$(1),$(2),$(3))
+  $(call _expand-inherited-values,$(1),$(2),$(3),$(4))
 
   $(eval $(1).$(2).inherited :=)
   $(eval _include_stack := $(wordlist 2,9999,$$(_include_stack)))
@@ -215,6 +223,7 @@
 # $(1): context prefix
 # $(2): list of makefiles representing nodes to import
 # $(3): list of node variable names
+# $(4): list of single value variable names (subset of $(3))
 #
 #TODO: Make the "does not exist" message more helpful;
 #      should print out the name of the file trying to include it.
@@ -225,7 +234,7 @@
         $(eval ### "skipping already-imported $(_in)") \
        , \
         $(eval $(1).$(_in).seen := true) \
-        $(call _import-node,$(1),$(strip $(_in)),$(3)) \
+        $(call _import-node,$(1),$(strip $(_in)),$(3),$(4)) \
        ) \
      , \
       $(error $(1): "$(_in)" does not exist) \
@@ -237,6 +246,8 @@
 # $(1): output list variable name, like "PRODUCTS" or "DEVICES"
 # $(2): list of makefiles representing nodes to import
 # $(3): list of node variable names
+# $(4): list with subset of variable names that take only a single value, instead
+#       of the default list semantics
 #
 define import-nodes
 $(if \
@@ -245,7 +256,7 @@
     $(if $(_include_stack),$(eval $(error ASSERTION FAILED: _include_stack \
                 should be empty here: $(_include_stack))),) \
     $(eval _include_stack := ) \
-    $(call _import-nodes-inner,$(_node_import_context),$(_in),$(3)) \
+    $(call _import-nodes-inner,$(_node_import_context),$(_in),$(3),$(4)) \
     $(call move-var-list,$(_node_import_context).$(_in),$(1).$(_in),$(3)) \
     $(eval _node_import_context :=) \
     $(eval $(1) := $($(1)) $(_in)) \