From 18926521dc71b70d656caf9f50ac98f0101f8867 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 3 Sep 2020 12:34:49 -0700 Subject: [PATCH 1/2] Make VisitAllModuleVariants, PrimaryModule and FinalModule available to mutators Move the VisitAllModuleVariants, PrimaryModule and FinalModule methods to baseModuleContext so they can be used by mutators. Test: m checkbuild Change-Id: I1827ce2fc75f017460a7f6a53b1dab6a81109435 --- module_ctx.go | 60 +++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/module_ctx.go b/module_ctx.go index 28578e0..c992c0a 100644 --- a/module_ctx.go +++ b/module_ctx.go @@ -246,6 +246,24 @@ type BaseModuleContext interface { // invalidated by future mutators. WalkDeps(visit func(Module, Module) bool) + // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in + // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the + // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are + // only done once for all variants of a module. + PrimaryModule() Module + + // FinalModule returns the last variant of the current module. Variants of a module are always visited in + // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all + // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform + // singleton actions that are only done once for all variants of a module. + FinalModule() Module + + // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always + // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read + // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any + // data modified by the current mutator. + VisitAllModuleVariants(visit func(Module)) + // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information. // It is intended for use inside the visit functions of Visit* and WalkDeps. OtherModuleName(m Module) string @@ -309,24 +327,6 @@ type ModuleContext interface { // Build creates a new ninja build statement. Build(pctx PackageContext, params BuildParams) - // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in - // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the - // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are - // only done once for all variants of a module. - PrimaryModule() Module - - // FinalModule returns the last variant of the current module. Variants of a module are always visited in - // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all - // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform - // singleton actions that are only done once for all variants of a module. - FinalModule() Module - - // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always - // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read - // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any - // data modified by the current mutator. - VisitAllModuleVariants(visit func(Module)) - // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods, // but do not exist. It can be used with Context.SetAllowMissingDependencies to allow the primary builder to // handle missing dependencies on its own instead of having Blueprint treat them as an error. @@ -642,6 +642,18 @@ func (m *baseModuleContext) WalkDeps(visit func(child, parent Module) bool) { m.visitingDep = depInfo{} } +func (m *baseModuleContext) PrimaryModule() Module { + return m.module.group.modules[0].logicModule +} + +func (m *baseModuleContext) FinalModule() Module { + return m.module.group.modules[len(m.module.group.modules)-1].logicModule +} + +func (m *baseModuleContext) VisitAllModuleVariants(visit func(Module)) { + m.context.visitAllModuleVariants(m.module, visit) +} + func (m *baseModuleContext) AddNinjaFileDeps(deps ...string) { m.ninjaFileDeps = append(m.ninjaFileDeps, deps...) } @@ -695,18 +707,6 @@ func (m *moduleContext) Build(pctx PackageContext, params BuildParams) { m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def) } -func (m *moduleContext) PrimaryModule() Module { - return m.module.group.modules[0].logicModule -} - -func (m *moduleContext) FinalModule() Module { - return m.module.group.modules[len(m.module.group.modules)-1].logicModule -} - -func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) { - m.context.visitAllModuleVariants(m.module, visit) -} - func (m *moduleContext) GetMissingDependencies() []string { m.handledMissingDeps = true return m.module.missingDeps From d2458a23bf292a5d9707ff0971855201f58dc841 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 9 Sep 2020 13:03:57 -0700 Subject: [PATCH 2/2] Enable variants of bootstrap modules The primary builder may want to create variants of bootstrap modules if they need to fit in to the primary builder's dependency graph. Enable arbitrary variants of bootstrap modules by only running the module's actions on the primary variant and then copying the result to any other variants that exist. Test: m checkbuild Change-Id: I24b97771bb11faeacab4079ed8cf69aef59da140 --- bootstrap/bootstrap.go | 46 +++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go index 8a9a5f8..64fa8e5 100644 --- a/bootstrap/bootstrap.go +++ b/bootstrap/bootstrap.go @@ -180,8 +180,10 @@ func toolDir(config interface{}) string { func pluginDeps(ctx blueprint.BottomUpMutatorContext) { if pkg, ok := ctx.Module().(*goPackage); ok { - for _, plugin := range pkg.properties.PluginFor { - ctx.AddReverseDependency(ctx.Module(), nil, plugin) + if ctx.PrimaryModule() == ctx.Module() { + for _, plugin := range pkg.properties.PluginFor { + ctx.AddReverseDependency(ctx.Module(), nil, plugin) + } } } } @@ -211,7 +213,7 @@ func isGoPluginFor(name string) func(blueprint.Module) bool { } } -func isBootstrapModule(module blueprint.Module) bool { +func IsBootstrapModule(module blueprint.Module) bool { _, isPackage := module.(*goPackage) _, isBinary := module.(*goBinary) return isPackage || isBinary @@ -268,6 +270,9 @@ func newGoPackageModuleFactory(config *Config) func() (blueprint.Module, []inter } func (g *goPackage) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string { + if ctx.Module() != ctx.PrimaryModule() { + return nil + } return g.properties.Deps } @@ -297,6 +302,16 @@ func (g *goPackage) IsPluginFor(name string) bool { } func (g *goPackage) GenerateBuildActions(ctx blueprint.ModuleContext) { + // Allow the primary builder to create multiple variants. Any variants after the first + // will copy outputs from the first. + if ctx.Module() != ctx.PrimaryModule() { + primary := ctx.PrimaryModule().(*goPackage) + g.pkgRoot = primary.pkgRoot + g.archiveFile = primary.archiveFile + g.testResultFile = primary.testResultFile + return + } + var ( name = ctx.ModuleName() hasPlugins = false @@ -386,6 +401,9 @@ func newGoBinaryModuleFactory(config *Config, tooldir bool) func() (blueprint.Mo } func (g *goBinary) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string { + if ctx.Module() != ctx.PrimaryModule() { + return nil + } return g.properties.Deps } @@ -395,6 +413,14 @@ func (g *goBinary) InstallPath() string { } func (g *goBinary) GenerateBuildActions(ctx blueprint.ModuleContext) { + // Allow the primary builder to create multiple variants. Any variants after the first + // will copy outputs from the first. + if ctx.Module() != ctx.PrimaryModule() { + primary := ctx.PrimaryModule().(*goBinary) + g.installPath = primary.installPath + return + } + var ( name = ctx.ModuleName() objDir = moduleObjDir(ctx, g.config) @@ -653,13 +679,15 @@ func (s *singleton) GenerateBuildActions(ctx blueprint.SingletonContext) { var blueprintTools []string ctx.VisitAllModulesIf(isBootstrapBinaryModule, func(module blueprint.Module) { - binaryModule := module.(*goBinary) + if ctx.PrimaryModule(module) == module { + binaryModule := module.(*goBinary) - if binaryModule.properties.Tool_dir { - blueprintTools = append(blueprintTools, binaryModule.InstallPath()) - } - if binaryModule.properties.PrimaryBuilder { - primaryBuilders = append(primaryBuilders, binaryModule) + if binaryModule.properties.Tool_dir { + blueprintTools = append(blueprintTools, binaryModule.InstallPath()) + } + if binaryModule.properties.PrimaryBuilder { + primaryBuilders = append(primaryBuilders, binaryModule) + } } })