Home | History | Annotate | Download | only in blueprint
      1 // Copyright 2014 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package blueprint
     16 
     17 import (
     18 	"fmt"
     19 	"path/filepath"
     20 	"text/scanner"
     21 
     22 	"github.com/google/blueprint/pathtools"
     23 )
     24 
     25 // A Module handles generating all of the Ninja build actions needed to build a
     26 // single module based on properties defined in a Blueprints file.  Module
     27 // objects are initially created during the parse phase of a Context using one
     28 // of the registered module types (and the associated ModuleFactory function).
     29 // The Module's properties struct is automatically filled in with the property
     30 // values specified in the Blueprints file (see Context.RegisterModuleType for more
     31 // information on this).
     32 //
     33 // A Module can be split into multiple Modules by a Mutator.  All existing
     34 // properties set on the module will be duplicated to the new Module, and then
     35 // modified as necessary by the Mutator.
     36 //
     37 // The Module implementation can access the build configuration as well as any
     38 // modules on which on which it depends (as defined by the "deps" property
     39 // specified in the Blueprints file, dynamically added by implementing the
     40 // (deprecated) DynamicDependerModule interface, or dynamically added by a
     41 // BottomUpMutator) using the ModuleContext passed to GenerateBuildActions.
     42 // This ModuleContext is also used to create Ninja build actions and to report
     43 // errors to the user.
     44 //
     45 // In addition to implementing the GenerateBuildActions method, a Module should
     46 // implement methods that provide dependant modules and singletons information
     47 // they need to generate their build actions.  These methods will only be called
     48 // after GenerateBuildActions is called because the Context calls
     49 // GenerateBuildActions in dependency-order (and singletons are invoked after
     50 // all the Modules).  The set of methods a Module supports will determine how
     51 // dependant Modules interact with it.
     52 //
     53 // For example, consider a Module that is responsible for generating a library
     54 // that other modules can link against.  The library Module might implement the
     55 // following interface:
     56 //
     57 //   type LibraryProducer interface {
     58 //       LibraryFileName() string
     59 //   }
     60 //
     61 //   func IsLibraryProducer(module blueprint.Module) {
     62 //       _, ok := module.(LibraryProducer)
     63 //       return ok
     64 //   }
     65 //
     66 // A binary-producing Module that depends on the library Module could then do:
     67 //
     68 //   func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
     69 //       ...
     70 //       var libraryFiles []string
     71 //       ctx.VisitDepsDepthFirstIf(IsLibraryProducer,
     72 //           func(module blueprint.Module) {
     73 //               libProducer := module.(LibraryProducer)
     74 //               libraryFiles = append(libraryFiles, libProducer.LibraryFileName())
     75 //           })
     76 //       ...
     77 //   }
     78 //
     79 // to build the list of library file names that should be included in its link
     80 // command.
     81 //
     82 // GenerateBuildActions may be called from multiple threads.  It is guaranteed to
     83 // be called after it has finished being called on all dependencies and on all
     84 // variants of that appear earlier in the ModuleContext.VisitAllModuleVariants list.
     85 // Any accesses to global variables or to Module objects that are not dependencies
     86 // or variants of the current Module must be synchronized by the implementation of
     87 // GenerateBuildActions.
     88 type Module interface {
     89 	// Name returns a string used to uniquely identify each module.  The return
     90 	// value must be unique across all modules.  It is only called once, during
     91 	// initial blueprint parsing.  To change the name later a mutator must call
     92 	// MutatorContext.Rename
     93 	//
     94 	// In most cases, Name should return the contents of a "name:" property from
     95 	// the blueprint file.  An embeddable SimpleName object can be used for this
     96 	// case.
     97 	Name() string
     98 
     99 	// GenerateBuildActions is called by the Context that created the Module
    100 	// during its generate phase.  This call should generate all Ninja build
    101 	// actions (rules, pools, and build statements) needed to build the module.
    102 	GenerateBuildActions(ModuleContext)
    103 }
    104 
    105 // A DynamicDependerModule is a Module that may add dependencies that do not
    106 // appear in its "deps" property.  Any Module that implements this interface
    107 // will have its DynamicDependencies method called by the Context that created
    108 // it during generate phase.
    109 //
    110 // Deprecated, use a BottomUpMutator instead
    111 type DynamicDependerModule interface {
    112 	Module
    113 
    114 	// DynamicDependencies is called by the Context that created the
    115 	// DynamicDependerModule during its generate phase.  This call should return
    116 	// the list of module names that the DynamicDependerModule depends on
    117 	// dynamically.  Module names that already appear in the "deps" property may
    118 	// but do not need to be included in the returned list.
    119 	DynamicDependencies(DynamicDependerModuleContext) []string
    120 }
    121 
    122 type BaseModuleContext interface {
    123 	ModuleName() string
    124 	ModuleDir() string
    125 	Config() interface{}
    126 
    127 	ContainsProperty(name string) bool
    128 	Errorf(pos scanner.Position, fmt string, args ...interface{})
    129 	ModuleErrorf(fmt string, args ...interface{})
    130 	PropertyErrorf(property, fmt string, args ...interface{})
    131 	Failed() bool
    132 
    133 	// GlobWithDeps returns a list of files that match the specified pattern but do not match any
    134 	// of the patterns in excludes.  It also adds efficient dependencies to rerun the primary
    135 	// builder whenever a file matching the pattern as added or removed, without rerunning if a
    136 	// file that does not match the pattern is added to a searched directory.
    137 	GlobWithDeps(pattern string, excludes []string) ([]string, error)
    138 
    139 	Fs() pathtools.FileSystem
    140 
    141 	moduleInfo() *moduleInfo
    142 	error(err error)
    143 }
    144 
    145 type DynamicDependerModuleContext BottomUpMutatorContext
    146 
    147 type ModuleContext interface {
    148 	BaseModuleContext
    149 
    150 	OtherModuleName(m Module) string
    151 	OtherModuleErrorf(m Module, fmt string, args ...interface{})
    152 	OtherModuleDependencyTag(m Module) DependencyTag
    153 
    154 	GetDirectDepWithTag(name string, tag DependencyTag) Module
    155 	GetDirectDep(name string) (Module, DependencyTag)
    156 
    157 	VisitDirectDeps(visit func(Module))
    158 	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
    159 	VisitDepsDepthFirst(visit func(Module))
    160 	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
    161 	WalkDeps(visit func(Module, Module) bool)
    162 
    163 	ModuleSubDir() string
    164 
    165 	Variable(pctx PackageContext, name, value string)
    166 	Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule
    167 	Build(pctx PackageContext, params BuildParams)
    168 
    169 	AddNinjaFileDeps(deps ...string)
    170 
    171 	PrimaryModule() Module
    172 	FinalModule() Module
    173 	VisitAllModuleVariants(visit func(Module))
    174 
    175 	GetMissingDependencies() []string
    176 }
    177 
    178 var _ BaseModuleContext = (*baseModuleContext)(nil)
    179 
    180 type baseModuleContext struct {
    181 	context        *Context
    182 	config         interface{}
    183 	module         *moduleInfo
    184 	errs           []error
    185 	visitingParent *moduleInfo
    186 	visitingDep    depInfo
    187 }
    188 
    189 func (d *baseModuleContext) moduleInfo() *moduleInfo {
    190 	return d.module
    191 }
    192 
    193 func (d *baseModuleContext) ModuleName() string {
    194 	return d.module.Name()
    195 }
    196 
    197 func (d *baseModuleContext) ContainsProperty(name string) bool {
    198 	_, ok := d.module.propertyPos[name]
    199 	return ok
    200 }
    201 
    202 func (d *baseModuleContext) ModuleDir() string {
    203 	return filepath.Dir(d.module.relBlueprintsFile)
    204 }
    205 
    206 func (d *baseModuleContext) Config() interface{} {
    207 	return d.config
    208 }
    209 
    210 func (d *baseModuleContext) error(err error) {
    211 	if err != nil {
    212 		d.errs = append(d.errs, err)
    213 	}
    214 }
    215 
    216 func (d *baseModuleContext) Errorf(pos scanner.Position,
    217 	format string, args ...interface{}) {
    218 
    219 	d.error(&BlueprintError{
    220 		Err: fmt.Errorf(format, args...),
    221 		Pos: pos,
    222 	})
    223 }
    224 
    225 func (d *baseModuleContext) ModuleErrorf(format string,
    226 	args ...interface{}) {
    227 
    228 	d.error(&ModuleError{
    229 		BlueprintError: BlueprintError{
    230 			Err: fmt.Errorf(format, args...),
    231 			Pos: d.module.pos,
    232 		},
    233 		module: d.module,
    234 	})
    235 }
    236 
    237 func (d *baseModuleContext) PropertyErrorf(property, format string,
    238 	args ...interface{}) {
    239 
    240 	pos := d.module.propertyPos[property]
    241 
    242 	if !pos.IsValid() {
    243 		pos = d.module.pos
    244 	}
    245 
    246 	d.error(&PropertyError{
    247 		ModuleError: ModuleError{
    248 			BlueprintError: BlueprintError{
    249 				Err: fmt.Errorf(format, args...),
    250 				Pos: pos,
    251 			},
    252 			module: d.module,
    253 		},
    254 		property: property,
    255 	})
    256 }
    257 
    258 func (d *baseModuleContext) Failed() bool {
    259 	return len(d.errs) > 0
    260 }
    261 
    262 func (d *baseModuleContext) GlobWithDeps(pattern string,
    263 	excludes []string) ([]string, error) {
    264 	return d.context.glob(pattern, excludes)
    265 }
    266 
    267 func (d *baseModuleContext) Fs() pathtools.FileSystem {
    268 	return d.context.fs
    269 }
    270 
    271 var _ ModuleContext = (*moduleContext)(nil)
    272 
    273 type moduleContext struct {
    274 	baseModuleContext
    275 	scope              *localScope
    276 	ninjaFileDeps      []string
    277 	actionDefs         localBuildActions
    278 	handledMissingDeps bool
    279 }
    280 
    281 func (m *baseModuleContext) OtherModuleName(logicModule Module) string {
    282 	module := m.context.moduleInfo[logicModule]
    283 	return module.Name()
    284 }
    285 
    286 func (m *baseModuleContext) OtherModuleErrorf(logicModule Module, format string,
    287 	args ...interface{}) {
    288 
    289 	module := m.context.moduleInfo[logicModule]
    290 	m.errs = append(m.errs, &ModuleError{
    291 		BlueprintError: BlueprintError{
    292 			Err: fmt.Errorf(format, args...),
    293 			Pos: module.pos,
    294 		},
    295 		module: module,
    296 	})
    297 }
    298 
    299 func (m *baseModuleContext) OtherModuleDependencyTag(logicModule Module) DependencyTag {
    300 	// fast path for calling OtherModuleDependencyTag from inside VisitDirectDeps
    301 	if logicModule == m.visitingDep.module.logicModule {
    302 		return m.visitingDep.tag
    303 	}
    304 
    305 	for _, dep := range m.visitingParent.directDeps {
    306 		if dep.module.logicModule == logicModule {
    307 			return dep.tag
    308 		}
    309 	}
    310 
    311 	return nil
    312 }
    313 
    314 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
    315 // name, or nil if none exists.
    316 func (m *baseModuleContext) GetDirectDep(name string) (Module, DependencyTag) {
    317 	for _, dep := range m.module.directDeps {
    318 		if dep.module.Name() == name {
    319 			return dep.module.logicModule, dep.tag
    320 		}
    321 	}
    322 
    323 	return nil, nil
    324 }
    325 
    326 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
    327 // none exists.  It panics if the dependency does not have the specified tag.
    328 func (m *baseModuleContext) GetDirectDepWithTag(name string, tag DependencyTag) Module {
    329 	for _, dep := range m.module.directDeps {
    330 		if dep.module.Name() == name {
    331 			if dep.tag != tag {
    332 				panic(fmt.Errorf("found dependency %q with tag %#v, expected tag %#v",
    333 					dep.module, dep.tag, tag))
    334 			}
    335 			return dep.module.logicModule
    336 		}
    337 	}
    338 
    339 	return nil
    340 }
    341 
    342 func (m *baseModuleContext) VisitDirectDeps(visit func(Module)) {
    343 	defer func() {
    344 		if r := recover(); r != nil {
    345 			panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
    346 				m.module, funcName(visit), m.visitingDep.module))
    347 		}
    348 	}()
    349 
    350 	m.visitingParent = m.module
    351 
    352 	for _, dep := range m.module.directDeps {
    353 		m.visitingDep = dep
    354 		visit(dep.module.logicModule)
    355 	}
    356 
    357 	m.visitingParent = nil
    358 	m.visitingDep = depInfo{}
    359 }
    360 
    361 func (m *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
    362 	defer func() {
    363 		if r := recover(); r != nil {
    364 			panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
    365 				m.module, funcName(pred), funcName(visit), m.visitingDep.module))
    366 		}
    367 	}()
    368 
    369 	m.visitingParent = m.module
    370 
    371 	for _, dep := range m.module.directDeps {
    372 		m.visitingDep = dep
    373 		if pred(dep.module.logicModule) {
    374 			visit(dep.module.logicModule)
    375 		}
    376 	}
    377 
    378 	m.visitingParent = nil
    379 	m.visitingDep = depInfo{}
    380 }
    381 
    382 func (m *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
    383 	defer func() {
    384 		if r := recover(); r != nil {
    385 			panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s",
    386 				m.module, funcName(visit), m.visitingDep.module))
    387 		}
    388 	}()
    389 
    390 	m.context.walkDeps(m.module, nil, func(dep depInfo, parent *moduleInfo) {
    391 		m.visitingParent = parent
    392 		m.visitingDep = dep
    393 		visit(dep.module.logicModule)
    394 	})
    395 
    396 	m.visitingParent = nil
    397 	m.visitingDep = depInfo{}
    398 }
    399 
    400 func (m *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
    401 	visit func(Module)) {
    402 
    403 	defer func() {
    404 		if r := recover(); r != nil {
    405 			panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s",
    406 				m.module, funcName(pred), funcName(visit), m.visitingDep.module))
    407 		}
    408 	}()
    409 
    410 	m.context.walkDeps(m.module, nil, func(dep depInfo, parent *moduleInfo) {
    411 		if pred(dep.module.logicModule) {
    412 			m.visitingParent = parent
    413 			m.visitingDep = dep
    414 			visit(dep.module.logicModule)
    415 		}
    416 	})
    417 
    418 	m.visitingParent = nil
    419 	m.visitingDep = depInfo{}
    420 }
    421 
    422 func (m *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
    423 	m.context.walkDeps(m.module, func(dep depInfo, parent *moduleInfo) bool {
    424 		m.visitingParent = parent
    425 		m.visitingDep = dep
    426 		return visit(dep.module.logicModule, parent.logicModule)
    427 	}, nil)
    428 
    429 	m.visitingParent = nil
    430 	m.visitingDep = depInfo{}
    431 }
    432 
    433 func (m *moduleContext) ModuleSubDir() string {
    434 	return m.module.variantName
    435 }
    436 
    437 func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
    438 	m.scope.ReparentTo(pctx)
    439 
    440 	v, err := m.scope.AddLocalVariable(name, value)
    441 	if err != nil {
    442 		panic(err)
    443 	}
    444 
    445 	m.actionDefs.variables = append(m.actionDefs.variables, v)
    446 }
    447 
    448 func (m *moduleContext) Rule(pctx PackageContext, name string,
    449 	params RuleParams, argNames ...string) Rule {
    450 
    451 	m.scope.ReparentTo(pctx)
    452 
    453 	r, err := m.scope.AddLocalRule(name, &params, argNames...)
    454 	if err != nil {
    455 		panic(err)
    456 	}
    457 
    458 	m.actionDefs.rules = append(m.actionDefs.rules, r)
    459 
    460 	return r
    461 }
    462 
    463 func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
    464 	m.scope.ReparentTo(pctx)
    465 
    466 	def, err := parseBuildParams(m.scope, &params)
    467 	if err != nil {
    468 		panic(err)
    469 	}
    470 
    471 	m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def)
    472 }
    473 
    474 func (m *moduleContext) AddNinjaFileDeps(deps ...string) {
    475 	m.ninjaFileDeps = append(m.ninjaFileDeps, deps...)
    476 }
    477 
    478 func (m *moduleContext) PrimaryModule() Module {
    479 	return m.module.group.modules[0].logicModule
    480 }
    481 
    482 func (m *moduleContext) FinalModule() Module {
    483 	return m.module.group.modules[len(m.module.group.modules)-1].logicModule
    484 }
    485 
    486 func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) {
    487 	m.context.visitAllModuleVariants(m.module, visit)
    488 }
    489 
    490 func (m *moduleContext) GetMissingDependencies() []string {
    491 	m.handledMissingDeps = true
    492 	return m.module.missingDeps
    493 }
    494 
    495 //
    496 // MutatorContext
    497 //
    498 
    499 type mutatorContext struct {
    500 	baseModuleContext
    501 	name        string
    502 	reverseDeps []reverseDep
    503 	rename      []rename
    504 	replace     []replace
    505 	newModules  []*moduleInfo
    506 }
    507 
    508 type baseMutatorContext interface {
    509 	BaseModuleContext
    510 
    511 	OtherModuleExists(name string) bool
    512 	Rename(name string)
    513 	Module() Module
    514 }
    515 
    516 type EarlyMutatorContext interface {
    517 	baseMutatorContext
    518 
    519 	CreateVariations(...string) []Module
    520 	CreateLocalVariations(...string) []Module
    521 }
    522 
    523 type TopDownMutatorContext interface {
    524 	baseMutatorContext
    525 
    526 	OtherModuleName(m Module) string
    527 	OtherModuleErrorf(m Module, fmt string, args ...interface{})
    528 	OtherModuleDependencyTag(m Module) DependencyTag
    529 
    530 	GetDirectDepWithTag(name string, tag DependencyTag) Module
    531 	GetDirectDep(name string) (Module, DependencyTag)
    532 
    533 	VisitDirectDeps(visit func(Module))
    534 	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
    535 	VisitDepsDepthFirst(visit func(Module))
    536 	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
    537 	WalkDeps(visit func(Module, Module) bool)
    538 }
    539 
    540 type BottomUpMutatorContext interface {
    541 	baseMutatorContext
    542 
    543 	AddDependency(module Module, tag DependencyTag, name ...string)
    544 	AddReverseDependency(module Module, tag DependencyTag, name string)
    545 	CreateVariations(...string) []Module
    546 	CreateLocalVariations(...string) []Module
    547 	SetDependencyVariation(string)
    548 	AddVariationDependencies([]Variation, DependencyTag, ...string)
    549 	AddFarVariationDependencies([]Variation, DependencyTag, ...string)
    550 	AddInterVariantDependency(tag DependencyTag, from, to Module)
    551 	ReplaceDependencies(string)
    552 }
    553 
    554 // A Mutator function is called for each Module, and can use
    555 // MutatorContext.CreateVariations to split a Module into multiple Modules,
    556 // modifying properties on the new modules to differentiate them.  It is called
    557 // after parsing all Blueprint files, but before generating any build rules,
    558 // and is always called on dependencies before being called on the depending module.
    559 //
    560 // The Mutator function should only modify members of properties structs, and not
    561 // members of the module struct itself, to ensure the modified values are copied
    562 // if a second Mutator chooses to split the module a second time.
    563 type TopDownMutator func(mctx TopDownMutatorContext)
    564 type BottomUpMutator func(mctx BottomUpMutatorContext)
    565 type EarlyMutator func(mctx EarlyMutatorContext)
    566 
    567 // DependencyTag is an interface to an arbitrary object that embeds BaseDependencyTag.  It can be
    568 // used to transfer information on a dependency between the mutator that called AddDependency
    569 // and the GenerateBuildActions method.  Variants created by CreateVariations have a copy of the
    570 // interface (pointing to the same concrete object) from their original module.
    571 type DependencyTag interface {
    572 	dependencyTag(DependencyTag)
    573 }
    574 
    575 type BaseDependencyTag struct {
    576 }
    577 
    578 func (BaseDependencyTag) dependencyTag(DependencyTag) {
    579 }
    580 
    581 var _ DependencyTag = BaseDependencyTag{}
    582 
    583 // Split a module into mulitple variants, one for each name in the variationNames
    584 // parameter.  It returns a list of new modules in the same order as the variationNames
    585 // list.
    586 //
    587 // If any of the dependencies of the module being operated on were already split
    588 // by calling CreateVariations with the same name, the dependency will automatically
    589 // be updated to point the matching variant.
    590 //
    591 // If a module is split, and then a module depending on the first module is not split
    592 // when the Mutator is later called on it, the dependency of the depending module will
    593 // automatically be updated to point to the first variant.
    594 func (mctx *mutatorContext) CreateVariations(variationNames ...string) []Module {
    595 	return mctx.createVariations(variationNames, false)
    596 }
    597 
    598 // Split a module into mulitple variants, one for each name in the variantNames
    599 // parameter.  It returns a list of new modules in the same order as the variantNames
    600 // list.
    601 //
    602 // Local variations do not affect automatic dependency resolution - dependencies added
    603 // to the split module via deps or DynamicDependerModule must exactly match a variant
    604 // that contains all the non-local variations.
    605 func (mctx *mutatorContext) CreateLocalVariations(variationNames ...string) []Module {
    606 	return mctx.createVariations(variationNames, true)
    607 }
    608 
    609 func (mctx *mutatorContext) createVariations(variationNames []string, local bool) []Module {
    610 	ret := []Module{}
    611 	modules, errs := mctx.context.createVariations(mctx.module, mctx.name, variationNames)
    612 	if len(errs) > 0 {
    613 		mctx.errs = append(mctx.errs, errs...)
    614 	}
    615 
    616 	for i, module := range modules {
    617 		ret = append(ret, module.logicModule)
    618 		if !local {
    619 			module.dependencyVariant[mctx.name] = variationNames[i]
    620 		}
    621 	}
    622 
    623 	if mctx.newModules != nil {
    624 		panic("module already has variations from this mutator")
    625 	}
    626 	mctx.newModules = modules
    627 
    628 	if len(ret) != len(variationNames) {
    629 		panic("oops!")
    630 	}
    631 
    632 	return ret
    633 }
    634 
    635 // Set all dangling dependencies on the current module to point to the variation
    636 // with given name.
    637 func (mctx *mutatorContext) SetDependencyVariation(variationName string) {
    638 	mctx.context.convertDepsToVariation(mctx.module, mctx.name, variationName)
    639 }
    640 
    641 func (mctx *mutatorContext) Module() Module {
    642 	return mctx.module.logicModule
    643 }
    644 
    645 // Add a dependency to the given module.
    646 // Does not affect the ordering of the current mutator pass, but will be ordered
    647 // correctly for all future mutator passes.
    648 func (mctx *mutatorContext) AddDependency(module Module, tag DependencyTag, deps ...string) {
    649 	for _, dep := range deps {
    650 		errs := mctx.context.addDependency(mctx.context.moduleInfo[module], tag, dep)
    651 		if len(errs) > 0 {
    652 			mctx.errs = append(mctx.errs, errs...)
    653 		}
    654 	}
    655 }
    656 
    657 // Add a dependency from the destination to the given module.
    658 // Does not affect the ordering of the current mutator pass, but will be ordered
    659 // correctly for all future mutator passes.  All reverse dependencies for a destination module are
    660 // collected until the end of the mutator pass, sorted by name, and then appended to the destination
    661 // module's dependency list.
    662 func (mctx *mutatorContext) AddReverseDependency(module Module, tag DependencyTag, destName string) {
    663 	if _, ok := tag.(BaseDependencyTag); ok {
    664 		panic("BaseDependencyTag is not allowed to be used directly!")
    665 	}
    666 
    667 	destModule, errs := mctx.context.findReverseDependency(mctx.context.moduleInfo[module], destName)
    668 	if len(errs) > 0 {
    669 		mctx.errs = append(mctx.errs, errs...)
    670 		return
    671 	}
    672 
    673 	mctx.reverseDeps = append(mctx.reverseDeps, reverseDep{
    674 		destModule,
    675 		depInfo{mctx.context.moduleInfo[module], tag},
    676 	})
    677 }
    678 
    679 // AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
    680 // argument to select which variant of the dependency to use.  A variant of the dependency must
    681 // exist that matches the all of the non-local variations of the current module, plus the variations
    682 // argument.
    683 func (mctx *mutatorContext) AddVariationDependencies(variations []Variation, tag DependencyTag,
    684 	deps ...string) {
    685 
    686 	for _, dep := range deps {
    687 		errs := mctx.context.addVariationDependency(mctx.module, variations, tag, dep, false)
    688 		if len(errs) > 0 {
    689 			mctx.errs = append(mctx.errs, errs...)
    690 		}
    691 	}
    692 }
    693 
    694 // AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
    695 // variations argument to select which variant of the dependency to use.  A variant of the
    696 // dependency must exist that matches the variations argument, but may also have other variations.
    697 // For any unspecified variation the first variant will be used.
    698 //
    699 // Unlike AddVariationDependencies, the variations of the current module are ignored - the
    700 // depdendency only needs to match the supplied variations.
    701 func (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation, tag DependencyTag,
    702 	deps ...string) {
    703 
    704 	for _, dep := range deps {
    705 		errs := mctx.context.addVariationDependency(mctx.module, variations, tag, dep, true)
    706 		if len(errs) > 0 {
    707 			mctx.errs = append(mctx.errs, errs...)
    708 		}
    709 	}
    710 }
    711 
    712 func (mctx *mutatorContext) AddInterVariantDependency(tag DependencyTag, from, to Module) {
    713 	mctx.context.addInterVariantDependency(mctx.module, tag, from, to)
    714 }
    715 
    716 // ReplaceDependencies replaces all dependencies on the identical variant of the module with the
    717 // specified name with the current variant of this module.  Replacements don't take effect until
    718 // after the mutator pass is finished.
    719 func (mctx *mutatorContext) ReplaceDependencies(name string) {
    720 	target := mctx.context.moduleMatchingVariant(mctx.module, name)
    721 
    722 	if target == nil {
    723 		panic(fmt.Errorf("ReplaceDependencies could not find identical variant %q for module %q",
    724 			mctx.module.variantName, name))
    725 	}
    726 
    727 	mctx.replace = append(mctx.replace, replace{target, mctx.module})
    728 }
    729 
    730 func (mctx *mutatorContext) OtherModuleExists(name string) bool {
    731 	return mctx.context.moduleNames[name] != nil
    732 }
    733 
    734 // Rename all variants of a module.  The new name is not visible to calls to ModuleName,
    735 // AddDependency or OtherModuleName until after this mutator pass is complete.
    736 func (mctx *mutatorContext) Rename(name string) {
    737 	mctx.rename = append(mctx.rename, rename{mctx.module.group, name})
    738 }
    739 
    740 // SimpleName is an embeddable object to implement the ModuleContext.Name method using a property
    741 // called "name".  Modules that embed it must also add SimpleName.Properties to their property
    742 // structure list.
    743 type SimpleName struct {
    744 	Properties struct {
    745 		Name string
    746 	}
    747 }
    748 
    749 func (s *SimpleName) Name() string {
    750 	return s.Properties.Name
    751 }
    752