Merge "Populate individual classpath_fragments' classpaths.proto configs."
diff --git a/android/module.go b/android/module.go
index 69572dd..f745a4a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -165,13 +165,20 @@
 	// OtherModuleDependencyVariantExists returns true if a module with the
 	// specified name and variant exists. The variant must match the given
 	// variations. It must also match all the non-local variations of the current
-	// module. In other words, it checks for the module AddVariationDependencies
+	// module. In other words, it checks for the module that AddVariationDependencies
 	// would add a dependency on with the same arguments.
 	OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
 
+	// OtherModuleFarDependencyVariantExists returns true if a module with the
+	// specified name and variant exists. The variant must match the given
+	// variations, but not the non-local variations of the current module. In
+	// other words, it checks for the module that AddFarVariationDependencies
+	// would add a dependency on with the same arguments.
+	OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
+
 	// OtherModuleReverseDependencyVariantExists returns true if a module with the
 	// specified name exists with the same variations as the current module. In
-	// other words, it checks for the module AddReverseDependency would add a
+	// other words, it checks for the module that AddReverseDependency would add a
 	// dependency on with the same argument.
 	OtherModuleReverseDependencyVariantExists(name string) bool
 
@@ -2022,6 +2029,9 @@
 func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
 	return b.bp.OtherModuleDependencyVariantExists(variations, name)
 }
+func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
+	return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
+}
 func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
 	return b.bp.OtherModuleReverseDependencyVariantExists(name)
 }
diff --git a/android/paths.go b/android/paths.go
index 88d625a..b192a35 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -2001,6 +2001,9 @@
 	}
 }
 
+// absolutePath is deliberately private so that Soong's Go plugins can't use it to find and
+// read arbitrary files without going through the methods in the current package that track
+// dependencies.
 func absolutePath(path string) string {
 	if filepath.IsAbs(path) {
 		return path
diff --git a/build_kzip.bash b/build_kzip.bash
index a09335e..5655067 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -6,6 +6,8 @@
 # The following environment variables affect the result:
 #   BUILD_NUMBER          build number, used to generate unique ID (will use UUID if not set)
 #   SUPERPROJECT_SHA      superproject sha, used to generate unique id (will use BUILD_NUMBER if not set)
+#   SUPERPROJECT_REVISION superproject revision, used for unique id if defined as a sha
+#   KZIP_NAME             name of the output file (will use SUPERPROJECT_REVISION|SUPERPROJECT_SHA|BUILD_NUMBER|UUID if not set)
 #   DIST_DIR              where the resulting all.kzip will be placed
 #   KYTHE_KZIP_ENCODING   proto or json (proto is default)
 #   KYTHE_JAVA_SOURCE_BATCH_SIZE maximum number of the Java source files in a compilation unit
@@ -14,8 +16,16 @@
 #   TARGET_PRODUCT        target device name, e.g., 'aosp_blueline'
 #   XREF_CORPUS           source code repository URI, e.g., 'android.googlesource.com/platform/superproject'
 
-: ${BUILD_NUMBER:=$(uuidgen)}
-: ${SUPERPROJECT_SHA:=$BUILD_NUMBER}
+# If the SUPERPROJECT_REVISION is defined as a sha, use this as the default value if no
+# SUPERPROJECT_SHA is specified.
+if [[ ${SUPERPROJECT_REVISION:-} =~ [0-9a-f]{40} ]]; then
+  : ${KZIP_NAME:=${SUPERPROJECT_REVISION:-}}
+fi
+
+: ${KZIP_NAME:=${SUPERPROJECT_SHA:-}}
+: ${KZIP_NAME:=${BUILD_NUMBER:-}}
+: ${KZIP_NAME:=$(uuidgen)}
+
 : ${KYTHE_JAVA_SOURCE_BATCH_SIZE:=500}
 : ${KYTHE_KZIP_ENCODING:=proto}
 : ${XREF_CORPUS:?should be set}
@@ -50,6 +60,6 @@
 
 # Pack
 # TODO(asmundak): this should be done by soong.
-declare -r allkzip="$SUPERPROJECT_SHA.kzip"
+declare -r allkzip="$KZIP_NAME.kzip"
 "$out/soong/host/linux-x86/bin/merge_zips" "$DIST_DIR/$allkzip" @<(find "$out" -name '*.kzip')
 
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index a402f8f..439084e 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -163,56 +163,49 @@
 )
 
 const (
+	name          = "arm"
 	armGccVersion = "4.9"
+	gccTriple     = "arm-linux-androideabi"
+	clangTriple   = "armv7a-linux-androideabi"
 )
 
 func init() {
 	pctx.StaticVariable("armGccVersion", armGccVersion)
 
-	pctx.SourcePathVariable("ArmGccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
+	pctx.SourcePathVariable("ArmGccRoot", "prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
 
-	pctx.StaticVariable("ArmLdflags", strings.Join(armLdflags, " "))
-	pctx.StaticVariable("ArmLldflags", strings.Join(armLldflags, " "))
+	// Just exported. Not created as a Ninja static variable.
+	exportedStringVars.Set("ArmClangTriple", clangTriple)
+
+	exportStringListStaticVariable("ArmLdflags", armLdflags)
+	exportStringListStaticVariable("ArmLldflags", armLldflags)
 
 	// Clang cflags
-	pctx.StaticVariable("ArmToolchainClangCflags", strings.Join(ClangFilterUnknownCflags(armToolchainCflags), " "))
-	pctx.StaticVariable("ArmClangCflags", strings.Join(ClangFilterUnknownCflags(armCflags), " "))
-	pctx.StaticVariable("ArmClangLdflags", strings.Join(ClangFilterUnknownCflags(armLdflags), " "))
-	pctx.StaticVariable("ArmClangLldflags", strings.Join(ClangFilterUnknownCflags(armLldflags), " "))
-	pctx.StaticVariable("ArmClangCppflags", strings.Join(ClangFilterUnknownCflags(armCppflags), " "))
+	exportStringListStaticVariable("ArmToolchainClangCflags", ClangFilterUnknownCflags(armToolchainCflags))
+	exportStringListStaticVariable("ArmClangCflags", ClangFilterUnknownCflags(armCflags))
+	exportStringListStaticVariable("ArmClangLdflags", ClangFilterUnknownCflags(armLdflags))
+	exportStringListStaticVariable("ArmClangLldflags", ClangFilterUnknownCflags(armLldflags))
+	exportStringListStaticVariable("ArmClangCppflags", ClangFilterUnknownCflags(armCppflags))
 
 	// Clang ARM vs. Thumb instruction set cflags
-	pctx.StaticVariable("ArmClangArmCflags", strings.Join(ClangFilterUnknownCflags(armArmCflags), " "))
-	pctx.StaticVariable("ArmClangThumbCflags", strings.Join(ClangFilterUnknownCflags(armThumbCflags), " "))
+	exportStringListStaticVariable("ArmClangArmCflags", ClangFilterUnknownCflags(armArmCflags))
+	exportStringListStaticVariable("ArmClangThumbCflags", ClangFilterUnknownCflags(armThumbCflags))
 
 	// Clang arch variant cflags
-	pctx.StaticVariable("ArmClangArmv7ACflags",
-		strings.Join(armClangArchVariantCflags["armv7-a"], " "))
-	pctx.StaticVariable("ArmClangArmv7ANeonCflags",
-		strings.Join(armClangArchVariantCflags["armv7-a-neon"], " "))
-	pctx.StaticVariable("ArmClangArmv8ACflags",
-		strings.Join(armClangArchVariantCflags["armv8-a"], " "))
-	pctx.StaticVariable("ArmClangArmv82ACflags",
-		strings.Join(armClangArchVariantCflags["armv8-2a"], " "))
+	exportStringListStaticVariable("ArmClangArmv7ACflags", armClangArchVariantCflags["armv7-a"])
+	exportStringListStaticVariable("ArmClangArmv7ANeonCflags", armClangArchVariantCflags["armv7-a-neon"])
+	exportStringListStaticVariable("ArmClangArmv8ACflags", armClangArchVariantCflags["armv8-a"])
+	exportStringListStaticVariable("ArmClangArmv82ACflags", armClangArchVariantCflags["armv8-2a"])
 
 	// Clang cpu variant cflags
-	pctx.StaticVariable("ArmClangGenericCflags",
-		strings.Join(armClangCpuVariantCflags[""], " "))
-	pctx.StaticVariable("ArmClangCortexA7Cflags",
-		strings.Join(armClangCpuVariantCflags["cortex-a7"], " "))
-	pctx.StaticVariable("ArmClangCortexA8Cflags",
-		strings.Join(armClangCpuVariantCflags["cortex-a8"], " "))
-	pctx.StaticVariable("ArmClangCortexA15Cflags",
-		strings.Join(armClangCpuVariantCflags["cortex-a15"], " "))
-	pctx.StaticVariable("ArmClangCortexA53Cflags",
-		strings.Join(armClangCpuVariantCflags["cortex-a53"], " "))
-	pctx.StaticVariable("ArmClangCortexA55Cflags",
-		strings.Join(armClangCpuVariantCflags["cortex-a55"], " "))
-	pctx.StaticVariable("ArmClangKraitCflags",
-		strings.Join(armClangCpuVariantCflags["krait"], " "))
-	pctx.StaticVariable("ArmClangKryoCflags",
-		strings.Join(armClangCpuVariantCflags["kryo"], " "))
+	exportStringListStaticVariable("ArmClangGenericCflags", armClangCpuVariantCflags[""])
+	exportStringListStaticVariable("ArmClangCortexA7Cflags", armClangCpuVariantCflags["cortex-a7"])
+	exportStringListStaticVariable("ArmClangCortexA8Cflags", armClangCpuVariantCflags["cortex-a8"])
+	exportStringListStaticVariable("ArmClangCortexA15Cflags", armClangCpuVariantCflags["cortex-a15"])
+	exportStringListStaticVariable("ArmClangCortexA53Cflags", armClangCpuVariantCflags["cortex-a53"])
+	exportStringListStaticVariable("ArmClangCortexA55Cflags", armClangCpuVariantCflags["cortex-a55"])
+	exportStringListStaticVariable("ArmClangKraitCflags", armClangCpuVariantCflags["krait"])
+	exportStringListStaticVariable("ArmClangKryoCflags", armClangCpuVariantCflags["kryo"])
 }
 
 var (
@@ -251,7 +244,7 @@
 }
 
 func (t *toolchainArm) Name() string {
-	return "arm"
+	return name
 }
 
 func (t *toolchainArm) GccRoot() string {
@@ -259,7 +252,7 @@
 }
 
 func (t *toolchainArm) GccTriple() string {
-	return "arm-linux-androideabi"
+	return gccTriple
 }
 
 func (t *toolchainArm) GccVersion() string {
@@ -272,7 +265,7 @@
 
 func (t *toolchainArm) ClangTriple() string {
 	// http://b/72619014 work around llvm LTO bug.
-	return "armv7a-linux-androideabi"
+	return clangTriple
 }
 
 func (t *toolchainArm) ndkTriple() string {
@@ -312,7 +305,7 @@
 }
 
 func (toolchainArm) LibclangRuntimeLibraryArch() string {
-	return "arm"
+	return name
 }
 
 func armToolchainFactory(arch android.Arch) Toolchain {
diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go
index 16892e6..19571f1 100644
--- a/cc/config/bp2build.go
+++ b/cc/config/bp2build.go
@@ -22,29 +22,34 @@
 )
 
 // Helpers for exporting cc configuration information to Bazel.
-
 var (
 	// Map containing toolchain variables that are independent of the
 	// environment variables of the build.
-	exportedVars = exportedVariablesMap{}
+	exportedStringListVars = exportedStringListVariables{}
+	exportedStringVars     = exportedStringVariables{}
 )
 
-// variableValue is a string slice because the exported variables are all lists
-// of string, and it's simpler to manipulate string lists before joining them
-// into their final string representation.
-type variableValue []string
+type exportedStringVariables map[string]string
+type exportedStringListVariables map[string][]string
 
-// envDependentVariable is a toolchain variable computed based on an environment variable.
-type exportedVariablesMap map[string]variableValue
-
-func (m exportedVariablesMap) Set(k string, v variableValue) {
+func (m exportedStringVariables) Set(k string, v string) {
 	m[k] = v
 }
 
 // Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
-func staticVariableExportedToBazel(name string, value []string) {
+func exportStringStaticVariable(name string, value string) {
+	pctx.StaticVariable(name, value)
+	exportedStringVars.Set(name, value)
+}
+
+func (m exportedStringListVariables) Set(k string, v []string) {
+	m[k] = v
+}
+
+// Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
+func exportStringListStaticVariable(name string, value []string) {
 	pctx.StaticVariable(name, strings.Join(value, " "))
-	exportedVars.Set(name, variableValue(value))
+	exportedStringListVars.Set(name, value)
 }
 
 // BazelCcToolchainVars generates bzl file content containing variables for
@@ -64,12 +69,12 @@
 
 	// For each exported variable, recursively expand elements in the variableValue
 	// list to ensure that interpolated variables are expanded according to their values
-	// in the exportedVars scope.
-	for _, k := range android.SortedStringKeys(exportedVars) {
-		variableValue := exportedVars[k]
+	// in the variable scope.
+	for _, k := range android.SortedStringKeys(exportedStringListVars) {
+		variableValue := exportedStringListVars[k]
 		var expandedVars []string
 		for _, v := range variableValue {
-			expandedVars = append(expandedVars, expandVar(v, exportedVars)...)
+			expandedVars = append(expandedVars, expandVar(v, exportedStringVars, exportedStringListVars)...)
 		}
 		// Build the list for this variable.
 		list := "["
@@ -83,9 +88,22 @@
 		ret += "\n"
 	}
 
+	for _, k := range android.SortedStringKeys(exportedStringVars) {
+		variableValue := exportedStringVars[k]
+		expandedVar := expandVar(variableValue, exportedStringVars, exportedStringListVars)
+		if len(expandedVar) > 1 {
+			panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
+		}
+		ret += fmt.Sprintf("_%s = \"%s\"\n", k, validateCharacters(expandedVar[0]))
+		ret += "\n"
+	}
+
 	// Build the exported constants struct.
 	ret += "constants = struct(\n"
-	for _, k := range android.SortedStringKeys(exportedVars) {
+	for _, k := range android.SortedStringKeys(exportedStringVars) {
+		ret += fmt.Sprintf("    %s = _%s,\n", k, k)
+	}
+	for _, k := range android.SortedStringKeys(exportedStringListVars) {
 		ret += fmt.Sprintf("    %s = _%s,\n", k, k)
 	}
 	ret += ")"
@@ -99,7 +117,7 @@
 // string slice than to handle a pass-by-referenced map, which would make it
 // quite complex to track depth-first interpolations. It's also unlikely the
 // interpolation stacks are deep (n > 1).
-func expandVar(toExpand string, exportedVars map[string]variableValue) []string {
+func expandVar(toExpand string, stringScope exportedStringVariables, stringListScope exportedStringListVariables) []string {
 	// e.g. "${ClangExternalCflags}"
 	r := regexp.MustCompile(`\${([a-zA-Z0-9_]+)}`)
 
@@ -136,8 +154,11 @@
 				newSeenVars[k] = true
 			}
 			newSeenVars[variable] = true
-			unexpandedVars := exportedVars[variable]
-			for _, unexpandedVar := range unexpandedVars {
+			if unexpandedVars, ok := stringListScope[variable]; ok {
+				for _, unexpandedVar := range unexpandedVars {
+					ret = append(ret, expandVarInternal(unexpandedVar, newSeenVars)...)
+				}
+			} else if unexpandedVar, ok := stringScope[variable]; ok {
 				ret = append(ret, expandVarInternal(unexpandedVar, newSeenVars)...)
 			}
 		}
diff --git a/cc/config/bp2build_test.go b/cc/config/bp2build_test.go
index 7744b4b..a4745e6 100644
--- a/cc/config/bp2build_test.go
+++ b/cc/config/bp2build_test.go
@@ -20,54 +20,80 @@
 
 func TestExpandVars(t *testing.T) {
 	testCases := []struct {
-		description    string
-		exportedVars   map[string]variableValue
-		toExpand       string
-		expectedValues []string
+		description     string
+		stringScope     exportedStringVariables
+		stringListScope exportedStringListVariables
+		toExpand        string
+		expectedValues  []string
 	}{
 		{
-			description: "single level expansion",
-			exportedVars: map[string]variableValue{
-				"foo": variableValue([]string{"bar"}),
+			description:    "no expansion for non-interpolated value",
+			toExpand:       "foo",
+			expectedValues: []string{"foo"},
+		},
+		{
+			description: "single level expansion for string var",
+			stringScope: exportedStringVariables{
+				"foo": "bar",
 			},
 			toExpand:       "${foo}",
 			expectedValues: []string{"bar"},
 		},
 		{
+			description: "single level expansion string list var",
+			stringListScope: exportedStringListVariables{
+				"foo": []string{"bar"},
+			},
+			toExpand:       "${foo}",
+			expectedValues: []string{"bar"},
+		},
+		{
+			description: "mixed level expansion for string list var",
+			stringScope: exportedStringVariables{
+				"foo": "${bar}",
+				"qux": "hello",
+			},
+			stringListScope: exportedStringListVariables{
+				"bar": []string{"baz", "${qux}"},
+			},
+			toExpand:       "${foo}",
+			expectedValues: []string{"baz", "hello"},
+		},
+		{
 			description: "double level expansion",
-			exportedVars: map[string]variableValue{
-				"foo": variableValue([]string{"${bar}"}),
-				"bar": variableValue([]string{"baz"}),
+			stringListScope: exportedStringListVariables{
+				"foo": []string{"${bar}"},
+				"bar": []string{"baz"},
 			},
 			toExpand:       "${foo}",
 			expectedValues: []string{"baz"},
 		},
 		{
 			description: "double level expansion with a literal",
-			exportedVars: map[string]variableValue{
-				"a": variableValue([]string{"${b}", "c"}),
-				"b": variableValue([]string{"d"}),
+			stringListScope: exportedStringListVariables{
+				"a": []string{"${b}", "c"},
+				"b": []string{"d"},
 			},
 			toExpand:       "${a}",
 			expectedValues: []string{"d", "c"},
 		},
 		{
 			description: "double level expansion, with two variables in a string",
-			exportedVars: map[string]variableValue{
-				"a": variableValue([]string{"${b} ${c}"}),
-				"b": variableValue([]string{"d"}),
-				"c": variableValue([]string{"e"}),
+			stringListScope: exportedStringListVariables{
+				"a": []string{"${b} ${c}"},
+				"b": []string{"d"},
+				"c": []string{"e"},
 			},
 			toExpand:       "${a}",
 			expectedValues: []string{"d", "e"},
 		},
 		{
 			description: "triple level expansion with two variables in a string",
-			exportedVars: map[string]variableValue{
-				"a": variableValue([]string{"${b} ${c}"}),
-				"b": variableValue([]string{"${c}", "${d}"}),
-				"c": variableValue([]string{"${d}"}),
-				"d": variableValue([]string{"foo"}),
+			stringListScope: exportedStringListVariables{
+				"a": []string{"${b} ${c}"},
+				"b": []string{"${c}", "${d}"},
+				"c": []string{"${d}"},
+				"d": []string{"foo"},
 			},
 			toExpand:       "${a}",
 			expectedValues: []string{"foo", "foo", "foo"},
@@ -76,7 +102,7 @@
 
 	for _, testCase := range testCases {
 		t.Run(testCase.description, func(t *testing.T) {
-			output := expandVar(testCase.toExpand, testCase.exportedVars)
+			output := expandVar(testCase.toExpand, testCase.stringScope, testCase.stringListScope)
 			if len(output) != len(testCase.expectedValues) {
 				t.Errorf("Expected %d values, got %d", len(testCase.expectedValues), len(output))
 			}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 4fbb9c3..c484fc9 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -98,7 +98,7 @@
 }
 
 func init() {
-	staticVariableExportedToBazel("ClangExtraCflags", []string{
+	exportStringListStaticVariable("ClangExtraCflags", []string{
 		"-D__compiler_offsetof=__builtin_offsetof",
 
 		// Emit address-significance table which allows linker to perform safe ICF. Clang does
@@ -153,7 +153,7 @@
 		"-D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__",
 	})
 
-	staticVariableExportedToBazel("ClangExtraCppflags", []string{
+	exportStringListStaticVariable("ClangExtraCppflags", []string{
 		// -Wimplicit-fallthrough is not enabled by -Wall.
 		"-Wimplicit-fallthrough",
 
@@ -164,9 +164,9 @@
 		"-Wno-gnu-include-next",
 	})
 
-	staticVariableExportedToBazel("ClangExtraTargetCflags", []string{"-nostdlibinc"})
+	exportStringListStaticVariable("ClangExtraTargetCflags", []string{"-nostdlibinc"})
 
-	staticVariableExportedToBazel("ClangExtraNoOverrideCflags", []string{
+	exportStringListStaticVariable("ClangExtraNoOverrideCflags", []string{
 		"-Werror=address-of-temporary",
 		// Bug: http://b/29823425 Disable -Wnull-dereference until the
 		// new cases detected by this warning in Clang r271374 are
@@ -205,7 +205,7 @@
 
 	// Extra cflags for external third-party projects to disable warnings that
 	// are infeasible to fix in all the external projects and their upstream repos.
-	staticVariableExportedToBazel("ClangExtraExternalCflags", []string{
+	exportStringListStaticVariable("ClangExtraExternalCflags", []string{
 		"-Wno-enum-compare",
 		"-Wno-enum-compare-switch",
 
diff --git a/cc/config/global.go b/cc/config/global.go
index d6eba0f..d458311 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -165,13 +165,13 @@
 		commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
 	}
 
-	staticVariableExportedToBazel("CommonGlobalConlyflags", commonGlobalConlyflags)
-	staticVariableExportedToBazel("DeviceGlobalCppflags", deviceGlobalCppflags)
-	staticVariableExportedToBazel("DeviceGlobalLdflags", deviceGlobalLdflags)
-	staticVariableExportedToBazel("DeviceGlobalLldflags", deviceGlobalLldflags)
-	staticVariableExportedToBazel("HostGlobalCppflags", hostGlobalCppflags)
-	staticVariableExportedToBazel("HostGlobalLdflags", hostGlobalLdflags)
-	staticVariableExportedToBazel("HostGlobalLldflags", hostGlobalLldflags)
+	exportStringListStaticVariable("CommonGlobalConlyflags", commonGlobalConlyflags)
+	exportStringListStaticVariable("DeviceGlobalCppflags", deviceGlobalCppflags)
+	exportStringListStaticVariable("DeviceGlobalLdflags", deviceGlobalLdflags)
+	exportStringListStaticVariable("DeviceGlobalLldflags", deviceGlobalLldflags)
+	exportStringListStaticVariable("HostGlobalCppflags", hostGlobalCppflags)
+	exportStringListStaticVariable("HostGlobalLdflags", hostGlobalLdflags)
+	exportStringListStaticVariable("HostGlobalLldflags", hostGlobalLldflags)
 
 	// Export the static default CommonClangGlobalCflags to Bazel.
 	// TODO(187086342): handle cflags that are set in VariableFuncs.
@@ -183,7 +183,7 @@
 			"-ftrivial-auto-var-init=zero",
 			"-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang",
 		}...)
-	exportedVars.Set("CommonClangGlobalCflags", variableValue(commonClangGlobalCFlags))
+	exportedStringListVars.Set("CommonClangGlobalCflags", commonClangGlobalCFlags)
 
 	pctx.VariableFunc("CommonClangGlobalCflags", func(ctx android.PackageVarContext) string {
 		flags := ClangFilterUnknownCflags(commonGlobalCflags)
@@ -208,7 +208,7 @@
 	// Export the static default DeviceClangGlobalCflags to Bazel.
 	// TODO(187086342): handle cflags that are set in VariableFuncs.
 	deviceClangGlobalCflags := append(ClangFilterUnknownCflags(deviceGlobalCflags), "${ClangExtraTargetCflags}")
-	exportedVars.Set("DeviceClangGlobalCflags", variableValue(deviceClangGlobalCflags))
+	exportedStringListVars.Set("DeviceClangGlobalCflags", deviceClangGlobalCflags)
 
 	pctx.VariableFunc("DeviceClangGlobalCflags", func(ctx android.PackageVarContext) string {
 		if ctx.Config().Fuchsia() {
@@ -218,10 +218,10 @@
 		}
 	})
 
-	staticVariableExportedToBazel("HostClangGlobalCflags", ClangFilterUnknownCflags(hostGlobalCflags))
-	staticVariableExportedToBazel("NoOverrideClangGlobalCflags", append(ClangFilterUnknownCflags(noOverrideGlobalCflags), "${ClangExtraNoOverrideCflags}"))
-	staticVariableExportedToBazel("CommonClangGlobalCppflags", append(ClangFilterUnknownCflags(commonGlobalCppflags), "${ClangExtraCppflags}"))
-	staticVariableExportedToBazel("ClangExternalCflags", []string{"${ClangExtraExternalCflags}"})
+	exportStringListStaticVariable("HostClangGlobalCflags", ClangFilterUnknownCflags(hostGlobalCflags))
+	exportStringListStaticVariable("NoOverrideClangGlobalCflags", append(ClangFilterUnknownCflags(noOverrideGlobalCflags), "${ClangExtraNoOverrideCflags}"))
+	exportStringListStaticVariable("CommonClangGlobalCppflags", append(ClangFilterUnknownCflags(commonGlobalCppflags), "${ClangExtraCppflags}"))
+	exportStringListStaticVariable("ClangExternalCflags", []string{"${ClangExtraExternalCflags}"})
 
 	// Everything in these lists is a crime against abstraction and dependency tracking.
 	// Do not add anything to this list.
@@ -236,7 +236,7 @@
 		"frameworks/native/opengl/include",
 		"frameworks/av/include",
 	}
-	exportedVars.Set("CommonGlobalIncludes", commonGlobalIncludes)
+	exportedStringListVars.Set("CommonGlobalIncludes", commonGlobalIncludes)
 	pctx.PrefixedExistentPathsForSourcesVariable("CommonGlobalIncludes", "-I", commonGlobalIncludes)
 
 	pctx.SourcePathVariable("ClangDefaultBase", ClangDefaultBase)
diff --git a/cc/image.go b/cc/image.go
index 5d41717..47a424b 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -430,6 +430,16 @@
 	recoverySnapshotVersion := mctx.DeviceConfig().RecoverySnapshotVersion()
 	usingRecoverySnapshot := recoverySnapshotVersion != "current" &&
 		recoverySnapshotVersion != ""
+	needVndkVersionVendorVariantForLlndk := false
+	if boardVndkVersion != "" {
+		boardVndkApiLevel, err := android.ApiLevelFromUser(mctx, boardVndkVersion)
+		if err == nil && !boardVndkApiLevel.IsPreview() {
+			// VNDK snapshot newer than v30 has LLNDK stub libraries.
+			// Only the VNDK version less than or equal to v30 requires generating the vendor
+			// variant of the VNDK version from the source tree.
+			needVndkVersionVendorVariantForLlndk = boardVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, "30"))
+		}
+	}
 	if boardVndkVersion == "current" {
 		boardVndkVersion = platformVndkVersion
 	}
@@ -446,7 +456,9 @@
 			vendorVariants = append(vendorVariants, platformVndkVersion)
 			productVariants = append(productVariants, platformVndkVersion)
 		}
-		if boardVndkVersion != "" {
+		// Generate vendor variants for boardVndkVersion only if the VNDK snapshot does not
+		// provide the LLNDK stub libraries.
+		if needVndkVersionVendorVariantForLlndk {
 			vendorVariants = append(vendorVariants, boardVndkVersion)
 		}
 		if productVndkVersion != "" {
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 0b1147e..a7351a9 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -454,13 +454,30 @@
 }
 
 func (p *baseSnapshotDecorator) setSnapshotAndroidMkSuffix(ctx android.ModuleContext) {
-	if ctx.OtherModuleDependencyVariantExists([]blueprint.Variation{
-		{Mutator: "image", Variation: android.CoreVariation},
-	}, ctx.Module().(*Module).BaseModuleName()) {
+	coreVariations := append(ctx.Target().Variations(), blueprint.Variation{
+		Mutator:   "image",
+		Variation: android.CoreVariation})
+
+	if ctx.OtherModuleFarDependencyVariantExists(coreVariations, ctx.Module().(*Module).BaseModuleName()) {
 		p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
-	} else {
-		p.baseProperties.Androidmk_suffix = ""
+		return
 	}
+
+	// If there is no matching core variation, there could still be a
+	// product variation, for example if a module is product specific and
+	// vendor available. In that case, we also want to add the androidmk
+	// suffix.
+
+	productVariations := append(ctx.Target().Variations(), blueprint.Variation{
+		Mutator:   "image",
+		Variation: ProductVariationPrefix + ctx.DeviceConfig().PlatformVndkVersion()})
+
+	if ctx.OtherModuleFarDependencyVariantExists(productVariations, ctx.Module().(*Module).BaseModuleName()) {
+		p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
+		return
+	}
+
+	p.baseProperties.Androidmk_suffix = ""
 }
 
 // Call this with a module suffix after creating a snapshot module, such as
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index fddd72a..c3b5e8c 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -309,6 +309,13 @@
 		compile_multilib: "64",
 	}
 
+	cc_library {
+		name: "libllndk",
+		llndk: {
+			symbol_file: "libllndk.map.txt",
+		},
+	}
+
 	cc_binary {
 		name: "bin",
 		vendor: true,
@@ -332,7 +339,7 @@
 	vndkBp := `
 	vndk_prebuilt_shared {
 		name: "libvndk",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		vendor_available: true,
 		product_available: true,
@@ -376,7 +383,7 @@
 	// different arch snapshot which has to be ignored
 	vndk_prebuilt_shared {
 		name: "libvndk",
-		version: "30",
+		version: "31",
 		target_arch: "arm",
 		vendor_available: true,
 		product_available: true,
@@ -390,6 +397,22 @@
 			},
 		},
 	}
+
+	vndk_prebuilt_shared {
+		name: "libllndk",
+		version: "31",
+		target_arch: "arm64",
+		vendor_available: true,
+		product_available: true,
+		arch: {
+			arm64: {
+				srcs: ["libllndk.so"],
+			},
+			arm: {
+				srcs: ["libllndk.so"],
+			},
+		},
+	}
 `
 
 	vendorProprietaryBp := `
@@ -409,7 +432,7 @@
 		no_libcrt: true,
 		stl: "none",
 		system_shared_libs: [],
-		shared_libs: ["libvndk", "libvendor_available"],
+		shared_libs: ["libvndk", "libvendor_available", "libllndk"],
 		static_libs: ["libvendor", "libvendor_without_snapshot"],
 		arch: {
 			arm64: {
@@ -449,16 +472,17 @@
 
 	vendor_snapshot {
 		name: "vendor_snapshot",
-		version: "30",
+		version: "31",
 		arch: {
 			arm64: {
 				vndk_libs: [
 					"libvndk",
+					"libllndk",
 				],
 				static_libs: [
 					"libc++_static",
 					"libc++demangle",
-					"libgcc_stripped",
+					"libunwind",
 					"libvendor",
 					"libvendor_available",
 					"libvndk",
@@ -476,6 +500,7 @@
 			arm: {
 				vndk_libs: [
 					"libvndk",
+					"libllndk",
 				],
 				static_libs: [
 					"libvendor",
@@ -497,7 +522,7 @@
 
 	vendor_snapshot_static {
 		name: "libvndk",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "both",
 		vendor: true,
@@ -515,7 +540,7 @@
 
 	vendor_snapshot_shared {
 		name: "libvendor",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "both",
 		vendor: true,
@@ -538,7 +563,7 @@
 
 	vendor_snapshot_static {
 		name: "lib32",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "32",
 		vendor: true,
@@ -551,7 +576,7 @@
 
 	vendor_snapshot_shared {
 		name: "lib32",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "32",
 		vendor: true,
@@ -564,7 +589,7 @@
 
 	vendor_snapshot_static {
 		name: "lib64",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "64",
 		vendor: true,
@@ -577,7 +602,7 @@
 
 	vendor_snapshot_shared {
 		name: "lib64",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "64",
 		vendor: true,
@@ -590,7 +615,7 @@
 
 	vendor_snapshot_static {
 		name: "libvendor",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "both",
 		vendor: true,
@@ -616,7 +641,7 @@
 
 	vendor_snapshot_shared {
 		name: "libvendor_available",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "both",
 		vendor: true,
@@ -634,7 +659,7 @@
 
 	vendor_snapshot_static {
 		name: "libvendor_available",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "both",
 		vendor: true,
@@ -652,7 +677,7 @@
 
 	vendor_snapshot_static {
 		name: "libc++_static",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "64",
 		vendor: true,
@@ -665,7 +690,7 @@
 
 	vendor_snapshot_static {
 		name: "libc++demangle",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "64",
 		vendor: true,
@@ -677,21 +702,21 @@
 	}
 
 	vendor_snapshot_static {
-		name: "libgcc_stripped",
-		version: "30",
+		name: "libunwind",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "64",
 		vendor: true,
 		arch: {
 			arm64: {
-				src: "libgcc_stripped.a",
+				src: "libunwind.a",
 			},
 		},
 	}
 
 	vendor_snapshot_binary {
 		name: "bin",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "64",
 		vendor: true,
@@ -704,7 +729,7 @@
 
 	vendor_snapshot_binary {
 		name: "bin32",
-		version: "30",
+		version: "31",
 		target_arch: "arm64",
 		compile_multilib: "32",
 		vendor: true,
@@ -732,7 +757,7 @@
 	// different arch snapshot which has to be ignored
 	vendor_snapshot_binary {
 		name: "bin",
-		version: "30",
+		version: "31",
 		target_arch: "arm",
 		compile_multilib: "first",
 		vendor: true,
@@ -759,7 +784,7 @@
 		"vendor/include/libvendor_cfi/c.h": nil,
 		"vendor/libc++_static.a":           nil,
 		"vendor/libc++demangle.a":          nil,
-		"vendor/libgcc_striped.a":          nil,
+		"vendor/libunwind.a":               nil,
 		"vendor/libvndk.a":                 nil,
 		"vendor/libvendor.a":               nil,
 		"vendor/libvendor.cfi.a":           nil,
@@ -771,11 +796,12 @@
 		"vndk/Android.bp":                  []byte(vndkBp),
 		"vndk/include/libvndk/a.h":         nil,
 		"vndk/libvndk.so":                  nil,
+		"vndk/libllndk.so":                 nil,
 	}
 
 	config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("30")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("31")
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("31")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("32")
 	ctx := CreateTestContext(config)
 	ctx.Register()
 
@@ -784,17 +810,17 @@
 	_, errs = ctx.PrepareBuildActions(config)
 	android.FailIfErrored(t, errs)
 
-	sharedVariant := "android_vendor.30_arm64_armv8-a_shared"
-	staticVariant := "android_vendor.30_arm64_armv8-a_static"
-	binaryVariant := "android_vendor.30_arm64_armv8-a"
+	sharedVariant := "android_vendor.31_arm64_armv8-a_shared"
+	staticVariant := "android_vendor.31_arm64_armv8-a_static"
+	binaryVariant := "android_vendor.31_arm64_armv8-a"
 
-	sharedCfiVariant := "android_vendor.30_arm64_armv8-a_shared_cfi"
-	staticCfiVariant := "android_vendor.30_arm64_armv8-a_static_cfi"
+	sharedCfiVariant := "android_vendor.31_arm64_armv8-a_shared_cfi"
+	staticCfiVariant := "android_vendor.31_arm64_armv8-a_static_cfi"
 
-	shared32Variant := "android_vendor.30_arm_armv7-a-neon_shared"
-	binary32Variant := "android_vendor.30_arm_armv7-a-neon"
+	shared32Variant := "android_vendor.31_arm_armv7-a-neon_shared"
+	binary32Variant := "android_vendor.31_arm_armv7-a-neon"
 
-	// libclient uses libvndk.vndk.30.arm64, libvendor.vendor_static.30.arm64, libvendor_without_snapshot
+	// libclient uses libvndk.vndk.31.arm64, libvendor.vendor_static.31.arm64, libvendor_without_snapshot
 	libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"]
 	for _, includeFlags := range []string{
 		"-Ivndk/include/libvndk",     // libvndk
@@ -808,8 +834,9 @@
 
 	libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"]
 	for _, input := range [][]string{
-		[]string{sharedVariant, "libvndk.vndk.30.arm64"},
-		[]string{staticVariant, "libvendor.vendor_static.30.arm64"},
+		[]string{sharedVariant, "libvndk.vndk.31.arm64"},
+		[]string{sharedVariant, "libllndk.vndk.31.arm64"},
+		[]string{staticVariant, "libvendor.vendor_static.31.arm64"},
 		[]string{staticVariant, "libvendor_without_snapshot"},
 	} {
 		outputPaths := getOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
@@ -819,7 +846,7 @@
 	}
 
 	libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs
-	if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib64"}; !reflect.DeepEqual(g, w) {
+	if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib64"}; !reflect.DeepEqual(g, w) {
 		t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
 	}
 
@@ -829,11 +856,11 @@
 	}
 
 	libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs
-	if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib32"}; !reflect.DeepEqual(g, w) {
+	if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib32"}; !reflect.DeepEqual(g, w) {
 		t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g)
 	}
 
-	// libclient_cfi uses libvendor.vendor_static.30.arm64's cfi variant
+	// libclient_cfi uses libvendor.vendor_static.31.arm64's cfi variant
 	libclientCfiCcFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("cc").Args["cFlags"]
 	if !strings.Contains(libclientCfiCcFlags, "-Ivendor/include/libvendor_cfi") {
 		t.Errorf("flags for libclient_cfi must contain %#v, but was %#v.",
@@ -841,12 +868,12 @@
 	}
 
 	libclientCfiLdFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("ld").Args["libFlags"]
-	libvendorCfiOutputPaths := getOutputPaths(ctx, staticCfiVariant, []string{"libvendor.vendor_static.30.arm64"})
+	libvendorCfiOutputPaths := getOutputPaths(ctx, staticCfiVariant, []string{"libvendor.vendor_static.31.arm64"})
 	if !strings.Contains(libclientCfiLdFlags, libvendorCfiOutputPaths[0].String()) {
 		t.Errorf("libflags for libclientCfi must contain %#v, but was %#v", libvendorCfiOutputPaths[0], libclientCfiLdFlags)
 	}
 
-	// bin_without_snapshot uses libvndk.vendor_static.30.arm64 (which reexports vndk's exported headers)
+	// bin_without_snapshot uses libvndk.vendor_static.31.arm64 (which reexports vndk's exported headers)
 	binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"]
 	if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivndk/include/libvndk") {
 		t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.",
@@ -854,37 +881,37 @@
 	}
 
 	binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"]
-	libVndkStaticOutputPaths := getOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.30.arm64"})
+	libVndkStaticOutputPaths := getOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.31.arm64"})
 	if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
 		t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
 			libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
 	}
 
-	// libvendor.so is installed by libvendor.vendor_shared.30.arm64
-	ctx.ModuleForTests("libvendor.vendor_shared.30.arm64", sharedVariant).Output("libvendor.so")
+	// libvendor.so is installed by libvendor.vendor_shared.31.arm64
+	ctx.ModuleForTests("libvendor.vendor_shared.31.arm64", sharedVariant).Output("libvendor.so")
 
-	// lib64.so is installed by lib64.vendor_shared.30.arm64
-	ctx.ModuleForTests("lib64.vendor_shared.30.arm64", sharedVariant).Output("lib64.so")
+	// lib64.so is installed by lib64.vendor_shared.31.arm64
+	ctx.ModuleForTests("lib64.vendor_shared.31.arm64", sharedVariant).Output("lib64.so")
 
-	// lib32.so is installed by lib32.vendor_shared.30.arm64
-	ctx.ModuleForTests("lib32.vendor_shared.30.arm64", shared32Variant).Output("lib32.so")
+	// lib32.so is installed by lib32.vendor_shared.31.arm64
+	ctx.ModuleForTests("lib32.vendor_shared.31.arm64", shared32Variant).Output("lib32.so")
 
-	// libvendor_available.so is installed by libvendor_available.vendor_shared.30.arm64
-	ctx.ModuleForTests("libvendor_available.vendor_shared.30.arm64", sharedVariant).Output("libvendor_available.so")
+	// libvendor_available.so is installed by libvendor_available.vendor_shared.31.arm64
+	ctx.ModuleForTests("libvendor_available.vendor_shared.31.arm64", sharedVariant).Output("libvendor_available.so")
 
 	// libvendor_without_snapshot.so is installed by libvendor_without_snapshot
 	ctx.ModuleForTests("libvendor_without_snapshot", sharedVariant).Output("libvendor_without_snapshot.so")
 
-	// bin is installed by bin.vendor_binary.30.arm64
-	ctx.ModuleForTests("bin.vendor_binary.30.arm64", binaryVariant).Output("bin")
+	// bin is installed by bin.vendor_binary.31.arm64
+	ctx.ModuleForTests("bin.vendor_binary.31.arm64", binaryVariant).Output("bin")
 
-	// bin32 is installed by bin32.vendor_binary.30.arm64
-	ctx.ModuleForTests("bin32.vendor_binary.30.arm64", binary32Variant).Output("bin32")
+	// bin32 is installed by bin32.vendor_binary.31.arm64
+	ctx.ModuleForTests("bin32.vendor_binary.31.arm64", binary32Variant).Output("bin32")
 
 	// bin_without_snapshot is installed by bin_without_snapshot
 	ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
 
-	// libvendor, libvendor_available and bin don't have vendor.30 variant
+	// libvendor, libvendor_available and bin don't have vendor.31 variant
 	libvendorVariants := ctx.ModuleVariantsForTests("libvendor")
 	if inList(sharedVariant, libvendorVariants) {
 		t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant)