Merge "Update the ConfigurableEvaluator for typed selects" into main am: 1a8906d938
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/3037517 Change-Id: I8732516b695ce343fa55419709d8900eebdba86c Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -20,7 +20,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
"github.com/google/blueprint"
|
||||||
"github.com/google/blueprint/parser"
|
"github.com/google/blueprint/proptools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
|
// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
|
||||||
@@ -219,7 +219,7 @@ type BaseModuleContext interface {
|
|||||||
|
|
||||||
// EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
|
// EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
|
||||||
// can be used to evaluate the final value of Configurable properties.
|
// can be used to evaluate the final value of Configurable properties.
|
||||||
EvaluateConfiguration(parser.SelectType, string, string) (string, bool)
|
EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue
|
||||||
}
|
}
|
||||||
|
|
||||||
type baseModuleContext struct {
|
type baseModuleContext struct {
|
||||||
@@ -577,6 +577,6 @@ func (b *baseModuleContext) GetPathString(skipFirst bool) string {
|
|||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *baseModuleContext) EvaluateConfiguration(ty parser.SelectType, property, condition string) (string, bool) {
|
func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
|
||||||
return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(ty, property, condition)
|
return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property)
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,6 @@ import (
|
|||||||
"android/soong/bazel"
|
"android/soong/bazel"
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
"github.com/google/blueprint"
|
||||||
"github.com/google/blueprint/parser"
|
|
||||||
"github.com/google/blueprint/proptools"
|
"github.com/google/blueprint/proptools"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -2140,41 +2139,75 @@ func (e configurationEvalutor) PropertyErrorf(property string, fmt string, args
|
|||||||
e.ctx.OtherModulePropertyErrorf(e.m, property, fmt, args)
|
e.ctx.OtherModulePropertyErrorf(e.m, property, fmt, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e configurationEvalutor) EvaluateConfiguration(ty parser.SelectType, property, condition string) (string, bool) {
|
func (e configurationEvalutor) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
|
||||||
ctx := e.ctx
|
ctx := e.ctx
|
||||||
m := e.m
|
m := e.m
|
||||||
switch ty {
|
switch condition.FunctionName {
|
||||||
case parser.SelectTypeReleaseVariable:
|
case "release_variable":
|
||||||
if v, ok := ctx.Config().productVariables.BuildFlags[condition]; ok {
|
if len(condition.Args) != 1 {
|
||||||
return v, true
|
ctx.OtherModulePropertyErrorf(m, property, "release_variable requires 1 argument, found %d", len(condition.Args))
|
||||||
|
return proptools.ConfigurableValueUndefined()
|
||||||
}
|
}
|
||||||
return "", false
|
if v, ok := ctx.Config().productVariables.BuildFlags[condition.Args[0]]; ok {
|
||||||
case parser.SelectTypeProductVariable:
|
return proptools.ConfigurableValueString(v)
|
||||||
|
}
|
||||||
|
return proptools.ConfigurableValueUndefined()
|
||||||
|
case "product_variable":
|
||||||
// TODO(b/323382414): Might add these on a case-by-case basis
|
// TODO(b/323382414): Might add these on a case-by-case basis
|
||||||
ctx.OtherModulePropertyErrorf(m, property, "TODO(b/323382414): Product variables are not yet supported in selects")
|
ctx.OtherModulePropertyErrorf(m, property, "TODO(b/323382414): Product variables are not yet supported in selects")
|
||||||
return "", false
|
return proptools.ConfigurableValueUndefined()
|
||||||
case parser.SelectTypeSoongConfigVariable:
|
case "soong_config_variable":
|
||||||
parts := strings.Split(condition, ":")
|
if len(condition.Args) != 2 {
|
||||||
namespace := parts[0]
|
ctx.OtherModulePropertyErrorf(m, property, "soong_config_variable requires 2 arguments, found %d", len(condition.Args))
|
||||||
variable := parts[1]
|
return proptools.ConfigurableValueUndefined()
|
||||||
|
}
|
||||||
|
namespace := condition.Args[0]
|
||||||
|
variable := condition.Args[1]
|
||||||
if n, ok := ctx.Config().productVariables.VendorVars[namespace]; ok {
|
if n, ok := ctx.Config().productVariables.VendorVars[namespace]; ok {
|
||||||
if v, ok := n[variable]; ok {
|
if v, ok := n[variable]; ok {
|
||||||
return v, true
|
return proptools.ConfigurableValueString(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", false
|
return proptools.ConfigurableValueUndefined()
|
||||||
case parser.SelectTypeVariant:
|
case "variant":
|
||||||
if condition == "arch" {
|
if len(condition.Args) != 1 {
|
||||||
|
ctx.OtherModulePropertyErrorf(m, property, "variant requires 1 argument, found %d", len(condition.Args))
|
||||||
|
return proptools.ConfigurableValueUndefined()
|
||||||
|
}
|
||||||
|
if condition.Args[0] == "arch" {
|
||||||
if !m.base().ArchReady() {
|
if !m.base().ArchReady() {
|
||||||
ctx.OtherModulePropertyErrorf(m, property, "A select on arch was attempted before the arch mutator ran")
|
ctx.OtherModulePropertyErrorf(m, property, "A select on arch was attempted before the arch mutator ran")
|
||||||
return "", false
|
return proptools.ConfigurableValueUndefined()
|
||||||
}
|
}
|
||||||
return m.base().Arch().ArchType.Name, true
|
return proptools.ConfigurableValueString(m.base().Arch().ArchType.Name)
|
||||||
}
|
}
|
||||||
ctx.OtherModulePropertyErrorf(m, property, "Unknown variant %s", condition)
|
ctx.OtherModulePropertyErrorf(m, property, "Unknown variant %s", condition.Args[0])
|
||||||
return "", false
|
return proptools.ConfigurableValueUndefined()
|
||||||
|
case "boolean_var_for_testing":
|
||||||
|
// We currently don't have any other boolean variables (we should add support for typing
|
||||||
|
// the soong config variables), so add this fake one for testing the boolean select
|
||||||
|
// functionality.
|
||||||
|
if len(condition.Args) != 0 {
|
||||||
|
ctx.OtherModulePropertyErrorf(m, property, "boolean_var_for_testing requires 0 arguments, found %d", len(condition.Args))
|
||||||
|
return proptools.ConfigurableValueUndefined()
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, ok := ctx.Config().productVariables.VendorVars["boolean_var"]; ok {
|
||||||
|
if v, ok := n["for_testing"]; ok {
|
||||||
|
switch v {
|
||||||
|
case "true":
|
||||||
|
return proptools.ConfigurableValueBool(true)
|
||||||
|
case "false":
|
||||||
|
return proptools.ConfigurableValueBool(false)
|
||||||
|
default:
|
||||||
|
ctx.OtherModulePropertyErrorf(m, property, "testing:my_boolean_var can only be true or false, found %q", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return proptools.ConfigurableValueUndefined()
|
||||||
default:
|
default:
|
||||||
panic("Should be unreachable")
|
ctx.OtherModulePropertyErrorf(m, property, "Unknown select condition %s", condition.FunctionName)
|
||||||
|
return proptools.ConfigurableValueUndefined()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -327,8 +327,10 @@ func TestSelects(t *testing.T) {
|
|||||||
my_module_type {
|
my_module_type {
|
||||||
name: "foo",
|
name: "foo",
|
||||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||||
|
"foo": "bar",
|
||||||
default: unset,
|
default: unset,
|
||||||
}) + select(soong_config_variable("my_namespace", "my_variable2"), {
|
}) + select(soong_config_variable("my_namespace", "my_variable2"), {
|
||||||
|
"baz": "qux",
|
||||||
default: unset,
|
default: unset,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -341,6 +343,7 @@ func TestSelects(t *testing.T) {
|
|||||||
my_module_type {
|
my_module_type {
|
||||||
name: "foo",
|
name: "foo",
|
||||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||||
|
"foo": "bar",
|
||||||
default: unset,
|
default: unset,
|
||||||
}) + select(soong_config_variable("my_namespace", "my_variable2"), {
|
}) + select(soong_config_variable("my_namespace", "my_variable2"), {
|
||||||
default: "a",
|
default: "a",
|
||||||
@@ -414,6 +417,169 @@ func TestSelects(t *testing.T) {
|
|||||||
replacing_string_list: &[]string{"b1"},
|
replacing_string_list: &[]string{"b1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Multi-condition string 1",
|
||||||
|
bp: `
|
||||||
|
my_module_type {
|
||||||
|
name: "foo",
|
||||||
|
my_string: select((
|
||||||
|
soong_config_variable("my_namespace", "my_variable"),
|
||||||
|
soong_config_variable("my_namespace", "my_variable2"),
|
||||||
|
), {
|
||||||
|
("a", "b"): "a+b",
|
||||||
|
("a", default): "a+default",
|
||||||
|
(default, default): "default",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
vendorVars: map[string]map[string]string{
|
||||||
|
"my_namespace": {
|
||||||
|
"my_variable": "a",
|
||||||
|
"my_variable2": "b",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
provider: selectsTestProvider{
|
||||||
|
my_string: proptools.StringPtr("a+b"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Multi-condition string 2",
|
||||||
|
bp: `
|
||||||
|
my_module_type {
|
||||||
|
name: "foo",
|
||||||
|
my_string: select((
|
||||||
|
soong_config_variable("my_namespace", "my_variable"),
|
||||||
|
soong_config_variable("my_namespace", "my_variable2"),
|
||||||
|
), {
|
||||||
|
("a", "b"): "a+b",
|
||||||
|
("a", default): "a+default",
|
||||||
|
(default, default): "default",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
vendorVars: map[string]map[string]string{
|
||||||
|
"my_namespace": {
|
||||||
|
"my_variable": "a",
|
||||||
|
"my_variable2": "c",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
provider: selectsTestProvider{
|
||||||
|
my_string: proptools.StringPtr("a+default"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Multi-condition string 3",
|
||||||
|
bp: `
|
||||||
|
my_module_type {
|
||||||
|
name: "foo",
|
||||||
|
my_string: select((
|
||||||
|
soong_config_variable("my_namespace", "my_variable"),
|
||||||
|
soong_config_variable("my_namespace", "my_variable2"),
|
||||||
|
), {
|
||||||
|
("a", "b"): "a+b",
|
||||||
|
("a", default): "a+default",
|
||||||
|
(default, default): "default",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
vendorVars: map[string]map[string]string{
|
||||||
|
"my_namespace": {
|
||||||
|
"my_variable": "c",
|
||||||
|
"my_variable2": "b",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
provider: selectsTestProvider{
|
||||||
|
my_string: proptools.StringPtr("default"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Select on boolean",
|
||||||
|
bp: `
|
||||||
|
my_module_type {
|
||||||
|
name: "foo",
|
||||||
|
my_string: select(boolean_var_for_testing(), {
|
||||||
|
true: "t",
|
||||||
|
false: "f",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
vendorVars: map[string]map[string]string{
|
||||||
|
"boolean_var": {
|
||||||
|
"for_testing": "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
provider: selectsTestProvider{
|
||||||
|
my_string: proptools.StringPtr("t"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Select on boolean false",
|
||||||
|
bp: `
|
||||||
|
my_module_type {
|
||||||
|
name: "foo",
|
||||||
|
my_string: select(boolean_var_for_testing(), {
|
||||||
|
true: "t",
|
||||||
|
false: "f",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
vendorVars: map[string]map[string]string{
|
||||||
|
"boolean_var": {
|
||||||
|
"for_testing": "false",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
provider: selectsTestProvider{
|
||||||
|
my_string: proptools.StringPtr("f"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Select on boolean undefined",
|
||||||
|
bp: `
|
||||||
|
my_module_type {
|
||||||
|
name: "foo",
|
||||||
|
my_string: select(boolean_var_for_testing(), {
|
||||||
|
true: "t",
|
||||||
|
false: "f",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
expectedError: "foo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Select on boolean undefined with default",
|
||||||
|
bp: `
|
||||||
|
my_module_type {
|
||||||
|
name: "foo",
|
||||||
|
my_string: select(boolean_var_for_testing(), {
|
||||||
|
true: "t",
|
||||||
|
false: "f",
|
||||||
|
default: "default",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
provider: selectsTestProvider{
|
||||||
|
my_string: proptools.StringPtr("default"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mismatched condition types",
|
||||||
|
bp: `
|
||||||
|
my_module_type {
|
||||||
|
name: "foo",
|
||||||
|
my_string: select(boolean_var_for_testing(), {
|
||||||
|
"true": "t",
|
||||||
|
"false": "f",
|
||||||
|
default: "default",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
vendorVars: map[string]map[string]string{
|
||||||
|
"boolean_var": {
|
||||||
|
"for_testing": "false",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedError: "Expected all branches of a select on condition boolean_var_for_testing\\(\\) to have type bool, found string",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
Reference in New Issue
Block a user