1// Copyright 2014 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 blueprint 16 17import ( 18 "errors" 19 "fmt" 20 "path/filepath" 21 "sort" 22 "strings" 23 "sync" 24 "text/scanner" 25 26 "github.com/google/blueprint/parser" 27 "github.com/google/blueprint/pathtools" 28 "github.com/google/blueprint/proptools" 29) 30 31// A Module handles generating all of the Ninja build actions needed to build a 32// single module based on properties defined in a Blueprints file. Module 33// objects are initially created during the parse phase of a Context using one 34// of the registered module types (and the associated ModuleFactory function). 35// The Module's properties struct is automatically filled in with the property 36// values specified in the Blueprints file (see Context.RegisterModuleType for more 37// information on this). 38// 39// A Module can be split into multiple Modules by a Mutator. All existing 40// properties set on the module will be duplicated to the new Module, and then 41// modified as necessary by the Mutator. 42// 43// The Module implementation can access the build configuration as well as any 44// modules on which it depends (as defined by the "deps" property 45// specified in the Blueprints file, dynamically added by implementing the 46// (deprecated) DynamicDependerModule interface, or dynamically added by a 47// BottomUpMutator) using the ModuleContext passed to GenerateBuildActions. 48// This ModuleContext is also used to create Ninja build actions and to report 49// errors to the user. 50// 51// In addition to implementing the GenerateBuildActions method, a Module should 52// implement methods that provide dependant modules and singletons information 53// they need to generate their build actions. These methods will only be called 54// after GenerateBuildActions is called because the Context calls 55// GenerateBuildActions in dependency-order (and singletons are invoked after 56// all the Modules). The set of methods a Module supports will determine how 57// dependant Modules interact with it. 58// 59// For example, consider a Module that is responsible for generating a library 60// that other modules can link against. The library Module might implement the 61// following interface: 62// 63// type LibraryProducer interface { 64// LibraryFileName() string 65// } 66// 67// func IsLibraryProducer(module blueprint.Module) { 68// _, ok := module.(LibraryProducer) 69// return ok 70// } 71// 72// A binary-producing Module that depends on the library Module could then do: 73// 74// func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) { 75// ... 76// var libraryFiles []string 77// ctx.VisitDepsDepthFirstIf(IsLibraryProducer, 78// func(module blueprint.Module) { 79// libProducer := module.(LibraryProducer) 80// libraryFiles = append(libraryFiles, libProducer.LibraryFileName()) 81// }) 82// ... 83// } 84// 85// to build the list of library file names that should be included in its link 86// command. 87// 88// GenerateBuildActions may be called from multiple threads. It is guaranteed to 89// be called after it has finished being called on all dependencies and on all 90// variants of that appear earlier in the ModuleContext.VisitAllModuleVariants list. 91// Any accesses to global variables or to Module objects that are not dependencies 92// or variants of the current Module must be synchronized by the implementation of 93// GenerateBuildActions. 94type Module interface { 95 // Name returns a string used to uniquely identify each module. The return 96 // value must be unique across all modules. It is only called once, during 97 // initial blueprint parsing. To change the name later a mutator must call 98 // MutatorContext.Rename 99 // 100 // In most cases, Name should return the contents of a "name:" property from 101 // the blueprint file. An embeddable SimpleName object can be used for this 102 // case. 103 Name() string 104 105 // GenerateBuildActions is called by the Context that created the Module 106 // during its generate phase. This call should generate all Ninja build 107 // actions (rules, pools, and build statements) needed to build the module. 108 GenerateBuildActions(ModuleContext) 109} 110 111type ModuleProxy struct { 112 module Module 113} 114 115func CreateModuleProxy(module Module) ModuleProxy { 116 return ModuleProxy{ 117 module: module, 118 } 119} 120 121func (m ModuleProxy) Name() string { 122 return m.module.Name() 123} 124 125func (m ModuleProxy) GenerateBuildActions(context ModuleContext) { 126 m.module.GenerateBuildActions(context) 127} 128 129// A DynamicDependerModule is a Module that may add dependencies that do not 130// appear in its "deps" property. Any Module that implements this interface 131// will have its DynamicDependencies method called by the Context that created 132// it during generate phase. 133// 134// Deprecated, use a BottomUpMutator instead 135type DynamicDependerModule interface { 136 Module 137 138 // DynamicDependencies is called by the Context that created the 139 // DynamicDependerModule during its generate phase. This call should return 140 // the list of module names that the DynamicDependerModule depends on 141 // dynamically. Module names that already appear in the "deps" property may 142 // but do not need to be included in the returned list. 143 DynamicDependencies(DynamicDependerModuleContext) []string 144} 145 146type EarlyModuleContext interface { 147 // Module returns the current module as a Module. It should rarely be necessary, as the module already has a 148 // reference to itself. 149 Module() Module 150 151 // ModuleName returns the name of the module. This is generally the value that was returned by Module.Name() when 152 // the module was created, but may have been modified by calls to BottomUpMutatorContext.Rename. 153 ModuleName() string 154 155 // ModuleDir returns the path to the directory that contains the definition of the module. 156 ModuleDir() string 157 158 // ModuleType returns the name of the module type that was used to create the module, as specified in 159 // Context.RegisterModuleType(). 160 ModuleType() string 161 162 // ModuleTags returns the tags for this module that should be passed to 163 // ninja for analysis. For example: 164 // [ 165 // "module_name": "libfoo", 166 // "module_type": "cc_library", 167 // ] 168 ModuleTags() map[string]string 169 170 // BlueprintsFile returns the name of the blueprint file that contains the definition of this 171 // module. 172 BlueprintsFile() string 173 174 // Config returns the config object that was passed to Context.PrepareBuildActions. 175 Config() interface{} 176 177 // ContainsProperty returns true if the specified property name was set in the module definition. 178 ContainsProperty(name string) bool 179 180 // Errorf reports an error at the specified position of the module definition file. 181 Errorf(pos scanner.Position, fmt string, args ...interface{}) 182 183 // ModuleErrorf reports an error at the line number of the module type in the module definition. 184 ModuleErrorf(fmt string, args ...interface{}) 185 186 // PropertyErrorf reports an error at the line number of a property in the module definition. 187 PropertyErrorf(property, fmt string, args ...interface{}) 188 189 // OtherModulePropertyErrorf reports an error at the line number of a property in the given module definition. 190 OtherModulePropertyErrorf(logicModule Module, property string, format string, args ...interface{}) 191 192 // Failed returns true if any errors have been reported. In most cases the module can continue with generating 193 // build rules after an error, allowing it to report additional errors in a single run, but in cases where the error 194 // has prevented the module from creating necessary data it can return early when Failed returns true. 195 Failed() bool 196 197 // GlobWithDeps returns a list of files and directories that match the 198 // specified pattern but do not match any of the patterns in excludes. 199 // Any directories will have a '/' suffix. It also adds efficient 200 // dependencies to rerun the primary builder whenever a file matching 201 // the pattern as added or removed, without rerunning if a file that 202 // does not match the pattern is added to a searched directory. 203 GlobWithDeps(pattern string, excludes []string) ([]string, error) 204 205 // Fs returns a pathtools.Filesystem that can be used to interact with files. Using the Filesystem interface allows 206 // the module to be used in build system tests that run against a mock filesystem. 207 Fs() pathtools.FileSystem 208 209 // AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest. The 210 // primary builder will be rerun whenever the specified files are modified. 211 AddNinjaFileDeps(deps ...string) 212 213 moduleInfo() *moduleInfo 214 215 error(err error) 216 217 // Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the 218 // default SimpleNameInterface if Context.SetNameInterface was not called. 219 Namespace() Namespace 220 221 // ModuleFactories returns a map of all of the global ModuleFactories by name. 222 ModuleFactories() map[string]ModuleFactory 223 224 // HasMutatorFinished returns true if the given mutator has finished running. 225 // It will panic if given an invalid mutator name. 226 HasMutatorFinished(mutatorName string) bool 227} 228 229type BaseModuleContext interface { 230 EarlyModuleContext 231 232 // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if 233 // none exists. It panics if the dependency does not have the specified tag. 234 GetDirectDepWithTag(name string, tag DependencyTag) Module 235 236 // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified 237 // name, or nil if none exists. If there are multiple dependencies on the same module it returns 238 // the first DependencyTag. 239 GetDirectDep(name string) (Module, DependencyTag) 240 241 // VisitDirectDeps calls visit for each direct dependency. If there are multiple direct dependencies on the same 242 // module visit will be called multiple times on that module and OtherModuleDependencyTag will return a different 243 // tag for each. 244 // 245 // The Module passed to the visit function should not be retained outside of the visit function, it may be 246 // invalidated by future mutators. 247 VisitDirectDeps(visit func(Module)) 248 249 VisitDirectDepsProxy(visit func(proxy ModuleProxy)) 250 251 // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are 252 // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and 253 // OtherModuleDependencyTag will return a different tag for each. 254 // 255 // The Module passed to the visit function should not be retained outside of the visit function, it may be 256 // invalidated by future mutators. 257 VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) 258 259 // VisitDepsDepthFirst calls visit for each transitive dependency, traversing the dependency tree in depth first 260 // order. visit will only be called once for any given module, even if there are multiple paths through the 261 // dependency tree to the module or multiple direct dependencies with different tags. OtherModuleDependencyTag will 262 // return the tag for the first path found to the module. 263 // 264 // The Module passed to the visit function should not be retained outside of the visit function, it may be 265 // invalidated by future mutators. 266 VisitDepsDepthFirst(visit func(Module)) 267 268 // VisitDepsDepthFirstIf calls pred for each transitive dependency, and if pred returns true calls visit, traversing 269 // the dependency tree in depth first order. visit will only be called once for any given module, even if there are 270 // multiple paths through the dependency tree to the module or multiple direct dependencies with different tags. 271 // OtherModuleDependencyTag will return the tag for the first path found to the module. The return value of pred 272 // does not affect which branches of the tree are traversed. 273 // 274 // The Module passed to the visit function should not be retained outside of the visit function, it may be 275 // invalidated by future mutators. 276 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) 277 278 // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may 279 // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the 280 // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited 281 // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. 282 // 283 // The Modules passed to the visit function should not be retained outside of the visit function, they may be 284 // invalidated by future mutators. 285 WalkDeps(visit func(Module, Module) bool) 286 287 WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) 288 289 // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in 290 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the 291 // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are 292 // only done once for all variants of a module. 293 PrimaryModule() Module 294 295 // FinalModule returns the last variant of the current module. Variants of a module are always visited in 296 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all 297 // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform 298 // singleton actions that are only done once for all variants of a module. 299 FinalModule() Module 300 301 // IsFinalModule returns if the current module is the last variant. Variants of a module are always visited in 302 // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all 303 // variants using VisitAllModuleVariants if the current module is the last one. This can be used to perform 304 // singleton actions that are only done once for all variants of a module. 305 IsFinalModule(module Module) bool 306 307 // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always 308 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read 309 // from all variants if the current module is the last one. Otherwise, care must be taken to not access any 310 // data modified by the current mutator. 311 VisitAllModuleVariants(visit func(Module)) 312 313 // VisitAllModuleVariantProxies calls visit for each variant of the current module. Variants of a module are always 314 // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read 315 // from all variants if the current module is the last one. Otherwise, care must be taken to not access any 316 // data modified by the current mutator. 317 VisitAllModuleVariantProxies(visit func(proxy ModuleProxy)) 318 319 // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information. 320 // It is intended for use inside the visit functions of Visit* and WalkDeps. 321 OtherModuleName(m Module) string 322 323 // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information. 324 // It is intended for use inside the visit functions of Visit* and WalkDeps. 325 OtherModuleDir(m Module) string 326 327 // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information. 328 // It is intended for use inside the visit functions of Visit* and WalkDeps. 329 OtherModuleType(m Module) string 330 331 // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information. 332 // It is intended for use inside the visit functions of Visit* and WalkDeps. 333 OtherModuleErrorf(m Module, fmt string, args ...interface{}) 334 335 // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency 336 // on the module. When called inside a Visit* method with current module being visited, and there are multiple 337 // dependencies on the module being visited, it returns the dependency tag used for the current dependency. 338 OtherModuleDependencyTag(m Module) DependencyTag 339 340 // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface 341 // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called. 342 OtherModuleExists(name string) bool 343 344 // ModuleFromName returns (module, true) if a module exists by the given name and same context namespace, 345 // or (nil, false) if it does not exist. It panics if there is either more than one 346 // module of the given name, or if the given name refers to an alias instead of a module. 347 // There are no guarantees about which variant of the module will be returned. 348 // Prefer retrieving the module using GetDirectDep or a visit function, when possible, as 349 // this will guarantee the appropriate module-variant dependency is returned. 350 // 351 // WARNING: This should _only_ be used within the context of bp2build, where variants and 352 // dependencies are not created. 353 ModuleFromName(name string) (Module, bool) 354 355 // OtherModuleDependencyVariantExists returns true if a module with the 356 // specified name and variant exists. The variant must match the given 357 // variations. It must also match all the non-local variations of the current 358 // module. In other words, it checks for the module that AddVariationDependencies 359 // would add a dependency on with the same arguments. 360 OtherModuleDependencyVariantExists(variations []Variation, name string) bool 361 362 // OtherModuleFarDependencyVariantExists returns true if a module with the 363 // specified name and variant exists. The variant must match the given 364 // variations, but not the non-local variations of the current module. In 365 // other words, it checks for the module that AddFarVariationDependencies 366 // would add a dependency on with the same arguments. 367 OtherModuleFarDependencyVariantExists(variations []Variation, name string) bool 368 369 // OtherModuleReverseDependencyVariantExists returns true if a module with the 370 // specified name exists with the same variations as the current module. In 371 // other words, it checks for the module that AddReverseDependency would add a 372 // dependency on with the same argument. 373 OtherModuleReverseDependencyVariantExists(name string) bool 374 375 // OtherModuleProvider returns the value for a provider for the given module. If the value is 376 // not set it returns nil and false. The value returned may be a deep copy of the value originally 377 // passed to SetProvider. 378 // 379 // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead. 380 OtherModuleProvider(m Module, provider AnyProviderKey) (any, bool) 381 382 // OtherModuleIsAutoGenerated returns true if a module has been generated from another module, 383 // instead of being defined in Android.bp file 384 OtherModuleIsAutoGenerated(m Module) bool 385 386 // Provider returns the value for a provider for the current module. If the value is 387 // not set it returns nil and false. It panics if called before the appropriate 388 // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep 389 // copy of the value originally passed to SetProvider. 390 // 391 // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead. 392 Provider(provider AnyProviderKey) (any, bool) 393 394 // SetProvider sets the value for a provider for the current module. It panics if not called 395 // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value 396 // is not of the appropriate type, or if the value has already been set. The value should not 397 // be modified after being passed to SetProvider. 398 // 399 // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead. 400 SetProvider(provider AnyProviderKey, value any) 401 402 EarlyGetMissingDependencies() []string 403 404 EqualModules(m1, m2 Module) bool 405 406 base() *baseModuleContext 407} 408 409type DynamicDependerModuleContext BottomUpMutatorContext 410 411type ModuleContext interface { 412 BaseModuleContext 413 414 // ModuleSubDir returns a unique name for the current variant of a module that can be used as part of the path 415 // to ensure that each variant of a module gets its own intermediates directory to write to. 416 ModuleSubDir() string 417 418 ModuleCacheKey() string 419 420 // Variable creates a new ninja variable scoped to the module. It can be referenced by calls to Rule and Build 421 // in the same module. 422 Variable(pctx PackageContext, name, value string) 423 424 // Rule creates a new ninja rule scoped to the module. It can be referenced by calls to Build in the same module. 425 Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule 426 427 // Build creates a new ninja build statement. 428 Build(pctx PackageContext, params BuildParams) 429 430 // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods, 431 // but do not exist. It can be used with Context.SetAllowMissingDependencies to allow the primary builder to 432 // handle missing dependencies on its own instead of having Blueprint treat them as an error. 433 GetMissingDependencies() []string 434} 435 436var _ BaseModuleContext = (*baseModuleContext)(nil) 437 438type baseModuleContext struct { 439 context *Context 440 config interface{} 441 module *moduleInfo 442 errs []error 443 visitingParent *moduleInfo 444 visitingDep depInfo 445 ninjaFileDeps []string 446} 447 448func (d *baseModuleContext) moduleInfo() *moduleInfo { 449 return d.module 450} 451 452func (d *baseModuleContext) Module() Module { 453 return d.module.logicModule 454} 455 456func (d *baseModuleContext) ModuleName() string { 457 return d.module.Name() 458} 459 460func (d *baseModuleContext) ModuleType() string { 461 return d.module.typeName 462} 463 464func (d *baseModuleContext) ModuleTags() map[string]string { 465 return map[string]string{ 466 "module_name": d.ModuleName(), 467 "module_type": d.ModuleType(), 468 } 469} 470 471func (d *baseModuleContext) ContainsProperty(name string) bool { 472 _, ok := d.module.propertyPos[name] 473 return ok 474} 475 476func (d *baseModuleContext) ModuleDir() string { 477 return filepath.Dir(d.module.relBlueprintsFile) 478} 479 480func (d *baseModuleContext) BlueprintsFile() string { 481 return d.module.relBlueprintsFile 482} 483 484func (d *baseModuleContext) Config() interface{} { 485 return d.config 486} 487 488func (d *baseModuleContext) error(err error) { 489 if err != nil { 490 d.errs = append(d.errs, err) 491 } 492} 493 494func (d *baseModuleContext) Errorf(pos scanner.Position, 495 format string, args ...interface{}) { 496 497 d.error(&BlueprintError{ 498 Err: fmt.Errorf(format, args...), 499 Pos: pos, 500 }) 501} 502 503func (d *baseModuleContext) ModuleErrorf(format string, 504 args ...interface{}) { 505 506 d.error(d.context.moduleErrorf(d.module, format, args...)) 507} 508 509func (d *baseModuleContext) PropertyErrorf(property, format string, 510 args ...interface{}) { 511 512 d.error(d.context.PropertyErrorf(d.module.logicModule, property, format, args...)) 513} 514 515func (d *baseModuleContext) OtherModulePropertyErrorf(logicModule Module, property string, format string, 516 args ...interface{}) { 517 518 d.error(d.context.PropertyErrorf(logicModule, property, format, args...)) 519} 520 521func (d *baseModuleContext) Failed() bool { 522 return len(d.errs) > 0 523} 524 525func (d *baseModuleContext) GlobWithDeps(pattern string, 526 excludes []string) ([]string, error) { 527 return d.context.glob(pattern, excludes) 528} 529 530func (d *baseModuleContext) Fs() pathtools.FileSystem { 531 return d.context.fs 532} 533 534func (d *baseModuleContext) Namespace() Namespace { 535 return d.context.nameInterface.GetNamespace(newNamespaceContext(d.module)) 536} 537 538func (d *baseModuleContext) HasMutatorFinished(mutatorName string) bool { 539 return d.context.HasMutatorFinished(mutatorName) 540} 541 542var _ ModuleContext = (*moduleContext)(nil) 543 544type moduleContext struct { 545 baseModuleContext 546 scope *localScope 547 actionDefs localBuildActions 548 handledMissingDeps bool 549} 550 551func (m *baseModuleContext) EqualModules(m1, m2 Module) bool { 552 return getWrappedModule(m1) == getWrappedModule(m2) 553} 554 555func (m *baseModuleContext) OtherModuleName(logicModule Module) string { 556 module := m.context.moduleInfo[getWrappedModule(logicModule)] 557 return module.Name() 558} 559 560func (m *baseModuleContext) OtherModuleDir(logicModule Module) string { 561 module := m.context.moduleInfo[getWrappedModule(logicModule)] 562 return filepath.Dir(module.relBlueprintsFile) 563} 564 565func (m *baseModuleContext) OtherModuleType(logicModule Module) string { 566 module := m.context.moduleInfo[getWrappedModule(logicModule)] 567 return module.typeName 568} 569 570func (m *baseModuleContext) OtherModuleErrorf(logicModule Module, format string, 571 args ...interface{}) { 572 573 module := m.context.moduleInfo[getWrappedModule(logicModule)] 574 m.errs = append(m.errs, &ModuleError{ 575 BlueprintError: BlueprintError{ 576 Err: fmt.Errorf(format, args...), 577 Pos: module.pos, 578 }, 579 module: module, 580 }) 581} 582 583func getWrappedModule(module Module) Module { 584 if mp, isProxy := module.(ModuleProxy); isProxy { 585 return mp.module 586 } 587 return module 588} 589 590func (m *baseModuleContext) OtherModuleDependencyTag(logicModule Module) DependencyTag { 591 // fast path for calling OtherModuleDependencyTag from inside VisitDirectDeps 592 if m.visitingDep.module != nil && getWrappedModule(logicModule) == m.visitingDep.module.logicModule { 593 return m.visitingDep.tag 594 } 595 596 if m.visitingParent == nil { 597 return nil 598 } 599 600 for _, dep := range m.visitingParent.directDeps { 601 if dep.module.logicModule == getWrappedModule(logicModule) { 602 return dep.tag 603 } 604 } 605 606 return nil 607} 608 609func (m *baseModuleContext) ModuleFromName(name string) (Module, bool) { 610 moduleGroup, exists := m.context.nameInterface.ModuleFromName(name, m.module.namespace()) 611 if exists { 612 if len(moduleGroup.modules) != 1 { 613 panic(fmt.Errorf("Expected exactly one module named %q, but got %d", name, len(moduleGroup.modules))) 614 } 615 moduleInfo := moduleGroup.modules[0] 616 if moduleInfo != nil { 617 return moduleInfo.logicModule, true 618 } else { 619 panic(fmt.Errorf(`Expected actual module named %q, but group did not contain a module. 620 There may instead be an alias by that name.`, name)) 621 } 622 } 623 return nil, exists 624} 625 626func (m *baseModuleContext) OtherModuleExists(name string) bool { 627 _, exists := m.context.nameInterface.ModuleFromName(name, m.module.namespace()) 628 return exists 629} 630 631func (m *baseModuleContext) OtherModuleDependencyVariantExists(variations []Variation, name string) bool { 632 possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace()) 633 if possibleDeps == nil { 634 return false 635 } 636 found, _, errs := m.context.findVariant(m.module, m.config, possibleDeps, variations, false, false) 637 if errs != nil { 638 panic(errors.Join(errs...)) 639 } 640 return found != nil 641} 642 643func (m *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []Variation, name string) bool { 644 possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace()) 645 if possibleDeps == nil { 646 return false 647 } 648 found, _, errs := m.context.findVariant(m.module, m.config, possibleDeps, variations, true, false) 649 if errs != nil { 650 panic(errors.Join(errs...)) 651 } 652 return found != nil 653} 654 655func (m *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool { 656 possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace()) 657 if possibleDeps == nil { 658 return false 659 } 660 found, _, errs := m.context.findVariant(m.module, m.config, possibleDeps, nil, false, true) 661 if errs != nil { 662 panic(errors.Join(errs...)) 663 } 664 return found != nil 665} 666 667func (m *baseModuleContext) OtherModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) { 668 module := m.context.moduleInfo[getWrappedModule(logicModule)] 669 return m.context.provider(module, provider.provider()) 670} 671 672func (m *baseModuleContext) Provider(provider AnyProviderKey) (any, bool) { 673 return m.context.provider(m.module, provider.provider()) 674} 675 676func (m *baseModuleContext) SetProvider(provider AnyProviderKey, value interface{}) { 677 m.context.setProvider(m.module, provider.provider(), value) 678} 679 680func (m *moduleContext) cacheModuleBuildActions(key *BuildActionCacheKey) { 681 var providers []CachedProvider 682 for i, p := range m.module.providers { 683 if p != nil && providerRegistry[i].mutator == "" { 684 providers = append(providers, 685 CachedProvider{ 686 Id: providerRegistry[i], 687 Value: &p, 688 }) 689 } 690 } 691 692 // These show up in the ninja file, so we need to cache these to ensure we 693 // re-generate ninja file if they changed. 694 relPos := m.module.pos 695 relPos.Filename = m.module.relBlueprintsFile 696 data := BuildActionCachedData{ 697 Providers: providers, 698 Pos: &relPos, 699 } 700 701 m.context.updateBuildActionsCache(key, &data) 702} 703 704func (m *moduleContext) restoreModuleBuildActions() (bool, *BuildActionCacheKey) { 705 // Whether the incremental flag is set and the module type supports 706 // incremental, this will decide weather to cache the data for the module. 707 incrementalEnabled := false 708 // Whether the above conditions are true and we can try to restore from 709 // the cache for this module, i.e., no env, product variables and Soong 710 // code changes. 711 incrementalAnalysis := false 712 var cacheKey *BuildActionCacheKey = nil 713 if m.context.GetIncrementalEnabled() { 714 if im, ok := m.module.logicModule.(Incremental); ok { 715 incrementalEnabled = im.IncrementalSupported() 716 incrementalAnalysis = m.context.GetIncrementalAnalysis() && incrementalEnabled 717 } 718 } 719 if incrementalEnabled { 720 hash, err := proptools.CalculateHash(m.module.properties) 721 if err != nil { 722 panic(newPanicErrorf(err, "failed to calculate properties hash")) 723 } 724 cacheInput := new(BuildActionCacheInput) 725 cacheInput.PropertiesHash = hash 726 m.VisitDirectDeps(func(module Module) { 727 cacheInput.ProvidersHash = 728 append(cacheInput.ProvidersHash, m.context.moduleInfo[module].providerInitialValueHashes) 729 }) 730 hash, err = proptools.CalculateHash(&cacheInput) 731 if err != nil { 732 panic(newPanicErrorf(err, "failed to calculate cache input hash")) 733 } 734 cacheKey = &BuildActionCacheKey{ 735 Id: m.ModuleCacheKey(), 736 InputHash: hash, 737 } 738 m.module.buildActionCacheKey = cacheKey 739 } 740 741 restored := false 742 if incrementalAnalysis && cacheKey != nil { 743 // Try to restore from cache if there is a cache hit 744 data := m.context.getBuildActionsFromCache(cacheKey) 745 relPos := m.module.pos 746 relPos.Filename = m.module.relBlueprintsFile 747 if data != nil && data.Pos != nil && relPos == *data.Pos { 748 for _, provider := range data.Providers { 749 m.context.setProvider(m.module, provider.Id, *provider.Value) 750 } 751 m.module.incrementalRestored = true 752 m.module.orderOnlyStrings = data.OrderOnlyStrings 753 restored = true 754 } 755 } 756 757 return restored, cacheKey 758} 759 760func (m *baseModuleContext) GetDirectDep(name string) (Module, DependencyTag) { 761 for _, dep := range m.module.directDeps { 762 if dep.module.Name() == name { 763 return dep.module.logicModule, dep.tag 764 } 765 } 766 767 return nil, nil 768} 769 770func (m *baseModuleContext) GetDirectDepWithTag(name string, tag DependencyTag) Module { 771 var deps []depInfo 772 for _, dep := range m.module.directDeps { 773 if dep.module.Name() == name { 774 if dep.tag == tag { 775 return dep.module.logicModule 776 } 777 deps = append(deps, dep) 778 } 779 } 780 781 if len(deps) != 0 { 782 panic(fmt.Errorf("Unable to find dependency %q with requested tag %#v. Found: %#v", deps[0].module, tag, deps)) 783 } 784 785 return nil 786} 787 788func (m *baseModuleContext) VisitDirectDeps(visit func(Module)) { 789 defer func() { 790 if r := recover(); r != nil { 791 panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s", 792 m.module, funcName(visit), m.visitingDep.module)) 793 } 794 }() 795 796 m.visitingParent = m.module 797 798 for _, dep := range m.module.directDeps { 799 m.visitingDep = dep 800 visit(dep.module.logicModule) 801 } 802 803 m.visitingParent = nil 804 m.visitingDep = depInfo{} 805} 806 807func (m *baseModuleContext) VisitDirectDepsProxy(visit func(proxy ModuleProxy)) { 808 defer func() { 809 if r := recover(); r != nil { 810 panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s", 811 m.module, funcName(visit), m.visitingDep.module)) 812 } 813 }() 814 815 m.visitingParent = m.module 816 817 for _, dep := range m.module.directDeps { 818 m.visitingDep = dep 819 visit(ModuleProxy{dep.module.logicModule}) 820 } 821 822 m.visitingParent = nil 823 m.visitingDep = depInfo{} 824} 825 826func (m *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) { 827 defer func() { 828 if r := recover(); r != nil { 829 panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s", 830 m.module, funcName(pred), funcName(visit), m.visitingDep.module)) 831 } 832 }() 833 834 m.visitingParent = m.module 835 836 for _, dep := range m.module.directDeps { 837 m.visitingDep = dep 838 if pred(dep.module.logicModule) { 839 visit(dep.module.logicModule) 840 } 841 } 842 843 m.visitingParent = nil 844 m.visitingDep = depInfo{} 845} 846 847func (m *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) { 848 defer func() { 849 if r := recover(); r != nil { 850 panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s", 851 m.module, funcName(visit), m.visitingDep.module)) 852 } 853 }() 854 855 m.context.walkDeps(m.module, false, nil, func(dep depInfo, parent *moduleInfo) { 856 m.visitingParent = parent 857 m.visitingDep = dep 858 visit(dep.module.logicModule) 859 }) 860 861 m.visitingParent = nil 862 m.visitingDep = depInfo{} 863} 864 865func (m *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, 866 visit func(Module)) { 867 868 defer func() { 869 if r := recover(); r != nil { 870 panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s", 871 m.module, funcName(pred), funcName(visit), m.visitingDep.module)) 872 } 873 }() 874 875 m.context.walkDeps(m.module, false, nil, func(dep depInfo, parent *moduleInfo) { 876 if pred(dep.module.logicModule) { 877 m.visitingParent = parent 878 m.visitingDep = dep 879 visit(dep.module.logicModule) 880 } 881 }) 882 883 m.visitingParent = nil 884 m.visitingDep = depInfo{} 885} 886 887func (m *baseModuleContext) WalkDeps(visit func(child, parent Module) bool) { 888 m.context.walkDeps(m.module, true, func(dep depInfo, parent *moduleInfo) bool { 889 m.visitingParent = parent 890 m.visitingDep = dep 891 return visit(dep.module.logicModule, parent.logicModule) 892 }, nil) 893 894 m.visitingParent = nil 895 m.visitingDep = depInfo{} 896} 897 898func (m *baseModuleContext) WalkDepsProxy(visit func(child, parent ModuleProxy) bool) { 899 m.context.walkDeps(m.module, true, func(dep depInfo, parent *moduleInfo) bool { 900 m.visitingParent = parent 901 m.visitingDep = dep 902 return visit(ModuleProxy{dep.module.logicModule}, ModuleProxy{parent.logicModule}) 903 }, nil) 904 905 m.visitingParent = nil 906 m.visitingDep = depInfo{} 907} 908 909func (m *baseModuleContext) PrimaryModule() Module { 910 return m.module.group.modules.firstModule().logicModule 911} 912 913func (m *baseModuleContext) FinalModule() Module { 914 return m.module.group.modules.lastModule().logicModule 915} 916 917func (m *baseModuleContext) IsFinalModule(module Module) bool { 918 return m.module.group.modules.lastModule().logicModule == module 919} 920 921func (m *baseModuleContext) VisitAllModuleVariants(visit func(Module)) { 922 m.context.visitAllModuleVariants(m.module, visit) 923} 924 925func (m *baseModuleContext) VisitAllModuleVariantProxies(visit func(proxy ModuleProxy)) { 926 m.context.visitAllModuleVariants(m.module, visitProxyAdaptor(visit)) 927} 928 929func (m *baseModuleContext) AddNinjaFileDeps(deps ...string) { 930 m.ninjaFileDeps = append(m.ninjaFileDeps, deps...) 931} 932 933func (m *baseModuleContext) ModuleFactories() map[string]ModuleFactory { 934 return m.context.ModuleTypeFactories() 935} 936 937func (m *baseModuleContext) base() *baseModuleContext { 938 return m 939} 940 941func (m *baseModuleContext) OtherModuleIsAutoGenerated(logicModule Module) bool { 942 module := m.context.moduleInfo[getWrappedModule(logicModule)] 943 if module == nil { 944 panic(fmt.Errorf("Module %s not found in baseModuleContext", logicModule.Name())) 945 } 946 return module.createdBy != nil 947} 948 949func (m *moduleContext) ModuleSubDir() string { 950 return m.module.variant.name 951} 952 953func (m *moduleContext) ModuleCacheKey() string { 954 return m.module.ModuleCacheKey() 955} 956 957func (m *moduleContext) Variable(pctx PackageContext, name, value string) { 958 m.scope.ReparentTo(pctx) 959 960 v, err := m.scope.AddLocalVariable(name, value) 961 if err != nil { 962 panic(err) 963 } 964 965 m.actionDefs.variables = append(m.actionDefs.variables, v) 966} 967 968func (m *moduleContext) Rule(pctx PackageContext, name string, 969 params RuleParams, argNames ...string) Rule { 970 971 m.scope.ReparentTo(pctx) 972 973 r, err := m.scope.AddLocalRule(name, ¶ms, argNames...) 974 if err != nil { 975 panic(err) 976 } 977 978 m.actionDefs.rules = append(m.actionDefs.rules, r) 979 980 return r 981} 982 983func (m *moduleContext) Build(pctx PackageContext, params BuildParams) { 984 m.scope.ReparentTo(pctx) 985 986 def, err := parseBuildParams(m.scope, ¶ms, m.ModuleTags()) 987 if err != nil { 988 panic(err) 989 } 990 991 m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def) 992} 993 994func (m *moduleContext) GetMissingDependencies() []string { 995 m.handledMissingDeps = true 996 return m.module.missingDeps 997} 998 999func (m *baseModuleContext) EarlyGetMissingDependencies() []string { 1000 return m.module.missingDeps 1001} 1002 1003// 1004// MutatorContext 1005// 1006 1007type mutatorContext struct { 1008 baseModuleContext 1009 mutator *mutatorInfo 1010 reverseDeps []reverseDep 1011 rename []rename 1012 replace []replace 1013 newVariations moduleList // new variants of existing modules 1014 newModules []*moduleInfo // brand new modules 1015 defaultVariation *string 1016 pauseCh chan<- pauseSpec 1017} 1018 1019type TopDownMutatorContext interface { 1020 BaseModuleContext 1021} 1022 1023type BottomUpMutatorContext interface { 1024 BaseModuleContext 1025 1026 // AddDependency adds a dependency to the given module. It returns a slice of modules for each 1027 // dependency (some entries may be nil). Does not affect the ordering of the current mutator 1028 // pass, but will be ordered correctly for all future mutator passes. 1029 // 1030 // This method will pause until the new dependencies have had the current mutator called on them. 1031 AddDependency(module Module, tag DependencyTag, name ...string) []Module 1032 1033 // AddReverseDependency adds a dependency from the destination to the given module. 1034 // Does not affect the ordering of the current mutator pass, but will be ordered 1035 // correctly for all future mutator passes. All reverse dependencies for a destination module are 1036 // collected until the end of the mutator pass, sorted by name, and then appended to the destination 1037 // module's dependency list. May only be called by mutators that were marked with 1038 // UsesReverseDependencies during registration. 1039 AddReverseDependency(module Module, tag DependencyTag, name string) 1040 1041 // AddVariationDependencies adds deps as dependencies of the current module, but uses the variations 1042 // argument to select which variant of the dependency to use. It returns a slice of modules for 1043 // each dependency (some entries may be nil). A variant of the dependency must exist that matches 1044 // the all of the non-local variations of the current module, plus the variations argument. 1045 // 1046 // 1047 // This method will pause until the new dependencies have had the current mutator called on them. 1048 AddVariationDependencies([]Variation, DependencyTag, ...string) []Module 1049 1050 // AddReverseVariationDependency adds a dependency from the named module to the current 1051 // module. The given variations will be added to the current module's varations, and then the 1052 // result will be used to find the correct variation of the depending module, which must exist. 1053 // 1054 // Does not affect the ordering of the current mutator pass, but will be ordered 1055 // correctly for all future mutator passes. All reverse dependencies for a destination module are 1056 // collected until the end of the mutator pass, sorted by name, and then appended to the destination 1057 // module's dependency list. May only be called by mutators that were marked with 1058 // UsesReverseDependencies during registration. 1059 AddReverseVariationDependency([]Variation, DependencyTag, string) 1060 1061 // AddFarVariationDependencies adds deps as dependencies of the current module, but uses the 1062 // variations argument to select which variant of the dependency to use. It returns a slice of 1063 // modules for each dependency (some entries may be nil). A variant of the dependency must 1064 // exist that matches the variations argument, but may also have other variations. 1065 // For any unspecified variation the first variant will be used. 1066 // 1067 // Unlike AddVariationDependencies, the variations of the current module are ignored - the 1068 // dependency only needs to match the supplied variations. 1069 // 1070 // 1071 // This method will pause until the new dependencies have had the current mutator called on them. 1072 AddFarVariationDependencies([]Variation, DependencyTag, ...string) []Module 1073 1074 // ReplaceDependencies finds all the variants of the module with the specified name, then 1075 // replaces all dependencies onto those variants with the current variant of this module. 1076 // Replacements don't take effect until after the mutator pass is finished. May only 1077 // be called by mutators that were marked with UsesReplaceDependencies during registration. 1078 ReplaceDependencies(string) 1079 1080 // ReplaceDependenciesIf finds all the variants of the module with the specified name, then 1081 // replaces all dependencies onto those variants with the current variant of this module 1082 // as long as the supplied predicate returns true. 1083 // Replacements don't take effect until after the mutator pass is finished. May only 1084 // be called by mutators that were marked with UsesReplaceDependencies during registration. 1085 ReplaceDependenciesIf(string, ReplaceDependencyPredicate) 1086 1087 // Rename all variants of a module. The new name is not visible to calls to ModuleName, 1088 // AddDependency or OtherModuleName until after this mutator pass is complete. May only be called 1089 // by mutators that were marked with UsesRename during registration. 1090 Rename(name string) 1091 1092 // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies 1093 // the specified property structs to it as if the properties were set in a blueprint file. May only 1094 // be called by mutators that were marked with UsesCreateModule during registration. 1095 CreateModule(ModuleFactory, string, ...interface{}) Module 1096} 1097 1098// A Mutator function is called for each Module, and can modify properties on the modules. 1099// It is called after parsing all Blueprint files, but before generating any build rules, 1100// and is always called on dependencies before being called on the depending module. 1101// 1102// The Mutator function should only modify members of properties structs, and not 1103// members of the module struct itself, to ensure the modified values are copied 1104// if a second Mutator chooses to split the module a second time. 1105type TopDownMutator func(mctx TopDownMutatorContext) 1106type BottomUpMutator func(mctx BottomUpMutatorContext) 1107 1108// DependencyTag is an interface to an arbitrary object that embeds BaseDependencyTag. It can be 1109// used to transfer information on a dependency between the mutator that called AddDependency 1110// and the GenerateBuildActions method. 1111type DependencyTag interface { 1112 dependencyTag(DependencyTag) 1113} 1114 1115type BaseDependencyTag struct { 1116} 1117 1118func (BaseDependencyTag) dependencyTag(DependencyTag) { 1119} 1120 1121var _ DependencyTag = BaseDependencyTag{} 1122 1123func (mctx *mutatorContext) createVariationsWithTransition(variationNames []string, outgoingTransitions [][]string) []Module { 1124 return mctx.createVariations(variationNames, chooseDepByIndexes(mctx.mutator.name, outgoingTransitions)) 1125} 1126 1127func (mctx *mutatorContext) createVariations(variationNames []string, depChooser depChooser) []Module { 1128 var ret []Module 1129 modules, errs := mctx.context.createVariations(mctx.module, mctx.mutator, depChooser, variationNames) 1130 if len(errs) > 0 { 1131 mctx.errs = append(mctx.errs, errs...) 1132 } 1133 1134 for _, module := range modules { 1135 ret = append(ret, module.logicModule) 1136 } 1137 1138 if mctx.newVariations != nil { 1139 panic("module already has variations from this mutator") 1140 } 1141 mctx.newVariations = modules 1142 1143 if len(ret) != len(variationNames) { 1144 panic("oops!") 1145 } 1146 1147 return ret 1148} 1149 1150func (mctx *mutatorContext) Module() Module { 1151 return mctx.module.logicModule 1152} 1153 1154func (mctx *mutatorContext) AddDependency(module Module, tag DependencyTag, deps ...string) []Module { 1155 depInfos := make([]Module, 0, len(deps)) 1156 for _, dep := range deps { 1157 modInfo := mctx.context.moduleInfo[module] 1158 depInfo, errs := mctx.context.addVariationDependency(modInfo, mctx.mutator, mctx.config, nil, tag, dep, false) 1159 if len(errs) > 0 { 1160 mctx.errs = append(mctx.errs, errs...) 1161 } 1162 if !mctx.pause(depInfo) { 1163 // Pausing not supported by this mutator, new dependencies can't be returned. 1164 depInfo = nil 1165 } 1166 depInfos = append(depInfos, maybeLogicModule(depInfo)) 1167 } 1168 return depInfos 1169} 1170 1171func (mctx *mutatorContext) AddReverseDependency(module Module, tag DependencyTag, destName string) { 1172 if !mctx.mutator.usesReverseDependencies { 1173 panic(fmt.Errorf("method AddReverseDependency called from mutator that was not marked UsesReverseDependencies")) 1174 } 1175 1176 if _, ok := tag.(BaseDependencyTag); ok { 1177 panic("BaseDependencyTag is not allowed to be used directly!") 1178 } 1179 1180 destModule, errs := mctx.context.findReverseDependency(mctx.context.moduleInfo[module], mctx.config, nil, destName) 1181 if len(errs) > 0 { 1182 mctx.errs = append(mctx.errs, errs...) 1183 return 1184 } 1185 1186 if destModule == nil { 1187 // allowMissingDependencies is true and the module wasn't found 1188 return 1189 } 1190 1191 mctx.reverseDeps = append(mctx.reverseDeps, reverseDep{ 1192 destModule, 1193 depInfo{mctx.context.moduleInfo[module], tag}, 1194 }) 1195} 1196 1197func (mctx *mutatorContext) AddReverseVariationDependency(variations []Variation, tag DependencyTag, destName string) { 1198 if !mctx.mutator.usesReverseDependencies { 1199 panic(fmt.Errorf("method AddReverseVariationDependency called from mutator that was not marked UsesReverseDependencies")) 1200 } 1201 1202 if _, ok := tag.(BaseDependencyTag); ok { 1203 panic("BaseDependencyTag is not allowed to be used directly!") 1204 } 1205 1206 destModule, errs := mctx.context.findReverseDependency(mctx.module, mctx.config, variations, destName) 1207 if len(errs) > 0 { 1208 mctx.errs = append(mctx.errs, errs...) 1209 return 1210 } 1211 1212 if destModule == nil { 1213 // allowMissingDependencies is true and the module wasn't found 1214 return 1215 } 1216 1217 mctx.reverseDeps = append(mctx.reverseDeps, reverseDep{ 1218 destModule, 1219 depInfo{mctx.module, tag}, 1220 }) 1221} 1222 1223func (mctx *mutatorContext) AddVariationDependencies(variations []Variation, tag DependencyTag, 1224 deps ...string) []Module { 1225 1226 depInfos := make([]Module, 0, len(deps)) 1227 for _, dep := range deps { 1228 depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.mutator, mctx.config, variations, tag, dep, false) 1229 if len(errs) > 0 { 1230 mctx.errs = append(mctx.errs, errs...) 1231 } 1232 if !mctx.pause(depInfo) { 1233 // Pausing not supported by this mutator, new dependencies can't be returned. 1234 depInfo = nil 1235 } 1236 depInfos = append(depInfos, maybeLogicModule(depInfo)) 1237 } 1238 return depInfos 1239} 1240 1241func (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation, tag DependencyTag, 1242 deps ...string) []Module { 1243 1244 depInfos := make([]Module, 0, len(deps)) 1245 for _, dep := range deps { 1246 depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.mutator, mctx.config, variations, tag, dep, true) 1247 if len(errs) > 0 { 1248 mctx.errs = append(mctx.errs, errs...) 1249 } 1250 if !mctx.pause(depInfo) { 1251 // Pausing not supported by this mutator, new dependencies can't be returned. 1252 depInfo = nil 1253 } 1254 depInfos = append(depInfos, maybeLogicModule(depInfo)) 1255 } 1256 return depInfos 1257} 1258 1259func (mctx *mutatorContext) ReplaceDependencies(name string) { 1260 mctx.ReplaceDependenciesIf(name, nil) 1261} 1262 1263type ReplaceDependencyPredicate func(from Module, tag DependencyTag, to Module) bool 1264 1265func (mctx *mutatorContext) ReplaceDependenciesIf(name string, predicate ReplaceDependencyPredicate) { 1266 if !mctx.mutator.usesReplaceDependencies { 1267 panic(fmt.Errorf("method ReplaceDependenciesIf called from mutator that was not marked UsesReplaceDependencies")) 1268 } 1269 1270 targets := mctx.context.moduleVariantsThatDependOn(name, mctx.module) 1271 1272 if len(targets) == 0 { 1273 panic(fmt.Errorf("ReplaceDependencies could not find identical variant {%s} for module %s\n"+ 1274 "available variants:\n %s", 1275 mctx.context.prettyPrintVariant(mctx.module.variant.variations), 1276 name, 1277 mctx.context.prettyPrintGroupVariants(mctx.context.moduleGroupFromName(name, mctx.module.namespace())))) 1278 } 1279 1280 for _, target := range targets { 1281 mctx.replace = append(mctx.replace, replace{target, mctx.module, predicate}) 1282 } 1283} 1284 1285func (mctx *mutatorContext) Rename(name string) { 1286 if !mctx.mutator.usesRename { 1287 panic(fmt.Errorf("method Rename called from mutator that was not marked UsesRename")) 1288 } 1289 mctx.rename = append(mctx.rename, rename{mctx.module.group, name}) 1290} 1291 1292func (mctx *mutatorContext) CreateModule(factory ModuleFactory, typeName string, props ...interface{}) Module { 1293 if !mctx.mutator.usesCreateModule { 1294 panic(fmt.Errorf("method CreateModule called from mutator that was not marked UsesCreateModule")) 1295 } 1296 1297 module := newModule(factory) 1298 1299 module.relBlueprintsFile = mctx.module.relBlueprintsFile 1300 module.pos = mctx.module.pos 1301 module.propertyPos = mctx.module.propertyPos 1302 module.createdBy = mctx.module 1303 module.typeName = typeName 1304 1305 for _, p := range props { 1306 err := proptools.AppendMatchingProperties(module.properties, p, nil) 1307 if err != nil { 1308 panic(err) 1309 } 1310 } 1311 1312 mctx.newModules = append(mctx.newModules, module) 1313 1314 return module.logicModule 1315} 1316 1317// pause waits until the given dependency has been visited by the mutator's parallelVisit call. 1318// It returns true if the pause was supported, false if the pause was not supported and did not 1319// occur, which will happen when the mutator is not parallelizable. If the dependency is nil 1320// it returns true if pausing is supported or false if it is not. 1321func (mctx *mutatorContext) pause(dep *moduleInfo) bool { 1322 if mctx.pauseCh != nil { 1323 if dep != nil { 1324 unpause := make(unpause) 1325 mctx.pauseCh <- pauseSpec{ 1326 paused: mctx.module, 1327 until: dep, 1328 unpause: unpause, 1329 } 1330 <-unpause 1331 } 1332 return true 1333 } 1334 return false 1335} 1336 1337// SimpleName is an embeddable object to implement the ModuleContext.Name method using a property 1338// called "name". Modules that embed it must also add SimpleName.Properties to their property 1339// structure list. 1340type SimpleName struct { 1341 Properties struct { 1342 Name string 1343 } 1344} 1345 1346func (s *SimpleName) Name() string { 1347 return s.Properties.Name 1348} 1349 1350// Load Hooks 1351 1352type LoadHookContext interface { 1353 EarlyModuleContext 1354 1355 // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies 1356 // the specified property structs to it as if the properties were set in a blueprint file. 1357 CreateModule(ModuleFactory, string, ...interface{}) Module 1358 1359 // CreateModuleInDirectory creates a new module in the specified directory by calling the 1360 // factory method for the specified moduleType, and applies the specified property structs 1361 // to it as if the properties were set in a blueprint file. 1362 CreateModuleInDirectory(ModuleFactory, string, string, ...interface{}) Module 1363 1364 // RegisterScopedModuleType creates a new module type that is scoped to the current Blueprints 1365 // file. 1366 RegisterScopedModuleType(name string, factory ModuleFactory) 1367} 1368 1369func (l *loadHookContext) createModule(factory ModuleFactory, typeName, moduleDir string, props ...interface{}) Module { 1370 module := newModule(factory) 1371 1372 module.relBlueprintsFile = moduleDir 1373 module.pos = l.module.pos 1374 module.propertyPos = l.module.propertyPos 1375 module.createdBy = l.module 1376 module.typeName = typeName 1377 1378 for _, p := range props { 1379 err := proptools.AppendMatchingProperties(module.properties, p, nil) 1380 if err != nil { 1381 panic(err) 1382 } 1383 } 1384 1385 l.newModules = append(l.newModules, module) 1386 1387 return module.logicModule 1388} 1389 1390func (l *loadHookContext) CreateModule(factory ModuleFactory, typeName string, props ...interface{}) Module { 1391 return l.createModule(factory, typeName, l.module.relBlueprintsFile, props...) 1392} 1393 1394func (l *loadHookContext) CreateModuleInDirectory(factory ModuleFactory, typeName, moduleDir string, props ...interface{}) Module { 1395 if moduleDir != filepath.Clean(moduleDir) { 1396 panic(fmt.Errorf("Cannot create a module in %s", moduleDir)) 1397 } 1398 1399 filePath := filepath.Join(moduleDir, "Android.bp") 1400 return l.createModule(factory, typeName, filePath, props...) 1401} 1402 1403func (l *loadHookContext) RegisterScopedModuleType(name string, factory ModuleFactory) { 1404 if _, exists := l.context.moduleFactories[name]; exists { 1405 panic(fmt.Errorf("A global module type named %q already exists", name)) 1406 } 1407 1408 if _, exists := (*l.scopedModuleFactories)[name]; exists { 1409 panic(fmt.Errorf("A module type named %q already exists in this scope", name)) 1410 } 1411 1412 if *l.scopedModuleFactories == nil { 1413 *l.scopedModuleFactories = make(map[string]ModuleFactory) 1414 } 1415 1416 (*l.scopedModuleFactories)[name] = factory 1417} 1418 1419type loadHookContext struct { 1420 baseModuleContext 1421 newModules []*moduleInfo 1422 scopedModuleFactories *map[string]ModuleFactory 1423} 1424 1425type LoadHook func(ctx LoadHookContext) 1426 1427// LoadHookWithPriority is a wrapper around LoadHook and allows hooks to be sorted by priority. 1428// hooks with higher value of `priority` run last. 1429// hooks with equal value of `priority` run in the order they were registered. 1430type LoadHookWithPriority struct { 1431 priority int 1432 loadHook LoadHook 1433} 1434 1435// Load hooks need to be added by module factories, which don't have any parameter to get to the 1436// Context, and only produce a Module interface with no base implementation, so the load hooks 1437// must be stored in a global map. The key is a pointer allocated by the module factory, so there 1438// is no chance of collisions even if tests are running in parallel with multiple contexts. The 1439// contents should be short-lived, they are added during a module factory and removed immediately 1440// after the module factory returns. 1441var pendingHooks sync.Map 1442 1443func AddLoadHook(module Module, hook LoadHook) { 1444 // default priority is 0 1445 AddLoadHookWithPriority(module, hook, 0) 1446} 1447 1448// AddLoadhHookWithPriority adds a load hook with a specified priority. 1449// Hooks with higher priority run last. 1450// Hooks with equal priority run in the order they were registered. 1451func AddLoadHookWithPriority(module Module, hook LoadHook, priority int) { 1452 // Only one goroutine can be processing a given module, so no additional locking is required 1453 // for the slice stored in the sync.Map. 1454 v, exists := pendingHooks.Load(module) 1455 if !exists { 1456 v, _ = pendingHooks.LoadOrStore(module, new([]LoadHookWithPriority)) 1457 } 1458 hooks := v.(*[]LoadHookWithPriority) 1459 *hooks = append(*hooks, LoadHookWithPriority{priority, hook}) 1460} 1461 1462func runAndRemoveLoadHooks(ctx *Context, config interface{}, module *moduleInfo, 1463 scopedModuleFactories *map[string]ModuleFactory) (newModules []*moduleInfo, deps []string, errs []error) { 1464 1465 if v, exists := pendingHooks.Load(module.logicModule); exists { 1466 hooks := v.(*[]LoadHookWithPriority) 1467 // Sort the hooks by priority. 1468 // Use SliceStable so that hooks with equal priority run in the order they were registered. 1469 sort.SliceStable(*hooks, func(i, j int) bool { return (*hooks)[i].priority < (*hooks)[j].priority }) 1470 1471 for _, hook := range *hooks { 1472 mctx := &loadHookContext{ 1473 baseModuleContext: baseModuleContext{ 1474 context: ctx, 1475 config: config, 1476 module: module, 1477 }, 1478 scopedModuleFactories: scopedModuleFactories, 1479 } 1480 hook.loadHook(mctx) 1481 newModules = append(newModules, mctx.newModules...) 1482 deps = append(deps, mctx.ninjaFileDeps...) 1483 errs = append(errs, mctx.errs...) 1484 } 1485 pendingHooks.Delete(module.logicModule) 1486 1487 return newModules, deps, errs 1488 } 1489 1490 return nil, nil, nil 1491} 1492 1493// Check the syntax of a generated blueprint file. 1494// 1495// This is intended to perform a quick syntactic check for generated blueprint 1496// code, where syntactically correct means: 1497// * No variable definitions. 1498// * Valid module types. 1499// * Valid property names. 1500// * Valid values for the property type. 1501// 1502// It does not perform any semantic checking of properties, existence of referenced 1503// files, or dependencies. 1504// 1505// At a low level it: 1506// * Parses the contents. 1507// * Invokes relevant factory to create Module instances. 1508// * Unpacks the properties into the Module. 1509// * Does not invoke load hooks or any mutators. 1510// 1511// The filename is only used for reporting errors. 1512func CheckBlueprintSyntax(moduleFactories map[string]ModuleFactory, filename string, contents string) []error { 1513 file, errs := parser.Parse(filename, strings.NewReader(contents)) 1514 if len(errs) != 0 { 1515 return errs 1516 } 1517 1518 for _, def := range file.Defs { 1519 switch def := def.(type) { 1520 case *parser.Module: 1521 _, moduleErrs := processModuleDef(def, filename, moduleFactories, nil, false) 1522 errs = append(errs, moduleErrs...) 1523 1524 default: 1525 panic(fmt.Errorf("unknown definition type: %T", def)) 1526 } 1527 } 1528 1529 return errs 1530} 1531 1532func maybeLogicModule(module *moduleInfo) Module { 1533 if module != nil { 1534 return module.logicModule 1535 } else { 1536 return nil 1537 } 1538} 1539