Loading android/base_module_context.go +36 −1 Original line number Original line Diff line number Diff line Loading @@ -16,9 +16,11 @@ package android import ( import ( "fmt" "fmt" "github.com/google/blueprint" "regexp" "regexp" "strings" "strings" "github.com/google/blueprint" "github.com/google/blueprint/parser" ) ) // BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns // BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns Loading Loading @@ -214,6 +216,10 @@ type BaseModuleContext interface { // getMissingDependencies returns the list of missing dependencies. // getMissingDependencies returns the list of missing dependencies. // Calling this function prevents adding new dependencies. // Calling this function prevents adding new dependencies. getMissingDependencies() []string getMissingDependencies() []string // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context // can be used to evaluate the final value of Configurable properties. EvaluateConfiguration(parser.SelectType, string) (string, bool) } } type baseModuleContext struct { type baseModuleContext struct { Loading Loading @@ -564,3 +570,32 @@ func (b *baseModuleContext) GetPathString(skipFirst bool) string { } } return sb.String() return sb.String() } } func (m *baseModuleContext) EvaluateConfiguration(ty parser.SelectType, condition string) (string, bool) { switch ty { case parser.SelectTypeReleaseVariable: if v, ok := m.Config().productVariables.BuildFlags[condition]; ok { return v, true } return "", false case parser.SelectTypeProductVariable: // TODO(b/323382414): Might add these on a case-by-case basis m.ModuleErrorf("TODO(b/323382414): Product variables are not yet supported in selects") return "", false case parser.SelectTypeSoongConfigVariable: parts := strings.Split(condition, ":") namespace := parts[0] variable := parts[1] if n, ok := m.Config().productVariables.VendorVars[namespace]; ok { if v, ok := n[variable]; ok { return v, true } } return "", false case parser.SelectTypeVariant: m.ModuleErrorf("TODO(b/323382414): Variants are not yet supported in selects") return "", false default: panic("Should be unreachable") } } android/module_context.go +0 −34 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,6 @@ import ( "strings" "strings" "github.com/google/blueprint" "github.com/google/blueprint" "github.com/google/blueprint/parser" "github.com/google/blueprint/proptools" "github.com/google/blueprint/proptools" ) ) Loading Loading @@ -213,10 +212,6 @@ type ModuleContext interface { // GenerateAndroidBuildActions. If it is called then the struct will be written out and included in // GenerateAndroidBuildActions. If it is called then the struct will be written out and included in // the module-info.json generated by Make, and Make will not generate its own data for this module. // the module-info.json generated by Make, and Make will not generate its own data for this module. ModuleInfoJSON() *ModuleInfoJSON ModuleInfoJSON() *ModuleInfoJSON // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context // can be used to evaluate the final value of Configurable properties. EvaluateConfiguration(parser.SelectType, string) (string, bool) } } type moduleContext struct { type moduleContext struct { Loading Loading @@ -719,32 +714,3 @@ func (m *moduleContext) HostRequiredModuleNames() []string { func (m *moduleContext) TargetRequiredModuleNames() []string { func (m *moduleContext) TargetRequiredModuleNames() []string { return m.module.TargetRequiredModuleNames() return m.module.TargetRequiredModuleNames() } } func (m *moduleContext) EvaluateConfiguration(ty parser.SelectType, condition string) (string, bool) { switch ty { case parser.SelectTypeReleaseVariable: if v, ok := m.Config().productVariables.BuildFlags[condition]; ok { return v, true } return "", false case parser.SelectTypeProductVariable: // TODO: Might add these on a case-by-case basis m.ModuleErrorf("TODO(b/323382414): Product variables are not yet supported in selects") return "", false case parser.SelectTypeSoongConfigVariable: parts := strings.Split(condition, ":") namespace := parts[0] variable := parts[1] if n, ok := m.Config().productVariables.VendorVars[namespace]; ok { if v, ok := n[variable]; ok { return v, true } } return "", false case parser.SelectTypeVariant: m.ModuleErrorf("TODO(b/323382414): Variants are not yet supported in selects") return "", false default: panic("Should be unreachable") } } android/path_properties.go +12 −2 Original line number Original line Diff line number Diff line Loading @@ -47,7 +47,7 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { // tagged with `android:"path"`. // tagged with `android:"path"`. var pathProperties []string var pathProperties []string for _, ps := range props { for _, ps := range props { pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ps)...) pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ctx, ps)...) } } // Remove duplicates to avoid multiple dependencies. // Remove duplicates to avoid multiple dependencies. Loading @@ -64,7 +64,7 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { // pathPropertiesForPropertyStruct uses the indexes of properties that are tagged with // pathPropertiesForPropertyStruct uses the indexes of properties that are tagged with // android:"path" to extract all their values from a property struct, returning them as a single // android:"path" to extract all their values from a property struct, returning them as a single // slice of strings. // slice of strings. func pathPropertiesForPropertyStruct(ps interface{}) []string { func pathPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}) []string { v := reflect.ValueOf(ps) v := reflect.ValueOf(ps) if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type())) panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type())) Loading Loading @@ -106,6 +106,16 @@ func pathPropertiesForPropertyStruct(ps interface{}) []string { ret = append(ret, sv.String()) ret = append(ret, sv.String()) case reflect.Slice: case reflect.Slice: ret = append(ret, sv.Interface().([]string)...) ret = append(ret, sv.Interface().([]string)...) case reflect.Struct: intf := sv.Interface() if configurable, ok := intf.(proptools.Configurable[string]); ok { ret = append(ret, proptools.String(configurable.Evaluate(ctx))) } else if configurable, ok := intf.(proptools.Configurable[[]string]); ok { ret = append(ret, proptools.Slice(configurable.Evaluate(ctx))...) } else { panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`, v.Type().FieldByIndex(i).Name, v.Type(), sv.Type())) } default: default: panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`, panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`, v.Type().FieldByIndex(i).Name, v.Type(), sv.Type())) v.Type().FieldByIndex(i).Name, v.Type(), sv.Type())) Loading android/selects_test.go +36 −2 Original line number Original line Diff line number Diff line Loading @@ -79,6 +79,36 @@ func TestSelects(t *testing.T) { my_bool: proptools.BoolPtr(true), my_bool: proptools.BoolPtr(true), }, }, }, }, { name: "basic paths", bp: ` my_module_type { name: "foo", my_paths: select(soong_config_variable("my_namespace", "my_variable"), { "a": ["foo.txt"], "b": ["bar.txt"], _: ["baz.txt"], }), } `, provider: selectsTestProvider{ my_paths: &[]string{"baz.txt"}, }, }, { name: "paths with module references", bp: ` my_module_type { name: "foo", my_paths: select(soong_config_variable("my_namespace", "my_variable"), { "a": [":a"], "b": [":b"], _: [":c"], }), } `, expectedError: `"foo" depends on undefined module "c"`, }, { { name: "Differing types", name: "Differing types", bp: ` bp: ` Loading Loading @@ -233,6 +263,7 @@ type selectsTestProvider struct { my_bool *bool my_bool *bool my_string *string my_string *string my_string_list *[]string my_string_list *[]string my_paths *[]string } } func (p *selectsTestProvider) String() string { func (p *selectsTestProvider) String() string { Loading @@ -248,7 +279,8 @@ func (p *selectsTestProvider) String() string { my_bool: %v, my_bool: %v, my_string: %s, my_string: %s, my_string_list: %s, my_string_list: %s, }`, myBoolStr, myStringStr, p.my_string_list) my_paths: %s, }`, myBoolStr, myStringStr, p.my_string_list, p.my_paths) } } var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]() var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]() Loading @@ -257,6 +289,7 @@ type selectsMockModuleProperties struct { My_bool proptools.Configurable[bool] My_bool proptools.Configurable[bool] My_string proptools.Configurable[string] My_string proptools.Configurable[string] My_string_list proptools.Configurable[[]string] My_string_list proptools.Configurable[[]string] My_paths proptools.Configurable[[]string] `android:"path"` } } type selectsMockModule struct { type selectsMockModule struct { Loading @@ -266,10 +299,11 @@ type selectsMockModule struct { } } func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) { func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) { SetProvider[selectsTestProvider](ctx, selectsTestProviderKey, selectsTestProvider{ SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{ my_bool: p.properties.My_bool.Evaluate(ctx), my_bool: p.properties.My_bool.Evaluate(ctx), my_string: p.properties.My_string.Evaluate(ctx), my_string: p.properties.My_string.Evaluate(ctx), my_string_list: p.properties.My_string_list.Evaluate(ctx), my_string_list: p.properties.My_string_list.Evaluate(ctx), my_paths: p.properties.My_paths.Evaluate(ctx), }) }) } } Loading Loading
android/base_module_context.go +36 −1 Original line number Original line Diff line number Diff line Loading @@ -16,9 +16,11 @@ package android import ( import ( "fmt" "fmt" "github.com/google/blueprint" "regexp" "regexp" "strings" "strings" "github.com/google/blueprint" "github.com/google/blueprint/parser" ) ) // BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns // BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns Loading Loading @@ -214,6 +216,10 @@ type BaseModuleContext interface { // getMissingDependencies returns the list of missing dependencies. // getMissingDependencies returns the list of missing dependencies. // Calling this function prevents adding new dependencies. // Calling this function prevents adding new dependencies. getMissingDependencies() []string getMissingDependencies() []string // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context // can be used to evaluate the final value of Configurable properties. EvaluateConfiguration(parser.SelectType, string) (string, bool) } } type baseModuleContext struct { type baseModuleContext struct { Loading Loading @@ -564,3 +570,32 @@ func (b *baseModuleContext) GetPathString(skipFirst bool) string { } } return sb.String() return sb.String() } } func (m *baseModuleContext) EvaluateConfiguration(ty parser.SelectType, condition string) (string, bool) { switch ty { case parser.SelectTypeReleaseVariable: if v, ok := m.Config().productVariables.BuildFlags[condition]; ok { return v, true } return "", false case parser.SelectTypeProductVariable: // TODO(b/323382414): Might add these on a case-by-case basis m.ModuleErrorf("TODO(b/323382414): Product variables are not yet supported in selects") return "", false case parser.SelectTypeSoongConfigVariable: parts := strings.Split(condition, ":") namespace := parts[0] variable := parts[1] if n, ok := m.Config().productVariables.VendorVars[namespace]; ok { if v, ok := n[variable]; ok { return v, true } } return "", false case parser.SelectTypeVariant: m.ModuleErrorf("TODO(b/323382414): Variants are not yet supported in selects") return "", false default: panic("Should be unreachable") } }
android/module_context.go +0 −34 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,6 @@ import ( "strings" "strings" "github.com/google/blueprint" "github.com/google/blueprint" "github.com/google/blueprint/parser" "github.com/google/blueprint/proptools" "github.com/google/blueprint/proptools" ) ) Loading Loading @@ -213,10 +212,6 @@ type ModuleContext interface { // GenerateAndroidBuildActions. If it is called then the struct will be written out and included in // GenerateAndroidBuildActions. If it is called then the struct will be written out and included in // the module-info.json generated by Make, and Make will not generate its own data for this module. // the module-info.json generated by Make, and Make will not generate its own data for this module. ModuleInfoJSON() *ModuleInfoJSON ModuleInfoJSON() *ModuleInfoJSON // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context // can be used to evaluate the final value of Configurable properties. EvaluateConfiguration(parser.SelectType, string) (string, bool) } } type moduleContext struct { type moduleContext struct { Loading Loading @@ -719,32 +714,3 @@ func (m *moduleContext) HostRequiredModuleNames() []string { func (m *moduleContext) TargetRequiredModuleNames() []string { func (m *moduleContext) TargetRequiredModuleNames() []string { return m.module.TargetRequiredModuleNames() return m.module.TargetRequiredModuleNames() } } func (m *moduleContext) EvaluateConfiguration(ty parser.SelectType, condition string) (string, bool) { switch ty { case parser.SelectTypeReleaseVariable: if v, ok := m.Config().productVariables.BuildFlags[condition]; ok { return v, true } return "", false case parser.SelectTypeProductVariable: // TODO: Might add these on a case-by-case basis m.ModuleErrorf("TODO(b/323382414): Product variables are not yet supported in selects") return "", false case parser.SelectTypeSoongConfigVariable: parts := strings.Split(condition, ":") namespace := parts[0] variable := parts[1] if n, ok := m.Config().productVariables.VendorVars[namespace]; ok { if v, ok := n[variable]; ok { return v, true } } return "", false case parser.SelectTypeVariant: m.ModuleErrorf("TODO(b/323382414): Variants are not yet supported in selects") return "", false default: panic("Should be unreachable") } }
android/path_properties.go +12 −2 Original line number Original line Diff line number Diff line Loading @@ -47,7 +47,7 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { // tagged with `android:"path"`. // tagged with `android:"path"`. var pathProperties []string var pathProperties []string for _, ps := range props { for _, ps := range props { pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ps)...) pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ctx, ps)...) } } // Remove duplicates to avoid multiple dependencies. // Remove duplicates to avoid multiple dependencies. Loading @@ -64,7 +64,7 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { // pathPropertiesForPropertyStruct uses the indexes of properties that are tagged with // pathPropertiesForPropertyStruct uses the indexes of properties that are tagged with // android:"path" to extract all their values from a property struct, returning them as a single // android:"path" to extract all their values from a property struct, returning them as a single // slice of strings. // slice of strings. func pathPropertiesForPropertyStruct(ps interface{}) []string { func pathPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}) []string { v := reflect.ValueOf(ps) v := reflect.ValueOf(ps) if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type())) panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type())) Loading Loading @@ -106,6 +106,16 @@ func pathPropertiesForPropertyStruct(ps interface{}) []string { ret = append(ret, sv.String()) ret = append(ret, sv.String()) case reflect.Slice: case reflect.Slice: ret = append(ret, sv.Interface().([]string)...) ret = append(ret, sv.Interface().([]string)...) case reflect.Struct: intf := sv.Interface() if configurable, ok := intf.(proptools.Configurable[string]); ok { ret = append(ret, proptools.String(configurable.Evaluate(ctx))) } else if configurable, ok := intf.(proptools.Configurable[[]string]); ok { ret = append(ret, proptools.Slice(configurable.Evaluate(ctx))...) } else { panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`, v.Type().FieldByIndex(i).Name, v.Type(), sv.Type())) } default: default: panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`, panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`, v.Type().FieldByIndex(i).Name, v.Type(), sv.Type())) v.Type().FieldByIndex(i).Name, v.Type(), sv.Type())) Loading
android/selects_test.go +36 −2 Original line number Original line Diff line number Diff line Loading @@ -79,6 +79,36 @@ func TestSelects(t *testing.T) { my_bool: proptools.BoolPtr(true), my_bool: proptools.BoolPtr(true), }, }, }, }, { name: "basic paths", bp: ` my_module_type { name: "foo", my_paths: select(soong_config_variable("my_namespace", "my_variable"), { "a": ["foo.txt"], "b": ["bar.txt"], _: ["baz.txt"], }), } `, provider: selectsTestProvider{ my_paths: &[]string{"baz.txt"}, }, }, { name: "paths with module references", bp: ` my_module_type { name: "foo", my_paths: select(soong_config_variable("my_namespace", "my_variable"), { "a": [":a"], "b": [":b"], _: [":c"], }), } `, expectedError: `"foo" depends on undefined module "c"`, }, { { name: "Differing types", name: "Differing types", bp: ` bp: ` Loading Loading @@ -233,6 +263,7 @@ type selectsTestProvider struct { my_bool *bool my_bool *bool my_string *string my_string *string my_string_list *[]string my_string_list *[]string my_paths *[]string } } func (p *selectsTestProvider) String() string { func (p *selectsTestProvider) String() string { Loading @@ -248,7 +279,8 @@ func (p *selectsTestProvider) String() string { my_bool: %v, my_bool: %v, my_string: %s, my_string: %s, my_string_list: %s, my_string_list: %s, }`, myBoolStr, myStringStr, p.my_string_list) my_paths: %s, }`, myBoolStr, myStringStr, p.my_string_list, p.my_paths) } } var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]() var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]() Loading @@ -257,6 +289,7 @@ type selectsMockModuleProperties struct { My_bool proptools.Configurable[bool] My_bool proptools.Configurable[bool] My_string proptools.Configurable[string] My_string proptools.Configurable[string] My_string_list proptools.Configurable[[]string] My_string_list proptools.Configurable[[]string] My_paths proptools.Configurable[[]string] `android:"path"` } } type selectsMockModule struct { type selectsMockModule struct { Loading @@ -266,10 +299,11 @@ type selectsMockModule struct { } } func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) { func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) { SetProvider[selectsTestProvider](ctx, selectsTestProviderKey, selectsTestProvider{ SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{ my_bool: p.properties.My_bool.Evaluate(ctx), my_bool: p.properties.My_bool.Evaluate(ctx), my_string: p.properties.My_string.Evaluate(ctx), my_string: p.properties.My_string.Evaluate(ctx), my_string_list: p.properties.My_string_list.Evaluate(ctx), my_string_list: p.properties.My_string_list.Evaluate(ctx), my_paths: p.properties.My_paths.Evaluate(ctx), }) }) } } Loading