diff --git a/Android.bp b/Android.bp index bb9ab74c3..355dfd2e2 100644 --- a/Android.bp +++ b/Android.bp @@ -94,6 +94,7 @@ bootstrap_go_package { "android/androidmk.go", "android/arch.go", "android/config.go", + "android/customizer.go", "android/defaults.go", "android/defs.go", "android/glob.go", diff --git a/android/arch.go b/android/arch.go index 2d38dafc1..62acb09d8 100644 --- a/android/arch.go +++ b/android/arch.go @@ -24,13 +24,6 @@ import ( "github.com/google/blueprint/proptools" ) -func init() { - RegisterBottomUpMutator("defaults_deps", defaultsDepsMutator).Parallel() - RegisterTopDownMutator("defaults", defaultsMutator).Parallel() - - RegisterBottomUpMutator("arch", ArchMutator).Parallel() -} - var ( Arm = newArch("arm", "lib32") Arm64 = newArch("arm64", "lib64") @@ -490,6 +483,8 @@ func InitArchModule(m Module, allProperties = append(allProperties, asp) } + base.customizableProperties = allProperties + return m, allProperties } diff --git a/android/customizer.go b/android/customizer.go new file mode 100644 index 000000000..056880dab --- /dev/null +++ b/android/customizer.go @@ -0,0 +1,77 @@ +// Copyright 2016 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 android + +import "github.com/google/blueprint/proptools" + +type CustomizePropertiesContext interface { + BaseContext + AppendProperties(...interface{}) + PrependProperties(...interface{}) +} + +type customizePropertiesContext struct { + BaseContext + + module *ModuleBase +} + +type PropertyCustomizer interface { + CustomizeProperties(CustomizePropertiesContext) +} + +func customizerMutator(ctx TopDownMutatorContext) { + if m, ok := ctx.Module().(Module); ok { + a := m.base() + if len(a.customizers) > 0 { + mctx := &customizePropertiesContext{ + BaseContext: ctx, + module: a, + } + for _, c := range a.customizers { + c.CustomizeProperties(mctx) + if mctx.Failed() { + return + } + } + } + } +} + +func (ctx *customizePropertiesContext) AppendProperties(props ...interface{}) { + for _, p := range props { + err := proptools.AppendMatchingProperties(ctx.module.customizableProperties, p, nil) + if err != nil { + if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { + ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) + } else { + panic(err) + } + } + } +} + +func (ctx *customizePropertiesContext) PrependProperties(props ...interface{}) { + for _, p := range props { + err := proptools.PrependMatchingProperties(ctx.module.customizableProperties, p, nil) + if err != nil { + if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { + ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) + } else { + panic(err) + } + } + } +} diff --git a/android/module.go b/android/module.go index 03c06b42f..fd37ca85c 100644 --- a/android/module.go +++ b/android/module.go @@ -25,6 +25,14 @@ import ( "github.com/google/blueprint" ) +func init() { + RegisterTopDownMutator("customizer", customizerMutator).Parallel() + RegisterBottomUpMutator("defaults_deps", defaultsDepsMutator).Parallel() + RegisterTopDownMutator("defaults", defaultsMutator).Parallel() + + RegisterBottomUpMutator("arch", ArchMutator).Parallel() +} + var ( DeviceSharedLibrary = "shared_library" DeviceStaticLibrary = "static_library" @@ -188,6 +196,11 @@ func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib return InitArchModule(m, propertyStructs...) } +func AddCustomizer(m blueprint.Module, c PropertyCustomizer) { + base := m.(Module).base() + base.customizers = append(base.customizers, c) +} + // A AndroidModuleBase object contains the properties that are common to all Android // modules. It should be included as an anonymous field in every module // struct definition. InitAndroidModule should then be called from the module's @@ -238,6 +251,7 @@ type ModuleBase struct { hostAndDeviceProperties hostAndDeviceProperties generalProperties []interface{} archProperties []*archProperties + customizableProperties []interface{} noAddressSanitizer bool installFiles Paths @@ -248,6 +262,8 @@ type ModuleBase struct { installTarget string checkbuildTarget string blueprintDir string + + customizers []PropertyCustomizer } func (a *ModuleBase) base() *ModuleBase {