Files
build_soong/android/mutator.go
Martin Stjernholm 710ec3aef2 Add FinalDeps mutator phase, where CreateVariations is disallowed.
This is for use to add dependencies between specific module variants,
without getting the dependencies potentially duplicated as more
variants are created.

Moved genrule tool dependency registration to this phase, to avoid
potential splitting of its dependencies, and for consistency with the
same kind of dependency on dex2oat in https://r.android.com/1205730.

Test: m nothing
Bug: 145934348
Change-Id: I1f9e75354e359cef5f41d14e5016b0a67d7655d7
2020-01-21 11:40:02 +00:00

368 lines
11 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,
// Rename package module types.
RegisterPackageRenamer,
RegisterPrebuiltsPreArchMutators,
RegisterVisibilityRuleChecker,
RegisterDefaultsPreArchMutators,
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)
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 depsMutator(ctx BottomUpMutatorContext) {
if m, ok := ctx.Module().(Module); ok && 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).Elem()).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) AliasVariation(variationName string) {
b.bp.AliasVariation(variationName)
}