1// 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" 19 "regexp" 20 "slices" 21 "strings" 22 23 "github.com/google/blueprint" 24 "github.com/google/blueprint/proptools" 25) 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 { 32 ArchModuleContext 33 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 54 // OtherModuleSubDir returns the string representing the variations of a module. 55 OtherModuleSubDir(m blueprint.Module) string 56 57 // 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 85 // 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. 90 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) 91 92 // 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 97 // 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 101 // Provider returns the value for a provider for the current module. If the value is 102 // not set it returns nil and false. It panics if called before the appropriate 103 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep 104 // copy of the value originally passed to SetProvider. 105 // 106 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead. 107 provider(provider blueprint.AnyProviderKey) (any, bool) 108 109 // setProvider sets the value for a provider for the current module. It panics if not called 110 // 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. 113 // 114 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead. 115 setProvider(provider blueprint.AnyProviderKey, value any) 116 117 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module 118 119 GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy 120 121 // 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. 124 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module 125 126 GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy 127 128 // 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 137 // VisitDirectDepsProxy calls visit for each direct dependency. If there are multiple 138 // direct dependencies on the same module visit will be called multiple times on that module 139 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the 140 // dependencies are disabled. 141 // 142 // The ModuleProxy passed to the visit function should not be retained outside of the visit 143 // function, it may be invalidated by future mutators. 144 VisitDirectDepsProxy(visit func(proxy ModuleProxy)) 145 146 // 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 // 150 // The ModuleProxy passed to the visit function should not be retained outside of the visit function, it may be 151 // invalidated by future mutators. 152 VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) 153 154 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) 155 156 VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) 157 158 // 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 181 // 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. 189 WalkDepsProxy(visit func(child, parent ModuleProxy) bool) 190 191 // 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 207 // 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 213 // 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 215 // from all variants if the current module is the last one. Otherwise, care must be taken to not access any 216 // data modified by the current mutator. 217 VisitAllModuleVariants(visit func(Module)) 218 219 // 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 225 // 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 244 245 // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context 246 // can be used to evaluate the final value of Configurable properties. 247 EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue 248} 249 250type baseModuleContext struct { 251 bp blueprint.BaseModuleContext 252 earlyModuleContext 253 archModuleContext 254 255 walkPath []Module 256 tagPath []blueprint.DependencyTag 257 258 strictVisitDeps bool // If true, enforce that all dependencies are enabled 259 260} 261 262func getWrappedModule(module blueprint.Module) blueprint.Module { 263 if mp, isProxy := module.(*ModuleProxy); isProxy { 264 return mp.module 265 } 266 if mp, isProxy := module.(ModuleProxy); isProxy { 267 return mp.module 268 } 269 return module 270} 271 272func EqualModules(m1, m2 Module) bool { 273 return blueprint.EqualModules(getWrappedModule(m1), getWrappedModule(m2)) 274} 275 276func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string { 277 return b.bp.OtherModuleName(getWrappedModule(m)) 278} 279func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { 280 return b.bp.OtherModuleDir(getWrappedModule(m)) 281} 282func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) { 283 b.bp.OtherModuleErrorf(getWrappedModule(m), fmt, args...) 284} 285func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag { 286 return b.bp.OtherModuleDependencyTag(getWrappedModule(m)) 287} 288func (b *baseModuleContext) OtherModuleSubDir(m blueprint.Module) string { 289 return b.bp.OtherModuleSubDir(getWrappedModule(m)) 290} 291func (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 { 302 return b.bp.OtherModuleType(getWrappedModule(m)) 303} 304 305func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) { 306 return b.bp.OtherModuleProvider(getWrappedModule(m), provider) 307} 308 309func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool { 310 return b.bp.OtherModuleHasProvider(getWrappedModule(m), provider) 311} 312 313func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool { 314 return b.bp.OtherModuleIsAutoGenerated(m) 315} 316 317func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) { 318 return b.bp.Provider(provider) 319} 320 321func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) { 322 b.bp.SetProvider(provider, value) 323} 324 325func (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 330} 331 332func (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 339func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext { 340 return b.bp 341} 342 343func (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 368 AllowDisabledModuleDependencyProxy(ctx OtherModuleProviderContext, target ModuleProxy) bool 369} 370 371type AlwaysAllowDisabledModuleDependencyTag struct{} 372 373func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool { 374 return true 375} 376 377func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependencyProxy(OtherModuleProviderContext, ModuleProxy) bool { 378 return true 379} 380 381func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module { 382 aModule, _ := module.(Module) 383 384 if !strict { 385 return aModule 386 } 387 388 if aModule == nil { 389 panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)) 390 } 391 392 if !aModule.Enabled(b) { 393 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 405func (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 413 if !OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).Enabled { 414 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 427func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []Module { 428 var deps []Module 429 b.VisitDirectDeps(func(module Module) { 430 if module.base().BaseModuleName() == name { 431 returnedTag := b.bp.OtherModuleDependencyTag(module) 432 if tag == nil || returnedTag == tag { 433 deps = append(deps, module) 434 } 435 } 436 }) 437 return deps 438} 439 440func (b *baseModuleContext) getDirectDepsProxyInternal(name string, tag blueprint.DependencyTag) []ModuleProxy { 441 var deps []ModuleProxy 442 b.VisitDirectDepsProxy(func(module ModuleProxy) { 443 if OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).BaseModuleName == name { 444 returnedTag := b.OtherModuleDependencyTag(module) 445 if tag == nil || returnedTag == tag { 446 deps = append(deps, module) 447 } 448 } 449 }) 450 return deps 451} 452 453func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module { 454 var deps []Module 455 b.VisitDirectDeps(func(module Module) { 456 if b.bp.OtherModuleDependencyTag(module) == tag { 457 deps = append(deps, module) 458 } 459 }) 460 return deps 461} 462 463func (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 473func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) { 474 b.bp.VisitDirectDeps(func(module blueprint.Module) { 475 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { 476 visit(aModule) 477 } 478 }) 479} 480 481func (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 } 486 }) 487} 488 489func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) { 490 b.bp.VisitDirectDepsProxy(visitProxyAdaptor(visit)) 491} 492 493func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) { 494 b.bp.VisitDirectDeps(func(module blueprint.Module) { 495 if b.bp.OtherModuleDependencyTag(module) == tag { 496 if aModule := b.validateAndroidModule(module, tag, b.strictVisitDeps); aModule != nil { 497 visit(aModule) 498 } 499 } 500 }) 501} 502 503func (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 513func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) { 514 b.bp.VisitDirectDepsIf( 515 // pred 516 func(module blueprint.Module) bool { 517 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { 518 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) { 531 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { 532 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 { 541 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { 542 return pred(aModule) 543 } else { 544 return false 545 } 546 }, 547 // visit 548 func(module blueprint.Module) { 549 visit(module.(Module)) 550 }) 551} 552 553func (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 574func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) { 575 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 591func (b *baseModuleContext) GetWalkPath() []Module { 592 return slices.Clone(b.walkPath) 593} 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 605func (b *baseModuleContext) VisitAllModuleVariantProxies(visit func(ModuleProxy)) { 606 b.bp.VisitAllModuleVariantProxies(visitProxyAdaptor(visit)) 607} 608 609func (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 617func (b *baseModuleContext) IsFinalModule(module Module) bool { 618 return b.bp.IsFinalModule(module) 619} 620 621// 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 627 } else if tag == AcDepTag { 628 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} 667 668func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue { 669 return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property) 670} 671