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 EqualModules(m1, m2 Module) bool 38 39 // 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 84 // 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. 89 otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) 90 91 // OtherModuleIsAutoGenerated returns true if the module is auto generated by another module 92 // instead of being defined in Android.bp file. 93 OtherModuleIsAutoGenerated(m blueprint.Module) bool 94 95 // Provider returns the value for a provider for the current module. If the value is 96 // not set it returns nil and false. It panics if called before the appropriate 97 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep 98 // copy of the value originally passed to SetProvider. 99 // 100 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead. 101 provider(provider blueprint.AnyProviderKey) (any, bool) 102 103 // setProvider sets the value for a provider for the current module. It panics if not called 104 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value 105 // is not of the appropriate type, or if the value has already been set. The value should not 106 // be modified after being passed to SetProvider. 107 // 108 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead. 109 setProvider(provider blueprint.AnyProviderKey, value any) 110 111 GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module 112 113 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if 114 // none exists. It panics if the dependency does not have the specified tag. It skips any 115 // dependencies that are not an android.Module. 116 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module 117 118 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified 119 // name, or nil if none exists. If there are multiple dependencies on the same module it returns 120 // the first DependencyTag. 121 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) 122 123 // VisitDirectDeps calls visit for each direct dependency. If there are multiple 124 // direct dependencies on the same module visit will be called multiple times on that module 125 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the 126 // dependencies are disabled. 127 // 128 // The Module passed to the visit function should not be retained outside of the visit 129 // function, it may be invalidated by future mutators. 130 VisitDirectDeps(visit func(Module)) 131 132 // VisitDirectDepsProxy calls visit for each direct dependency. If there are multiple 133 // direct dependencies on the same module visit will be called multiple times on that module 134 // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the 135 // dependencies are disabled. 136 // 137 // The ModuleProxy passed to the visit function should not be retained outside of the visit 138 // function, it may be invalidated by future mutators. 139 VisitDirectDepsProxy(visit func(proxy ModuleProxy)) 140 141 // VisitDirectDepsProxyAllowDisabled calls visit for each direct dependency. If there are 142 // multiple direct dependencies on the same module visit will be called multiple times on 143 // that module and OtherModuleDependencyTag will return a different tag for each. 144 // 145 // The ModuleProxy passed to the visit function should not be retained outside of the visit function, it may be 146 // invalidated by future mutators. 147 VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) 148 149 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) 150 151 VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) 152 153 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are 154 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and 155 // OtherModuleDependencyTag will return a different tag for each. It skips any 156 // dependencies that are not an android.Module. 157 // 158 // The Module passed to the visit function should not be retained outside of the visit function, it may be 159 // invalidated by future mutators. 160 VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) 161 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module 162 VisitDepsDepthFirst(visit func(Module)) 163 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module 164 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) 165 166 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may 167 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the 168 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited 169 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips 170 // any dependencies that are not an android.Module. 171 // 172 // The Modules passed to the visit function should not be retained outside of the visit function, they may be 173 // invalidated by future mutators. 174 WalkDeps(visit func(child, parent Module) bool) 175 176 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may 177 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the 178 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited 179 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips 180 // any dependencies that are not an android.Module. 181 // 182 // The Modules passed to the visit function should not be retained outside of the visit function, they may be 183 // invalidated by future mutators. 184 WalkDepsProxy(visit func(child, parent ModuleProxy) bool) 185 186 // GetWalkPath is supposed to be called in visit function passed in WalkDeps() 187 // and returns a top-down dependency path from a start module to current child module. 188 GetWalkPath() []Module 189 190 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in 191 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the 192 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are 193 // only done once for all variants of a module. 194 PrimaryModule() Module 195 196 // FinalModule returns the last variant of the current module. Variants of a module are always visited in 197 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all 198 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform 199 // singleton actions that are only done once for all variants of a module. 200 FinalModule() Module 201 202 // IsFinalModule returns if the current module is the last variant. Variants of a module are always visited in 203 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all 204 // variants using VisitAllModuleVariants if the current module is the last one. This can be used to perform 205 // singleton actions that are only done once for all variants of a module. 206 IsFinalModule(module Module) bool 207 208 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always 209 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read 210 // from all variants if the current module is the last one. Otherwise, care must be taken to not access any 211 // data modified by the current mutator. 212 VisitAllModuleVariants(visit func(Module)) 213 214 // VisitAllModuleVariantProxies calls visit for each variant of the current module. Variants of a module are always 215 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read 216 // from all variants if the current module is the last one. Otherwise, care must be taken to not access any 217 // data modified by the current mutator. 218 VisitAllModuleVariantProxies(visit func(proxy ModuleProxy)) 219 220 // GetTagPath is supposed to be called in visit function passed in WalkDeps() 221 // and returns a top-down dependency tags path from a start module to current child module. 222 // It has one less entry than GetWalkPath() as it contains the dependency tags that 223 // exist between each adjacent pair of modules in the GetWalkPath(). 224 // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1] 225 GetTagPath() []blueprint.DependencyTag 226 227 // GetPathString is supposed to be called in visit function passed in WalkDeps() 228 // and returns a multi-line string showing the modules and dependency tags 229 // among them along the top-down dependency path from a start module to current child module. 230 // skipFirst when set to true, the output doesn't include the start module, 231 // which is already printed when this function is used along with ModuleErrorf(). 232 GetPathString(skipFirst bool) string 233 234 AddMissingDependencies(missingDeps []string) 235 236 // getMissingDependencies returns the list of missing dependencies. 237 // Calling this function prevents adding new dependencies. 238 getMissingDependencies() []string 239 240 // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context 241 // can be used to evaluate the final value of Configurable properties. 242 EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue 243} 244 245type baseModuleContext struct { 246 bp blueprint.BaseModuleContext 247 earlyModuleContext 248 archModuleContext 249 250 walkPath []Module 251 tagPath []blueprint.DependencyTag 252 253 strictVisitDeps bool // If true, enforce that all dependencies are enabled 254 255} 256 257func getWrappedModule(module blueprint.Module) blueprint.Module { 258 if mp, isProxy := module.(ModuleProxy); isProxy { 259 return mp.module 260 } 261 return module 262} 263 264func (b *baseModuleContext) EqualModules(m1, m2 Module) bool { 265 return b.bp.EqualModules(getWrappedModule(m1), getWrappedModule(m2)) 266} 267 268func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string { 269 return b.bp.OtherModuleName(getWrappedModule(m)) 270} 271func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { 272 return b.bp.OtherModuleDir(getWrappedModule(m)) 273} 274func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) { 275 b.bp.OtherModuleErrorf(getWrappedModule(m), fmt, args...) 276} 277func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag { 278 return b.bp.OtherModuleDependencyTag(getWrappedModule(m)) 279} 280func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) } 281func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool { 282 return b.bp.OtherModuleDependencyVariantExists(variations, name) 283} 284func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool { 285 return b.bp.OtherModuleFarDependencyVariantExists(variations, name) 286} 287func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool { 288 return b.bp.OtherModuleReverseDependencyVariantExists(name) 289} 290func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string { 291 return b.bp.OtherModuleType(getWrappedModule(m)) 292} 293 294func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) { 295 return b.bp.OtherModuleProvider(m, provider) 296} 297 298func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool { 299 return b.bp.OtherModuleIsAutoGenerated(m) 300} 301 302func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) { 303 return b.bp.Provider(provider) 304} 305 306func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) { 307 b.bp.SetProvider(provider, value) 308} 309 310func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module { 311 if module := b.bp.GetDirectDepWithTag(name, tag); module != nil { 312 return module.(Module) 313 } 314 return nil 315} 316 317func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext { 318 return b.bp 319} 320 321func (b *baseModuleContext) AddMissingDependencies(deps []string) { 322 if deps != nil { 323 missingDeps := &b.Module().base().commonProperties.MissingDeps 324 *missingDeps = append(*missingDeps, deps...) 325 *missingDeps = FirstUniqueStrings(*missingDeps) 326 } 327} 328 329func (b *baseModuleContext) checkedMissingDeps() bool { 330 return b.Module().base().commonProperties.CheckedMissingDeps 331} 332 333func (b *baseModuleContext) getMissingDependencies() []string { 334 checked := &b.Module().base().commonProperties.CheckedMissingDeps 335 *checked = true 336 var missingDeps []string 337 missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...) 338 missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...) 339 missingDeps = FirstUniqueStrings(missingDeps) 340 return missingDeps 341} 342 343type AllowDisabledModuleDependency interface { 344 blueprint.DependencyTag 345 AllowDisabledModuleDependency(target Module) bool 346 AllowDisabledModuleDependencyProxy(ctx OtherModuleProviderContext, target ModuleProxy) bool 347} 348 349type AlwaysAllowDisabledModuleDependencyTag struct{} 350 351func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool { 352 return true 353} 354 355func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependencyProxy(OtherModuleProviderContext, ModuleProxy) bool { 356 return true 357} 358 359func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module { 360 aModule, _ := module.(Module) 361 362 if !strict { 363 return aModule 364 } 365 366 if aModule == nil { 367 panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)) 368 } 369 370 if !aModule.Enabled(b) { 371 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) { 372 if b.Config().AllowMissingDependencies() { 373 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)}) 374 } else { 375 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule)) 376 } 377 } 378 return nil 379 } 380 return aModule 381} 382 383func (b *baseModuleContext) validateAndroidModuleProxy( 384 module blueprint.ModuleProxy, tag blueprint.DependencyTag, strict bool) *ModuleProxy { 385 aModule := ModuleProxy{module: module} 386 387 if !strict { 388 return &aModule 389 } 390 391 if !OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).Enabled { 392 if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) { 393 if b.Config().AllowMissingDependencies() { 394 b.AddMissingDependencies([]string{b.OtherModuleName(aModule)}) 395 } else { 396 b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule)) 397 } 398 } 399 return nil 400 } 401 402 return &aModule 403} 404 405type dep struct { 406 mod blueprint.Module 407 tag blueprint.DependencyTag 408} 409 410func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep { 411 var deps []dep 412 b.VisitDirectDeps(func(module Module) { 413 if module.base().BaseModuleName() == name { 414 returnedTag := b.bp.OtherModuleDependencyTag(module) 415 if tag == nil || returnedTag == tag { 416 deps = append(deps, dep{module, returnedTag}) 417 } 418 } 419 }) 420 return deps 421} 422 423func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) { 424 deps := b.getDirectDepsInternal(name, tag) 425 if len(deps) == 1 { 426 return deps[0].mod, deps[0].tag 427 } else if len(deps) >= 2 { 428 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q", 429 name, b.ModuleName())) 430 } else { 431 return nil, nil 432 } 433} 434 435func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) { 436 foundDeps := b.getDirectDepsInternal(name, nil) 437 deps := map[blueprint.Module]bool{} 438 for _, dep := range foundDeps { 439 deps[dep.mod] = true 440 } 441 if len(deps) == 1 { 442 return foundDeps[0].mod, foundDeps[0].tag 443 } else if len(deps) >= 2 { 444 // this could happen if two dependencies have the same name in different namespaces 445 // TODO(b/186554727): this should not occur if namespaces are handled within 446 // getDirectDepsInternal. 447 panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q", 448 name, b.ModuleName())) 449 } else { 450 return nil, nil 451 } 452} 453 454func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module { 455 var deps []Module 456 b.VisitDirectDeps(func(module Module) { 457 if b.bp.OtherModuleDependencyTag(module) == tag { 458 deps = append(deps, module) 459 } 460 }) 461 return deps 462} 463 464// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified 465// name, or nil if none exists. If there are multiple dependencies on the same module it returns the 466// first DependencyTag. 467func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) { 468 return b.getDirectDepFirstTag(name) 469} 470 471func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) { 472 b.bp.VisitDirectDeps(func(module blueprint.Module) { 473 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { 474 visit(aModule) 475 } 476 }) 477} 478 479func (b *baseModuleContext) VisitDirectDepsProxy(visit func(ModuleProxy)) { 480 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) { 481 if aModule := b.validateAndroidModuleProxy(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { 482 visit(*aModule) 483 } 484 }) 485} 486 487func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy ModuleProxy)) { 488 b.bp.VisitDirectDepsProxy(visitProxyAdaptor(visit)) 489} 490 491func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) { 492 b.bp.VisitDirectDeps(func(module blueprint.Module) { 493 if b.bp.OtherModuleDependencyTag(module) == tag { 494 if aModule := b.validateAndroidModule(module, tag, b.strictVisitDeps); aModule != nil { 495 visit(aModule) 496 } 497 } 498 }) 499} 500 501func (b *baseModuleContext) VisitDirectDepsProxyWithTag(tag blueprint.DependencyTag, visit func(proxy ModuleProxy)) { 502 b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) { 503 if b.bp.OtherModuleDependencyTag(module) == tag { 504 if aModule := b.validateAndroidModuleProxy(module, tag, b.strictVisitDeps); aModule != nil { 505 visit(*aModule) 506 } 507 } 508 }) 509} 510 511func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) { 512 b.bp.VisitDirectDepsIf( 513 // pred 514 func(module blueprint.Module) bool { 515 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { 516 return pred(aModule) 517 } else { 518 return false 519 } 520 }, 521 // visit 522 func(module blueprint.Module) { 523 visit(module.(Module)) 524 }) 525} 526 527func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) { 528 b.bp.VisitDepsDepthFirst(func(module blueprint.Module) { 529 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { 530 visit(aModule) 531 } 532 }) 533} 534 535func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) { 536 b.bp.VisitDepsDepthFirstIf( 537 // pred 538 func(module blueprint.Module) bool { 539 if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { 540 return pred(aModule) 541 } else { 542 return false 543 } 544 }, 545 // visit 546 func(module blueprint.Module) { 547 visit(module.(Module)) 548 }) 549} 550 551func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) { 552 b.walkPath = []Module{b.Module()} 553 b.tagPath = []blueprint.DependencyTag{} 554 b.bp.WalkDeps(func(child, parent blueprint.Module) bool { 555 childAndroidModule, _ := child.(Module) 556 parentAndroidModule, _ := parent.(Module) 557 if childAndroidModule != nil && parentAndroidModule != nil { 558 // record walkPath before visit 559 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule { 560 b.walkPath = b.walkPath[0 : len(b.walkPath)-1] 561 b.tagPath = b.tagPath[0 : len(b.tagPath)-1] 562 } 563 b.walkPath = append(b.walkPath, childAndroidModule) 564 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule)) 565 return visit(childAndroidModule, parentAndroidModule) 566 } else { 567 return false 568 } 569 }) 570} 571 572func (b *baseModuleContext) WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) { 573 b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}} 574 b.tagPath = []blueprint.DependencyTag{} 575 b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool { 576 childAndroidModule := ModuleProxy{child} 577 parentAndroidModule := ModuleProxy{parent} 578 // record walkPath before visit 579 for b.walkPath[len(b.walkPath)-1] != parentAndroidModule { 580 b.walkPath = b.walkPath[0 : len(b.walkPath)-1] 581 b.tagPath = b.tagPath[0 : len(b.tagPath)-1] 582 } 583 b.walkPath = append(b.walkPath, childAndroidModule) 584 b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule)) 585 return visit(childAndroidModule, parentAndroidModule) 586 }) 587} 588 589func (b *baseModuleContext) GetWalkPath() []Module { 590 return slices.Clone(b.walkPath) 591} 592 593func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag { 594 return b.tagPath 595} 596 597func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) { 598 b.bp.VisitAllModuleVariants(func(module blueprint.Module) { 599 visit(module.(Module)) 600 }) 601} 602 603func (b *baseModuleContext) VisitAllModuleVariantProxies(visit func(ModuleProxy)) { 604 b.bp.VisitAllModuleVariantProxies(visitProxyAdaptor(visit)) 605} 606 607func (b *baseModuleContext) PrimaryModule() Module { 608 return b.bp.PrimaryModule().(Module) 609} 610 611func (b *baseModuleContext) FinalModule() Module { 612 return b.bp.FinalModule().(Module) 613} 614 615func (b *baseModuleContext) IsFinalModule(module Module) bool { 616 return b.bp.IsFinalModule(module) 617} 618 619// IsMetaDependencyTag returns true for cross-cutting metadata dependencies. 620func IsMetaDependencyTag(tag blueprint.DependencyTag) bool { 621 if tag == licenseKindTag { 622 return true 623 } else if tag == licensesTag { 624 return true 625 } else if tag == AcDepTag { 626 return true 627 } 628 return false 629} 630 631// A regexp for removing boilerplate from BaseDependencyTag from the string representation of 632// a dependency tag. 633var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`) 634 635// PrettyPrintTag returns string representation of the tag, but prefers 636// custom String() method if available. 637func PrettyPrintTag(tag blueprint.DependencyTag) string { 638 // Use tag's custom String() method if available. 639 if stringer, ok := tag.(fmt.Stringer); ok { 640 return stringer.String() 641 } 642 643 // Otherwise, get a default string representation of the tag's struct. 644 tagString := fmt.Sprintf("%T: %+v", tag, tag) 645 646 // Remove the boilerplate from BaseDependencyTag as it adds no value. 647 tagString = tagCleaner.ReplaceAllString(tagString, "") 648 return tagString 649} 650 651func (b *baseModuleContext) GetPathString(skipFirst bool) string { 652 sb := strings.Builder{} 653 tagPath := b.GetTagPath() 654 walkPath := b.GetWalkPath() 655 if !skipFirst { 656 sb.WriteString(walkPath[0].String()) 657 } 658 for i, m := range walkPath[1:] { 659 sb.WriteString("\n") 660 sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i]))) 661 sb.WriteString(fmt.Sprintf(" -> %s", m.String())) 662 } 663 return sb.String() 664} 665 666func (m *baseModuleContext) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue { 667 return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(condition, property) 668} 669