blob: 223b5341df5419f9ddb5ebe75b47c54d263c60b1 [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"
20 "strings"
Cole Faustbdd8aee2024-03-14 14:33:02 -070021
22 "github.com/google/blueprint"
Cole Faustfdbf5d42024-04-10 15:01:23 -070023 "github.com/google/blueprint/proptools"
Colin Cross69452e12023-11-15 11:20:53 -080024)
25
26// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
27// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module
28// instead of a blueprint.Module, plus some extra methods that return Android-specific information
29// about the current module.
30type BaseModuleContext interface {
Colin Cross1d3d9f12024-01-18 14:30:22 -080031 ArchModuleContext
Colin Cross69452e12023-11-15 11:20:53 -080032 EarlyModuleContext
33
34 blueprintBaseModuleContext() blueprint.BaseModuleContext
35
Yu Liudd9ccb42024-10-07 17:07:44 +000036 EqualModules(m1, m2 Module) bool
37
Colin Cross69452e12023-11-15 11:20:53 -080038 // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
39 // It is intended for use inside the visit functions of Visit* and WalkDeps.
40 OtherModuleName(m blueprint.Module) string
41
42 // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
43 // It is intended for use inside the visit functions of Visit* and WalkDeps.
44 OtherModuleDir(m blueprint.Module) string
45
46 // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
47 // It is intended for use inside the visit functions of Visit* and WalkDeps.
48 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
49
50 // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
51 // on the module. When called inside a Visit* method with current module being visited, and there are multiple
52 // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
53 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
54
55 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
56 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
57 OtherModuleExists(name string) bool
58
59 // OtherModuleDependencyVariantExists returns true if a module with the
60 // specified name and variant exists. The variant must match the given
61 // variations. It must also match all the non-local variations of the current
62 // module. In other words, it checks for the module that AddVariationDependencies
63 // would add a dependency on with the same arguments.
64 OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
65
66 // OtherModuleFarDependencyVariantExists returns true if a module with the
67 // specified name and variant exists. The variant must match the given
68 // variations, but not the non-local variations of the current module. In
69 // other words, it checks for the module that AddFarVariationDependencies
70 // would add a dependency on with the same arguments.
71 OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
72
73 // OtherModuleReverseDependencyVariantExists returns true if a module with the
74 // specified name exists with the same variations as the current module. In
75 // other words, it checks for the module that AddReverseDependency would add a
76 // dependency on with the same argument.
77 OtherModuleReverseDependencyVariantExists(name string) bool
78
79 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
80 // It is intended for use inside the visit functions of Visit* and WalkDeps.
81 OtherModuleType(m blueprint.Module) string
82
Colin Cross24c1cbe2023-12-21 23:42:56 +000083 // otherModuleProvider returns the value for a provider for the given module. If the value is
84 // not set it returns nil and false. The value returned may be a deep copy of the value originally
85 // passed to SetProvider.
86 //
87 // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080088 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080089
Jihoon Kang2a7bf752024-11-01 21:21:25 +000090 // OtherModuleIsAutoGenerated returns true if the module is auto generated by another module
91 // instead of being defined in Android.bp file.
92 OtherModuleIsAutoGenerated(m blueprint.Module) bool
93
Colin Cross69452e12023-11-15 11:20:53 -080094 // Provider returns the value for a provider for the current module. If the value is
Colin Cross24c1cbe2023-12-21 23:42:56 +000095 // not set it returns nil and false. It panics if called before the appropriate
Colin Cross69452e12023-11-15 11:20:53 -080096 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
97 // copy of the value originally passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +000098 //
99 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -0800100 provider(provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -0800101
Colin Cross24c1cbe2023-12-21 23:42:56 +0000102 // setProvider sets the value for a provider for the current module. It panics if not called
Colin Cross69452e12023-11-15 11:20:53 -0800103 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
104 // is not of the appropriate type, or if the value has already been set. The value should not
105 // be modified after being passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000106 //
107 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
108 setProvider(provider blueprint.AnyProviderKey, value any)
Colin Cross69452e12023-11-15 11:20:53 -0800109
110 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
111
112 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
113 // none exists. It panics if the dependency does not have the specified tag. It skips any
114 // dependencies that are not an android.Module.
115 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
116
LaMont Jones34314b72024-01-18 18:27:35 +0000117 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
Colin Cross69452e12023-11-15 11:20:53 -0800118 // name, or nil if none exists. If there are multiple dependencies on the same module it returns
119 // the first DependencyTag.
120 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
121
Colin Cross648daea2024-09-12 14:35:29 -0700122 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
123 // direct dependencies on the same module visit will be called multiple times on that module
124 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
125 // dependencies are disabled.
126 //
127 // The Module passed to the visit function should not be retained outside of the visit
128 // function, it may be invalidated by future mutators.
129 VisitDirectDeps(visit func(Module))
130
131 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
Colin Cross69452e12023-11-15 11:20:53 -0800132 // direct dependencies on the same module visit will be called multiple times on that module
133 // and OtherModuleDependencyTag will return a different tag for each.
134 //
135 // The Module passed to the visit function should not be retained outside of the visit
136 // function, it may be invalidated by future mutators.
Colin Cross648daea2024-09-12 14:35:29 -0700137 VisitDirectDepsAllowDisabled(visit func(Module))
Colin Cross69452e12023-11-15 11:20:53 -0800138
Yu Liudd9ccb42024-10-07 17:07:44 +0000139 // VisitDirectDepsProxyAllowDisabled calls visit for each direct dependency. If there are
140 // multiple direct dependencies on the same module visit will be called multiple times on
141 // that module and OtherModuleDependencyTag will return a different tag for each.
142 //
Yu Liud2a95952024-10-10 00:15:26 +0000143 // 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 +0000144 // invalidated by future mutators.
Yu Liud2a95952024-10-10 00:15:26 +0000145 VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy))
Yu Liudd9ccb42024-10-07 17:07:44 +0000146
Colin Cross69452e12023-11-15 11:20:53 -0800147 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
148
Yu Liud2a95952024-10-10 00:15:26 +0000149 VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy))
150
Colin Cross69452e12023-11-15 11:20:53 -0800151 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
152 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
153 // OtherModuleDependencyTag will return a different tag for each. It skips any
154 // dependencies that are not an android.Module.
155 //
156 // The Module passed to the visit function should not be retained outside of the visit function, it may be
157 // invalidated by future mutators.
158 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
159 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
160 VisitDepsDepthFirst(visit func(Module))
161 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
162 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
163
164 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
165 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
166 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
167 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
168 // any dependencies that are not an android.Module.
169 //
170 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
171 // invalidated by future mutators.
172 WalkDeps(visit func(child, parent Module) bool)
173
Yu Liudd9ccb42024-10-07 17:07:44 +0000174 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
175 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
176 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
177 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
178 // any dependencies that are not an android.Module.
179 //
180 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
181 // invalidated by future mutators.
Yu Liud2a95952024-10-10 00:15:26 +0000182 WalkDepsProxy(visit func(child, parent ModuleProxy) bool)
Yu Liudd9ccb42024-10-07 17:07:44 +0000183
Colin Cross69452e12023-11-15 11:20:53 -0800184 // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
185 // and returns a top-down dependency path from a start module to current child module.
186 GetWalkPath() []Module
187
188 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
189 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
190 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
191 // only done once for all variants of a module.
192 PrimaryModule() Module
193
194 // FinalModule returns the last variant of the current module. Variants of a module are always visited in
195 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
196 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
197 // singleton actions that are only done once for all variants of a module.
198 FinalModule() Module
199
200 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
201 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
202 // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any
203 // data modified by the current mutator.
204 VisitAllModuleVariants(visit func(Module))
205
206 // GetTagPath is supposed to be called in visit function passed in WalkDeps()
207 // and returns a top-down dependency tags path from a start module to current child module.
208 // It has one less entry than GetWalkPath() as it contains the dependency tags that
209 // exist between each adjacent pair of modules in the GetWalkPath().
210 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
211 GetTagPath() []blueprint.DependencyTag
212
213 // GetPathString is supposed to be called in visit function passed in WalkDeps()
214 // and returns a multi-line string showing the modules and dependency tags
215 // among them along the top-down dependency path from a start module to current child module.
216 // skipFirst when set to true, the output doesn't include the start module,
217 // which is already printed when this function is used along with ModuleErrorf().
218 GetPathString(skipFirst bool) string
219
220 AddMissingDependencies(missingDeps []string)
221
222 // getMissingDependencies returns the list of missing dependencies.
223 // Calling this function prevents adding new dependencies.
224 getMissingDependencies() []string
Cole Faustbdd8aee2024-03-14 14:33:02 -0700225
226 // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
227 // can be used to evaluate the final value of Configurable properties.
Cole Faustfdbf5d42024-04-10 15:01:23 -0700228 EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue
Colin Cross69452e12023-11-15 11:20:53 -0800229}
230
231type baseModuleContext struct {
232 bp blueprint.BaseModuleContext
233 earlyModuleContext
Colin Cross1d3d9f12024-01-18 14:30:22 -0800234 archModuleContext
Colin Cross69452e12023-11-15 11:20:53 -0800235
236 walkPath []Module
237 tagPath []blueprint.DependencyTag
238
239 strictVisitDeps bool // If true, enforce that all dependencies are enabled
240
Colin Cross69452e12023-11-15 11:20:53 -0800241}
242
Yu Liudd9ccb42024-10-07 17:07:44 +0000243func getWrappedModule(module blueprint.Module) blueprint.Module {
244 if mp, isProxy := module.(ModuleProxy); isProxy {
245 return mp.module
246 }
247 return module
248}
249
250func (b *baseModuleContext) EqualModules(m1, m2 Module) bool {
251 return b.bp.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
252}
253
Colin Cross69452e12023-11-15 11:20:53 -0800254func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
Yu Liudd9ccb42024-10-07 17:07:44 +0000255 return b.bp.OtherModuleName(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800256}
257func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
258func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
259 b.bp.OtherModuleErrorf(m, fmt, args...)
260}
261func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
Yu Liudd9ccb42024-10-07 17:07:44 +0000262 return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800263}
264func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
265func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
266 return b.bp.OtherModuleDependencyVariantExists(variations, name)
267}
268func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
269 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
270}
271func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
272 return b.bp.OtherModuleReverseDependencyVariantExists(name)
273}
274func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
275 return b.bp.OtherModuleType(m)
276}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800277
278func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800279 return b.bp.OtherModuleProvider(m, provider)
280}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800281
Jihoon Kang2a7bf752024-11-01 21:21:25 +0000282func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool {
283 return b.bp.OtherModuleIsAutoGenerated(m)
284}
285
Colin Cross3c0a83d2023-12-12 14:13:26 -0800286func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800287 return b.bp.Provider(provider)
288}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800289
Colin Cross24c1cbe2023-12-21 23:42:56 +0000290func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
Colin Cross69452e12023-11-15 11:20:53 -0800291 b.bp.SetProvider(provider, value)
292}
293
294func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
295 return b.bp.GetDirectDepWithTag(name, tag)
296}
297
298func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
299 return b.bp
300}
301
Colin Cross69452e12023-11-15 11:20:53 -0800302func (b *baseModuleContext) AddMissingDependencies(deps []string) {
303 if deps != nil {
304 missingDeps := &b.Module().base().commonProperties.MissingDeps
305 *missingDeps = append(*missingDeps, deps...)
306 *missingDeps = FirstUniqueStrings(*missingDeps)
307 }
308}
309
310func (b *baseModuleContext) checkedMissingDeps() bool {
311 return b.Module().base().commonProperties.CheckedMissingDeps
312}
313
314func (b *baseModuleContext) getMissingDependencies() []string {
315 checked := &b.Module().base().commonProperties.CheckedMissingDeps
316 *checked = true
317 var missingDeps []string
318 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
319 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
320 missingDeps = FirstUniqueStrings(missingDeps)
321 return missingDeps
322}
323
324type AllowDisabledModuleDependency interface {
325 blueprint.DependencyTag
326 AllowDisabledModuleDependency(target Module) bool
Yu Liud2a95952024-10-10 00:15:26 +0000327 AllowDisabledModuleDependencyProxy(ctx OtherModuleProviderContext, target ModuleProxy) bool
Colin Cross69452e12023-11-15 11:20:53 -0800328}
329
Jiyong Park8bcf3c62024-03-18 18:37:10 +0900330type AlwaysAllowDisabledModuleDependencyTag struct{}
331
332func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
333 return true
334}
335
Yu Liud2a95952024-10-10 00:15:26 +0000336func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependencyProxy(OtherModuleProviderContext, ModuleProxy) bool {
337 return true
338}
339
Colin Cross648daea2024-09-12 14:35:29 -0700340func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
Colin Cross69452e12023-11-15 11:20:53 -0800341 aModule, _ := module.(Module)
342
343 if !strict {
344 return aModule
345 }
346
347 if aModule == nil {
Colin Cross648daea2024-09-12 14:35:29 -0700348 panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag))
Colin Cross69452e12023-11-15 11:20:53 -0800349 }
350
Cole Fausta963b942024-04-11 17:43:00 -0700351 if !aModule.Enabled(b) {
Colin Cross69452e12023-11-15 11:20:53 -0800352 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
353 if b.Config().AllowMissingDependencies() {
354 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
355 } else {
356 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
357 }
358 }
359 return nil
360 }
361 return aModule
362}
363
Yu Liud2a95952024-10-10 00:15:26 +0000364func (b *baseModuleContext) validateAndroidModuleProxy(
365 module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) *ModuleProxy {
366 aModule := ModuleProxy{module: module}
367
368 if !strict {
369 return &aModule
370 }
371
372 if !OtherModuleProviderOrDefault(b, module, CommonPropertiesProviderKey).Enabled {
373 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) {
374 if b.Config().AllowMissingDependencies() {
375 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
376 } else {
377 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
378 }
379 }
380 return nil
381 }
382
383 return &aModule
384}
385
Colin Cross69452e12023-11-15 11:20:53 -0800386type dep struct {
387 mod blueprint.Module
388 tag blueprint.DependencyTag
389}
390
391func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
392 var deps []dep
Colin Cross648daea2024-09-12 14:35:29 -0700393 b.VisitDirectDeps(func(module Module) {
394 if module.base().BaseModuleName() == name {
Colin Cross69452e12023-11-15 11:20:53 -0800395 returnedTag := b.bp.OtherModuleDependencyTag(module)
396 if tag == nil || returnedTag == tag {
397 deps = append(deps, dep{module, returnedTag})
398 }
399 }
400 })
401 return deps
402}
403
404func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
405 deps := b.getDirectDepsInternal(name, tag)
406 if len(deps) == 1 {
407 return deps[0].mod, deps[0].tag
408 } else if len(deps) >= 2 {
409 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
410 name, b.ModuleName()))
411 } else {
412 return nil, nil
413 }
414}
415
416func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
417 foundDeps := b.getDirectDepsInternal(name, nil)
418 deps := map[blueprint.Module]bool{}
419 for _, dep := range foundDeps {
420 deps[dep.mod] = true
421 }
422 if len(deps) == 1 {
423 return foundDeps[0].mod, foundDeps[0].tag
424 } else if len(deps) >= 2 {
425 // this could happen if two dependencies have the same name in different namespaces
426 // TODO(b/186554727): this should not occur if namespaces are handled within
427 // getDirectDepsInternal.
428 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
429 name, b.ModuleName()))
430 } else {
431 return nil, nil
432 }
433}
434
435func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
436 var deps []Module
Colin Cross648daea2024-09-12 14:35:29 -0700437 b.VisitDirectDeps(func(module Module) {
438 if b.bp.OtherModuleDependencyTag(module) == tag {
439 deps = append(deps, module)
Colin Cross69452e12023-11-15 11:20:53 -0800440 }
441 })
442 return deps
443}
444
445// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
446// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
447// first DependencyTag.
448func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
449 return b.getDirectDepFirstTag(name)
450}
451
Colin Cross69452e12023-11-15 11:20:53 -0800452func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
453 b.bp.VisitDirectDeps(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700454 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800455 visit(aModule)
456 }
457 })
458}
459
Colin Cross648daea2024-09-12 14:35:29 -0700460func (b *baseModuleContext) VisitDirectDepsAllowDisabled(visit func(Module)) {
461 b.bp.VisitDirectDeps(func(module blueprint.Module) {
462 visit(module.(Module))
463 })
464}
465
Yu Liud2a95952024-10-10 00:15:26 +0000466func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) {
Yu Liudd9ccb42024-10-07 17:07:44 +0000467 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
468 visit(ModuleProxy{
469 module: module,
470 })
471 })
472}
473
Colin Cross69452e12023-11-15 11:20:53 -0800474func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
475 b.bp.VisitDirectDeps(func(module blueprint.Module) {
476 if b.bp.OtherModuleDependencyTag(module) == tag {
Yu Liud2a95952024-10-10 00:15:26 +0000477 if aModule := b.validateAndroidModule(module, tag, b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800478 visit(aModule)
479 }
480 }
481 })
482}
483
Yu Liud2a95952024-10-10 00:15:26 +0000484func (b *baseModuleContext) VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) {
485 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
486 if b.bp.OtherModuleDependencyTag(module) == tag {
487 if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); aModule != nil {
488 visit(*aModule)
489 }
490 }
491 })
492}
493
Colin Cross69452e12023-11-15 11:20:53 -0800494func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
495 b.bp.VisitDirectDepsIf(
496 // pred
497 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700498 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800499 return pred(aModule)
500 } else {
501 return false
502 }
503 },
504 // visit
505 func(module blueprint.Module) {
506 visit(module.(Module))
507 })
508}
509
510func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
511 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700512 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800513 visit(aModule)
514 }
515 })
516}
517
518func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
519 b.bp.VisitDepsDepthFirstIf(
520 // pred
521 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700522 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800523 return pred(aModule)
524 } else {
525 return false
526 }
527 },
528 // visit
529 func(module blueprint.Module) {
530 visit(module.(Module))
531 })
532}
533
Colin Cross69452e12023-11-15 11:20:53 -0800534func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
535 b.walkPath = []Module{b.Module()}
536 b.tagPath = []blueprint.DependencyTag{}
537 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
538 childAndroidModule, _ := child.(Module)
539 parentAndroidModule, _ := parent.(Module)
540 if childAndroidModule != nil && parentAndroidModule != nil {
541 // record walkPath before visit
542 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
543 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
544 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
545 }
546 b.walkPath = append(b.walkPath, childAndroidModule)
547 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
548 return visit(childAndroidModule, parentAndroidModule)
549 } else {
550 return false
551 }
552 })
553}
554
Yu Liud2a95952024-10-10 00:15:26 +0000555func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) {
Yu Liudd9ccb42024-10-07 17:07:44 +0000556 b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
557 b.tagPath = []blueprint.DependencyTag{}
558 b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
559 childAndroidModule := ModuleProxy{child}
560 parentAndroidModule := ModuleProxy{parent}
561 // record walkPath before visit
562 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
563 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
564 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
565 }
566 b.walkPath = append(b.walkPath, childAndroidModule)
567 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
568 return visit(childAndroidModule, parentAndroidModule)
569 })
570}
571
Colin Cross69452e12023-11-15 11:20:53 -0800572func (b *baseModuleContext) GetWalkPath() []Module {
573 return b.walkPath
574}
575
576func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
577 return b.tagPath
578}
579
580func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
581 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
582 visit(module.(Module))
583 })
584}
585
586func (b *baseModuleContext) PrimaryModule() Module {
587 return b.bp.PrimaryModule().(Module)
588}
589
590func (b *baseModuleContext) FinalModule() Module {
591 return b.bp.FinalModule().(Module)
592}
593
594// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
595func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
596 if tag == licenseKindTag {
597 return true
598 } else if tag == licensesTag {
599 return true
Jihoon Kanga3a05462024-04-05 00:36:44 +0000600 } else if tag == AcDepTag {
Colin Cross69452e12023-11-15 11:20:53 -0800601 return true
602 }
603 return false
604}
605
606// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
607// a dependency tag.
608var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
609
610// PrettyPrintTag returns string representation of the tag, but prefers
611// custom String() method if available.
612func PrettyPrintTag(tag blueprint.DependencyTag) string {
613 // Use tag's custom String() method if available.
614 if stringer, ok := tag.(fmt.Stringer); ok {
615 return stringer.String()
616 }
617
618 // Otherwise, get a default string representation of the tag's struct.
619 tagString := fmt.Sprintf("%T: %+v", tag, tag)
620
621 // Remove the boilerplate from BaseDependencyTag as it adds no value.
622 tagString = tagCleaner.ReplaceAllString(tagString, "")
623 return tagString
624}
625
626func (b *baseModuleContext) GetPathString(skipFirst bool) string {
627 sb := strings.Builder{}
628 tagPath := b.GetTagPath()
629 walkPath := b.GetWalkPath()
630 if !skipFirst {
631 sb.WriteString(walkPath[0].String())
632 }
633 for i, m := range walkPath[1:] {
634 sb.WriteString("\n")
635 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
636 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
637 }
638 return sb.String()
639}
Cole Faustbdd8aee2024-03-14 14:33:02 -0700640
Cole Faustfdbf5d42024-04-10 15:01:23 -0700641func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
642 return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property)
Cole Faustbdd8aee2024-03-14 14:33:02 -0700643}