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
15package blueprint
16
17import (
18	"fmt"
19	"path/filepath"
20	"strings"
21	"sync"
22	"text/scanner"
23
24	"github.com/google/blueprint/parser"
25	"github.com/google/blueprint/pathtools"
26	"github.com/google/blueprint/proptools"
27)
28
29// A Module handles generating all of the Ninja build actions needed to build a
30// single module based on properties defined in a Blueprints file.  Module
31// objects are initially created during the parse phase of a Context using one
32// of the registered module types (and the associated ModuleFactory function).
33// The Module's properties struct is automatically filled in with the property
34// values specified in the Blueprints file (see Context.RegisterModuleType for more
35// information on this).
36//
37// A Module can be split into multiple Modules by a Mutator.  All existing
38// properties set on the module will be duplicated to the new Module, and then
39// modified as necessary by the Mutator.
40//
41// The Module implementation can access the build configuration as well as any
42// modules on which it depends (as defined by the "deps" property
43// specified in the Blueprints file, dynamically added by implementing the
44// (deprecated) DynamicDependerModule interface, or dynamically added by a
45// BottomUpMutator) using the ModuleContext passed to GenerateBuildActions.
46// This ModuleContext is also used to create Ninja build actions and to report
47// errors to the user.
48//
49// In addition to implementing the GenerateBuildActions method, a Module should
50// implement methods that provide dependant modules and singletons information
51// they need to generate their build actions.  These methods will only be called
52// after GenerateBuildActions is called because the Context calls
53// GenerateBuildActions in dependency-order (and singletons are invoked after
54// all the Modules).  The set of methods a Module supports will determine how
55// dependant Modules interact with it.
56//
57// For example, consider a Module that is responsible for generating a library
58// that other modules can link against.  The library Module might implement the
59// following interface:
60//
61//	type LibraryProducer interface {
62//	    LibraryFileName() string
63//	}
64//
65//	func IsLibraryProducer(module blueprint.Module) {
66//	    _, ok := module.(LibraryProducer)
67//	    return ok
68//	}
69//
70// A binary-producing Module that depends on the library Module could then do:
71//
72//	func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
73//	    ...
74//	    var libraryFiles []string
75//	    ctx.VisitDepsDepthFirstIf(IsLibraryProducer,
76//	        func(module blueprint.Module) {
77//	            libProducer := module.(LibraryProducer)
78//	            libraryFiles = append(libraryFiles, libProducer.LibraryFileName())
79//	        })
80//	    ...
81//	}
82//
83// to build the list of library file names that should be included in its link
84// command.
85//
86// GenerateBuildActions may be called from multiple threads.  It is guaranteed to
87// be called after it has finished being called on all dependencies and on all
88// variants of that appear earlier in the ModuleContext.VisitAllModuleVariants list.
89// Any accesses to global variables or to Module objects that are not dependencies
90// or variants of the current Module must be synchronized by the implementation of
91// GenerateBuildActions.
92type Module interface {
93	// Name returns a string used to uniquely identify each module.  The return
94	// value must be unique across all modules.  It is only called once, during
95	// initial blueprint parsing.  To change the name later a mutator must call
96	// MutatorContext.Rename
97	//
98	// In most cases, Name should return the contents of a "name:" property from
99	// the blueprint file.  An embeddable SimpleName object can be used for this
100	// case.
101	Name() string
102
103	// GenerateBuildActions is called by the Context that created the Module
104	// during its generate phase.  This call should generate all Ninja build
105	// actions (rules, pools, and build statements) needed to build the module.
106	GenerateBuildActions(ModuleContext)
107}
108
109// A DynamicDependerModule is a Module that may add dependencies that do not
110// appear in its "deps" property.  Any Module that implements this interface
111// will have its DynamicDependencies method called by the Context that created
112// it during generate phase.
113//
114// Deprecated, use a BottomUpMutator instead
115type DynamicDependerModule interface {
116	Module
117
118	// DynamicDependencies is called by the Context that created the
119	// DynamicDependerModule during its generate phase.  This call should return
120	// the list of module names that the DynamicDependerModule depends on
121	// dynamically.  Module names that already appear in the "deps" property may
122	// but do not need to be included in the returned list.
123	DynamicDependencies(DynamicDependerModuleContext) []string
124}
125
126type EarlyModuleContext interface {
127	// Module returns the current module as a Module.  It should rarely be necessary, as the module already has a
128	// reference to itself.
129	Module() Module
130
131	// ModuleName returns the name of the module.  This is generally the value that was returned by Module.Name() when
132	// the module was created, but may have been modified by calls to BaseMutatorContext.Rename.
133	ModuleName() string
134
135	// ModuleDir returns the path to the directory that contains the definition of the module.
136	ModuleDir() string
137
138	// ModuleType returns the name of the module type that was used to create the module, as specified in
139	// Context.RegisterModuleType().
140	ModuleType() string
141
142	// ModuleTags returns the tags for this module that should be passed to
143	// ninja for analysis. For example:
144	// [
145	//   "module_name": "libfoo",
146	//   "module_type": "cc_library",
147	// ]
148	ModuleTags() map[string]string
149
150	// BlueprintsFile returns the name of the blueprint file that contains the definition of this
151	// module.
152	BlueprintsFile() string
153
154	// Config returns the config object that was passed to Context.PrepareBuildActions.
155	Config() interface{}
156
157	// ContainsProperty returns true if the specified property name was set in the module definition.
158	ContainsProperty(name string) bool
159
160	// Errorf reports an error at the specified position of the module definition file.
161	Errorf(pos scanner.Position, fmt string, args ...interface{})
162
163	// ModuleErrorf reports an error at the line number of the module type in the module definition.
164	ModuleErrorf(fmt string, args ...interface{})
165
166	// PropertyErrorf reports an error at the line number of a property in the module definition.
167	PropertyErrorf(property, fmt string, args ...interface{})
168
169	// OtherModulePropertyErrorf reports an error at the line number of a property in the given module definition.
170	OtherModulePropertyErrorf(logicModule Module, property string, format string, args ...interface{})
171
172	// Failed returns true if any errors have been reported.  In most cases the module can continue with generating
173	// build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
174	// has prevented the module from creating necessary data it can return early when Failed returns true.
175	Failed() bool
176
177	// GlobWithDeps returns a list of files and directories that match the
178	// specified pattern but do not match any of the patterns in excludes.
179	// Any directories will have a '/' suffix.  It also adds efficient
180	// dependencies to rerun the primary builder whenever a file matching
181	// the pattern as added or removed, without rerunning if a file that
182	// does not match the pattern is added to a searched directory.
183	GlobWithDeps(pattern string, excludes []string) ([]string, error)
184
185	// Fs returns a pathtools.Filesystem that can be used to interact with files.  Using the Filesystem interface allows
186	// the module to be used in build system tests that run against a mock filesystem.
187	Fs() pathtools.FileSystem
188
189	// AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest.  The
190	// primary builder will be rerun whenever the specified files are modified.
191	AddNinjaFileDeps(deps ...string)
192
193	moduleInfo() *moduleInfo
194	error(err error)
195
196	// Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the
197	// default SimpleNameInterface if Context.SetNameInterface was not called.
198	Namespace() Namespace
199
200	// ModuleFactories returns a map of all of the global ModuleFactories by name.
201	ModuleFactories() map[string]ModuleFactory
202}
203
204type BaseModuleContext interface {
205	EarlyModuleContext
206
207	// GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
208	// none exists.  It panics if the dependency does not have the specified tag.
209	GetDirectDepWithTag(name string, tag DependencyTag) Module
210
211	// GetDirectDep returns the Module and DependencyTag for the  direct dependency with the specified
212	// name, or nil if none exists.  If there are multiple dependencies on the same module it returns
213	// the first DependencyTag.
214	GetDirectDep(name string) (Module, DependencyTag)
215
216	// VisitDirectDeps calls visit for each direct dependency.  If there are multiple direct dependencies on the same
217	// module visit will be called multiple times on that module and OtherModuleDependencyTag will return a different
218	// tag for each.
219	//
220	// The Module passed to the visit function should not be retained outside of the visit function, it may be
221	// invalidated by future mutators.
222	VisitDirectDeps(visit func(Module))
223
224	// VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit.  If there are
225	// multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
226	// OtherModuleDependencyTag will return a different tag for each.
227	//
228	// The Module passed to the visit function should not be retained outside of the visit function, it may be
229	// invalidated by future mutators.
230	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
231
232	// VisitDepsDepthFirst calls visit for each transitive dependency, traversing the dependency tree in depth first
233	// order. visit will only be called once for any given module, even if there are multiple paths through the
234	// dependency tree to the module or multiple direct dependencies with different tags.  OtherModuleDependencyTag will
235	// return the tag for the first path found to the module.
236	//
237	// The Module passed to the visit function should not be retained outside of the visit function, it may be
238	// invalidated by future mutators.
239	VisitDepsDepthFirst(visit func(Module))
240
241	// VisitDepsDepthFirstIf calls pred for each transitive dependency, and if pred returns true calls visit, traversing
242	// the dependency tree in depth first order.  visit will only be called once for any given module, even if there are
243	// multiple paths through the dependency tree to the module or multiple direct dependencies with different tags.
244	// OtherModuleDependencyTag will return the tag for the first path found to the module.  The return value of pred
245	// does not affect which branches of the tree are traversed.
246	//
247	// The Module passed to the visit function should not be retained outside of the visit function, it may be
248	// invalidated by future mutators.
249	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
250
251	// WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order.  visit may
252	// be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
253	// child and parent with different tags.  OtherModuleDependencyTag will return the tag for the currently visited
254	// (child, parent) pair.  If visit returns false WalkDeps will not continue recursing down to child.
255	//
256	// The Modules passed to the visit function should not be retained outside of the visit function, they may be
257	// invalidated by future mutators.
258	WalkDeps(visit func(Module, Module) bool)
259
260	// PrimaryModule returns the first variant of the current module.  Variants of a module are always visited in
261	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
262	// Module returned by PrimaryModule without data races.  This can be used to perform singleton actions that are
263	// only done once for all variants of a module.
264	PrimaryModule() Module
265
266	// FinalModule returns the last variant of the current module.  Variants of a module are always visited in
267	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
268	// variants using VisitAllModuleVariants if the current module == FinalModule().  This can be used to perform
269	// singleton actions that are only done once for all variants of a module.
270	FinalModule() Module
271
272	// VisitAllModuleVariants calls visit for each variant of the current module.  Variants of a module are always
273	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
274	// from all variants if the current module == FinalModule().  Otherwise, care must be taken to not access any
275	// data modified by the current mutator.
276	VisitAllModuleVariants(visit func(Module))
277
278	// OtherModuleName returns the name of another Module.  See BaseModuleContext.ModuleName for more information.
279	// It is intended for use inside the visit functions of Visit* and WalkDeps.
280	OtherModuleName(m Module) string
281
282	// OtherModuleDir returns the directory of another Module.  See BaseModuleContext.ModuleDir for more information.
283	// It is intended for use inside the visit functions of Visit* and WalkDeps.
284	OtherModuleDir(m Module) string
285
286	// OtherModuleSubDir returns the unique subdirectory name of another Module.  See ModuleContext.ModuleSubDir for
287	// more information.
288	// It is intended for use inside the visit functions of Visit* and WalkDeps.
289	OtherModuleSubDir(m Module) string
290
291	// OtherModuleType returns the type of another Module.  See BaseModuleContext.ModuleType for more information.
292	// It is intended for use inside the visit functions of Visit* and WalkDeps.
293	OtherModuleType(m Module) string
294
295	// OtherModuleErrorf reports an error on another Module.  See BaseModuleContext.ModuleErrorf for more information.
296	// It is intended for use inside the visit functions of Visit* and WalkDeps.
297	OtherModuleErrorf(m Module, fmt string, args ...interface{})
298
299	// OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
300	// on the module.  When called inside a Visit* method with current module being visited, and there are multiple
301	// dependencies on the module being visited, it returns the dependency tag used for the current dependency.
302	OtherModuleDependencyTag(m Module) DependencyTag
303
304	// OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
305	// passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
306	OtherModuleExists(name string) bool
307
308	// ModuleFromName returns (module, true) if a module exists by the given name and same context namespace,
309	// or (nil, false) if it does not exist. It panics if there is either more than one
310	// module of the given name, or if the given name refers to an alias instead of a module.
311	// There are no guarantees about which variant of the module will be returned.
312	// Prefer retrieving the module using GetDirectDep or a visit function, when possible, as
313	// this will guarantee the appropriate module-variant dependency is returned.
314	//
315	// WARNING: This should _only_ be used within the context of bp2build, where variants and
316	// dependencies are not created.
317	ModuleFromName(name string) (Module, bool)
318
319	// OtherModuleDependencyVariantExists returns true if a module with the
320	// specified name and variant exists. The variant must match the given
321	// variations. It must also match all the non-local variations of the current
322	// module. In other words, it checks for the module that AddVariationDependencies
323	// would add a dependency on with the same arguments.
324	OtherModuleDependencyVariantExists(variations []Variation, name string) bool
325
326	// OtherModuleFarDependencyVariantExists returns true if a module with the
327	// specified name and variant exists. The variant must match the given
328	// variations, but not the non-local variations of the current module. In
329	// other words, it checks for the module that AddFarVariationDependencies
330	// would add a dependency on with the same arguments.
331	OtherModuleFarDependencyVariantExists(variations []Variation, name string) bool
332
333	// OtherModuleReverseDependencyVariantExists returns true if a module with the
334	// specified name exists with the same variations as the current module. In
335	// other words, it checks for the module that AddReverseDependency would add a
336	// dependency on with the same argument.
337	OtherModuleReverseDependencyVariantExists(name string) bool
338
339	// OtherModuleProvider returns the value for a provider for the given module.  If the value is
340	// not set it returns nil and false.  The value returned may be a deep copy of the value originally
341	// passed to SetProvider.
342	//
343	// This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
344	OtherModuleProvider(m Module, provider AnyProviderKey) (any, bool)
345
346	// Provider returns the value for a provider for the current module.  If the value is
347	// not set it returns nil and false.  It panics if called before the appropriate
348	// mutator or GenerateBuildActions pass for the provider.  The value returned may be a deep
349	// copy of the value originally passed to SetProvider.
350	//
351	// This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
352	Provider(provider AnyProviderKey) (any, bool)
353
354	// SetProvider sets the value for a provider for the current module.  It panics if not called
355	// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
356	// is not of the appropriate type, or if the value has already been set.  The value should not
357	// be modified after being passed to SetProvider.
358	//
359	// This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
360	SetProvider(provider AnyProviderKey, value any)
361
362	EarlyGetMissingDependencies() []string
363
364	base() *baseModuleContext
365}
366
367type DynamicDependerModuleContext BottomUpMutatorContext
368
369type ModuleContext interface {
370	BaseModuleContext
371
372	// ModuleSubDir returns a unique name for the current variant of a module that can be used as part of the path
373	// to ensure that each variant of a module gets its own intermediates directory to write to.
374	ModuleSubDir() string
375
376	// Variable creates a new ninja variable scoped to the module.  It can be referenced by calls to Rule and Build
377	// in the same module.
378	Variable(pctx PackageContext, name, value string)
379
380	// Rule creates a new ninja rule scoped to the module.  It can be referenced by calls to Build in the same module.
381	Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule
382
383	// Build creates a new ninja build statement.
384	Build(pctx PackageContext, params BuildParams)
385
386	// GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
387	// but do not exist.  It can be used with Context.SetAllowMissingDependencies to allow the primary builder to
388	// handle missing dependencies on its own instead of having Blueprint treat them as an error.
389	GetMissingDependencies() []string
390}
391
392var _ BaseModuleContext = (*baseModuleContext)(nil)
393
394type baseModuleContext struct {
395	context        *Context
396	config         interface{}
397	module         *moduleInfo
398	errs           []error
399	visitingParent *moduleInfo
400	visitingDep    depInfo
401	ninjaFileDeps  []string
402}
403
404func (d *baseModuleContext) moduleInfo() *moduleInfo {
405	return d.module
406}
407
408func (d *baseModuleContext) Module() Module {
409	return d.module.logicModule
410}
411
412func (d *baseModuleContext) ModuleName() string {
413	return d.module.Name()
414}
415
416func (d *baseModuleContext) ModuleType() string {
417	return d.module.typeName
418}
419
420func (d *baseModuleContext) ModuleTags() map[string]string {
421	return map[string]string{
422		"module_name": d.ModuleName(),
423		"module_type": d.ModuleType(),
424	}
425}
426
427func (d *baseModuleContext) ContainsProperty(name string) bool {
428	_, ok := d.module.propertyPos[name]
429	return ok
430}
431
432func (d *baseModuleContext) ModuleDir() string {
433	return filepath.Dir(d.module.relBlueprintsFile)
434}
435
436func (d *baseModuleContext) BlueprintsFile() string {
437	return d.module.relBlueprintsFile
438}
439
440func (d *baseModuleContext) Config() interface{} {
441	return d.config
442}
443
444func (d *baseModuleContext) error(err error) {
445	if err != nil {
446		d.errs = append(d.errs, err)
447	}
448}
449
450func (d *baseModuleContext) Errorf(pos scanner.Position,
451	format string, args ...interface{}) {
452
453	d.error(&BlueprintError{
454		Err: fmt.Errorf(format, args...),
455		Pos: pos,
456	})
457}
458
459func (d *baseModuleContext) ModuleErrorf(format string,
460	args ...interface{}) {
461
462	d.error(d.context.ModuleErrorf(d.module.logicModule, format, args...))
463}
464
465func (d *baseModuleContext) PropertyErrorf(property, format string,
466	args ...interface{}) {
467
468	d.error(d.context.PropertyErrorf(d.module.logicModule, property, format, args...))
469}
470
471func (d *baseModuleContext) OtherModulePropertyErrorf(logicModule Module, property string, format string,
472	args ...interface{}) {
473
474	d.error(d.context.PropertyErrorf(logicModule, property, format, args...))
475}
476
477func (d *baseModuleContext) Failed() bool {
478	return len(d.errs) > 0
479}
480
481func (d *baseModuleContext) GlobWithDeps(pattern string,
482	excludes []string) ([]string, error) {
483	return d.context.glob(pattern, excludes)
484}
485
486func (d *baseModuleContext) Fs() pathtools.FileSystem {
487	return d.context.fs
488}
489
490func (d *baseModuleContext) Namespace() Namespace {
491	return d.context.nameInterface.GetNamespace(newNamespaceContext(d.module))
492}
493
494var _ ModuleContext = (*moduleContext)(nil)
495
496type moduleContext struct {
497	baseModuleContext
498	scope              *localScope
499	actionDefs         localBuildActions
500	handledMissingDeps bool
501}
502
503func (m *baseModuleContext) OtherModuleName(logicModule Module) string {
504	module := m.context.moduleInfo[logicModule]
505	return module.Name()
506}
507
508func (m *baseModuleContext) OtherModuleDir(logicModule Module) string {
509	module := m.context.moduleInfo[logicModule]
510	return filepath.Dir(module.relBlueprintsFile)
511}
512
513func (m *baseModuleContext) OtherModuleSubDir(logicModule Module) string {
514	module := m.context.moduleInfo[logicModule]
515	return module.variant.name
516}
517
518func (m *baseModuleContext) OtherModuleType(logicModule Module) string {
519	module := m.context.moduleInfo[logicModule]
520	return module.typeName
521}
522
523func (m *baseModuleContext) OtherModuleErrorf(logicModule Module, format string,
524	args ...interface{}) {
525
526	module := m.context.moduleInfo[logicModule]
527	m.errs = append(m.errs, &ModuleError{
528		BlueprintError: BlueprintError{
529			Err: fmt.Errorf(format, args...),
530			Pos: module.pos,
531		},
532		module: module,
533	})
534}
535
536func (m *baseModuleContext) OtherModuleDependencyTag(logicModule Module) DependencyTag {
537	// fast path for calling OtherModuleDependencyTag from inside VisitDirectDeps
538	if logicModule == m.visitingDep.module.logicModule {
539		return m.visitingDep.tag
540	}
541
542	for _, dep := range m.visitingParent.directDeps {
543		if dep.module.logicModule == logicModule {
544			return dep.tag
545		}
546	}
547
548	return nil
549}
550
551func (m *baseModuleContext) ModuleFromName(name string) (Module, bool) {
552	moduleGroup, exists := m.context.nameInterface.ModuleFromName(name, m.module.namespace())
553	if exists {
554		if len(moduleGroup.modules) != 1 {
555			panic(fmt.Errorf("Expected exactly one module named %q, but got %d", name, len(moduleGroup.modules)))
556		}
557		moduleInfo := moduleGroup.modules[0].module()
558		if moduleInfo != nil {
559			return moduleInfo.logicModule, true
560		} else {
561			panic(fmt.Errorf(`Expected actual module named %q, but group did not contain a module.
562    There may instead be an alias by that name.`, name))
563		}
564	}
565	return nil, exists
566}
567
568func (m *baseModuleContext) OtherModuleExists(name string) bool {
569	_, exists := m.context.nameInterface.ModuleFromName(name, m.module.namespace())
570	return exists
571}
572
573func (m *baseModuleContext) OtherModuleDependencyVariantExists(variations []Variation, name string) bool {
574	possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace())
575	if possibleDeps == nil {
576		return false
577	}
578	found, _ := m.context.findVariant(m.module, m.config, possibleDeps, variations, false, false)
579	return found != nil
580}
581
582func (m *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []Variation, name string) bool {
583	possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace())
584	if possibleDeps == nil {
585		return false
586	}
587	found, _ := m.context.findVariant(m.module, m.config, possibleDeps, variations, true, false)
588	return found != nil
589}
590
591func (m *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
592	possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace())
593	if possibleDeps == nil {
594		return false
595	}
596	found, _ := m.context.findVariant(m.module, m.config, possibleDeps, nil, false, true)
597	return found != nil
598}
599
600func (m *baseModuleContext) OtherModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) {
601	module := m.context.moduleInfo[logicModule]
602	return m.context.provider(module, provider.provider())
603}
604
605func (m *baseModuleContext) Provider(provider AnyProviderKey) (any, bool) {
606	return m.context.provider(m.module, provider.provider())
607}
608
609func (m *baseModuleContext) SetProvider(provider AnyProviderKey, value interface{}) {
610	m.context.setProvider(m.module, provider.provider(), value)
611}
612
613func (m *baseModuleContext) GetDirectDep(name string) (Module, DependencyTag) {
614	for _, dep := range m.module.directDeps {
615		if dep.module.Name() == name {
616			return dep.module.logicModule, dep.tag
617		}
618	}
619
620	return nil, nil
621}
622
623func (m *baseModuleContext) GetDirectDepWithTag(name string, tag DependencyTag) Module {
624	var deps []depInfo
625	for _, dep := range m.module.directDeps {
626		if dep.module.Name() == name {
627			if dep.tag == tag {
628				return dep.module.logicModule
629			}
630			deps = append(deps, dep)
631		}
632	}
633
634	if len(deps) != 0 {
635		panic(fmt.Errorf("Unable to find dependency %q with requested tag %#v. Found: %#v", deps[0].module, tag, deps))
636	}
637
638	return nil
639}
640
641func (m *baseModuleContext) VisitDirectDeps(visit func(Module)) {
642	defer func() {
643		if r := recover(); r != nil {
644			panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
645				m.module, funcName(visit), m.visitingDep.module))
646		}
647	}()
648
649	m.visitingParent = m.module
650
651	for _, dep := range m.module.directDeps {
652		m.visitingDep = dep
653		visit(dep.module.logicModule)
654	}
655
656	m.visitingParent = nil
657	m.visitingDep = depInfo{}
658}
659
660func (m *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
661	defer func() {
662		if r := recover(); r != nil {
663			panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
664				m.module, funcName(pred), funcName(visit), m.visitingDep.module))
665		}
666	}()
667
668	m.visitingParent = m.module
669
670	for _, dep := range m.module.directDeps {
671		m.visitingDep = dep
672		if pred(dep.module.logicModule) {
673			visit(dep.module.logicModule)
674		}
675	}
676
677	m.visitingParent = nil
678	m.visitingDep = depInfo{}
679}
680
681func (m *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
682	defer func() {
683		if r := recover(); r != nil {
684			panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s",
685				m.module, funcName(visit), m.visitingDep.module))
686		}
687	}()
688
689	m.context.walkDeps(m.module, false, nil, func(dep depInfo, parent *moduleInfo) {
690		m.visitingParent = parent
691		m.visitingDep = dep
692		visit(dep.module.logicModule)
693	})
694
695	m.visitingParent = nil
696	m.visitingDep = depInfo{}
697}
698
699func (m *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
700	visit func(Module)) {
701
702	defer func() {
703		if r := recover(); r != nil {
704			panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s",
705				m.module, funcName(pred), funcName(visit), m.visitingDep.module))
706		}
707	}()
708
709	m.context.walkDeps(m.module, false, nil, func(dep depInfo, parent *moduleInfo) {
710		if pred(dep.module.logicModule) {
711			m.visitingParent = parent
712			m.visitingDep = dep
713			visit(dep.module.logicModule)
714		}
715	})
716
717	m.visitingParent = nil
718	m.visitingDep = depInfo{}
719}
720
721func (m *baseModuleContext) WalkDeps(visit func(child, parent Module) bool) {
722	m.context.walkDeps(m.module, true, func(dep depInfo, parent *moduleInfo) bool {
723		m.visitingParent = parent
724		m.visitingDep = dep
725		return visit(dep.module.logicModule, parent.logicModule)
726	}, nil)
727
728	m.visitingParent = nil
729	m.visitingDep = depInfo{}
730}
731
732func (m *baseModuleContext) PrimaryModule() Module {
733	return m.module.group.modules.firstModule().logicModule
734}
735
736func (m *baseModuleContext) FinalModule() Module {
737	return m.module.group.modules.lastModule().logicModule
738}
739
740func (m *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
741	m.context.visitAllModuleVariants(m.module, visit)
742}
743
744func (m *baseModuleContext) AddNinjaFileDeps(deps ...string) {
745	m.ninjaFileDeps = append(m.ninjaFileDeps, deps...)
746}
747
748func (m *baseModuleContext) ModuleFactories() map[string]ModuleFactory {
749	ret := make(map[string]ModuleFactory)
750	for k, v := range m.context.moduleFactories {
751		ret[k] = v
752	}
753	return ret
754}
755
756func (m *baseModuleContext) base() *baseModuleContext {
757	return m
758}
759
760func (m *moduleContext) ModuleSubDir() string {
761	return m.module.variant.name
762}
763
764func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
765	m.scope.ReparentTo(pctx)
766
767	v, err := m.scope.AddLocalVariable(name, value)
768	if err != nil {
769		panic(err)
770	}
771
772	m.actionDefs.variables = append(m.actionDefs.variables, v)
773}
774
775func (m *moduleContext) Rule(pctx PackageContext, name string,
776	params RuleParams, argNames ...string) Rule {
777
778	m.scope.ReparentTo(pctx)
779
780	r, err := m.scope.AddLocalRule(name, &params, argNames...)
781	if err != nil {
782		panic(err)
783	}
784
785	m.actionDefs.rules = append(m.actionDefs.rules, r)
786
787	return r
788}
789
790func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
791	m.scope.ReparentTo(pctx)
792
793	def, err := parseBuildParams(m.scope, &params, m.ModuleTags())
794	if err != nil {
795		panic(err)
796	}
797
798	m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def)
799}
800
801func (m *moduleContext) GetMissingDependencies() []string {
802	m.handledMissingDeps = true
803	return m.module.missingDeps
804}
805
806func (m *baseModuleContext) EarlyGetMissingDependencies() []string {
807	return m.module.missingDeps
808}
809
810//
811// MutatorContext
812//
813
814type mutatorContext struct {
815	baseModuleContext
816	mutator          *mutatorInfo
817	reverseDeps      []reverseDep
818	rename           []rename
819	replace          []replace
820	newVariations    modulesOrAliases // new variants of existing modules
821	newModules       []*moduleInfo    // brand new modules
822	defaultVariation *string
823	pauseCh          chan<- pauseSpec
824}
825
826type BaseMutatorContext interface {
827	BaseModuleContext
828
829	// Rename all variants of a module.  The new name is not visible to calls to ModuleName,
830	// AddDependency or OtherModuleName until after this mutator pass is complete.
831	Rename(name string)
832
833	// MutatorName returns the name that this mutator was registered with.
834	MutatorName() string
835}
836
837type TopDownMutatorContext interface {
838	BaseMutatorContext
839
840	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
841	// the specified property structs to it as if the properties were set in a blueprint file.
842	CreateModule(ModuleFactory, string, ...interface{}) Module
843}
844
845type BottomUpMutatorContext interface {
846	BaseMutatorContext
847
848	// AddDependency adds a dependency to the given module.  It returns a slice of modules for each
849	// dependency (some entries may be nil).  Does not affect the ordering of the current mutator
850	// pass, but will be ordered correctly for all future mutator passes.
851	//
852	// If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
853	// new dependencies have had the current mutator called on them.  If the mutator is not
854	// parallel this method does not affect the ordering of the current mutator pass, but will
855	// be ordered correctly for all future mutator passes.
856	AddDependency(module Module, tag DependencyTag, name ...string) []Module
857
858	// AddReverseDependency adds a dependency from the destination to the given module.
859	// Does not affect the ordering of the current mutator pass, but will be ordered
860	// correctly for all future mutator passes.  All reverse dependencies for a destination module are
861	// collected until the end of the mutator pass, sorted by name, and then appended to the destination
862	// module's dependency list.
863	AddReverseDependency(module Module, tag DependencyTag, name string)
864
865	// CreateVariations splits  a module into multiple variants, one for each name in the variationNames
866	// parameter.  It returns a list of new modules in the same order as the variationNames
867	// list.
868	//
869	// If any of the dependencies of the module being operated on were already split
870	// by calling CreateVariations with the same name, the dependency will automatically
871	// be updated to point the matching variant.
872	//
873	// If a module is split, and then a module depending on the first module is not split
874	// when the Mutator is later called on it, the dependency of the depending module will
875	// automatically be updated to point to the first variant.
876	CreateVariations(variationNames ...string) []Module
877
878	// CreateLocalVariations splits a module into multiple variants, one for each name in the variationNames
879	// parameter.  It returns a list of new modules in the same order as the variantNames
880	// list.
881	//
882	// Local variations do not affect automatic dependency resolution - dependencies added
883	// to the split module via deps or DynamicDependerModule must exactly match a variant
884	// that contains all the non-local variations.
885	CreateLocalVariations(variationNames ...string) []Module
886
887	// SetDependencyVariation sets all dangling dependencies on the current module to point to the variation
888	// with given name. This function ignores the default variation set by SetDefaultDependencyVariation.
889	SetDependencyVariation(string)
890
891	// SetDefaultDependencyVariation sets the default variation when a dangling reference is detected
892	// during the subsequent calls on Create*Variations* functions. To reset, set it to nil.
893	SetDefaultDependencyVariation(*string)
894
895	// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
896	// argument to select which variant of the dependency to use.  It returns a slice of modules for
897	// each dependency (some entries may be nil).  A variant of the dependency must exist that matches
898	// the all of the non-local variations of the current module, plus the variations argument.
899	//
900	// If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
901	// new dependencies have had the current mutator called on them.  If the mutator is not
902	// parallel this method does not affect the ordering of the current mutator pass, but will
903	// be ordered correctly for all future mutator passes.
904	AddVariationDependencies([]Variation, DependencyTag, ...string) []Module
905
906	// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
907	// variations argument to select which variant of the dependency to use.  It returns a slice of
908	// modules for each dependency (some entries may be nil).  A variant of the dependency must
909	// exist that matches the variations argument, but may also have other variations.
910	// For any unspecified variation the first variant will be used.
911	//
912	// Unlike AddVariationDependencies, the variations of the current module are ignored - the
913	// dependency only needs to match the supplied variations.
914	//
915	// If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
916	// new dependencies have had the current mutator called on them.  If the mutator is not
917	// parallel this method does not affect the ordering of the current mutator pass, but will
918	// be ordered correctly for all future mutator passes.
919	AddFarVariationDependencies([]Variation, DependencyTag, ...string) []Module
920
921	// AddInterVariantDependency adds a dependency between two variants of the same module.  Variants are always
922	// ordered in the same order as they were listed in CreateVariations, and AddInterVariantDependency does not change
923	// that ordering, but it associates a DependencyTag with the dependency and makes it visible to VisitDirectDeps,
924	// WalkDeps, etc.
925	AddInterVariantDependency(tag DependencyTag, from, to Module)
926
927	// ReplaceDependencies finds all the variants of the module with the specified name, then
928	// replaces all dependencies onto those variants with the current variant of this module.
929	// Replacements don't take effect until after the mutator pass is finished.
930	ReplaceDependencies(string)
931
932	// ReplaceDependenciesIf finds all the variants of the module with the specified name, then
933	// replaces all dependencies onto those variants with the current variant of this module
934	// as long as the supplied predicate returns true.
935	// Replacements don't take effect until after the mutator pass is finished.
936	ReplaceDependenciesIf(string, ReplaceDependencyPredicate)
937
938	// AliasVariation takes a variationName that was passed to CreateVariations for this module,
939	// and creates an alias from the current variant (before the mutator has run) to the new
940	// variant.  The alias will be valid until the next time a mutator calls CreateVariations or
941	// CreateLocalVariations on this module without also calling AliasVariation.  The alias can
942	// be used to add dependencies on the newly created variant using the variant map from
943	// before CreateVariations was run.
944	AliasVariation(variationName string)
945
946	// CreateAliasVariation takes a toVariationName that was passed to CreateVariations for this
947	// module, and creates an alias from a new fromVariationName variant the toVariationName
948	// variant.  The alias will be valid until the next time a mutator calls CreateVariations or
949	// CreateLocalVariations on this module without also calling AliasVariation.  The alias can
950	// be used to add dependencies on the toVariationName variant using the fromVariationName
951	// variant.
952	CreateAliasVariation(fromVariationName, toVariationName string)
953
954	// SetVariationProvider sets the value for a provider for the given newly created variant of
955	// the current module, i.e. one of the Modules returned by CreateVariations..  It panics if
956	// not called during the appropriate mutator or GenerateBuildActions pass for the provider,
957	// if the value is not of the appropriate type, or if the module is not a newly created
958	// variant of the current module.  The value should not be modified after being passed to
959	// SetVariationProvider.
960	SetVariationProvider(module Module, provider AnyProviderKey, value interface{})
961}
962
963// A Mutator function is called for each Module, and can use
964// MutatorContext.CreateVariations to split a Module into multiple Modules,
965// modifying properties on the new modules to differentiate them.  It is called
966// after parsing all Blueprint files, but before generating any build rules,
967// and is always called on dependencies before being called on the depending module.
968//
969// The Mutator function should only modify members of properties structs, and not
970// members of the module struct itself, to ensure the modified values are copied
971// if a second Mutator chooses to split the module a second time.
972type TopDownMutator func(mctx TopDownMutatorContext)
973type BottomUpMutator func(mctx BottomUpMutatorContext)
974
975// DependencyTag is an interface to an arbitrary object that embeds BaseDependencyTag.  It can be
976// used to transfer information on a dependency between the mutator that called AddDependency
977// and the GenerateBuildActions method.  Variants created by CreateVariations have a copy of the
978// interface (pointing to the same concrete object) from their original module.
979type DependencyTag interface {
980	dependencyTag(DependencyTag)
981}
982
983type BaseDependencyTag struct {
984}
985
986func (BaseDependencyTag) dependencyTag(DependencyTag) {
987}
988
989var _ DependencyTag = BaseDependencyTag{}
990
991func (mctx *mutatorContext) MutatorName() string {
992	return mctx.mutator.name
993}
994
995func (mctx *mutatorContext) CreateVariations(variationNames ...string) []Module {
996	depChooser := chooseDepInherit(mctx.mutator.name, mctx.defaultVariation)
997	return mctx.createVariations(variationNames, depChooser, false)
998}
999
1000func (mctx *mutatorContext) createVariationsWithTransition(variationNames []string, outgoingTransitions [][]string) []Module {
1001	return mctx.createVariations(variationNames, chooseDepByIndexes(mctx.mutator.name, outgoingTransitions), false)
1002}
1003
1004func (mctx *mutatorContext) CreateLocalVariations(variationNames ...string) []Module {
1005	depChooser := chooseDepInherit(mctx.mutator.name, mctx.defaultVariation)
1006	return mctx.createVariations(variationNames, depChooser, true)
1007}
1008
1009func (mctx *mutatorContext) SetVariationProvider(module Module, provider AnyProviderKey, value interface{}) {
1010	for _, variant := range mctx.newVariations {
1011		if m := variant.module(); m != nil && m.logicModule == module {
1012			mctx.context.setProvider(m, provider.provider(), value)
1013			return
1014		}
1015	}
1016	panic(fmt.Errorf("module %q is not a newly created variant of %q", module, mctx.module))
1017}
1018
1019func (mctx *mutatorContext) createVariations(variationNames []string, depChooser depChooser, local bool) []Module {
1020	var ret []Module
1021	modules, errs := mctx.context.createVariations(mctx.module, mctx.mutator, depChooser, variationNames, local)
1022	if len(errs) > 0 {
1023		mctx.errs = append(mctx.errs, errs...)
1024	}
1025
1026	for _, module := range modules {
1027		ret = append(ret, module.module().logicModule)
1028	}
1029
1030	if mctx.newVariations != nil {
1031		panic("module already has variations from this mutator")
1032	}
1033	mctx.newVariations = modules
1034
1035	if len(ret) != len(variationNames) {
1036		panic("oops!")
1037	}
1038
1039	return ret
1040}
1041
1042func (mctx *mutatorContext) AliasVariation(variationName string) {
1043	for _, moduleOrAlias := range mctx.module.splitModules {
1044		if alias := moduleOrAlias.alias(); alias != nil {
1045			if alias.variant.variations.equal(mctx.module.variant.variations) {
1046				panic(fmt.Errorf("AliasVariation already called"))
1047			}
1048		}
1049	}
1050
1051	for _, variant := range mctx.newVariations {
1052		if variant.moduleOrAliasVariant().variations[mctx.mutator.name] == variationName {
1053			alias := &moduleAlias{
1054				variant: mctx.module.variant,
1055				target:  variant.moduleOrAliasTarget(),
1056			}
1057			// Prepend the alias so that AddFarVariationDependencies subset match matches
1058			// the alias before matching the first variation.
1059			mctx.module.splitModules = append(modulesOrAliases{alias}, mctx.module.splitModules...)
1060			return
1061		}
1062	}
1063
1064	var foundVariations []string
1065	for _, variant := range mctx.newVariations {
1066		foundVariations = append(foundVariations, variant.moduleOrAliasVariant().variations[mctx.mutator.name])
1067	}
1068	panic(fmt.Errorf("no %q variation in module variations %q", variationName, foundVariations))
1069}
1070
1071func (mctx *mutatorContext) CreateAliasVariation(aliasVariationName, targetVariationName string) {
1072	newVariant := newVariant(mctx.module, mctx.mutator.name, aliasVariationName, false)
1073
1074	for _, moduleOrAlias := range mctx.module.splitModules {
1075		if moduleOrAlias.moduleOrAliasVariant().variations.equal(newVariant.variations) {
1076			if alias := moduleOrAlias.alias(); alias != nil {
1077				panic(fmt.Errorf("can't alias %q to %q, already aliased to %q", aliasVariationName, targetVariationName, alias.target.variant.name))
1078			} else {
1079				panic(fmt.Errorf("can't alias %q to %q, there is already a variant with that name", aliasVariationName, targetVariationName))
1080			}
1081		}
1082	}
1083
1084	for _, variant := range mctx.newVariations {
1085		if variant.moduleOrAliasVariant().variations[mctx.mutator.name] == targetVariationName {
1086			// Append the alias here so that it comes after any aliases created by AliasVariation.
1087			mctx.module.splitModules = append(mctx.module.splitModules, &moduleAlias{
1088				variant: newVariant,
1089				target:  variant.moduleOrAliasTarget(),
1090			})
1091			return
1092		}
1093	}
1094
1095	var foundVariations []string
1096	for _, variant := range mctx.newVariations {
1097		foundVariations = append(foundVariations, variant.moduleOrAliasVariant().variations[mctx.mutator.name])
1098	}
1099	panic(fmt.Errorf("no %q variation in module variations %q", targetVariationName, foundVariations))
1100}
1101
1102func (mctx *mutatorContext) SetDependencyVariation(variationName string) {
1103	mctx.context.convertDepsToVariation(mctx.module, 0, chooseDepExplicit(
1104		mctx.mutator.name, variationName, nil))
1105}
1106
1107func (mctx *mutatorContext) SetDefaultDependencyVariation(variationName *string) {
1108	mctx.defaultVariation = variationName
1109}
1110
1111func (mctx *mutatorContext) Module() Module {
1112	return mctx.module.logicModule
1113}
1114
1115func (mctx *mutatorContext) AddDependency(module Module, tag DependencyTag, deps ...string) []Module {
1116	depInfos := make([]Module, 0, len(deps))
1117	for _, dep := range deps {
1118		modInfo := mctx.context.moduleInfo[module]
1119		depInfo, errs := mctx.context.addDependency(modInfo, mctx.config, tag, dep)
1120		if len(errs) > 0 {
1121			mctx.errs = append(mctx.errs, errs...)
1122		}
1123		if !mctx.pause(depInfo) {
1124			// Pausing not supported by this mutator, new dependencies can't be returned.
1125			depInfo = nil
1126		}
1127		depInfos = append(depInfos, maybeLogicModule(depInfo))
1128	}
1129	return depInfos
1130}
1131
1132func (mctx *mutatorContext) AddReverseDependency(module Module, tag DependencyTag, destName string) {
1133	if _, ok := tag.(BaseDependencyTag); ok {
1134		panic("BaseDependencyTag is not allowed to be used directly!")
1135	}
1136
1137	destModule, errs := mctx.context.findReverseDependency(mctx.context.moduleInfo[module], mctx.config, destName)
1138	if len(errs) > 0 {
1139		mctx.errs = append(mctx.errs, errs...)
1140		return
1141	}
1142
1143	mctx.reverseDeps = append(mctx.reverseDeps, reverseDep{
1144		destModule,
1145		depInfo{mctx.context.moduleInfo[module], tag},
1146	})
1147}
1148
1149func (mctx *mutatorContext) AddVariationDependencies(variations []Variation, tag DependencyTag,
1150	deps ...string) []Module {
1151
1152	depInfos := make([]Module, 0, len(deps))
1153	for _, dep := range deps {
1154		depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.config, variations, tag, dep, false)
1155		if len(errs) > 0 {
1156			mctx.errs = append(mctx.errs, errs...)
1157		}
1158		if !mctx.pause(depInfo) {
1159			// Pausing not supported by this mutator, new dependencies can't be returned.
1160			depInfo = nil
1161		}
1162		depInfos = append(depInfos, maybeLogicModule(depInfo))
1163	}
1164	return depInfos
1165}
1166
1167func (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation, tag DependencyTag,
1168	deps ...string) []Module {
1169
1170	depInfos := make([]Module, 0, len(deps))
1171	for _, dep := range deps {
1172		depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.config, variations, tag, dep, true)
1173		if len(errs) > 0 {
1174			mctx.errs = append(mctx.errs, errs...)
1175		}
1176		if !mctx.pause(depInfo) {
1177			// Pausing not supported by this mutator, new dependencies can't be returned.
1178			depInfo = nil
1179		}
1180		depInfos = append(depInfos, maybeLogicModule(depInfo))
1181	}
1182	return depInfos
1183}
1184
1185func (mctx *mutatorContext) AddInterVariantDependency(tag DependencyTag, from, to Module) {
1186	mctx.context.addInterVariantDependency(mctx.module, tag, from, to)
1187}
1188
1189func (mctx *mutatorContext) ReplaceDependencies(name string) {
1190	mctx.ReplaceDependenciesIf(name, nil)
1191}
1192
1193type ReplaceDependencyPredicate func(from Module, tag DependencyTag, to Module) bool
1194
1195func (mctx *mutatorContext) ReplaceDependenciesIf(name string, predicate ReplaceDependencyPredicate) {
1196	targets := mctx.context.moduleVariantsThatDependOn(name, mctx.module)
1197
1198	if len(targets) == 0 {
1199		panic(fmt.Errorf("ReplaceDependencies could not find identical variant {%s} for module %s\n"+
1200			"available variants:\n  %s",
1201			mctx.context.prettyPrintVariant(mctx.module.variant.variations),
1202			name,
1203			mctx.context.prettyPrintGroupVariants(mctx.context.moduleGroupFromName(name, mctx.module.namespace()))))
1204	}
1205
1206	for _, target := range targets {
1207		mctx.replace = append(mctx.replace, replace{target, mctx.module, predicate})
1208	}
1209}
1210
1211func (mctx *mutatorContext) Rename(name string) {
1212	mctx.rename = append(mctx.rename, rename{mctx.module.group, name})
1213}
1214
1215func (mctx *mutatorContext) CreateModule(factory ModuleFactory, typeName string, props ...interface{}) Module {
1216	module := newModule(factory)
1217
1218	module.relBlueprintsFile = mctx.module.relBlueprintsFile
1219	module.pos = mctx.module.pos
1220	module.propertyPos = mctx.module.propertyPos
1221	module.createdBy = mctx.module
1222	module.typeName = typeName
1223
1224	for _, p := range props {
1225		err := proptools.AppendMatchingProperties(module.properties, p, nil)
1226		if err != nil {
1227			panic(err)
1228		}
1229	}
1230
1231	mctx.newModules = append(mctx.newModules, module)
1232
1233	return module.logicModule
1234}
1235
1236// pause waits until the given dependency has been visited by the mutator's parallelVisit call.
1237// It returns true if the pause was supported, false if the pause was not supported and did not
1238// occur, which will happen when the mutator is not parallelizable.  If the dependency is nil
1239// it returns true if pausing is supported or false if it is not.
1240func (mctx *mutatorContext) pause(dep *moduleInfo) bool {
1241	if mctx.pauseCh != nil {
1242		if dep != nil {
1243			unpause := make(unpause)
1244			mctx.pauseCh <- pauseSpec{
1245				paused:  mctx.module,
1246				until:   dep,
1247				unpause: unpause,
1248			}
1249			<-unpause
1250		}
1251		return true
1252	}
1253	return false
1254}
1255
1256// SimpleName is an embeddable object to implement the ModuleContext.Name method using a property
1257// called "name".  Modules that embed it must also add SimpleName.Properties to their property
1258// structure list.
1259type SimpleName struct {
1260	Properties struct {
1261		Name string
1262	}
1263}
1264
1265func (s *SimpleName) Name() string {
1266	return s.Properties.Name
1267}
1268
1269// Load Hooks
1270
1271type LoadHookContext interface {
1272	EarlyModuleContext
1273
1274	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
1275	// the specified property structs to it as if the properties were set in a blueprint file.
1276	CreateModule(ModuleFactory, string, ...interface{}) Module
1277
1278	// RegisterScopedModuleType creates a new module type that is scoped to the current Blueprints
1279	// file.
1280	RegisterScopedModuleType(name string, factory ModuleFactory)
1281}
1282
1283func (l *loadHookContext) CreateModule(factory ModuleFactory, typeName string, props ...interface{}) Module {
1284	module := newModule(factory)
1285
1286	module.relBlueprintsFile = l.module.relBlueprintsFile
1287	module.pos = l.module.pos
1288	module.propertyPos = l.module.propertyPos
1289	module.createdBy = l.module
1290	module.typeName = typeName
1291
1292	for _, p := range props {
1293		err := proptools.AppendMatchingProperties(module.properties, p, nil)
1294		if err != nil {
1295			panic(err)
1296		}
1297	}
1298
1299	l.newModules = append(l.newModules, module)
1300
1301	return module.logicModule
1302}
1303
1304func (l *loadHookContext) RegisterScopedModuleType(name string, factory ModuleFactory) {
1305	if _, exists := l.context.moduleFactories[name]; exists {
1306		panic(fmt.Errorf("A global module type named %q already exists", name))
1307	}
1308
1309	if _, exists := (*l.scopedModuleFactories)[name]; exists {
1310		panic(fmt.Errorf("A module type named %q already exists in this scope", name))
1311	}
1312
1313	if *l.scopedModuleFactories == nil {
1314		*l.scopedModuleFactories = make(map[string]ModuleFactory)
1315	}
1316
1317	(*l.scopedModuleFactories)[name] = factory
1318}
1319
1320type loadHookContext struct {
1321	baseModuleContext
1322	newModules            []*moduleInfo
1323	scopedModuleFactories *map[string]ModuleFactory
1324}
1325
1326type LoadHook func(ctx LoadHookContext)
1327
1328// Load hooks need to be added by module factories, which don't have any parameter to get to the
1329// Context, and only produce a Module interface with no base implementation, so the load hooks
1330// must be stored in a global map.  The key is a pointer allocated by the module factory, so there
1331// is no chance of collisions even if tests are running in parallel with multiple contexts.  The
1332// contents should be short-lived, they are added during a module factory and removed immediately
1333// after the module factory returns.
1334var pendingHooks sync.Map
1335
1336func AddLoadHook(module Module, hook LoadHook) {
1337	// Only one goroutine can be processing a given module, so no additional locking is required
1338	// for the slice stored in the sync.Map.
1339	v, exists := pendingHooks.Load(module)
1340	if !exists {
1341		v, _ = pendingHooks.LoadOrStore(module, new([]LoadHook))
1342	}
1343	hooks := v.(*[]LoadHook)
1344	*hooks = append(*hooks, hook)
1345}
1346
1347func runAndRemoveLoadHooks(ctx *Context, config interface{}, module *moduleInfo,
1348	scopedModuleFactories *map[string]ModuleFactory) (newModules []*moduleInfo, deps []string, errs []error) {
1349
1350	if v, exists := pendingHooks.Load(module.logicModule); exists {
1351		hooks := v.(*[]LoadHook)
1352
1353		for _, hook := range *hooks {
1354			mctx := &loadHookContext{
1355				baseModuleContext: baseModuleContext{
1356					context: ctx,
1357					config:  config,
1358					module:  module,
1359				},
1360				scopedModuleFactories: scopedModuleFactories,
1361			}
1362			hook(mctx)
1363			newModules = append(newModules, mctx.newModules...)
1364			deps = append(deps, mctx.ninjaFileDeps...)
1365			errs = append(errs, mctx.errs...)
1366		}
1367		pendingHooks.Delete(module.logicModule)
1368
1369		return newModules, deps, errs
1370	}
1371
1372	return nil, nil, nil
1373}
1374
1375// Check the syntax of a generated blueprint file.
1376//
1377// This is intended to perform a quick syntactic check for generated blueprint
1378// code, where syntactically correct means:
1379// * No variable definitions.
1380// * Valid module types.
1381// * Valid property names.
1382// * Valid values for the property type.
1383//
1384// It does not perform any semantic checking of properties, existence of referenced
1385// files, or dependencies.
1386//
1387// At a low level it:
1388// * Parses the contents.
1389// * Invokes relevant factory to create Module instances.
1390// * Unpacks the properties into the Module.
1391// * Does not invoke load hooks or any mutators.
1392//
1393// The filename is only used for reporting errors.
1394func CheckBlueprintSyntax(moduleFactories map[string]ModuleFactory, filename string, contents string) []error {
1395	scope := parser.NewScope(nil)
1396	file, errs := parser.Parse(filename, strings.NewReader(contents), scope)
1397	if len(errs) != 0 {
1398		return errs
1399	}
1400
1401	for _, def := range file.Defs {
1402		switch def := def.(type) {
1403		case *parser.Module:
1404			_, moduleErrs := processModuleDef(def, filename, moduleFactories, nil, false)
1405			errs = append(errs, moduleErrs...)
1406
1407		default:
1408			panic(fmt.Errorf("unknown definition type: %T", def))
1409		}
1410	}
1411
1412	return errs
1413}
1414
1415func maybeLogicModule(module *moduleInfo) Module {
1416	if module != nil {
1417		return module.logicModule
1418	} else {
1419		return nil
1420	}
1421}
1422