blob: 5cb9e71cf5f71be6891a4efdad07f0b142b8f748 [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"
Colin Crossb614cd42024-10-11 12:52:21 -070020 "slices"
Colin Cross69452e12023-11-15 11:20:53 -080021 "strings"
Cole Faustbdd8aee2024-03-14 14:33:02 -070022
23 "github.com/google/blueprint"
Cole Faustfdbf5d42024-04-10 15:01:23 -070024 "github.com/google/blueprint/proptools"
Colin Cross69452e12023-11-15 11:20:53 -080025)
26
27// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
28// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module
29// instead of a blueprint.Module, plus some extra methods that return Android-specific information
30// about the current module.
31type BaseModuleContext interface {
Colin Cross1d3d9f12024-01-18 14:30:22 -080032 ArchModuleContext
Colin Cross69452e12023-11-15 11:20:53 -080033 EarlyModuleContext
34
35 blueprintBaseModuleContext() blueprint.BaseModuleContext
36
37 // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
38 // It is intended for use inside the visit functions of Visit* and WalkDeps.
39 OtherModuleName(m blueprint.Module) string
40
41 // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
42 // It is intended for use inside the visit functions of Visit* and WalkDeps.
43 OtherModuleDir(m blueprint.Module) string
44
45 // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
46 // It is intended for use inside the visit functions of Visit* and WalkDeps.
47 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
48
49 // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
50 // on the module. When called inside a Visit* method with current module being visited, and there are multiple
51 // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
52 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
53
Jihoon Kangf50d2e62025-02-19 00:47:23 +000054 // OtherModuleSubDir returns the string representing the variations of a module.
55 OtherModuleSubDir(m blueprint.Module) string
56
Colin Cross69452e12023-11-15 11:20:53 -080057 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
58 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
59 OtherModuleExists(name string) bool
60
61 // OtherModuleDependencyVariantExists returns true if a module with the
62 // specified name and variant exists. The variant must match the given
63 // variations. It must also match all the non-local variations of the current
64 // module. In other words, it checks for the module that AddVariationDependencies
65 // would add a dependency on with the same arguments.
66 OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
67
68 // OtherModuleFarDependencyVariantExists returns true if a module with the
69 // specified name and variant exists. The variant must match the given
70 // variations, but not the non-local variations of the current module. In
71 // other words, it checks for the module that AddFarVariationDependencies
72 // would add a dependency on with the same arguments.
73 OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
74
75 // OtherModuleReverseDependencyVariantExists returns true if a module with the
76 // specified name exists with the same variations as the current module. In
77 // other words, it checks for the module that AddReverseDependency would add a
78 // dependency on with the same argument.
79 OtherModuleReverseDependencyVariantExists(name string) bool
80
81 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
82 // It is intended for use inside the visit functions of Visit* and WalkDeps.
83 OtherModuleType(m blueprint.Module) string
84
Colin Cross24c1cbe2023-12-21 23:42:56 +000085 // otherModuleProvider returns the value for a provider for the given module. If the value is
86 // not set it returns nil and false. The value returned may be a deep copy of the value originally
87 // passed to SetProvider.
88 //
89 // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080090 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080091
Yu Liu0a37d422025-02-13 02:05:00 +000092 // OtherModuleHasProvider returns true if the module has the given provider set. This
93 // can avoid copying the provider if the caller only cares about the existence of
94 // the provider.
95 OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool
96
Jihoon Kang2a7bf752024-11-01 21:21:25 +000097 // OtherModuleIsAutoGenerated returns true if the module is auto generated by another module
98 // instead of being defined in Android.bp file.
99 OtherModuleIsAutoGenerated(m blueprint.Module) bool
100
Colin Cross69452e12023-11-15 11:20:53 -0800101 // Provider returns the value for a provider for the current module. If the value is
Colin Cross24c1cbe2023-12-21 23:42:56 +0000102 // not set it returns nil and false. It panics if called before the appropriate
Colin Cross69452e12023-11-15 11:20:53 -0800103 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
104 // copy of the value originally passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000105 //
106 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -0800107 provider(provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -0800108
Colin Cross24c1cbe2023-12-21 23:42:56 +0000109 // setProvider sets the value for a provider for the current module. It panics if not called
Colin Cross69452e12023-11-15 11:20:53 -0800110 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
111 // is not of the appropriate type, or if the value has already been set. The value should not
112 // be modified after being passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000113 //
114 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
115 setProvider(provider blueprint.AnyProviderKey, value any)
Colin Cross69452e12023-11-15 11:20:53 -0800116
117 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
118
Yu Liuf432c2e2024-12-17 00:09:15 +0000119 GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy
120
Colin Cross69452e12023-11-15 11:20:53 -0800121 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
122 // none exists. It panics if the dependency does not have the specified tag. It skips any
123 // dependencies that are not an android.Module.
Yu Liud3228ac2024-11-08 23:11:47 +0000124 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module
Colin Cross69452e12023-11-15 11:20:53 -0800125
Yu Liu3ae96652024-12-17 22:27:38 +0000126 GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy
127
Colin Cross648daea2024-09-12 14:35:29 -0700128 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
129 // direct dependencies on the same module visit will be called multiple times on that module
130 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
131 // dependencies are disabled.
132 //
133 // The Module passed to the visit function should not be retained outside of the visit
134 // function, it may be invalidated by future mutators.
135 VisitDirectDeps(visit func(Module))
136
Yu Liud3228ac2024-11-08 23:11:47 +0000137 // VisitDirectDepsProxy calls visit for each direct dependency. If there are multiple
Colin Cross69452e12023-11-15 11:20:53 -0800138 // direct dependencies on the same module visit will be called multiple times on that module
Yu Liud3228ac2024-11-08 23:11:47 +0000139 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
140 // dependencies are disabled.
Colin Cross69452e12023-11-15 11:20:53 -0800141 //
Yu Liud3228ac2024-11-08 23:11:47 +0000142 // The ModuleProxy passed to the visit function should not be retained outside of the visit
Colin Cross69452e12023-11-15 11:20:53 -0800143 // function, it may be invalidated by future mutators.
Yu Liud3228ac2024-11-08 23:11:47 +0000144 VisitDirectDepsProxy(visit func(proxy ModuleProxy))
Colin Cross69452e12023-11-15 11:20:53 -0800145
Yu Liudd9ccb42024-10-07 17:07:44 +0000146 // VisitDirectDepsProxyAllowDisabled calls visit for each direct dependency. If there are
147 // multiple direct dependencies on the same module visit will be called multiple times on
148 // that module and OtherModuleDependencyTag will return a different tag for each.
149 //
Yu Liud2a95952024-10-10 00:15:26 +0000150 // The ModuleProxy passed to the visit function should not be retained outside of the visit function, it may be
Yu Liudd9ccb42024-10-07 17:07:44 +0000151 // invalidated by future mutators.
Yu Liud2a95952024-10-10 00:15:26 +0000152 VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy))
Yu Liudd9ccb42024-10-07 17:07:44 +0000153
Colin Cross69452e12023-11-15 11:20:53 -0800154 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
155
Yu Liud2a95952024-10-10 00:15:26 +0000156 VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy))
157
Colin Cross69452e12023-11-15 11:20:53 -0800158 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
159 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
160 // OtherModuleDependencyTag will return a different tag for each. It skips any
161 // dependencies that are not an android.Module.
162 //
163 // The Module passed to the visit function should not be retained outside of the visit function, it may be
164 // invalidated by future mutators.
165 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
166 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
167 VisitDepsDepthFirst(visit func(Module))
168 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
169 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
170
171 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
172 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
173 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
174 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
175 // any dependencies that are not an android.Module.
176 //
177 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
178 // invalidated by future mutators.
179 WalkDeps(visit func(child, parent Module) bool)
180
Yu Liudd9ccb42024-10-07 17:07:44 +0000181 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
182 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
183 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
184 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
185 // any dependencies that are not an android.Module.
186 //
187 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
188 // invalidated by future mutators.
Yu Liud2a95952024-10-10 00:15:26 +0000189 WalkDepsProxy(visit func(child, parent ModuleProxy) bool)
Yu Liudd9ccb42024-10-07 17:07:44 +0000190
Colin Cross69452e12023-11-15 11:20:53 -0800191 // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
192 // and returns a top-down dependency path from a start module to current child module.
193 GetWalkPath() []Module
194
195 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
196 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
197 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
198 // only done once for all variants of a module.
199 PrimaryModule() Module
200
201 // FinalModule returns the last variant of the current module. Variants of a module are always visited in
202 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
203 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
204 // singleton actions that are only done once for all variants of a module.
205 FinalModule() Module
206
Yu Liu88ea9ff2024-11-07 19:19:42 +0000207 // IsFinalModule returns if the current module is the last variant. Variants of a module are always visited in
208 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
209 // variants using VisitAllModuleVariants if the current module is the last one. This can be used to perform
210 // singleton actions that are only done once for all variants of a module.
211 IsFinalModule(module Module) bool
212
Colin Cross69452e12023-11-15 11:20:53 -0800213 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
214 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
Yu Liu88ea9ff2024-11-07 19:19:42 +0000215 // from all variants if the current module is the last one. Otherwise, care must be taken to not access any
Colin Cross69452e12023-11-15 11:20:53 -0800216 // data modified by the current mutator.
217 VisitAllModuleVariants(visit func(Module))
218
Yu Liub5275322024-11-13 18:40:43 +0000219 // VisitAllModuleVariantProxies calls visit for each variant of the current module. Variants of a module are always
220 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
221 // from all variants if the current module is the last one. Otherwise, care must be taken to not access any
222 // data modified by the current mutator.
223 VisitAllModuleVariantProxies(visit func(proxy ModuleProxy))
224
Colin Cross69452e12023-11-15 11:20:53 -0800225 // GetTagPath is supposed to be called in visit function passed in WalkDeps()
226 // and returns a top-down dependency tags path from a start module to current child module.
227 // It has one less entry than GetWalkPath() as it contains the dependency tags that
228 // exist between each adjacent pair of modules in the GetWalkPath().
229 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
230 GetTagPath() []blueprint.DependencyTag
231
232 // GetPathString is supposed to be called in visit function passed in WalkDeps()
233 // and returns a multi-line string showing the modules and dependency tags
234 // among them along the top-down dependency path from a start module to current child module.
235 // skipFirst when set to true, the output doesn't include the start module,
236 // which is already printed when this function is used along with ModuleErrorf().
237 GetPathString(skipFirst bool) string
238
239 AddMissingDependencies(missingDeps []string)
240
241 // getMissingDependencies returns the list of missing dependencies.
242 // Calling this function prevents adding new dependencies.
243 getMissingDependencies() []string
Cole Faustbdd8aee2024-03-14 14:33:02 -0700244
245 // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
246 // can be used to evaluate the final value of Configurable properties.
Cole Faustfdbf5d42024-04-10 15:01:23 -0700247 EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue
Colin Cross69452e12023-11-15 11:20:53 -0800248}
249
250type baseModuleContext struct {
251 bp blueprint.BaseModuleContext
252 earlyModuleContext
Colin Cross1d3d9f12024-01-18 14:30:22 -0800253 archModuleContext
Colin Cross69452e12023-11-15 11:20:53 -0800254
255 walkPath []Module
256 tagPath []blueprint.DependencyTag
257
258 strictVisitDeps bool // If true, enforce that all dependencies are enabled
259
Colin Cross69452e12023-11-15 11:20:53 -0800260}
261
Yu Liudd9ccb42024-10-07 17:07:44 +0000262func getWrappedModule(module blueprint.Module) blueprint.Module {
Cole Faust19eb09d2025-01-14 13:27:00 -0800263 if mp, isProxy := module.(*ModuleProxy); isProxy {
264 return mp.module
265 }
Yu Liudd9ccb42024-10-07 17:07:44 +0000266 if mp, isProxy := module.(ModuleProxy); isProxy {
267 return mp.module
268 }
269 return module
270}
271
Yu Liue472c1d2025-02-26 20:13:04 +0000272func EqualModules(m1, m2 Module) bool {
273 return blueprint.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
Yu Liudd9ccb42024-10-07 17:07:44 +0000274}
275
Colin Cross69452e12023-11-15 11:20:53 -0800276func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
Yu Liudd9ccb42024-10-07 17:07:44 +0000277 return b.bp.OtherModuleName(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800278}
Yu Liud3228ac2024-11-08 23:11:47 +0000279func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string {
280 return b.bp.OtherModuleDir(getWrappedModule(m))
281}
Colin Cross69452e12023-11-15 11:20:53 -0800282func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
Yu Liuac483e02024-11-11 22:29:30 +0000283 b.bp.OtherModuleErrorf(getWrappedModule(m), fmt, args...)
Colin Cross69452e12023-11-15 11:20:53 -0800284}
285func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
Yu Liudd9ccb42024-10-07 17:07:44 +0000286 return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800287}
Jihoon Kangf50d2e62025-02-19 00:47:23 +0000288func (b *baseModuleContext) OtherModuleSubDir(m blueprint.Module) string {
289 return b.bp.OtherModuleSubDir(getWrappedModule(m))
290}
Colin Cross69452e12023-11-15 11:20:53 -0800291func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
292func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
293 return b.bp.OtherModuleDependencyVariantExists(variations, name)
294}
295func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
296 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
297}
298func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
299 return b.bp.OtherModuleReverseDependencyVariantExists(name)
300}
301func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
Yu Liub1bfa9d2024-12-05 18:57:51 +0000302 return b.bp.OtherModuleType(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800303}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800304
305func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Cole Faust19eb09d2025-01-14 13:27:00 -0800306 return b.bp.OtherModuleProvider(getWrappedModule(m), provider)
Colin Cross69452e12023-11-15 11:20:53 -0800307}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800308
Yu Liu0a37d422025-02-13 02:05:00 +0000309func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool {
310 return b.bp.OtherModuleHasProvider(getWrappedModule(m), provider)
311}
312
Jihoon Kang2a7bf752024-11-01 21:21:25 +0000313func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool {
314 return b.bp.OtherModuleIsAutoGenerated(m)
315}
316
Colin Cross3c0a83d2023-12-12 14:13:26 -0800317func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800318 return b.bp.Provider(provider)
319}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800320
Colin Cross24c1cbe2023-12-21 23:42:56 +0000321func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
Colin Cross69452e12023-11-15 11:20:53 -0800322 b.bp.SetProvider(provider, value)
323}
324
Yu Liud3228ac2024-11-08 23:11:47 +0000325func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module {
326 if module := b.bp.GetDirectDepWithTag(name, tag); module != nil {
327 return module.(Module)
328 }
329 return nil
Colin Cross69452e12023-11-15 11:20:53 -0800330}
331
Yu Liu3ae96652024-12-17 22:27:38 +0000332func (b *baseModuleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy {
333 if module := b.bp.GetDirectDepProxyWithTag(name, tag); module != nil {
334 return &ModuleProxy{*module}
335 }
336 return nil
337}
338
Colin Cross69452e12023-11-15 11:20:53 -0800339func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
340 return b.bp
341}
342
Colin Cross69452e12023-11-15 11:20:53 -0800343func (b *baseModuleContext) AddMissingDependencies(deps []string) {
344 if deps != nil {
345 missingDeps := &b.Module().base().commonProperties.MissingDeps
346 *missingDeps = append(*missingDeps, deps...)
347 *missingDeps = FirstUniqueStrings(*missingDeps)
348 }
349}
350
351func (b *baseModuleContext) checkedMissingDeps() bool {
352 return b.Module().base().commonProperties.CheckedMissingDeps
353}
354
355func (b *baseModuleContext) getMissingDependencies() []string {
356 checked := &b.Module().base().commonProperties.CheckedMissingDeps
357 *checked = true
358 var missingDeps []string
359 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
360 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
361 missingDeps = FirstUniqueStrings(missingDeps)
362 return missingDeps
363}
364
365type AllowDisabledModuleDependency interface {
366 blueprint.DependencyTag
367 AllowDisabledModuleDependency(target Module) bool
Yu Liud2a95952024-10-10 00:15:26 +0000368 AllowDisabledModuleDependencyProxy(ctx OtherModuleProviderContext, target ModuleProxy) bool
Colin Cross69452e12023-11-15 11:20:53 -0800369}
370
Jiyong Park8bcf3c62024-03-18 18:37:10 +0900371type AlwaysAllowDisabledModuleDependencyTag struct{}
372
373func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
374 return true
375}
376
Yu Liud2a95952024-10-10 00:15:26 +0000377func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependencyProxy(OtherModuleProviderContext, ModuleProxy) bool {
378 return true
379}
380
Colin Cross648daea2024-09-12 14:35:29 -0700381func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
Colin Cross69452e12023-11-15 11:20:53 -0800382 aModule, _ := module.(Module)
383
384 if !strict {
385 return aModule
386 }
387
388 if aModule == nil {
Colin Cross648daea2024-09-12 14:35:29 -0700389 panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag))
Colin Cross69452e12023-11-15 11:20:53 -0800390 }
391
Cole Fausta963b942024-04-11 17:43:00 -0700392 if !aModule.Enabled(b) {
Colin Cross69452e12023-11-15 11:20:53 -0800393 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
394 if b.Config().AllowMissingDependencies() {
395 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
396 } else {
397 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
398 }
399 }
400 return nil
401 }
402 return aModule
403}
404
Yu Liud2a95952024-10-10 00:15:26 +0000405func (b *baseModuleContext) validateAndroidModuleProxy(
406 module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) *ModuleProxy {
407 aModule := ModuleProxy{module: module}
408
409 if !strict {
410 return &aModule
411 }
412
Yu Liuf22120f2025-03-13 18:36:35 +0000413 if !OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).Enabled {
Yu Liud2a95952024-10-10 00:15:26 +0000414 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) {
415 if b.Config().AllowMissingDependencies() {
416 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
417 } else {
418 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
419 }
420 }
421 return nil
422 }
423
424 return &aModule
425}
426
Yu Liu3ae96652024-12-17 22:27:38 +0000427func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []Module {
428 var deps []Module
Colin Cross648daea2024-09-12 14:35:29 -0700429 b.VisitDirectDeps(func(module Module) {
430 if module.base().BaseModuleName() == name {
Colin Cross69452e12023-11-15 11:20:53 -0800431 returnedTag := b.bp.OtherModuleDependencyTag(module)
432 if tag == nil || returnedTag == tag {
Yu Liu3ae96652024-12-17 22:27:38 +0000433 deps = append(deps, module)
Colin Cross69452e12023-11-15 11:20:53 -0800434 }
435 }
436 })
437 return deps
438}
439
Yu Liu3ae96652024-12-17 22:27:38 +0000440func (b *baseModuleContext) getDirectDepsProxyInternal(name string, tag blueprint.DependencyTag) []ModuleProxy {
441 var deps []ModuleProxy
442 b.VisitDirectDepsProxy(func(module ModuleProxy) {
Yu Liuf22120f2025-03-13 18:36:35 +0000443 if OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).BaseModuleName == name {
Yu Liu3ae96652024-12-17 22:27:38 +0000444 returnedTag := b.OtherModuleDependencyTag(module)
445 if tag == nil || returnedTag == tag {
446 deps = append(deps, module)
447 }
448 }
449 })
450 return deps
Colin Cross69452e12023-11-15 11:20:53 -0800451}
452
Colin Cross69452e12023-11-15 11:20:53 -0800453func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
454 var deps []Module
Colin Cross648daea2024-09-12 14:35:29 -0700455 b.VisitDirectDeps(func(module Module) {
456 if b.bp.OtherModuleDependencyTag(module) == tag {
457 deps = append(deps, module)
Colin Cross69452e12023-11-15 11:20:53 -0800458 }
459 })
460 return deps
461}
462
Yu Liuf432c2e2024-12-17 00:09:15 +0000463func (b *baseModuleContext) GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy {
464 var deps []ModuleProxy
465 b.VisitDirectDepsProxy(func(module ModuleProxy) {
466 if b.OtherModuleDependencyTag(module) == tag {
467 deps = append(deps, module)
468 }
469 })
470 return deps
471}
472
Colin Cross69452e12023-11-15 11:20:53 -0800473func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
474 b.bp.VisitDirectDeps(func(module blueprint.Module) {
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 visit(aModule)
477 }
478 })
479}
480
Yu Liud3228ac2024-11-08 23:11:47 +0000481func (b *baseModuleContext) VisitDirectDepsProxy(visit func(ModuleProxy)) {
482 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
483 if aModule := b.validateAndroidModuleProxy(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
484 visit(*aModule)
485 }
Colin Cross648daea2024-09-12 14:35:29 -0700486 })
487}
488
Yu Liud2a95952024-10-10 00:15:26 +0000489func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) {
Yu Liud3228ac2024-11-08 23:11:47 +0000490 b.bp.VisitDirectDepsProxy(visitProxyAdaptor(visit))
Yu Liudd9ccb42024-10-07 17:07:44 +0000491}
492
Colin Cross69452e12023-11-15 11:20:53 -0800493func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
494 b.bp.VisitDirectDeps(func(module blueprint.Module) {
495 if b.bp.OtherModuleDependencyTag(module) == tag {
Yu Liud2a95952024-10-10 00:15:26 +0000496 if aModule := b.validateAndroidModule(module, tag, b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800497 visit(aModule)
498 }
499 }
500 })
501}
502
Yu Liud2a95952024-10-10 00:15:26 +0000503func (b *baseModuleContext) VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) {
504 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
505 if b.bp.OtherModuleDependencyTag(module) == tag {
506 if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); aModule != nil {
507 visit(*aModule)
508 }
509 }
510 })
511}
512
Colin Cross69452e12023-11-15 11:20:53 -0800513func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
514 b.bp.VisitDirectDepsIf(
515 // pred
516 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700517 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800518 return pred(aModule)
519 } else {
520 return false
521 }
522 },
523 // visit
524 func(module blueprint.Module) {
525 visit(module.(Module))
526 })
527}
528
529func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
530 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700531 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800532 visit(aModule)
533 }
534 })
535}
536
537func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
538 b.bp.VisitDepsDepthFirstIf(
539 // pred
540 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700541 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800542 return pred(aModule)
543 } else {
544 return false
545 }
546 },
547 // visit
548 func(module blueprint.Module) {
549 visit(module.(Module))
550 })
551}
552
Colin Cross69452e12023-11-15 11:20:53 -0800553func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
554 b.walkPath = []Module{b.Module()}
555 b.tagPath = []blueprint.DependencyTag{}
556 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
557 childAndroidModule, _ := child.(Module)
558 parentAndroidModule, _ := parent.(Module)
559 if childAndroidModule != nil && parentAndroidModule != nil {
560 // record walkPath before visit
561 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
562 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
563 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
564 }
565 b.walkPath = append(b.walkPath, childAndroidModule)
566 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
567 return visit(childAndroidModule, parentAndroidModule)
568 } else {
569 return false
570 }
571 })
572}
573
Yu Liud2a95952024-10-10 00:15:26 +0000574func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) {
Yu Liudd9ccb42024-10-07 17:07:44 +0000575 b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
576 b.tagPath = []blueprint.DependencyTag{}
577 b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
578 childAndroidModule := ModuleProxy{child}
579 parentAndroidModule := ModuleProxy{parent}
580 // record walkPath before visit
581 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
582 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
583 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
584 }
585 b.walkPath = append(b.walkPath, childAndroidModule)
586 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
587 return visit(childAndroidModule, parentAndroidModule)
588 })
589}
590
Colin Cross69452e12023-11-15 11:20:53 -0800591func (b *baseModuleContext) GetWalkPath() []Module {
Colin Crossb614cd42024-10-11 12:52:21 -0700592 return slices.Clone(b.walkPath)
Colin Cross69452e12023-11-15 11:20:53 -0800593}
594
595func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
596 return b.tagPath
597}
598
599func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
600 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
601 visit(module.(Module))
602 })
603}
604
Yu Liub5275322024-11-13 18:40:43 +0000605func (b *baseModuleContext) VisitAllModuleVariantProxies(visit func(ModuleProxy)) {
606 b.bp.VisitAllModuleVariantProxies(visitProxyAdaptor(visit))
607}
608
Colin Cross69452e12023-11-15 11:20:53 -0800609func (b *baseModuleContext) PrimaryModule() Module {
610 return b.bp.PrimaryModule().(Module)
611}
612
613func (b *baseModuleContext) FinalModule() Module {
614 return b.bp.FinalModule().(Module)
615}
616
Yu Liu88ea9ff2024-11-07 19:19:42 +0000617func (b *baseModuleContext) IsFinalModule(module Module) bool {
618 return b.bp.IsFinalModule(module)
619}
620
Colin Cross69452e12023-11-15 11:20:53 -0800621// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
622func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
623 if tag == licenseKindTag {
624 return true
625 } else if tag == licensesTag {
626 return true
Jihoon Kanga3a05462024-04-05 00:36:44 +0000627 } else if tag == AcDepTag {
Colin Cross69452e12023-11-15 11:20:53 -0800628 return true
629 }
630 return false
631}
632
633// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
634// a dependency tag.
635var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
636
637// PrettyPrintTag returns string representation of the tag, but prefers
638// custom String() method if available.
639func PrettyPrintTag(tag blueprint.DependencyTag) string {
640 // Use tag's custom String() method if available.
641 if stringer, ok := tag.(fmt.Stringer); ok {
642 return stringer.String()
643 }
644
645 // Otherwise, get a default string representation of the tag's struct.
646 tagString := fmt.Sprintf("%T: %+v", tag, tag)
647
648 // Remove the boilerplate from BaseDependencyTag as it adds no value.
649 tagString = tagCleaner.ReplaceAllString(tagString, "")
650 return tagString
651}
652
653func (b *baseModuleContext) GetPathString(skipFirst bool) string {
654 sb := strings.Builder{}
655 tagPath := b.GetTagPath()
656 walkPath := b.GetWalkPath()
657 if !skipFirst {
658 sb.WriteString(walkPath[0].String())
659 }
660 for i, m := range walkPath[1:] {
661 sb.WriteString("\n")
662 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
663 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
664 }
665 return sb.String()
666}
Cole Faustbdd8aee2024-03-14 14:33:02 -0700667
Cole Faustfdbf5d42024-04-10 15:01:23 -0700668func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
669 return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property)
Cole Faustbdd8aee2024-03-14 14:33:02 -0700670}