blob: cdee96f89168a4900d1a13a9ba5f59e9c2787c5e [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
Yu Liudd9ccb42024-10-07 17:07:44 +000037 EqualModules(m1, m2 Module) bool
38
Colin Cross69452e12023-11-15 11:20:53 -080039 // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
40 // It is intended for use inside the visit functions of Visit* and WalkDeps.
41 OtherModuleName(m blueprint.Module) string
42
43 // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
44 // It is intended for use inside the visit functions of Visit* and WalkDeps.
45 OtherModuleDir(m blueprint.Module) string
46
47 // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
48 // It is intended for use inside the visit functions of Visit* and WalkDeps.
49 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
50
51 // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
52 // on the module. When called inside a Visit* method with current module being visited, and there are multiple
53 // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
54 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
55
56 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
57 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
58 OtherModuleExists(name string) bool
59
60 // OtherModuleDependencyVariantExists returns true if a module with the
61 // specified name and variant exists. The variant must match the given
62 // variations. It must also match all the non-local variations of the current
63 // module. In other words, it checks for the module that AddVariationDependencies
64 // would add a dependency on with the same arguments.
65 OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
66
67 // OtherModuleFarDependencyVariantExists returns true if a module with the
68 // specified name and variant exists. The variant must match the given
69 // variations, but not the non-local variations of the current module. In
70 // other words, it checks for the module that AddFarVariationDependencies
71 // would add a dependency on with the same arguments.
72 OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
73
74 // OtherModuleReverseDependencyVariantExists returns true if a module with the
75 // specified name exists with the same variations as the current module. In
76 // other words, it checks for the module that AddReverseDependency would add a
77 // dependency on with the same argument.
78 OtherModuleReverseDependencyVariantExists(name string) bool
79
80 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
81 // It is intended for use inside the visit functions of Visit* and WalkDeps.
82 OtherModuleType(m blueprint.Module) string
83
Colin Cross24c1cbe2023-12-21 23:42:56 +000084 // otherModuleProvider returns the value for a provider for the given module. If the value is
85 // not set it returns nil and false. The value returned may be a deep copy of the value originally
86 // passed to SetProvider.
87 //
88 // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080089 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080090
Yu Liu0a37d422025-02-13 02:05:00 +000091 // OtherModuleHasProvider returns true if the module has the given provider set. This
92 // can avoid copying the provider if the caller only cares about the existence of
93 // the provider.
94 OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool
95
Jihoon Kang2a7bf752024-11-01 21:21:25 +000096 // OtherModuleIsAutoGenerated returns true if the module is auto generated by another module
97 // instead of being defined in Android.bp file.
98 OtherModuleIsAutoGenerated(m blueprint.Module) bool
99
Colin Cross69452e12023-11-15 11:20:53 -0800100 // Provider returns the value for a provider for the current module. If the value is
Colin Cross24c1cbe2023-12-21 23:42:56 +0000101 // not set it returns nil and false. It panics if called before the appropriate
Colin Cross69452e12023-11-15 11:20:53 -0800102 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
103 // copy of the value originally passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000104 //
105 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -0800106 provider(provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -0800107
Colin Cross24c1cbe2023-12-21 23:42:56 +0000108 // setProvider sets the value for a provider for the current module. It panics if not called
Colin Cross69452e12023-11-15 11:20:53 -0800109 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
110 // is not of the appropriate type, or if the value has already been set. The value should not
111 // be modified after being passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000112 //
113 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
114 setProvider(provider blueprint.AnyProviderKey, value any)
Colin Cross69452e12023-11-15 11:20:53 -0800115
116 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
117
Yu Liuf432c2e2024-12-17 00:09:15 +0000118 GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy
119
Colin Cross69452e12023-11-15 11:20:53 -0800120 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
121 // none exists. It panics if the dependency does not have the specified tag. It skips any
122 // dependencies that are not an android.Module.
Yu Liud3228ac2024-11-08 23:11:47 +0000123 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module
Colin Cross69452e12023-11-15 11:20:53 -0800124
Yu Liu3ae96652024-12-17 22:27:38 +0000125 GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy
126
Colin Cross648daea2024-09-12 14:35:29 -0700127 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
128 // 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. It raises an error if any of the
130 // dependencies are disabled.
131 //
132 // The Module passed to the visit function should not be retained outside of the visit
133 // function, it may be invalidated by future mutators.
134 VisitDirectDeps(visit func(Module))
135
Yu Liud3228ac2024-11-08 23:11:47 +0000136 // VisitDirectDepsProxy calls visit for each direct dependency. If there are multiple
Colin Cross69452e12023-11-15 11:20:53 -0800137 // direct dependencies on the same module visit will be called multiple times on that module
Yu Liud3228ac2024-11-08 23:11:47 +0000138 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
139 // dependencies are disabled.
Colin Cross69452e12023-11-15 11:20:53 -0800140 //
Yu Liud3228ac2024-11-08 23:11:47 +0000141 // The ModuleProxy passed to the visit function should not be retained outside of the visit
Colin Cross69452e12023-11-15 11:20:53 -0800142 // function, it may be invalidated by future mutators.
Yu Liud3228ac2024-11-08 23:11:47 +0000143 VisitDirectDepsProxy(visit func(proxy ModuleProxy))
Colin Cross69452e12023-11-15 11:20:53 -0800144
Yu Liudd9ccb42024-10-07 17:07:44 +0000145 // VisitDirectDepsProxyAllowDisabled calls visit for each direct dependency. If there are
146 // multiple direct dependencies on the same module visit will be called multiple times on
147 // that module and OtherModuleDependencyTag will return a different tag for each.
148 //
Yu Liud2a95952024-10-10 00:15:26 +0000149 // 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 +0000150 // invalidated by future mutators.
Yu Liud2a95952024-10-10 00:15:26 +0000151 VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy))
Yu Liudd9ccb42024-10-07 17:07:44 +0000152
Colin Cross69452e12023-11-15 11:20:53 -0800153 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
154
Yu Liud2a95952024-10-10 00:15:26 +0000155 VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy))
156
Colin Cross69452e12023-11-15 11:20:53 -0800157 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
158 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
159 // OtherModuleDependencyTag will return a different tag for each. It skips any
160 // dependencies that are not an android.Module.
161 //
162 // The Module passed to the visit function should not be retained outside of the visit function, it may be
163 // invalidated by future mutators.
164 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
165 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
166 VisitDepsDepthFirst(visit func(Module))
167 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
168 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
169
170 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
171 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
172 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
173 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
174 // any dependencies that are not an android.Module.
175 //
176 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
177 // invalidated by future mutators.
178 WalkDeps(visit func(child, parent Module) bool)
179
Yu Liudd9ccb42024-10-07 17:07:44 +0000180 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
181 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
182 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
183 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
184 // any dependencies that are not an android.Module.
185 //
186 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
187 // invalidated by future mutators.
Yu Liud2a95952024-10-10 00:15:26 +0000188 WalkDepsProxy(visit func(child, parent ModuleProxy) bool)
Yu Liudd9ccb42024-10-07 17:07:44 +0000189
Colin Cross69452e12023-11-15 11:20:53 -0800190 // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
191 // and returns a top-down dependency path from a start module to current child module.
192 GetWalkPath() []Module
193
194 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
195 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
196 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
197 // only done once for all variants of a module.
198 PrimaryModule() Module
199
200 // FinalModule returns the last variant of the current module. Variants of a module are always visited in
201 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
202 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
203 // singleton actions that are only done once for all variants of a module.
204 FinalModule() Module
205
Yu Liu88ea9ff2024-11-07 19:19:42 +0000206 // IsFinalModule returns if the current module is the last variant. Variants of a module are always visited in
207 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
208 // variants using VisitAllModuleVariants if the current module is the last one. This can be used to perform
209 // singleton actions that are only done once for all variants of a module.
210 IsFinalModule(module Module) bool
211
Colin Cross69452e12023-11-15 11:20:53 -0800212 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
213 // 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 +0000214 // 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 -0800215 // data modified by the current mutator.
216 VisitAllModuleVariants(visit func(Module))
217
Yu Liub5275322024-11-13 18:40:43 +0000218 // VisitAllModuleVariantProxies calls visit for each variant of the current module. Variants of a module are always
219 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
220 // from all variants if the current module is the last one. Otherwise, care must be taken to not access any
221 // data modified by the current mutator.
222 VisitAllModuleVariantProxies(visit func(proxy ModuleProxy))
223
Colin Cross69452e12023-11-15 11:20:53 -0800224 // GetTagPath is supposed to be called in visit function passed in WalkDeps()
225 // and returns a top-down dependency tags path from a start module to current child module.
226 // It has one less entry than GetWalkPath() as it contains the dependency tags that
227 // exist between each adjacent pair of modules in the GetWalkPath().
228 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
229 GetTagPath() []blueprint.DependencyTag
230
231 // GetPathString is supposed to be called in visit function passed in WalkDeps()
232 // and returns a multi-line string showing the modules and dependency tags
233 // among them along the top-down dependency path from a start module to current child module.
234 // skipFirst when set to true, the output doesn't include the start module,
235 // which is already printed when this function is used along with ModuleErrorf().
236 GetPathString(skipFirst bool) string
237
238 AddMissingDependencies(missingDeps []string)
239
240 // getMissingDependencies returns the list of missing dependencies.
241 // Calling this function prevents adding new dependencies.
242 getMissingDependencies() []string
Cole Faustbdd8aee2024-03-14 14:33:02 -0700243
244 // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
245 // can be used to evaluate the final value of Configurable properties.
Cole Faustfdbf5d42024-04-10 15:01:23 -0700246 EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue
Colin Cross69452e12023-11-15 11:20:53 -0800247}
248
249type baseModuleContext struct {
250 bp blueprint.BaseModuleContext
251 earlyModuleContext
Colin Cross1d3d9f12024-01-18 14:30:22 -0800252 archModuleContext
Colin Cross69452e12023-11-15 11:20:53 -0800253
254 walkPath []Module
255 tagPath []blueprint.DependencyTag
256
257 strictVisitDeps bool // If true, enforce that all dependencies are enabled
258
Colin Cross69452e12023-11-15 11:20:53 -0800259}
260
Yu Liudd9ccb42024-10-07 17:07:44 +0000261func getWrappedModule(module blueprint.Module) blueprint.Module {
Cole Faust19eb09d2025-01-14 13:27:00 -0800262 if mp, isProxy := module.(*ModuleProxy); isProxy {
263 return mp.module
264 }
Yu Liudd9ccb42024-10-07 17:07:44 +0000265 if mp, isProxy := module.(ModuleProxy); isProxy {
266 return mp.module
267 }
268 return module
269}
270
271func (b *baseModuleContext) EqualModules(m1, m2 Module) bool {
272 return b.bp.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
273}
274
Colin Cross69452e12023-11-15 11:20:53 -0800275func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
Yu Liudd9ccb42024-10-07 17:07:44 +0000276 return b.bp.OtherModuleName(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800277}
Yu Liud3228ac2024-11-08 23:11:47 +0000278func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string {
279 return b.bp.OtherModuleDir(getWrappedModule(m))
280}
Colin Cross69452e12023-11-15 11:20:53 -0800281func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
Yu Liuac483e02024-11-11 22:29:30 +0000282 b.bp.OtherModuleErrorf(getWrappedModule(m), fmt, args...)
Colin Cross69452e12023-11-15 11:20:53 -0800283}
284func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
Yu Liudd9ccb42024-10-07 17:07:44 +0000285 return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800286}
287func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
288func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
289 return b.bp.OtherModuleDependencyVariantExists(variations, name)
290}
291func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
292 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
293}
294func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
295 return b.bp.OtherModuleReverseDependencyVariantExists(name)
296}
297func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
Yu Liub1bfa9d2024-12-05 18:57:51 +0000298 return b.bp.OtherModuleType(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800299}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800300
301func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Cole Faust19eb09d2025-01-14 13:27:00 -0800302 return b.bp.OtherModuleProvider(getWrappedModule(m), provider)
Colin Cross69452e12023-11-15 11:20:53 -0800303}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800304
Yu Liu0a37d422025-02-13 02:05:00 +0000305func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool {
306 return b.bp.OtherModuleHasProvider(getWrappedModule(m), provider)
307}
308
Jihoon Kang2a7bf752024-11-01 21:21:25 +0000309func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool {
310 return b.bp.OtherModuleIsAutoGenerated(m)
311}
312
Colin Cross3c0a83d2023-12-12 14:13:26 -0800313func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800314 return b.bp.Provider(provider)
315}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800316
Colin Cross24c1cbe2023-12-21 23:42:56 +0000317func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
Colin Cross69452e12023-11-15 11:20:53 -0800318 b.bp.SetProvider(provider, value)
319}
320
Yu Liud3228ac2024-11-08 23:11:47 +0000321func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module {
322 if module := b.bp.GetDirectDepWithTag(name, tag); module != nil {
323 return module.(Module)
324 }
325 return nil
Colin Cross69452e12023-11-15 11:20:53 -0800326}
327
Yu Liu3ae96652024-12-17 22:27:38 +0000328func (b *baseModuleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy {
329 if module := b.bp.GetDirectDepProxyWithTag(name, tag); module != nil {
330 return &ModuleProxy{*module}
331 }
332 return nil
333}
334
Colin Cross69452e12023-11-15 11:20:53 -0800335func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
336 return b.bp
337}
338
Colin Cross69452e12023-11-15 11:20:53 -0800339func (b *baseModuleContext) AddMissingDependencies(deps []string) {
340 if deps != nil {
341 missingDeps := &b.Module().base().commonProperties.MissingDeps
342 *missingDeps = append(*missingDeps, deps...)
343 *missingDeps = FirstUniqueStrings(*missingDeps)
344 }
345}
346
347func (b *baseModuleContext) checkedMissingDeps() bool {
348 return b.Module().base().commonProperties.CheckedMissingDeps
349}
350
351func (b *baseModuleContext) getMissingDependencies() []string {
352 checked := &b.Module().base().commonProperties.CheckedMissingDeps
353 *checked = true
354 var missingDeps []string
355 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
356 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
357 missingDeps = FirstUniqueStrings(missingDeps)
358 return missingDeps
359}
360
361type AllowDisabledModuleDependency interface {
362 blueprint.DependencyTag
363 AllowDisabledModuleDependency(target Module) bool
Yu Liud2a95952024-10-10 00:15:26 +0000364 AllowDisabledModuleDependencyProxy(ctx OtherModuleProviderContext, target ModuleProxy) bool
Colin Cross69452e12023-11-15 11:20:53 -0800365}
366
Jiyong Park8bcf3c62024-03-18 18:37:10 +0900367type AlwaysAllowDisabledModuleDependencyTag struct{}
368
369func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
370 return true
371}
372
Yu Liud2a95952024-10-10 00:15:26 +0000373func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependencyProxy(OtherModuleProviderContext, ModuleProxy) bool {
374 return true
375}
376
Colin Cross648daea2024-09-12 14:35:29 -0700377func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
Colin Cross69452e12023-11-15 11:20:53 -0800378 aModule, _ := module.(Module)
379
380 if !strict {
381 return aModule
382 }
383
384 if aModule == nil {
Colin Cross648daea2024-09-12 14:35:29 -0700385 panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag))
Colin Cross69452e12023-11-15 11:20:53 -0800386 }
387
Cole Fausta963b942024-04-11 17:43:00 -0700388 if !aModule.Enabled(b) {
Colin Cross69452e12023-11-15 11:20:53 -0800389 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
390 if b.Config().AllowMissingDependencies() {
391 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
392 } else {
393 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
394 }
395 }
396 return nil
397 }
398 return aModule
399}
400
Yu Liud2a95952024-10-10 00:15:26 +0000401func (b *baseModuleContext) validateAndroidModuleProxy(
402 module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) *ModuleProxy {
403 aModule := ModuleProxy{module: module}
404
405 if !strict {
406 return &aModule
407 }
408
Yu Liub5275322024-11-13 18:40:43 +0000409 if !OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).Enabled {
Yu Liud2a95952024-10-10 00:15:26 +0000410 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) {
411 if b.Config().AllowMissingDependencies() {
412 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
413 } else {
414 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
415 }
416 }
417 return nil
418 }
419
420 return &aModule
421}
422
Yu Liu3ae96652024-12-17 22:27:38 +0000423func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []Module {
424 var deps []Module
Colin Cross648daea2024-09-12 14:35:29 -0700425 b.VisitDirectDeps(func(module Module) {
426 if module.base().BaseModuleName() == name {
Colin Cross69452e12023-11-15 11:20:53 -0800427 returnedTag := b.bp.OtherModuleDependencyTag(module)
428 if tag == nil || returnedTag == tag {
Yu Liu3ae96652024-12-17 22:27:38 +0000429 deps = append(deps, module)
Colin Cross69452e12023-11-15 11:20:53 -0800430 }
431 }
432 })
433 return deps
434}
435
Yu Liu3ae96652024-12-17 22:27:38 +0000436func (b *baseModuleContext) getDirectDepsProxyInternal(name string, tag blueprint.DependencyTag) []ModuleProxy {
437 var deps []ModuleProxy
438 b.VisitDirectDepsProxy(func(module ModuleProxy) {
439 if OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).BaseModuleName == name {
440 returnedTag := b.OtherModuleDependencyTag(module)
441 if tag == nil || returnedTag == tag {
442 deps = append(deps, module)
443 }
444 }
445 })
446 return deps
Colin Cross69452e12023-11-15 11:20:53 -0800447}
448
Colin Cross69452e12023-11-15 11:20:53 -0800449func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
450 var deps []Module
Colin Cross648daea2024-09-12 14:35:29 -0700451 b.VisitDirectDeps(func(module Module) {
452 if b.bp.OtherModuleDependencyTag(module) == tag {
453 deps = append(deps, module)
Colin Cross69452e12023-11-15 11:20:53 -0800454 }
455 })
456 return deps
457}
458
Yu Liuf432c2e2024-12-17 00:09:15 +0000459func (b *baseModuleContext) GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy {
460 var deps []ModuleProxy
461 b.VisitDirectDepsProxy(func(module ModuleProxy) {
462 if b.OtherModuleDependencyTag(module) == tag {
463 deps = append(deps, module)
464 }
465 })
466 return deps
467}
468
Colin Cross69452e12023-11-15 11:20:53 -0800469func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
470 b.bp.VisitDirectDeps(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700471 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800472 visit(aModule)
473 }
474 })
475}
476
Yu Liud3228ac2024-11-08 23:11:47 +0000477func (b *baseModuleContext) VisitDirectDepsProxy(visit func(ModuleProxy)) {
478 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
479 if aModule := b.validateAndroidModuleProxy(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
480 visit(*aModule)
481 }
Colin Cross648daea2024-09-12 14:35:29 -0700482 })
483}
484
Yu Liud2a95952024-10-10 00:15:26 +0000485func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) {
Yu Liud3228ac2024-11-08 23:11:47 +0000486 b.bp.VisitDirectDepsProxy(visitProxyAdaptor(visit))
Yu Liudd9ccb42024-10-07 17:07:44 +0000487}
488
Colin Cross69452e12023-11-15 11:20:53 -0800489func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
490 b.bp.VisitDirectDeps(func(module blueprint.Module) {
491 if b.bp.OtherModuleDependencyTag(module) == tag {
Yu Liud2a95952024-10-10 00:15:26 +0000492 if aModule := b.validateAndroidModule(module, tag, b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800493 visit(aModule)
494 }
495 }
496 })
497}
498
Yu Liud2a95952024-10-10 00:15:26 +0000499func (b *baseModuleContext) VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) {
500 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
501 if b.bp.OtherModuleDependencyTag(module) == tag {
502 if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); aModule != nil {
503 visit(*aModule)
504 }
505 }
506 })
507}
508
Colin Cross69452e12023-11-15 11:20:53 -0800509func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
510 b.bp.VisitDirectDepsIf(
511 // pred
512 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700513 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800514 return pred(aModule)
515 } else {
516 return false
517 }
518 },
519 // visit
520 func(module blueprint.Module) {
521 visit(module.(Module))
522 })
523}
524
525func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
526 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700527 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800528 visit(aModule)
529 }
530 })
531}
532
533func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
534 b.bp.VisitDepsDepthFirstIf(
535 // pred
536 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700537 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800538 return pred(aModule)
539 } else {
540 return false
541 }
542 },
543 // visit
544 func(module blueprint.Module) {
545 visit(module.(Module))
546 })
547}
548
Colin Cross69452e12023-11-15 11:20:53 -0800549func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
550 b.walkPath = []Module{b.Module()}
551 b.tagPath = []blueprint.DependencyTag{}
552 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
553 childAndroidModule, _ := child.(Module)
554 parentAndroidModule, _ := parent.(Module)
555 if childAndroidModule != nil && parentAndroidModule != nil {
556 // record walkPath before visit
557 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
558 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
559 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
560 }
561 b.walkPath = append(b.walkPath, childAndroidModule)
562 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
563 return visit(childAndroidModule, parentAndroidModule)
564 } else {
565 return false
566 }
567 })
568}
569
Yu Liud2a95952024-10-10 00:15:26 +0000570func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) {
Yu Liudd9ccb42024-10-07 17:07:44 +0000571 b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
572 b.tagPath = []blueprint.DependencyTag{}
573 b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
574 childAndroidModule := ModuleProxy{child}
575 parentAndroidModule := ModuleProxy{parent}
576 // record walkPath before visit
577 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
578 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
579 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
580 }
581 b.walkPath = append(b.walkPath, childAndroidModule)
582 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
583 return visit(childAndroidModule, parentAndroidModule)
584 })
585}
586
Colin Cross69452e12023-11-15 11:20:53 -0800587func (b *baseModuleContext) GetWalkPath() []Module {
Colin Crossb614cd42024-10-11 12:52:21 -0700588 return slices.Clone(b.walkPath)
Colin Cross69452e12023-11-15 11:20:53 -0800589}
590
591func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
592 return b.tagPath
593}
594
595func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
596 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
597 visit(module.(Module))
598 })
599}
600
Yu Liub5275322024-11-13 18:40:43 +0000601func (b *baseModuleContext) VisitAllModuleVariantProxies(visit func(ModuleProxy)) {
602 b.bp.VisitAllModuleVariantProxies(visitProxyAdaptor(visit))
603}
604
Colin Cross69452e12023-11-15 11:20:53 -0800605func (b *baseModuleContext) PrimaryModule() Module {
606 return b.bp.PrimaryModule().(Module)
607}
608
609func (b *baseModuleContext) FinalModule() Module {
610 return b.bp.FinalModule().(Module)
611}
612
Yu Liu88ea9ff2024-11-07 19:19:42 +0000613func (b *baseModuleContext) IsFinalModule(module Module) bool {
614 return b.bp.IsFinalModule(module)
615}
616
Colin Cross69452e12023-11-15 11:20:53 -0800617// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
618func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
619 if tag == licenseKindTag {
620 return true
621 } else if tag == licensesTag {
622 return true
Jihoon Kanga3a05462024-04-05 00:36:44 +0000623 } else if tag == AcDepTag {
Colin Cross69452e12023-11-15 11:20:53 -0800624 return true
625 }
626 return false
627}
628
629// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
630// a dependency tag.
631var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
632
633// PrettyPrintTag returns string representation of the tag, but prefers
634// custom String() method if available.
635func PrettyPrintTag(tag blueprint.DependencyTag) string {
636 // Use tag's custom String() method if available.
637 if stringer, ok := tag.(fmt.Stringer); ok {
638 return stringer.String()
639 }
640
641 // Otherwise, get a default string representation of the tag's struct.
642 tagString := fmt.Sprintf("%T: %+v", tag, tag)
643
644 // Remove the boilerplate from BaseDependencyTag as it adds no value.
645 tagString = tagCleaner.ReplaceAllString(tagString, "")
646 return tagString
647}
648
649func (b *baseModuleContext) GetPathString(skipFirst bool) string {
650 sb := strings.Builder{}
651 tagPath := b.GetTagPath()
652 walkPath := b.GetWalkPath()
653 if !skipFirst {
654 sb.WriteString(walkPath[0].String())
655 }
656 for i, m := range walkPath[1:] {
657 sb.WriteString("\n")
658 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
659 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
660 }
661 return sb.String()
662}
Cole Faustbdd8aee2024-03-14 14:33:02 -0700663
Cole Faustfdbf5d42024-04-10 15:01:23 -0700664func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
665 return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property)
Cole Faustbdd8aee2024-03-14 14:33:02 -0700666}