1// Copyright 2016 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package android 16 17import ( 18 "fmt" 19 "reflect" 20 "strings" 21 22 "github.com/google/blueprint" 23 "github.com/google/blueprint/proptools" 24) 25 26// This file implements common functionality for handling modules that may exist as prebuilts, 27// source, or both. 28 29func RegisterPrebuiltMutators(ctx RegistrationContext) { 30 ctx.PreArchMutators(RegisterPrebuiltsPreArchMutators) 31 ctx.PreDepsMutators(RegisterPrebuiltsPreDepsMutators) 32 ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators) 33} 34 35// Marks a dependency tag as possibly preventing a reference to a source from being 36// replaced with the prebuilt. 37type ReplaceSourceWithPrebuilt interface { 38 blueprint.DependencyTag 39 40 // Return true if the dependency defined by this tag should be replaced with the 41 // prebuilt. 42 ReplaceSourceWithPrebuilt() bool 43} 44 45type prebuiltDependencyTag struct { 46 blueprint.BaseDependencyTag 47} 48 49var PrebuiltDepTag prebuiltDependencyTag 50 51// Mark this tag so dependencies that use it are excluded from visibility enforcement. 52func (t prebuiltDependencyTag) ExcludeFromVisibilityEnforcement() {} 53 54// Mark this tag so dependencies that use it are excluded from APEX contents. 55func (t prebuiltDependencyTag) ExcludeFromApexContents() {} 56 57var _ ExcludeFromVisibilityEnforcementTag = PrebuiltDepTag 58var _ ExcludeFromApexContentsTag = PrebuiltDepTag 59 60// UserSuppliedPrebuiltProperties contains the prebuilt properties that can be specified in an 61// Android.bp file. 62type UserSuppliedPrebuiltProperties struct { 63 // When prefer is set to true the prebuilt will be used instead of any source module with 64 // a matching name. 65 Prefer proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` 66 67 // When specified this names a Soong config variable that controls the prefer property. 68 // 69 // If the value of the named Soong config variable is true then prefer is set to false and vice 70 // versa. If the Soong config variable is not set then it defaults to false, so prefer defaults 71 // to true. 72 // 73 // If specified then the prefer property is ignored in favor of the value of the Soong config 74 // variable. 75 // 76 // DEPRECATED: This property is being deprecated b/308188211. 77 // Use RELEASE_APEX_CONTRIBUTIONS build flags to select prebuilts of mainline modules. 78 Use_source_config_var *ConfigVarProperties 79} 80 81// CopyUserSuppliedPropertiesFromPrebuilt copies the user supplied prebuilt properties from the 82// prebuilt properties. 83func (u *UserSuppliedPrebuiltProperties) CopyUserSuppliedPropertiesFromPrebuilt(p *Prebuilt) { 84 *u = p.properties.UserSuppliedPrebuiltProperties 85} 86 87type PrebuiltProperties struct { 88 UserSuppliedPrebuiltProperties 89 90 SourceExists bool `blueprint:"mutated"` 91 UsePrebuilt bool `blueprint:"mutated"` 92 93 // Set if the module has been renamed to remove the "prebuilt_" prefix. 94 PrebuiltRenamedToSource bool `blueprint:"mutated"` 95} 96 97// Properties that can be used to select a Soong config variable. 98type ConfigVarProperties struct { 99 // Allow instances of this struct to be used as a property value in a BpPropertySet. 100 BpPrintableBase 101 102 // The name of the configuration namespace. 103 // 104 // As passed to add_soong_config_namespace in Make. 105 Config_namespace *string 106 107 // The name of the configuration variable. 108 // 109 // As passed to add_soong_config_var_value in Make. 110 Var_name *string 111} 112 113type Prebuilt struct { 114 properties PrebuiltProperties 115 116 // nil if the prebuilt has no srcs property at all. See InitPrebuiltModuleWithoutSrcs. 117 srcsSupplier PrebuiltSrcsSupplier 118 119 // "-" if the prebuilt has no srcs property at all. See InitPrebuiltModuleWithoutSrcs. 120 srcsPropertyName string 121} 122 123// RemoveOptionalPrebuiltPrefix returns the result of removing the "prebuilt_" prefix from the 124// supplied name if it has one, or returns the name unmodified if it does not. 125func RemoveOptionalPrebuiltPrefix(name string) string { 126 return strings.TrimPrefix(name, "prebuilt_") 127} 128 129// RemoveOptionalPrebuiltPrefixFromBazelLabel removes the "prebuilt_" prefix from the *target name* of a Bazel label. 130// This differs from RemoveOptionalPrebuiltPrefix in that it does not remove it from the start of the string, but 131// instead removes it from the target name itself. 132func RemoveOptionalPrebuiltPrefixFromBazelLabel(label string) string { 133 splitLabel := strings.Split(label, ":") 134 bazelModuleNameNoPrebuilt := RemoveOptionalPrebuiltPrefix(splitLabel[1]) 135 return strings.Join([]string{ 136 splitLabel[0], 137 bazelModuleNameNoPrebuilt, 138 }, ":") 139} 140 141func (p *Prebuilt) Name(name string) string { 142 return PrebuiltNameFromSource(name) 143} 144 145// PrebuiltNameFromSource returns the result of prepending the "prebuilt_" prefix to the supplied 146// name. 147func PrebuiltNameFromSource(name string) string { 148 return "prebuilt_" + name 149} 150 151func (p *Prebuilt) ForcePrefer() { 152 p.properties.Prefer = NewSimpleConfigurable(true) 153} 154 155// SingleSourcePathFromSupplier invokes the supplied supplier for the current module in the 156// supplied context to retrieve a list of file paths, ensures that the returned list of file paths 157// contains a single value and then assumes that is a module relative file path and converts it to 158// a Path accordingly. 159// 160// Any issues, such as nil supplier or not exactly one file path will be reported as errors on the 161// supplied context and this will return nil. 162func SingleSourcePathFromSupplier(ctx ModuleContext, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) Path { 163 if srcsSupplier != nil { 164 srcs := srcsSupplier(ctx, ctx.Module()) 165 166 if len(srcs) == 0 { 167 ctx.PropertyErrorf(srcsPropertyName, "missing prebuilt source file") 168 return nil 169 } 170 171 if len(srcs) > 1 { 172 ctx.PropertyErrorf(srcsPropertyName, "multiple prebuilt source files") 173 return nil 174 } 175 176 // Return the singleton source after expanding any filegroup in the 177 // sources. 178 src := srcs[0] 179 return PathForModuleSrc(ctx, src) 180 } else { 181 ctx.ModuleErrorf("prebuilt source was not set") 182 return nil 183 } 184} 185 186// The below source-related functions and the srcs, src fields are based on an assumption that 187// prebuilt modules have a static source property at the moment. Currently there is only one 188// exception, android_app_import, which chooses a source file depending on the product's DPI 189// preference configs. We'll want to add native support for dynamic source cases if we end up having 190// more modules like this. 191func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { 192 return SingleSourcePathFromSupplier(ctx, p.srcsSupplier, p.srcsPropertyName) 193} 194 195func (p *Prebuilt) UsePrebuilt() bool { 196 return p.properties.UsePrebuilt 197} 198 199func (p *Prebuilt) SetUsePrebuilt(use bool) { 200 p.properties.UsePrebuilt = use 201} 202 203// Called to provide the srcs value for the prebuilt module. 204// 205// This can be called with a context for any module not just the prebuilt one itself. It can also be 206// called concurrently. 207// 208// Return the src value or nil if it is not available. 209type PrebuiltSrcsSupplier func(ctx BaseModuleContext, prebuilt Module) []string 210 211func initPrebuiltModuleCommon(module PrebuiltInterface) *Prebuilt { 212 p := module.Prebuilt() 213 module.AddProperties(&p.properties) 214 return p 215} 216 217// Initialize the module as a prebuilt module that has no dedicated property that lists its 218// sources. SingleSourcePathFromSupplier should not be called for this module. 219// 220// This is the case e.g. for header modules, which provides the headers in source form 221// regardless whether they are prebuilt or not. 222func InitPrebuiltModuleWithoutSrcs(module PrebuiltInterface) { 223 p := initPrebuiltModuleCommon(module) 224 p.srcsPropertyName = "-" 225} 226 227// Initialize the module as a prebuilt module that uses the provided supplier to access the 228// prebuilt sources of the module. 229// 230// The supplier will be called multiple times and must return the same values each time it 231// is called. If it returns an empty array (or nil) then the prebuilt module will not be used 232// as a replacement for a source module with the same name even if prefer = true. 233// 234// If the Prebuilt.SingleSourcePath() is called on the module then this must return an array 235// containing exactly one source file. 236// 237// The provided property name is used to provide helpful error messages in the event that 238// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided. 239func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) { 240 if srcsSupplier == nil { 241 panic(fmt.Errorf("srcsSupplier must not be nil")) 242 } 243 if srcsPropertyName == "" { 244 panic(fmt.Errorf("srcsPropertyName must not be empty")) 245 } 246 247 p := initPrebuiltModuleCommon(module) 248 p.srcsSupplier = srcsSupplier 249 p.srcsPropertyName = srcsPropertyName 250} 251 252// InitPrebuiltModule is the same as InitPrebuiltModuleWithSrcSupplier, but uses the 253// provided list of strings property as the source provider. 254func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { 255 if srcs == nil { 256 panic(fmt.Errorf("srcs must not be nil")) 257 } 258 259 srcsSupplier := func(ctx BaseModuleContext, _ Module) []string { 260 return *srcs 261 } 262 263 InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs") 264} 265 266// InitConfigurablePrebuiltModule is the same as InitPrebuiltModule, but uses a 267// Configurable list of strings property instead of a regular list of strings. 268func InitConfigurablePrebuiltModule(module PrebuiltInterface, srcs *proptools.Configurable[[]string]) { 269 if srcs == nil { 270 panic(fmt.Errorf("srcs must not be nil")) 271 } 272 273 srcsSupplier := func(ctx BaseModuleContext, _ Module) []string { 274 return srcs.GetOrDefault(ctx, nil) 275 } 276 277 InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs") 278} 279 280// InitConfigurablePrebuiltModuleString is the same as InitPrebuiltModule, but uses a 281// Configurable string property instead of a regular list of strings. It only produces a single 282// source file. 283func InitConfigurablePrebuiltModuleString(module PrebuiltInterface, srcs *proptools.Configurable[string], propertyName string) { 284 if srcs == nil { 285 panic(fmt.Errorf("%s must not be nil", propertyName)) 286 } 287 288 srcsSupplier := func(ctx BaseModuleContext, _ Module) []string { 289 src := srcs.GetOrDefault(ctx, "") 290 if src == "" { 291 return nil 292 } 293 return []string{src} 294 } 295 296 InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, propertyName) 297} 298 299func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) { 300 srcPropsValue := reflect.ValueOf(srcProps).Elem() 301 srcStructField, _ := srcPropsValue.Type().FieldByName(srcField) 302 if !srcPropsValue.IsValid() || srcStructField.Name == "" { 303 panic(fmt.Errorf("invalid single source prebuilt %+v", module)) 304 } 305 306 if srcPropsValue.Kind() != reflect.Struct && srcPropsValue.Kind() != reflect.Interface { 307 panic(fmt.Errorf("invalid single source prebuilt %+v", srcProps)) 308 } 309 310 srcFieldIndex := srcStructField.Index 311 srcPropertyName := proptools.PropertyNameForField(srcField) 312 313 srcsSupplier := func(ctx BaseModuleContext, _ Module) []string { 314 if !module.Enabled(ctx) { 315 return nil 316 } 317 value := srcPropsValue.FieldByIndex(srcFieldIndex) 318 if value.Kind() == reflect.Ptr { 319 if value.IsNil() { 320 return nil 321 } 322 value = value.Elem() 323 } 324 if value.Kind() != reflect.String { 325 panic(fmt.Errorf("prebuilt src field %q in %T in module %s should be a string or a pointer to one but was %v", srcField, srcProps, module, value)) 326 } 327 src := value.String() 328 if src == "" { 329 return nil 330 } 331 return []string{src} 332 } 333 334 InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcPropertyName) 335} 336 337type PrebuiltInterface interface { 338 Module 339 Prebuilt() *Prebuilt 340} 341 342// IsModulePreferred returns true if the given module is preferred. 343// 344// A source module is preferred if there is no corresponding prebuilt module or the prebuilt module 345// does not have "prefer: true". 346// 347// A prebuilt module is preferred if there is no corresponding source module or the prebuilt module 348// has "prefer: true". 349func IsModulePreferred(module Module) bool { 350 if module.IsReplacedByPrebuilt() { 351 // A source module that has been replaced by a prebuilt counterpart. 352 return false 353 } 354 if p := GetEmbeddedPrebuilt(module); p != nil { 355 return p.UsePrebuilt() 356 } 357 return true 358} 359 360func IsModulePreferredProxy(ctx OtherModuleProviderContext, module ModuleProxy) bool { 361 if OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt { 362 // A source module that has been replaced by a prebuilt counterpart. 363 return false 364 } 365 if p, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok { 366 return p.UsePrebuilt 367 } 368 return true 369} 370 371// IsModulePrebuilt returns true if the module implements PrebuiltInterface and 372// has been initialized as a prebuilt and so returns a non-nil value from the 373// PrebuiltInterface.Prebuilt() method. 374func IsModulePrebuilt(module Module) bool { 375 return GetEmbeddedPrebuilt(module) != nil 376} 377 378// GetEmbeddedPrebuilt returns a pointer to the embedded Prebuilt structure or 379// nil if the module does not implement PrebuiltInterface or has not been 380// initialized as a prebuilt module. 381func GetEmbeddedPrebuilt(module Module) *Prebuilt { 382 if p, ok := module.(PrebuiltInterface); ok { 383 return p.Prebuilt() 384 } 385 386 return nil 387} 388 389// PrebuiltGetPreferred returns the module that is preferred for the given 390// module. That is either the module itself or the prebuilt counterpart that has 391// taken its place. The given module must be a direct dependency of the current 392// context module, and it must be the source module if both source and prebuilt 393// exist. 394// 395// This function is for use on dependencies after PrebuiltPostDepsMutator has 396// run - any dependency that is registered before that will already reference 397// the right module. This function is only safe to call after all TransitionMutators 398// have run, e.g. in GenerateAndroidBuildActions. 399func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module { 400 if !OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt { 401 return module 402 } 403 if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok { 404 // If we're given a prebuilt then assume there's no source module around. 405 return module 406 } 407 408 sourceModDepFound := false 409 var prebuiltMod Module 410 411 ctx.WalkDepsProxy(func(child, parent ModuleProxy) bool { 412 if prebuiltMod != nil { 413 return false 414 } 415 if EqualModules(parent, ctx.Module()) { 416 // First level: Only recurse if the module is found as a direct dependency. 417 sourceModDepFound = child == module 418 return sourceModDepFound 419 } 420 // Second level: Follow PrebuiltDepTag to the prebuilt. 421 if t := ctx.OtherModuleDependencyTag(child); t == PrebuiltDepTag { 422 prebuiltMod = child 423 } 424 return false 425 }) 426 427 if prebuiltMod == nil { 428 if !sourceModDepFound { 429 panic(fmt.Errorf("Failed to find source module as a direct dependency: %s", module)) 430 } else { 431 panic(fmt.Errorf("Failed to find prebuilt for source module: %s", module)) 432 } 433 } 434 return prebuiltMod 435} 436 437func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) { 438 ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).UsesRename() 439} 440 441func RegisterPrebuiltsPreDepsMutators(ctx RegisterMutatorsContext) { 442 ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).UsesReverseDependencies() 443 ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator) 444} 445 446func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) { 447 ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).UsesReplaceDependencies() 448} 449 450// Returns the name of the source module corresponding to a prebuilt module 451// For source modules, it returns its own name 452type baseModuleName interface { 453 BaseModuleName() string 454} 455 456// PrebuiltRenameMutator ensures that there always is a module with an 457// undecorated name. 458func PrebuiltRenameMutator(ctx BottomUpMutatorContext) { 459 m := ctx.Module() 460 if p := GetEmbeddedPrebuilt(m); p != nil { 461 bmn, _ := m.(baseModuleName) 462 name := bmn.BaseModuleName() 463 if !ctx.OtherModuleExists(name) { 464 ctx.Rename(name) 465 p.properties.PrebuiltRenamedToSource = true 466 } 467 } 468} 469 470// PrebuiltSourceDepsMutator adds dependencies to the prebuilt module from the 471// corresponding source module, if one exists for the same variant. 472// Add a dependency from the prebuilt to `all_apex_contributions` 473// The metadata will be used for source vs prebuilts selection 474func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) { 475 m := ctx.Module() 476 if p := GetEmbeddedPrebuilt(m); p != nil { 477 // Add a dependency from the prebuilt to the `all_apex_contributions` 478 // metadata module 479 // TODO: When all branches contain this singleton module, make this strict 480 // TODO: Add this dependency only for mainline prebuilts and not every prebuilt module 481 if ctx.OtherModuleExists("all_apex_contributions") { 482 ctx.AddDependency(m, AcDepTag, "all_apex_contributions") 483 } 484 if m.Enabled(ctx) && !p.properties.PrebuiltRenamedToSource { 485 // If this module is a prebuilt, is enabled and has not been renamed to source then add a 486 // dependency onto the source if it is present. 487 bmn, _ := m.(baseModuleName) 488 name := bmn.BaseModuleName() 489 if ctx.OtherModuleReverseDependencyVariantExists(name) { 490 ctx.AddReverseVariationDependency(nil, PrebuiltDepTag, name) 491 p.properties.SourceExists = true 492 } 493 } 494 } 495} 496 497// checkInvariantsForSourceAndPrebuilt checks if invariants are kept when replacing 498// source with prebuilt. Note that the current module for the context is the source module. 499func checkInvariantsForSourceAndPrebuilt(ctx BaseModuleContext, s, p Module) { 500 if _, ok := s.(OverrideModule); ok { 501 // skip the check when the source module is `override_X` because it's only a placeholder 502 // for the actual source module. The check will be invoked for the actual module. 503 return 504 } 505 if sourcePartition, prebuiltPartition := s.PartitionTag(ctx.DeviceConfig()), p.PartitionTag(ctx.DeviceConfig()); sourcePartition != prebuiltPartition { 506 ctx.OtherModuleErrorf(p, "partition is different: %s(%s) != %s(%s)", 507 sourcePartition, ctx.ModuleName(), prebuiltPartition, ctx.OtherModuleName(p)) 508 } 509} 510 511// PrebuiltSelectModuleMutator marks prebuilts that are used, either overriding source modules or 512// because the source module doesn't exist. It also disables installing overridden source modules. 513// 514// If the visited module is the metadata module `all_apex_contributions`, it sets a 515// provider containing metadata about whether source or prebuilt of mainline modules should be used. 516// This logic was added here to prevent the overhead of creating a new mutator. 517func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) { 518 m := ctx.Module() 519 if p := GetEmbeddedPrebuilt(m); p != nil { 520 if p.srcsSupplier == nil && p.srcsPropertyName == "" { 521 panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it")) 522 } 523 if !p.properties.SourceExists { 524 p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil, m) 525 } 526 // Propagate the provider received from `all_apex_contributions` 527 // to the source module 528 ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) { 529 psi, _ := OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) 530 SetProvider(ctx, PrebuiltSelectionInfoProvider, psi) 531 }) 532 533 } else if s, ok := ctx.Module().(Module); ok { 534 // Use `all_apex_contributions` for source vs prebuilt selection. 535 psi := PrebuiltSelectionInfoMap{} 536 ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(am Module) { 537 // The value of psi gets overwritten with the provider from the last visited prebuilt. 538 // But all prebuilts have the same value of the provider, so this should be idempontent. 539 psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) 540 }) 541 ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) { 542 p := GetEmbeddedPrebuilt(prebuiltModule) 543 if p.usePrebuilt(ctx, s, prebuiltModule) { 544 checkInvariantsForSourceAndPrebuilt(ctx, s, prebuiltModule) 545 546 p.properties.UsePrebuilt = true 547 s.ReplacedByPrebuilt() 548 } 549 }) 550 551 // If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family 552 // Add source 553 allModules := []Module{s} 554 // Add each prebuilt 555 ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) { 556 allModules = append(allModules, prebuiltModule) 557 }) 558 hideUnflaggedModules(ctx, psi, allModules) 559 560 } 561 562 // If this is `all_apex_contributions`, set a provider containing 563 // metadata about source vs prebuilts selection 564 if am, ok := m.(*allApexContributions); ok { 565 am.SetPrebuiltSelectionInfoProvider(ctx) 566 } 567} 568 569// If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family 570func hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoMap, allModulesInFamily []Module) { 571 var selectedModuleInFamily Module 572 // query all_apex_contributions to see if any module in this family has been selected 573 for _, moduleInFamily := range allModulesInFamily { 574 // validate that are no duplicates 575 if isSelected(psi, moduleInFamily) { 576 if selectedModuleInFamily == nil { 577 // Store this so we can validate that there are no duplicates 578 selectedModuleInFamily = moduleInFamily 579 } else { 580 // There are duplicate modules from the same mainline module family 581 ctx.ModuleErrorf("Found duplicate variations of the same module in apex_contributions: %s and %s. Please remove one of these.\n", selectedModuleInFamily.Name(), moduleInFamily.Name()) 582 } 583 } 584 } 585 586 // If a module has been selected, hide all other modules 587 if selectedModuleInFamily != nil { 588 for _, moduleInFamily := range allModulesInFamily { 589 if moduleInFamily.Name() != selectedModuleInFamily.Name() { 590 moduleInFamily.HideFromMake() 591 moduleInFamily.SkipInstall() 592 // If this is a prebuilt module, unset properties.UsePrebuilt 593 // properties.UsePrebuilt might evaluate to true via soong config var fallback mechanism 594 // Set it to false explicitly so that the following mutator does not replace rdeps to this unselected prebuilt 595 if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil { 596 p.properties.UsePrebuilt = false 597 } 598 } 599 } 600 } 601 // Do a validation pass to make sure that multiple prebuilts of a specific module are not selected. 602 // This might happen if the prebuilts share the same soong config var namespace. 603 // This should be an error, unless one of the prebuilts has been explicitly declared in apex_contributions 604 var selectedPrebuilt Module 605 for _, moduleInFamily := range allModulesInFamily { 606 // Skip if this module is in a different namespace 607 if !moduleInFamily.ExportedToMake() { 608 continue 609 } 610 if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil && p.properties.UsePrebuilt { 611 if selectedPrebuilt == nil { 612 selectedPrebuilt = moduleInFamily 613 } else { 614 ctx.ModuleErrorf("Multiple prebuilt modules %v and %v have been marked as preferred for this source module. "+ 615 "Please add the appropriate prebuilt module to apex_contributions for this release config.", selectedPrebuilt.Name(), moduleInFamily.Name()) 616 } 617 } 618 } 619} 620 621func IsDontReplaceSourceWithPrebuiltTag(tag blueprint.DependencyTag) bool { 622 if t, ok := tag.(ReplaceSourceWithPrebuilt); ok { 623 return !t.ReplaceSourceWithPrebuilt() 624 } 625 return false 626} 627 628// PrebuiltPostDepsMutator replaces dependencies on the source module with dependencies on the 629// prebuilt when both modules exist and the prebuilt should be used. When the prebuilt should not 630// be used, disable installing it. 631func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { 632 m := ctx.Module() 633 if p := GetEmbeddedPrebuilt(m); p != nil { 634 bmn, _ := m.(baseModuleName) 635 name := bmn.BaseModuleName() 636 637 if p.properties.UsePrebuilt { 638 if p.properties.SourceExists { 639 ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool { 640 if t, ok := tag.(ReplaceSourceWithPrebuilt); ok { 641 return t.ReplaceSourceWithPrebuilt() 642 } 643 return true 644 }) 645 } 646 } else { 647 m.HideFromMake() 648 m.SkipInstall() 649 } 650 } 651} 652 653// A wrapper around PrebuiltSelectionInfoMap.IsSelected with special handling for java_sdk_library 654// java_sdk_library is a macro that creates 655// 1. top-level impl library 656// 2. stub libraries (suffixed with .stubs...) 657// 658// java_sdk_library_import is a macro that creates 659// 1. top-level "impl" library 660// 2. stub libraries (suffixed with .stubs...) 661func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool { 662 if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { 663 sln := proptools.String(sdkLibrary.SdkLibraryName()) 664 665 // This is the top-level library 666 if bmn, ok := m.(baseModuleName); ok && sln == bmn.BaseModuleName() { 667 return psi.IsSelected(m.Name()) 668 } 669 670 // Stub library created by java_sdk_library_import 671 // java_sdk_library creates several child modules (java_import + prebuilt_stubs_sources) dynamically. 672 // This code block ensures that these child modules are selected if the top-level java_sdk_library_import is listed 673 // in the selected apex_contributions. 674 if javaImport, ok := m.(createdByJavaSdkLibraryName); ok && javaImport.CreatedByJavaSdkLibraryName() != nil { 675 return psi.IsSelected(PrebuiltNameFromSource(proptools.String(javaImport.CreatedByJavaSdkLibraryName()))) 676 } 677 678 // Stub library created by java_sdk_library 679 return psi.IsSelected(sln) 680 } 681 return psi.IsSelected(m.Name()) 682} 683 684// implemented by child modules of java_sdk_library_import 685type createdByJavaSdkLibraryName interface { 686 CreatedByJavaSdkLibraryName() *string 687} 688 689// Returns true if the prebuilt variant is disabled 690// e.g. for a cc_prebuilt_library_shared, this will return 691// - true for the static variant of the module 692// - false for the shared variant of the module 693// 694// Even though this is a cc_prebuilt_library_shared, we create both the variants today 695// https://source.corp.google.com/h/googleplex-android/platform/build/soong/+/e08e32b45a18a77bc3c3e751f730539b1b374f1b:cc/library.go;l=2113-2116;drc=2c4a9779cd1921d0397a12b3d3521f4c9b30d747;bpv=1;bpt=0 696func (p *Prebuilt) variantIsDisabled(ctx BaseModuleContext, prebuilt Module) bool { 697 return p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 698} 699 700type apexVariationName interface { 701 ApexVariationName() string 702} 703 704// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt 705// will be used if it is marked "prefer" or if the source module is disabled. 706func (p *Prebuilt) usePrebuilt(ctx BaseModuleContext, source Module, prebuilt Module) bool { 707 isMainlinePrebuilt := func(prebuilt Module) bool { 708 apex, ok := prebuilt.(apexVariationName) 709 if !ok { 710 return false 711 } 712 // Prebuilts of aosp apexes in prebuilts/runtime 713 // Used in minimal art branches 714 if prebuilt.base().BaseModuleName() == apex.ApexVariationName() { 715 return false 716 } 717 return InList(apex.ApexVariationName(), ctx.Config().AllMainlineApexNames()) 718 } 719 720 // Use `all_apex_contributions` for source vs prebuilt selection. 721 psi := PrebuiltSelectionInfoMap{} 722 var psiDepTag blueprint.DependencyTag 723 if p := GetEmbeddedPrebuilt(ctx.Module()); p != nil { 724 // This is a prebuilt module, visit all_apex_contributions to get the info 725 psiDepTag = AcDepTag 726 } else { 727 // This is a source module, visit any of its prebuilts to get the info 728 psiDepTag = PrebuiltDepTag 729 } 730 ctx.VisitDirectDepsWithTag(psiDepTag, func(am Module) { 731 psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) 732 }) 733 734 // If the source module is explicitly listed in the metadata module, use that 735 if source != nil && isSelected(psi, source) { 736 return false 737 } 738 // If the prebuilt module is explicitly listed in the metadata module, use that 739 if isSelected(psi, prebuilt) && !p.variantIsDisabled(ctx, prebuilt) { 740 return true 741 } 742 743 // If this is a mainline prebuilt, but has not been flagged, hide it. 744 if isMainlinePrebuilt(prebuilt) { 745 return false 746 } 747 748 // If the baseModuleName could not be found in the metadata module, 749 // fall back to the existing source vs prebuilt selection. 750 // TODO: Drop the fallback mechanisms 751 752 if p.variantIsDisabled(ctx, prebuilt) { 753 return false 754 } 755 756 // Skip prebuilt modules under unexported namespaces so that we won't 757 // end up shadowing non-prebuilt module when prebuilt module under same 758 // name happens to have a `Prefer` property set to true. 759 if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() { 760 return false 761 } 762 763 // If source is not available or is disabled then always use the prebuilt. 764 if source == nil || !source.Enabled(ctx) { 765 return true 766 } 767 768 // TODO: use p.Properties.Name and ctx.ModuleDir to override preference 769 return p.properties.Prefer.GetOrDefault(ctx, false) 770} 771 772func (p *Prebuilt) SourceExists() bool { 773 return p.properties.SourceExists 774} 775