1// Copyright 2020 The Android Open Source Project 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. 14package cc 15 16// This file contains image variant related things, including image mutator functions, utility 17// functions to determine where a module is installed, etc. 18 19import ( 20 "strings" 21 22 "android/soong/android" 23 24 "github.com/google/blueprint/proptools" 25) 26 27var _ android.ImageInterface = (*Module)(nil) 28 29type ImageVariantType string 30 31const ( 32 coreImageVariant ImageVariantType = "core" 33 vendorImageVariant ImageVariantType = "vendor" 34 productImageVariant ImageVariantType = "product" 35 ramdiskImageVariant ImageVariantType = "ramdisk" 36 vendorRamdiskImageVariant ImageVariantType = "vendor_ramdisk" 37 recoveryImageVariant ImageVariantType = "recovery" 38 hostImageVariant ImageVariantType = "host" 39) 40 41const ( 42 // VendorVariation is the variant name used for /vendor code that does not 43 // compile against the VNDK. 44 VendorVariation = "vendor" 45 46 // VendorVariationPrefix is the variant prefix used for /vendor code that compiles 47 // against the VNDK. 48 VendorVariationPrefix = "vendor." 49 50 // ProductVariation is the variant name used for /product code that does not 51 // compile against the VNDK. 52 ProductVariation = "product" 53 54 // ProductVariationPrefix is the variant prefix used for /product code that compiles 55 // against the VNDK. 56 ProductVariationPrefix = "product." 57) 58 59func (ctx *moduleContextImpl) inProduct() bool { 60 return ctx.mod.InProduct() 61} 62 63func (ctx *moduleContextImpl) inVendor() bool { 64 return ctx.mod.InVendor() 65} 66 67func (ctx *moduleContextImpl) inRamdisk() bool { 68 return ctx.mod.InRamdisk() 69} 70 71func (ctx *moduleContextImpl) inVendorRamdisk() bool { 72 return ctx.mod.InVendorRamdisk() 73} 74 75func (ctx *moduleContextImpl) inRecovery() bool { 76 return ctx.mod.InRecovery() 77} 78 79func (c *Module) InstallInProduct() bool { 80 // Additionally check if this module is inProduct() that means it is a "product" variant of a 81 // module. As well as product specific modules, product variants must be installed to /product. 82 return c.InProduct() 83} 84 85func (c *Module) InstallInVendor() bool { 86 // Additionally check if this module is inVendor() that means it is a "vendor" variant of a 87 // module. As well as SoC specific modules, vendor variants must be installed to /vendor 88 // unless they have "odm_available: true". 89 return c.HasVendorVariant() && c.InVendor() && !c.VendorVariantToOdm() 90} 91 92func (c *Module) InstallInOdm() bool { 93 // Some vendor variants want to be installed to /odm by setting "odm_available: true". 94 return c.InVendor() && c.VendorVariantToOdm() 95} 96 97// Returns true when this module is configured to have core and vendor variants. 98func (c *Module) HasVendorVariant() bool { 99 return Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Odm_available) 100} 101 102// Returns true when this module creates a vendor variant and wants to install the vendor variant 103// to the odm partition. 104func (c *Module) VendorVariantToOdm() bool { 105 return Bool(c.VendorProperties.Odm_available) 106} 107 108// Returns true when this module is configured to have core and product variants. 109func (c *Module) HasProductVariant() bool { 110 return Bool(c.VendorProperties.Product_available) 111} 112 113// Returns true when this module is configured to have core and either product or vendor variants. 114func (c *Module) HasNonSystemVariants() bool { 115 return c.HasVendorVariant() || c.HasProductVariant() 116} 117 118// Returns true if the module is "product" variant. Usually these modules are installed in /product 119func (c *Module) InProduct() bool { 120 return c.Properties.ImageVariation == ProductVariation 121} 122 123// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor 124func (c *Module) InVendor() bool { 125 return c.Properties.ImageVariation == VendorVariation 126} 127 128// Returns true if the module is "vendor" or "product" variant. This replaces previous UseVndk usages 129// which were misused to check if the module variant is vendor or product. 130func (c *Module) InVendorOrProduct() bool { 131 return c.InVendor() || c.InProduct() 132} 133 134func (c *Module) InRamdisk() bool { 135 return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk() 136} 137 138func (c *Module) InVendorRamdisk() bool { 139 return c.ModuleBase.InVendorRamdisk() || c.ModuleBase.InstallInVendorRamdisk() 140} 141 142func (c *Module) InRecovery() bool { 143 return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery() 144} 145 146func (c *Module) OnlyInRamdisk() bool { 147 return c.ModuleBase.InstallInRamdisk() 148} 149 150func (c *Module) OnlyInVendorRamdisk() bool { 151 return c.ModuleBase.InstallInVendorRamdisk() 152} 153 154func (c *Module) OnlyInRecovery() bool { 155 return c.ModuleBase.InstallInRecovery() 156} 157 158// ImageMutatableModule provides a common image mutation interface for LinkableInterface modules. 159type ImageMutatableModule interface { 160 android.Module 161 LinkableInterface 162 163 // AndroidModuleBase returns the android.ModuleBase for this module 164 AndroidModuleBase() *android.ModuleBase 165 166 // VendorAvailable returns true if this module is available on the vendor image. 167 VendorAvailable() bool 168 169 // OdmAvailable returns true if this module is available on the odm image. 170 OdmAvailable() bool 171 172 // ProductAvailable returns true if this module is available on the product image. 173 ProductAvailable() bool 174 175 // RamdiskAvailable returns true if this module is available on the ramdisk image. 176 RamdiskAvailable() bool 177 178 // RecoveryAvailable returns true if this module is available on the recovery image. 179 RecoveryAvailable() bool 180 181 // VendorRamdiskAvailable returns true if this module is available on the vendor ramdisk image. 182 VendorRamdiskAvailable() bool 183 184 // IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt. 185 IsSnapshotPrebuilt() bool 186 187 // SnapshotVersion returns the snapshot version for this module. 188 SnapshotVersion(mctx android.BaseModuleContext) string 189 190 // SdkVersion returns the SDK version for this module. 191 SdkVersion() string 192 193 // ExtraVariants returns the list of extra variants this module requires. 194 ExtraVariants() []string 195 196 // AppendExtraVariant returns an extra variant to the list of extra variants this module requires. 197 AppendExtraVariant(extraVariant string) 198 199 // SetRamdiskVariantNeeded sets whether the Ramdisk Variant is needed. 200 SetRamdiskVariantNeeded(b bool) 201 202 // SetVendorRamdiskVariantNeeded sets whether the Vendor Ramdisk Variant is needed. 203 SetVendorRamdiskVariantNeeded(b bool) 204 205 // SetRecoveryVariantNeeded sets whether the Recovery Variant is needed. 206 SetRecoveryVariantNeeded(b bool) 207 208 // SetCoreVariantNeeded sets whether the Core Variant is needed. 209 SetCoreVariantNeeded(b bool) 210} 211 212var _ ImageMutatableModule = (*Module)(nil) 213 214func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { 215 MutateImage(mctx, m) 216} 217 218func (m *Module) VendorAvailable() bool { 219 return Bool(m.VendorProperties.Vendor_available) 220} 221 222func (m *Module) OdmAvailable() bool { 223 return Bool(m.VendorProperties.Odm_available) 224} 225 226func (m *Module) ProductAvailable() bool { 227 return Bool(m.VendorProperties.Product_available) 228} 229 230func (m *Module) RamdiskAvailable() bool { 231 return Bool(m.Properties.Ramdisk_available) 232} 233 234func (m *Module) VendorRamdiskAvailable() bool { 235 return Bool(m.Properties.Vendor_ramdisk_available) 236} 237 238func (m *Module) AndroidModuleBase() *android.ModuleBase { 239 return &m.ModuleBase 240} 241 242func (m *Module) RecoveryAvailable() bool { 243 return Bool(m.Properties.Recovery_available) 244} 245 246func (m *Module) ExtraVariants() []string { 247 return m.Properties.ExtraVersionedImageVariations 248} 249 250func (m *Module) AppendExtraVariant(extraVariant string) { 251 m.Properties.ExtraVersionedImageVariations = append(m.Properties.ExtraVersionedImageVariations, extraVariant) 252} 253 254func (m *Module) SetRamdiskVariantNeeded(b bool) { 255 m.Properties.RamdiskVariantNeeded = b 256} 257 258func (m *Module) SetVendorRamdiskVariantNeeded(b bool) { 259 m.Properties.VendorRamdiskVariantNeeded = b 260} 261 262func (m *Module) SetRecoveryVariantNeeded(b bool) { 263 m.Properties.RecoveryVariantNeeded = b 264} 265 266func (m *Module) SetCoreVariantNeeded(b bool) { 267 m.Properties.CoreVariantNeeded = b 268} 269 270func (m *Module) SnapshotVersion(mctx android.BaseModuleContext) string { 271 if snapshot, ok := m.linker.(SnapshotInterface); ok { 272 return snapshot.Version() 273 } else { 274 mctx.ModuleErrorf("version is unknown for snapshot prebuilt") 275 // Should we be panicking here instead? 276 return "" 277 } 278} 279 280func (m *Module) KernelHeadersDecorator() bool { 281 if _, ok := m.linker.(*kernelHeadersDecorator); ok { 282 return true 283 } 284 return false 285} 286 287// MutateImage handles common image mutations for ImageMutatableModule interfaces. 288func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) { 289 // Validation check 290 vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() 291 productSpecific := mctx.ProductSpecific() 292 293 if m.VendorAvailable() { 294 if vendorSpecific { 295 mctx.PropertyErrorf("vendor_available", 296 "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`") 297 } 298 if m.OdmAvailable() { 299 mctx.PropertyErrorf("vendor_available", 300 "doesn't make sense at the same time as `odm_available: true`") 301 } 302 } 303 304 if m.OdmAvailable() { 305 if vendorSpecific { 306 mctx.PropertyErrorf("odm_available", 307 "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`") 308 } 309 } 310 311 if m.ProductAvailable() { 312 if productSpecific { 313 mctx.PropertyErrorf("product_available", 314 "doesn't make sense at the same time as `product_specific: true`") 315 } 316 if vendorSpecific { 317 mctx.PropertyErrorf("product_available", 318 "cannot provide product variant from a vendor module. Please use `product_specific: true` with `vendor_available: true`") 319 } 320 } 321 322 var coreVariantNeeded bool = false 323 var ramdiskVariantNeeded bool = false 324 var vendorRamdiskVariantNeeded bool = false 325 var recoveryVariantNeeded bool = false 326 327 var vendorVariants []string 328 var productVariants []string 329 330 needVndkVersionVendorVariantForLlndk := false 331 332 if m.NeedsLlndkVariants() { 333 // This is an LLNDK library. The implementation of the library will be on /system, 334 // and vendor and product variants will be created with LLNDK stubs. 335 // The LLNDK libraries need vendor variants even if there is no VNDK. 336 coreVariantNeeded = true 337 vendorVariants = append(vendorVariants, "") 338 productVariants = append(productVariants, "") 339 // Generate vendor variants for boardVndkVersion only if the VNDK snapshot does not 340 // provide the LLNDK stub libraries. 341 if needVndkVersionVendorVariantForLlndk { 342 vendorVariants = append(vendorVariants, "") 343 } 344 } else if m.NeedsVendorPublicLibraryVariants() { 345 // A vendor public library has the implementation on /vendor, with stub variants 346 // for system and product. 347 coreVariantNeeded = true 348 vendorVariants = append(vendorVariants, "") 349 productVariants = append(productVariants, "") 350 } else if m.IsSnapshotPrebuilt() { 351 // Make vendor variants only for the versions in BOARD_VNDK_VERSION and 352 // PRODUCT_EXTRA_VNDK_VERSIONS. 353 if m.InstallInRecovery() { 354 recoveryVariantNeeded = true 355 } else { 356 vendorVariants = append(vendorVariants, m.SnapshotVersion(mctx)) 357 } 358 } else if m.HasNonSystemVariants() { 359 // This will be available to /system unless it is product_specific 360 // which will be handled later. 361 coreVariantNeeded = true 362 363 // We assume that modules under proprietary paths are compatible for 364 // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or 365 // PLATFORM_VNDK_VERSION. 366 if m.HasVendorVariant() { 367 vendorVariants = append(vendorVariants, "") 368 } 369 370 // product_available modules are available to /product. 371 if m.HasProductVariant() { 372 productVariants = append(productVariants, "") 373 } 374 } else if vendorSpecific && m.SdkVersion() == "" { 375 // This will be available in /vendor (or /odm) only 376 vendorVariants = append(vendorVariants, "") 377 } else { 378 // This is either in /system (or similar: /data), or is a 379 // module built with the NDK. Modules built with the NDK 380 // will be restricted using the existing link type checks. 381 coreVariantNeeded = true 382 } 383 384 if coreVariantNeeded && productSpecific && m.SdkVersion() == "" { 385 // The module has "product_specific: true" that does not create core variant. 386 coreVariantNeeded = false 387 productVariants = append(productVariants, "") 388 } 389 390 if m.RamdiskAvailable() { 391 ramdiskVariantNeeded = true 392 } 393 394 if m.AndroidModuleBase().InstallInRamdisk() { 395 ramdiskVariantNeeded = true 396 coreVariantNeeded = false 397 } 398 399 if m.VendorRamdiskAvailable() { 400 vendorRamdiskVariantNeeded = true 401 } 402 403 if m.AndroidModuleBase().InstallInVendorRamdisk() { 404 vendorRamdiskVariantNeeded = true 405 coreVariantNeeded = false 406 } 407 408 if m.RecoveryAvailable() { 409 recoveryVariantNeeded = true 410 } 411 412 if m.AndroidModuleBase().InstallInRecovery() { 413 recoveryVariantNeeded = true 414 coreVariantNeeded = false 415 } 416 417 for _, variant := range android.FirstUniqueStrings(vendorVariants) { 418 if variant == "" { 419 m.AppendExtraVariant(VendorVariation) 420 } else { 421 m.AppendExtraVariant(VendorVariationPrefix + variant) 422 } 423 } 424 425 for _, variant := range android.FirstUniqueStrings(productVariants) { 426 if variant == "" { 427 m.AppendExtraVariant(ProductVariation) 428 } else { 429 m.AppendExtraVariant(ProductVariationPrefix + variant) 430 } 431 } 432 433 m.SetRamdiskVariantNeeded(ramdiskVariantNeeded) 434 m.SetVendorRamdiskVariantNeeded(vendorRamdiskVariantNeeded) 435 m.SetRecoveryVariantNeeded(recoveryVariantNeeded) 436 m.SetCoreVariantNeeded(coreVariantNeeded) 437 438 // Disable the module if no variants are needed. 439 if !ramdiskVariantNeeded && 440 !recoveryVariantNeeded && 441 !coreVariantNeeded && 442 len(m.ExtraVariants()) == 0 { 443 m.Disable() 444 } 445} 446 447func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool { 448 return c.Properties.CoreVariantNeeded 449} 450 451func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 452 return c.Properties.RamdiskVariantNeeded 453} 454 455func (c *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 456 return c.Properties.VendorRamdiskVariantNeeded 457} 458 459func (c *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 460 return false 461} 462 463func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { 464 return c.Properties.RecoveryVariantNeeded 465} 466 467func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string { 468 return c.Properties.ExtraVersionedImageVariations 469} 470 471func squashVendorSrcs(m *Module) { 472 if lib, ok := m.compiler.(*libraryDecorator); ok { 473 lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, 474 lib.baseCompiler.Properties.Target.Vendor.Srcs...) 475 476 lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, 477 lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...) 478 479 lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources, 480 lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...) 481 482 if lib.Properties.Target.Vendor.No_stubs { 483 proptools.Clear(&lib.Properties.Stubs) 484 } 485 } 486} 487 488func squashProductSrcs(m *Module) { 489 if lib, ok := m.compiler.(*libraryDecorator); ok { 490 lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, 491 lib.baseCompiler.Properties.Target.Product.Srcs...) 492 493 lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, 494 lib.baseCompiler.Properties.Target.Product.Exclude_srcs...) 495 496 lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources, 497 lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...) 498 499 if lib.Properties.Target.Product.No_stubs { 500 proptools.Clear(&lib.Properties.Stubs) 501 } 502 } 503} 504 505func squashRecoverySrcs(m *Module) { 506 if lib, ok := m.compiler.(*libraryDecorator); ok { 507 lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, 508 lib.baseCompiler.Properties.Target.Recovery.Srcs...) 509 510 lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, 511 lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...) 512 513 lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources, 514 lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...) 515 } 516} 517 518func squashVendorRamdiskSrcs(m *Module) { 519 if lib, ok := m.compiler.(*libraryDecorator); ok { 520 lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs...) 521 } 522} 523 524func squashRamdiskSrcs(m *Module) { 525 if lib, ok := m.compiler.(*libraryDecorator); ok { 526 lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Ramdisk.Exclude_srcs...) 527 } 528} 529 530func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string) { 531 if variant == android.RamdiskVariation { 532 c.MakeAsPlatform() 533 squashRamdiskSrcs(c) 534 } else if variant == android.VendorRamdiskVariation { 535 c.MakeAsPlatform() 536 squashVendorRamdiskSrcs(c) 537 } else if variant == android.RecoveryVariation { 538 c.MakeAsPlatform() 539 squashRecoverySrcs(c) 540 } else if strings.HasPrefix(variant, VendorVariation) { 541 c.Properties.ImageVariation = VendorVariation 542 543 if strings.HasPrefix(variant, VendorVariationPrefix) { 544 c.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix) 545 } 546 squashVendorSrcs(c) 547 } else if strings.HasPrefix(variant, ProductVariation) { 548 c.Properties.ImageVariation = ProductVariation 549 if strings.HasPrefix(variant, ProductVariationPrefix) { 550 c.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix) 551 } 552 squashProductSrcs(c) 553 } 554 555 if c.NeedsVendorPublicLibraryVariants() && 556 (variant == android.CoreVariation || strings.HasPrefix(variant, ProductVariationPrefix)) { 557 c.VendorProperties.IsVendorPublicLibrary = true 558 } 559} 560