Store SingletonMakeVarsProviders in the config

Store SingletonMakeVarsProviders in the config instead of a global
variable to avoid races between tests running in parallel.

Test: all soong tests
Change-Id: I2ab64f368b5ac673fd985399d4421ed018abc562
This commit is contained in:
Colin Cross 2020-10-29 18:21:38 -07:00
parent beab64ea81
commit 06fa588d1a
4 changed files with 35 additions and 44 deletions

View File

@ -139,15 +139,24 @@ type SingletonMakeVarsProvider interface {
MakeVars(ctx MakeVarsContext) MakeVars(ctx MakeVarsContext)
} }
// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to the list of var singletonMakeVarsProvidersKey = NewOnceKey("singletonMakeVarsProvidersKey")
// MakeVarsProviders to run.
func registerSingletonMakeVarsProvider(singleton SingletonMakeVarsProvider) { // registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to
singletonMakeVarsProviders = append(singletonMakeVarsProviders, // the list of MakeVarsProviders to run.
makeVarsProvider{pctx, SingletonmakeVarsProviderAdapter(singleton)}) func registerSingletonMakeVarsProvider(config Config, singleton SingletonMakeVarsProvider) {
// Singletons are registered on the Context and may be different between different Contexts,
// for example when running multiple tests. Store the SingletonMakeVarsProviders in the
// Config so they are attached to the Context.
singletonMakeVarsProviders := config.Once(singletonMakeVarsProvidersKey, func() interface{} {
return &[]makeVarsProvider{}
}).(*[]makeVarsProvider)
*singletonMakeVarsProviders = append(*singletonMakeVarsProviders,
makeVarsProvider{pctx, singletonMakeVarsProviderAdapter(singleton)})
} }
// SingletonmakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider. // singletonMakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
func SingletonmakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider { func singletonMakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider {
return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) } return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
} }
@ -175,9 +184,6 @@ type makeVarsProvider struct {
// Collection of makevars providers that are registered in init() methods. // Collection of makevars providers that are registered in init() methods.
var makeVarsInitProviders []makeVarsProvider var makeVarsInitProviders []makeVarsProvider
// Collection of singleton makevars providers that are not registered as part of init() methods.
var singletonMakeVarsProviders []makeVarsProvider
type makeVarsContext struct { type makeVarsContext struct {
SingletonContext SingletonContext
config Config config Config
@ -224,7 +230,11 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
var vars []makeVarsVariable var vars []makeVarsVariable
var dists []dist var dists []dist
var phonies []phony var phonies []phony
for _, provider := range append(makeVarsInitProviders) {
providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
providers = append(providers, *ctx.Config().Get(singletonMakeVarsProvidersKey).(*[]makeVarsProvider)...)
for _, provider := range providers {
mctx := &makeVarsContext{ mctx := &makeVarsContext{
SingletonContext: ctx, SingletonContext: ctx,
pctx: provider.pctx, pctx: provider.pctx,
@ -237,25 +247,6 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
dists = append(dists, mctx.dists...) dists = append(dists, mctx.dists...)
} }
for _, provider := range append(singletonMakeVarsProviders) {
mctx := &makeVarsContext{
SingletonContext: ctx,
pctx: provider.pctx,
}
provider.call(mctx)
vars = append(vars, mctx.vars...)
phonies = append(phonies, mctx.phonies...)
dists = append(dists, mctx.dists...)
}
// Clear singleton makevars providers after use. Since these are in-memory
// singletons, this ensures state is reset if the build tree is processed
// multiple times.
// TODO(cparsons): Clean up makeVarsProviders to be part of the context.
singletonMakeVarsProviders = nil
ctx.VisitAllModules(func(m Module) { ctx.VisitAllModules(func(m Module) {
if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled() { if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled() {
mctx := &makeVarsContext{ mctx := &makeVarsContext{

View File

@ -29,7 +29,7 @@ var moduleTypes []moduleType
type singleton struct { type singleton struct {
name string name string
factory blueprint.SingletonFactory factory SingletonFactory
} }
var singletons []singleton var singletons []singleton
@ -57,11 +57,11 @@ type SingletonFactory func() Singleton
// SingletonFactoryAdaptor wraps a SingletonFactory into a blueprint.SingletonFactory by converting // SingletonFactoryAdaptor wraps a SingletonFactory into a blueprint.SingletonFactory by converting
// a Singleton into a blueprint.Singleton // a Singleton into a blueprint.Singleton
func SingletonFactoryAdaptor(factory SingletonFactory) blueprint.SingletonFactory { func SingletonFactoryAdaptor(ctx *Context, factory SingletonFactory) blueprint.SingletonFactory {
return func() blueprint.Singleton { return func() blueprint.Singleton {
singleton := factory() singleton := factory()
if makevars, ok := singleton.(SingletonMakeVarsProvider); ok { if makevars, ok := singleton.(SingletonMakeVarsProvider); ok {
registerSingletonMakeVarsProvider(makevars) registerSingletonMakeVarsProvider(ctx.config, makevars)
} }
return &singletonAdaptor{Singleton: singleton} return &singletonAdaptor{Singleton: singleton}
} }
@ -72,11 +72,11 @@ func RegisterModuleType(name string, factory ModuleFactory) {
} }
func RegisterSingletonType(name string, factory SingletonFactory) { func RegisterSingletonType(name string, factory SingletonFactory) {
singletons = append(singletons, singleton{name, SingletonFactoryAdaptor(factory)}) singletons = append(singletons, singleton{name, factory})
} }
func RegisterPreSingletonType(name string, factory SingletonFactory) { func RegisterPreSingletonType(name string, factory SingletonFactory) {
preSingletons = append(preSingletons, singleton{name, SingletonFactoryAdaptor(factory)}) preSingletons = append(preSingletons, singleton{name, factory})
} }
type Context struct { type Context struct {
@ -92,7 +92,7 @@ func NewContext(config Config) *Context {
func (ctx *Context) Register() { func (ctx *Context) Register() {
for _, t := range preSingletons { for _, t := range preSingletons {
ctx.RegisterPreSingletonType(t.name, t.factory) ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
} }
for _, t := range moduleTypes { for _, t := range moduleTypes {
@ -100,21 +100,21 @@ func (ctx *Context) Register() {
} }
for _, t := range singletons { for _, t := range singletons {
ctx.RegisterSingletonType(t.name, t.factory) ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
} }
registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps) registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(BazelSingleton)) ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(ctx, BazelSingleton))
// Register phony just before makevars so it can write out its phony rules as Make rules // Register phony just before makevars so it can write out its phony rules as Make rules
ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory)) ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(ctx, phonySingletonFactory))
// Register makevars after other singletons so they can export values through makevars // Register makevars after other singletons so they can export values through makevars
ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc)) ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(ctx, makeVarsSingletonFunc))
// Register env last so that it can track all used environment variables // Register env last so that it can track all used environment variables
ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(EnvSingleton)) ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(ctx, EnvSingleton))
} }
func ModuleTypeFactories() map[string]ModuleFactory { func ModuleTypeFactories() map[string]ModuleFactory {

View File

@ -104,7 +104,7 @@ func (ctx *TestContext) RegisterModuleType(name string, factory ModuleFactory) {
} }
func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) { func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(factory)) ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
} }
func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule { func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {

View File

@ -92,8 +92,8 @@ func testContext(config android.Config) *android.TestContext {
ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators) ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators) ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory)) ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(ctx.Context, OverlaySingletonFactory))
ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory)) ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(ctx.Context, sdkPreSingletonFactory))
android.RegisterPrebuiltMutators(ctx) android.RegisterPrebuiltMutators(ctx)