diff --git a/Android.bp b/Android.bp index 30cbf150c..914d6734d 100644 --- a/Android.bp +++ b/Android.bp @@ -93,7 +93,6 @@ bootstrap_go_package { "common/config.go", "common/defs.go", "common/env.go", - "common/extend.go", "common/glob.go", "common/module.go", "common/paths.go", diff --git a/cc/cc.go b/cc/cc.go index c4e1d0e8c..a1b5a424d 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -26,6 +26,7 @@ import ( "github.com/google/blueprint" "github.com/google/blueprint/pathtools" + "github.com/google/blueprint/proptools" "android/soong" "android/soong/common" @@ -270,24 +271,24 @@ type CCBaseProperties struct { // modules cannot contain undefined symbols that are not satisified by their immediate // dependencies. Set this flag to true to remove --no-undefined from the linker flags. // This flag should only be necessary for compiling low-level libraries like libc. - Allow_undefined_symbols bool + Allow_undefined_symbols *bool // don't link in crt_begin and crt_end. This flag should only be necessary for // compiling crt or libc. - Nocrt bool `android:"arch_variant"` + Nocrt *bool `android:"arch_variant"` // don't link in libgcc.a - No_libgcc bool + No_libgcc *bool // don't insert default compiler flags into asflags, cflags, // cppflags, conlyflags, ldflags, or include_dirs - No_default_compiler_flags bool + No_default_compiler_flags *bool // compile module with clang instead of gcc - Clang bool `android:"arch_variant"` + Clang *bool `android:"arch_variant"` // pass -frtti instead of -fno-rtti - Rtti bool + Rtti *bool // -l arguments to pass to linker for host-provided shared libraries Host_ldlibs []string `android:"arch_variant"` @@ -323,7 +324,7 @@ type CCBase struct { Properties CCBaseProperties unused struct { - Native_coverage bool + Native_coverage *bool Required []string Sanitize []string `android:"arch_variant"` Sanitize_recover []string @@ -451,9 +452,9 @@ func (c *CCBase) collectFlags(ctx common.AndroidModuleContext, toolchain Toolcha LdFlags: c.Properties.Ldflags, AsFlags: c.Properties.Asflags, YaccFlags: c.Properties.Yaccflags, - Nocrt: c.Properties.Nocrt, + Nocrt: Bool(c.Properties.Nocrt), Toolchain: toolchain, - Clang: c.Properties.Clang, + Clang: Bool(c.Properties.Clang), } // Include dir cflags @@ -473,7 +474,7 @@ func (c *CCBase) collectFlags(ctx common.AndroidModuleContext, toolchain Toolcha includeFilesToFlags(rootIncludeFiles), includeFilesToFlags(localIncludeFiles)) - if !c.Properties.No_default_compiler_flags { + if !Bool(c.Properties.No_default_compiler_flags) { if c.Properties.Sdk_version == "" || ctx.Host() { flags.GlobalFlags = append(flags.GlobalFlags, "${commonGlobalIncludes}", @@ -488,7 +489,7 @@ func (c *CCBase) collectFlags(ctx common.AndroidModuleContext, toolchain Toolcha }...) } - if !ctx.ContainsProperty("clang") { + if c.Properties.Clang == nil { if ctx.Host() { flags.Clang = true } @@ -532,8 +533,8 @@ func (c *CCBase) collectFlags(ctx common.AndroidModuleContext, toolchain Toolcha flags.LdFlags = append(flags.LdFlags, target, gccPrefix) } - if !c.Properties.No_default_compiler_flags { - if ctx.Device() && !c.Properties.Allow_undefined_symbols { + if !Bool(c.Properties.No_default_compiler_flags) { + if ctx.Device() && !Bool(c.Properties.Allow_undefined_symbols) { flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined") } @@ -554,7 +555,7 @@ func (c *CCBase) collectFlags(ctx common.AndroidModuleContext, toolchain Toolcha } if ctx.Device() { - if c.Properties.Rtti { + if Bool(c.Properties.Rtti) { flags.CppFlags = append(flags.CppFlags, "-frtti") } else { flags.CppFlags = append(flags.CppFlags, "-fno-rtti") @@ -743,11 +744,11 @@ func (c *CCBase) depsToPaths(ctx common.AndroidModuleContext, depNames CCDeps) C if obj, ok := m.(ccObjectProvider); ok { otherName := ctx.OtherModuleName(m) if otherName == depNames.CrtBegin { - if !c.Properties.Nocrt { + if !Bool(c.Properties.Nocrt) { depPaths.CrtBegin = obj.object().outputFile() } } else if otherName == depNames.CrtEnd { - if !c.Properties.Nocrt { + if !Bool(c.Properties.Nocrt) { depPaths.CrtEnd = obj.object().outputFile() } } else { @@ -780,7 +781,7 @@ func newCCDynamic(dynamic *CCLinked, module CCModuleType, hod common.HostOrDevic } func (c *CCLinked) systemSharedLibs(ctx common.AndroidBaseContext) []string { - if ctx.ContainsProperty("system_shared_libs") { + if c.Properties.System_shared_libs != nil { return c.Properties.System_shared_libs } else if ctx.Device() && c.Properties.Sdk_version == "" { return []string{"libc", "libm"} @@ -941,7 +942,7 @@ func (c *CCLinked) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCDe if ctx.Device() { // libgcc and libatomic have to be last on the command line depNames.LateStaticLibs = append(depNames.LateStaticLibs, "libgcov", "libatomic") - if !c.Properties.No_libgcc { + if !Bool(c.Properties.No_libgcc) { depNames.LateStaticLibs = append(depNames.LateStaticLibs, "libgcc") } @@ -1328,7 +1329,7 @@ var _ ccObjectProvider = (*ccObject)(nil) type CCBinaryProperties struct { // compile executable with -static - Static_executable bool + Static_executable *bool // set the name of the output Stem string `android:"arch_variant"` @@ -1341,7 +1342,7 @@ type CCBinaryProperties struct { // Create a separate binary for each source file. Useful when there is // global state that can not be torn down and reset between each test suite. - Test_per_src bool + Test_per_src *bool } type CCBinary struct { @@ -1352,11 +1353,11 @@ type CCBinary struct { } func (c *CCBinary) buildStatic() bool { - return c.BinaryProperties.Static_executable + return Bool(c.BinaryProperties.Static_executable) } func (c *CCBinary) buildShared() bool { - return !c.BinaryProperties.Static_executable + return !Bool(c.BinaryProperties.Static_executable) } func (c *CCBinary) getStem(ctx common.AndroidModuleContext) string { @@ -1372,14 +1373,14 @@ func (c *CCBinary) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCDe depNames = c.CCLinked.depNames(ctx, depNames) if ctx.Device() { if c.Properties.Sdk_version == "" { - if c.BinaryProperties.Static_executable { + if Bool(c.BinaryProperties.Static_executable) { depNames.CrtBegin = "crtbegin_static" } else { depNames.CrtBegin = "crtbegin_dynamic" } depNames.CrtEnd = "crtend_android" } else { - if c.BinaryProperties.Static_executable { + if Bool(c.BinaryProperties.Static_executable) { depNames.CrtBegin = "ndk_crtbegin_static." + c.Properties.Sdk_version } else { depNames.CrtBegin = "ndk_crtbegin_dynamic." + c.Properties.Sdk_version @@ -1387,7 +1388,7 @@ func (c *CCBinary) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCDe depNames.CrtEnd = "ndk_crtend_android." + c.Properties.Sdk_version } - if c.BinaryProperties.Static_executable { + if Bool(c.BinaryProperties.Static_executable) { if c.stl(ctx) == "libc++_static" { depNames.StaticLibs = append(depNames.StaticLibs, "libm", "libc", "libdl") } @@ -1419,9 +1420,9 @@ func CCBinaryFactory() (blueprint.Module, []interface{}) { func (c *CCBinary) ModifyProperties(ctx common.AndroidBaseContext) { if ctx.Darwin() { - c.BinaryProperties.Static_executable = false + c.BinaryProperties.Static_executable = proptools.BoolPtr(false) } - if c.BinaryProperties.Static_executable { + if Bool(c.BinaryProperties.Static_executable) { c.dynamicProperties.VariantIsStaticBinary = true } } @@ -1432,7 +1433,7 @@ func (c *CCBinary) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags flags.CFlags = append(flags.CFlags, "-fpie") if ctx.Device() { - if c.BinaryProperties.Static_executable { + if Bool(c.BinaryProperties.Static_executable) { // Clang driver needs -static to create static executable. // However, bionic/linker uses -shared to overwrite. // Linker for x86 targets does not allow coexistance of -static and -shared, @@ -1471,7 +1472,7 @@ func (c *CCBinary) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags func (c *CCBinary) compileModule(ctx common.AndroidModuleContext, flags CCFlags, deps CCDeps, objFiles []string) { - if !c.BinaryProperties.Static_executable && inList("libc", c.Properties.Static_libs) { + if !Bool(c.BinaryProperties.Static_executable) && inList("libc", c.Properties.Static_libs) { ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" + "from static libs or set static_executable: true") } @@ -1504,7 +1505,7 @@ func (c *CCBinary) HostToolPath() string { } func (c *CCBinary) testPerSrc() bool { - return c.BinaryProperties.Test_per_src + return Bool(c.BinaryProperties.Test_per_src) } func (c *CCBinary) binary() *CCBinary { @@ -1938,3 +1939,5 @@ func lastUniqueElements(list []string) []string { } return list[totalSkip:] } + +var Bool = proptools.Bool diff --git a/common/arch.go b/common/arch.go index 4dd01c30a..05945672e 100644 --- a/common/arch.go +++ b/common/arch.go @@ -426,6 +426,38 @@ func InitArchModule(m AndroidModule, defaultMultilib Multilib, var dashToUnderscoreReplacer = strings.NewReplacer("-", "_") +func (a *AndroidModuleBase) appendProperties(ctx blueprint.EarlyMutatorContext, + dst, src interface{}, field, srcPrefix string) { + + src = reflect.ValueOf(src).FieldByName(field).Elem().Interface() + + filter := func(property string, + dstField, srcField reflect.StructField, + dstValue, srcValue interface{}) (bool, error) { + + srcProperty := srcPrefix + "." + property + + if !proptools.HasTag(dstField, "android", "arch_variant") { + if ctx.ContainsProperty(srcProperty) { + return false, fmt.Errorf("can't be specific to a build variant") + } else { + return false, nil + } + } + + return true, nil + } + + err := proptools.AppendProperties(dst, src, filter) + if err != nil { + if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { + ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) + } else { + panic(err) + } + } +} + // Rewrite the module's properties structs to contain arch-specific values. func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) { arch := a.commonProperties.CompileArch @@ -435,13 +467,9 @@ func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) return } - callback := func(srcPropertyName, dstPropertyName string) { - a.extendedProperties[dstPropertyName] = struct{}{} - } - for i := range a.generalProperties { - generalPropsValue := []reflect.Value{reflect.ValueOf(a.generalProperties[i]).Elem()} - + genProps := a.generalProperties[i] + archProps := a.archProperties[i] // Handle arch-specific properties in the form: // arch: { // arm64: { @@ -449,9 +477,10 @@ func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) // }, // }, t := arch.ArchType + field := proptools.FieldNameForProperty(t.Name) - extendProperties(ctx, "arch_variant", "arch."+t.Name, generalPropsValue, - reflect.ValueOf(a.archProperties[i].Arch).FieldByName(field).Elem().Elem(), callback) + prefix := "arch." + t.Name + a.appendProperties(ctx, genProps, archProps.Arch, field, prefix) // Handle arch-variant-specific properties in the form: // arch: { @@ -462,8 +491,8 @@ func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) v := dashToUnderscoreReplacer.Replace(arch.ArchVariant) if v != "" { field := proptools.FieldNameForProperty(v) - extendProperties(ctx, "arch_variant", "arch."+v, generalPropsValue, - reflect.ValueOf(a.archProperties[i].Arch).FieldByName(field).Elem().Elem(), callback) + prefix := "arch." + v + a.appendProperties(ctx, genProps, archProps.Arch, field, prefix) } // Handle cpu-variant-specific properties in the form: @@ -475,8 +504,8 @@ func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) c := dashToUnderscoreReplacer.Replace(arch.CpuVariant) if c != "" { field := proptools.FieldNameForProperty(c) - extendProperties(ctx, "arch_variant", "arch."+c, generalPropsValue, - reflect.ValueOf(a.archProperties[i].Arch).FieldByName(field).Elem().Elem(), callback) + prefix := "arch." + c + a.appendProperties(ctx, genProps, archProps.Arch, field, prefix) } // Handle multilib-specific properties in the form: @@ -485,9 +514,9 @@ func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) // key: value, // }, // }, - multilibField := proptools.FieldNameForProperty(t.Multilib) - extendProperties(ctx, "arch_variant", "multilib."+t.Multilib, generalPropsValue, - reflect.ValueOf(a.archProperties[i].Multilib).FieldByName(multilibField).Elem().Elem(), callback) + field = proptools.FieldNameForProperty(t.Multilib) + prefix = "multilib." + t.Multilib + a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix) // Handle host-or-device-specific properties in the form: // target: { @@ -496,9 +525,9 @@ func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) // }, // }, hodProperty := hod.Property() - hodField := proptools.FieldNameForProperty(hodProperty) - extendProperties(ctx, "arch_variant", "target."+hodProperty, generalPropsValue, - reflect.ValueOf(a.archProperties[i].Target).FieldByName(hodField).Elem().Elem(), callback) + field = proptools.FieldNameForProperty(hodProperty) + prefix = "target." + hodProperty + a.appendProperties(ctx, genProps, archProps.Target, field, prefix) // Handle host target properties in the form: // target: { @@ -527,15 +556,18 @@ func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) if hod.Host() { for _, v := range osList { if v.goos == runtime.GOOS { - extendProperties(ctx, "arch_variant", "target."+v.goos, generalPropsValue, - reflect.ValueOf(a.archProperties[i].Target).FieldByName(v.field).Elem().Elem(), callback) + field := v.field + prefix := "target." + v.goos + a.appendProperties(ctx, genProps, archProps.Target, field, prefix) t := arch.ArchType - extendProperties(ctx, "arch_variant", "target."+v.goos+"_"+t.Name, generalPropsValue, - reflect.ValueOf(a.archProperties[i].Target).FieldByName(v.field+"_"+t.Name).Elem().Elem(), callback) + field = v.field + "_" + t.Name + prefix = "target." + v.goos + "_" + t.Name + a.appendProperties(ctx, genProps, archProps.Target, field, prefix) } } - extendProperties(ctx, "arch_variant", "target.not_windows", generalPropsValue, - reflect.ValueOf(a.archProperties[i].Target).FieldByName("Not_windows").Elem().Elem(), callback) + field := "Not_windows" + prefix := "target.not_windows" + a.appendProperties(ctx, genProps, archProps.Target, field, prefix) } // Handle 64-bit device properties in the form: @@ -553,11 +585,13 @@ func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) // debuggerd that need to know when they are a 32-bit process running on a 64-bit device if hod.Device() { if true /* && target_is_64_bit */ { - extendProperties(ctx, "arch_variant", "target.android64", generalPropsValue, - reflect.ValueOf(a.archProperties[i].Target).FieldByName("Android64").Elem().Elem(), callback) + field := "Android64" + prefix := "target.android64" + a.appendProperties(ctx, genProps, archProps.Target, field, prefix) } else { - extendProperties(ctx, "arch_variant", "target.android32", generalPropsValue, - reflect.ValueOf(a.archProperties[i].Target).FieldByName("Android32").Elem().Elem(), callback) + field := "Android32" + prefix := "target.android32" + a.appendProperties(ctx, genProps, archProps.Target, field, prefix) } } @@ -572,8 +606,9 @@ func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) // }, if hod.Device() { t := arch.ArchType - extendProperties(ctx, "arch_variant", "target.android_"+t.Name, generalPropsValue, - reflect.ValueOf(a.archProperties[i].Target).FieldByName("Android_"+t.Name).Elem().Elem(), callback) + field := "Android_" + t.Name + prefix := "target.android_" + t.Name + a.appendProperties(ctx, genProps, archProps.Target, field, prefix) } if ctx.Failed() { diff --git a/common/extend.go b/common/extend.go deleted file mode 100644 index f2d061bde..000000000 --- a/common/extend.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package common - -import ( - "fmt" - "reflect" - "strings" - - "github.com/google/blueprint" - "github.com/google/blueprint/proptools" -) - -// TODO: move this to proptools -func extendProperties(ctx blueprint.EarlyMutatorContext, - requiredTag, srcPrefix string, dstValues []reflect.Value, srcValue reflect.Value, - callback func(string, string)) { - if srcPrefix != "" { - srcPrefix += "." - } - extendPropertiesRecursive(ctx, requiredTag, srcValue, dstValues, srcPrefix, "", callback) -} - -func extendPropertiesRecursive(ctx blueprint.EarlyMutatorContext, requiredTag string, - srcValue reflect.Value, dstValues []reflect.Value, srcPrefix, dstPrefix string, - callback func(string, string)) { - - typ := srcValue.Type() - for i := 0; i < srcValue.NumField(); i++ { - srcField := typ.Field(i) - if srcField.PkgPath != "" { - // The field is not exported so just skip it. - continue - } - - localPropertyName := proptools.PropertyNameForField(srcField.Name) - srcPropertyName := srcPrefix + localPropertyName - srcFieldValue := srcValue.Field(i) - - if !ctx.ContainsProperty(srcPropertyName) { - continue - } - - found := false - for _, dstValue := range dstValues { - dstField, ok := dstValue.Type().FieldByName(srcField.Name) - if !ok { - continue - } - - dstFieldValue := dstValue.FieldByIndex(dstField.Index) - - if srcFieldValue.Type() != dstFieldValue.Type() { - panic(fmt.Errorf("can't extend mismatching types for %q (%s <- %s)", - srcPropertyName, dstFieldValue.Type(), srcFieldValue.Type())) - } - - dstPropertyName := dstPrefix + localPropertyName - - if requiredTag != "" { - tag := dstField.Tag.Get("android") - tags := map[string]bool{} - for _, entry := range strings.Split(tag, ",") { - if entry != "" { - tags[entry] = true - } - } - - if !tags[requiredTag] { - ctx.PropertyErrorf(srcPropertyName, "property can't be specific to a build variant") - continue - } - } - - if callback != nil { - callback(srcPropertyName, dstPropertyName) - } - - found = true - - switch srcFieldValue.Kind() { - case reflect.Bool: - // Replace the original value. - dstFieldValue.Set(srcFieldValue) - case reflect.String: - // Append the extension string. - dstFieldValue.SetString(dstFieldValue.String() + - srcFieldValue.String()) - case reflect.Slice: - dstFieldValue.Set(reflect.AppendSlice(dstFieldValue, srcFieldValue)) - case reflect.Interface: - if dstFieldValue.IsNil() != srcFieldValue.IsNil() { - panic(fmt.Errorf("can't extend field %q: nilitude mismatch", srcPropertyName)) - } - if dstFieldValue.IsNil() { - continue - } - - dstFieldValue = dstFieldValue.Elem() - srcFieldValue = srcFieldValue.Elem() - - if dstFieldValue.Type() != srcFieldValue.Type() { - panic(fmt.Errorf("can't extend field %q: type mismatch", srcPropertyName)) - } - if srcFieldValue.Kind() != reflect.Ptr { - panic(fmt.Errorf("can't extend field %q: interface not a pointer", srcPropertyName)) - } - fallthrough - case reflect.Ptr: - if dstFieldValue.IsNil() != srcFieldValue.IsNil() { - panic(fmt.Errorf("can't extend field %q: nilitude mismatch", srcPropertyName)) - } - if dstFieldValue.IsNil() { - continue - } - - dstFieldValue = dstFieldValue.Elem() - srcFieldValue = srcFieldValue.Elem() - - if dstFieldValue.Type() != srcFieldValue.Type() { - panic(fmt.Errorf("can't extend field %q: type mismatch", srcPropertyName)) - } - if srcFieldValue.Kind() != reflect.Struct { - panic(fmt.Errorf("can't extend field %q: pointer not to a struct", srcPropertyName)) - } - fallthrough - case reflect.Struct: - // Recursively extend the struct's fields. - extendPropertiesRecursive(ctx, requiredTag, srcFieldValue, []reflect.Value{dstFieldValue}, - srcPropertyName+".", srcPropertyName+".", callback) - default: - panic(fmt.Errorf("unexpected kind for property struct field %q: %s", - srcPropertyName, srcFieldValue.Kind())) - } - } - if !found { - ctx.PropertyErrorf(srcPropertyName, "failed to find property to extend") - } - } -} diff --git a/common/module.go b/common/module.go index feaba83d4..d31a9fc23 100644 --- a/common/module.go +++ b/common/module.go @@ -123,7 +123,6 @@ func InitAndroidModule(m AndroidModule, base := m.base() base.module = m - base.extendedProperties = make(map[string]struct{}) propertyStructs = append(propertyStructs, &base.commonProperties, &base.variableProperties) @@ -198,7 +197,6 @@ type AndroidModuleBase struct { hostAndDeviceProperties hostAndDeviceProperties generalProperties []interface{} archProperties []*archProperties - extendedProperties map[string]struct{} noAddressSanitizer bool installFiles []string @@ -340,9 +338,8 @@ func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) { hod: a.commonProperties.CompileHostOrDevice, config: ctx.Config().(Config), }, - installDeps: a.computeInstallDeps(ctx), - installFiles: a.installFiles, - extendedProperties: a.extendedProperties, + installDeps: a.computeInstallDeps(ctx), + installFiles: a.installFiles, } if a.commonProperties.Disabled { @@ -373,10 +370,9 @@ type androidBaseContextImpl struct { type androidModuleContext struct { blueprint.ModuleContext androidBaseContextImpl - installDeps []string - installFiles []string - checkbuildFiles []string - extendedProperties map[string]struct{} + installDeps []string + installFiles []string + checkbuildFiles []string } func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) { @@ -384,14 +380,6 @@ func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blue a.ModuleContext.Build(pctx, params) } -func (a *androidModuleContext) ContainsProperty(property string) bool { - if a.ModuleContext.ContainsProperty(property) { - return true - } - _, ok := a.extendedProperties[property] - return ok -} - func (a *androidBaseContextImpl) Arch() Arch { return a.arch } diff --git a/common/variable.go b/common/variable.go index 23a97a6d9..39496810d 100644 --- a/common/variable.go +++ b/common/variable.go @@ -113,7 +113,7 @@ func VariableMutator(mctx blueprint.EarlyMutatorContext) { // TODO: depend on config variable, create variants, propagate variants up tree a := module.base() - variableValues := reflect.ValueOf(a.variableProperties.Product_variables) + variableValues := reflect.ValueOf(&a.variableProperties.Product_variables).Elem() zeroValues := reflect.ValueOf(zeroProductVariables.Product_variables) for i := 0; i < variableValues.NumField(); i++ { @@ -147,16 +147,19 @@ func VariableMutator(mctx blueprint.EarlyMutatorContext) { func (a *AndroidModuleBase) setVariableProperties(ctx blueprint.EarlyMutatorContext, prefix string, productVariablePropertyValue reflect.Value, variableValue interface{}) { - generalPropertyValues := make([]reflect.Value, len(a.generalProperties)) - for i := range a.generalProperties { - generalPropertyValues[i] = reflect.ValueOf(a.generalProperties[i]).Elem() - } - if variableValue != nil { printfIntoProperties(productVariablePropertyValue, variableValue) } - extendProperties(ctx, "", prefix, generalPropertyValues, productVariablePropertyValue, nil) + err := proptools.AppendMatchingProperties(a.generalProperties, + productVariablePropertyValue.Addr().Interface(), nil) + if err != nil { + if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { + ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) + } else { + panic(err) + } + } } func printfIntoProperties(productVariablePropertyValue reflect.Value, variableValue interface{}) {