blob: 5e05f547ae86843dc4e243a447d2b2eb4f4cd3ef [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
Jihoon Kangf50d2e62025-02-19 00:47:23 +000056 // OtherModuleSubDir returns the string representing the variations of a module.
57 OtherModuleSubDir(m blueprint.Module) string
58
Colin Cross69452e12023-11-15 11:20:53 -080059 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
60 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
61 OtherModuleExists(name string) bool
62
63 // OtherModuleDependencyVariantExists returns true if a module with the
64 // specified name and variant exists. The variant must match the given
65 // variations. It must also match all the non-local variations of the current
66 // module. In other words, it checks for the module that AddVariationDependencies
67 // would add a dependency on with the same arguments.
68 OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
69
70 // OtherModuleFarDependencyVariantExists returns true if a module with the
71 // specified name and variant exists. The variant must match the given
72 // variations, but not the non-local variations of the current module. In
73 // other words, it checks for the module that AddFarVariationDependencies
74 // would add a dependency on with the same arguments.
75 OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
76
77 // OtherModuleReverseDependencyVariantExists returns true if a module with the
78 // specified name exists with the same variations as the current module. In
79 // other words, it checks for the module that AddReverseDependency would add a
80 // dependency on with the same argument.
81 OtherModuleReverseDependencyVariantExists(name string) bool
82
83 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
84 // It is intended for use inside the visit functions of Visit* and WalkDeps.
85 OtherModuleType(m blueprint.Module) string
86
Colin Cross24c1cbe2023-12-21 23:42:56 +000087 // otherModuleProvider returns the value for a provider for the given module. If the value is
88 // not set it returns nil and false. The value returned may be a deep copy of the value originally
89 // passed to SetProvider.
90 //
91 // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -080092 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -080093
Yu Liu0a37d422025-02-13 02:05:00 +000094 // OtherModuleHasProvider returns true if the module has the given provider set. This
95 // can avoid copying the provider if the caller only cares about the existence of
96 // the provider.
97 OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool
98
Jihoon Kang2a7bf752024-11-01 21:21:25 +000099 // OtherModuleIsAutoGenerated returns true if the module is auto generated by another module
100 // instead of being defined in Android.bp file.
101 OtherModuleIsAutoGenerated(m blueprint.Module) bool
102
Colin Cross69452e12023-11-15 11:20:53 -0800103 // Provider returns the value for a provider for the current module. If the value is
Colin Cross24c1cbe2023-12-21 23:42:56 +0000104 // not set it returns nil and false. It panics if called before the appropriate
Colin Cross69452e12023-11-15 11:20:53 -0800105 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
106 // copy of the value originally passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000107 //
108 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
Colin Cross3c0a83d2023-12-12 14:13:26 -0800109 provider(provider blueprint.AnyProviderKey) (any, bool)
Colin Cross69452e12023-11-15 11:20:53 -0800110
Colin Cross24c1cbe2023-12-21 23:42:56 +0000111 // setProvider sets the value for a provider for the current module. It panics if not called
Colin Cross69452e12023-11-15 11:20:53 -0800112 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
113 // is not of the appropriate type, or if the value has already been set. The value should not
114 // be modified after being passed to SetProvider.
Colin Cross24c1cbe2023-12-21 23:42:56 +0000115 //
116 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
117 setProvider(provider blueprint.AnyProviderKey, value any)
Colin Cross69452e12023-11-15 11:20:53 -0800118
119 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
120
Yu Liuf432c2e2024-12-17 00:09:15 +0000121 GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy
122
Colin Cross69452e12023-11-15 11:20:53 -0800123 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
124 // none exists. It panics if the dependency does not have the specified tag. It skips any
125 // dependencies that are not an android.Module.
Yu Liud3228ac2024-11-08 23:11:47 +0000126 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module
Colin Cross69452e12023-11-15 11:20:53 -0800127
Yu Liu3ae96652024-12-17 22:27:38 +0000128 GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy
129
Colin Cross648daea2024-09-12 14:35:29 -0700130 // VisitDirectDeps calls visit for each direct dependency. If there are multiple
131 // direct dependencies on the same module visit will be called multiple times on that module
132 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
133 // dependencies are disabled.
134 //
135 // The Module passed to the visit function should not be retained outside of the visit
136 // function, it may be invalidated by future mutators.
137 VisitDirectDeps(visit func(Module))
138
Yu Liud3228ac2024-11-08 23:11:47 +0000139 // VisitDirectDepsProxy calls visit for each direct dependency. If there are multiple
Colin Cross69452e12023-11-15 11:20:53 -0800140 // direct dependencies on the same module visit will be called multiple times on that module
Yu Liud3228ac2024-11-08 23:11:47 +0000141 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
142 // dependencies are disabled.
Colin Cross69452e12023-11-15 11:20:53 -0800143 //
Yu Liud3228ac2024-11-08 23:11:47 +0000144 // The ModuleProxy passed to the visit function should not be retained outside of the visit
Colin Cross69452e12023-11-15 11:20:53 -0800145 // function, it may be invalidated by future mutators.
Yu Liud3228ac2024-11-08 23:11:47 +0000146 VisitDirectDepsProxy(visit func(proxy ModuleProxy))
Colin Cross69452e12023-11-15 11:20:53 -0800147
Yu Liudd9ccb42024-10-07 17:07:44 +0000148 // VisitDirectDepsProxyAllowDisabled calls visit for each direct dependency. If there are
149 // multiple direct dependencies on the same module visit will be called multiple times on
150 // that module and OtherModuleDependencyTag will return a different tag for each.
151 //
Yu Liud2a95952024-10-10 00:15:26 +0000152 // 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 +0000153 // invalidated by future mutators.
Yu Liud2a95952024-10-10 00:15:26 +0000154 VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy))
Yu Liudd9ccb42024-10-07 17:07:44 +0000155
Colin Cross69452e12023-11-15 11:20:53 -0800156 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
157
Yu Liud2a95952024-10-10 00:15:26 +0000158 VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy))
159
Colin Cross69452e12023-11-15 11:20:53 -0800160 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
161 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
162 // OtherModuleDependencyTag will return a different tag for each. It skips any
163 // dependencies that are not an android.Module.
164 //
165 // The Module passed to the visit function should not be retained outside of the visit function, it may be
166 // invalidated by future mutators.
167 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
168 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
169 VisitDepsDepthFirst(visit func(Module))
170 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
171 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
172
173 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
174 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
175 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
176 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
177 // any dependencies that are not an android.Module.
178 //
179 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
180 // invalidated by future mutators.
181 WalkDeps(visit func(child, parent Module) bool)
182
Yu Liudd9ccb42024-10-07 17:07:44 +0000183 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
184 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
185 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
186 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
187 // any dependencies that are not an android.Module.
188 //
189 // The Modules passed to the visit function should not be retained outside of the visit function, they may be
190 // invalidated by future mutators.
Yu Liud2a95952024-10-10 00:15:26 +0000191 WalkDepsProxy(visit func(child, parent ModuleProxy) bool)
Yu Liudd9ccb42024-10-07 17:07:44 +0000192
Colin Cross69452e12023-11-15 11:20:53 -0800193 // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
194 // and returns a top-down dependency path from a start module to current child module.
195 GetWalkPath() []Module
196
197 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
198 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
199 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
200 // only done once for all variants of a module.
201 PrimaryModule() Module
202
203 // FinalModule returns the last variant of the current module. Variants of a module are always visited in
204 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
205 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
206 // singleton actions that are only done once for all variants of a module.
207 FinalModule() Module
208
Yu Liu88ea9ff2024-11-07 19:19:42 +0000209 // IsFinalModule returns if the current module is the last variant. Variants of a module are always visited in
210 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
211 // variants using VisitAllModuleVariants if the current module is the last one. This can be used to perform
212 // singleton actions that are only done once for all variants of a module.
213 IsFinalModule(module Module) bool
214
Colin Cross69452e12023-11-15 11:20:53 -0800215 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
216 // 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 +0000217 // 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 -0800218 // data modified by the current mutator.
219 VisitAllModuleVariants(visit func(Module))
220
Yu Liub5275322024-11-13 18:40:43 +0000221 // VisitAllModuleVariantProxies calls visit for each variant of the current module. Variants of a module are always
222 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
223 // from all variants if the current module is the last one. Otherwise, care must be taken to not access any
224 // data modified by the current mutator.
225 VisitAllModuleVariantProxies(visit func(proxy ModuleProxy))
226
Colin Cross69452e12023-11-15 11:20:53 -0800227 // GetTagPath is supposed to be called in visit function passed in WalkDeps()
228 // and returns a top-down dependency tags path from a start module to current child module.
229 // It has one less entry than GetWalkPath() as it contains the dependency tags that
230 // exist between each adjacent pair of modules in the GetWalkPath().
231 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
232 GetTagPath() []blueprint.DependencyTag
233
234 // GetPathString is supposed to be called in visit function passed in WalkDeps()
235 // and returns a multi-line string showing the modules and dependency tags
236 // among them along the top-down dependency path from a start module to current child module.
237 // skipFirst when set to true, the output doesn't include the start module,
238 // which is already printed when this function is used along with ModuleErrorf().
239 GetPathString(skipFirst bool) string
240
241 AddMissingDependencies(missingDeps []string)
242
243 // getMissingDependencies returns the list of missing dependencies.
244 // Calling this function prevents adding new dependencies.
245 getMissingDependencies() []string
Cole Faustbdd8aee2024-03-14 14:33:02 -0700246
247 // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
248 // can be used to evaluate the final value of Configurable properties.
Cole Faustfdbf5d42024-04-10 15:01:23 -0700249 EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue
Colin Cross69452e12023-11-15 11:20:53 -0800250}
251
252type baseModuleContext struct {
253 bp blueprint.BaseModuleContext
254 earlyModuleContext
Colin Cross1d3d9f12024-01-18 14:30:22 -0800255 archModuleContext
Colin Cross69452e12023-11-15 11:20:53 -0800256
257 walkPath []Module
258 tagPath []blueprint.DependencyTag
259
260 strictVisitDeps bool // If true, enforce that all dependencies are enabled
261
Colin Cross69452e12023-11-15 11:20:53 -0800262}
263
Yu Liudd9ccb42024-10-07 17:07:44 +0000264func getWrappedModule(module blueprint.Module) blueprint.Module {
Cole Faust19eb09d2025-01-14 13:27:00 -0800265 if mp, isProxy := module.(*ModuleProxy); isProxy {
266 return mp.module
267 }
Yu Liudd9ccb42024-10-07 17:07:44 +0000268 if mp, isProxy := module.(ModuleProxy); isProxy {
269 return mp.module
270 }
271 return module
272}
273
274func (b *baseModuleContext) EqualModules(m1, m2 Module) bool {
275 return b.bp.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
276}
277
Colin Cross69452e12023-11-15 11:20:53 -0800278func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
Yu Liudd9ccb42024-10-07 17:07:44 +0000279 return b.bp.OtherModuleName(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800280}
Yu Liud3228ac2024-11-08 23:11:47 +0000281func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string {
282 return b.bp.OtherModuleDir(getWrappedModule(m))
283}
Colin Cross69452e12023-11-15 11:20:53 -0800284func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
Yu Liuac483e02024-11-11 22:29:30 +0000285 b.bp.OtherModuleErrorf(getWrappedModule(m), fmt, args...)
Colin Cross69452e12023-11-15 11:20:53 -0800286}
287func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
Yu Liudd9ccb42024-10-07 17:07:44 +0000288 return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800289}
Jihoon Kangf50d2e62025-02-19 00:47:23 +0000290func (b *baseModuleContext) OtherModuleSubDir(m blueprint.Module) string {
291 return b.bp.OtherModuleSubDir(getWrappedModule(m))
292}
Colin Cross69452e12023-11-15 11:20:53 -0800293func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
294func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
295 return b.bp.OtherModuleDependencyVariantExists(variations, name)
296}
297func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
298 return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
299}
300func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
301 return b.bp.OtherModuleReverseDependencyVariantExists(name)
302}
303func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
Yu Liub1bfa9d2024-12-05 18:57:51 +0000304 return b.bp.OtherModuleType(getWrappedModule(m))
Colin Cross69452e12023-11-15 11:20:53 -0800305}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800306
307func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Cole Faust19eb09d2025-01-14 13:27:00 -0800308 return b.bp.OtherModuleProvider(getWrappedModule(m), provider)
Colin Cross69452e12023-11-15 11:20:53 -0800309}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800310
Yu Liu0a37d422025-02-13 02:05:00 +0000311func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool {
312 return b.bp.OtherModuleHasProvider(getWrappedModule(m), provider)
313}
314
Jihoon Kang2a7bf752024-11-01 21:21:25 +0000315func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool {
316 return b.bp.OtherModuleIsAutoGenerated(m)
317}
318
Colin Cross3c0a83d2023-12-12 14:13:26 -0800319func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross69452e12023-11-15 11:20:53 -0800320 return b.bp.Provider(provider)
321}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800322
Colin Cross24c1cbe2023-12-21 23:42:56 +0000323func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
Colin Cross69452e12023-11-15 11:20:53 -0800324 b.bp.SetProvider(provider, value)
325}
326
Yu Liud3228ac2024-11-08 23:11:47 +0000327func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module {
328 if module := b.bp.GetDirectDepWithTag(name, tag); module != nil {
329 return module.(Module)
330 }
331 return nil
Colin Cross69452e12023-11-15 11:20:53 -0800332}
333
Yu Liu3ae96652024-12-17 22:27:38 +0000334func (b *baseModuleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy {
335 if module := b.bp.GetDirectDepProxyWithTag(name, tag); module != nil {
336 return &ModuleProxy{*module}
337 }
338 return nil
339}
340
Colin Cross69452e12023-11-15 11:20:53 -0800341func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
342 return b.bp
343}
344
Colin Cross69452e12023-11-15 11:20:53 -0800345func (b *baseModuleContext) AddMissingDependencies(deps []string) {
346 if deps != nil {
347 missingDeps := &b.Module().base().commonProperties.MissingDeps
348 *missingDeps = append(*missingDeps, deps...)
349 *missingDeps = FirstUniqueStrings(*missingDeps)
350 }
351}
352
353func (b *baseModuleContext) checkedMissingDeps() bool {
354 return b.Module().base().commonProperties.CheckedMissingDeps
355}
356
357func (b *baseModuleContext) getMissingDependencies() []string {
358 checked := &b.Module().base().commonProperties.CheckedMissingDeps
359 *checked = true
360 var missingDeps []string
361 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
362 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
363 missingDeps = FirstUniqueStrings(missingDeps)
364 return missingDeps
365}
366
367type AllowDisabledModuleDependency interface {
368 blueprint.DependencyTag
369 AllowDisabledModuleDependency(target Module) bool
Yu Liud2a95952024-10-10 00:15:26 +0000370 AllowDisabledModuleDependencyProxy(ctx OtherModuleProviderContext, target ModuleProxy) bool
Colin Cross69452e12023-11-15 11:20:53 -0800371}
372
Jiyong Park8bcf3c62024-03-18 18:37:10 +0900373type AlwaysAllowDisabledModuleDependencyTag struct{}
374
375func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
376 return true
377}
378
Yu Liud2a95952024-10-10 00:15:26 +0000379func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependencyProxy(OtherModuleProviderContext, ModuleProxy) bool {
380 return true
381}
382
Colin Cross648daea2024-09-12 14:35:29 -0700383func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
Colin Cross69452e12023-11-15 11:20:53 -0800384 aModule, _ := module.(Module)
385
386 if !strict {
387 return aModule
388 }
389
390 if aModule == nil {
Colin Cross648daea2024-09-12 14:35:29 -0700391 panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag))
Colin Cross69452e12023-11-15 11:20:53 -0800392 }
393
Cole Fausta963b942024-04-11 17:43:00 -0700394 if !aModule.Enabled(b) {
Colin Cross69452e12023-11-15 11:20:53 -0800395 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
396 if b.Config().AllowMissingDependencies() {
397 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
398 } else {
399 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
400 }
401 }
402 return nil
403 }
404 return aModule
405}
406
Yu Liud2a95952024-10-10 00:15:26 +0000407func (b *baseModuleContext) validateAndroidModuleProxy(
408 module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) *ModuleProxy {
409 aModule := ModuleProxy{module: module}
410
411 if !strict {
412 return &aModule
413 }
414
Yu Liub5275322024-11-13 18:40:43 +0000415 if !OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).Enabled {
Yu Liud2a95952024-10-10 00:15:26 +0000416 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) {
417 if b.Config().AllowMissingDependencies() {
418 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
419 } else {
420 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
421 }
422 }
423 return nil
424 }
425
426 return &aModule
427}
428
Yu Liu3ae96652024-12-17 22:27:38 +0000429func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []Module {
430 var deps []Module
Colin Cross648daea2024-09-12 14:35:29 -0700431 b.VisitDirectDeps(func(module Module) {
432 if module.base().BaseModuleName() == name {
Colin Cross69452e12023-11-15 11:20:53 -0800433 returnedTag := b.bp.OtherModuleDependencyTag(module)
434 if tag == nil || returnedTag == tag {
Yu Liu3ae96652024-12-17 22:27:38 +0000435 deps = append(deps, module)
Colin Cross69452e12023-11-15 11:20:53 -0800436 }
437 }
438 })
439 return deps
440}
441
Yu Liu3ae96652024-12-17 22:27:38 +0000442func (b *baseModuleContext) getDirectDepsProxyInternal(name string, tag blueprint.DependencyTag) []ModuleProxy {
443 var deps []ModuleProxy
444 b.VisitDirectDepsProxy(func(module ModuleProxy) {
445 if OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).BaseModuleName == name {
446 returnedTag := b.OtherModuleDependencyTag(module)
447 if tag == nil || returnedTag == tag {
448 deps = append(deps, module)
449 }
450 }
451 })
452 return deps
Colin Cross69452e12023-11-15 11:20:53 -0800453}
454
Colin Cross69452e12023-11-15 11:20:53 -0800455func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
456 var deps []Module
Colin Cross648daea2024-09-12 14:35:29 -0700457 b.VisitDirectDeps(func(module Module) {
458 if b.bp.OtherModuleDependencyTag(module) == tag {
459 deps = append(deps, module)
Colin Cross69452e12023-11-15 11:20:53 -0800460 }
461 })
462 return deps
463}
464
Yu Liuf432c2e2024-12-17 00:09:15 +0000465func (b *baseModuleContext) GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy {
466 var deps []ModuleProxy
467 b.VisitDirectDepsProxy(func(module ModuleProxy) {
468 if b.OtherModuleDependencyTag(module) == tag {
469 deps = append(deps, module)
470 }
471 })
472 return deps
473}
474
Colin Cross69452e12023-11-15 11:20:53 -0800475func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
476 b.bp.VisitDirectDeps(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700477 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800478 visit(aModule)
479 }
480 })
481}
482
Yu Liud3228ac2024-11-08 23:11:47 +0000483func (b *baseModuleContext) VisitDirectDepsProxy(visit func(ModuleProxy)) {
484 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
485 if aModule := b.validateAndroidModuleProxy(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
486 visit(*aModule)
487 }
Colin Cross648daea2024-09-12 14:35:29 -0700488 })
489}
490
Yu Liud2a95952024-10-10 00:15:26 +0000491func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) {
Yu Liud3228ac2024-11-08 23:11:47 +0000492 b.bp.VisitDirectDepsProxy(visitProxyAdaptor(visit))
Yu Liudd9ccb42024-10-07 17:07:44 +0000493}
494
Colin Cross69452e12023-11-15 11:20:53 -0800495func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
496 b.bp.VisitDirectDeps(func(module blueprint.Module) {
497 if b.bp.OtherModuleDependencyTag(module) == tag {
Yu Liud2a95952024-10-10 00:15:26 +0000498 if aModule := b.validateAndroidModule(module, tag, b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800499 visit(aModule)
500 }
501 }
502 })
503}
504
Yu Liud2a95952024-10-10 00:15:26 +0000505func (b *baseModuleContext) VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) {
506 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
507 if b.bp.OtherModuleDependencyTag(module) == tag {
508 if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); aModule != nil {
509 visit(*aModule)
510 }
511 }
512 })
513}
514
Colin Cross69452e12023-11-15 11:20:53 -0800515func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
516 b.bp.VisitDirectDepsIf(
517 // pred
518 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700519 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800520 return pred(aModule)
521 } else {
522 return false
523 }
524 },
525 // visit
526 func(module blueprint.Module) {
527 visit(module.(Module))
528 })
529}
530
531func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
532 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
Colin Cross648daea2024-09-12 14:35:29 -0700533 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800534 visit(aModule)
535 }
536 })
537}
538
539func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
540 b.bp.VisitDepsDepthFirstIf(
541 // pred
542 func(module blueprint.Module) bool {
Colin Cross648daea2024-09-12 14:35:29 -0700543 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
Colin Cross69452e12023-11-15 11:20:53 -0800544 return pred(aModule)
545 } else {
546 return false
547 }
548 },
549 // visit
550 func(module blueprint.Module) {
551 visit(module.(Module))
552 })
553}
554
Colin Cross69452e12023-11-15 11:20:53 -0800555func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
556 b.walkPath = []Module{b.Module()}
557 b.tagPath = []blueprint.DependencyTag{}
558 b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
559 childAndroidModule, _ := child.(Module)
560 parentAndroidModule, _ := parent.(Module)
561 if childAndroidModule != nil && parentAndroidModule != nil {
562 // record walkPath before visit
563 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
564 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
565 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
566 }
567 b.walkPath = append(b.walkPath, childAndroidModule)
568 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
569 return visit(childAndroidModule, parentAndroidModule)
570 } else {
571 return false
572 }
573 })
574}
575
Yu Liud2a95952024-10-10 00:15:26 +0000576func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) {
Yu Liudd9ccb42024-10-07 17:07:44 +0000577 b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
578 b.tagPath = []blueprint.DependencyTag{}
579 b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
580 childAndroidModule := ModuleProxy{child}
581 parentAndroidModule := ModuleProxy{parent}
582 // record walkPath before visit
583 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
584 b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
585 b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
586 }
587 b.walkPath = append(b.walkPath, childAndroidModule)
588 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
589 return visit(childAndroidModule, parentAndroidModule)
590 })
591}
592
Colin Cross69452e12023-11-15 11:20:53 -0800593func (b *baseModuleContext) GetWalkPath() []Module {
Colin Crossb614cd42024-10-11 12:52:21 -0700594 return slices.Clone(b.walkPath)
Colin Cross69452e12023-11-15 11:20:53 -0800595}
596
597func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
598 return b.tagPath
599}
600
601func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
602 b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
603 visit(module.(Module))
604 })
605}
606
Yu Liub5275322024-11-13 18:40:43 +0000607func (b *baseModuleContext) VisitAllModuleVariantProxies(visit func(ModuleProxy)) {
608 b.bp.VisitAllModuleVariantProxies(visitProxyAdaptor(visit))
609}
610
Colin Cross69452e12023-11-15 11:20:53 -0800611func (b *baseModuleContext) PrimaryModule() Module {
612 return b.bp.PrimaryModule().(Module)
613}
614
615func (b *baseModuleContext) FinalModule() Module {
616 return b.bp.FinalModule().(Module)
617}
618
Yu Liu88ea9ff2024-11-07 19:19:42 +0000619func (b *baseModuleContext) IsFinalModule(module Module) bool {
620 return b.bp.IsFinalModule(module)
621}
622
Colin Cross69452e12023-11-15 11:20:53 -0800623// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
624func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
625 if tag == licenseKindTag {
626 return true
627 } else if tag == licensesTag {
628 return true
Jihoon Kanga3a05462024-04-05 00:36:44 +0000629 } else if tag == AcDepTag {
Colin Cross69452e12023-11-15 11:20:53 -0800630 return true
631 }
632 return false
633}
634
635// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
636// a dependency tag.
637var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
638
639// PrettyPrintTag returns string representation of the tag, but prefers
640// custom String() method if available.
641func PrettyPrintTag(tag blueprint.DependencyTag) string {
642 // Use tag's custom String() method if available.
643 if stringer, ok := tag.(fmt.Stringer); ok {
644 return stringer.String()
645 }
646
647 // Otherwise, get a default string representation of the tag's struct.
648 tagString := fmt.Sprintf("%T: %+v", tag, tag)
649
650 // Remove the boilerplate from BaseDependencyTag as it adds no value.
651 tagString = tagCleaner.ReplaceAllString(tagString, "")
652 return tagString
653}
654
655func (b *baseModuleContext) GetPathString(skipFirst bool) string {
656 sb := strings.Builder{}
657 tagPath := b.GetTagPath()
658 walkPath := b.GetWalkPath()
659 if !skipFirst {
660 sb.WriteString(walkPath[0].String())
661 }
662 for i, m := range walkPath[1:] {
663 sb.WriteString("\n")
664 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
665 sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
666 }
667 return sb.String()
668}
Cole Faustbdd8aee2024-03-14 14:33:02 -0700669
Cole Faustfdbf5d42024-04-10 15:01:23 -0700670func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
671 return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property)
Cole Faustbdd8aee2024-03-14 14:33:02 -0700672}