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