platform_build_soong/android/mutator.go

439 lines
13 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"
)
// Phases:
// run Pre-arch mutators
// run archMutator
// run Pre-deps mutators
// run depsMutator
// run PostDeps mutators
// run FinalDeps mutators (CreateVariations disallowed in this phase)
// continue on to GenerateAndroidBuildActions
func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) {
for _, t := range mutators {
var handle blueprint.MutatorHandle
if t.bottomUpMutator != nil {
handle = ctx.RegisterBottomUpMutator(t.name, t.bottomUpMutator)
} else if t.topDownMutator != nil {
handle = ctx.RegisterTopDownMutator(t.name, t.topDownMutator)
}
if t.parallel {
handle.Parallel()
}
}
}
func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) {
mctx := &registerMutatorsContext{}
register := func(funcs []RegisterMutatorFunc) {
for _, f := range funcs {
f(mctx)
}
}
register(preArch)
register(preDeps)
mctx.BottomUp("deps", depsMutator).Parallel()
register(postDeps)
mctx.finalPhase = true
register(finalDeps)
registerMutatorsToContext(ctx, mctx.mutators)
}
type registerMutatorsContext struct {
mutators []*mutator
finalPhase bool
}
type RegisterMutatorsContext interface {
TopDown(name string, m TopDownMutator) MutatorHandle
BottomUp(name string, m BottomUpMutator) MutatorHandle
}
type RegisterMutatorFunc func(RegisterMutatorsContext)
var preArch = []RegisterMutatorFunc{
RegisterNamespaceMutator,
// Check the visibility rules are valid.
//
// This must run after the package renamer mutators so that any issues found during
// validation of the package's default_visibility property are reported using the
// correct package name and not the synthetic name.
//
// This must also be run before defaults mutators as the rules for validation are
// different before checking the rules than they are afterwards. e.g.
// visibility: ["//visibility:private", "//visibility:public"]
// would be invalid if specified in a module definition but is valid if it results
// from something like this:
//
// defaults {
// name: "defaults",
// // Be inaccessible outside a package by default.
// visibility: ["//visibility:private"]
// }
//
// defaultable_module {
// name: "defaultable_module",
// defaults: ["defaults"],
// // Override the default.
// visibility: ["//visibility:public"]
// }
//
RegisterVisibilityRuleChecker,
// Apply properties from defaults modules to the referencing modules.
//
// Any mutators that are added before this will not see any modules created by
// a DefaultableHook.
RegisterDefaultsPreArchMutators,
// Add dependencies on any components so that any component references can be
// resolved within the deps mutator.
//
// Must be run after defaults so it can be used to create dependencies on the
// component modules that are creating in a DefaultableHook.
//
// Must be run before RegisterPrebuiltsPreArchMutators, i.e. before prebuilts are
// renamed. That is so that if a module creates components using a prebuilt module
// type that any dependencies (which must use prebuilt_ prefixes) are resolved to
// the prebuilt module and not the source module.
RegisterComponentsMutator,
// Create an association between prebuilt modules and their corresponding source
// modules (if any).
//
// Must be run after defaults mutators to ensure that any modules created by
// a DefaultableHook can be either a prebuilt or a source module with a matching
// prebuilt.
RegisterPrebuiltsPreArchMutators,
// Gather the visibility rules for all modules for us during visibility enforcement.
//
// This must come after the defaults mutators to ensure that any visibility supplied
// in a defaults module has been successfully applied before the rules are gathered.
RegisterVisibilityRuleGatherer,
}
func registerArchMutator(ctx RegisterMutatorsContext) {
ctx.BottomUp("os", osMutator).Parallel()
ctx.BottomUp("image", imageMutator).Parallel()
ctx.BottomUp("arch", archMutator).Parallel()
}
var preDeps = []RegisterMutatorFunc{
registerArchMutator,
}
var postDeps = []RegisterMutatorFunc{
registerPathDepsMutator,
RegisterPrebuiltsPostDepsMutators,
RegisterVisibilityRuleEnforcer,
RegisterNeverallowMutator,
RegisterOverridePostDepsMutators,
}
var finalDeps = []RegisterMutatorFunc{}
func PreArchMutators(f RegisterMutatorFunc) {
preArch = append(preArch, f)
}
func PreDepsMutators(f RegisterMutatorFunc) {
preDeps = append(preDeps, f)
}
func PostDepsMutators(f RegisterMutatorFunc) {
postDeps = append(postDeps, f)
}
func FinalDepsMutators(f RegisterMutatorFunc) {
finalDeps = append(finalDeps, f)
}
type TopDownMutator func(TopDownMutatorContext)
type TopDownMutatorContext interface {
BaseModuleContext
MutatorName() string
Rename(name string)
CreateModule(ModuleFactory, ...interface{}) Module
}
type topDownMutatorContext struct {
bp blueprint.TopDownMutatorContext
baseModuleContext
}
type BottomUpMutator func(BottomUpMutatorContext)
type BottomUpMutatorContext interface {
BaseModuleContext
MutatorName() string
Rename(name string)
AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string)
AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string)
CreateVariations(...string) []Module
CreateLocalVariations(...string) []Module
SetDependencyVariation(string)
SetDefaultDependencyVariation(*string)
AddVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string)
AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string)
AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module)
ReplaceDependencies(string)
ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
AliasVariation(variationName string)
}
type bottomUpMutatorContext struct {
bp blueprint.BottomUpMutatorContext
baseModuleContext
finalPhase bool
}
func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) MutatorHandle {
finalPhase := x.finalPhase
f := func(ctx blueprint.BottomUpMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
actx := &bottomUpMutatorContext{
bp: ctx,
baseModuleContext: a.base().baseModuleContextFactory(ctx),
finalPhase: finalPhase,
}
m(actx)
}
}
mutator := &mutator{name: name, bottomUpMutator: f}
x.mutators = append(x.mutators, mutator)
return mutator
}
func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) MutatorHandle {
f := func(ctx blueprint.TopDownMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
actx := &topDownMutatorContext{
bp: ctx,
baseModuleContext: a.base().baseModuleContextFactory(ctx),
}
m(actx)
}
}
mutator := &mutator{name: name, topDownMutator: f}
x.mutators = append(x.mutators, mutator)
return mutator
}
type MutatorHandle interface {
Parallel() MutatorHandle
}
func (mutator *mutator) Parallel() MutatorHandle {
mutator.parallel = true
return mutator
}
func RegisterComponentsMutator(ctx RegisterMutatorsContext) {
ctx.BottomUp("component-deps", componentDepsMutator).Parallel()
}
// A special mutator that runs just prior to the deps mutator to allow the dependencies
// on component modules to be added so that they can depend directly on a prebuilt
// module.
func componentDepsMutator(ctx BottomUpMutatorContext) {
if m := ctx.Module(); m.Enabled() {
m.ComponentDepsMutator(ctx)
}
}
func depsMutator(ctx BottomUpMutatorContext) {
if m := ctx.Module(); m.Enabled() {
m.DepsMutator(ctx)
}
}
func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
for _, p := range props {
err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties,
p, nil)
if err != nil {
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
t.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
} else {
panic(err)
}
}
}
}
func (t *topDownMutatorContext) PrependProperties(props ...interface{}) {
for _, p := range props {
err := proptools.PrependMatchingProperties(t.Module().base().customizableProperties,
p, nil)
if err != nil {
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
t.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
} else {
panic(err)
}
}
}
}
// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
// has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid
// ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every
// non-overridden method has to be forwarded. There are fewer non-overridden methods, so use the latter. The following
// methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext.
func (t *topDownMutatorContext) MutatorName() string {
return t.bp.MutatorName()
}
func (t *topDownMutatorContext) Rename(name string) {
t.bp.Rename(name)
t.Module().base().commonProperties.DebugName = name
}
func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
inherited := []interface{}{&t.Module().base().commonProperties}
module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), append(inherited, props...)...).(Module)
if t.Module().base().variableProperties != nil && module.base().variableProperties != nil {
src := t.Module().base().variableProperties
dst := []interface{}{
module.base().variableProperties,
// 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(src)).Interface(),
}
err := proptools.AppendMatchingProperties(dst, src, nil)
if err != nil {
panic(err)
}
}
return module
}
func (b *bottomUpMutatorContext) MutatorName() string {
return b.bp.MutatorName()
}
func (b *bottomUpMutatorContext) Rename(name string) {
b.bp.Rename(name)
b.Module().base().commonProperties.DebugName = name
}
func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) {
b.bp.AddDependency(module, tag, name...)
}
func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) {
b.bp.AddReverseDependency(module, tag, name)
}
func (b *bottomUpMutatorContext) CreateVariations(variations ...string) []Module {
if b.finalPhase {
panic("CreateVariations not allowed in FinalDepsMutators")
}
modules := b.bp.CreateVariations(variations...)
aModules := make([]Module, len(modules))
for i := range variations {
aModules[i] = modules[i].(Module)
base := aModules[i].base()
base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
}
return aModules
}
func (b *bottomUpMutatorContext) CreateLocalVariations(variations ...string) []Module {
if b.finalPhase {
panic("CreateLocalVariations not allowed in FinalDepsMutators")
}
modules := b.bp.CreateLocalVariations(variations...)
aModules := make([]Module, len(modules))
for i := range variations {
aModules[i] = modules[i].(Module)
base := aModules[i].base()
base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
}
return aModules
}
func (b *bottomUpMutatorContext) SetDependencyVariation(variation string) {
b.bp.SetDependencyVariation(variation)
}
func (b *bottomUpMutatorContext) SetDefaultDependencyVariation(variation *string) {
b.bp.SetDefaultDependencyVariation(variation)
}
func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
names ...string) {
b.bp.AddVariationDependencies(variations, tag, names...)
}
func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation,
tag blueprint.DependencyTag, names ...string) {
b.bp.AddFarVariationDependencies(variations, tag, names...)
}
func (b *bottomUpMutatorContext) AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) {
b.bp.AddInterVariantDependency(tag, from, to)
}
func (b *bottomUpMutatorContext) ReplaceDependencies(name string) {
b.bp.ReplaceDependencies(name)
}
func (b *bottomUpMutatorContext) ReplaceDependenciesIf(name string, predicate blueprint.ReplaceDependencyPredicate) {
b.bp.ReplaceDependenciesIf(name, predicate)
}
func (b *bottomUpMutatorContext) AliasVariation(variationName string) {
b.bp.AliasVariation(variationName)
}