From 3a7d000d129b9e14cd471f157bf2fcc23621b7ec Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Tue, 30 Mar 2021 12:19:36 -0400 Subject: [PATCH] cc: Create a common image mutator interface As part of adding Vendor support to Rust, refactor the image mutator in CC to a new common image mutator interface so this logic can be reused across both CC and Rust. Bug: 184042776 Test: m nothing Change-Id: Ia55d5ad840db7cf1a64d6c65ed86487230cb8742 --- cc/cc.go | 23 +++- cc/image.go | 255 +++++++++++++++++++++++++++++++----------- cc/linkable.go | 22 +++- cc/sabi.go | 2 +- cc/vendor_snapshot.go | 2 +- cc/vndk.go | 4 +- rust/rust.go | 16 +++ 7 files changed, 252 insertions(+), 72 deletions(-) diff --git a/cc/cc.go b/cc/cc.go index 9176bc3ed..4413df051 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -1113,16 +1113,33 @@ func (c *Module) IsNdk(config android.Config) bool { return inList(c.BaseModuleName(), *getNDKKnownLibs(config)) } -// isLLndk returns true for both LLNDK (public) and LLNDK-private libs. func (c *Module) IsLlndk() bool { return c.VendorProperties.IsLLNDK } -// IsLlndkPublic returns true only for LLNDK (public) libs. func (c *Module) IsLlndkPublic() bool { return c.VendorProperties.IsLLNDK && !c.VendorProperties.IsVNDKPrivate } +func (c *Module) IsLlndkHeaders() bool { + if _, ok := c.linker.(*llndkHeadersDecorator); ok { + return true + } + return false +} + +func (c *Module) IsLlndkLibrary() bool { + if _, ok := c.linker.(*llndkStubDecorator); ok { + return true + } + return false +} + +func (m *Module) HasLlndkStubs() bool { + lib := moduleLibraryInterface(m) + return lib != nil && lib.hasLLNDKStubs() +} + // isImplementationForLLNDKPublic returns true for any variant of a cc_library that has LLNDK stubs // and does not set llndk.vendor_available: false. func (c *Module) isImplementationForLLNDKPublic() bool { @@ -1246,7 +1263,7 @@ func (c *Module) nativeCoverage() bool { return c.linker != nil && c.linker.nativeCoverage() } -func (c *Module) isSnapshotPrebuilt() bool { +func (c *Module) IsSnapshotPrebuilt() bool { if p, ok := c.linker.(snapshotInterface); ok { return p.isSnapshotPrebuilt() } diff --git a/cc/image.go b/cc/image.go index afe6a0e0c..cb8589db5 100644 --- a/cc/image.go +++ b/cc/image.go @@ -187,40 +187,73 @@ func (c *Module) compareVendorAndProductProps() bool { return true } +// 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) { - // Validation check + m.CheckVndkProperties(mctx) + MutateImage(mctx, m) +} + +// CheckVndkProperties checks whether the VNDK-related properties are set correctly. +// If properties are not set correctly, results in a module context property error. +func (m *Module) CheckVndkProperties(mctx android.BaseModuleContext) { vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() productSpecific := mctx.ProductSpecific() - if Bool(m.VendorProperties.Vendor_available) { - if vendorSpecific { - mctx.PropertyErrorf("vendor_available", - "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`") - } - if Bool(m.VendorProperties.Odm_available) { - mctx.PropertyErrorf("vendor_available", - "doesn't make sense at the same time as `odm_available: true`") - } - } - - if Bool(m.VendorProperties.Odm_available) { - if vendorSpecific { - mctx.PropertyErrorf("odm_available", - "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`") - } - } - - if Bool(m.VendorProperties.Product_available) { - 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`") - } - } - if vndkdep := m.vndkdep; vndkdep != nil { if vndkdep.isVndk() { if vendorSpecific || productSpecific { @@ -265,6 +298,111 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { } } } +} + +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.ExtraVariants +} + +func (m *Module) AppendExtraVariant(extraVariant string) { + m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, 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 @@ -287,18 +425,13 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { productVndkVersion = platformVndkVersion } - _, isLLNDKLibrary := m.linker.(*llndkStubDecorator) - _, isLLNDKHeaders := m.linker.(*llndkHeadersDecorator) - lib := moduleLibraryInterface(m) - hasLLNDKStubs := lib != nil && lib.hasLLNDKStubs() - - if isLLNDKLibrary || isLLNDKHeaders || hasLLNDKStubs { + if m.IsLlndkLibrary() || m.IsLlndkHeaders() || m.HasLlndkStubs() { // 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. // The obsolete llndk_library and llndk_headers modules also need the vendor variants // so the cc_library LLNDK stubs can depend on them. - if hasLLNDKStubs { + if m.HasLlndkStubs() { coreVariantNeeded = true } if platformVndkVersion != "" { @@ -315,17 +448,13 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { // If the device isn't compiling against the VNDK, we always // use the core mode. coreVariantNeeded = true - } else if m.isSnapshotPrebuilt() { + } else if m.IsSnapshotPrebuilt() { // Make vendor variants only for the versions in BOARD_VNDK_VERSION and // PRODUCT_EXTRA_VNDK_VERSIONS. - if snapshot, ok := m.linker.(snapshotInterface); ok { - if m.InstallInRecovery() { - recoveryVariantNeeded = true - } else { - vendorVariants = append(vendorVariants, snapshot.version()) - } + if m.InstallInRecovery() { + recoveryVariantNeeded = true } else { - mctx.ModuleErrorf("version is unknown for snapshot prebuilt") + vendorVariants = append(vendorVariants, m.SnapshotVersion(mctx)) } } else if m.HasNonSystemVariants() && !m.IsVndkExt() { // This will be available to /system unless it is product_specific @@ -351,7 +480,7 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { productVariants = append(productVariants, productVndkVersion) } } - } else if vendorSpecific && String(m.Properties.Sdk_version) == "" { + } else if vendorSpecific && m.SdkVersion() == "" { // This will be available in /vendor (or /odm) only // kernel_headers is a special module type whose exported headers @@ -360,7 +489,7 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { // For other modules, we assume that modules under proprietary // paths are compatible for BOARD_VNDK_VERSION. The other modules // are regarded as AOSP, which is PLATFORM_VNDK_VERSION. - if _, ok := m.linker.(*kernelHeadersDecorator); ok { + if m.KernelHeadersDecorator() { vendorVariants = append(vendorVariants, platformVndkVersion, boardVndkVersion, @@ -378,7 +507,7 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { } if boardVndkVersion != "" && productVndkVersion != "" { - if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" { + if coreVariantNeeded && productSpecific && m.SdkVersion() == "" { // The module has "product_specific: true" that does not create core variant. coreVariantNeeded = false productVariants = append(productVariants, productVndkVersion) @@ -390,60 +519,60 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { productVariants = []string{} } - if Bool(m.Properties.Ramdisk_available) { + if m.RamdiskAvailable() { ramdiskVariantNeeded = true } - if m.ModuleBase.InstallInRamdisk() { + if m.AndroidModuleBase().InstallInRamdisk() { ramdiskVariantNeeded = true coreVariantNeeded = false } - if Bool(m.Properties.Vendor_ramdisk_available) { + if m.VendorRamdiskAvailable() { vendorRamdiskVariantNeeded = true } - if m.ModuleBase.InstallInVendorRamdisk() { + if m.AndroidModuleBase().InstallInVendorRamdisk() { vendorRamdiskVariantNeeded = true coreVariantNeeded = false } - if Bool(m.Properties.Recovery_available) { + if m.RecoveryAvailable() { recoveryVariantNeeded = true } - if m.ModuleBase.InstallInRecovery() { + if m.AndroidModuleBase().InstallInRecovery() { recoveryVariantNeeded = true coreVariantNeeded = false } // If using a snapshot, the recovery variant under AOSP directories is not needed, // except for kernel headers, which needs all variants. - if _, ok := m.linker.(*kernelHeadersDecorator); !ok && - !m.isSnapshotPrebuilt() && + if m.KernelHeadersDecorator() && + !m.IsSnapshotPrebuilt() && usingRecoverySnapshot && !isRecoveryProprietaryModule(mctx) { recoveryVariantNeeded = false } for _, variant := range android.FirstUniqueStrings(vendorVariants) { - m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant) + m.AppendExtraVariant(VendorVariationPrefix + variant) } for _, variant := range android.FirstUniqueStrings(productVariants) { - m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant) + m.AppendExtraVariant(ProductVariationPrefix + variant) } - m.Properties.RamdiskVariantNeeded = ramdiskVariantNeeded - m.Properties.VendorRamdiskVariantNeeded = vendorRamdiskVariantNeeded - m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded - m.Properties.CoreVariantNeeded = coreVariantNeeded + 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.Properties.ExtraVariants) == 0 { + len(m.ExtraVariants()) == 0 { m.Disable() } } diff --git a/cc/linkable.go b/cc/linkable.go index 6aa238b24..17bafcc41 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -98,10 +98,24 @@ type LinkableInterface interface { InVendor() bool UseSdk() bool + + // IsLlndk returns true for both LLNDK (public) and LLNDK-private libs. + IsLlndk() bool + + // IsLlndkPublic returns true only for LLNDK (public) libs. + IsLlndkPublic() bool + + // IsLlndkHeaders returns true if this module is an LLNDK headers module. + IsLlndkHeaders() bool + + // IsLlndkLibrary returns true if this module is an LLNDK library module. + IsLlndkLibrary() bool + + // HasLlndkStubs returns true if this module has LLNDK stubs. + HasLlndkStubs() bool + UseVndk() bool MustUseVendorVariant() bool - IsLlndk() bool - IsLlndkPublic() bool IsVndk() bool IsVndkExt() bool IsVndkPrivate() bool @@ -121,6 +135,10 @@ type LinkableInterface interface { SetPreventInstall() // SetHideFromMake sets the HideFromMake property to 'true' for this module. SetHideFromMake() + + // KernelHeadersDecorator returns true if this is a kernel headers decorator module. + // This is specific to cc and should always return false for all other packages. + KernelHeadersDecorator() bool } var ( diff --git a/cc/sabi.go b/cc/sabi.go index 4a1ba3cda..c0eb57cc3 100644 --- a/cc/sabi.go +++ b/cc/sabi.go @@ -141,7 +141,7 @@ func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool { } // Don't create ABI dump for prebuilts. - if m.Prebuilt() != nil || m.isSnapshotPrebuilt() { + if m.Prebuilt() != nil || m.IsSnapshotPrebuilt() { return false } diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 3437d77a4..2f68ccad1 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -173,7 +173,7 @@ func isSnapshotAware(cfg android.DeviceConfig, m *Module, inProprietaryPath bool return false } // the module must be installed in target image - if !apexInfo.IsForPlatform() || m.isSnapshotPrebuilt() || !image.inImage(m)() { + if !apexInfo.IsForPlatform() || m.IsSnapshotPrebuilt() || !image.inImage(m)() { return false } // skip kernel_headers which always depend on vendor diff --git a/cc/vndk.go b/cc/vndk.go index b7047e92e..1a8a45439 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -609,8 +609,8 @@ func isVndkSnapshotAware(config android.DeviceConfig, m *Module, } // !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants. // !installable: Snapshot only cares about "installable" modules. - // isSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense. - if !m.InVendor() || !m.installable(apexInfo) || m.isSnapshotPrebuilt() { + // IsSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense. + if !m.InVendor() || !m.installable(apexInfo) || m.IsSnapshotPrebuilt() { return nil, "", false } l, ok := m.linker.(snapshotLibraryInterface) diff --git a/rust/rust.go b/rust/rust.go index 34e197a07..f0da2ced0 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -255,6 +255,22 @@ func (c *Module) IsLlndkPublic() bool { return false } +func (m *Module) IsLlndkHeaders() bool { + return false +} + +func (m *Module) IsLlndkLibrary() bool { + return false +} + +func (mod *Module) KernelHeadersDecorator() bool { + return false +} + +func (m *Module) HasLlndkStubs() bool { + return false +} + func (mod *Module) SdkVersion() string { return "" }