From 5353744f1d0068559bb2ae4980066f126f035e0e Mon Sep 17 00:00:00 2001 From: "Lukacs T. Berki" Date: Fri, 12 Mar 2021 08:31:19 +0100 Subject: [PATCH] Remove global variables from Blueprint. The end goal of this exercise is to remove all mutable global state so that multiple Blueprint instances can be run in the same process. This is done by plumbing the necessary data through the configuration. Test: Presubmit. Change-Id: I040a461ae17705258b882b3a44740a4dd5027a2c --- bootstrap/bootstrap.go | 8 ++++---- bootstrap/cleanup.go | 6 +++--- bootstrap/command.go | 11 ++++++----- bootstrap/config.go | 15 ++++++++++----- bootstrap/glob.go | 6 +++--- bootstrap/minibp/main.go | 26 +++++++++++++++++++------- bootstrap/writedocs.go | 8 ++++---- 7 files changed, 49 insertions(+), 31 deletions(-) diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go index c64e42c..1a42551 100644 --- a/bootstrap/bootstrap.go +++ b/bootstrap/bootstrap.go @@ -163,7 +163,7 @@ var ( "depfile") _ = pctx.VariableFunc("BinDir", func(config interface{}) (string, error) { - return bootstrapBinDir(), nil + return bootstrapBinDir(config), nil }) _ = pctx.VariableFunc("ToolDir", func(config interface{}) (string, error) { @@ -186,15 +186,15 @@ type GoBinaryTool interface { isGoBinary() } -func bootstrapBinDir() string { - return filepath.Join(BuildDir, bootstrapSubDir, "bin") +func bootstrapBinDir(config interface{}) string { + return filepath.Join(config.(BootstrapConfig).BuildDir(), bootstrapSubDir, "bin") } func toolDir(config interface{}) string { if c, ok := config.(ConfigBlueprintToolLocation); ok { return filepath.Join(c.BlueprintToolLocation()) } - return filepath.Join(BuildDir, "bin") + return filepath.Join(config.(BootstrapConfig).BuildDir(), "bin") } func pluginDeps(ctx blueprint.BottomUpMutatorContext) { diff --git a/bootstrap/cleanup.go b/bootstrap/cleanup.go index 6444081..9dbea2a 100644 --- a/bootstrap/cleanup.go +++ b/bootstrap/cleanup.go @@ -31,8 +31,8 @@ const logFileName = ".ninja_log" // removeAbandonedFilesUnder removes any files that appear in the Ninja log, and // are prefixed with one of the `under` entries, but that are not currently // build targets, or in `exempt` -func removeAbandonedFilesUnder(ctx *blueprint.Context, config *Config, - srcDir string, under, exempt []string) error { +func removeAbandonedFilesUnder(ctx *blueprint.Context, + srcDir, buildDir string, under, exempt []string) error { if len(under) == 0 { return nil @@ -50,7 +50,7 @@ func removeAbandonedFilesUnder(ctx *blueprint.Context, config *Config, replacer := strings.NewReplacer( "@@SrcDir@@", srcDir, - "@@BuildDir@@", BuildDir) + "@@BuildDir@@", buildDir) ninjaBuildDir = replacer.Replace(ninjaBuildDir) targets := make(map[string]bool) for target := range targetRules { diff --git a/bootstrap/command.go b/bootstrap/command.go index 01e449f..85446fc 100644 --- a/bootstrap/command.go +++ b/bootstrap/command.go @@ -43,11 +43,12 @@ var ( useValidations bool noGC bool emptyNinjaFile bool + absSrcDir string + BuildDir string ModuleListFile string NinjaBuildDir string SrcDir string - absSrcDir string ) func init() { @@ -121,7 +122,7 @@ func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...stri } stage := StageMain - if c, ok := config.(ConfigInterface); ok { + if c, ok := config.(interface{ GeneratingPrimaryBuilder() bool }); ok { if c.GeneratingPrimaryBuilder() { stage = StagePrimary } @@ -160,7 +161,7 @@ func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...stri deps = append(deps, extraDeps...) if docFile != "" { - err := writeDocs(ctx, absolutePath(docFile)) + err := writeDocs(ctx, config, absolutePath(docFile)) if err != nil { fatalErrors([]error{err}) } @@ -208,7 +209,7 @@ func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...stri } if globFile != "" { - buffer, errs := generateGlobNinjaFile(ctx.Globs) + buffer, errs := generateGlobNinjaFile(config, ctx.Globs) if len(errs) > 0 { fatalErrors(errs) } @@ -247,7 +248,7 @@ func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...stri if c, ok := config.(ConfigRemoveAbandonedFilesUnder); ok { under, except := c.RemoveAbandonedFilesUnder() - err := removeAbandonedFilesUnder(ctx, bootstrapConfig, SrcDir, under, except) + err := removeAbandonedFilesUnder(ctx, SrcDir, BuildDir, under, except) if err != nil { fatalf("error removing abandoned files: %s", err) } diff --git a/bootstrap/config.go b/bootstrap/config.go index d83b042..5873da8 100644 --- a/bootstrap/config.go +++ b/bootstrap/config.go @@ -61,11 +61,16 @@ var ( }) ) -type ConfigInterface interface { - // GeneratingPrimaryBuilder should return true if this build invocation is - // creating a .bootstrap/build.ninja file to be used to build the - // primary builder - GeneratingPrimaryBuilder() bool +type BootstrapConfig interface { + // The top-level directory of the source tree + SrcDir() string + + // The directory where files emitted during bootstrapping are located. + // Usually NinjaBuildDir() + "/soong". + BuildDir() string + + // The output directory for the build. + NinjaBuildDir() string } type ConfigRemoveAbandonedFilesUnder interface { diff --git a/bootstrap/glob.go b/bootstrap/glob.go index cf5af72..db7f37f 100644 --- a/bootstrap/glob.go +++ b/bootstrap/glob.go @@ -146,7 +146,7 @@ func (s *globSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) { } } -func generateGlobNinjaFile(globLister func() []blueprint.GlobPath) ([]byte, []error) { +func generateGlobNinjaFile(config interface{}, globLister func() []blueprint.GlobPath) ([]byte, []error) { ctx := blueprint.NewContext() ctx.RegisterSingletonType("glob", func() blueprint.Singleton { return &globSingleton{ @@ -155,7 +155,7 @@ func generateGlobNinjaFile(globLister func() []blueprint.GlobPath) ([]byte, []er } }) - extraDeps, errs := ctx.ResolveDependencies(nil) + extraDeps, errs := ctx.ResolveDependencies(config) if len(extraDeps) > 0 { return nil, []error{fmt.Errorf("shouldn't have extra deps")} } @@ -163,7 +163,7 @@ func generateGlobNinjaFile(globLister func() []blueprint.GlobPath) ([]byte, []er return nil, errs } - extraDeps, errs = ctx.PrepareBuildActions(nil) + extraDeps, errs = ctx.PrepareBuildActions(config) if len(extraDeps) > 0 { return nil, []error{fmt.Errorf("shouldn't have extra deps")} } diff --git a/bootstrap/minibp/main.go b/bootstrap/minibp/main.go index 1714739..781f13a 100644 --- a/bootstrap/minibp/main.go +++ b/bootstrap/minibp/main.go @@ -30,18 +30,29 @@ func init() { } type Config struct { - generatingPrimaryBuilder bool + buildDir string + ninjaBuildDir string } func (c Config) GeneratingPrimaryBuilder() bool { - return c.generatingPrimaryBuilder + return true +} + +func (c Config) SrcDir() string { + return "." +} + +func (c Config) BuildDir() string { + return c.buildDir +} + +func (c Config) NinjaBuildDir() string { + return c.ninjaBuildDir } func (c Config) RemoveAbandonedFilesUnder() (under, exempt []string) { - if c.generatingPrimaryBuilder { - under = []string{filepath.Join(bootstrap.BuildDir, ".bootstrap")} - exempt = []string{filepath.Join(bootstrap.BuildDir, ".bootstrap", "build.ninja")} - } + under = []string{filepath.Join(bootstrap.BuildDir, ".bootstrap")} + exempt = []string{filepath.Join(bootstrap.BuildDir, ".bootstrap", "build.ninja")} return } @@ -54,7 +65,8 @@ func main() { } config := Config{ - generatingPrimaryBuilder: !runAsPrimaryBuilder, + buildDir: bootstrap.BuildDir, + ninjaBuildDir: bootstrap.NinjaBuildDir, } bootstrap.Main(ctx, config) diff --git a/bootstrap/writedocs.go b/bootstrap/writedocs.go index 4edbcab..99df32f 100644 --- a/bootstrap/writedocs.go +++ b/bootstrap/writedocs.go @@ -15,7 +15,7 @@ import ( // ModuleTypeDocs returns a list of bpdoc.ModuleType objects that contain information relevant // to generating documentation for module types supported by the primary builder. -func ModuleTypeDocs(ctx *blueprint.Context, factories map[string]reflect.Value) ([]*bpdoc.Package, error) { +func ModuleTypeDocs(ctx *blueprint.Context, config interface{}, factories map[string]reflect.Value) ([]*bpdoc.Package, error) { // Find the module that's marked as the "primary builder", which means it's // creating the binary that we'll use to generate the non-bootstrap // build.ninja file. @@ -55,7 +55,7 @@ func ModuleTypeDocs(ctx *blueprint.Context, factories map[string]reflect.Value) switch m := module.(type) { case (*goPackage): pkgFiles[m.properties.PkgPath] = pathtools.PrefixPaths(m.properties.Srcs, - filepath.Join(SrcDir, ctx.ModuleDir(m))) + filepath.Join(config.(BootstrapConfig).SrcDir(), ctx.ModuleDir(m))) default: panic(fmt.Errorf("unknown dependency type %T", module)) } @@ -75,8 +75,8 @@ func ModuleTypeDocs(ctx *blueprint.Context, factories map[string]reflect.Value) return bpdoc.AllPackages(pkgFiles, mergedFactories, ctx.ModuleTypePropertyStructs()) } -func writeDocs(ctx *blueprint.Context, filename string) error { - moduleTypeList, err := ModuleTypeDocs(ctx, nil) +func writeDocs(ctx *blueprint.Context, config interface{}, filename string) error { + moduleTypeList, err := ModuleTypeDocs(ctx, config, nil) if err != nil { return err }