blob: 2a4b12ee5872bf63cbf199e9689862a000c5ba53 [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 {
29 EarlyModuleContext
30
31 blueprintBaseModuleContext() blueprint.BaseModuleContext
32
33 // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
34 // It is intended for use inside the visit functions of Visit* and WalkDeps.
35 OtherModuleName(m blueprint.Module) string
36
37 // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
38 // It is intended for use inside the visit functions of Visit* and WalkDeps.
39 OtherModuleDir(m blueprint.Module) string
40
41 // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
42 // It is intended for use inside the visit functions of Visit* and WalkDeps.
43 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
44
45 // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
46 // on the module. When called inside a Visit* method with current module being visited, and there are multiple
47 // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
48 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
49
50 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
51 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
52 OtherModuleExists(name string) bool
53
54 // OtherModuleDependencyVariantExists returns true if a module with the
55 // specified name and variant exists. The variant must match the given
56 // variations. It must also match all the non-local variations of the current
57 // module. In other words, it checks for the module that AddVariationDependencies
58 // would add a dependency on with the same arguments.
59 OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
60
61 // OtherModuleFarDependencyVariantExists returns true if a module with the
62 // specified name and variant exists. The variant must match the given
63 // variations, but not the non-local variations of the current module. In
64 // other words, it checks for the module that AddFarVariationDependencies
65 // would add a dependency on with the same arguments.
66 OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
67
68 // OtherModuleReverseDependencyVariantExists returns true if a module with the
69 // specified name exists with the same variations as the current module. In
70 // other words, it checks for the module that AddReverseDependency would add a
71 // dependency on with the same argument.
72 OtherModuleReverseDependencyVariantExists(name string) bool
73
74 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
75 // It is intended for use inside the visit functions of Visit* and WalkDeps.
76 OtherModuleType(m blueprint.Module) string
77
Colin Cross84b68c92023-12-20 00:59:28 +000078 // OtherModuleProvider returns the value for a provider for the given module. If the value is
79 // not set it returns the zero value of the type of the provider, so the return value can always
80 // be type asserted to the type of the provider. The value returned may be a deep copy of the
81 // value originally passed to SetProvider.
82 OtherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) any
83
84 // OtherModuleHasProvider returns true if the provider for the given module has been set.
85 OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool
86
Colin Cross3c0a83d2023-12-12 14:13:26 -080087 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080088
89 // Provider returns the value for a provider for the current module. If the value is
Colin Cross84b68c92023-12-20 00:59:28 +000090 // not set it returns the zero value of the type of the provider, so the return value can always
91 // be type asserted to the type of the provider. It panics if called before the appropriate
Colin Cross69452e12023-11-15 11:20:53 -080092 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
93 // copy of the value originally passed to SetProvider.
Colin Cross84b68c92023-12-20 00:59:28 +000094 Provider(provider blueprint.AnyProviderKey) any
95
96 // HasProvider returns true if the provider for the current module has been set.
97 HasProvider(provider blueprint.AnyProviderKey) bool
98
Colin Cross3c0a83d2023-12-12 14:13:26 -080099 provider(provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -0800100
Colin Cross84b68c92023-12-20 00:59:28 +0000101 // SetProvider sets the value for a provider for the current module. It panics if not called
Colin Cross69452e12023-11-15 11:20:53 -0800102 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
103 // is not of the appropriate type, or if the value has already been set. The value should not
104 // be modified after being passed to SetProvider.
Colin Cross84b68c92023-12-20 00:59:28 +0000105 SetProvider(provider blueprint.AnyProviderKey, value interface{})
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
114 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
115 // 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 Cross69452e12023-11-15 11:20:53 -0800119 // VisitDirectDepsBlueprint 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.
122 //
123 // The Module passed to the visit function should not be retained outside of the visit
124 // function, it may be invalidated by future mutators.
125 VisitDirectDepsBlueprint(visit func(blueprint.Module))
126
127 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
128 // direct dependencies on the same module visit will be called multiple times on that module
129 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
130 // dependencies are not an android.Module.
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.
134 VisitDirectDeps(visit func(Module))
135
136 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
137
138 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
139 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
140 // OtherModuleDependencyTag will return a different tag for each. It skips any
141 // dependencies that are not an android.Module.
142 //
143 // The Module passed to the visit function should not be retained outside of the visit function, it may be
144 // invalidated by future mutators.
145 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
146 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
147 VisitDepsDepthFirst(visit func(Module))
148 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
149 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
150
151 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
152 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
153 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
154 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
155 // any dependencies that are not an android.Module.
156 //
157 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
158 // invalidated by future mutators.
159 WalkDeps(visit func(child, parent Module) bool)
160
161 // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
162 // tree in top down order. visit may be called multiple times for the same (child, parent)
163 // pair if there are multiple direct dependencies between the child and parent with different
164 // tags. OtherModuleDependencyTag will return the tag for the currently visited
165 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down
166 // to child.
167 //
168 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
169 // invalidated by future mutators.
170 WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
171
172 // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
173 // and returns a top-down dependency path from a start module to current child module.
174 GetWalkPath() []Module
175
176 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
177 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
178 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
179 // only done once for all variants of a module.
180 PrimaryModule() Module
181
182 // FinalModule returns the last variant of the current module. Variants of a module are always visited in
183 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
184 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
185 // singleton actions that are only done once for all variants of a module.
186 FinalModule() Module
187
188 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
189 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
190 // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any
191 // data modified by the current mutator.
192 VisitAllModuleVariants(visit func(Module))
193
194 // GetTagPath is supposed to be called in visit function passed in WalkDeps()
195 // and returns a top-down dependency tags path from a start module to current child module.
196 // It has one less entry than GetWalkPath() as it contains the dependency tags that
197 // exist between each adjacent pair of modules in the GetWalkPath().
198 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
199 GetTagPath() []blueprint.DependencyTag
200
201 // GetPathString is supposed to be called in visit function passed in WalkDeps()
202 // and returns a multi-line string showing the modules and dependency tags
203 // among them along the top-down dependency path from a start module to current child module.
204 // skipFirst when set to true, the output doesn't include the start module,
205 // which is already printed when this function is used along with ModuleErrorf().
206 GetPathString(skipFirst bool) string
207
208 AddMissingDependencies(missingDeps []string)
209
210 // getMissingDependencies returns the list of missing dependencies.
211 // Calling this function prevents adding new dependencies.
212 getMissingDependencies() []string
213
Colin Cross69452e12023-11-15 11:20:53 -0800214 Target() Target
215 TargetPrimary() bool
216
217 // The additional arch specific targets (e.g. 32/64 bit) that this module variant is
218 // responsible for creating.
219 MultiTargets() []Target
220 Arch() Arch
221 Os() OsType
222 Host() bool
223 Device() bool
224 Darwin() bool
225 Windows() bool
226 PrimaryArch() bool
227}
228
229type baseModuleContext struct {
230 bp blueprint.BaseModuleContext
231 earlyModuleContext
232 os OsType
233 target Target
234 multiTargets []Target
235 targetPrimary bool
236
237 walkPath []Module
238 tagPath []blueprint.DependencyTag
239
240 strictVisitDeps bool // If true, enforce that all dependencies are enabled
241
Colin Cross69452e12023-11-15 11:20:53 -0800242}
243
Colin Cross69452e12023-11-15 11:20:53 -0800244func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
245 return b.bp.OtherModuleName(m)
246}
247func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
248func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
249 b.bp.OtherModuleErrorf(m, fmt, args...)
250}
251func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
252 return b.bp.OtherModuleDependencyTag(m)
253}
254func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
255func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
256 return b.bp.OtherModuleDependencyVariantExists(variations, name)
257}
258func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
259 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
260}
261func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
262 return b.bp.OtherModuleReverseDependencyVariantExists(name)
263}
264func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
265 return b.bp.OtherModuleType(m)
266}
Colin Cross84b68c92023-12-20 00:59:28 +0000267func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) any {
268 value, _ := b.bp.OtherModuleProvider(m, provider)
269 return value
270}
271
272func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool {
273 _, ok := b.bp.OtherModuleProvider(m, provider)
274 return ok
275}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800276
277func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800278 return b.bp.OtherModuleProvider(m, provider)
279}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800280
Colin Cross84b68c92023-12-20 00:59:28 +0000281func (b *baseModuleContext) Provider(provider blueprint.AnyProviderKey) any {
282 value, _ := b.bp.Provider(provider)
283 return value
284}
285
286func (b *baseModuleContext) HasProvider(provider blueprint.AnyProviderKey) bool {
287 _, ok := b.bp.Provider(provider)
288 return ok
289}
290
Colin Cross3c0a83d2023-12-12 14:13:26 -0800291func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800292 return b.bp.Provider(provider)
293}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800294
Colin Cross84b68c92023-12-20 00:59:28 +0000295func (b *baseModuleContext) SetProvider(provider blueprint.AnyProviderKey, value any) {
Colin Cross69452e12023-11-15 11:20:53 -0800296 b.bp.SetProvider(provider, value)
297}
298
299func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
300 return b.bp.GetDirectDepWithTag(name, tag)
301}
302
303func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
304 return b.bp
305}
306
Colin Cross69452e12023-11-15 11:20:53 -0800307func (b *baseModuleContext) AddMissingDependencies(deps []string) {
308 if deps != nil {
309 missingDeps := &b.Module().base().commonProperties.MissingDeps
310 *missingDeps = append(*missingDeps, deps...)
311 *missingDeps = FirstUniqueStrings(*missingDeps)
312 }
313}
314
315func (b *baseModuleContext) checkedMissingDeps() bool {
316 return b.Module().base().commonProperties.CheckedMissingDeps
317}
318
319func (b *baseModuleContext) getMissingDependencies() []string {
320 checked := &b.Module().base().commonProperties.CheckedMissingDeps
321 *checked = true
322 var missingDeps []string
323 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
324 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
325 missingDeps = FirstUniqueStrings(missingDeps)
326 return missingDeps
327}
328
329type AllowDisabledModuleDependency interface {
330 blueprint.DependencyTag
331 AllowDisabledModuleDependency(target Module) bool
332}
333
334func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
335 aModule, _ := module.(Module)
336
337 if !strict {
338 return aModule
339 }
340
341 if aModule == nil {
342 b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
343 return nil
344 }
345
346 if !aModule.Enabled() {
347 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
348 if b.Config().AllowMissingDependencies() {
349 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
350 } else {
351 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
352 }
353 }
354 return nil
355 }
356 return aModule
357}
358
359type dep struct {
360 mod blueprint.Module
361 tag blueprint.DependencyTag
362}
363
364func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
365 var deps []dep
366 b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
367 if aModule, _ := module.(Module); aModule != nil {
368 if aModule.base().BaseModuleName() == name {
369 returnedTag := b.bp.OtherModuleDependencyTag(aModule)
370 if tag == nil || returnedTag == tag {
371 deps = append(deps, dep{aModule, returnedTag})
372 }
373 }
374 } else if b.bp.OtherModuleName(module) == name {
375 returnedTag := b.bp.OtherModuleDependencyTag(module)
376 if tag == nil || returnedTag == tag {
377 deps = append(deps, dep{module, returnedTag})
378 }
379 }
380 })
381 return deps
382}
383
384func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
385 deps := b.getDirectDepsInternal(name, tag)
386 if len(deps) == 1 {
387 return deps[0].mod, deps[0].tag
388 } else if len(deps) >= 2 {
389 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
390 name, b.ModuleName()))
391 } else {
392 return nil, nil
393 }
394}
395
396func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
397 foundDeps := b.getDirectDepsInternal(name, nil)
398 deps := map[blueprint.Module]bool{}
399 for _, dep := range foundDeps {
400 deps[dep.mod] = true
401 }
402 if len(deps) == 1 {
403 return foundDeps[0].mod, foundDeps[0].tag
404 } else if len(deps) >= 2 {
405 // this could happen if two dependencies have the same name in different namespaces
406 // TODO(b/186554727): this should not occur if namespaces are handled within
407 // getDirectDepsInternal.
408 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
409 name, b.ModuleName()))
410 } else {
411 return nil, nil
412 }
413}
414
415func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
416 var deps []Module
417 b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
418 if aModule, _ := module.(Module); aModule != nil {
419 if b.bp.OtherModuleDependencyTag(aModule) == tag {
420 deps = append(deps, aModule)
421 }
422 }
423 })
424 return deps
425}
426
427// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
428// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
429// first DependencyTag.
430func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
431 return b.getDirectDepFirstTag(name)
432}
433
Colin Cross69452e12023-11-15 11:20:53 -0800434func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
435 b.bp.VisitDirectDeps(visit)
436}
437
438func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
439 b.bp.VisitDirectDeps(func(module blueprint.Module) {
440 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
441 visit(aModule)
442 }
443 })
444}
445
446func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
447 b.bp.VisitDirectDeps(func(module blueprint.Module) {
448 if b.bp.OtherModuleDependencyTag(module) == tag {
449 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
450 visit(aModule)
451 }
452 }
453 })
454}
455
456func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
457 b.bp.VisitDirectDepsIf(
458 // pred
459 func(module blueprint.Module) bool {
460 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
461 return pred(aModule)
462 } else {
463 return false
464 }
465 },
466 // visit
467 func(module blueprint.Module) {
468 visit(module.(Module))
469 })
470}
471
472func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
473 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
474 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
475 visit(aModule)
476 }
477 })
478}
479
480func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
481 b.bp.VisitDepsDepthFirstIf(
482 // pred
483 func(module blueprint.Module) bool {
484 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
485 return pred(aModule)
486 } else {
487 return false
488 }
489 },
490 // visit
491 func(module blueprint.Module) {
492 visit(module.(Module))
493 })
494}
495
496func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
497 b.bp.WalkDeps(visit)
498}
499
500func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
501 b.walkPath = []Module{b.Module()}
502 b.tagPath = []blueprint.DependencyTag{}
503 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
504 childAndroidModule, _ := child.(Module)
505 parentAndroidModule, _ := parent.(Module)
506 if childAndroidModule != nil && parentAndroidModule != nil {
507 // record walkPath before visit
508 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
509 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
510 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
511 }
512 b.walkPath = append(b.walkPath, childAndroidModule)
513 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
514 return visit(childAndroidModule, parentAndroidModule)
515 } else {
516 return false
517 }
518 })
519}
520
521func (b *baseModuleContext) GetWalkPath() []Module {
522 return b.walkPath
523}
524
525func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
526 return b.tagPath
527}
528
529func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
530 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
531 visit(module.(Module))
532 })
533}
534
535func (b *baseModuleContext) PrimaryModule() Module {
536 return b.bp.PrimaryModule().(Module)
537}
538
539func (b *baseModuleContext) FinalModule() Module {
540 return b.bp.FinalModule().(Module)
541}
542
543// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
544func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
545 if tag == licenseKindTag {
546 return true
547 } else if tag == licensesTag {
548 return true
549 } else if tag == acDepTag {
550 return true
551 }
552 return false
553}
554
555// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
556// a dependency tag.
557var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
558
559// PrettyPrintTag returns string representation of the tag, but prefers
560// custom String() method if available.
561func PrettyPrintTag(tag blueprint.DependencyTag) string {
562 // Use tag's custom String() method if available.
563 if stringer, ok := tag.(fmt.Stringer); ok {
564 return stringer.String()
565 }
566
567 // Otherwise, get a default string representation of the tag's struct.
568 tagString := fmt.Sprintf("%T: %+v", tag, tag)
569
570 // Remove the boilerplate from BaseDependencyTag as it adds no value.
571 tagString = tagCleaner.ReplaceAllString(tagString, "")
572 return tagString
573}
574
575func (b *baseModuleContext) GetPathString(skipFirst bool) string {
576 sb := strings.Builder{}
577 tagPath := b.GetTagPath()
578 walkPath := b.GetWalkPath()
579 if !skipFirst {
580 sb.WriteString(walkPath[0].String())
581 }
582 for i, m := range walkPath[1:] {
583 sb.WriteString("\n")
584 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
585 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
586 }
587 return sb.String()
588}
589
590func (b *baseModuleContext) Target() Target {
591 return b.target
592}
593
594func (b *baseModuleContext) TargetPrimary() bool {
595 return b.targetPrimary
596}
597
598func (b *baseModuleContext) MultiTargets() []Target {
599 return b.multiTargets
600}
601
602func (b *baseModuleContext) Arch() Arch {
603 return b.target.Arch
604}
605
606func (b *baseModuleContext) Os() OsType {
607 return b.os
608}
609
610func (b *baseModuleContext) Host() bool {
611 return b.os.Class == Host
612}
613
614func (b *baseModuleContext) Device() bool {
615 return b.os.Class == Device
616}
617
618func (b *baseModuleContext) Darwin() bool {
619 return b.os == Darwin
620}
621
622func (b *baseModuleContext) Windows() bool {
623 return b.os == Windows
624}
625
626func (b *baseModuleContext) PrimaryArch() bool {
627 if len(b.config.Targets[b.target.Os]) <= 1 {
628 return true
629 }
630 return b.target.Arch.ArchType == b.config.Targets[b.target.Os][0].Arch.ArchType
631}