blob: ec9c888be6eea16468e7a7ad023db283c715f055 [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
78 // 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.ProviderKey) interface{}
83
84 // OtherModuleHasProvider returns true if the provider for the given module has been set.
85 OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool
86
87 // Provider returns the value for a provider for the current module. If the value is
88 // not set it returns the zero value of the type of the provider, so the return value can always
89 // be type asserted to the type of the provider. It panics if called before the appropriate
90 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
91 // copy of the value originally passed to SetProvider.
92 Provider(provider blueprint.ProviderKey) interface{}
93
94 // HasProvider returns true if the provider for the current module has been set.
95 HasProvider(provider blueprint.ProviderKey) bool
96
97 // SetProvider sets the value for a provider for the current module. It panics if not called
98 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
99 // is not of the appropriate type, or if the value has already been set. The value should not
100 // be modified after being passed to SetProvider.
101 SetProvider(provider blueprint.ProviderKey, value interface{})
102
103 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
104
105 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
106 // none exists. It panics if the dependency does not have the specified tag. It skips any
107 // dependencies that are not an android.Module.
108 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
109
110 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
111 // name, or nil if none exists. If there are multiple dependencies on the same module it returns
112 // the first DependencyTag.
113 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
114
115 ModuleFromName(name string) (blueprint.Module, bool)
116
117 // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple
118 // direct dependencies on the same module visit will be called multiple times on that module
119 // and OtherModuleDependencyTag will return a different tag for each.
120 //
121 // The Module passed to the visit function should not be retained outside of the visit
122 // function, it may be invalidated by future mutators.
123 VisitDirectDepsBlueprint(visit func(blueprint.Module))
124
125 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
126 // direct dependencies on the same module visit will be called multiple times on that module
127 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
128 // dependencies are not an android.Module.
129 //
130 // The Module passed to the visit function should not be retained outside of the visit
131 // function, it may be invalidated by future mutators.
132 VisitDirectDeps(visit func(Module))
133
134 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
135
136 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
137 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
138 // OtherModuleDependencyTag will return a different tag for each. It skips any
139 // dependencies that are not an android.Module.
140 //
141 // The Module passed to the visit function should not be retained outside of the visit function, it may be
142 // invalidated by future mutators.
143 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
144 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
145 VisitDepsDepthFirst(visit func(Module))
146 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
147 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
148
149 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
150 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
151 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
152 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
153 // any dependencies that are not an android.Module.
154 //
155 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
156 // invalidated by future mutators.
157 WalkDeps(visit func(child, parent Module) bool)
158
159 // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
160 // tree in top down order. visit may be called multiple times for the same (child, parent)
161 // pair if there are multiple direct dependencies between the child and parent with different
162 // tags. OtherModuleDependencyTag will return the tag for the currently visited
163 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down
164 // to child.
165 //
166 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
167 // invalidated by future mutators.
168 WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
169
170 // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
171 // and returns a top-down dependency path from a start module to current child module.
172 GetWalkPath() []Module
173
174 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
175 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
176 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
177 // only done once for all variants of a module.
178 PrimaryModule() Module
179
180 // FinalModule returns the last 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 all
182 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
183 // singleton actions that are only done once for all variants of a module.
184 FinalModule() Module
185
186 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
187 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
188 // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any
189 // data modified by the current mutator.
190 VisitAllModuleVariants(visit func(Module))
191
192 // GetTagPath is supposed to be called in visit function passed in WalkDeps()
193 // and returns a top-down dependency tags path from a start module to current child module.
194 // It has one less entry than GetWalkPath() as it contains the dependency tags that
195 // exist between each adjacent pair of modules in the GetWalkPath().
196 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
197 GetTagPath() []blueprint.DependencyTag
198
199 // GetPathString is supposed to be called in visit function passed in WalkDeps()
200 // and returns a multi-line string showing the modules and dependency tags
201 // among them along the top-down dependency path from a start module to current child module.
202 // skipFirst when set to true, the output doesn't include the start module,
203 // which is already printed when this function is used along with ModuleErrorf().
204 GetPathString(skipFirst bool) string
205
206 AddMissingDependencies(missingDeps []string)
207
208 // getMissingDependencies returns the list of missing dependencies.
209 // Calling this function prevents adding new dependencies.
210 getMissingDependencies() []string
211
212 // AddUnconvertedBp2buildDep stores module name of a direct dependency that was not converted via bp2build
213 AddUnconvertedBp2buildDep(dep string)
214
215 // AddMissingBp2buildDep stores the module name of a direct dependency that was not found.
216 AddMissingBp2buildDep(dep string)
217
218 Target() Target
219 TargetPrimary() bool
220
221 // The additional arch specific targets (e.g. 32/64 bit) that this module variant is
222 // responsible for creating.
223 MultiTargets() []Target
224 Arch() Arch
225 Os() OsType
226 Host() bool
227 Device() bool
228 Darwin() bool
229 Windows() bool
230 PrimaryArch() bool
231}
232
233type baseModuleContext struct {
234 bp blueprint.BaseModuleContext
235 earlyModuleContext
236 os OsType
237 target Target
238 multiTargets []Target
239 targetPrimary bool
240
241 walkPath []Module
242 tagPath []blueprint.DependencyTag
243
244 strictVisitDeps bool // If true, enforce that all dependencies are enabled
245
246 bazelConversionMode bool
247}
248
249func (b *baseModuleContext) isBazelConversionMode() bool {
250 return b.bazelConversionMode
251}
252func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
253 return b.bp.OtherModuleName(m)
254}
255func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
256func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
257 b.bp.OtherModuleErrorf(m, fmt, args...)
258}
259func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
260 return b.bp.OtherModuleDependencyTag(m)
261}
262func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
263func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
264 return b.bp.OtherModuleDependencyVariantExists(variations, name)
265}
266func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
267 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
268}
269func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
270 return b.bp.OtherModuleReverseDependencyVariantExists(name)
271}
272func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
273 return b.bp.OtherModuleType(m)
274}
275func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} {
276 return b.bp.OtherModuleProvider(m, provider)
277}
278func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool {
279 return b.bp.OtherModuleHasProvider(m, provider)
280}
281func (b *baseModuleContext) Provider(provider blueprint.ProviderKey) interface{} {
282 return b.bp.Provider(provider)
283}
284func (b *baseModuleContext) HasProvider(provider blueprint.ProviderKey) bool {
285 return b.bp.HasProvider(provider)
286}
287func (b *baseModuleContext) SetProvider(provider blueprint.ProviderKey, value interface{}) {
288 b.bp.SetProvider(provider, value)
289}
290
291func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
292 return b.bp.GetDirectDepWithTag(name, tag)
293}
294
295func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
296 return b.bp
297}
298
299// AddUnconvertedBp2buildDep stores module name of a dependency that was not converted to Bazel.
300func (b *baseModuleContext) AddUnconvertedBp2buildDep(dep string) {
301 unconvertedDeps := &b.Module().base().commonProperties.BazelConversionStatus.UnconvertedDeps
302 *unconvertedDeps = append(*unconvertedDeps, dep)
303}
304
305// AddMissingBp2buildDep stores module name of a dependency that was not found in a Android.bp file.
306func (b *baseModuleContext) AddMissingBp2buildDep(dep string) {
307 missingDeps := &b.Module().base().commonProperties.BazelConversionStatus.MissingDeps
308 *missingDeps = append(*missingDeps, dep)
309}
310
311func (b *baseModuleContext) AddMissingDependencies(deps []string) {
312 if deps != nil {
313 missingDeps := &b.Module().base().commonProperties.MissingDeps
314 *missingDeps = append(*missingDeps, deps...)
315 *missingDeps = FirstUniqueStrings(*missingDeps)
316 }
317}
318
319func (b *baseModuleContext) checkedMissingDeps() bool {
320 return b.Module().base().commonProperties.CheckedMissingDeps
321}
322
323func (b *baseModuleContext) getMissingDependencies() []string {
324 checked := &b.Module().base().commonProperties.CheckedMissingDeps
325 *checked = true
326 var missingDeps []string
327 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
328 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
329 missingDeps = FirstUniqueStrings(missingDeps)
330 return missingDeps
331}
332
333type AllowDisabledModuleDependency interface {
334 blueprint.DependencyTag
335 AllowDisabledModuleDependency(target Module) bool
336}
337
338func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
339 aModule, _ := module.(Module)
340
341 if !strict {
342 return aModule
343 }
344
345 if aModule == nil {
346 b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
347 return nil
348 }
349
350 if !aModule.Enabled() {
351 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
352 if b.Config().AllowMissingDependencies() {
353 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
354 } else {
355 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
356 }
357 }
358 return nil
359 }
360 return aModule
361}
362
363type dep struct {
364 mod blueprint.Module
365 tag blueprint.DependencyTag
366}
367
368func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
369 var deps []dep
370 b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
371 if aModule, _ := module.(Module); aModule != nil {
372 if aModule.base().BaseModuleName() == name {
373 returnedTag := b.bp.OtherModuleDependencyTag(aModule)
374 if tag == nil || returnedTag == tag {
375 deps = append(deps, dep{aModule, returnedTag})
376 }
377 }
378 } else if b.bp.OtherModuleName(module) == name {
379 returnedTag := b.bp.OtherModuleDependencyTag(module)
380 if tag == nil || returnedTag == tag {
381 deps = append(deps, dep{module, returnedTag})
382 }
383 }
384 })
385 return deps
386}
387
388func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
389 deps := b.getDirectDepsInternal(name, tag)
390 if len(deps) == 1 {
391 return deps[0].mod, deps[0].tag
392 } else if len(deps) >= 2 {
393 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
394 name, b.ModuleName()))
395 } else {
396 return nil, nil
397 }
398}
399
400func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
401 foundDeps := b.getDirectDepsInternal(name, nil)
402 deps := map[blueprint.Module]bool{}
403 for _, dep := range foundDeps {
404 deps[dep.mod] = true
405 }
406 if len(deps) == 1 {
407 return foundDeps[0].mod, foundDeps[0].tag
408 } else if len(deps) >= 2 {
409 // this could happen if two dependencies have the same name in different namespaces
410 // TODO(b/186554727): this should not occur if namespaces are handled within
411 // getDirectDepsInternal.
412 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
413 name, b.ModuleName()))
414 } else {
415 return nil, nil
416 }
417}
418
419func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
420 var deps []Module
421 b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
422 if aModule, _ := module.(Module); aModule != nil {
423 if b.bp.OtherModuleDependencyTag(aModule) == tag {
424 deps = append(deps, aModule)
425 }
426 }
427 })
428 return deps
429}
430
431// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
432// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
433// first DependencyTag.
434func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
435 return b.getDirectDepFirstTag(name)
436}
437
438func (b *baseModuleContext) ModuleFromName(name string) (blueprint.Module, bool) {
439 if !b.isBazelConversionMode() {
440 panic("cannot call ModuleFromName if not in bazel conversion mode")
441 }
442 var m blueprint.Module
443 var ok bool
444 if moduleName, _ := SrcIsModuleWithTag(name); moduleName != "" {
445 m, ok = b.bp.ModuleFromName(moduleName)
446 } else {
447 m, ok = b.bp.ModuleFromName(name)
448 }
449 if !ok {
450 return m, ok
451 }
452 // If this module is not preferred, tried to get the prebuilt version instead
453 if a, aOk := m.(Module); aOk && !IsModulePrebuilt(a) && !IsModulePreferred(a) {
454 return b.ModuleFromName("prebuilt_" + name)
455 }
456 return m, ok
457}
458
459func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
460 b.bp.VisitDirectDeps(visit)
461}
462
463func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
464 b.bp.VisitDirectDeps(func(module blueprint.Module) {
465 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
466 visit(aModule)
467 }
468 })
469}
470
471func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
472 b.bp.VisitDirectDeps(func(module blueprint.Module) {
473 if b.bp.OtherModuleDependencyTag(module) == tag {
474 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
475 visit(aModule)
476 }
477 }
478 })
479}
480
481func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
482 b.bp.VisitDirectDepsIf(
483 // pred
484 func(module blueprint.Module) bool {
485 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
486 return pred(aModule)
487 } else {
488 return false
489 }
490 },
491 // visit
492 func(module blueprint.Module) {
493 visit(module.(Module))
494 })
495}
496
497func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
498 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
499 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
500 visit(aModule)
501 }
502 })
503}
504
505func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
506 b.bp.VisitDepsDepthFirstIf(
507 // pred
508 func(module blueprint.Module) bool {
509 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
510 return pred(aModule)
511 } else {
512 return false
513 }
514 },
515 // visit
516 func(module blueprint.Module) {
517 visit(module.(Module))
518 })
519}
520
521func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
522 b.bp.WalkDeps(visit)
523}
524
525func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
526 b.walkPath = []Module{b.Module()}
527 b.tagPath = []blueprint.DependencyTag{}
528 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
529 childAndroidModule, _ := child.(Module)
530 parentAndroidModule, _ := parent.(Module)
531 if childAndroidModule != nil && parentAndroidModule != nil {
532 // record walkPath before visit
533 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
534 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
535 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
536 }
537 b.walkPath = append(b.walkPath, childAndroidModule)
538 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
539 return visit(childAndroidModule, parentAndroidModule)
540 } else {
541 return false
542 }
543 })
544}
545
546func (b *baseModuleContext) GetWalkPath() []Module {
547 return b.walkPath
548}
549
550func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
551 return b.tagPath
552}
553
554func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
555 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
556 visit(module.(Module))
557 })
558}
559
560func (b *baseModuleContext) PrimaryModule() Module {
561 return b.bp.PrimaryModule().(Module)
562}
563
564func (b *baseModuleContext) FinalModule() Module {
565 return b.bp.FinalModule().(Module)
566}
567
568// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
569func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
570 if tag == licenseKindTag {
571 return true
572 } else if tag == licensesTag {
573 return true
574 } else if tag == acDepTag {
575 return true
576 }
577 return false
578}
579
580// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
581// a dependency tag.
582var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
583
584// PrettyPrintTag returns string representation of the tag, but prefers
585// custom String() method if available.
586func PrettyPrintTag(tag blueprint.DependencyTag) string {
587 // Use tag's custom String() method if available.
588 if stringer, ok := tag.(fmt.Stringer); ok {
589 return stringer.String()
590 }
591
592 // Otherwise, get a default string representation of the tag's struct.
593 tagString := fmt.Sprintf("%T: %+v", tag, tag)
594
595 // Remove the boilerplate from BaseDependencyTag as it adds no value.
596 tagString = tagCleaner.ReplaceAllString(tagString, "")
597 return tagString
598}
599
600func (b *baseModuleContext) GetPathString(skipFirst bool) string {
601 sb := strings.Builder{}
602 tagPath := b.GetTagPath()
603 walkPath := b.GetWalkPath()
604 if !skipFirst {
605 sb.WriteString(walkPath[0].String())
606 }
607 for i, m := range walkPath[1:] {
608 sb.WriteString("\n")
609 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
610 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
611 }
612 return sb.String()
613}
614
615func (b *baseModuleContext) Target() Target {
616 return b.target
617}
618
619func (b *baseModuleContext) TargetPrimary() bool {
620 return b.targetPrimary
621}
622
623func (b *baseModuleContext) MultiTargets() []Target {
624 return b.multiTargets
625}
626
627func (b *baseModuleContext) Arch() Arch {
628 return b.target.Arch
629}
630
631func (b *baseModuleContext) Os() OsType {
632 return b.os
633}
634
635func (b *baseModuleContext) Host() bool {
636 return b.os.Class == Host
637}
638
639func (b *baseModuleContext) Device() bool {
640 return b.os.Class == Device
641}
642
643func (b *baseModuleContext) Darwin() bool {
644 return b.os == Darwin
645}
646
647func (b *baseModuleContext) Windows() bool {
648 return b.os == Windows
649}
650
651func (b *baseModuleContext) PrimaryArch() bool {
652 if len(b.config.Targets[b.target.Os]) <= 1 {
653 return true
654 }
655 return b.target.Arch.ArchType == b.config.Targets[b.target.Os][0].Arch.ArchType
656}