blob: 670537fb5cb2236b84fdd81fe51fea0aad71827c [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
Yu Liudd9ccb42024-10-07 17:07:44 +000036 EqualModules(m1, m2 Module) bool
37
Colin Cross69452e12023-11-15 11:20:53 -080038 // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
39 // It is intended for use inside the visit functions of Visit* and WalkDeps.
40 OtherModuleName(m blueprint.Module) string
41
42 // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
43 // It is intended for use inside the visit functions of Visit* and WalkDeps.
44 OtherModuleDir(m blueprint.Module) string
45
46 // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
47 // It is intended for use inside the visit functions of Visit* and WalkDeps.
48 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
49
50 // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
51 // on the module. When called inside a Visit* method with current module being visited, and there are multiple
52 // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
53 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
54
55 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
56 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
57 OtherModuleExists(name string) bool
58
59 // OtherModuleDependencyVariantExists returns true if a module with the
60 // specified name and variant exists. The variant must match the given
61 // variations. It must also match all the non-local variations of the current
62 // module. In other words, it checks for the module that AddVariationDependencies
63 // would add a dependency on with the same arguments.
64 OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
65
66 // OtherModuleFarDependencyVariantExists returns true if a module with the
67 // specified name and variant exists. The variant must match the given
68 // variations, but not the non-local variations of the current module. In
69 // other words, it checks for the module that AddFarVariationDependencies
70 // would add a dependency on with the same arguments.
71 OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
72
73 // OtherModuleReverseDependencyVariantExists returns true if a module with the
74 // specified name exists with the same variations as the current module. In
75 // other words, it checks for the module that AddReverseDependency would add a
76 // dependency on with the same argument.
77 OtherModuleReverseDependencyVariantExists(name string) bool
78
79 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
80 // It is intended for use inside the visit functions of Visit* and WalkDeps.
81 OtherModuleType(m blueprint.Module) string
82
Colin Cross24c1cbe2023-12-21 23:42:56 +000083 // otherModuleProvider returns the value for a provider for the given module. If the value is
84 // not set it returns nil and false. The value returned may be a deep copy of the value originally
85 // passed to SetProvider.
86 //
87 // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080088 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080089
90 // Provider returns the value for a provider for the current module. If the value is
Colin Cross24c1cbe2023-12-21 23:42:56 +000091 // not set it returns nil and false. 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 Cross24c1cbe2023-12-21 23:42:56 +000094 //
95 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080096 provider(provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080097
Colin Cross24c1cbe2023-12-21 23:42:56 +000098 // setProvider sets the value for a provider for the current module. It panics if not called
Colin Cross69452e12023-11-15 11:20:53 -080099 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
100 // is not of the appropriate type, or if the value has already been set. The value should not
101 // be modified after being passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000102 //
103 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
104 setProvider(provider blueprint.AnyProviderKey, value any)
Colin Cross69452e12023-11-15 11:20:53 -0800105
106 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
107
108 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
109 // none exists. It panics if the dependency does not have the specified tag. It skips any
110 // dependencies that are not an android.Module.
111 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
112
LaMont Jones34314b72024-01-18 18:27:35 +0000113 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
Colin Cross69452e12023-11-15 11:20:53 -0800114 // name, or nil if none exists. If there are multiple dependencies on the same module it returns
115 // the first DependencyTag.
116 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
117
Colin Cross648daea2024-09-12 14:35:29 -0700118 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
119 // direct dependencies on the same module visit will be called multiple times on that module
120 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
121 // dependencies are disabled.
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 VisitDirectDeps(visit func(Module))
126
127 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
Colin Cross69452e12023-11-15 11:20:53 -0800128 // 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.
130 //
131 // The Module passed to the visit function should not be retained outside of the visit
132 // function, it may be invalidated by future mutators.
Colin Cross648daea2024-09-12 14:35:29 -0700133 VisitDirectDepsAllowDisabled(visit func(Module))
Colin Cross69452e12023-11-15 11:20:53 -0800134
Yu Liudd9ccb42024-10-07 17:07:44 +0000135 // VisitDirectDepsProxyAllowDisabled calls visit for each direct dependency. If there are
136 // multiple direct dependencies on the same module visit will be called multiple times on
137 // that module and OtherModuleDependencyTag will return a different tag for each.
138 //
139 // The Module passed to the visit function should not be retained outside of the visit function, it may be
140 // invalidated by future mutators.
141 VisitDirectDepsProxyAllowDisabled(visit func(proxy Module))
142
Colin Cross69452e12023-11-15 11:20:53 -0800143 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
144
145 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
146 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
147 // OtherModuleDependencyTag will return a different tag for each. It skips any
148 // dependencies that are not an android.Module.
149 //
150 // The Module passed to the visit function should not be retained outside of the visit function, it may be
151 // invalidated by future mutators.
152 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
153 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
154 VisitDepsDepthFirst(visit func(Module))
155 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
156 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
157
158 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
159 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
160 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
161 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
162 // any dependencies that are not an android.Module.
163 //
164 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
165 // invalidated by future mutators.
166 WalkDeps(visit func(child, parent Module) bool)
167
Yu Liudd9ccb42024-10-07 17:07:44 +0000168 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
169 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
170 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
171 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
172 // any dependencies that are not an android.Module.
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 WalkDepsProxy(visit func(child, parent Module) bool)
177
Colin Cross69452e12023-11-15 11:20:53 -0800178 // 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
Colin Cross69452e12023-11-15 11:20:53 -0800223}
224
225type baseModuleContext struct {
226 bp blueprint.BaseModuleContext
227 earlyModuleContext
Colin Cross1d3d9f12024-01-18 14:30:22 -0800228 archModuleContext
Colin Cross69452e12023-11-15 11:20:53 -0800229
230 walkPath []Module
231 tagPath []blueprint.DependencyTag
232
233 strictVisitDeps bool // If true, enforce that all dependencies are enabled
234
Colin Cross69452e12023-11-15 11:20:53 -0800235}
236
Yu Liudd9ccb42024-10-07 17:07:44 +0000237func getWrappedModule(module blueprint.Module) blueprint.Module {
238 if mp, isProxy := module.(ModuleProxy); isProxy {
239 return mp.module
240 }
241 return module
242}
243
244func (b *baseModuleContext) EqualModules(m1, m2 Module) bool {
245 return b.bp.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
246}
247
Colin Cross69452e12023-11-15 11:20:53 -0800248func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
Yu Liudd9ccb42024-10-07 17:07:44 +0000249 return b.bp.OtherModuleName(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800250}
251func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
252func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
253 b.bp.OtherModuleErrorf(m, fmt, args...)
254}
255func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
Yu Liudd9ccb42024-10-07 17:07:44 +0000256 return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800257}
258func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
259func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
260 return b.bp.OtherModuleDependencyVariantExists(variations, name)
261}
262func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
263 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
264}
265func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
266 return b.bp.OtherModuleReverseDependencyVariantExists(name)
267}
268func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
269 return b.bp.OtherModuleType(m)
270}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800271
272func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800273 return b.bp.OtherModuleProvider(m, provider)
274}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800275
Colin Cross3c0a83d2023-12-12 14:13:26 -0800276func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800277 return b.bp.Provider(provider)
278}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800279
Colin Cross24c1cbe2023-12-21 23:42:56 +0000280func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
Colin Cross69452e12023-11-15 11:20:53 -0800281 b.bp.SetProvider(provider, value)
282}
283
284func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
285 return b.bp.GetDirectDepWithTag(name, tag)
286}
287
288func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
289 return b.bp
290}
291
Colin Cross69452e12023-11-15 11:20:53 -0800292func (b *baseModuleContext) AddMissingDependencies(deps []string) {
293 if deps != nil {
294 missingDeps := &b.Module().base().commonProperties.MissingDeps
295 *missingDeps = append(*missingDeps, deps...)
296 *missingDeps = FirstUniqueStrings(*missingDeps)
297 }
298}
299
300func (b *baseModuleContext) checkedMissingDeps() bool {
301 return b.Module().base().commonProperties.CheckedMissingDeps
302}
303
304func (b *baseModuleContext) getMissingDependencies() []string {
305 checked := &b.Module().base().commonProperties.CheckedMissingDeps
306 *checked = true
307 var missingDeps []string
308 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
309 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
310 missingDeps = FirstUniqueStrings(missingDeps)
311 return missingDeps
312}
313
314type AllowDisabledModuleDependency interface {
315 blueprint.DependencyTag
316 AllowDisabledModuleDependency(target Module) bool
317}
318
Jiyong Park8bcf3c62024-03-18 18:37:10 +0900319type AlwaysAllowDisabledModuleDependencyTag struct{}
320
321func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
322 return true
323}
324
Colin Cross648daea2024-09-12 14:35:29 -0700325func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
Colin Cross69452e12023-11-15 11:20:53 -0800326 aModule, _ := module.(Module)
327
328 if !strict {
329 return aModule
330 }
331
332 if aModule == nil {
Colin Cross648daea2024-09-12 14:35:29 -0700333 panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag))
Colin Cross69452e12023-11-15 11:20:53 -0800334 }
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
Colin Cross648daea2024-09-12 14:35:29 -0700356 b.VisitDirectDeps(func(module Module) {
357 if module.base().BaseModuleName() == name {
Colin Cross69452e12023-11-15 11:20:53 -0800358 returnedTag := b.bp.OtherModuleDependencyTag(module)
359 if tag == nil || returnedTag == tag {
360 deps = append(deps, dep{module, returnedTag})
361 }
362 }
363 })
364 return deps
365}
366
367func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
368 deps := b.getDirectDepsInternal(name, tag)
369 if len(deps) == 1 {
370 return deps[0].mod, deps[0].tag
371 } else if len(deps) >= 2 {
372 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
373 name, b.ModuleName()))
374 } else {
375 return nil, nil
376 }
377}
378
379func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
380 foundDeps := b.getDirectDepsInternal(name, nil)
381 deps := map[blueprint.Module]bool{}
382 for _, dep := range foundDeps {
383 deps[dep.mod] = true
384 }
385 if len(deps) == 1 {
386 return foundDeps[0].mod, foundDeps[0].tag
387 } else if len(deps) >= 2 {
388 // this could happen if two dependencies have the same name in different namespaces
389 // TODO(b/186554727): this should not occur if namespaces are handled within
390 // getDirectDepsInternal.
391 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
392 name, b.ModuleName()))
393 } else {
394 return nil, nil
395 }
396}
397
398func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
399 var deps []Module
Colin Cross648daea2024-09-12 14:35:29 -0700400 b.VisitDirectDeps(func(module Module) {
401 if b.bp.OtherModuleDependencyTag(module) == tag {
402 deps = append(deps, module)
Colin Cross69452e12023-11-15 11:20:53 -0800403 }
404 })
405 return deps
406}
407
408// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
409// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
410// first DependencyTag.
411func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
412 return b.getDirectDepFirstTag(name)
413}
414
Colin Cross69452e12023-11-15 11:20:53 -0800415func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
416 b.bp.VisitDirectDeps(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700417 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800418 visit(aModule)
419 }
420 })
421}
422
Colin Cross648daea2024-09-12 14:35:29 -0700423func (b *baseModuleContext) VisitDirectDepsAllowDisabled(visit func(Module)) {
424 b.bp.VisitDirectDeps(func(module blueprint.Module) {
425 visit(module.(Module))
426 })
427}
428
Yu Liudd9ccb42024-10-07 17:07:44 +0000429func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy Module)) {
430 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
431 visit(ModuleProxy{
432 module: module,
433 })
434 })
435}
436
Colin Cross69452e12023-11-15 11:20:53 -0800437func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
438 b.bp.VisitDirectDeps(func(module blueprint.Module) {
439 if b.bp.OtherModuleDependencyTag(module) == tag {
Colin Cross648daea2024-09-12 14:35:29 -0700440 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800441 visit(aModule)
442 }
443 }
444 })
445}
446
447func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
448 b.bp.VisitDirectDepsIf(
449 // pred
450 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700451 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800452 return pred(aModule)
453 } else {
454 return false
455 }
456 },
457 // visit
458 func(module blueprint.Module) {
459 visit(module.(Module))
460 })
461}
462
463func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
464 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700465 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800466 visit(aModule)
467 }
468 })
469}
470
471func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
472 b.bp.VisitDepsDepthFirstIf(
473 // pred
474 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700475 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800476 return pred(aModule)
477 } else {
478 return false
479 }
480 },
481 // visit
482 func(module blueprint.Module) {
483 visit(module.(Module))
484 })
485}
486
Colin Cross69452e12023-11-15 11:20:53 -0800487func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
488 b.walkPath = []Module{b.Module()}
489 b.tagPath = []blueprint.DependencyTag{}
490 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
491 childAndroidModule, _ := child.(Module)
492 parentAndroidModule, _ := parent.(Module)
493 if childAndroidModule != nil && parentAndroidModule != nil {
494 // record walkPath before visit
495 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
496 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
497 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
498 }
499 b.walkPath = append(b.walkPath, childAndroidModule)
500 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
501 return visit(childAndroidModule, parentAndroidModule)
502 } else {
503 return false
504 }
505 })
506}
507
Yu Liudd9ccb42024-10-07 17:07:44 +0000508func (b *baseModuleContext) WalkDepsProxy(visit func(Module, Module) bool) {
509 b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
510 b.tagPath = []blueprint.DependencyTag{}
511 b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
512 childAndroidModule := ModuleProxy{child}
513 parentAndroidModule := ModuleProxy{parent}
514 // record walkPath before visit
515 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
516 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
517 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
518 }
519 b.walkPath = append(b.walkPath, childAndroidModule)
520 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
521 return visit(childAndroidModule, parentAndroidModule)
522 })
523}
524
Colin Cross69452e12023-11-15 11:20:53 -0800525func (b *baseModuleContext) GetWalkPath() []Module {
526 return b.walkPath
527}
528
529func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
530 return b.tagPath
531}
532
533func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
534 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
535 visit(module.(Module))
536 })
537}
538
539func (b *baseModuleContext) PrimaryModule() Module {
540 return b.bp.PrimaryModule().(Module)
541}
542
543func (b *baseModuleContext) FinalModule() Module {
544 return b.bp.FinalModule().(Module)
545}
546
547// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
548func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
549 if tag == licenseKindTag {
550 return true
551 } else if tag == licensesTag {
552 return true
Jihoon Kanga3a05462024-04-05 00:36:44 +0000553 } else if tag == AcDepTag {
Colin Cross69452e12023-11-15 11:20:53 -0800554 return true
555 }
556 return false
557}
558
559// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
560// a dependency tag.
561var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
562
563// PrettyPrintTag returns string representation of the tag, but prefers
564// custom String() method if available.
565func PrettyPrintTag(tag blueprint.DependencyTag) string {
566 // Use tag's custom String() method if available.
567 if stringer, ok := tag.(fmt.Stringer); ok {
568 return stringer.String()
569 }
570
571 // Otherwise, get a default string representation of the tag's struct.
572 tagString := fmt.Sprintf("%T: %+v", tag, tag)
573
574 // Remove the boilerplate from BaseDependencyTag as it adds no value.
575 tagString = tagCleaner.ReplaceAllString(tagString, "")
576 return tagString
577}
578
579func (b *baseModuleContext) GetPathString(skipFirst bool) string {
580 sb := strings.Builder{}
581 tagPath := b.GetTagPath()
582 walkPath := b.GetWalkPath()
583 if !skipFirst {
584 sb.WriteString(walkPath[0].String())
585 }
586 for i, m := range walkPath[1:] {
587 sb.WriteString("\n")
588 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
589 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
590 }
591 return sb.String()
592}
Cole Faustbdd8aee2024-03-14 14:33:02 -0700593
Cole Faustfdbf5d42024-04-10 15:01:23 -0700594func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
595 return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property)
Cole Faustbdd8aee2024-03-14 14:33:02 -0700596}