2015-01-23 23:15:10 +01:00
|
|
|
// Copyright 2014 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
package blueprint
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"path/filepath"
|
2014-07-03 01:40:31 +02:00
|
|
|
"text/scanner"
|
2014-05-28 01:34:41 +02:00
|
|
|
)
|
|
|
|
|
2014-09-25 05:28:11 +02:00
|
|
|
// A Module handles generating all of the Ninja build actions needed to build a
|
2014-12-19 01:28:54 +01:00
|
|
|
// single module based on properties defined in a Blueprints file. Module
|
|
|
|
// objects are initially created during the parse phase of a Context using one
|
|
|
|
// of the registered module types (and the associated ModuleFactory function).
|
|
|
|
// The Module's properties struct is automatically filled in with the property
|
|
|
|
// values specified in the Blueprints file (see Context.RegisterModuleType for more
|
2014-09-25 05:28:11 +02:00
|
|
|
// information on this).
|
|
|
|
//
|
2014-12-19 01:28:54 +01:00
|
|
|
// A Module can be split into multiple Modules by a Mutator. All existing
|
|
|
|
// properties set on the module will be duplicated to the new Module, and then
|
|
|
|
// modified as necessary by the Mutator.
|
|
|
|
//
|
2014-09-25 05:28:11 +02:00
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// In addition to implementing the GenerateBuildActions method, a Module should
|
|
|
|
// implement methods that provide dependant modules and singletons information
|
|
|
|
// they need to generate their build actions. These methods will only be called
|
|
|
|
// after GenerateBuildActions is called because the Context calls
|
|
|
|
// GenerateBuildActions in dependency-order (and singletons are invoked after
|
|
|
|
// all the Modules). The set of methods a Module supports will determine how
|
|
|
|
// dependant Modules interact with it.
|
|
|
|
//
|
|
|
|
// For example, consider a Module that is responsible for generating a library
|
|
|
|
// that other modules can link against. The library Module might implement the
|
|
|
|
// following interface:
|
|
|
|
//
|
|
|
|
// type LibraryProducer interface {
|
|
|
|
// LibraryFileName() string
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// func IsLibraryProducer(module blueprint.Module) {
|
|
|
|
// _, ok := module.(LibraryProducer)
|
|
|
|
// return ok
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// A binary-producing Module that depends on the library Module could then do:
|
|
|
|
//
|
|
|
|
// func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
|
|
|
// ...
|
|
|
|
// var libraryFiles []string
|
|
|
|
// ctx.VisitDepsDepthFirstIf(IsLibraryProducer,
|
|
|
|
// func(module blueprint.Module) {
|
|
|
|
// libProducer := module.(LibraryProducer)
|
|
|
|
// libraryFiles = append(libraryFiles, libProducer.LibraryFileName())
|
|
|
|
// })
|
|
|
|
// ...
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// to build the list of library file names that should be included in its link
|
|
|
|
// command.
|
2015-01-08 03:08:56 +01:00
|
|
|
//
|
|
|
|
// GenerateBuildActions may be called from multiple threads. It is guaranteed to
|
|
|
|
// be called after it has finished being called on all dependencies and on all
|
|
|
|
// variants of that appear earlier in the ModuleContext.VisitAllModuleVariants list.
|
|
|
|
// Any accesses to global variables or to Module objects that are not dependencies
|
|
|
|
// or variants of the current Module must be synchronized by the implementation of
|
|
|
|
// GenerateBuildActions.
|
2014-05-28 01:34:41 +02:00
|
|
|
type Module interface {
|
2014-09-25 05:28:11 +02:00
|
|
|
// GenerateBuildActions is called by the Context that created the Module
|
|
|
|
// during its generate phase. This call should generate all Ninja build
|
|
|
|
// actions (rules, pools, and build statements) needed to build the module.
|
2014-05-28 01:34:41 +02:00
|
|
|
GenerateBuildActions(ModuleContext)
|
|
|
|
}
|
|
|
|
|
2014-09-25 05:28:11 +02:00
|
|
|
// A DynamicDependerModule is a Module that may add dependencies that do not
|
|
|
|
// 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.
|
|
|
|
type DynamicDependerModule interface {
|
|
|
|
Module
|
|
|
|
|
|
|
|
// DynamicDependencies is called by the Context that created the
|
|
|
|
// DynamicDependerModule during its generate phase. This call should return
|
|
|
|
// the list of module names that the DynamicDependerModule depends on
|
|
|
|
// dynamically. Module names that already appear in the "deps" property may
|
|
|
|
// but do not need to be included in the returned list.
|
|
|
|
DynamicDependencies(DynamicDependerModuleContext) []string
|
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
type BaseModuleContext interface {
|
2014-05-28 01:34:41 +02:00
|
|
|
ModuleName() string
|
|
|
|
ModuleDir() string
|
2014-06-12 03:31:16 +02:00
|
|
|
Config() interface{}
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2014-10-29 22:51:13 +01:00
|
|
|
ContainsProperty(name string) bool
|
2014-07-03 01:40:31 +02:00
|
|
|
Errorf(pos scanner.Position, fmt string, args ...interface{})
|
2014-05-28 01:34:41 +02:00
|
|
|
ModuleErrorf(fmt string, args ...interface{})
|
|
|
|
PropertyErrorf(property, fmt string, args ...interface{})
|
2014-07-03 01:40:31 +02:00
|
|
|
Failed() bool
|
2014-09-25 05:28:11 +02:00
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
type DynamicDependerModuleContext interface {
|
|
|
|
BaseModuleContext
|
|
|
|
}
|
|
|
|
|
2014-12-17 22:23:56 +01:00
|
|
|
type ModuleContext interface {
|
2014-12-18 20:05:45 +01:00
|
|
|
BaseModuleContext
|
2014-09-25 05:28:11 +02:00
|
|
|
|
|
|
|
OtherModuleName(m Module) string
|
|
|
|
OtherModuleErrorf(m Module, fmt string, args ...interface{})
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2015-02-10 20:24:52 +01:00
|
|
|
VisitDirectDeps(visit func(Module))
|
|
|
|
VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
|
2014-11-11 23:18:53 +01:00
|
|
|
VisitDepsDepthFirst(visit func(Module))
|
|
|
|
VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
|
|
|
|
|
2014-12-19 01:28:54 +01:00
|
|
|
ModuleSubDir() string
|
|
|
|
|
2014-10-03 11:49:58 +02:00
|
|
|
Variable(pctx *PackageContext, name, value string)
|
|
|
|
Rule(pctx *PackageContext, name string, params RuleParams, argNames ...string) Rule
|
|
|
|
Build(pctx *PackageContext, params BuildParams)
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2014-06-26 02:21:54 +02:00
|
|
|
AddNinjaFileDeps(deps ...string)
|
2014-12-19 01:28:54 +01:00
|
|
|
|
|
|
|
PrimaryModule() Module
|
2015-01-07 01:19:59 +01:00
|
|
|
FinalModule() Module
|
|
|
|
VisitAllModuleVariants(visit func(Module))
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
var _ BaseModuleContext = (*baseModuleContext)(nil)
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
type baseModuleContext struct {
|
2014-05-28 01:34:41 +02:00
|
|
|
context *Context
|
2014-06-12 03:31:16 +02:00
|
|
|
config interface{}
|
2014-12-18 01:12:41 +01:00
|
|
|
group *moduleGroup
|
2014-09-25 05:28:11 +02:00
|
|
|
errs []error
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
func (d *baseModuleContext) ModuleName() string {
|
2014-12-18 01:12:41 +01:00
|
|
|
return d.group.properties.Name
|
2014-06-23 02:02:55 +02:00
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
func (d *baseModuleContext) ContainsProperty(name string) bool {
|
2014-12-18 01:12:41 +01:00
|
|
|
_, ok := d.group.propertyPos[name]
|
2014-10-29 22:51:13 +01:00
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
func (d *baseModuleContext) ModuleDir() string {
|
2014-12-18 01:12:41 +01:00
|
|
|
return filepath.Dir(d.group.relBlueprintsFile)
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
func (d *baseModuleContext) Config() interface{} {
|
2014-09-25 05:28:11 +02:00
|
|
|
return d.config
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
func (d *baseModuleContext) Errorf(pos scanner.Position,
|
2014-09-25 05:28:11 +02:00
|
|
|
format string, args ...interface{}) {
|
2014-07-03 01:40:31 +02:00
|
|
|
|
2014-09-25 05:28:11 +02:00
|
|
|
d.errs = append(d.errs, &Error{
|
2014-07-03 01:40:31 +02:00
|
|
|
Err: fmt.Errorf(format, args...),
|
|
|
|
Pos: pos,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
func (d *baseModuleContext) ModuleErrorf(format string,
|
2014-09-25 05:28:11 +02:00
|
|
|
args ...interface{}) {
|
|
|
|
|
|
|
|
d.errs = append(d.errs, &Error{
|
2014-05-28 01:34:41 +02:00
|
|
|
Err: fmt.Errorf(format, args...),
|
2014-12-18 01:12:41 +01:00
|
|
|
Pos: d.group.pos,
|
2014-05-28 01:34:41 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
func (d *baseModuleContext) PropertyErrorf(property, format string,
|
2014-05-28 01:34:41 +02:00
|
|
|
args ...interface{}) {
|
|
|
|
|
2014-12-18 01:12:41 +01:00
|
|
|
pos, ok := d.group.propertyPos[property]
|
2014-05-28 01:34:41 +02:00
|
|
|
if !ok {
|
|
|
|
panic(fmt.Errorf("property %q was not set for this module", property))
|
|
|
|
}
|
|
|
|
|
2014-09-25 05:28:11 +02:00
|
|
|
d.errs = append(d.errs, &Error{
|
2014-05-28 01:34:41 +02:00
|
|
|
Err: fmt.Errorf(format, args...),
|
|
|
|
Pos: pos,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-12-18 20:05:45 +01:00
|
|
|
func (d *baseModuleContext) Failed() bool {
|
2014-09-25 05:28:11 +02:00
|
|
|
return len(d.errs) > 0
|
|
|
|
}
|
|
|
|
|
2014-12-17 22:23:56 +01:00
|
|
|
var _ ModuleContext = (*moduleContext)(nil)
|
2014-09-25 05:28:11 +02:00
|
|
|
|
2014-12-17 22:23:56 +01:00
|
|
|
type moduleContext struct {
|
2014-12-18 20:05:45 +01:00
|
|
|
baseModuleContext
|
2014-12-17 22:23:56 +01:00
|
|
|
module *moduleInfo
|
|
|
|
scope *localScope
|
|
|
|
ninjaFileDeps []string
|
|
|
|
actionDefs localBuildActions
|
2014-09-25 05:28:11 +02:00
|
|
|
}
|
|
|
|
|
2014-12-17 22:23:56 +01:00
|
|
|
func (m *moduleContext) OtherModuleName(module Module) string {
|
2014-09-25 05:28:11 +02:00
|
|
|
info := m.context.moduleInfo[module]
|
2014-12-18 01:12:41 +01:00
|
|
|
return info.group.properties.Name
|
2014-09-25 05:28:11 +02:00
|
|
|
}
|
|
|
|
|
2014-12-17 22:23:56 +01:00
|
|
|
func (m *moduleContext) OtherModuleErrorf(module Module, format string,
|
2014-06-23 02:02:55 +02:00
|
|
|
args ...interface{}) {
|
|
|
|
|
|
|
|
info := m.context.moduleInfo[module]
|
|
|
|
m.errs = append(m.errs, &Error{
|
|
|
|
Err: fmt.Errorf(format, args...),
|
2014-12-18 01:12:41 +01:00
|
|
|
Pos: info.group.pos,
|
2014-06-23 02:02:55 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-02-10 20:24:52 +01:00
|
|
|
func (m *moduleContext) VisitDirectDeps(visit func(Module)) {
|
|
|
|
m.context.visitDirectDeps(m.module, visit)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *moduleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
|
|
|
|
m.context.visitDirectDepsIf(m.module, pred, visit)
|
|
|
|
}
|
|
|
|
|
2014-12-17 22:23:56 +01:00
|
|
|
func (m *moduleContext) VisitDepsDepthFirst(visit func(Module)) {
|
2014-11-11 23:18:53 +01:00
|
|
|
m.context.visitDepsDepthFirst(m.module, visit)
|
|
|
|
}
|
|
|
|
|
2014-12-17 22:23:56 +01:00
|
|
|
func (m *moduleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
|
2014-11-11 23:18:53 +01:00
|
|
|
visit func(Module)) {
|
|
|
|
|
|
|
|
m.context.visitDepsDepthFirstIf(m.module, pred, visit)
|
|
|
|
}
|
|
|
|
|
2014-12-19 01:28:54 +01:00
|
|
|
func (m *moduleContext) ModuleSubDir() string {
|
|
|
|
return m.module.subName()
|
|
|
|
}
|
|
|
|
|
2014-10-03 11:49:58 +02:00
|
|
|
func (m *moduleContext) Variable(pctx *PackageContext, name, value string) {
|
|
|
|
m.scope.ReparentTo(pctx)
|
2014-07-01 03:07:17 +02:00
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
v, err := m.scope.AddLocalVariable(name, value)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.actionDefs.variables = append(m.actionDefs.variables, v)
|
|
|
|
}
|
|
|
|
|
2014-10-03 11:49:58 +02:00
|
|
|
func (m *moduleContext) Rule(pctx *PackageContext, name string,
|
|
|
|
params RuleParams, argNames ...string) Rule {
|
2014-06-06 05:00:22 +02:00
|
|
|
|
2014-10-03 11:49:58 +02:00
|
|
|
m.scope.ReparentTo(pctx)
|
2014-07-01 03:07:17 +02:00
|
|
|
|
2014-06-06 05:00:22 +02:00
|
|
|
r, err := m.scope.AddLocalRule(name, ¶ms, argNames...)
|
2014-05-28 01:34:41 +02:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.actionDefs.rules = append(m.actionDefs.rules, r)
|
|
|
|
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
2014-10-03 11:49:58 +02:00
|
|
|
func (m *moduleContext) Build(pctx *PackageContext, params BuildParams) {
|
|
|
|
m.scope.ReparentTo(pctx)
|
2014-07-01 03:07:17 +02:00
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
def, err := parseBuildParams(m.scope, ¶ms)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def)
|
|
|
|
}
|
|
|
|
|
2014-06-26 02:21:54 +02:00
|
|
|
func (m *moduleContext) AddNinjaFileDeps(deps ...string) {
|
|
|
|
m.ninjaFileDeps = append(m.ninjaFileDeps, deps...)
|
|
|
|
}
|
2014-12-19 01:28:54 +01:00
|
|
|
|
|
|
|
func (m *moduleContext) PrimaryModule() Module {
|
2015-01-07 01:19:59 +01:00
|
|
|
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)) {
|
|
|
|
for _, module := range m.module.group.modules {
|
|
|
|
visit(module.logicModule)
|
|
|
|
}
|
2014-12-19 01:28:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// MutatorContext
|
|
|
|
//
|
|
|
|
|
|
|
|
type mutatorContext struct {
|
|
|
|
baseModuleContext
|
|
|
|
module *moduleInfo
|
|
|
|
name string
|
|
|
|
dependenciesModified bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type baseMutatorContext interface {
|
|
|
|
BaseModuleContext
|
|
|
|
|
|
|
|
Module() Module
|
|
|
|
}
|
|
|
|
|
|
|
|
type TopDownMutatorContext interface {
|
|
|
|
baseMutatorContext
|
|
|
|
|
|
|
|
VisitDirectDeps(visit func(Module))
|
|
|
|
VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
|
|
|
|
VisitDepsDepthFirst(visit func(Module))
|
|
|
|
VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
|
|
|
|
}
|
|
|
|
|
|
|
|
type BottomUpMutatorContext interface {
|
|
|
|
baseMutatorContext
|
|
|
|
|
|
|
|
AddDependency(module Module, name string)
|
|
|
|
CreateVariants(...string) []Module
|
|
|
|
SetDependencyVariant(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
// A Mutator function is called for each Module, and can use
|
|
|
|
// MutatorContext.CreateSubVariants to split a Module into multiple Modules,
|
|
|
|
// modifying properties on the new modules to differentiate them. It is called
|
|
|
|
// after parsing all Blueprint files, but before generating any build rules,
|
|
|
|
// and is always called on dependencies before being called on the depending module.
|
|
|
|
//
|
|
|
|
// The Mutator function should only modify members of properties structs, and not
|
|
|
|
// members of the module struct itself, to ensure the modified values are copied
|
|
|
|
// if a second Mutator chooses to split the module a second time.
|
|
|
|
type TopDownMutator func(mctx TopDownMutatorContext)
|
|
|
|
type BottomUpMutator func(mctx BottomUpMutatorContext)
|
|
|
|
|
|
|
|
// Split a module into mulitple variants, one for each name in the variantNames
|
|
|
|
// parameter. It returns a list of new modules in the same order as the variantNames
|
|
|
|
// list.
|
|
|
|
//
|
|
|
|
// If any of the dependencies of the module being operated on were already split
|
|
|
|
// by calling CreateVariants with the same name, the dependency will automatically
|
|
|
|
// be updated to point the matching variant.
|
|
|
|
//
|
|
|
|
// If a module is split, and then a module depending on the first module is not split
|
|
|
|
// when the Mutator is later called on it, the dependency of the depending module will
|
|
|
|
// automatically be updated to point to the first variant.
|
|
|
|
func (mctx *mutatorContext) CreateVariants(variantNames ...string) []Module {
|
|
|
|
ret := []Module{}
|
2015-03-04 02:37:03 +01:00
|
|
|
modules, errs := mctx.context.createVariants(mctx.module, mctx.name, variantNames)
|
|
|
|
if len(errs) > 0 {
|
|
|
|
mctx.errs = append(mctx.errs, errs...)
|
|
|
|
}
|
2014-12-19 01:28:54 +01:00
|
|
|
|
|
|
|
for _, module := range modules {
|
|
|
|
ret = append(ret, module.logicModule)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(ret) != len(variantNames) {
|
|
|
|
panic("oops!")
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set all dangling dependencies on the current module to point to the variant
|
|
|
|
// with given name.
|
|
|
|
func (mctx *mutatorContext) SetDependencyVariant(variantName string) {
|
|
|
|
subName := subName{
|
|
|
|
mutatorName: mctx.name,
|
|
|
|
variantName: variantName,
|
|
|
|
}
|
|
|
|
mctx.context.convertDepsToVariant(mctx.module, subName)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mctx *mutatorContext) Module() Module {
|
|
|
|
return mctx.module.logicModule
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a dependency to the given module. The depender can be a specific variant
|
|
|
|
// of a module, but the dependee must be a module that only has a single variant.
|
|
|
|
// 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) {
|
|
|
|
mctx.context.addDependency(mctx.context.moduleInfo[module], depName)
|
|
|
|
mctx.dependenciesModified = true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mctx *mutatorContext) VisitDirectDeps(visit func(Module)) {
|
|
|
|
mctx.context.visitDirectDeps(mctx.module, visit)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mctx *mutatorContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
|
|
|
|
mctx.context.visitDirectDepsIf(mctx.module, pred, visit)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mctx *mutatorContext) VisitDepsDepthFirst(visit func(Module)) {
|
|
|
|
mctx.context.visitDepsDepthFirst(mctx.module, visit)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mctx *mutatorContext) VisitDepsDepthFirstIf(pred func(Module) bool,
|
|
|
|
visit func(Module)) {
|
|
|
|
|
|
|
|
mctx.context.visitDepsDepthFirstIf(mctx.module, pred, visit)
|
|
|
|
}
|