diff --git a/android/mutator.go b/android/mutator.go index f2f966399..3d1bb4f7d 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -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 := ®isterMutatorsContext{} 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)) diff --git a/android/mutator_test.go b/android/mutator_test.go index d179f9d4b..191b535a3 100644 --- a/android/mutator_test.go +++ b/android/mutator_test.go @@ -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) +} diff --git a/android/register.go b/android/register.go index d5aa1a537..ccfe01e74 100644 --- a/android/register.go +++ b/android/register.go @@ -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) +} diff --git a/android/testing.go b/android/testing.go index c07af7f32..9aff03940 100644 --- a/android/testing.go +++ b/android/testing.go @@ -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) diff --git a/genrule/genrule.go b/genrule/genrule.go index 57ca9bc6f..c5aaed29c 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -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} diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go index ea49e0891..7eb43ac9d 100644 --- a/genrule/genrule_test.go +++ b/genrule/genrule_test.go @@ -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)