18f840c45e
java_sdk_library modules in builds with AllowMissingDependencies may be missing defaults modules that cause them to look for api files that they normally wouldn't need. Move the error to runtime so it doesn't block the build unless the branch tries to build that module. Test: prebuilts/build-tools/build-prebuilts.sh in aosp-build-tools Change-Id: I279b0cd8493779f972c0ac02235967c10b35a5a0
315 lines
9.8 KiB
Go
315 lines
9.8 KiB
Go
// 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 android
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/google/blueprint"
|
|
"github.com/google/blueprint/proptools"
|
|
)
|
|
|
|
type defaultsDependencyTag struct {
|
|
blueprint.BaseDependencyTag
|
|
}
|
|
|
|
var DefaultsDepTag defaultsDependencyTag
|
|
|
|
type defaultsProperties struct {
|
|
Defaults []string
|
|
}
|
|
|
|
type DefaultableModuleBase struct {
|
|
defaultsProperties defaultsProperties
|
|
defaultableProperties []interface{}
|
|
defaultableVariableProperties interface{}
|
|
|
|
// The optional hook to call after any defaults have been applied.
|
|
hook DefaultableHook
|
|
}
|
|
|
|
func (d *DefaultableModuleBase) defaults() *defaultsProperties {
|
|
return &d.defaultsProperties
|
|
}
|
|
|
|
func (d *DefaultableModuleBase) setProperties(props []interface{}, variableProperties interface{}) {
|
|
d.defaultableProperties = props
|
|
d.defaultableVariableProperties = variableProperties
|
|
}
|
|
|
|
func (d *DefaultableModuleBase) SetDefaultableHook(hook DefaultableHook) {
|
|
d.hook = hook
|
|
}
|
|
|
|
func (d *DefaultableModuleBase) callHookIfAvailable(ctx DefaultableHookContext) {
|
|
if d.hook != nil {
|
|
d.hook(ctx)
|
|
}
|
|
}
|
|
|
|
// Interface that must be supported by any module to which defaults can be applied.
|
|
type Defaultable interface {
|
|
// Get a pointer to the struct containing the Defaults property.
|
|
defaults() *defaultsProperties
|
|
|
|
// Set the property structures into which defaults will be added.
|
|
setProperties(props []interface{}, variableProperties interface{})
|
|
|
|
// Apply defaults from the supplied Defaults to the property structures supplied to
|
|
// setProperties(...).
|
|
applyDefaults(TopDownMutatorContext, []Defaults)
|
|
|
|
// Set the hook to be called after any defaults have been applied.
|
|
//
|
|
// Should be used in preference to a AddLoadHook when the behavior of the load
|
|
// hook is dependent on properties supplied in the Android.bp file.
|
|
SetDefaultableHook(hook DefaultableHook)
|
|
|
|
// Call the hook if specified.
|
|
callHookIfAvailable(context DefaultableHookContext)
|
|
}
|
|
|
|
type DefaultableModule interface {
|
|
Module
|
|
Defaultable
|
|
}
|
|
|
|
var _ Defaultable = (*DefaultableModuleBase)(nil)
|
|
|
|
func InitDefaultableModule(module DefaultableModule) {
|
|
if module.(Module).base().module == nil {
|
|
panic("InitAndroidModule must be called before InitDefaultableModule")
|
|
}
|
|
module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties)
|
|
|
|
module.AddProperties(module.defaults())
|
|
|
|
module.base().customizableProperties = module.GetProperties()
|
|
}
|
|
|
|
// A restricted subset of context methods, similar to LoadHookContext.
|
|
type DefaultableHookContext interface {
|
|
EarlyModuleContext
|
|
|
|
CreateModule(ModuleFactory, ...interface{}) Module
|
|
AddMissingDependencies(missingDeps []string)
|
|
}
|
|
|
|
type DefaultableHook func(ctx DefaultableHookContext)
|
|
|
|
// The Defaults_visibility property.
|
|
type DefaultsVisibilityProperties struct {
|
|
|
|
// Controls the visibility of the defaults module itself.
|
|
Defaults_visibility []string
|
|
}
|
|
|
|
type DefaultsModuleBase struct {
|
|
DefaultableModuleBase
|
|
}
|
|
|
|
// The common pattern for defaults modules is to register separate instances of
|
|
// the xxxProperties structs in the AddProperties calls, rather than reusing the
|
|
// ones inherited from Module.
|
|
//
|
|
// The effect is that e.g. myDefaultsModuleInstance.base().xxxProperties won't
|
|
// contain the values that have been set for the defaults module. Rather, to
|
|
// retrieve the values it is necessary to iterate over properties(). E.g. to get
|
|
// the commonProperties instance that have the real values:
|
|
//
|
|
// d := myModule.(Defaults)
|
|
// for _, props := range d.properties() {
|
|
// if cp, ok := props.(*commonProperties); ok {
|
|
// ... access property values in cp ...
|
|
// }
|
|
// }
|
|
//
|
|
// The rationale is that the properties on a defaults module apply to the
|
|
// defaultable modules using it, not to the defaults module itself. E.g. setting
|
|
// the "enabled" property false makes inheriting modules disabled by default,
|
|
// rather than disabling the defaults module itself.
|
|
type Defaults interface {
|
|
Defaultable
|
|
|
|
// Although this function is unused it is actually needed to ensure that only modules that embed
|
|
// DefaultsModuleBase will type-assert to the Defaults interface.
|
|
isDefaults() bool
|
|
|
|
// Get the structures containing the properties for which defaults can be provided.
|
|
properties() []interface{}
|
|
|
|
productVariableProperties() interface{}
|
|
}
|
|
|
|
func (d *DefaultsModuleBase) isDefaults() bool {
|
|
return true
|
|
}
|
|
|
|
type DefaultsModule interface {
|
|
Module
|
|
Defaults
|
|
}
|
|
|
|
func (d *DefaultsModuleBase) properties() []interface{} {
|
|
return d.defaultableProperties
|
|
}
|
|
|
|
func (d *DefaultsModuleBase) productVariableProperties() interface{} {
|
|
return d.defaultableVariableProperties
|
|
}
|
|
|
|
func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {
|
|
}
|
|
|
|
func InitDefaultsModule(module DefaultsModule) {
|
|
commonProperties := &commonProperties{}
|
|
|
|
module.AddProperties(
|
|
&hostAndDeviceProperties{},
|
|
commonProperties,
|
|
&ApexProperties{},
|
|
&distProperties{})
|
|
|
|
initAndroidModuleBase(module)
|
|
initProductVariableModule(module)
|
|
initArchModule(module)
|
|
InitDefaultableModule(module)
|
|
|
|
// Add properties that will not have defaults applied to them.
|
|
base := module.base()
|
|
defaultsVisibility := &DefaultsVisibilityProperties{}
|
|
module.AddProperties(&base.nameProperties, defaultsVisibility)
|
|
|
|
// Unlike non-defaults modules the visibility property is not stored in m.base().commonProperties.
|
|
// Instead it is stored in a separate instance of commonProperties created above so clear the
|
|
// existing list of properties.
|
|
clearVisibilityProperties(module)
|
|
|
|
// The defaults_visibility property controls the visibility of a defaults module so it must be
|
|
// set as the primary property, which also adds it to the list.
|
|
setPrimaryVisibilityProperty(module, "defaults_visibility", &defaultsVisibility.Defaults_visibility)
|
|
|
|
// The visibility property needs to be checked (but not parsed) by the visibility module during
|
|
// its checking phase and parsing phase so add it to the list as a normal property.
|
|
AddVisibilityProperty(module, "visibility", &commonProperties.Visibility)
|
|
|
|
// The applicable licenses property for defaults is 'licenses'.
|
|
setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
|
|
|
|
base.module = module
|
|
}
|
|
|
|
var _ Defaults = (*DefaultsModuleBase)(nil)
|
|
|
|
func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
|
|
defaultsList []Defaults) {
|
|
|
|
for _, defaults := range defaultsList {
|
|
for _, prop := range defaultable.defaultableProperties {
|
|
if prop == defaultable.defaultableVariableProperties {
|
|
defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
|
|
} else {
|
|
defaultable.applyDefaultProperties(ctx, defaults, prop)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Product variable properties need special handling, the type of the filtered product variable
|
|
// property struct may not be identical between the defaults module and the defaultable module.
|
|
// Use PrependMatchingProperties to apply whichever properties match.
|
|
func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
|
|
defaults Defaults, defaultableProp interface{}) {
|
|
if defaultableProp == nil {
|
|
return
|
|
}
|
|
|
|
defaultsProp := defaults.productVariableProperties()
|
|
if defaultsProp == nil {
|
|
return
|
|
}
|
|
|
|
dst := []interface{}{
|
|
defaultableProp,
|
|
// Put an empty copy of the src properties into dst so that properties in src that are not in dst
|
|
// don't cause a "failed to find property to extend" error.
|
|
proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
|
|
}
|
|
|
|
err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
|
|
if err != nil {
|
|
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
|
|
ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
|
|
} else {
|
|
panic(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
|
|
defaults Defaults, defaultableProp interface{}) {
|
|
|
|
for _, def := range defaults.properties() {
|
|
if proptools.TypeEqual(defaultableProp, def) {
|
|
err := proptools.PrependProperties(defaultableProp, def, nil)
|
|
if err != nil {
|
|
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
|
|
ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
|
|
} else {
|
|
panic(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
|
|
ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
|
|
ctx.TopDown("defaults", defaultsMutator).Parallel()
|
|
}
|
|
|
|
func defaultsDepsMutator(ctx BottomUpMutatorContext) {
|
|
if defaultable, ok := ctx.Module().(Defaultable); ok {
|
|
ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
|
|
}
|
|
}
|
|
|
|
func defaultsMutator(ctx TopDownMutatorContext) {
|
|
if defaultable, ok := ctx.Module().(Defaultable); ok {
|
|
if len(defaultable.defaults().Defaults) > 0 {
|
|
var defaultsList []Defaults
|
|
seen := make(map[Defaults]bool)
|
|
|
|
ctx.WalkDeps(func(module, parent Module) bool {
|
|
if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
|
|
if defaults, ok := module.(Defaults); ok {
|
|
if !seen[defaults] {
|
|
seen[defaults] = true
|
|
defaultsList = append(defaultsList, defaults)
|
|
return len(defaults.defaults().Defaults) > 0
|
|
}
|
|
} else {
|
|
ctx.PropertyErrorf("defaults", "module %s is not an defaults module",
|
|
ctx.OtherModuleName(module))
|
|
}
|
|
}
|
|
return false
|
|
})
|
|
defaultable.applyDefaults(ctx, defaultsList)
|
|
}
|
|
|
|
defaultable.callHookIfAvailable(ctx)
|
|
}
|
|
}
|