blob: 7fa58766ff415a8cf6fe9590c2335b85ee9d6b06 [file] [log] [blame]
Colin Cross69452e12023-11-15 11:20:53 -08001// 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"
Colin Cross69452e12023-11-15 11:20:53 -080019 "regexp"
Colin Crossb614cd42024-10-11 12:52:21 -070020 "slices"
Colin Cross69452e12023-11-15 11:20:53 -080021 "strings"
Cole Faustbdd8aee2024-03-14 14:33:02 -070022
23 "github.com/google/blueprint"
Cole Faustfdbf5d42024-04-10 15:01:23 -070024 "github.com/google/blueprint/proptools"
Colin Cross69452e12023-11-15 11:20:53 -080025)
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 {
Colin Cross1d3d9f12024-01-18 14:30:22 -080032 ArchModuleContext
Colin Cross69452e12023-11-15 11:20:53 -080033 EarlyModuleContext
34
35 blueprintBaseModuleContext() blueprint.BaseModuleContext
36
Yu Liudd9ccb42024-10-07 17:07:44 +000037 EqualModules(m1, m2 Module) bool
38
Colin Cross69452e12023-11-15 11:20:53 -080039 // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
40 // It is intended for use inside the visit functions of Visit* and WalkDeps.
41 OtherModuleName(m blueprint.Module) string
42
43 // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
44 // It is intended for use inside the visit functions of Visit* and WalkDeps.
45 OtherModuleDir(m blueprint.Module) string
46
47 // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
48 // It is intended for use inside the visit functions of Visit* and WalkDeps.
49 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
50
51 // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
52 // on the module. When called inside a Visit* method with current module being visited, and there are multiple
53 // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
54 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
55
56 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
57 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
58 OtherModuleExists(name string) bool
59
60 // OtherModuleDependencyVariantExists returns true if a module with the
61 // specified name and variant exists. The variant must match the given
62 // variations. It must also match all the non-local variations of the current
63 // module. In other words, it checks for the module that AddVariationDependencies
64 // would add a dependency on with the same arguments.
65 OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
66
67 // OtherModuleFarDependencyVariantExists returns true if a module with the
68 // specified name and variant exists. The variant must match the given
69 // variations, but not the non-local variations of the current module. In
70 // other words, it checks for the module that AddFarVariationDependencies
71 // would add a dependency on with the same arguments.
72 OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
73
74 // OtherModuleReverseDependencyVariantExists returns true if a module with the
75 // specified name exists with the same variations as the current module. In
76 // other words, it checks for the module that AddReverseDependency would add a
77 // dependency on with the same argument.
78 OtherModuleReverseDependencyVariantExists(name string) bool
79
80 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
81 // It is intended for use inside the visit functions of Visit* and WalkDeps.
82 OtherModuleType(m blueprint.Module) string
83
Colin Cross24c1cbe2023-12-21 23:42:56 +000084 // otherModuleProvider returns the value for a provider for the given module. If the value is
85 // not set it returns nil and false. The value returned may be a deep copy of the value originally
86 // passed to SetProvider.
87 //
88 // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080089 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080090
91 // Provider returns the value for a provider for the current module. If the value is
Colin Cross24c1cbe2023-12-21 23:42:56 +000092 // not set it returns nil and false. It panics if called before the appropriate
Colin Cross69452e12023-11-15 11:20:53 -080093 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
94 // copy of the value originally passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +000095 //
96 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080097 provider(provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080098
Colin Cross24c1cbe2023-12-21 23:42:56 +000099 // setProvider sets the value for a provider for the current module. It panics if not called
Colin Cross69452e12023-11-15 11:20:53 -0800100 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
101 // is not of the appropriate type, or if the value has already been set. The value should not
102 // be modified after being passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000103 //
104 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
105 setProvider(provider blueprint.AnyProviderKey, value any)
Colin Cross69452e12023-11-15 11:20:53 -0800106
107 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
108
109 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
110 // none exists. It panics if the dependency does not have the specified tag. It skips any
111 // dependencies that are not an android.Module.
112 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
113
LaMont Jones34314b72024-01-18 18:27:35 +0000114 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
Colin Cross69452e12023-11-15 11:20:53 -0800115 // name, or nil if none exists. If there are multiple dependencies on the same module it returns
116 // the first DependencyTag.
117 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
118
Colin Cross648daea2024-09-12 14:35:29 -0700119 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
120 // direct dependencies on the same module visit will be called multiple times on that module
121 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
122 // dependencies are disabled.
123 //
124 // The Module passed to the visit function should not be retained outside of the visit
125 // function, it may be invalidated by future mutators.
126 VisitDirectDeps(visit func(Module))
127
128 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
Colin Cross69452e12023-11-15 11:20:53 -0800129 // 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.
131 //
132 // The Module passed to the visit function should not be retained outside of the visit
133 // function, it may be invalidated by future mutators.
Colin Cross648daea2024-09-12 14:35:29 -0700134 VisitDirectDepsAllowDisabled(visit func(Module))
Colin Cross69452e12023-11-15 11:20:53 -0800135
Yu Liudd9ccb42024-10-07 17:07:44 +0000136 // VisitDirectDepsProxyAllowDisabled calls visit for each direct dependency. If there are
137 // multiple direct dependencies on the same module visit will be called multiple times on
138 // that module and OtherModuleDependencyTag will return a different tag for each.
139 //
Yu Liud2a95952024-10-10 00:15:26 +0000140 // The ModuleProxy passed to the visit function should not be retained outside of the visit function, it may be
Yu Liudd9ccb42024-10-07 17:07:44 +0000141 // invalidated by future mutators.
Yu Liud2a95952024-10-10 00:15:26 +0000142 VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy))
Yu Liudd9ccb42024-10-07 17:07:44 +0000143
Colin Cross69452e12023-11-15 11:20:53 -0800144 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
145
Yu Liud2a95952024-10-10 00:15:26 +0000146 VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy))
147
Colin Cross69452e12023-11-15 11:20:53 -0800148 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
149 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
150 // OtherModuleDependencyTag will return a different tag for each. It skips any
151 // dependencies that are not an android.Module.
152 //
153 // The Module passed to the visit function should not be retained outside of the visit function, it may be
154 // invalidated by future mutators.
155 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
156 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
157 VisitDepsDepthFirst(visit func(Module))
158 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
159 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
160
161 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
162 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
163 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
164 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
165 // any dependencies that are not an android.Module.
166 //
167 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
168 // invalidated by future mutators.
169 WalkDeps(visit func(child, parent Module) bool)
170
Yu Liudd9ccb42024-10-07 17:07:44 +0000171 // 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.
Yu Liud2a95952024-10-10 00:15:26 +0000179 WalkDepsProxy(visit func(child, parent ModuleProxy) bool)
Yu Liudd9ccb42024-10-07 17:07:44 +0000180
Colin Cross69452e12023-11-15 11:20:53 -0800181 // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
182 // and returns a top-down dependency path from a start module to current child module.
183 GetWalkPath() []Module
184
185 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
186 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
187 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
188 // only done once for all variants of a module.
189 PrimaryModule() Module
190
191 // FinalModule returns the last variant of the current module. Variants of a module are always visited in
192 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
193 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
194 // singleton actions that are only done once for all variants of a module.
195 FinalModule() Module
196
197 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
198 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
199 // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any
200 // data modified by the current mutator.
201 VisitAllModuleVariants(visit func(Module))
202
203 // GetTagPath is supposed to be called in visit function passed in WalkDeps()
204 // and returns a top-down dependency tags path from a start module to current child module.
205 // It has one less entry than GetWalkPath() as it contains the dependency tags that
206 // exist between each adjacent pair of modules in the GetWalkPath().
207 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
208 GetTagPath() []blueprint.DependencyTag
209
210 // GetPathString is supposed to be called in visit function passed in WalkDeps()
211 // and returns a multi-line string showing the modules and dependency tags
212 // among them along the top-down dependency path from a start module to current child module.
213 // skipFirst when set to true, the output doesn't include the start module,
214 // which is already printed when this function is used along with ModuleErrorf().
215 GetPathString(skipFirst bool) string
216
217 AddMissingDependencies(missingDeps []string)
218
219 // getMissingDependencies returns the list of missing dependencies.
220 // Calling this function prevents adding new dependencies.
221 getMissingDependencies() []string
Cole Faustbdd8aee2024-03-14 14:33:02 -0700222
223 // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
224 // can be used to evaluate the final value of Configurable properties.
Cole Faustfdbf5d42024-04-10 15:01:23 -0700225 EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue
Colin Cross69452e12023-11-15 11:20:53 -0800226}
227
228type baseModuleContext struct {
229 bp blueprint.BaseModuleContext
230 earlyModuleContext
Colin Cross1d3d9f12024-01-18 14:30:22 -0800231 archModuleContext
Colin Cross69452e12023-11-15 11:20:53 -0800232
233 walkPath []Module
234 tagPath []blueprint.DependencyTag
235
236 strictVisitDeps bool // If true, enforce that all dependencies are enabled
237
Colin Cross69452e12023-11-15 11:20:53 -0800238}
239
Yu Liudd9ccb42024-10-07 17:07:44 +0000240func getWrappedModule(module blueprint.Module) blueprint.Module {
241 if mp, isProxy := module.(ModuleProxy); isProxy {
242 return mp.module
243 }
244 return module
245}
246
247func (b *baseModuleContext) EqualModules(m1, m2 Module) bool {
248 return b.bp.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
249}
250
Colin Cross69452e12023-11-15 11:20:53 -0800251func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
Yu Liudd9ccb42024-10-07 17:07:44 +0000252 return b.bp.OtherModuleName(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800253}
254func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
255func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
256 b.bp.OtherModuleErrorf(m, fmt, args...)
257}
258func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
Yu Liudd9ccb42024-10-07 17:07:44 +0000259 return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800260}
261func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
262func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
263 return b.bp.OtherModuleDependencyVariantExists(variations, name)
264}
265func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
266 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
267}
268func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
269 return b.bp.OtherModuleReverseDependencyVariantExists(name)
270}
271func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
272 return b.bp.OtherModuleType(m)
273}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800274
275func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800276 return b.bp.OtherModuleProvider(m, provider)
277}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800278
Colin Cross3c0a83d2023-12-12 14:13:26 -0800279func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800280 return b.bp.Provider(provider)
281}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800282
Colin Cross24c1cbe2023-12-21 23:42:56 +0000283func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
Colin Cross69452e12023-11-15 11:20:53 -0800284 b.bp.SetProvider(provider, value)
285}
286
287func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
288 return b.bp.GetDirectDepWithTag(name, tag)
289}
290
291func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
292 return b.bp
293}
294
Colin Cross69452e12023-11-15 11:20:53 -0800295func (b *baseModuleContext) AddMissingDependencies(deps []string) {
296 if deps != nil {
297 missingDeps := &b.Module().base().commonProperties.MissingDeps
298 *missingDeps = append(*missingDeps, deps...)
299 *missingDeps = FirstUniqueStrings(*missingDeps)
300 }
301}
302
303func (b *baseModuleContext) checkedMissingDeps() bool {
304 return b.Module().base().commonProperties.CheckedMissingDeps
305}
306
307func (b *baseModuleContext) getMissingDependencies() []string {
308 checked := &b.Module().base().commonProperties.CheckedMissingDeps
309 *checked = true
310 var missingDeps []string
311 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
312 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
313 missingDeps = FirstUniqueStrings(missingDeps)
314 return missingDeps
315}
316
317type AllowDisabledModuleDependency interface {
318 blueprint.DependencyTag
319 AllowDisabledModuleDependency(target Module) bool
Yu Liud2a95952024-10-10 00:15:26 +0000320 AllowDisabledModuleDependencyProxy(ctx OtherModuleProviderContext, target ModuleProxy) bool
Colin Cross69452e12023-11-15 11:20:53 -0800321}
322
Jiyong Park8bcf3c62024-03-18 18:37:10 +0900323type AlwaysAllowDisabledModuleDependencyTag struct{}
324
325func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
326 return true
327}
328
Yu Liud2a95952024-10-10 00:15:26 +0000329func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependencyProxy(OtherModuleProviderContext, ModuleProxy) bool {
330 return true
331}
332
Colin Cross648daea2024-09-12 14:35:29 -0700333func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
Colin Cross69452e12023-11-15 11:20:53 -0800334 aModule, _ := module.(Module)
335
336 if !strict {
337 return aModule
338 }
339
340 if aModule == nil {
Colin Cross648daea2024-09-12 14:35:29 -0700341 panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag))
Colin Cross69452e12023-11-15 11:20:53 -0800342 }
343
Cole Fausta963b942024-04-11 17:43:00 -0700344 if !aModule.Enabled(b) {
Colin Cross69452e12023-11-15 11:20:53 -0800345 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
346 if b.Config().AllowMissingDependencies() {
347 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
348 } else {
349 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
350 }
351 }
352 return nil
353 }
354 return aModule
355}
356
Yu Liud2a95952024-10-10 00:15:26 +0000357func (b *baseModuleContext) validateAndroidModuleProxy(
358 module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) *ModuleProxy {
359 aModule := ModuleProxy{module: module}
360
361 if !strict {
362 return &aModule
363 }
364
365 if !OtherModuleProviderOrDefault(b, module, CommonPropertiesProviderKey).Enabled {
366 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) {
367 if b.Config().AllowMissingDependencies() {
368 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
369 } else {
370 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
371 }
372 }
373 return nil
374 }
375
376 return &aModule
377}
378
Colin Cross69452e12023-11-15 11:20:53 -0800379type dep struct {
380 mod blueprint.Module
381 tag blueprint.DependencyTag
382}
383
384func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
385 var deps []dep
Colin Cross648daea2024-09-12 14:35:29 -0700386 b.VisitDirectDeps(func(module Module) {
387 if module.base().BaseModuleName() == name {
Colin Cross69452e12023-11-15 11:20:53 -0800388 returnedTag := b.bp.OtherModuleDependencyTag(module)
389 if tag == nil || returnedTag == tag {
390 deps = append(deps, dep{module, returnedTag})
391 }
392 }
393 })
394 return deps
395}
396
397func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
398 deps := b.getDirectDepsInternal(name, tag)
399 if len(deps) == 1 {
400 return deps[0].mod, deps[0].tag
401 } else if len(deps) >= 2 {
402 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
403 name, b.ModuleName()))
404 } else {
405 return nil, nil
406 }
407}
408
409func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
410 foundDeps := b.getDirectDepsInternal(name, nil)
411 deps := map[blueprint.Module]bool{}
412 for _, dep := range foundDeps {
413 deps[dep.mod] = true
414 }
415 if len(deps) == 1 {
416 return foundDeps[0].mod, foundDeps[0].tag
417 } else if len(deps) >= 2 {
418 // this could happen if two dependencies have the same name in different namespaces
419 // TODO(b/186554727): this should not occur if namespaces are handled within
420 // getDirectDepsInternal.
421 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
422 name, b.ModuleName()))
423 } else {
424 return nil, nil
425 }
426}
427
428func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
429 var deps []Module
Colin Cross648daea2024-09-12 14:35:29 -0700430 b.VisitDirectDeps(func(module Module) {
431 if b.bp.OtherModuleDependencyTag(module) == tag {
432 deps = append(deps, module)
Colin Cross69452e12023-11-15 11:20:53 -0800433 }
434 })
435 return deps
436}
437
438// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
439// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
440// first DependencyTag.
441func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
442 return b.getDirectDepFirstTag(name)
443}
444
Colin Cross69452e12023-11-15 11:20:53 -0800445func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
446 b.bp.VisitDirectDeps(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700447 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800448 visit(aModule)
449 }
450 })
451}
452
Colin Cross648daea2024-09-12 14:35:29 -0700453func (b *baseModuleContext) VisitDirectDepsAllowDisabled(visit func(Module)) {
454 b.bp.VisitDirectDeps(func(module blueprint.Module) {
455 visit(module.(Module))
456 })
457}
458
Yu Liud2a95952024-10-10 00:15:26 +0000459func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) {
Yu Liudd9ccb42024-10-07 17:07:44 +0000460 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
461 visit(ModuleProxy{
462 module: module,
463 })
464 })
465}
466
Colin Cross69452e12023-11-15 11:20:53 -0800467func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
468 b.bp.VisitDirectDeps(func(module blueprint.Module) {
469 if b.bp.OtherModuleDependencyTag(module) == tag {
Yu Liud2a95952024-10-10 00:15:26 +0000470 if aModule := b.validateAndroidModule(module, tag, b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800471 visit(aModule)
472 }
473 }
474 })
475}
476
Yu Liud2a95952024-10-10 00:15:26 +0000477func (b *baseModuleContext) VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) {
478 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
479 if b.bp.OtherModuleDependencyTag(module) == tag {
480 if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); aModule != nil {
481 visit(*aModule)
482 }
483 }
484 })
485}
486
Colin Cross69452e12023-11-15 11:20:53 -0800487func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
488 b.bp.VisitDirectDepsIf(
489 // pred
490 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700491 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800492 return pred(aModule)
493 } else {
494 return false
495 }
496 },
497 // visit
498 func(module blueprint.Module) {
499 visit(module.(Module))
500 })
501}
502
503func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
504 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700505 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800506 visit(aModule)
507 }
508 })
509}
510
511func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
512 b.bp.VisitDepsDepthFirstIf(
513 // pred
514 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700515 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800516 return pred(aModule)
517 } else {
518 return false
519 }
520 },
521 // visit
522 func(module blueprint.Module) {
523 visit(module.(Module))
524 })
525}
526
Colin Cross69452e12023-11-15 11:20:53 -0800527func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
528 b.walkPath = []Module{b.Module()}
529 b.tagPath = []blueprint.DependencyTag{}
530 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
531 childAndroidModule, _ := child.(Module)
532 parentAndroidModule, _ := parent.(Module)
533 if childAndroidModule != nil && parentAndroidModule != nil {
534 // record walkPath before visit
535 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
536 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
537 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
538 }
539 b.walkPath = append(b.walkPath, childAndroidModule)
540 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
541 return visit(childAndroidModule, parentAndroidModule)
542 } else {
543 return false
544 }
545 })
546}
547
Yu Liud2a95952024-10-10 00:15:26 +0000548func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) {
Yu Liudd9ccb42024-10-07 17:07:44 +0000549 b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
550 b.tagPath = []blueprint.DependencyTag{}
551 b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
552 childAndroidModule := ModuleProxy{child}
553 parentAndroidModule := ModuleProxy{parent}
554 // record walkPath before visit
555 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
556 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
557 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
558 }
559 b.walkPath = append(b.walkPath, childAndroidModule)
560 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
561 return visit(childAndroidModule, parentAndroidModule)
562 })
563}
564
Colin Cross69452e12023-11-15 11:20:53 -0800565func (b *baseModuleContext) GetWalkPath() []Module {
Colin Crossb614cd42024-10-11 12:52:21 -0700566 return slices.Clone(b.walkPath)
Colin Cross69452e12023-11-15 11:20:53 -0800567}
568
569func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
570 return b.tagPath
571}
572
573func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
574 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
575 visit(module.(Module))
576 })
577}
578
579func (b *baseModuleContext) PrimaryModule() Module {
580 return b.bp.PrimaryModule().(Module)
581}
582
583func (b *baseModuleContext) FinalModule() Module {
584 return b.bp.FinalModule().(Module)
585}
586
587// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
588func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
589 if tag == licenseKindTag {
590 return true
591 } else if tag == licensesTag {
592 return true
Jihoon Kanga3a05462024-04-05 00:36:44 +0000593 } else if tag == AcDepTag {
Colin Cross69452e12023-11-15 11:20:53 -0800594 return true
595 }
596 return false
597}
598
599// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
600// a dependency tag.
601var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
602
603// PrettyPrintTag returns string representation of the tag, but prefers
604// custom String() method if available.
605func PrettyPrintTag(tag blueprint.DependencyTag) string {
606 // Use tag's custom String() method if available.
607 if stringer, ok := tag.(fmt.Stringer); ok {
608 return stringer.String()
609 }
610
611 // Otherwise, get a default string representation of the tag's struct.
612 tagString := fmt.Sprintf("%T: %+v", tag, tag)
613
614 // Remove the boilerplate from BaseDependencyTag as it adds no value.
615 tagString = tagCleaner.ReplaceAllString(tagString, "")
616 return tagString
617}
618
619func (b *baseModuleContext) GetPathString(skipFirst bool) string {
620 sb := strings.Builder{}
621 tagPath := b.GetTagPath()
622 walkPath := b.GetWalkPath()
623 if !skipFirst {
624 sb.WriteString(walkPath[0].String())
625 }
626 for i, m := range walkPath[1:] {
627 sb.WriteString("\n")
628 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
629 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
630 }
631 return sb.String()
632}
Cole Faustbdd8aee2024-03-14 14:33:02 -0700633
Cole Faustfdbf5d42024-04-10 15:01:23 -0700634func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
635 return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property)
Cole Faustbdd8aee2024-03-14 14:33:02 -0700636}