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