From f055db60d4ad0e23b07fc9542851767ff59c1bdc Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Mon, 24 Jul 2023 15:17:03 -0700 Subject: [PATCH] Create build settings for all product config variables Bug: 269577299 Test: Presubmits Change-Id: Id8b7d65d657fa20ad8591e58d5173445b0e4f4df --- bp2build/Android.bp | 1 + bp2build/bp2build_product_config.go | 137 +++++++++++++++++------ bp2build/bp2build_product_config_test.go | 88 +++++++++++++++ starlark_import/unmarshal.go | 3 + 4 files changed, 194 insertions(+), 35 deletions(-) create mode 100644 bp2build/bp2build_product_config_test.go diff --git a/bp2build/Android.bp b/bp2build/Android.bp index f889693c4..4a3786feb 100644 --- a/bp2build/Android.bp +++ b/bp2build/Android.bp @@ -46,6 +46,7 @@ bootstrap_go_package { "apex_conversion_test.go", "apex_key_conversion_test.go", "build_conversion_test.go", + "bp2build_product_config_test.go", "bzl_conversion_test.go", "cc_binary_conversion_test.go", "cc_library_conversion_test.go", diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go index c8067af05..f56e6d86e 100644 --- a/bp2build/bp2build_product_config.go +++ b/bp2build/bp2build_product_config.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "path/filepath" + "reflect" "strings" "github.com/google/blueprint/proptools" @@ -151,16 +152,17 @@ func platformMappingContent(mainProductLabel string, mainProductVariables *andro if err != nil { return "", err } - result := "platforms:\n" - result += platformMappingSingleProduct(mainProductLabel, mainProductVariables) + var result strings.Builder + result.WriteString("platforms:\n") + platformMappingSingleProduct(mainProductLabel, mainProductVariables, &result) for product, productVariablesStarlark := range productsForTesting { productVariables, err := starlarkMapToProductVariables(productVariablesStarlark) if err != nil { return "", err } - result += platformMappingSingleProduct("@//build/bazel/tests/products:"+product, &productVariables) + platformMappingSingleProduct("@//build/bazel/tests/products:"+product, &productVariables, &result) } - return result, nil + return result.String(), nil } var bazelPlatformSuffixes = []string{ @@ -177,42 +179,107 @@ var bazelPlatformSuffixes = []string{ "_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)) - buildSettings += fmt.Sprintf(" --//build/bazel/product_config:device_abi=%s\n", strings.Join(productVariables.DeviceAbi, ",")) - result := "" - for _, suffix := range bazelPlatformSuffixes { - result += " " + label + suffix + "\n" + buildSettings +func platformMappingSingleProduct(label string, productVariables *android.ProductVariables, result *strings.Builder) { + targetBuildVariant := "user" + if proptools.Bool(productVariables.Eng) { + targetBuildVariant = "eng" + } else if proptools.Bool(productVariables.Debuggable) { + targetBuildVariant = "userdebug" + } + + for _, suffix := range bazelPlatformSuffixes { + result.WriteString(" ") + result.WriteString(label) + result.WriteString(suffix) + result.WriteString("\n") + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:always_use_prebuilt_sdks=%t\n", proptools.Bool(productVariables.Always_use_prebuilt_sdks))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:apex_global_min_sdk_version_override=%s\n", proptools.String(productVariables.ApexGlobalMinSdkVersionOverride))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:build_id=%s\n", proptools.String(productVariables.BuildId))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:build_version_tags=%s\n", strings.Join(productVariables.BuildVersionTags, ","))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:certificate_overrides=%s\n", strings.Join(productVariables.CertificateOverrides, ","))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:cfi_exclude_paths=%s\n", strings.Join(productVariables.CFIExcludePaths, ","))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:cfi_include_paths=%s\n", strings.Join(productVariables.CFIIncludePaths, ","))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:compressed_apex=%t\n", proptools.Bool(productVariables.CompressedApex))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:default_app_certificate=%s\n", proptools.String(productVariables.DefaultAppCertificate))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_abi=%s\n", strings.Join(productVariables.DeviceAbi, ","))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_max_page_size_supported=%s\n", proptools.String(productVariables.DeviceMaxPageSizeSupported))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_name=%s\n", proptools.String(productVariables.DeviceName))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_product=%s\n", proptools.String(productVariables.DeviceProduct))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:enable_cfi=%t\n", proptools.BoolDefault(productVariables.EnableCFI, true))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:manifest_package_name_overrides=%s\n", strings.Join(productVariables.ManifestPackageNameOverrides, ","))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_version_name=%s\n", proptools.String(productVariables.Platform_version_name))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:product_brand=%s\n", productVariables.ProductBrand)) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:product_manufacturer=%s\n", productVariables.ProductManufacturer)) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:target_build_variant=%s\n", targetBuildVariant)) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:tidy_checks=%s\n", proptools.String(productVariables.TidyChecks))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:unbundled_build=%t\n", proptools.Bool(productVariables.Unbundled_build))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:unbundled_build_apps=%s\n", strings.Join(productVariables.Unbundled_build_apps, ","))) } - return result } func starlarkMapToProductVariables(in map[string]starlark.Value) (android.ProductVariables, error) { - var err error result := android.ProductVariables{} - 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 - } - result.DeviceAbi, err = starlark_import.Unmarshal[[]string](in["DeviceAbi"]) - if err != nil { - return result, err + productVarsReflect := reflect.ValueOf(&result).Elem() + for i := 0; i < productVarsReflect.NumField(); i++ { + field := productVarsReflect.Field(i) + fieldType := productVarsReflect.Type().Field(i) + name := fieldType.Name + if name == "BootJars" || name == "ApexBootJars" || name == "VendorVars" || + name == "VendorSnapshotModules" || name == "RecoverySnapshotModules" { + // These variables have more complicated types, and we don't need them right now + continue + } + if _, ok := in[name]; ok { + switch field.Type().Kind() { + case reflect.Bool: + val, err := starlark_import.Unmarshal[bool](in[name]) + if err != nil { + return result, err + } + field.SetBool(val) + case reflect.String: + val, err := starlark_import.Unmarshal[string](in[name]) + if err != nil { + return result, err + } + field.SetString(val) + case reflect.Slice: + if field.Type().Elem().Kind() != reflect.String { + return result, fmt.Errorf("slices of types other than strings are unimplemented") + } + val, err := starlark_import.UnmarshalReflect(in[name], field.Type()) + if err != nil { + return result, err + } + field.Set(val) + case reflect.Pointer: + switch field.Type().Elem().Kind() { + case reflect.Bool: + val, err := starlark_import.UnmarshalNoneable[bool](in[name]) + if err != nil { + return result, err + } + field.Set(reflect.ValueOf(val)) + case reflect.String: + val, err := starlark_import.UnmarshalNoneable[string](in[name]) + if err != nil { + return result, err + } + field.Set(reflect.ValueOf(val)) + case reflect.Int: + val, err := starlark_import.UnmarshalNoneable[int](in[name]) + if err != nil { + return result, err + } + field.Set(reflect.ValueOf(val)) + default: + return result, fmt.Errorf("pointers of types other than strings/bools are unimplemented: %s", field.Type().Elem().Kind().String()) + } + default: + return result, fmt.Errorf("unimplemented type: %s", field.Type().String()) + } + } } + return result, nil } diff --git a/bp2build/bp2build_product_config_test.go b/bp2build/bp2build_product_config_test.go new file mode 100644 index 000000000..3dd53ce23 --- /dev/null +++ b/bp2build/bp2build_product_config_test.go @@ -0,0 +1,88 @@ +package bp2build + +import ( + "android/soong/android" + "android/soong/starlark_import" + "encoding/json" + "reflect" + "testing" + + "github.com/google/blueprint/proptools" + "go.starlark.net/starlark" +) + +func createStarlarkValue(t *testing.T, code string) starlark.Value { + t.Helper() + result, err := starlark.ExecFile(&starlark.Thread{}, "main.bzl", "x = "+code, nil) + if err != nil { + t.Error(err) + } + return result["x"] +} + +func createStarlarkProductVariablesMap(t *testing.T, code string) map[string]starlark.Value { + t.Helper() + rawValue := createStarlarkValue(t, code) + value, err := starlark_import.Unmarshal[map[string]starlark.Value](rawValue) + if err != nil { + t.Error(err) + } + return value +} + +func TestStarlarkMapToProductVariables(t *testing.T) { + thirty := 30 + cases := []struct { + starlark string + result android.ProductVariables + }{ + { + starlark: `{"CompressedApex": True}`, + result: android.ProductVariables{CompressedApex: proptools.BoolPtr(true)}, + }, + { + starlark: `{"ApexGlobalMinSdkVersionOverride": "Tiramisu"}`, + result: android.ProductVariables{ApexGlobalMinSdkVersionOverride: proptools.StringPtr("Tiramisu")}, + }, + { + starlark: `{"ProductManufacturer": "Google"}`, + result: android.ProductVariables{ProductManufacturer: "Google"}, + }, + { + starlark: `{"Unbundled_build_apps": ["app1", "app2"]}`, + result: android.ProductVariables{Unbundled_build_apps: []string{"app1", "app2"}}, + }, + { + starlark: `{"Platform_sdk_version": 30}`, + result: android.ProductVariables{Platform_sdk_version: &thirty}, + }, + { + starlark: `{"HostFakeSnapshotEnabled": True}`, + result: android.ProductVariables{HostFakeSnapshotEnabled: true}, + }, + } + + for _, testCase := range cases { + productVariables, err := starlarkMapToProductVariables(createStarlarkProductVariablesMap(t, + testCase.starlark)) + if err != nil { + t.Error(err) + continue + } + if !reflect.DeepEqual(testCase.result, productVariables) { + expected, err := json.Marshal(testCase.result) + if err != nil { + t.Error(err) + continue + } + actual, err := json.Marshal(productVariables) + if err != nil { + t.Error(err) + continue + } + expectedStr := string(expected) + actualStr := string(actual) + t.Errorf("expected %q, but got %q", expectedStr, actualStr) + } + } +} diff --git a/starlark_import/unmarshal.go b/starlark_import/unmarshal.go index 33c0cd92b..b2434712b 100644 --- a/starlark_import/unmarshal.go +++ b/starlark_import/unmarshal.go @@ -34,6 +34,9 @@ func UnmarshalReflect(value starlark.Value, ty reflect.Type) (reflect.Value, err return reflect.ValueOf(value), nil } zero := reflect.Zero(ty) + if value == nil { + panic("nil value") + } var result reflect.Value if ty.Kind() == reflect.Interface { var err error