Add CFI product config variables to platform_mappings

Bug: 269577299
Fixes: 283130542
Test: b test --config=android //build/bazel/rules/cc/...
Change-Id: I2fc4094167c48b1f3b22bee6b7ada309278f7250
diff --git a/android/config.go b/android/config.go
index 9cfbc9e..2a243ee 100644
--- a/android/config.go
+++ b/android/config.go
@@ -18,7 +18,6 @@
 // product variables necessary for soong_build's operation.
 
 import (
-	"bytes"
 	"encoding/json"
 	"fmt"
 	"os"
@@ -431,32 +430,6 @@
 		return fmt.Errorf("cannot marshal arch variant product variable data: %s", err.Error())
 	}
 
-	configJson, err := json.MarshalIndent(&config, "", "    ")
-	if err != nil {
-		return fmt.Errorf("cannot marshal config data: %s", err.Error())
-	}
-	// The backslashes need to be escaped because this text is going to be put
-	// inside a Starlark string literal.
-	configJson = bytes.ReplaceAll(configJson, []byte("\\"), []byte("\\\\"))
-
-	bzl := []string{
-		bazel.GeneratedBazelFileWarning,
-		fmt.Sprintf(`_product_vars = json.decode("""%s""")`, configJson),
-		fmt.Sprintf(`_product_var_constraints = %s`, nonArchVariantProductVariablesJson),
-		fmt.Sprintf(`_arch_variant_product_var_constraints = %s`, archVariantProductVariablesJson),
-		"\n", `
-product_vars = _product_vars
-
-# TODO(b/269577299) Remove these when everything switches over to loading them from product_variable_constants.bzl
-product_var_constraints = _product_var_constraints
-arch_variant_product_var_constraints = _arch_variant_product_var_constraints
-`,
-	}
-	err = pathtools.WriteFileIfChanged(filepath.Join(dir, "product_variables.bzl"),
-		[]byte(strings.Join(bzl, "\n")), 0644)
-	if err != nil {
-		return fmt.Errorf("Could not write .bzl config file %s", err)
-	}
 	err = pathtools.WriteFileIfChanged(filepath.Join(dir, "product_variable_constants.bzl"), []byte(fmt.Sprintf(`
 product_var_constraints = %s
 arch_variant_product_var_constraints = %s
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index 8d5c99c..42a0866 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -163,12 +163,29 @@
 	return result, nil
 }
 
+var bazelPlatformSuffixes = []string{
+	"",
+	"_darwin_arm64",
+	"_darwin_x86_64",
+	"_linux_bionic_arm64",
+	"_linux_bionic_x86_64",
+	"_linux_musl_x86",
+	"_linux_musl_x86_64",
+	"_linux_x86",
+	"_linux_x86_64",
+	"_windows_x86",
+	"_windows_x86_64",
+}
+
 func platformMappingSingleProduct(label string, productVariables *android.ProductVariables) string {
 	buildSettings := ""
 	buildSettings += fmt.Sprintf("    --//build/bazel/product_config:apex_global_min_sdk_version_override=%s\n", proptools.String(productVariables.ApexGlobalMinSdkVersionOverride))
+	buildSettings += fmt.Sprintf("    --//build/bazel/product_config:cfi_include_paths=%s\n", strings.Join(productVariables.CFIIncludePaths, ","))
+	buildSettings += fmt.Sprintf("    --//build/bazel/product_config:cfi_exclude_paths=%s\n", strings.Join(productVariables.CFIExcludePaths, ","))
+	buildSettings += fmt.Sprintf("    --//build/bazel/product_config:enable_cfi=%t\n", proptools.BoolDefault(productVariables.EnableCFI, true))
 	result := ""
-	for _, extension := range []string{"", "_linux_x86_64", "_linux_bionic_x86_64", "_linux_musl_x86", "_linux_musl_x86_64"} {
-		result += "  " + label + extension + "\n" + buildSettings
+	for _, suffix := range bazelPlatformSuffixes {
+		result += "  " + label + suffix + "\n" + buildSettings
 	}
 	return result
 }
@@ -176,7 +193,19 @@
 func starlarkMapToProductVariables(in map[string]starlark.Value) (android.ProductVariables, error) {
 	var err error
 	result := android.ProductVariables{}
-	result.ApexGlobalMinSdkVersionOverride, err = starlark_import.NoneableString(in["ApexGlobalMinSdkVersionOverride"])
+	result.ApexGlobalMinSdkVersionOverride, err = starlark_import.UnmarshalNoneable[string](in["ApexGlobalMinSdkVersionOverride"])
+	if err != nil {
+		return result, err
+	}
+	result.CFIIncludePaths, err = starlark_import.Unmarshal[[]string](in["CFIIncludePaths"])
+	if err != nil {
+		return result, err
+	}
+	result.CFIExcludePaths, err = starlark_import.Unmarshal[[]string](in["CFIExcludePaths"])
+	if err != nil {
+		return result, err
+	}
+	result.EnableCFI, err = starlark_import.UnmarshalNoneable[bool](in["EnableCFI"])
 	if err != nil {
 		return result, err
 	}
diff --git a/starlark_import/unmarshal.go b/starlark_import/unmarshal.go
index 0e6f130..33c0cd9 100644
--- a/starlark_import/unmarshal.go
+++ b/starlark_import/unmarshal.go
@@ -289,16 +289,13 @@
 	}
 }
 
-// NoneableString converts a starlark.Value to a string pointer. If the starlark.Value is NoneType,
-// a nil pointer will be returned instead. All other types of starlark values are errors.
-func NoneableString(value starlark.Value) (*string, error) {
-	switch v := value.(type) {
-	case starlark.String:
-		result := v.GoString()
-		return &result, nil
-	case starlark.NoneType:
+// UnmarshalNoneable is like Unmarshal, but it will accept None as the top level (but not nested)
+// starlark value. If the value is None, a nil pointer will be returned, otherwise a pointer
+// to the result of Unmarshal will be returned.
+func UnmarshalNoneable[T any](value starlark.Value) (*T, error) {
+	if _, ok := value.(starlark.NoneType); ok {
 		return nil, nil
-	default:
-		return nil, fmt.Errorf("expected string or none, got %q", value.Type())
 	}
+	ret, err := Unmarshal[T](value)
+	return &ret, err
 }