• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 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 android
16
17import (
18	"fmt"
19	"regexp"
20	"slices"
21	"strings"
22
23	"github.com/google/blueprint"
24	"github.com/google/blueprint/proptools"
25)
26
27// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
28// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module
29// instead of a blueprint.Module, plus some extra methods that return Android-specific information
30// about the current module.
31type BaseModuleContext interface {
32	ArchModuleContext
33	EarlyModuleContext
34
35	blueprintBaseModuleContext() blueprint.BaseModuleContext
36
37	// OtherModuleName returns the name of another Module.  See BaseModuleContext.ModuleName for more information.
38	// It is intended for use inside the visit functions of Visit* and WalkDeps.
39	OtherModuleName(m blueprint.Module) string
40
41	// OtherModuleDir returns the directory of another Module.  See BaseModuleContext.ModuleDir for more information.
42	// It is intended for use inside the visit functions of Visit* and WalkDeps.
43	OtherModuleDir(m blueprint.Module) string
44
45	// OtherModuleErrorf reports an error on another Module.  See BaseModuleContext.ModuleErrorf for more information.
46	// It is intended for use inside the visit functions of Visit* and WalkDeps.
47	OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
48
49	// OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
50	// on the module.  When called inside a Visit* method with current module being visited, and there are multiple
51	// dependencies on the module being visited, it returns the dependency tag used for the current dependency.
52	OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
53
54	// OtherModuleSubDir returns the string representing the variations of a module.
55	OtherModuleSubDir(m blueprint.Module) string
56
57	// OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
58	// passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
59	OtherModuleExists(name string) bool
60
61	// OtherModuleDependencyVariantExists returns true if a module with the
62	// specified name and variant exists. The variant must match the given
63	// variations. It must also match all the non-local variations of the current
64	// module. In other words, it checks for the module that AddVariationDependencies
65	// would add a dependency on with the same arguments.
66	OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
67
68	// OtherModuleFarDependencyVariantExists returns true if a module with the
69	// specified name and variant exists. The variant must match the given
70	// variations, but not the non-local variations of the current module. In
71	// other words, it checks for the module that AddFarVariationDependencies
72	// would add a dependency on with the same arguments.
73	OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
74
75	// OtherModuleReverseDependencyVariantExists returns true if a module with the
76	// specified name exists with the same variations as the current module. In
77	// other words, it checks for the module that AddReverseDependency would add a
78	// dependency on with the same argument.
79	OtherModuleReverseDependencyVariantExists(name string) bool
80
81	// OtherModuleType returns the type of another Module.  See BaseModuleContext.ModuleType for more information.
82	// It is intended for use inside the visit functions of Visit* and WalkDeps.
83	OtherModuleType(m blueprint.Module) string
84
85	// otherModuleProvider returns the value for a provider for the given module.  If the value is
86	// not set it returns nil and false.  The value returned may be a deep copy of the value originally
87	// passed to SetProvider.
88	//
89	// This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
90	otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
91
92	// OtherModuleHasProvider returns true if the module has the given provider set. This
93	// can avoid copying the provider if the caller only cares about the existence of
94	// the provider.
95	OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool
96
97	// OtherModuleIsAutoGenerated returns true if the module is auto generated by another module
98	// instead of being defined in Android.bp file.
99	OtherModuleIsAutoGenerated(m blueprint.Module) bool
100
101	// Provider returns the value for a provider for the current module.  If the value is
102	// not set it returns nil and false.  It panics if called before the appropriate
103	// mutator or GenerateBuildActions pass for the provider.  The value returned may be a deep
104	// copy of the value originally passed to SetProvider.
105	//
106	// This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
107	provider(provider blueprint.AnyProviderKey) (any, bool)
108
109	// setProvider sets the value for a provider for the current module.  It panics if not called
110	// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
111	// is not of the appropriate type, or if the value has already been set.  The value should not
112	// be modified after being passed to SetProvider.
113	//
114	// This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
115	setProvider(provider blueprint.AnyProviderKey, value any)
116
117	GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
118
119	GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy
120
121	// GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
122	// none exists.  It panics if the dependency does not have the specified tag.  It skips any
123	// dependencies that are not an android.Module.
124	GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module
125
126	GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy
127
128	// VisitDirectDeps calls visit for each direct dependency.  If there are multiple
129	// direct dependencies on the same module visit will be called multiple times on that module
130	// and OtherModuleDependencyTag will return a different tag for each.  It raises an error if any of the
131	// dependencies are disabled.
132	//
133	// The Module passed to the visit function should not be retained outside of the visit
134	// function, it may be invalidated by future mutators.
135	VisitDirectDeps(visit func(Module))
136
137	// VisitDirectDepsProxy calls visit for each direct dependency.  If there are multiple
138	// direct dependencies on the same module visit will be called multiple times on that module
139	// and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
140	// dependencies are disabled.
141	//
142	// The ModuleProxy passed to the visit function should not be retained outside of the visit
143	// function, it may be invalidated by future mutators.
144	VisitDirectDepsProxy(visit func(proxy ModuleProxy))
145
146	// VisitDirectDepsProxyAllowDisabled calls visit for each direct dependency.  If there are
147	// multiple direct dependencies on the same module visit will be called multiple times on
148	// that module and OtherModuleDependencyTag will return a different tag for each.
149	//
150	// The ModuleProxy passed to the visit function should not be retained outside of the visit function, it may be
151	// invalidated by future mutators.
152	VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy))
153
154	VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
155
156	VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy))
157
158	// VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit.  If there are
159	// multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
160	// OtherModuleDependencyTag will return a different tag for each.  It skips any
161	// dependencies that are not an android.Module.
162	//
163	// The Module passed to the visit function should not be retained outside of the visit function, it may be
164	// invalidated by future mutators.
165	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
166	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
167	VisitDepsDepthFirst(visit func(Module))
168	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
169	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
170
171	// WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order.  visit may
172	// be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
173	// child and parent with different tags.  OtherModuleDependencyTag will return the tag for the currently visited
174	// (child, parent) pair.  If visit returns false WalkDeps will not continue recursing down to child.  It skips
175	// any dependencies that are not an android.Module.
176	//
177	// The Modules passed to the visit function should not be retained outside of the visit function, they may be
178	// invalidated by future mutators.
179	WalkDeps(visit func(child, parent Module) bool)
180
181	// WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order.  visit may
182	// be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
183	// child and parent with different tags.  OtherModuleDependencyTag will return the tag for the currently visited
184	// (child, parent) pair.  If visit returns false WalkDeps will not continue recursing down to child.  It skips
185	// any dependencies that are not an android.Module.
186	//
187	// The Modules passed to the visit function should not be retained outside of the visit function, they may be
188	// invalidated by future mutators.
189	WalkDepsProxy(visit func(child, parent ModuleProxy) bool)
190
191	// GetWalkPath is supposed to be called in visit function passed in WalkDeps()
192	// and returns a top-down dependency path from a start module to current child module.
193	GetWalkPath() []Module
194
195	// PrimaryModule returns the first variant of the current module.  Variants of a module are always visited in
196	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
197	// Module returned by PrimaryModule without data races.  This can be used to perform singleton actions that are
198	// only done once for all variants of a module.
199	PrimaryModule() Module
200
201	// FinalModule returns the last variant of the current module.  Variants of a module are always visited in
202	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
203	// variants using VisitAllModuleVariants if the current module == FinalModule().  This can be used to perform
204	// singleton actions that are only done once for all variants of a module.
205	FinalModule() Module
206
207	// IsFinalModule returns if the current module is the last variant.  Variants of a module are always visited in
208	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
209	// variants using VisitAllModuleVariants if the current module is the last one. This can be used to perform
210	// singleton actions that are only done once for all variants of a module.
211	IsFinalModule(module Module) bool
212
213	// VisitAllModuleVariants calls visit for each variant of the current module.  Variants of a module are always
214	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
215	// from all variants if the current module is the last one. Otherwise, care must be taken to not access any
216	// data modified by the current mutator.
217	VisitAllModuleVariants(visit func(Module))
218
219	// VisitAllModuleVariantProxies calls visit for each variant of the current module.  Variants of a module are always
220	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
221	// from all variants if the current module is the last one. Otherwise, care must be taken to not access any
222	// data modified by the current mutator.
223	VisitAllModuleVariantProxies(visit func(proxy ModuleProxy))
224
225	// GetTagPath is supposed to be called in visit function passed in WalkDeps()
226	// and returns a top-down dependency tags path from a start module to current child module.
227	// It has one less entry than GetWalkPath() as it contains the dependency tags that
228	// exist between each adjacent pair of modules in the GetWalkPath().
229	// GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
230	GetTagPath() []blueprint.DependencyTag
231
232	// GetPathString is supposed to be called in visit function passed in WalkDeps()
233	// and returns a multi-line string showing the modules and dependency tags
234	// among them along the top-down dependency path from a start module to current child module.
235	// skipFirst when set to true, the output doesn't include the start module,
236	// which is already printed when this function is used along with ModuleErrorf().
237	GetPathString(skipFirst bool) string
238
239	AddMissingDependencies(missingDeps []string)
240
241	// getMissingDependencies returns the list of missing dependencies.
242	// Calling this function prevents adding new dependencies.
243	getMissingDependencies() []string
244
245	// EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
246	// can be used to evaluate the final value of Configurable properties.
247	EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue
248}
249
250type baseModuleContext struct {
251	bp blueprint.BaseModuleContext
252	earlyModuleContext
253	archModuleContext
254
255	walkPath []Module
256	tagPath  []blueprint.DependencyTag
257
258	strictVisitDeps bool // If true, enforce that all dependencies are enabled
259
260}
261
262func getWrappedModule(module blueprint.Module) blueprint.Module {
263	if mp, isProxy := module.(*ModuleProxy); isProxy {
264		return mp.module
265	}
266	if mp, isProxy := module.(ModuleProxy); isProxy {
267		return mp.module
268	}
269	return module
270}
271
272func EqualModules(m1, m2 Module) bool {
273	return blueprint.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
274}
275
276func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
277	return b.bp.OtherModuleName(getWrappedModule(m))
278}
279func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string {
280	return b.bp.OtherModuleDir(getWrappedModule(m))
281}
282func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
283	b.bp.OtherModuleErrorf(getWrappedModule(m), fmt, args...)
284}
285func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
286	return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
287}
288func (b *baseModuleContext) OtherModuleSubDir(m blueprint.Module) string {
289	return b.bp.OtherModuleSubDir(getWrappedModule(m))
290}
291func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
292func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
293	return b.bp.OtherModuleDependencyVariantExists(variations, name)
294}
295func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
296	return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
297}
298func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
299	return b.bp.OtherModuleReverseDependencyVariantExists(name)
300}
301func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
302	return b.bp.OtherModuleType(getWrappedModule(m))
303}
304
305func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
306	return b.bp.OtherModuleProvider(getWrappedModule(m), provider)
307}
308
309func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool {
310	return b.bp.OtherModuleHasProvider(getWrappedModule(m), provider)
311}
312
313func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool {
314	return b.bp.OtherModuleIsAutoGenerated(m)
315}
316
317func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
318	return b.bp.Provider(provider)
319}
320
321func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
322	b.bp.SetProvider(provider, value)
323}
324
325func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module {
326	if module := b.bp.GetDirectDepWithTag(name, tag); module != nil {
327		return module.(Module)
328	}
329	return nil
330}
331
332func (b *baseModuleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy {
333	if module := b.bp.GetDirectDepProxyWithTag(name, tag); module != nil {
334		return &ModuleProxy{*module}
335	}
336	return nil
337}
338
339func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
340	return b.bp
341}
342
343func (b *baseModuleContext) AddMissingDependencies(deps []string) {
344	if deps != nil {
345		missingDeps := &b.Module().base().commonProperties.MissingDeps
346		*missingDeps = append(*missingDeps, deps...)
347		*missingDeps = FirstUniqueStrings(*missingDeps)
348	}
349}
350
351func (b *baseModuleContext) checkedMissingDeps() bool {
352	return b.Module().base().commonProperties.CheckedMissingDeps
353}
354
355func (b *baseModuleContext) getMissingDependencies() []string {
356	checked := &b.Module().base().commonProperties.CheckedMissingDeps
357	*checked = true
358	var missingDeps []string
359	missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
360	missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
361	missingDeps = FirstUniqueStrings(missingDeps)
362	return missingDeps
363}
364
365type AllowDisabledModuleDependency interface {
366	blueprint.DependencyTag
367	AllowDisabledModuleDependency(target Module) bool
368	AllowDisabledModuleDependencyProxy(ctx OtherModuleProviderContext, target ModuleProxy) bool
369}
370
371type AlwaysAllowDisabledModuleDependencyTag struct{}
372
373func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
374	return true
375}
376
377func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependencyProxy(OtherModuleProviderContext, ModuleProxy) bool {
378	return true
379}
380
381func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
382	aModule, _ := module.(Module)
383
384	if !strict {
385		return aModule
386	}
387
388	if aModule == nil {
389		panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag))
390	}
391
392	if !aModule.Enabled(b) {
393		if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
394			if b.Config().AllowMissingDependencies() {
395				b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
396			} else {
397				b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
398			}
399		}
400		return nil
401	}
402	return aModule
403}
404
405func (b *baseModuleContext) validateAndroidModuleProxy(
406	module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) *ModuleProxy {
407	aModule := ModuleProxy{module: module}
408
409	if !strict {
410		return &aModule
411	}
412
413	if !OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).Enabled {
414		if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) {
415			if b.Config().AllowMissingDependencies() {
416				b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
417			} else {
418				b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
419			}
420		}
421		return nil
422	}
423
424	return &aModule
425}
426
427func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []Module {
428	var deps []Module
429	b.VisitDirectDeps(func(module Module) {
430		if module.base().BaseModuleName() == name {
431			returnedTag := b.bp.OtherModuleDependencyTag(module)
432			if tag == nil || returnedTag == tag {
433				deps = append(deps, module)
434			}
435		}
436	})
437	return deps
438}
439
440func (b *baseModuleContext) getDirectDepsProxyInternal(name string, tag blueprint.DependencyTag) []ModuleProxy {
441	var deps []ModuleProxy
442	b.VisitDirectDepsProxy(func(module ModuleProxy) {
443		if OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).BaseModuleName == name {
444			returnedTag := b.OtherModuleDependencyTag(module)
445			if tag == nil || returnedTag == tag {
446				deps = append(deps, module)
447			}
448		}
449	})
450	return deps
451}
452
453func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
454	var deps []Module
455	b.VisitDirectDeps(func(module Module) {
456		if b.bp.OtherModuleDependencyTag(module) == tag {
457			deps = append(deps, module)
458		}
459	})
460	return deps
461}
462
463func (b *baseModuleContext) GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy {
464	var deps []ModuleProxy
465	b.VisitDirectDepsProxy(func(module ModuleProxy) {
466		if b.OtherModuleDependencyTag(module) == tag {
467			deps = append(deps, module)
468		}
469	})
470	return deps
471}
472
473func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
474	b.bp.VisitDirectDeps(func(module blueprint.Module) {
475		if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
476			visit(aModule)
477		}
478	})
479}
480
481func (b *baseModuleContext) VisitDirectDepsProxy(visit func(ModuleProxy)) {
482	b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
483		if aModule := b.validateAndroidModuleProxy(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
484			visit(*aModule)
485		}
486	})
487}
488
489func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) {
490	b.bp.VisitDirectDepsProxy(visitProxyAdaptor(visit))
491}
492
493func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
494	b.bp.VisitDirectDeps(func(module blueprint.Module) {
495		if b.bp.OtherModuleDependencyTag(module) == tag {
496			if aModule := b.validateAndroidModule(module, tag, b.strictVisitDeps); aModule != nil {
497				visit(aModule)
498			}
499		}
500	})
501}
502
503func (b *baseModuleContext) VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) {
504	b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
505		if b.bp.OtherModuleDependencyTag(module) == tag {
506			if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); aModule != nil {
507				visit(*aModule)
508			}
509		}
510	})
511}
512
513func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
514	b.bp.VisitDirectDepsIf(
515		// pred
516		func(module blueprint.Module) bool {
517			if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
518				return pred(aModule)
519			} else {
520				return false
521			}
522		},
523		// visit
524		func(module blueprint.Module) {
525			visit(module.(Module))
526		})
527}
528
529func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
530	b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
531		if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
532			visit(aModule)
533		}
534	})
535}
536
537func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
538	b.bp.VisitDepsDepthFirstIf(
539		// pred
540		func(module blueprint.Module) bool {
541			if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
542				return pred(aModule)
543			} else {
544				return false
545			}
546		},
547		// visit
548		func(module blueprint.Module) {
549			visit(module.(Module))
550		})
551}
552
553func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
554	b.walkPath = []Module{b.Module()}
555	b.tagPath = []blueprint.DependencyTag{}
556	b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
557		childAndroidModule, _ := child.(Module)
558		parentAndroidModule, _ := parent.(Module)
559		if childAndroidModule != nil && parentAndroidModule != nil {
560			// record walkPath before visit
561			for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
562				b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
563				b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
564			}
565			b.walkPath = append(b.walkPath, childAndroidModule)
566			b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
567			return visit(childAndroidModule, parentAndroidModule)
568		} else {
569			return false
570		}
571	})
572}
573
574func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) {
575	b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
576	b.tagPath = []blueprint.DependencyTag{}
577	b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
578		childAndroidModule := ModuleProxy{child}
579		parentAndroidModule := ModuleProxy{parent}
580		// record walkPath before visit
581		for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
582			b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
583			b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
584		}
585		b.walkPath = append(b.walkPath, childAndroidModule)
586		b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
587		return visit(childAndroidModule, parentAndroidModule)
588	})
589}
590
591func (b *baseModuleContext) GetWalkPath() []Module {
592	return slices.Clone(b.walkPath)
593}
594
595func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
596	return b.tagPath
597}
598
599func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
600	b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
601		visit(module.(Module))
602	})
603}
604
605func (b *baseModuleContext) VisitAllModuleVariantProxies(visit func(ModuleProxy)) {
606	b.bp.VisitAllModuleVariantProxies(visitProxyAdaptor(visit))
607}
608
609func (b *baseModuleContext) PrimaryModule() Module {
610	return b.bp.PrimaryModule().(Module)
611}
612
613func (b *baseModuleContext) FinalModule() Module {
614	return b.bp.FinalModule().(Module)
615}
616
617func (b *baseModuleContext) IsFinalModule(module Module) bool {
618	return b.bp.IsFinalModule(module)
619}
620
621// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
622func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
623	if tag == licenseKindTag {
624		return true
625	} else if tag == licensesTag {
626		return true
627	} else if tag == AcDepTag {
628		return true
629	}
630	return false
631}
632
633// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
634// a dependency tag.
635var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
636
637// PrettyPrintTag returns string representation of the tag, but prefers
638// custom String() method if available.
639func PrettyPrintTag(tag blueprint.DependencyTag) string {
640	// Use tag's custom String() method if available.
641	if stringer, ok := tag.(fmt.Stringer); ok {
642		return stringer.String()
643	}
644
645	// Otherwise, get a default string representation of the tag's struct.
646	tagString := fmt.Sprintf("%T: %+v", tag, tag)
647
648	// Remove the boilerplate from BaseDependencyTag as it adds no value.
649	tagString = tagCleaner.ReplaceAllString(tagString, "")
650	return tagString
651}
652
653func (b *baseModuleContext) GetPathString(skipFirst bool) string {
654	sb := strings.Builder{}
655	tagPath := b.GetTagPath()
656	walkPath := b.GetWalkPath()
657	if !skipFirst {
658		sb.WriteString(walkPath[0].String())
659	}
660	for i, m := range walkPath[1:] {
661		sb.WriteString("\n")
662		sb.WriteString(fmt.Sprintf("           via tag %s\n", PrettyPrintTag(tagPath[i])))
663		sb.WriteString(fmt.Sprintf("    -> %s", m.String()))
664	}
665	return sb.String()
666}
667
668func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
669	return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property)
670}
671