diff --git a/android/mutator.go b/android/mutator.go index b0230011d..8bfb24ed3 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -33,22 +33,8 @@ import ( // 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() - } - } -} - // RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing. -func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) { +func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) { mctx := ®isterMutatorsContext{ bazelConversionMode: true, } @@ -80,10 +66,10 @@ func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, preArchMutators, f(mctx) } - registerMutatorsToContext(ctx, mctx.mutators) + mctx.mutators.registerAll(ctx) } -func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) { +func registerMutators(ctx *Context, preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) { mctx := ®isterMutatorsContext{} register := func(funcs []RegisterMutatorFunc) { @@ -103,11 +89,11 @@ func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps, finalD mctx.finalPhase = true register(finalDeps) - registerMutatorsToContext(ctx, mctx.mutators) + mctx.mutators.registerAll(ctx) } type registerMutatorsContext struct { - mutators []*mutator + mutators sortableComponents finalPhase bool bazelConversionMode bool } @@ -473,6 +459,23 @@ func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) Mutator return mutator } +func (mutator *mutator) componentName() string { + return mutator.name +} + +func (mutator *mutator) register(ctx *Context) { + blueprintCtx := ctx.Context + var handle blueprint.MutatorHandle + if mutator.bottomUpMutator != nil { + handle = blueprintCtx.RegisterBottomUpMutator(mutator.name, mutator.bottomUpMutator) + } else if mutator.topDownMutator != nil { + handle = blueprintCtx.RegisterTopDownMutator(mutator.name, mutator.topDownMutator) + } + if mutator.parallel { + handle.Parallel() + } +} + type MutatorHandle interface { Parallel() MutatorHandle } diff --git a/android/register.go b/android/register.go index 47df9729e..5efa280cc 100644 --- a/android/register.go +++ b/android/register.go @@ -21,21 +21,78 @@ import ( "github.com/google/blueprint" ) +// A sortable component is one whose registration order affects the order in which it is executed +// and so affects the behavior of the build system. As a result it is important for the order in +// which they are registered during tests to match the order used at runtime and so the test +// infrastructure will sort them to match. +// +// The sortable components are mutators, singletons and pre-singletons. Module types are not +// sortable because their order of registration does not affect the runtime behavior. +type sortableComponent interface { + // componentName returns the name of the component. + // + // Uniquely identifies the components within the set of components used at runtimr and during + // tests. + componentName() string + + // register registers this component in the supplied context. + register(ctx *Context) +} + +type sortableComponents []sortableComponent + +// registerAll registers all components in this slice with the supplied context. +func (r sortableComponents) registerAll(ctx *Context) { + for _, c := range r { + c.register(ctx) + } +} + type moduleType struct { name string factory ModuleFactory } +func (t moduleType) register(ctx *Context) { + ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory)) +} + var moduleTypes []moduleType var moduleTypesForDocs = map[string]reflect.Value{} type singleton struct { + // True if this should be registered as a pre-singleton, false otherwise. + pre bool + name string factory SingletonFactory } -var singletons []singleton -var preSingletons []singleton +func newSingleton(name string, factory SingletonFactory) singleton { + return singleton{false, name, factory} +} + +func newPreSingleton(name string, factory SingletonFactory) singleton { + return singleton{true, name, factory} +} + +func (s singleton) componentName() string { + return s.name +} + +func (s singleton) register(ctx *Context) { + adaptor := SingletonFactoryAdaptor(ctx, s.factory) + if s.pre { + ctx.RegisterPreSingletonType(s.name, adaptor) + } else { + ctx.RegisterSingletonType(s.name, adaptor) + } +} + +var _ sortableComponent = singleton{} + +var singletons sortableComponents +var preSingletons sortableComponents type mutator struct { name string @@ -44,6 +101,8 @@ type mutator struct { parallel bool } +var _ sortableComponent = &mutator{} + type ModuleFactory func() Module // ModuleFactoryAdaptor wraps a ModuleFactory into a blueprint.ModuleFactory by converting a Module @@ -84,11 +143,11 @@ func RegisterModuleTypeForDocs(name string, factory reflect.Value) { } func RegisterSingletonType(name string, factory SingletonFactory) { - singletons = append(singletons, singleton{name, factory}) + singletons = append(singletons, newSingleton(name, factory)) } func RegisterPreSingletonType(name string, factory SingletonFactory) { - preSingletons = append(preSingletons, singleton{name, factory}) + preSingletons = append(preSingletons, newPreSingleton(name, factory)) } type Context struct { @@ -107,33 +166,29 @@ func NewContext(config Config) *Context { // files to semantically equivalent BUILD files. func (ctx *Context) RegisterForBazelConversion() { for _, t := range moduleTypes { - ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory)) + t.register(ctx) } // Required for SingletonModule types, even though we are not using them. for _, t := range singletons { - ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory)) + t.register(ctx) } - RegisterMutatorsForBazelConversion(ctx.Context, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators) + RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators) } // Register the pipeline of singletons, module types, and mutators for // generating build.ninja and other files for Kati, from Android.bp files. func (ctx *Context) Register() { - for _, t := range preSingletons { - ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory)) - } + preSingletons.registerAll(ctx) for _, t := range moduleTypes { - ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory)) + t.register(ctx) } - for _, t := range singletons { - ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory)) - } + singletons.registerAll(ctx) - registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps) + registerMutators(ctx, preArch, preDeps, postDeps, finalDeps) ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(ctx, BazelSingleton)) diff --git a/android/testing.go b/android/testing.go index d8c123bba..556db7863 100644 --- a/android/testing.go +++ b/android/testing.go @@ -141,14 +141,14 @@ func (ctx *TestContext) DepsBp2BuildMutators(f RegisterMutatorFunc) { } func (ctx *TestContext) Register() { - registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps) + registerMutators(ctx.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps) ctx.RegisterSingletonType("env", EnvSingleton) } // RegisterForBazelConversion prepares a test context for bp2build conversion. func (ctx *TestContext) RegisterForBazelConversion() { - RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators) + RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators) } func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {