blob: bb8137720e0cd352e5f8a543ef8d5d847f156ee9 [file] [log] [blame]
Colin Cross69452e12023-11-15 11:20:53 -08001// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
18 "fmt"
Colin Cross69452e12023-11-15 11:20:53 -080019 "regexp"
20 "strings"
Cole Faustbdd8aee2024-03-14 14:33:02 -070021
22 "github.com/google/blueprint"
Cole Faustfdbf5d42024-04-10 15:01:23 -070023 "github.com/google/blueprint/proptools"
Colin Cross69452e12023-11-15 11:20:53 -080024)
25
26// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
27// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module
28// instead of a blueprint.Module, plus some extra methods that return Android-specific information
29// about the current module.
30type BaseModuleContext interface {
Colin Cross1d3d9f12024-01-18 14:30:22 -080031 ArchModuleContext
Colin Cross69452e12023-11-15 11:20:53 -080032 EarlyModuleContext
33
34 blueprintBaseModuleContext() blueprint.BaseModuleContext
35
36 // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
37 // It is intended for use inside the visit functions of Visit* and WalkDeps.
38 OtherModuleName(m blueprint.Module) string
39
40 // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
41 // It is intended for use inside the visit functions of Visit* and WalkDeps.
42 OtherModuleDir(m blueprint.Module) string
43
44 // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
45 // It is intended for use inside the visit functions of Visit* and WalkDeps.
46 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
47
48 // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
49 // on the module. When called inside a Visit* method with current module being visited, and there are multiple
50 // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
51 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
52
53 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
54 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
55 OtherModuleExists(name string) bool
56
57 // OtherModuleDependencyVariantExists returns true if a module with the
58 // specified name and variant exists. The variant must match the given
59 // variations. It must also match all the non-local variations of the current
60 // module. In other words, it checks for the module that AddVariationDependencies
61 // would add a dependency on with the same arguments.
62 OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
63
64 // OtherModuleFarDependencyVariantExists returns true if a module with the
65 // specified name and variant exists. The variant must match the given
66 // variations, but not the non-local variations of the current module. In
67 // other words, it checks for the module that AddFarVariationDependencies
68 // would add a dependency on with the same arguments.
69 OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
70
71 // OtherModuleReverseDependencyVariantExists returns true if a module with the
72 // specified name exists with the same variations as the current module. In
73 // other words, it checks for the module that AddReverseDependency would add a
74 // dependency on with the same argument.
75 OtherModuleReverseDependencyVariantExists(name string) bool
76
77 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
78 // It is intended for use inside the visit functions of Visit* and WalkDeps.
79 OtherModuleType(m blueprint.Module) string
80
Colin Cross24c1cbe2023-12-21 23:42:56 +000081 // otherModuleProvider returns the value for a provider for the given module. If the value is
82 // not set it returns nil and false. The value returned may be a deep copy of the value originally
83 // passed to SetProvider.
84 //
85 // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080086 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080087
88 // Provider returns the value for a provider for the current module. If the value is
Colin Cross24c1cbe2023-12-21 23:42:56 +000089 // not set it returns nil and false. It panics if called before the appropriate
Colin Cross69452e12023-11-15 11:20:53 -080090 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
91 // copy of the value originally passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +000092 //
93 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080094 provider(provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080095
Colin Cross24c1cbe2023-12-21 23:42:56 +000096 // setProvider sets the value for a provider for the current module. It panics if not called
Colin Cross69452e12023-11-15 11:20:53 -080097 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
98 // is not of the appropriate type, or if the value has already been set. The value should not
99 // be modified after being passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000100 //
101 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
102 setProvider(provider blueprint.AnyProviderKey, value any)
Colin Cross69452e12023-11-15 11:20:53 -0800103
104 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
105
106 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
107 // none exists. It panics if the dependency does not have the specified tag. It skips any
108 // dependencies that are not an android.Module.
109 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
110
LaMont Jones34314b72024-01-18 18:27:35 +0000111 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
Colin Cross69452e12023-11-15 11:20:53 -0800112 // name, or nil if none exists. If there are multiple dependencies on the same module it returns
113 // the first DependencyTag.
114 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
115
Colin Cross69452e12023-11-15 11:20:53 -0800116 // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple
117 // direct dependencies on the same module visit will be called multiple times on that module
118 // and OtherModuleDependencyTag will return a different tag for each.
119 //
120 // The Module passed to the visit function should not be retained outside of the visit
121 // function, it may be invalidated by future mutators.
122 VisitDirectDepsBlueprint(visit func(blueprint.Module))
123
LaMont Jones34314b72024-01-18 18:27:35 +0000124 // VisitDirectDepsIgnoreBlueprint calls visit for each direct dependency. If there are multiple
125 // direct dependencies on the same module visit will be called multiple times on that module
126 // and OtherModuleDependencyTag will return a different tag for each. It silently ignores any
127 // dependencies that are not an android.Module.
128 //
129 // The Module passed to the visit function should not be retained outside of the visit
130 // function, it may be invalidated by future mutators.
131 VisitDirectDepsIgnoreBlueprint(visit func(Module))
132
Colin Cross69452e12023-11-15 11:20:53 -0800133 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
134 // direct dependencies on the same module visit will be called multiple times on that module
135 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
136 // dependencies are not an android.Module.
137 //
138 // The Module passed to the visit function should not be retained outside of the visit
139 // function, it may be invalidated by future mutators.
140 VisitDirectDeps(visit func(Module))
141
142 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
143
144 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
145 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
146 // OtherModuleDependencyTag will return a different tag for each. It skips any
147 // dependencies that are not an android.Module.
148 //
149 // The Module passed to the visit function should not be retained outside of the visit function, it may be
150 // invalidated by future mutators.
151 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
152 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
153 VisitDepsDepthFirst(visit func(Module))
154 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
155 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
156
157 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
158 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
159 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
160 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
161 // any dependencies that are not an android.Module.
162 //
163 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
164 // invalidated by future mutators.
165 WalkDeps(visit func(child, parent Module) bool)
166
167 // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
168 // tree in top down order. visit may be called multiple times for the same (child, parent)
169 // pair if there are multiple direct dependencies between the child and parent with different
170 // tags. OtherModuleDependencyTag will return the tag for the currently visited
171 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down
172 // to child.
173 //
174 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
175 // invalidated by future mutators.
176 WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
177
178 // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
179 // and returns a top-down dependency path from a start module to current child module.
180 GetWalkPath() []Module
181
182 // PrimaryModule returns the first 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 the
184 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
185 // only done once for all variants of a module.
186 PrimaryModule() Module
187
188 // FinalModule returns the last variant of the current module. Variants of a module are always visited in
189 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
190 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
191 // singleton actions that are only done once for all variants of a module.
192 FinalModule() Module
193
194 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
195 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
196 // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any
197 // data modified by the current mutator.
198 VisitAllModuleVariants(visit func(Module))
199
200 // GetTagPath is supposed to be called in visit function passed in WalkDeps()
201 // and returns a top-down dependency tags path from a start module to current child module.
202 // It has one less entry than GetWalkPath() as it contains the dependency tags that
203 // exist between each adjacent pair of modules in the GetWalkPath().
204 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
205 GetTagPath() []blueprint.DependencyTag
206
207 // GetPathString is supposed to be called in visit function passed in WalkDeps()
208 // and returns a multi-line string showing the modules and dependency tags
209 // among them along the top-down dependency path from a start module to current child module.
210 // skipFirst when set to true, the output doesn't include the start module,
211 // which is already printed when this function is used along with ModuleErrorf().
212 GetPathString(skipFirst bool) string
213
214 AddMissingDependencies(missingDeps []string)
215
216 // getMissingDependencies returns the list of missing dependencies.
217 // Calling this function prevents adding new dependencies.
218 getMissingDependencies() []string
Cole Faustbdd8aee2024-03-14 14:33:02 -0700219
220 // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
221 // can be used to evaluate the final value of Configurable properties.
Cole Faustfdbf5d42024-04-10 15:01:23 -0700222 EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue
Cole Faust4e2bf9f2024-09-11 13:26:20 -0700223
224 // HasMutatorFinished returns true if the given mutator has finished running.
225 // It will panic if given an invalid mutator name.
226 HasMutatorFinished(mutatorName string) bool
Colin Cross69452e12023-11-15 11:20:53 -0800227}
228
229type baseModuleContext struct {
230 bp blueprint.BaseModuleContext
231 earlyModuleContext
Colin Cross1d3d9f12024-01-18 14:30:22 -0800232 archModuleContext
Colin Cross69452e12023-11-15 11:20:53 -0800233
234 walkPath []Module
235 tagPath []blueprint.DependencyTag
236
237 strictVisitDeps bool // If true, enforce that all dependencies are enabled
238
Colin Cross69452e12023-11-15 11:20:53 -0800239}
240
Colin Cross69452e12023-11-15 11:20:53 -0800241func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
242 return b.bp.OtherModuleName(m)
243}
244func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
245func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
246 b.bp.OtherModuleErrorf(m, fmt, args...)
247}
248func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
249 return b.bp.OtherModuleDependencyTag(m)
250}
251func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
252func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
253 return b.bp.OtherModuleDependencyVariantExists(variations, name)
254}
255func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
256 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
257}
258func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
259 return b.bp.OtherModuleReverseDependencyVariantExists(name)
260}
261func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
262 return b.bp.OtherModuleType(m)
263}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800264
265func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800266 return b.bp.OtherModuleProvider(m, provider)
267}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800268
Colin Cross3c0a83d2023-12-12 14:13:26 -0800269func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800270 return b.bp.Provider(provider)
271}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800272
Colin Cross24c1cbe2023-12-21 23:42:56 +0000273func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
Colin Cross69452e12023-11-15 11:20:53 -0800274 b.bp.SetProvider(provider, value)
275}
276
Cole Faust4e2bf9f2024-09-11 13:26:20 -0700277func (b *baseModuleContext) HasMutatorFinished(mutatorName string) bool {
278 return b.bp.HasMutatorFinished(mutatorName)
279}
280
Colin Cross69452e12023-11-15 11:20:53 -0800281func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
282 return b.bp.GetDirectDepWithTag(name, tag)
283}
284
285func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
286 return b.bp
287}
288
Colin Cross69452e12023-11-15 11:20:53 -0800289func (b *baseModuleContext) AddMissingDependencies(deps []string) {
290 if deps != nil {
291 missingDeps := &b.Module().base().commonProperties.MissingDeps
292 *missingDeps = append(*missingDeps, deps...)
293 *missingDeps = FirstUniqueStrings(*missingDeps)
294 }
295}
296
297func (b *baseModuleContext) checkedMissingDeps() bool {
298 return b.Module().base().commonProperties.CheckedMissingDeps
299}
300
301func (b *baseModuleContext) getMissingDependencies() []string {
302 checked := &b.Module().base().commonProperties.CheckedMissingDeps
303 *checked = true
304 var missingDeps []string
305 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
306 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
307 missingDeps = FirstUniqueStrings(missingDeps)
308 return missingDeps
309}
310
311type AllowDisabledModuleDependency interface {
312 blueprint.DependencyTag
313 AllowDisabledModuleDependency(target Module) bool
314}
315
Jiyong Park8bcf3c62024-03-18 18:37:10 +0900316type AlwaysAllowDisabledModuleDependencyTag struct{}
317
318func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
319 return true
320}
321
LaMont Jones34314b72024-01-18 18:27:35 +0000322func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool, ignoreBlueprint bool) Module {
Colin Cross69452e12023-11-15 11:20:53 -0800323 aModule, _ := module.(Module)
324
325 if !strict {
326 return aModule
327 }
328
329 if aModule == nil {
LaMont Jones34314b72024-01-18 18:27:35 +0000330 if !ignoreBlueprint {
331 b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
332 }
Colin Cross69452e12023-11-15 11:20:53 -0800333 return nil
334 }
335
Cole Fausta963b942024-04-11 17:43:00 -0700336 if !aModule.Enabled(b) {
Colin Cross69452e12023-11-15 11:20:53 -0800337 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
338 if b.Config().AllowMissingDependencies() {
339 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
340 } else {
341 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
342 }
343 }
344 return nil
345 }
346 return aModule
347}
348
349type dep struct {
350 mod blueprint.Module
351 tag blueprint.DependencyTag
352}
353
354func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
355 var deps []dep
356 b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
357 if aModule, _ := module.(Module); aModule != nil {
358 if aModule.base().BaseModuleName() == name {
359 returnedTag := b.bp.OtherModuleDependencyTag(aModule)
360 if tag == nil || returnedTag == tag {
361 deps = append(deps, dep{aModule, returnedTag})
362 }
363 }
364 } else if b.bp.OtherModuleName(module) == name {
365 returnedTag := b.bp.OtherModuleDependencyTag(module)
366 if tag == nil || returnedTag == tag {
367 deps = append(deps, dep{module, returnedTag})
368 }
369 }
370 })
371 return deps
372}
373
374func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
375 deps := b.getDirectDepsInternal(name, tag)
376 if len(deps) == 1 {
377 return deps[0].mod, deps[0].tag
378 } else if len(deps) >= 2 {
379 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
380 name, b.ModuleName()))
381 } else {
382 return nil, nil
383 }
384}
385
386func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
387 foundDeps := b.getDirectDepsInternal(name, nil)
388 deps := map[blueprint.Module]bool{}
389 for _, dep := range foundDeps {
390 deps[dep.mod] = true
391 }
392 if len(deps) == 1 {
393 return foundDeps[0].mod, foundDeps[0].tag
394 } else if len(deps) >= 2 {
395 // this could happen if two dependencies have the same name in different namespaces
396 // TODO(b/186554727): this should not occur if namespaces are handled within
397 // getDirectDepsInternal.
398 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
399 name, b.ModuleName()))
400 } else {
401 return nil, nil
402 }
403}
404
405func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
406 var deps []Module
407 b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
408 if aModule, _ := module.(Module); aModule != nil {
409 if b.bp.OtherModuleDependencyTag(aModule) == tag {
410 deps = append(deps, aModule)
411 }
412 }
413 })
414 return deps
415}
416
417// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
418// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
419// first DependencyTag.
420func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
421 return b.getDirectDepFirstTag(name)
422}
423
Colin Cross69452e12023-11-15 11:20:53 -0800424func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
425 b.bp.VisitDirectDeps(visit)
426}
427
428func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
LaMont Jones34314b72024-01-18 18:27:35 +0000429 b.visitDirectDeps(visit, false)
430}
431
432func (b *baseModuleContext) VisitDirectDepsIgnoreBlueprint(visit func(Module)) {
433 b.visitDirectDeps(visit, true)
434}
435
436func (b *baseModuleContext) visitDirectDeps(visit func(Module), ignoreBlueprint bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800437 b.bp.VisitDirectDeps(func(module blueprint.Module) {
LaMont Jones34314b72024-01-18 18:27:35 +0000438 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, ignoreBlueprint); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800439 visit(aModule)
440 }
441 })
442}
443
444func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
445 b.bp.VisitDirectDeps(func(module blueprint.Module) {
446 if b.bp.OtherModuleDependencyTag(module) == tag {
LaMont Jones34314b72024-01-18 18:27:35 +0000447 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800448 visit(aModule)
449 }
450 }
451 })
452}
453
454func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
455 b.bp.VisitDirectDepsIf(
456 // pred
457 func(module blueprint.Module) bool {
LaMont Jones34314b72024-01-18 18:27:35 +0000458 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800459 return pred(aModule)
460 } else {
461 return false
462 }
463 },
464 // visit
465 func(module blueprint.Module) {
466 visit(module.(Module))
467 })
468}
469
470func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
471 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
LaMont Jones34314b72024-01-18 18:27:35 +0000472 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800473 visit(aModule)
474 }
475 })
476}
477
478func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
479 b.bp.VisitDepsDepthFirstIf(
480 // pred
481 func(module blueprint.Module) bool {
LaMont Jones34314b72024-01-18 18:27:35 +0000482 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800483 return pred(aModule)
484 } else {
485 return false
486 }
487 },
488 // visit
489 func(module blueprint.Module) {
490 visit(module.(Module))
491 })
492}
493
494func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
495 b.bp.WalkDeps(visit)
496}
497
498func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
499 b.walkPath = []Module{b.Module()}
500 b.tagPath = []blueprint.DependencyTag{}
501 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
502 childAndroidModule, _ := child.(Module)
503 parentAndroidModule, _ := parent.(Module)
504 if childAndroidModule != nil && parentAndroidModule != nil {
505 // record walkPath before visit
506 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
507 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
508 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
509 }
510 b.walkPath = append(b.walkPath, childAndroidModule)
511 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
512 return visit(childAndroidModule, parentAndroidModule)
513 } else {
514 return false
515 }
516 })
517}
518
519func (b *baseModuleContext) GetWalkPath() []Module {
520 return b.walkPath
521}
522
523func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
524 return b.tagPath
525}
526
527func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
528 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
529 visit(module.(Module))
530 })
531}
532
533func (b *baseModuleContext) PrimaryModule() Module {
534 return b.bp.PrimaryModule().(Module)
535}
536
537func (b *baseModuleContext) FinalModule() Module {
538 return b.bp.FinalModule().(Module)
539}
540
541// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
542func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
543 if tag == licenseKindTag {
544 return true
545 } else if tag == licensesTag {
546 return true
Jihoon Kanga3a05462024-04-05 00:36:44 +0000547 } else if tag == AcDepTag {
Colin Cross69452e12023-11-15 11:20:53 -0800548 return true
549 }
550 return false
551}
552
553// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
554// a dependency tag.
555var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
556
557// PrettyPrintTag returns string representation of the tag, but prefers
558// custom String() method if available.
559func PrettyPrintTag(tag blueprint.DependencyTag) string {
560 // Use tag's custom String() method if available.
561 if stringer, ok := tag.(fmt.Stringer); ok {
562 return stringer.String()
563 }
564
565 // Otherwise, get a default string representation of the tag's struct.
566 tagString := fmt.Sprintf("%T: %+v", tag, tag)
567
568 // Remove the boilerplate from BaseDependencyTag as it adds no value.
569 tagString = tagCleaner.ReplaceAllString(tagString, "")
570 return tagString
571}
572
573func (b *baseModuleContext) GetPathString(skipFirst bool) string {
574 sb := strings.Builder{}
575 tagPath := b.GetTagPath()
576 walkPath := b.GetWalkPath()
577 if !skipFirst {
578 sb.WriteString(walkPath[0].String())
579 }
580 for i, m := range walkPath[1:] {
581 sb.WriteString("\n")
582 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
583 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
584 }
585 return sb.String()
586}
Cole Faustbdd8aee2024-03-14 14:33:02 -0700587
Cole Faustfdbf5d42024-04-10 15:01:23 -0700588func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
589 return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property)
Cole Faustbdd8aee2024-03-14 14:33:02 -0700590}