blob: b9c115349677b2bf56194649bf11f7221f4b2462 [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"
19 "github.com/google/blueprint"
20 "regexp"
21 "strings"
22)
23
24// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
25// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module
26// instead of a blueprint.Module, plus some extra methods that return Android-specific information
27// about the current module.
28type BaseModuleContext interface {
Colin Cross1d3d9f12024-01-18 14:30:22 -080029 ArchModuleContext
Colin Cross69452e12023-11-15 11:20:53 -080030 EarlyModuleContext
31
32 blueprintBaseModuleContext() blueprint.BaseModuleContext
33
34 // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
35 // It is intended for use inside the visit functions of Visit* and WalkDeps.
36 OtherModuleName(m blueprint.Module) string
37
38 // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
39 // It is intended for use inside the visit functions of Visit* and WalkDeps.
40 OtherModuleDir(m blueprint.Module) string
41
42 // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
43 // It is intended for use inside the visit functions of Visit* and WalkDeps.
44 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
45
46 // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
47 // on the module. When called inside a Visit* method with current module being visited, and there are multiple
48 // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
49 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
50
51 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
52 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
53 OtherModuleExists(name string) bool
54
55 // OtherModuleDependencyVariantExists returns true if a module with the
56 // specified name and variant exists. The variant must match the given
57 // variations. It must also match all the non-local variations of the current
58 // module. In other words, it checks for the module that AddVariationDependencies
59 // would add a dependency on with the same arguments.
60 OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
61
62 // OtherModuleFarDependencyVariantExists returns true if a module with the
63 // specified name and variant exists. The variant must match the given
64 // variations, but not the non-local variations of the current module. In
65 // other words, it checks for the module that AddFarVariationDependencies
66 // would add a dependency on with the same arguments.
67 OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
68
69 // OtherModuleReverseDependencyVariantExists returns true if a module with the
70 // specified name exists with the same variations as the current module. In
71 // other words, it checks for the module that AddReverseDependency would add a
72 // dependency on with the same argument.
73 OtherModuleReverseDependencyVariantExists(name string) bool
74
75 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
76 // It is intended for use inside the visit functions of Visit* and WalkDeps.
77 OtherModuleType(m blueprint.Module) string
78
Colin Cross24c1cbe2023-12-21 23:42:56 +000079 // otherModuleProvider returns the value for a provider for the given module. If the value is
80 // not set it returns nil and false. The value returned may be a deep copy of the value originally
81 // passed to SetProvider.
82 //
83 // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080084 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080085
86 // Provider returns the value for a provider for the current module. If the value is
Colin Cross24c1cbe2023-12-21 23:42:56 +000087 // not set it returns nil and false. It panics if called before the appropriate
Colin Cross69452e12023-11-15 11:20:53 -080088 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
89 // copy of the value originally passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +000090 //
91 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080092 provider(provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080093
Colin Cross24c1cbe2023-12-21 23:42:56 +000094 // setProvider sets the value for a provider for the current module. It panics if not called
Colin Cross69452e12023-11-15 11:20:53 -080095 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
96 // is not of the appropriate type, or if the value has already been set. The value should not
97 // be modified after being passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +000098 //
99 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
100 setProvider(provider blueprint.AnyProviderKey, value any)
Colin Cross69452e12023-11-15 11:20:53 -0800101
102 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
103
104 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
105 // none exists. It panics if the dependency does not have the specified tag. It skips any
106 // dependencies that are not an android.Module.
107 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
108
LaMont Jones34314b72024-01-18 18:27:35 +0000109 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
Colin Cross69452e12023-11-15 11:20:53 -0800110 // name, or nil if none exists. If there are multiple dependencies on the same module it returns
111 // the first DependencyTag.
112 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
113
Colin Cross69452e12023-11-15 11:20:53 -0800114 // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple
115 // direct dependencies on the same module visit will be called multiple times on that module
116 // and OtherModuleDependencyTag will return a different tag for each.
117 //
118 // The Module passed to the visit function should not be retained outside of the visit
119 // function, it may be invalidated by future mutators.
120 VisitDirectDepsBlueprint(visit func(blueprint.Module))
121
LaMont Jones34314b72024-01-18 18:27:35 +0000122 // VisitDirectDepsIgnoreBlueprint 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 silently ignores any
125 // dependencies that are not an android.Module.
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 VisitDirectDepsIgnoreBlueprint(visit func(Module))
130
Colin Cross69452e12023-11-15 11:20:53 -0800131 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
132 // 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. It raises an error if any of the
134 // dependencies are not an android.Module.
135 //
136 // The Module passed to the visit function should not be retained outside of the visit
137 // function, it may be invalidated by future mutators.
138 VisitDirectDeps(visit func(Module))
139
140 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
141
142 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
143 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
144 // OtherModuleDependencyTag will return a different tag for each. It skips any
145 // dependencies that are not an android.Module.
146 //
147 // The Module passed to the visit function should not be retained outside of the visit function, it may be
148 // invalidated by future mutators.
149 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
150 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
151 VisitDepsDepthFirst(visit func(Module))
152 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
153 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
154
155 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
156 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
157 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
158 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
159 // any dependencies that are not an android.Module.
160 //
161 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
162 // invalidated by future mutators.
163 WalkDeps(visit func(child, parent Module) bool)
164
165 // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
166 // tree in top down order. visit may be called multiple times for the same (child, parent)
167 // pair if there are multiple direct dependencies between the child and parent with different
168 // tags. OtherModuleDependencyTag will return the tag for the currently visited
169 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down
170 // to child.
171 //
172 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
173 // invalidated by future mutators.
174 WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
175
176 // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
177 // and returns a top-down dependency path from a start module to current child module.
178 GetWalkPath() []Module
179
180 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
181 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
182 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
183 // only done once for all variants of a module.
184 PrimaryModule() Module
185
186 // FinalModule returns the last variant of the current module. Variants of a module are always visited in
187 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
188 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
189 // singleton actions that are only done once for all variants of a module.
190 FinalModule() Module
191
192 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
193 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
194 // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any
195 // data modified by the current mutator.
196 VisitAllModuleVariants(visit func(Module))
197
198 // GetTagPath is supposed to be called in visit function passed in WalkDeps()
199 // and returns a top-down dependency tags path from a start module to current child module.
200 // It has one less entry than GetWalkPath() as it contains the dependency tags that
201 // exist between each adjacent pair of modules in the GetWalkPath().
202 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
203 GetTagPath() []blueprint.DependencyTag
204
205 // GetPathString is supposed to be called in visit function passed in WalkDeps()
206 // and returns a multi-line string showing the modules and dependency tags
207 // among them along the top-down dependency path from a start module to current child module.
208 // skipFirst when set to true, the output doesn't include the start module,
209 // which is already printed when this function is used along with ModuleErrorf().
210 GetPathString(skipFirst bool) string
211
212 AddMissingDependencies(missingDeps []string)
213
214 // getMissingDependencies returns the list of missing dependencies.
215 // Calling this function prevents adding new dependencies.
216 getMissingDependencies() []string
Colin Cross69452e12023-11-15 11:20:53 -0800217}
218
219type baseModuleContext struct {
220 bp blueprint.BaseModuleContext
221 earlyModuleContext
Colin Cross1d3d9f12024-01-18 14:30:22 -0800222 archModuleContext
Colin Cross69452e12023-11-15 11:20:53 -0800223
224 walkPath []Module
225 tagPath []blueprint.DependencyTag
226
227 strictVisitDeps bool // If true, enforce that all dependencies are enabled
228
Colin Cross69452e12023-11-15 11:20:53 -0800229}
230
Colin Cross69452e12023-11-15 11:20:53 -0800231func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
232 return b.bp.OtherModuleName(m)
233}
234func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
235func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
236 b.bp.OtherModuleErrorf(m, fmt, args...)
237}
238func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
239 return b.bp.OtherModuleDependencyTag(m)
240}
241func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
242func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
243 return b.bp.OtherModuleDependencyVariantExists(variations, name)
244}
245func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
246 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
247}
248func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
249 return b.bp.OtherModuleReverseDependencyVariantExists(name)
250}
251func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
252 return b.bp.OtherModuleType(m)
253}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800254
255func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800256 return b.bp.OtherModuleProvider(m, provider)
257}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800258
Colin Cross3c0a83d2023-12-12 14:13:26 -0800259func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800260 return b.bp.Provider(provider)
261}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800262
Colin Cross24c1cbe2023-12-21 23:42:56 +0000263func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
Colin Cross69452e12023-11-15 11:20:53 -0800264 b.bp.SetProvider(provider, value)
265}
266
267func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
268 return b.bp.GetDirectDepWithTag(name, tag)
269}
270
271func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
272 return b.bp
273}
274
Colin Cross69452e12023-11-15 11:20:53 -0800275func (b *baseModuleContext) AddMissingDependencies(deps []string) {
276 if deps != nil {
277 missingDeps := &b.Module().base().commonProperties.MissingDeps
278 *missingDeps = append(*missingDeps, deps...)
279 *missingDeps = FirstUniqueStrings(*missingDeps)
280 }
281}
282
283func (b *baseModuleContext) checkedMissingDeps() bool {
284 return b.Module().base().commonProperties.CheckedMissingDeps
285}
286
287func (b *baseModuleContext) getMissingDependencies() []string {
288 checked := &b.Module().base().commonProperties.CheckedMissingDeps
289 *checked = true
290 var missingDeps []string
291 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
292 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
293 missingDeps = FirstUniqueStrings(missingDeps)
294 return missingDeps
295}
296
297type AllowDisabledModuleDependency interface {
298 blueprint.DependencyTag
299 AllowDisabledModuleDependency(target Module) bool
300}
301
LaMont Jones34314b72024-01-18 18:27:35 +0000302func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool, ignoreBlueprint bool) Module {
Colin Cross69452e12023-11-15 11:20:53 -0800303 aModule, _ := module.(Module)
304
305 if !strict {
306 return aModule
307 }
308
309 if aModule == nil {
LaMont Jones34314b72024-01-18 18:27:35 +0000310 if !ignoreBlueprint {
311 b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
312 }
Colin Cross69452e12023-11-15 11:20:53 -0800313 return nil
314 }
315
316 if !aModule.Enabled() {
317 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
318 if b.Config().AllowMissingDependencies() {
319 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
320 } else {
321 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
322 }
323 }
324 return nil
325 }
326 return aModule
327}
328
329type dep struct {
330 mod blueprint.Module
331 tag blueprint.DependencyTag
332}
333
334func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
335 var deps []dep
336 b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
337 if aModule, _ := module.(Module); aModule != nil {
338 if aModule.base().BaseModuleName() == name {
339 returnedTag := b.bp.OtherModuleDependencyTag(aModule)
340 if tag == nil || returnedTag == tag {
341 deps = append(deps, dep{aModule, returnedTag})
342 }
343 }
344 } else if b.bp.OtherModuleName(module) == name {
345 returnedTag := b.bp.OtherModuleDependencyTag(module)
346 if tag == nil || returnedTag == tag {
347 deps = append(deps, dep{module, returnedTag})
348 }
349 }
350 })
351 return deps
352}
353
354func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
355 deps := b.getDirectDepsInternal(name, tag)
356 if len(deps) == 1 {
357 return deps[0].mod, deps[0].tag
358 } else if len(deps) >= 2 {
359 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
360 name, b.ModuleName()))
361 } else {
362 return nil, nil
363 }
364}
365
366func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
367 foundDeps := b.getDirectDepsInternal(name, nil)
368 deps := map[blueprint.Module]bool{}
369 for _, dep := range foundDeps {
370 deps[dep.mod] = true
371 }
372 if len(deps) == 1 {
373 return foundDeps[0].mod, foundDeps[0].tag
374 } else if len(deps) >= 2 {
375 // this could happen if two dependencies have the same name in different namespaces
376 // TODO(b/186554727): this should not occur if namespaces are handled within
377 // getDirectDepsInternal.
378 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
379 name, b.ModuleName()))
380 } else {
381 return nil, nil
382 }
383}
384
385func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
386 var deps []Module
387 b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
388 if aModule, _ := module.(Module); aModule != nil {
389 if b.bp.OtherModuleDependencyTag(aModule) == tag {
390 deps = append(deps, aModule)
391 }
392 }
393 })
394 return deps
395}
396
397// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
398// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
399// first DependencyTag.
400func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
401 return b.getDirectDepFirstTag(name)
402}
403
Colin Cross69452e12023-11-15 11:20:53 -0800404func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
405 b.bp.VisitDirectDeps(visit)
406}
407
408func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
LaMont Jones34314b72024-01-18 18:27:35 +0000409 b.visitDirectDeps(visit, false)
410}
411
412func (b *baseModuleContext) VisitDirectDepsIgnoreBlueprint(visit func(Module)) {
413 b.visitDirectDeps(visit, true)
414}
415
416func (b *baseModuleContext) visitDirectDeps(visit func(Module), ignoreBlueprint bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800417 b.bp.VisitDirectDeps(func(module blueprint.Module) {
LaMont Jones34314b72024-01-18 18:27:35 +0000418 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, ignoreBlueprint); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800419 visit(aModule)
420 }
421 })
422}
423
424func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
425 b.bp.VisitDirectDeps(func(module blueprint.Module) {
426 if b.bp.OtherModuleDependencyTag(module) == tag {
LaMont Jones34314b72024-01-18 18:27:35 +0000427 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800428 visit(aModule)
429 }
430 }
431 })
432}
433
434func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
435 b.bp.VisitDirectDepsIf(
436 // pred
437 func(module blueprint.Module) bool {
LaMont Jones34314b72024-01-18 18:27:35 +0000438 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800439 return pred(aModule)
440 } else {
441 return false
442 }
443 },
444 // visit
445 func(module blueprint.Module) {
446 visit(module.(Module))
447 })
448}
449
450func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
451 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
LaMont Jones34314b72024-01-18 18:27:35 +0000452 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800453 visit(aModule)
454 }
455 })
456}
457
458func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
459 b.bp.VisitDepsDepthFirstIf(
460 // pred
461 func(module blueprint.Module) bool {
LaMont Jones34314b72024-01-18 18:27:35 +0000462 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800463 return pred(aModule)
464 } else {
465 return false
466 }
467 },
468 // visit
469 func(module blueprint.Module) {
470 visit(module.(Module))
471 })
472}
473
474func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
475 b.bp.WalkDeps(visit)
476}
477
478func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
479 b.walkPath = []Module{b.Module()}
480 b.tagPath = []blueprint.DependencyTag{}
481 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
482 childAndroidModule, _ := child.(Module)
483 parentAndroidModule, _ := parent.(Module)
484 if childAndroidModule != nil && parentAndroidModule != nil {
485 // record walkPath before visit
486 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
487 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
488 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
489 }
490 b.walkPath = append(b.walkPath, childAndroidModule)
491 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
492 return visit(childAndroidModule, parentAndroidModule)
493 } else {
494 return false
495 }
496 })
497}
498
499func (b *baseModuleContext) GetWalkPath() []Module {
500 return b.walkPath
501}
502
503func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
504 return b.tagPath
505}
506
507func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
508 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
509 visit(module.(Module))
510 })
511}
512
513func (b *baseModuleContext) PrimaryModule() Module {
514 return b.bp.PrimaryModule().(Module)
515}
516
517func (b *baseModuleContext) FinalModule() Module {
518 return b.bp.FinalModule().(Module)
519}
520
521// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
522func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
523 if tag == licenseKindTag {
524 return true
525 } else if tag == licensesTag {
526 return true
527 } else if tag == acDepTag {
528 return true
529 }
530 return false
531}
532
533// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
534// a dependency tag.
535var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
536
537// PrettyPrintTag returns string representation of the tag, but prefers
538// custom String() method if available.
539func PrettyPrintTag(tag blueprint.DependencyTag) string {
540 // Use tag's custom String() method if available.
541 if stringer, ok := tag.(fmt.Stringer); ok {
542 return stringer.String()
543 }
544
545 // Otherwise, get a default string representation of the tag's struct.
546 tagString := fmt.Sprintf("%T: %+v", tag, tag)
547
548 // Remove the boilerplate from BaseDependencyTag as it adds no value.
549 tagString = tagCleaner.ReplaceAllString(tagString, "")
550 return tagString
551}
552
553func (b *baseModuleContext) GetPathString(skipFirst bool) string {
554 sb := strings.Builder{}
555 tagPath := b.GetTagPath()
556 walkPath := b.GetWalkPath()
557 if !skipFirst {
558 sb.WriteString(walkPath[0].String())
559 }
560 for i, m := range walkPath[1:] {
561 sb.WriteString("\n")
562 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
563 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
564 }
565 return sb.String()
566}