From 763b6f18fa865a52f64fda453f471ee02f63a50a Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 29 Oct 2015 15:32:56 -0700 Subject: [PATCH] Deprecate EarlyMutator and DynamicDependencies DynamicDependencies can be implemented more flexibly by a BottomUpMutator. If there are no DynamicDependencies, then EarlyMutators are identical to BottomUpMutators. Deperecate both, and reimplement DynamicDependencies inside a BottomUpMutator that is guaranteed to be registered first. --- context.go | 109 ++++++++++++--------------------------------- context_test.go | 12 +---- module_ctx.go | 116 ++++++++++++++++++++++++------------------------ 3 files changed, 87 insertions(+), 150 deletions(-) diff --git a/context.go b/context.go index 982cf72..ee9beb6 100644 --- a/context.go +++ b/context.go @@ -224,12 +224,16 @@ func (e *Error) Error() string { // RegisterSingletonFactory methods must be called before it can do anything // useful. func NewContext() *Context { - return &Context{ + ctx := &Context{ moduleFactories: make(map[string]ModuleFactory), moduleGroups: make(map[string]*moduleGroup), moduleInfo: make(map[Module]*moduleInfo), moduleNinjaNames: make(map[string]*moduleGroup), } + + ctx.RegisterBottomUpMutator("blueprint_deps", blueprintDepsMutator) + + return ctx } // A ModuleFactory function creates a new Module object. See the @@ -402,6 +406,10 @@ func (c *Context) RegisterBottomUpMutator(name string, mutator BottomUpMutator) // // The mutator type names given here must be unique to all bottom up or early // mutators in the Context. +// +// Deprecated, use a BottomUpMutator instead. The only difference between +// EarlyMutator and BottomUpMutator is that EarlyMutator runs before the +// deprecated DynamicDependencies. func (c *Context) RegisterEarlyMutator(name string, mutator EarlyMutator) { for _, m := range c.variantMutatorNames { if m == name { @@ -1057,27 +1065,8 @@ func (c *Context) addModule(module *moduleInfo) []error { // modules defined in the parsed Blueprints files are valid. This means that // the modules depended upon are defined and that no circular dependencies // exist. -// -// The config argument is made available to all of the DynamicDependerModule -// objects via the Config method on the DynamicDependerModuleContext objects -// passed to their DynamicDependencies method. func (c *Context) ResolveDependencies(config interface{}) []error { - errs := c.runEarlyMutators(config) - if len(errs) > 0 { - return errs - } - - errs = c.resolveDependencies(config) - if len(errs) > 0 { - return errs - } - - errs = c.updateDependencies() - if len(errs) > 0 { - return errs - } - - errs = c.runMutators(config) + errs := c.runMutators(config) if len(errs) > 0 { return errs } @@ -1086,74 +1075,24 @@ func (c *Context) ResolveDependencies(config interface{}) []error { return nil } -// moduleDeps adds dependencies to a module. If the module implements the +// Default dependencies handling. If the module implements the (deprecated) // DynamicDependerModule interface then this set consists of the union of those // module names listed in its "deps" property, those returned by its // DynamicDependencies method, and those added by calling AddDependencies or // AddVariationDependencies on DynamicDependencyModuleContext. Otherwise it // is simply those names listed in its "deps" property. -func (c *Context) moduleDeps(module *moduleInfo, - config interface{}) (errs []error) { +func blueprintDepsMutator(ctx BottomUpMutatorContext) { + ctx.AddDependency(ctx.Module(), ctx.moduleInfo().properties.Deps...) - depNamesSet := make(map[string]bool) - depNames := []string{} + if dynamicDepender, ok := ctx.Module().(DynamicDependerModule); ok { + dynamicDeps := dynamicDepender.DynamicDependencies(ctx) - for _, depName := range module.properties.Deps { - if !depNamesSet[depName] { - depNamesSet[depName] = true - depNames = append(depNames, depName) + if ctx.Failed() { + return } + + ctx.AddDependency(ctx.Module(), dynamicDeps...) } - - dynamicDepender, ok := module.logicModule.(DynamicDependerModule) - if ok { - ddmctx := &dynamicDependerModuleContext{ - baseModuleContext: baseModuleContext{ - context: c, - config: config, - module: module, - }, - module: module, - } - - dynamicDeps := dynamicDepender.DynamicDependencies(ddmctx) - - if len(ddmctx.errs) > 0 { - return ddmctx.errs - } - - for _, depName := range dynamicDeps { - if !depNamesSet[depName] { - depNamesSet[depName] = true - depNames = append(depNames, depName) - } - } - } - - for _, depName := range depNames { - newErrs := c.addDependency(module, depName) - if len(newErrs) > 0 { - errs = append(errs, newErrs...) - } - } - return errs -} - -// resolveDependencies populates the directDeps list for every module. In doing so it checks for -// missing dependencies and self-dependant modules. -func (c *Context) resolveDependencies(config interface{}) (errs []error) { - for _, group := range c.moduleGroups { - for _, module := range group.modules { - module.directDeps = make([]*moduleInfo, 0, len(module.properties.Deps)) - - newErrs := c.moduleDeps(module, config) - if len(newErrs) > 0 { - errs = append(errs, newErrs...) - } - } - } - - return } // findMatchingVariant searches the moduleGroup for a module with the same variant as module, @@ -1545,10 +1484,20 @@ func (c *Context) runEarlyMutators(config interface{}) (errs []error) { } } + errs = c.updateDependencies() + if len(errs) > 0 { + return errs + } + return nil } func (c *Context) runMutators(config interface{}) (errs []error) { + errs = c.runEarlyMutators(config) + if len(errs) > 0 { + return errs + } + for _, mutator := range c.mutatorInfo { if mutator.topDownMutator != nil { errs = c.runTopDownMutator(config, mutator.name, mutator.topDownMutator) diff --git a/context_test.go b/context_test.go index 8877be9..acf0c1c 100644 --- a/context_test.go +++ b/context_test.go @@ -92,7 +92,7 @@ func TestContextParse(t *testing.T) { t.FailNow() } - errs = ctx.resolveDependencies(nil) + errs = ctx.ResolveDependencies(nil) if len(errs) > 0 { t.Errorf("unexpected dep errors:") for _, err := range errs { @@ -100,16 +100,6 @@ func TestContextParse(t *testing.T) { } t.FailNow() } - - errs = ctx.updateDependencies() - if len(errs) > 0 { - t.Errorf("unexpected dep cycle errors:") - for _, err := range errs { - t.Errorf(" %s", err) - } - t.FailNow() - } - } // |---B===D - represents a non-walkable edge diff --git a/module_ctx.go b/module_ctx.go index 94db01e..7af26d2 100644 --- a/module_ctx.go +++ b/module_ctx.go @@ -34,10 +34,11 @@ import ( // // The Module implementation can access the build configuration as well as any // modules on which on which it depends (as defined by the "deps" property -// specified in the Blueprints file or dynamically added by implementing the -// DynamicDependerModule interface) using the ModuleContext passed to -// GenerateBuildActions. This ModuleContext is also used to create Ninja build -// actions and to report errors to the user. +// specified in the Blueprints file, dynamically added by implementing the +// (deprecated) DynamicDependerModule interface, or dynamically added by a +// BottomUpMutator) using the ModuleContext passed to GenerateBuildActions. +// This ModuleContext is also used to create Ninja build actions and to report +// errors to the user. // // In addition to implementing the GenerateBuildActions method, a Module should // implement methods that provide dependant modules and singletons information @@ -93,6 +94,8 @@ type Module interface { // appear in its "deps" property. Any Module that implements this interface // will have its DynamicDependencies method called by the Context that created // it during generate phase. +// +// Deprecated, use a BottomUpMutator instead type DynamicDependerModule interface { Module @@ -114,14 +117,11 @@ type BaseModuleContext interface { ModuleErrorf(fmt string, args ...interface{}) PropertyErrorf(property, fmt string, args ...interface{}) Failed() bool + + moduleInfo() *moduleInfo } -type DynamicDependerModuleContext interface { - BaseModuleContext - - AddVariationDependencies([]Variation, ...string) - AddFarVariationDependencies([]Variation, ...string) -} +type DynamicDependerModuleContext BottomUpMutatorContext type ModuleContext interface { BaseModuleContext @@ -157,6 +157,10 @@ type baseModuleContext struct { errs []error } +func (d *baseModuleContext) moduleInfo() *moduleInfo { + return d.module +} + func (d *baseModuleContext) ModuleName() string { return d.module.properties.Name } @@ -315,49 +319,6 @@ func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) { } } -// -// DynamicDependerModuleContext -// - -type dynamicDependerModuleContext struct { - baseModuleContext - - module *moduleInfo -} - -// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations -// argument to select which variant of the dependency to use. A variant of the dependency must -// exist that matches the all of the non-local variations of the current module, plus the variations -// argument. -func (mctx *dynamicDependerModuleContext) AddVariationDependencies(variations []Variation, - deps ...string) { - - for _, dep := range deps { - errs := mctx.context.addVariationDependency(mctx.module, variations, dep, false) - if len(errs) > 0 { - mctx.errs = append(mctx.errs, errs...) - } - } -} - -// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the -// variations argument to select which variant of the dependency to use. A variant of the -// dependency must exist that matches the variations argument, but may also have other variations. -// For any unspecified variation the first variant will be used. -// -// Unlike AddVariationDependencies, the variations of the current module are ignored - the -// depdendency only needs to match the supplied variations. -func (mctx *dynamicDependerModuleContext) AddFarVariationDependencies(variations []Variation, - deps ...string) { - - for _, dep := range deps { - errs := mctx.context.addVariationDependency(mctx.module, variations, dep, true) - if len(errs) > 0 { - mctx.errs = append(mctx.errs, errs...) - } - } -} - // // MutatorContext // @@ -393,11 +354,13 @@ type TopDownMutatorContext interface { type BottomUpMutatorContext interface { baseMutatorContext - AddDependency(module Module, name string) + AddDependency(module Module, name ...string) AddReverseDependency(module Module, name string) CreateVariations(...string) []Module CreateLocalVariations(...string) []Module SetDependencyVariation(string) + AddVariationDependencies([]Variation, ...string) + AddFarVariationDependencies([]Variation, ...string) } // A Mutator function is called for each Module, and can use @@ -473,10 +436,12 @@ func (mctx *mutatorContext) Module() Module { // Add a dependency to the given module. // Does not affect the ordering of the current mutator pass, but will be ordered // correctly for all future mutator passes. -func (mctx *mutatorContext) AddDependency(module Module, depName string) { - errs := mctx.context.addDependency(mctx.context.moduleInfo[module], depName) - if len(errs) > 0 { - mctx.errs = append(mctx.errs, errs...) +func (mctx *mutatorContext) AddDependency(module Module, deps ...string) { + for _, dep := range deps { + errs := mctx.context.addDependency(mctx.context.moduleInfo[module], dep) + if len(errs) > 0 { + mctx.errs = append(mctx.errs, errs...) + } } } @@ -484,12 +449,45 @@ func (mctx *mutatorContext) AddDependency(module Module, depName string) { // Does not affect the ordering of the current mutator pass, but will be ordered // correctly for all future mutator passes. func (mctx *mutatorContext) AddReverseDependency(module Module, destName string) { - errs := mctx.context.addReverseDependency(mctx.context.moduleInfo[module], destName) + errs := mctx.context.addReverseDependency(mctx.module, destName) if len(errs) > 0 { mctx.errs = append(mctx.errs, errs...) } } +// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations +// argument to select which variant of the dependency to use. A variant of the dependency must +// exist that matches the all of the non-local variations of the current module, plus the variations +// argument. +func (mctx *mutatorContext) AddVariationDependencies(variations []Variation, + deps ...string) { + + for _, dep := range deps { + errs := mctx.context.addVariationDependency(mctx.module, variations, dep, false) + if len(errs) > 0 { + mctx.errs = append(mctx.errs, errs...) + } + } +} + +// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the +// variations argument to select which variant of the dependency to use. A variant of the +// dependency must exist that matches the variations argument, but may also have other variations. +// For any unspecified variation the first variant will be used. +// +// Unlike AddVariationDependencies, the variations of the current module are ignored - the +// depdendency only needs to match the supplied variations. +func (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation, + deps ...string) { + + for _, dep := range deps { + errs := mctx.context.addVariationDependency(mctx.module, variations, dep, true) + if len(errs) > 0 { + mctx.errs = append(mctx.errs, errs...) + } + } +} + func (mctx *mutatorContext) VisitDirectDeps(visit func(Module)) { mctx.context.visitDirectDeps(mctx.module, visit) }