Loading android/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ bootstrap_go_package { "soong-remoteexec", "soong-response", "soong-shared", "soong-starlark-format", "soong-ui-metrics_proto", "golang-protobuf-proto", "golang-protobuf-encoding-prototext", Loading android/config.go +3 −4 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import ( "android/soong/android/soongconfig" "android/soong/bazel" "android/soong/remoteexec" "android/soong/starlark_fmt" ) // Bool re-exports proptools.Bool for the android package. Loading Loading @@ -286,14 +287,12 @@ func saveToBazelConfigFile(config *productVariables, outDir string) error { } } //TODO(b/216168792) should use common function to print Starlark code nonArchVariantProductVariablesJson, err := json.MarshalIndent(&nonArchVariantProductVariables, "", " ") nonArchVariantProductVariablesJson := starlark_fmt.PrintStringList(nonArchVariantProductVariables, 0) if err != nil { return fmt.Errorf("cannot marshal product variable data: %s", err.Error()) } //TODO(b/216168792) should use common function to print Starlark code archVariantProductVariablesJson, err := json.MarshalIndent(&archVariantProductVariables, "", " ") archVariantProductVariablesJson := starlark_fmt.PrintStringList(archVariantProductVariables, 0) if err != nil { return fmt.Errorf("cannot marshal arch variant product variable data: %s", err.Error()) } Loading android/soong_config_modules_test.go +40 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,46 @@ func TestNonExistentPropertyInSoongConfigModule(t *testing.T) { })).RunTest(t) } func TestDuplicateStringValueInSoongConfigStringVariable(t *testing.T) { bp := ` soong_config_string_variable { name: "board", values: ["soc_a", "soc_b", "soc_c", "soc_a"], } soong_config_module_type { name: "acme_test", module_type: "test", config_namespace: "acme", variables: ["board"], properties: ["cflags", "srcs", "defaults"], } ` fixtureForVendorVars := func(vars map[string]map[string]string) FixturePreparer { return FixtureModifyProductVariables(func(variables FixtureProductVariables) { variables.VendorVars = vars }) } GroupFixturePreparers( fixtureForVendorVars(map[string]map[string]string{"acme": {"feature1": "1"}}), PrepareForTestWithDefaults, FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterModuleType("soong_config_module_type_import", SoongConfigModuleTypeImportFactory) ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory) ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory) ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory) ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory) ctx.RegisterModuleType("test", soongConfigTestModuleFactory) }), FixtureWithRootAndroidBp(bp), ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{ // TODO(b/171232169): improve the error message for non-existent properties `Android.bp: soong_config_string_variable: values property error: duplicate value: "soc_a"`, })).RunTest(t) } func testConfigWithVendorVars(buildDir, bp string, fs map[string][]byte, vendorVars map[string]map[string]string) Config { config := TestConfig(buildDir, nil, bp, fs) Loading android/soongconfig/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ bootstrap_go_package { "blueprint-parser", "blueprint-proptools", "soong-bazel", "soong-starlark-format", ], srcs: [ "config.go", Loading android/soongconfig/modules.go +34 −27 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import ( "github.com/google/blueprint" "github.com/google/blueprint/parser" "github.com/google/blueprint/proptools" "android/soong/starlark_fmt" ) const conditionsDefault = "conditions_default" Loading Loading @@ -177,10 +179,14 @@ func processStringVariableDef(v *SoongConfigDefinition, def *parser.Module) (err return []error{fmt.Errorf("values property must be set")} } vals := make(map[string]bool, len(stringProps.Values)) for _, name := range stringProps.Values { if err := checkVariableName(name); err != nil { return []error{fmt.Errorf("soong_config_string_variable: values property error %s", err)} } else if _, ok := vals[name]; ok { return []error{fmt.Errorf("soong_config_string_variable: values property error: duplicate value: %q", name)} } vals[name] = true } v.variables[base.variable] = &stringVariable{ Loading Loading @@ -235,7 +241,12 @@ type SoongConfigDefinition struct { // string vars, bool vars and value vars created by every // soong_config_module_type in this build. type Bp2BuildSoongConfigDefinitions struct { StringVars map[string]map[string]bool // varCache contains a cache of string variables namespace + property // The same variable may be used in multiple module types (for example, if need support // for cc_default and java_default), only need to process once varCache map[string]bool StringVars map[string][]string BoolVars map[string]bool ValueVars map[string]bool } Loading @@ -253,7 +264,7 @@ func (defs *Bp2BuildSoongConfigDefinitions) AddVars(mtDef SoongConfigDefinition) defer bp2buildSoongConfigVarsLock.Unlock() if defs.StringVars == nil { defs.StringVars = make(map[string]map[string]bool) defs.StringVars = make(map[string][]string) } if defs.BoolVars == nil { defs.BoolVars = make(map[string]bool) Loading @@ -261,15 +272,24 @@ func (defs *Bp2BuildSoongConfigDefinitions) AddVars(mtDef SoongConfigDefinition) if defs.ValueVars == nil { defs.ValueVars = make(map[string]bool) } if defs.varCache == nil { defs.varCache = make(map[string]bool) } for _, moduleType := range mtDef.ModuleTypes { for _, v := range moduleType.Variables { key := strings.Join([]string{moduleType.ConfigNamespace, v.variableProperty()}, "__") if strVar, ok := v.(*stringVariable); ok { if _, ok := defs.StringVars[key]; !ok { defs.StringVars[key] = make(map[string]bool, 0) // The same variable may be used in multiple module types (for example, if need support // for cc_default and java_default), only need to process once if _, keyInCache := defs.varCache[key]; keyInCache { continue } else { defs.varCache[key] = true } if strVar, ok := v.(*stringVariable); ok { for _, value := range strVar.values { defs.StringVars[key][value] = true defs.StringVars[key] = append(defs.StringVars[key], value) } } else if _, ok := v.(*boolVariable); ok { defs.BoolVars[key] = true Loading Loading @@ -302,29 +322,16 @@ func sortedStringKeys(m interface{}) []string { // String emits the Soong config variable definitions as Starlark dictionaries. func (defs Bp2BuildSoongConfigDefinitions) String() string { ret := "" ret += "soong_config_bool_variables = {\n" for _, boolVar := range sortedStringKeys(defs.BoolVars) { ret += fmt.Sprintf(" \"%s\": True,\n", boolVar) } ret += "}\n" ret += "\n" ret += "soong_config_bool_variables = " ret += starlark_fmt.PrintBoolDict(defs.BoolVars, 0) ret += "\n\n" ret += "soong_config_value_variables = {\n" for _, valueVar := range sortedStringKeys(defs.ValueVars) { ret += fmt.Sprintf(" \"%s\": True,\n", valueVar) } ret += "}\n" ret += "\n" ret += "soong_config_value_variables = " ret += starlark_fmt.PrintBoolDict(defs.ValueVars, 0) ret += "\n\n" ret += "soong_config_string_variables = {\n" for _, stringVar := range sortedStringKeys(defs.StringVars) { ret += fmt.Sprintf(" \"%s\": [\n", stringVar) for _, choice := range sortedStringKeys(defs.StringVars[stringVar]) { ret += fmt.Sprintf(" \"%s\",\n", choice) } ret += fmt.Sprintf(" ],\n") } ret += "}" ret += "soong_config_string_variables = " ret += starlark_fmt.PrintStringListDict(defs.StringVars, 0) return ret } Loading Loading
android/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ bootstrap_go_package { "soong-remoteexec", "soong-response", "soong-shared", "soong-starlark-format", "soong-ui-metrics_proto", "golang-protobuf-proto", "golang-protobuf-encoding-prototext", Loading
android/config.go +3 −4 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import ( "android/soong/android/soongconfig" "android/soong/bazel" "android/soong/remoteexec" "android/soong/starlark_fmt" ) // Bool re-exports proptools.Bool for the android package. Loading Loading @@ -286,14 +287,12 @@ func saveToBazelConfigFile(config *productVariables, outDir string) error { } } //TODO(b/216168792) should use common function to print Starlark code nonArchVariantProductVariablesJson, err := json.MarshalIndent(&nonArchVariantProductVariables, "", " ") nonArchVariantProductVariablesJson := starlark_fmt.PrintStringList(nonArchVariantProductVariables, 0) if err != nil { return fmt.Errorf("cannot marshal product variable data: %s", err.Error()) } //TODO(b/216168792) should use common function to print Starlark code archVariantProductVariablesJson, err := json.MarshalIndent(&archVariantProductVariables, "", " ") archVariantProductVariablesJson := starlark_fmt.PrintStringList(archVariantProductVariables, 0) if err != nil { return fmt.Errorf("cannot marshal arch variant product variable data: %s", err.Error()) } Loading
android/soong_config_modules_test.go +40 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,46 @@ func TestNonExistentPropertyInSoongConfigModule(t *testing.T) { })).RunTest(t) } func TestDuplicateStringValueInSoongConfigStringVariable(t *testing.T) { bp := ` soong_config_string_variable { name: "board", values: ["soc_a", "soc_b", "soc_c", "soc_a"], } soong_config_module_type { name: "acme_test", module_type: "test", config_namespace: "acme", variables: ["board"], properties: ["cflags", "srcs", "defaults"], } ` fixtureForVendorVars := func(vars map[string]map[string]string) FixturePreparer { return FixtureModifyProductVariables(func(variables FixtureProductVariables) { variables.VendorVars = vars }) } GroupFixturePreparers( fixtureForVendorVars(map[string]map[string]string{"acme": {"feature1": "1"}}), PrepareForTestWithDefaults, FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterModuleType("soong_config_module_type_import", SoongConfigModuleTypeImportFactory) ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory) ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory) ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory) ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory) ctx.RegisterModuleType("test", soongConfigTestModuleFactory) }), FixtureWithRootAndroidBp(bp), ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{ // TODO(b/171232169): improve the error message for non-existent properties `Android.bp: soong_config_string_variable: values property error: duplicate value: "soc_a"`, })).RunTest(t) } func testConfigWithVendorVars(buildDir, bp string, fs map[string][]byte, vendorVars map[string]map[string]string) Config { config := TestConfig(buildDir, nil, bp, fs) Loading
android/soongconfig/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ bootstrap_go_package { "blueprint-parser", "blueprint-proptools", "soong-bazel", "soong-starlark-format", ], srcs: [ "config.go", Loading
android/soongconfig/modules.go +34 −27 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import ( "github.com/google/blueprint" "github.com/google/blueprint/parser" "github.com/google/blueprint/proptools" "android/soong/starlark_fmt" ) const conditionsDefault = "conditions_default" Loading Loading @@ -177,10 +179,14 @@ func processStringVariableDef(v *SoongConfigDefinition, def *parser.Module) (err return []error{fmt.Errorf("values property must be set")} } vals := make(map[string]bool, len(stringProps.Values)) for _, name := range stringProps.Values { if err := checkVariableName(name); err != nil { return []error{fmt.Errorf("soong_config_string_variable: values property error %s", err)} } else if _, ok := vals[name]; ok { return []error{fmt.Errorf("soong_config_string_variable: values property error: duplicate value: %q", name)} } vals[name] = true } v.variables[base.variable] = &stringVariable{ Loading Loading @@ -235,7 +241,12 @@ type SoongConfigDefinition struct { // string vars, bool vars and value vars created by every // soong_config_module_type in this build. type Bp2BuildSoongConfigDefinitions struct { StringVars map[string]map[string]bool // varCache contains a cache of string variables namespace + property // The same variable may be used in multiple module types (for example, if need support // for cc_default and java_default), only need to process once varCache map[string]bool StringVars map[string][]string BoolVars map[string]bool ValueVars map[string]bool } Loading @@ -253,7 +264,7 @@ func (defs *Bp2BuildSoongConfigDefinitions) AddVars(mtDef SoongConfigDefinition) defer bp2buildSoongConfigVarsLock.Unlock() if defs.StringVars == nil { defs.StringVars = make(map[string]map[string]bool) defs.StringVars = make(map[string][]string) } if defs.BoolVars == nil { defs.BoolVars = make(map[string]bool) Loading @@ -261,15 +272,24 @@ func (defs *Bp2BuildSoongConfigDefinitions) AddVars(mtDef SoongConfigDefinition) if defs.ValueVars == nil { defs.ValueVars = make(map[string]bool) } if defs.varCache == nil { defs.varCache = make(map[string]bool) } for _, moduleType := range mtDef.ModuleTypes { for _, v := range moduleType.Variables { key := strings.Join([]string{moduleType.ConfigNamespace, v.variableProperty()}, "__") if strVar, ok := v.(*stringVariable); ok { if _, ok := defs.StringVars[key]; !ok { defs.StringVars[key] = make(map[string]bool, 0) // The same variable may be used in multiple module types (for example, if need support // for cc_default and java_default), only need to process once if _, keyInCache := defs.varCache[key]; keyInCache { continue } else { defs.varCache[key] = true } if strVar, ok := v.(*stringVariable); ok { for _, value := range strVar.values { defs.StringVars[key][value] = true defs.StringVars[key] = append(defs.StringVars[key], value) } } else if _, ok := v.(*boolVariable); ok { defs.BoolVars[key] = true Loading Loading @@ -302,29 +322,16 @@ func sortedStringKeys(m interface{}) []string { // String emits the Soong config variable definitions as Starlark dictionaries. func (defs Bp2BuildSoongConfigDefinitions) String() string { ret := "" ret += "soong_config_bool_variables = {\n" for _, boolVar := range sortedStringKeys(defs.BoolVars) { ret += fmt.Sprintf(" \"%s\": True,\n", boolVar) } ret += "}\n" ret += "\n" ret += "soong_config_bool_variables = " ret += starlark_fmt.PrintBoolDict(defs.BoolVars, 0) ret += "\n\n" ret += "soong_config_value_variables = {\n" for _, valueVar := range sortedStringKeys(defs.ValueVars) { ret += fmt.Sprintf(" \"%s\": True,\n", valueVar) } ret += "}\n" ret += "\n" ret += "soong_config_value_variables = " ret += starlark_fmt.PrintBoolDict(defs.ValueVars, 0) ret += "\n\n" ret += "soong_config_string_variables = {\n" for _, stringVar := range sortedStringKeys(defs.StringVars) { ret += fmt.Sprintf(" \"%s\": [\n", stringVar) for _, choice := range sortedStringKeys(defs.StringVars[stringVar]) { ret += fmt.Sprintf(" \"%s\",\n", choice) } ret += fmt.Sprintf(" ],\n") } ret += "}" ret += "soong_config_string_variables = " ret += starlark_fmt.PrintStringListDict(defs.StringVars, 0) return ret } Loading