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