Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1ffd090 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Make select statements work on path properties" into main

parents 4e493966 bdd8aeeb
Loading
Loading
Loading
Loading
+36 −1
Original line number Diff line number Diff line
@@ -16,9 +16,11 @@ package android

import (
	"fmt"
	"github.com/google/blueprint"
	"regexp"
	"strings"

	"github.com/google/blueprint"
	"github.com/google/blueprint/parser"
)

// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
@@ -214,6 +216,10 @@ type BaseModuleContext interface {
	// getMissingDependencies returns the list of missing dependencies.
	// Calling this function prevents adding new dependencies.
	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 {
@@ -564,3 +570,32 @@ func (b *baseModuleContext) GetPathString(skipFirst bool) 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")
	}
}
+0 −34
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import (
	"strings"

	"github.com/google/blueprint"
	"github.com/google/blueprint/parser"
	"github.com/google/blueprint/proptools"
)

@@ -213,10 +212,6 @@ type ModuleContext interface {
	// 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.
	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 {
@@ -719,32 +714,3 @@ func (m *moduleContext) HostRequiredModuleNames() []string {
func (m *moduleContext) TargetRequiredModuleNames() []string {
	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")
	}
}
+12 −2
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) {
	// tagged with `android:"path"`.
	var pathProperties []string
	for _, ps := range props {
		pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ps)...)
		pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ctx, ps)...)
	}

	// Remove duplicates to avoid multiple dependencies.
@@ -64,7 +64,7 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) {
// 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
// slice of strings.
func pathPropertiesForPropertyStruct(ps interface{}) []string {
func pathPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}) []string {
	v := reflect.ValueOf(ps)
	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
		panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type()))
@@ -106,6 +106,16 @@ func pathPropertiesForPropertyStruct(ps interface{}) []string {
				ret = append(ret, sv.String())
			case reflect.Slice:
				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:
				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()))
+36 −2
Original line number Diff line number Diff line
@@ -79,6 +79,36 @@ func TestSelects(t *testing.T) {
				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",
			bp: `
@@ -233,6 +263,7 @@ type selectsTestProvider struct {
	my_bool        *bool
	my_string      *string
	my_string_list *[]string
	my_paths       *[]string
}

func (p *selectsTestProvider) String() string {
@@ -248,7 +279,8 @@ func (p *selectsTestProvider) String() string {
	my_bool: %v,
	my_string: %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]()
@@ -257,6 +289,7 @@ type selectsMockModuleProperties struct {
	My_bool        proptools.Configurable[bool]
	My_string      proptools.Configurable[string]
	My_string_list proptools.Configurable[[]string]
	My_paths       proptools.Configurable[[]string] `android:"path"`
}

type selectsMockModule struct {
@@ -266,10 +299,11 @@ type selectsMockModule struct {
}

func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
	SetProvider[selectsTestProvider](ctx, selectsTestProviderKey, selectsTestProvider{
	SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
		my_bool:        p.properties.My_bool.Evaluate(ctx),
		my_string:      p.properties.My_string.Evaluate(ctx),
		my_string_list: p.properties.My_string_list.Evaluate(ctx),
		my_paths:       p.properties.My_paths.Evaluate(ctx),
	})
}