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