Fix product variables in defaults modules
Product variables structs are generated at runtime to contain only
the properties that apply to the current module. Defaults modules
always contained all product variable properties. Defaults modules
apply their properties to the target module using
proptools.PrependProperties, which prepends structs that have
matching types. Filtered property structs had a different type
and were dropped.
Even after adding filtering to the defaults product variable
properties, defaults modules may contain more property structs
than the target module they are applied to, so the product
variables struct for the defaults module could contain more
fields than the product variables struct for the target module.
Use proptools.PrependMatchingProperties when applying defaults
of product variables instead, which will apply matching properties
across types.
Test: defaults_test.go
Test: variable_test.go
Change-Id: I281bdefef92053457a3b7b65383493a4e7d999df
diff --git a/android/variable_test.go b/android/variable_test.go
index cde2b1a..9cafedd 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -171,7 +171,7 @@
Foo []string
}{}))
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("variable", variableMutator).Parallel()
+ ctx.BottomUp("variable", VariableMutator).Parallel()
})
// Test that a module can use one product variable even if it doesn't have all the properties
@@ -209,6 +209,115 @@
FailIfErrored(t, errs)
}
+var testProductVariableDefaultsProperties = struct {
+ Product_variables struct {
+ Eng struct {
+ Foo []string
+ Bar []string
+ }
+ }
+}{}
+
+type productVariablesDefaultsTestProperties struct {
+ Foo []string
+}
+
+type productVariablesDefaultsTestProperties2 struct {
+ Foo []string
+ Bar []string
+}
+
+type productVariablesDefaultsTestModule struct {
+ ModuleBase
+ DefaultableModuleBase
+ properties productVariablesDefaultsTestProperties
+}
+
+func (d *productVariablesDefaultsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ ctx.Build(pctx, BuildParams{
+ Rule: Touch,
+ Output: PathForModuleOut(ctx, "out"),
+ })
+}
+
+func productVariablesDefaultsTestModuleFactory() Module {
+ module := &productVariablesDefaultsTestModule{}
+ module.AddProperties(&module.properties)
+ module.variableProperties = testProductVariableDefaultsProperties
+ InitAndroidModule(module)
+ InitDefaultableModule(module)
+ return module
+}
+
+type productVariablesDefaultsTestDefaults struct {
+ ModuleBase
+ DefaultsModuleBase
+}
+
+func productVariablesDefaultsTestDefaultsFactory() Module {
+ defaults := &productVariablesDefaultsTestDefaults{}
+ defaults.AddProperties(&productVariablesDefaultsTestProperties{})
+ defaults.AddProperties(&productVariablesDefaultsTestProperties2{})
+ defaults.variableProperties = testProductVariableDefaultsProperties
+ InitDefaultsModule(defaults)
+ return defaults
+}
+
+// Test a defaults module that supports more product variable properties than the target module.
+func TestProductVariablesDefaults(t *testing.T) {
+ bp := `
+ defaults {
+ name: "defaults",
+ product_variables: {
+ eng: {
+ foo: ["product_variable_defaults"],
+ bar: ["product_variable_defaults"],
+ },
+ },
+ foo: ["defaults"],
+ bar: ["defaults"],
+ }
+
+ test {
+ name: "foo",
+ defaults: ["defaults"],
+ foo: ["module"],
+ product_variables: {
+ eng: {
+ foo: ["product_variable_module"],
+ },
+ },
+ }
+ `
+
+ config := TestConfig(buildDir, nil, bp, nil)
+ config.TestProductVariables.Eng = boolPtr(true)
+
+ ctx := NewTestContext()
+
+ ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
+ ctx.RegisterModuleType("defaults", productVariablesDefaultsTestDefaultsFactory)
+
+ ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("variable", VariableMutator).Parallel()
+ })
+
+ ctx.Register(config)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ foo := ctx.ModuleForTests("foo", "").Module().(*productVariablesDefaultsTestModule)
+
+ want := []string{"defaults", "module", "product_variable_defaults", "product_variable_module"}
+ if g, w := foo.properties.Foo, want; !reflect.DeepEqual(g, w) {
+ t.Errorf("expected foo %q, got %q", w, g)
+ }
+}
+
func BenchmarkSliceToTypeArray(b *testing.B) {
for _, n := range []int{1, 2, 4, 8, 100} {
var propStructs []interface{}