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.
This commit is contained in:
Colin Cross 2015-10-29 15:32:56 -07:00
parent 45021dcbbd
commit 763b6f18fa
3 changed files with 87 additions and 150 deletions

View file

@ -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)

View file

@ -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

View file

@ -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)
}