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
This commit is contained in:
Martin Stjernholm 2020-01-16 15:12:04 +00:00
parent dca59a516d
commit 710ec3aef2
6 changed files with 163 additions and 14 deletions

View File

@ -27,6 +27,7 @@ import (
// 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) {
@ -43,7 +44,7 @@ func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) {
}
}
func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps []RegisterMutatorFunc) {
func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) {
mctx := &registerMutatorsContext{}
register := func(funcs []RegisterMutatorFunc) {
@ -60,11 +61,15 @@ func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps []Regis
register(postDeps)
mctx.finalPhase = true
register(finalDeps)
registerMutatorsToContext(ctx, mctx.mutators)
}
type registerMutatorsContext struct {
mutators []*mutator
mutators []*mutator
finalPhase bool
}
type RegisterMutatorsContext interface {
@ -102,6 +107,8 @@ var postDeps = []RegisterMutatorFunc{
RegisterOverridePostDepsMutators,
}
var finalDeps = []RegisterMutatorFunc{}
func PreArchMutators(f RegisterMutatorFunc) {
preArch = append(preArch, f)
}
@ -114,6 +121,10 @@ func PostDepsMutators(f RegisterMutatorFunc) {
postDeps = append(postDeps, f)
}
func FinalDepsMutators(f RegisterMutatorFunc) {
finalDeps = append(finalDeps, f)
}
type TopDownMutator func(TopDownMutatorContext)
type TopDownMutatorContext interface {
@ -156,14 +167,17 @@ type BottomUpMutatorContext interface {
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)
}
@ -285,6 +299,10 @@ func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, t
}
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))
@ -299,6 +317,10 @@ func (b *bottomUpMutatorContext) CreateVariations(variations ...string) []Module
}
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))

View File

@ -15,9 +15,12 @@
package android
import (
"fmt"
"reflect"
"strings"
"testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@ -185,3 +188,110 @@ func TestModuleString(t *testing.T) {
t.Errorf("want module String() values:\n%q\ngot:\n%q", want, moduleStrings)
}
}
func TestFinalDepsPhase(t *testing.T) {
ctx := NewTestContext()
finalGot := map[string]int{}
dep1Tag := struct {
blueprint.BaseDependencyTag
}{}
dep2Tag := struct {
blueprint.BaseDependencyTag
}{}
ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
ctx.BottomUp("far_deps_1", func(ctx BottomUpMutatorContext) {
if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1")
}
})
ctx.BottomUp("variant", func(ctx BottomUpMutatorContext) {
ctx.CreateLocalVariations("a", "b")
})
})
ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
ctx.BottomUp("far_deps_2", func(ctx BottomUpMutatorContext) {
if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep2Tag, "common_dep_2")
}
})
ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
finalGot[ctx.Module().String()] += 1
ctx.VisitDirectDeps(func(mod Module) {
finalGot[fmt.Sprintf("%s -> %s", ctx.Module().String(), mod)] += 1
})
})
})
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
bp := `
test {
name: "common_dep_1",
}
test {
name: "common_dep_2",
}
test {
name: "foo",
}
`
config := TestConfig(buildDir, nil, bp, nil)
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
FailIfErrored(t, errs)
finalWant := map[string]int{
"common_dep_1{variant:a}": 1,
"common_dep_1{variant:b}": 1,
"common_dep_2{variant:a}": 1,
"common_dep_2{variant:b}": 1,
"foo{variant:a}": 1,
"foo{variant:a} -> common_dep_1{variant:a}": 1,
"foo{variant:a} -> common_dep_2{variant:a}": 1,
"foo{variant:b}": 1,
"foo{variant:b} -> common_dep_1{variant:b}": 1,
"foo{variant:b} -> common_dep_2{variant:a}": 1,
}
if !reflect.DeepEqual(finalWant, finalGot) {
t.Errorf("want:\n%q\ngot:\n%q", finalWant, finalGot)
}
}
func TestNoCreateVariationsInFinalDeps(t *testing.T) {
ctx := NewTestContext()
checkErr := func() {
if err := recover(); err == nil || !strings.Contains(fmt.Sprintf("%s", err), "not allowed in FinalDepsMutators") {
panic("Expected FinalDepsMutators consistency check to fail")
}
}
ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
ctx.BottomUp("vars", func(ctx BottomUpMutatorContext) {
defer checkErr()
ctx.CreateVariations("a", "b")
})
ctx.BottomUp("local_vars", func(ctx BottomUpMutatorContext) {
defer checkErr()
ctx.CreateLocalVariations("a", "b")
})
})
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
config := TestConfig(buildDir, nil, `test {name: "foo"}`, nil)
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
FailIfErrored(t, errs)
}

View File

@ -102,7 +102,7 @@ func (ctx *Context) Register() {
ctx.RegisterSingletonType(t.name, t.factory)
}
registerMutators(ctx.Context, preArch, preDeps, postDeps)
registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
// Register makevars after other singletons so they can export values through makevars
ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc))
@ -135,6 +135,7 @@ type RegistrationContext interface {
PreDepsMutators(f RegisterMutatorFunc)
PostDepsMutators(f RegisterMutatorFunc)
FinalDepsMutators(f RegisterMutatorFunc)
}
// Used to register build components from an init() method, e.g.
@ -197,3 +198,7 @@ func (ctx *initRegistrationContext) PreDepsMutators(f RegisterMutatorFunc) {
func (ctx *initRegistrationContext) PostDepsMutators(f RegisterMutatorFunc) {
PostDepsMutators(f)
}
func (ctx *initRegistrationContext) FinalDepsMutators(f RegisterMutatorFunc) {
FinalDepsMutators(f)
}

View File

@ -50,9 +50,9 @@ func NewTestArchContext() *TestContext {
type TestContext struct {
*Context
preArch, preDeps, postDeps []RegisterMutatorFunc
NameResolver *NameResolver
config Config
preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
NameResolver *NameResolver
config Config
}
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@ -72,12 +72,16 @@ func (ctx *TestContext) PostDepsMutators(f RegisterMutatorFunc) {
ctx.postDeps = append(ctx.postDeps, f)
}
func (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) {
ctx.finalDeps = append(ctx.finalDeps, f)
}
func (ctx *TestContext) Register(config Config) {
ctx.SetFs(config.fs)
if config.mockBpList != "" {
ctx.SetModuleListFile(config.mockBpList)
}
registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps)
registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
ctx.RegisterSingletonType("env", EnvSingleton)

View File

@ -30,10 +30,18 @@ import (
)
func init() {
android.RegisterModuleType("genrule_defaults", defaultsFactory)
registerGenruleBuildComponents(android.InitRegistrationContext)
}
android.RegisterModuleType("gensrcs", GenSrcsFactory)
android.RegisterModuleType("genrule", GenRuleFactory)
func registerGenruleBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
ctx.RegisterModuleType("gensrcs", GenSrcsFactory)
ctx.RegisterModuleType("genrule", GenRuleFactory)
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("genrule_tool_deps", toolDepsMutator).Parallel()
})
}
var (
@ -166,7 +174,7 @@ func (g *Module) GeneratedDeps() android.Paths {
return g.outputDeps
}
func (g *Module) DepsMutator(ctx android.BottomUpMutatorContext) {
func toolDepsMutator(ctx android.BottomUpMutatorContext) {
if g, ok := ctx.Module().(*Module); ok {
for _, tool := range g.properties.Tools {
tag := hostToolDependencyTag{label: tool}

View File

@ -55,10 +55,10 @@ func testContext(config android.Config) *android.TestContext {
ctx := android.NewTestArchContext()
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("genrule", GenRuleFactory)
ctx.RegisterModuleType("gensrcs", GenSrcsFactory)
ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
ctx.RegisterModuleType("tool", toolFactory)
registerGenruleBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.Register(config)