Merge "Add sortableComponent abstraction"
diff --git a/android/mutator.go b/android/mutator.go
index b023001..8bfb24e 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -33,22 +33,8 @@
// 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 @@
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 @@
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 @@
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 47df972..5efa280 100644
--- a/android/register.go
+++ b/android/register.go
@@ -21,21 +21,78 @@
"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 @@
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 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 @@
// 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 d8c123b..556db78 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -141,14 +141,14 @@
}
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) {