1// Copyright 2015 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package android 16 17import ( 18 "sync" 19 20 "github.com/google/blueprint" 21) 22 23// Phases: 24// run Pre-arch mutators 25// run archMutator 26// run Pre-deps mutators 27// run depsMutator 28// run PostDeps mutators 29// run FinalDeps mutators (TransitionMutators disallowed in this phase) 30// continue on to GenerateAndroidBuildActions 31 32// collateGloballyRegisteredMutators constructs the list of mutators that have been registered 33// with the InitRegistrationContext and will be used at runtime. 34func collateGloballyRegisteredMutators() sortableComponents { 35 return collateRegisteredMutators(preArch, preDeps, postDeps, postApex, finalDeps) 36} 37 38// collateRegisteredMutators constructs a single list of mutators from the separate lists. 39func collateRegisteredMutators(preArch, preDeps, postDeps, postApex, finalDeps []RegisterMutatorFunc) sortableComponents { 40 mctx := ®isterMutatorsContext{} 41 42 register := func(funcs []RegisterMutatorFunc) { 43 for _, f := range funcs { 44 f(mctx) 45 } 46 } 47 48 register(preArch) 49 50 register(preDeps) 51 52 register([]RegisterMutatorFunc{registerDepsMutator}) 53 54 register(postDeps) 55 56 register(postApex) 57 58 mctx.finalPhase = true 59 register(finalDeps) 60 61 return mctx.mutators 62} 63 64type registerMutatorsContext struct { 65 mutators sortableComponents 66 finalPhase bool 67} 68 69type RegisterMutatorsContext interface { 70 TopDown(name string, m TopDownMutator) MutatorHandle 71 BottomUp(name string, m BottomUpMutator) MutatorHandle 72 BottomUpBlueprint(name string, m blueprint.BottomUpMutator) MutatorHandle 73 Transition(name string, m TransitionMutator) TransitionMutatorHandle 74} 75 76type RegisterMutatorFunc func(RegisterMutatorsContext) 77 78var preArch = []RegisterMutatorFunc{ 79 RegisterNamespaceMutator, 80 81 // Check the visibility rules are valid. 82 // 83 // This must run after the package renamer mutators so that any issues found during 84 // validation of the package's default_visibility property are reported using the 85 // correct package name and not the synthetic name. 86 // 87 // This must also be run before defaults mutators as the rules for validation are 88 // different before checking the rules than they are afterwards. e.g. 89 // visibility: ["//visibility:private", "//visibility:public"] 90 // would be invalid if specified in a module definition but is valid if it results 91 // from something like this: 92 // 93 // defaults { 94 // name: "defaults", 95 // // Be inaccessible outside a package by default. 96 // visibility: ["//visibility:private"] 97 // } 98 // 99 // defaultable_module { 100 // name: "defaultable_module", 101 // defaults: ["defaults"], 102 // // Override the default. 103 // visibility: ["//visibility:public"] 104 // } 105 // 106 RegisterVisibilityRuleChecker, 107 108 // Record the default_applicable_licenses for each package. 109 // 110 // This must run before the defaults so that defaults modules can pick up the package default. 111 RegisterLicensesPackageMapper, 112 113 // Apply properties from defaults modules to the referencing modules. 114 // 115 // Any mutators that are added before this will not see any modules created by 116 // a DefaultableHook. 117 RegisterDefaultsPreArchMutators, 118 119 // Add dependencies on any components so that any component references can be 120 // resolved within the deps mutator. 121 // 122 // Must be run after defaults so it can be used to create dependencies on the 123 // component modules that are creating in a DefaultableHook. 124 // 125 // Must be run before RegisterPrebuiltsPreArchMutators, i.e. before prebuilts are 126 // renamed. That is so that if a module creates components using a prebuilt module 127 // type that any dependencies (which must use prebuilt_ prefixes) are resolved to 128 // the prebuilt module and not the source module. 129 RegisterComponentsMutator, 130 131 // Create an association between prebuilt modules and their corresponding source 132 // modules (if any). 133 // 134 // Must be run after defaults mutators to ensure that any modules created by 135 // a DefaultableHook can be either a prebuilt or a source module with a matching 136 // prebuilt. 137 RegisterPrebuiltsPreArchMutators, 138 139 // Gather the licenses properties for all modules for use during expansion and enforcement. 140 // 141 // This must come after the defaults mutators to ensure that any licenses supplied 142 // in a defaults module has been successfully applied before the rules are gathered. 143 RegisterLicensesPropertyGatherer, 144 145 // Gather the visibility rules for all modules for us during visibility enforcement. 146 // 147 // This must come after the defaults mutators to ensure that any visibility supplied 148 // in a defaults module has been successfully applied before the rules are gathered. 149 RegisterVisibilityRuleGatherer, 150} 151 152func registerArchMutator(ctx RegisterMutatorsContext) { 153 ctx.Transition("os", &osTransitionMutator{}) 154 ctx.BottomUp("image_begin", imageMutatorBeginMutator) 155 ctx.Transition("image", &imageTransitionMutator{}) 156 ctx.Transition("arch", &archTransitionMutator{}) 157} 158 159var preDeps = []RegisterMutatorFunc{ 160 registerArchMutator, 161} 162 163var postDeps = []RegisterMutatorFunc{ 164 registerPathDepsMutator, 165 RegisterPrebuiltsPostDepsMutators, 166 RegisterVisibilityRuleEnforcer, 167 RegisterLicensesDependencyChecker, 168 registerNeverallowMutator, 169 RegisterOverridePostDepsMutators, 170} 171 172var postApex = []RegisterMutatorFunc{} 173 174var finalDeps = []RegisterMutatorFunc{} 175 176func PreArchMutators(f RegisterMutatorFunc) { 177 preArch = append(preArch, f) 178} 179 180func PreDepsMutators(f RegisterMutatorFunc) { 181 preDeps = append(preDeps, f) 182} 183 184func PostDepsMutators(f RegisterMutatorFunc) { 185 postDeps = append(postDeps, f) 186} 187 188func PostApexMutators(f RegisterMutatorFunc) { 189 postApex = append(postApex, f) 190} 191 192func FinalDepsMutators(f RegisterMutatorFunc) { 193 finalDeps = append(finalDeps, f) 194} 195 196type TopDownMutator func(TopDownMutatorContext) 197 198type TopDownMutatorContext interface { 199 BaseModuleContext 200} 201 202type topDownMutatorContext struct { 203 bp blueprint.TopDownMutatorContext 204 baseModuleContext 205} 206 207type BottomUpMutator func(BottomUpMutatorContext) 208 209type BottomUpMutatorContext interface { 210 BaseModuleContext 211 212 // AddDependency adds a dependency to the given module. It returns a slice of modules for each 213 // dependency (some entries may be nil). 214 // 215 // This method will pause until the new dependencies have had the current mutator called on them. 216 AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module 217 218 // AddReverseDependency adds a dependency from the destination to the given module. 219 // Does not affect the ordering of the current mutator pass, but will be ordered 220 // correctly for all future mutator passes. All reverse dependencies for a destination module are 221 // collected until the end of the mutator pass, sorted by name, and then appended to the destination 222 // module's dependency list. May only be called by mutators that were marked with 223 // UsesReverseDependencies during registration. 224 AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) 225 226 // AddVariationDependencies adds deps as dependencies of the current module, but uses the variations 227 // argument to select which variant of the dependency to use. It returns a slice of modules for 228 // each dependency (some entries may be nil). A variant of the dependency must exist that matches 229 // all the non-local variations of the current module, plus the variations argument. 230 // 231 // This method will pause until the new dependencies have had the current mutator called on them. 232 AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, names ...string) []blueprint.Module 233 234 // AddReverseVariationDependency adds a dependency from the named module to the current 235 // module. The given variations will be added to the current module's varations, and then the 236 // result will be used to find the correct variation of the depending module, which must exist. 237 // 238 // Does not affect the ordering of the current mutator pass, but will be ordered 239 // correctly for all future mutator passes. All reverse dependencies for a destination module are 240 // collected until the end of the mutator pass, sorted by name, and then appended to the destination 241 // module's dependency list. May only be called by mutators that were marked with 242 // UsesReverseDependencies during registration. 243 AddReverseVariationDependency([]blueprint.Variation, blueprint.DependencyTag, string) 244 245 // AddFarVariationDependencies adds deps as dependencies of the current module, but uses the 246 // variations argument to select which variant of the dependency to use. It returns a slice of 247 // modules for each dependency (some entries may be nil). A variant of the dependency must 248 // exist that matches the variations argument, but may also have other variations. 249 // For any unspecified variation the first variant will be used. 250 // 251 // Unlike AddVariationDependencies, the variations of the current module are ignored - the 252 // dependency only needs to match the supplied variations. 253 // 254 // This method will pause until the new dependencies have had the current mutator called on them. 255 AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []blueprint.Module 256 257 // ReplaceDependencies finds all the variants of the module with the specified name, then 258 // replaces all dependencies onto those variants with the current variant of this module. 259 // Replacements don't take effect until after the mutator pass is finished. May only 260 // be called by mutators that were marked with UsesReplaceDependencies during registration. 261 ReplaceDependencies(string) 262 263 // ReplaceDependenciesIf finds all the variants of the module with the specified name, then 264 // replaces all dependencies onto those variants with the current variant of this module 265 // as long as the supplied predicate returns true. 266 // Replacements don't take effect until after the mutator pass is finished. May only 267 // be called by mutators that were marked with UsesReplaceDependencies during registration. 268 ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate) 269 270 // Rename all variants of a module. The new name is not visible to calls to ModuleName, 271 // AddDependency or OtherModuleName until after this mutator pass is complete. May only be called 272 // by mutators that were marked with UsesRename during registration. 273 Rename(name string) 274 275 // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies 276 // the specified property structs to it as if the properties were set in a blueprint file. May only 277 // be called by mutators that were marked with UsesCreateModule during registration. 278 CreateModule(ModuleFactory, ...interface{}) Module 279} 280 281// An outgoingTransitionContextImpl and incomingTransitionContextImpl is created for every dependency of every module 282// for each transition mutator. bottomUpMutatorContext and topDownMutatorContext are created once for every module 283// for every BottomUp or TopDown mutator. Use a global pool for each to avoid reallocating every time. 284var ( 285 outgoingTransitionContextPool = sync.Pool{ 286 New: func() any { return &outgoingTransitionContextImpl{} }, 287 } 288 incomingTransitionContextPool = sync.Pool{ 289 New: func() any { return &incomingTransitionContextImpl{} }, 290 } 291 bottomUpMutatorContextPool = sync.Pool{ 292 New: func() any { return &bottomUpMutatorContext{} }, 293 } 294 295 topDownMutatorContextPool = sync.Pool{ 296 New: func() any { return &topDownMutatorContext{} }, 297 } 298) 299 300type bottomUpMutatorContext struct { 301 bp blueprint.BottomUpMutatorContext 302 baseModuleContext 303 finalPhase bool 304} 305 306// callers must immediately follow the call to this function with defer bottomUpMutatorContextPool.Put(mctx). 307func bottomUpMutatorContextFactory(ctx blueprint.BottomUpMutatorContext, a Module, 308 finalPhase bool) BottomUpMutatorContext { 309 310 moduleContext := a.base().baseModuleContextFactory(ctx) 311 mctx := bottomUpMutatorContextPool.Get().(*bottomUpMutatorContext) 312 *mctx = bottomUpMutatorContext{ 313 bp: ctx, 314 baseModuleContext: moduleContext, 315 finalPhase: finalPhase, 316 } 317 return mctx 318} 319 320func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) MutatorHandle { 321 finalPhase := x.finalPhase 322 f := func(ctx blueprint.BottomUpMutatorContext) { 323 if a, ok := ctx.Module().(Module); ok { 324 mctx := bottomUpMutatorContextFactory(ctx, a, finalPhase) 325 defer bottomUpMutatorContextPool.Put(mctx) 326 m(mctx) 327 } 328 } 329 mutator := &mutator{name: x.mutatorName(name), bottomUpMutator: f} 330 x.mutators = append(x.mutators, mutator) 331 return mutator 332} 333 334func (x *registerMutatorsContext) BottomUpBlueprint(name string, m blueprint.BottomUpMutator) MutatorHandle { 335 mutator := &mutator{name: name, bottomUpMutator: m} 336 x.mutators = append(x.mutators, mutator) 337 return mutator 338} 339 340type IncomingTransitionContext interface { 341 ArchModuleContext 342 ModuleProviderContext 343 ModuleErrorContext 344 345 // Module returns the target of the dependency edge for which the transition 346 // is being computed 347 Module() Module 348 349 // Config returns the configuration for the build. 350 Config() Config 351 352 DeviceConfig() DeviceConfig 353 354 // IsAddingDependency returns true if the transition is being called while adding a dependency 355 // after the transition mutator has already run, or false if it is being called when the transition 356 // mutator is running. This should be used sparingly, all uses will have to be removed in order 357 // to support creating variants on demand. 358 IsAddingDependency() bool 359} 360 361type OutgoingTransitionContext interface { 362 ArchModuleContext 363 ModuleProviderContext 364 365 // Module returns the target of the dependency edge for which the transition 366 // is being computed 367 Module() Module 368 369 // DepTag() Returns the dependency tag through which this dependency is 370 // reached 371 DepTag() blueprint.DependencyTag 372 373 // Config returns the configuration for the build. 374 Config() Config 375 376 DeviceConfig() DeviceConfig 377} 378 379// TransitionMutator implements a top-down mechanism where a module tells its 380// direct dependencies what variation they should be built in but the dependency 381// has the final say. 382// 383// When implementing a transition mutator, one needs to implement four methods: 384// - Split() that tells what variations a module has by itself 385// - OutgoingTransition() where a module tells what it wants from its 386// dependency 387// - IncomingTransition() where a module has the final say about its own 388// variation 389// - Mutate() that changes the state of a module depending on its variation 390// 391// That the effective variation of module B when depended on by module A is the 392// composition the outgoing transition of module A and the incoming transition 393// of module B. 394// 395// the outgoing transition should not take the properties of the dependency into 396// account, only those of the module that depends on it. For this reason, the 397// dependency is not even passed into it as an argument. Likewise, the incoming 398// transition should not take the properties of the depending module into 399// account and is thus not informed about it. This makes for a nice 400// decomposition of the decision logic. 401// 402// A given transition mutator only affects its own variation; other variations 403// stay unchanged along the dependency edges. 404// 405// Soong makes sure that all modules are created in the desired variations and 406// that dependency edges are set up correctly. This ensures that "missing 407// variation" errors do not happen and allows for more flexible changes in the 408// value of the variation among dependency edges (as oppposed to bottom-up 409// mutators where if module A in variation X depends on module B and module B 410// has that variation X, A must depend on variation X of B) 411// 412// The limited power of the context objects passed to individual mutators 413// methods also makes it more difficult to shoot oneself in the foot. Complete 414// safety is not guaranteed because no one prevents individual transition 415// mutators from mutating modules in illegal ways and for e.g. Split() or 416// Mutate() to run their own visitations of the transitive dependency of the 417// module and both of these are bad ideas, but it's better than no guardrails at 418// all. 419// 420// This model is pretty close to Bazel's configuration transitions. The mapping 421// between concepts in Soong and Bazel is as follows: 422// - Module == configured target 423// - Variant == configuration 424// - Variation name == configuration flag 425// - Variation == configuration flag value 426// - Outgoing transition == attribute transition 427// - Incoming transition == rule transition 428// 429// The Split() method does not have a Bazel equivalent and Bazel split 430// transitions do not have a Soong equivalent. 431// 432// Mutate() does not make sense in Bazel due to the different models of the 433// two systems: when creating new variations, Soong clones the old module and 434// thus some way is needed to change it state whereas Bazel creates each 435// configuration of a given configured target anew. 436type TransitionMutator interface { 437 // Split returns the set of variations that should be created for a module no 438 // matter who depends on it. Used when Make depends on a particular variation 439 // or when the module knows its variations just based on information given to 440 // it in the Blueprint file. This method should not mutate the module it is 441 // called on. 442 Split(ctx BaseModuleContext) []string 443 444 // OutgoingTransition is called on a module to determine which variation it wants 445 // from its direct dependencies. The dependency itself can override this decision. 446 // This method should not mutate the module itself. 447 OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string 448 449 // IncomingTransition is called on a module to determine which variation it should 450 // be in based on the variation modules that depend on it want. This gives the module 451 // a final say about its own variations. This method should not mutate the module 452 // itself. 453 IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string 454 455 // Mutate is called after a module was split into multiple variations on each variation. 456 // It should not split the module any further but adding new dependencies is 457 // fine. Unlike all the other methods on TransitionMutator, this method is 458 // allowed to mutate the module. 459 Mutate(ctx BottomUpMutatorContext, variation string) 460} 461 462type androidTransitionMutator struct { 463 finalPhase bool 464 mutator TransitionMutator 465 name string 466} 467 468func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []string { 469 if a.finalPhase { 470 panic("TransitionMutator not allowed in FinalDepsMutators") 471 } 472 if m, ok := ctx.Module().(Module); ok { 473 moduleContext := m.base().baseModuleContextFactory(ctx) 474 return a.mutator.Split(&moduleContext) 475 } else { 476 return []string{""} 477 } 478} 479 480type outgoingTransitionContextImpl struct { 481 archModuleContext 482 bp blueprint.OutgoingTransitionContext 483} 484 485func (c *outgoingTransitionContextImpl) Module() Module { 486 return c.bp.Module().(Module) 487} 488 489func (c *outgoingTransitionContextImpl) DepTag() blueprint.DependencyTag { 490 return c.bp.DepTag() 491} 492 493func (c *outgoingTransitionContextImpl) Config() Config { 494 return c.bp.Config().(Config) 495} 496 497func (c *outgoingTransitionContextImpl) DeviceConfig() DeviceConfig { 498 return DeviceConfig{c.bp.Config().(Config).deviceConfig} 499} 500 501func (c *outgoingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) { 502 return c.bp.Provider(provider) 503} 504 505func (a *androidTransitionMutator) OutgoingTransition(bpctx blueprint.OutgoingTransitionContext, sourceVariation string) string { 506 if m, ok := bpctx.Module().(Module); ok { 507 ctx := outgoingTransitionContextPool.Get().(*outgoingTransitionContextImpl) 508 defer outgoingTransitionContextPool.Put(ctx) 509 *ctx = outgoingTransitionContextImpl{ 510 archModuleContext: m.base().archModuleContextFactory(bpctx), 511 bp: bpctx, 512 } 513 return a.mutator.OutgoingTransition(ctx, sourceVariation) 514 } else { 515 return "" 516 } 517} 518 519type incomingTransitionContextImpl struct { 520 archModuleContext 521 bp blueprint.IncomingTransitionContext 522} 523 524func (c *incomingTransitionContextImpl) Module() Module { 525 return c.bp.Module().(Module) 526} 527 528func (c *incomingTransitionContextImpl) Config() Config { 529 return c.bp.Config().(Config) 530} 531 532func (c *incomingTransitionContextImpl) DeviceConfig() DeviceConfig { 533 return DeviceConfig{c.bp.Config().(Config).deviceConfig} 534} 535 536func (c *incomingTransitionContextImpl) IsAddingDependency() bool { 537 return c.bp.IsAddingDependency() 538} 539 540func (c *incomingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) { 541 return c.bp.Provider(provider) 542} 543 544func (c *incomingTransitionContextImpl) ModuleErrorf(fmt string, args ...interface{}) { 545 c.bp.ModuleErrorf(fmt, args) 546} 547 548func (c *incomingTransitionContextImpl) PropertyErrorf(property, fmt string, args ...interface{}) { 549 c.bp.PropertyErrorf(property, fmt, args) 550} 551 552func (a *androidTransitionMutator) IncomingTransition(bpctx blueprint.IncomingTransitionContext, incomingVariation string) string { 553 if m, ok := bpctx.Module().(Module); ok { 554 ctx := incomingTransitionContextPool.Get().(*incomingTransitionContextImpl) 555 defer incomingTransitionContextPool.Put(ctx) 556 *ctx = incomingTransitionContextImpl{ 557 archModuleContext: m.base().archModuleContextFactory(bpctx), 558 bp: bpctx, 559 } 560 return a.mutator.IncomingTransition(ctx, incomingVariation) 561 } else { 562 return "" 563 } 564} 565 566func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) { 567 if am, ok := ctx.Module().(Module); ok { 568 if variation != "" { 569 // TODO: this should really be checking whether the TransitionMutator affected this module, not 570 // the empty variant, but TransitionMutator has no concept of skipping a module. 571 base := am.base() 572 base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name) 573 base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation) 574 } 575 576 mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase) 577 defer bottomUpMutatorContextPool.Put(mctx) 578 a.mutator.Mutate(mctx, variation) 579 } 580} 581 582func (x *registerMutatorsContext) Transition(name string, m TransitionMutator) TransitionMutatorHandle { 583 atm := &androidTransitionMutator{ 584 finalPhase: x.finalPhase, 585 mutator: m, 586 name: name, 587 } 588 mutator := &mutator{ 589 name: name, 590 transitionMutator: atm, 591 } 592 x.mutators = append(x.mutators, mutator) 593 return mutator 594} 595 596func (x *registerMutatorsContext) mutatorName(name string) string { 597 return name 598} 599 600func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) MutatorHandle { 601 f := func(ctx blueprint.TopDownMutatorContext) { 602 if a, ok := ctx.Module().(Module); ok { 603 moduleContext := a.base().baseModuleContextFactory(ctx) 604 actx := topDownMutatorContextPool.Get().(*topDownMutatorContext) 605 defer topDownMutatorContextPool.Put(actx) 606 *actx = topDownMutatorContext{ 607 bp: ctx, 608 baseModuleContext: moduleContext, 609 } 610 m(actx) 611 } 612 } 613 mutator := &mutator{name: x.mutatorName(name), topDownMutator: f} 614 x.mutators = append(x.mutators, mutator) 615 return mutator 616} 617 618func (mutator *mutator) componentName() string { 619 return mutator.name 620} 621 622func (mutator *mutator) register(ctx *Context) { 623 blueprintCtx := ctx.Context 624 var handle blueprint.MutatorHandle 625 if mutator.bottomUpMutator != nil { 626 handle = blueprintCtx.RegisterBottomUpMutator(mutator.name, mutator.bottomUpMutator) 627 } else if mutator.topDownMutator != nil { 628 handle = blueprintCtx.RegisterTopDownMutator(mutator.name, mutator.topDownMutator) 629 } else if mutator.transitionMutator != nil { 630 handle := blueprintCtx.RegisterTransitionMutator(mutator.name, mutator.transitionMutator) 631 if mutator.neverFar { 632 handle.NeverFar() 633 } 634 } 635 636 // Forward booleans set on the MutatorHandle to the blueprint.MutatorHandle. 637 if mutator.usesRename { 638 handle.UsesRename() 639 } 640 if mutator.usesReverseDependencies { 641 handle.UsesReverseDependencies() 642 } 643 if mutator.usesReplaceDependencies { 644 handle.UsesReplaceDependencies() 645 } 646 if mutator.usesCreateModule { 647 handle.UsesCreateModule() 648 } 649 if mutator.mutatesDependencies { 650 handle.MutatesDependencies() 651 } 652 if mutator.mutatesGlobalState { 653 handle.MutatesGlobalState() 654 } 655} 656 657type MutatorHandle interface { 658 // Parallel sets the mutator to visit modules in parallel while maintaining ordering. Calling any 659 // method on the mutator context is thread-safe, but the mutator must handle synchronization 660 // for any modifications to global state or any modules outside the one it was invoked on. 661 // Deprecated: all Mutators are parallel by default. 662 Parallel() MutatorHandle 663 664 // UsesRename marks the mutator as using the BottomUpMutatorContext.Rename method, which prevents 665 // coalescing adjacent mutators into a single mutator pass. 666 UsesRename() MutatorHandle 667 668 // UsesReverseDependencies marks the mutator as using the BottomUpMutatorContext.AddReverseDependency 669 // method, which prevents coalescing adjacent mutators into a single mutator pass. 670 UsesReverseDependencies() MutatorHandle 671 672 // UsesReplaceDependencies marks the mutator as using the BottomUpMutatorContext.ReplaceDependencies 673 // method, which prevents coalescing adjacent mutators into a single mutator pass. 674 UsesReplaceDependencies() MutatorHandle 675 676 // UsesCreateModule marks the mutator as using the BottomUpMutatorContext.CreateModule method, 677 // which prevents coalescing adjacent mutators into a single mutator pass. 678 UsesCreateModule() MutatorHandle 679 680 // MutatesDependencies marks the mutator as modifying properties in dependencies, which prevents 681 // coalescing adjacent mutators into a single mutator pass. 682 MutatesDependencies() MutatorHandle 683 684 // MutatesGlobalState marks the mutator as modifying global state, which prevents coalescing 685 // adjacent mutators into a single mutator pass. 686 MutatesGlobalState() MutatorHandle 687} 688 689type TransitionMutatorHandle interface { 690 // NeverFar causes the variations created by this mutator to never be ignored when adding 691 // far variation dependencies. Normally, far variation dependencies ignore all the variants 692 // of the source module, and only use the variants explicitly requested by the 693 // AddFarVariationDependencies call. 694 NeverFar() MutatorHandle 695} 696 697func (mutator *mutator) Parallel() MutatorHandle { 698 return mutator 699} 700 701func (mutator *mutator) UsesRename() MutatorHandle { 702 mutator.usesRename = true 703 return mutator 704} 705 706func (mutator *mutator) UsesReverseDependencies() MutatorHandle { 707 mutator.usesReverseDependencies = true 708 return mutator 709} 710 711func (mutator *mutator) UsesReplaceDependencies() MutatorHandle { 712 mutator.usesReplaceDependencies = true 713 return mutator 714} 715 716func (mutator *mutator) UsesCreateModule() MutatorHandle { 717 mutator.usesCreateModule = true 718 return mutator 719} 720 721func (mutator *mutator) MutatesDependencies() MutatorHandle { 722 mutator.mutatesDependencies = true 723 return mutator 724} 725 726func (mutator *mutator) MutatesGlobalState() MutatorHandle { 727 mutator.mutatesGlobalState = true 728 return mutator 729} 730 731func (mutator *mutator) NeverFar() MutatorHandle { 732 mutator.neverFar = true 733 return mutator 734} 735 736func RegisterComponentsMutator(ctx RegisterMutatorsContext) { 737 ctx.BottomUp("component-deps", componentDepsMutator) 738} 739 740// A special mutator that runs just prior to the deps mutator to allow the dependencies 741// on component modules to be added so that they can depend directly on a prebuilt 742// module. 743func componentDepsMutator(ctx BottomUpMutatorContext) { 744 ctx.Module().ComponentDepsMutator(ctx) 745} 746 747func depsMutator(ctx BottomUpMutatorContext) { 748 if m := ctx.Module(); m.Enabled(ctx) { 749 m.base().baseDepsMutator(ctx) 750 m.DepsMutator(ctx) 751 } 752} 753 754func registerDepsMutator(ctx RegisterMutatorsContext) { 755 ctx.BottomUp("deps", depsMutator).UsesReverseDependencies() 756} 757 758// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that 759// has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid 760// ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every 761// non-overridden method has to be forwarded. There are fewer non-overridden methods, so use the latter. The following 762// methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext. 763 764func (b *bottomUpMutatorContext) Rename(name string) { 765 b.bp.Rename(name) 766 b.Module().base().commonProperties.DebugName = name 767} 768 769func (b *bottomUpMutatorContext) createModule(factory blueprint.ModuleFactory, name string, props ...interface{}) blueprint.Module { 770 return b.bp.CreateModule(factory, name, props...) 771} 772 773func (b *bottomUpMutatorContext) createModuleInDirectory(factory blueprint.ModuleFactory, name string, _ string, props ...interface{}) blueprint.Module { 774 panic("createModuleInDirectory is not implemented for bottomUpMutatorContext") 775} 776 777func (b *bottomUpMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) Module { 778 return createModule(b, factory, "_bottomUpMutatorModule", doesNotSpecifyDirectory(), props...) 779} 780 781func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module { 782 if b.baseModuleContext.checkedMissingDeps() { 783 panic("Adding deps not allowed after checking for missing deps") 784 } 785 return b.bp.AddDependency(module, tag, name...) 786} 787 788func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) { 789 if b.baseModuleContext.checkedMissingDeps() { 790 panic("Adding deps not allowed after checking for missing deps") 791 } 792 b.bp.AddReverseDependency(module, tag, name) 793} 794 795func (b *bottomUpMutatorContext) AddReverseVariationDependency(variations []blueprint.Variation, tag blueprint.DependencyTag, name string) { 796 if b.baseModuleContext.checkedMissingDeps() { 797 panic("Adding deps not allowed after checking for missing deps") 798 } 799 b.bp.AddReverseVariationDependency(variations, tag, name) 800} 801 802func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, 803 names ...string) []blueprint.Module { 804 if b.baseModuleContext.checkedMissingDeps() { 805 panic("Adding deps not allowed after checking for missing deps") 806 } 807 return b.bp.AddVariationDependencies(variations, tag, names...) 808} 809 810func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation, 811 tag blueprint.DependencyTag, names ...string) []blueprint.Module { 812 if b.baseModuleContext.checkedMissingDeps() { 813 panic("Adding deps not allowed after checking for missing deps") 814 } 815 816 return b.bp.AddFarVariationDependencies(variations, tag, names...) 817} 818 819func (b *bottomUpMutatorContext) ReplaceDependencies(name string) { 820 if b.baseModuleContext.checkedMissingDeps() { 821 panic("Adding deps not allowed after checking for missing deps") 822 } 823 b.bp.ReplaceDependencies(name) 824} 825 826func (b *bottomUpMutatorContext) ReplaceDependenciesIf(name string, predicate blueprint.ReplaceDependencyPredicate) { 827 if b.baseModuleContext.checkedMissingDeps() { 828 panic("Adding deps not allowed after checking for missing deps") 829 } 830 b.bp.ReplaceDependenciesIf(name, predicate) 831} 832