Loading bp2build/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading bp2build/bp2build_product_config.go +101 −34 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import ( "fmt" "os" "path/filepath" "reflect" "strings" "github.com/google/blueprint/proptools" Loading Loading @@ -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{ Loading @@ -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 := "" 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 += " " + label + suffix + "\n" + buildSettings 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"]) 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 } result.CFIIncludePaths, err = starlark_import.Unmarshal[[]string](in["CFIIncludePaths"]) 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 } result.CFIExcludePaths, err = starlark_import.Unmarshal[[]string](in["CFIExcludePaths"]) 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 } result.EnableCFI, err = starlark_import.UnmarshalNoneable[bool](in["EnableCFI"]) field.Set(reflect.ValueOf(val)) case reflect.String: val, err := starlark_import.UnmarshalNoneable[string](in[name]) if err != nil { return result, err } result.DeviceAbi, err = starlark_import.Unmarshal[[]string](in["DeviceAbi"]) 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 } bp2build/bp2build_product_config_test.go 0 → 100644 +88 −0 Original line number Diff line number Diff line 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) } } } starlark_import/unmarshal.go +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading
bp2build/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading
bp2build/bp2build_product_config.go +101 −34 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import ( "fmt" "os" "path/filepath" "reflect" "strings" "github.com/google/blueprint/proptools" Loading Loading @@ -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{ Loading @@ -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 := "" 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 += " " + label + suffix + "\n" + buildSettings 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"]) 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 } result.CFIIncludePaths, err = starlark_import.Unmarshal[[]string](in["CFIIncludePaths"]) 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 } result.CFIExcludePaths, err = starlark_import.Unmarshal[[]string](in["CFIExcludePaths"]) 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 } result.EnableCFI, err = starlark_import.UnmarshalNoneable[bool](in["EnableCFI"]) field.Set(reflect.ValueOf(val)) case reflect.String: val, err := starlark_import.UnmarshalNoneable[string](in[name]) if err != nil { return result, err } result.DeviceAbi, err = starlark_import.Unmarshal[[]string](in["DeviceAbi"]) 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 }
bp2build/bp2build_product_config_test.go 0 → 100644 +88 −0 Original line number Diff line number Diff line 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) } } }
starlark_import/unmarshal.go +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading