| // Copyright 2020 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package cc |
| |
| // This file contains image variant related things, including image mutator functions, utility |
| // functions to determine where a module is installed, etc. |
| |
| import ( |
| "strings" |
| |
| "android/soong/android" |
| |
| "github.com/google/blueprint/proptools" |
| ) |
| |
| var _ android.ImageInterface = (*Module)(nil) |
| |
| type ImageVariantType string |
| |
| const ( |
| coreImageVariant ImageVariantType = "core" |
| vendorImageVariant ImageVariantType = "vendor" |
| productImageVariant ImageVariantType = "product" |
| ramdiskImageVariant ImageVariantType = "ramdisk" |
| vendorRamdiskImageVariant ImageVariantType = "vendor_ramdisk" |
| recoveryImageVariant ImageVariantType = "recovery" |
| hostImageVariant ImageVariantType = "host" |
| ) |
| |
| const ( |
| // VendorVariation is the variant name used for /vendor code that does not |
| // compile against the VNDK. |
| VendorVariation = "vendor" |
| |
| // VendorVariationPrefix is the variant prefix used for /vendor code that compiles |
| // against the VNDK. |
| VendorVariationPrefix = "vendor." |
| |
| // ProductVariation is the variant name used for /product code that does not |
| // compile against the VNDK. |
| ProductVariation = "product" |
| |
| // ProductVariationPrefix is the variant prefix used for /product code that compiles |
| // against the VNDK. |
| ProductVariationPrefix = "product." |
| ) |
| |
| func (ctx *moduleContextImpl) inProduct() bool { |
| return ctx.mod.InProduct() |
| } |
| |
| func (ctx *moduleContextImpl) inVendor() bool { |
| return ctx.mod.InVendor() |
| } |
| |
| func (ctx *moduleContextImpl) inRamdisk() bool { |
| return ctx.mod.InRamdisk() |
| } |
| |
| func (ctx *moduleContextImpl) inVendorRamdisk() bool { |
| return ctx.mod.InVendorRamdisk() |
| } |
| |
| func (ctx *moduleContextImpl) inRecovery() bool { |
| return ctx.mod.InRecovery() |
| } |
| |
| func (c *Module) InstallInProduct() bool { |
| // Additionally check if this module is inProduct() that means it is a "product" variant of a |
| // module. As well as product specific modules, product variants must be installed to /product. |
| return c.InProduct() |
| } |
| |
| func (c *Module) InstallInVendor() bool { |
| // Additionally check if this module is inVendor() that means it is a "vendor" variant of a |
| // module. As well as SoC specific modules, vendor variants must be installed to /vendor |
| // unless they have "odm_available: true". |
| return c.HasVendorVariant() && c.InVendor() && !c.VendorVariantToOdm() |
| } |
| |
| func (c *Module) InstallInOdm() bool { |
| // Some vendor variants want to be installed to /odm by setting "odm_available: true". |
| return c.InVendor() && c.VendorVariantToOdm() |
| } |
| |
| // Returns true when this module is configured to have core and vendor variants. |
| func (c *Module) HasVendorVariant() bool { |
| return Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Odm_available) |
| } |
| |
| // Returns true when this module creates a vendor variant and wants to install the vendor variant |
| // to the odm partition. |
| func (c *Module) VendorVariantToOdm() bool { |
| return Bool(c.VendorProperties.Odm_available) |
| } |
| |
| // Returns true when this module is configured to have core and product variants. |
| func (c *Module) HasProductVariant() bool { |
| return Bool(c.VendorProperties.Product_available) |
| } |
| |
| // Returns true when this module is configured to have core and either product or vendor variants. |
| func (c *Module) HasNonSystemVariants() bool { |
| return c.HasVendorVariant() || c.HasProductVariant() |
| } |
| |
| // Returns true if the module is "product" variant. Usually these modules are installed in /product |
| func (c *Module) InProduct() bool { |
| return c.Properties.ImageVariation == ProductVariation |
| } |
| |
| // Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor |
| func (c *Module) InVendor() bool { |
| return c.Properties.ImageVariation == VendorVariation |
| } |
| |
| // Returns true if the module is "vendor" or "product" variant. This replaces previous UseVndk usages |
| // which were misused to check if the module variant is vendor or product. |
| func (c *Module) InVendorOrProduct() bool { |
| return c.InVendor() || c.InProduct() |
| } |
| |
| func (c *Module) InRamdisk() bool { |
| return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk() |
| } |
| |
| func (c *Module) InVendorRamdisk() bool { |
| return c.ModuleBase.InVendorRamdisk() || c.ModuleBase.InstallInVendorRamdisk() |
| } |
| |
| func (c *Module) InRecovery() bool { |
| return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery() |
| } |
| |
| func (c *Module) OnlyInRamdisk() bool { |
| return c.ModuleBase.InstallInRamdisk() |
| } |
| |
| func (c *Module) OnlyInVendorRamdisk() bool { |
| return c.ModuleBase.InstallInVendorRamdisk() |
| } |
| |
| func (c *Module) OnlyInRecovery() bool { |
| return c.ModuleBase.InstallInRecovery() |
| } |
| |
| // ImageMutatableModule provides a common image mutation interface for LinkableInterface modules. |
| type ImageMutatableModule interface { |
| android.Module |
| LinkableInterface |
| |
| // AndroidModuleBase returns the android.ModuleBase for this module |
| AndroidModuleBase() *android.ModuleBase |
| |
| // VendorAvailable returns true if this module is available on the vendor image. |
| VendorAvailable() bool |
| |
| // OdmAvailable returns true if this module is available on the odm image. |
| OdmAvailable() bool |
| |
| // ProductAvailable returns true if this module is available on the product image. |
| ProductAvailable() bool |
| |
| // RamdiskAvailable returns true if this module is available on the ramdisk image. |
| RamdiskAvailable() bool |
| |
| // RecoveryAvailable returns true if this module is available on the recovery image. |
| RecoveryAvailable() bool |
| |
| // VendorRamdiskAvailable returns true if this module is available on the vendor ramdisk image. |
| VendorRamdiskAvailable() bool |
| |
| // IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt. |
| IsSnapshotPrebuilt() bool |
| |
| // SnapshotVersion returns the snapshot version for this module. |
| SnapshotVersion(mctx android.BaseModuleContext) string |
| |
| // SdkVersion returns the SDK version for this module. |
| SdkVersion() string |
| |
| // ExtraVariants returns the list of extra variants this module requires. |
| ExtraVariants() []string |
| |
| // AppendExtraVariant returns an extra variant to the list of extra variants this module requires. |
| AppendExtraVariant(extraVariant string) |
| |
| // SetRamdiskVariantNeeded sets whether the Ramdisk Variant is needed. |
| SetRamdiskVariantNeeded(b bool) |
| |
| // SetVendorRamdiskVariantNeeded sets whether the Vendor Ramdisk Variant is needed. |
| SetVendorRamdiskVariantNeeded(b bool) |
| |
| // SetRecoveryVariantNeeded sets whether the Recovery Variant is needed. |
| SetRecoveryVariantNeeded(b bool) |
| |
| // SetCoreVariantNeeded sets whether the Core Variant is needed. |
| SetCoreVariantNeeded(b bool) |
| } |
| |
| var _ ImageMutatableModule = (*Module)(nil) |
| |
| func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { |
| MutateImage(mctx, m) |
| } |
| |
| func (m *Module) VendorAvailable() bool { |
| return Bool(m.VendorProperties.Vendor_available) |
| } |
| |
| func (m *Module) OdmAvailable() bool { |
| return Bool(m.VendorProperties.Odm_available) |
| } |
| |
| func (m *Module) ProductAvailable() bool { |
| return Bool(m.VendorProperties.Product_available) |
| } |
| |
| func (m *Module) RamdiskAvailable() bool { |
| return Bool(m.Properties.Ramdisk_available) |
| } |
| |
| func (m *Module) VendorRamdiskAvailable() bool { |
| return Bool(m.Properties.Vendor_ramdisk_available) |
| } |
| |
| func (m *Module) AndroidModuleBase() *android.ModuleBase { |
| return &m.ModuleBase |
| } |
| |
| func (m *Module) RecoveryAvailable() bool { |
| return Bool(m.Properties.Recovery_available) |
| } |
| |
| func (m *Module) ExtraVariants() []string { |
| return m.Properties.ExtraVersionedImageVariations |
| } |
| |
| func (m *Module) AppendExtraVariant(extraVariant string) { |
| m.Properties.ExtraVersionedImageVariations = append(m.Properties.ExtraVersionedImageVariations, extraVariant) |
| } |
| |
| func (m *Module) SetRamdiskVariantNeeded(b bool) { |
| m.Properties.RamdiskVariantNeeded = b |
| } |
| |
| func (m *Module) SetVendorRamdiskVariantNeeded(b bool) { |
| m.Properties.VendorRamdiskVariantNeeded = b |
| } |
| |
| func (m *Module) SetRecoveryVariantNeeded(b bool) { |
| m.Properties.RecoveryVariantNeeded = b |
| } |
| |
| func (m *Module) SetCoreVariantNeeded(b bool) { |
| m.Properties.CoreVariantNeeded = b |
| } |
| |
| func (m *Module) SnapshotVersion(mctx android.BaseModuleContext) string { |
| if snapshot, ok := m.linker.(SnapshotInterface); ok { |
| return snapshot.Version() |
| } else { |
| mctx.ModuleErrorf("version is unknown for snapshot prebuilt") |
| // Should we be panicking here instead? |
| return "" |
| } |
| } |
| |
| func (m *Module) KernelHeadersDecorator() bool { |
| if _, ok := m.linker.(*kernelHeadersDecorator); ok { |
| return true |
| } |
| return false |
| } |
| |
| // MutateImage handles common image mutations for ImageMutatableModule interfaces. |
| func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) { |
| // Validation check |
| vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() |
| productSpecific := mctx.ProductSpecific() |
| |
| if m.VendorAvailable() { |
| if vendorSpecific { |
| mctx.PropertyErrorf("vendor_available", |
| "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`") |
| } |
| if m.OdmAvailable() { |
| mctx.PropertyErrorf("vendor_available", |
| "doesn't make sense at the same time as `odm_available: true`") |
| } |
| } |
| |
| if m.OdmAvailable() { |
| if vendorSpecific { |
| mctx.PropertyErrorf("odm_available", |
| "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`") |
| } |
| } |
| |
| if m.ProductAvailable() { |
| if productSpecific { |
| mctx.PropertyErrorf("product_available", |
| "doesn't make sense at the same time as `product_specific: true`") |
| } |
| if vendorSpecific { |
| mctx.PropertyErrorf("product_available", |
| "cannot provide product variant from a vendor module. Please use `product_specific: true` with `vendor_available: true`") |
| } |
| } |
| |
| var coreVariantNeeded bool = false |
| var ramdiskVariantNeeded bool = false |
| var vendorRamdiskVariantNeeded bool = false |
| var recoveryVariantNeeded bool = false |
| |
| var vendorVariants []string |
| var productVariants []string |
| |
| needVndkVersionVendorVariantForLlndk := false |
| |
| if m.NeedsLlndkVariants() { |
| // This is an LLNDK library. The implementation of the library will be on /system, |
| // and vendor and product variants will be created with LLNDK stubs. |
| // The LLNDK libraries need vendor variants even if there is no VNDK. |
| coreVariantNeeded = true |
| vendorVariants = append(vendorVariants, "") |
| productVariants = append(productVariants, "") |
| // Generate vendor variants for boardVndkVersion only if the VNDK snapshot does not |
| // provide the LLNDK stub libraries. |
| if needVndkVersionVendorVariantForLlndk { |
| vendorVariants = append(vendorVariants, "") |
| } |
| } else if m.NeedsVendorPublicLibraryVariants() { |
| // A vendor public library has the implementation on /vendor, with stub variants |
| // for system and product. |
| coreVariantNeeded = true |
| vendorVariants = append(vendorVariants, "") |
| productVariants = append(productVariants, "") |
| } else if m.IsSnapshotPrebuilt() { |
| // Make vendor variants only for the versions in BOARD_VNDK_VERSION and |
| // PRODUCT_EXTRA_VNDK_VERSIONS. |
| if m.InstallInRecovery() { |
| recoveryVariantNeeded = true |
| } else { |
| vendorVariants = append(vendorVariants, m.SnapshotVersion(mctx)) |
| } |
| } else if m.HasNonSystemVariants() { |
| // This will be available to /system unless it is product_specific |
| // which will be handled later. |
| coreVariantNeeded = true |
| |
| // We assume that modules under proprietary paths are compatible for |
| // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or |
| // PLATFORM_VNDK_VERSION. |
| if m.HasVendorVariant() { |
| vendorVariants = append(vendorVariants, "") |
| } |
| |
| // product_available modules are available to /product. |
| if m.HasProductVariant() { |
| productVariants = append(productVariants, "") |
| } |
| } else if vendorSpecific && m.SdkVersion() == "" { |
| // This will be available in /vendor (or /odm) only |
| vendorVariants = append(vendorVariants, "") |
| } else { |
| // This is either in /system (or similar: /data), or is a |
| // module built with the NDK. Modules built with the NDK |
| // will be restricted using the existing link type checks. |
| coreVariantNeeded = true |
| } |
| |
| if coreVariantNeeded && productSpecific && m.SdkVersion() == "" { |
| // The module has "product_specific: true" that does not create core variant. |
| coreVariantNeeded = false |
| productVariants = append(productVariants, "") |
| } |
| |
| if m.RamdiskAvailable() { |
| ramdiskVariantNeeded = true |
| } |
| |
| if m.AndroidModuleBase().InstallInRamdisk() { |
| ramdiskVariantNeeded = true |
| coreVariantNeeded = false |
| } |
| |
| if m.VendorRamdiskAvailable() { |
| vendorRamdiskVariantNeeded = true |
| } |
| |
| if m.AndroidModuleBase().InstallInVendorRamdisk() { |
| vendorRamdiskVariantNeeded = true |
| coreVariantNeeded = false |
| } |
| |
| if m.RecoveryAvailable() { |
| recoveryVariantNeeded = true |
| } |
| |
| if m.AndroidModuleBase().InstallInRecovery() { |
| recoveryVariantNeeded = true |
| coreVariantNeeded = false |
| } |
| |
| for _, variant := range android.FirstUniqueStrings(vendorVariants) { |
| if variant == "" { |
| m.AppendExtraVariant(VendorVariation) |
| } else { |
| m.AppendExtraVariant(VendorVariationPrefix + variant) |
| } |
| } |
| |
| for _, variant := range android.FirstUniqueStrings(productVariants) { |
| if variant == "" { |
| m.AppendExtraVariant(ProductVariation) |
| } else { |
| m.AppendExtraVariant(ProductVariationPrefix + variant) |
| } |
| } |
| |
| m.SetRamdiskVariantNeeded(ramdiskVariantNeeded) |
| m.SetVendorRamdiskVariantNeeded(vendorRamdiskVariantNeeded) |
| m.SetRecoveryVariantNeeded(recoveryVariantNeeded) |
| m.SetCoreVariantNeeded(coreVariantNeeded) |
| |
| // Disable the module if no variants are needed. |
| if !ramdiskVariantNeeded && |
| !recoveryVariantNeeded && |
| !coreVariantNeeded && |
| len(m.ExtraVariants()) == 0 { |
| m.Disable() |
| } |
| } |
| |
| func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool { |
| return c.Properties.CoreVariantNeeded |
| } |
| |
| func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { |
| return c.Properties.RamdiskVariantNeeded |
| } |
| |
| func (c *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { |
| return c.Properties.VendorRamdiskVariantNeeded |
| } |
| |
| func (c *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { |
| return false |
| } |
| |
| func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { |
| return c.Properties.RecoveryVariantNeeded |
| } |
| |
| func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string { |
| return c.Properties.ExtraVersionedImageVariations |
| } |
| |
| func squashVendorSrcs(m *Module) { |
| if lib, ok := m.compiler.(*libraryDecorator); ok { |
| lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, |
| lib.baseCompiler.Properties.Target.Vendor.Srcs...) |
| |
| lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, |
| lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...) |
| |
| lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources, |
| lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...) |
| |
| if lib.Properties.Target.Vendor.No_stubs { |
| proptools.Clear(&lib.Properties.Stubs) |
| } |
| } |
| } |
| |
| func squashProductSrcs(m *Module) { |
| if lib, ok := m.compiler.(*libraryDecorator); ok { |
| lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, |
| lib.baseCompiler.Properties.Target.Product.Srcs...) |
| |
| lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, |
| lib.baseCompiler.Properties.Target.Product.Exclude_srcs...) |
| |
| lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources, |
| lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...) |
| |
| if lib.Properties.Target.Product.No_stubs { |
| proptools.Clear(&lib.Properties.Stubs) |
| } |
| } |
| } |
| |
| func squashRecoverySrcs(m *Module) { |
| if lib, ok := m.compiler.(*libraryDecorator); ok { |
| lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, |
| lib.baseCompiler.Properties.Target.Recovery.Srcs...) |
| |
| lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, |
| lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...) |
| |
| lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources, |
| lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...) |
| } |
| } |
| |
| func squashVendorRamdiskSrcs(m *Module) { |
| if lib, ok := m.compiler.(*libraryDecorator); ok { |
| lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs...) |
| } |
| } |
| |
| func squashRamdiskSrcs(m *Module) { |
| if lib, ok := m.compiler.(*libraryDecorator); ok { |
| lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Ramdisk.Exclude_srcs...) |
| } |
| } |
| |
| func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string) { |
| if variant == android.RamdiskVariation { |
| c.MakeAsPlatform() |
| squashRamdiskSrcs(c) |
| } else if variant == android.VendorRamdiskVariation { |
| c.MakeAsPlatform() |
| squashVendorRamdiskSrcs(c) |
| } else if variant == android.RecoveryVariation { |
| c.MakeAsPlatform() |
| squashRecoverySrcs(c) |
| } else if strings.HasPrefix(variant, VendorVariation) { |
| c.Properties.ImageVariation = VendorVariation |
| |
| if strings.HasPrefix(variant, VendorVariationPrefix) { |
| c.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix) |
| } |
| squashVendorSrcs(c) |
| } else if strings.HasPrefix(variant, ProductVariation) { |
| c.Properties.ImageVariation = ProductVariation |
| if strings.HasPrefix(variant, ProductVariationPrefix) { |
| c.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix) |
| } |
| squashProductSrcs(c) |
| } |
| |
| if c.NeedsVendorPublicLibraryVariants() && |
| (variant == android.CoreVariation || strings.HasPrefix(variant, ProductVariationPrefix)) { |
| c.VendorProperties.IsVendorPublicLibrary = true |
| } |
| } |