From d7586b6526f6db839d368587fb58574db9b7042a Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Thu, 1 Apr 2021 09:49:36 -0400 Subject: [PATCH] Refactor vendor snapshot to use LinkableInterface. Refactors the vendor snapshot support to use the LinkableInterface so that support can be extended to Rust. This CL does not add vendor snapshot support for Rust; that is left for a follow-on CL. Bug: 184042776 Test: m nothing Change-Id: Id0c4970ca00053484a52677d182153cbc454c301 --- apex/apex.go | 2 +- cc/cc.go | 57 +++++++++++++-------- cc/cc_test.go | 4 +- cc/coverage.go | 4 +- cc/linkable.go | 106 ++++++++++++++++++++++++++++++++++++++-- cc/sabi.go | 2 +- cc/sanitize.go | 18 ++++++- cc/snapshot_prebuilt.go | 18 +++---- cc/snapshot_utils.go | 36 ++++++++++++-- cc/vendor_snapshot.go | 99 +++++++++++++++++++------------------ cc/vndk.go | 33 ++++++------- java/app.go | 2 +- rust/Android.bp | 3 +- rust/compiler.go | 5 ++ rust/proc_macro.go | 5 ++ rust/rust.go | 81 +++++++++++++++++++++++++++--- rust/sanitize.go | 16 ++++++ rust/snapshot_utils.go | 54 ++++++++++++++++++++ 18 files changed, 429 insertions(+), 116 deletions(-) create mode 100644 rust/snapshot_utils.go diff --git a/apex/apex.go b/apex/apex.go index 2c0df2785..24af85df0 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1256,7 +1256,7 @@ func (a *apexBundle) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool } // Implements cc.Coverage -func (a *apexBundle) PreventInstall() { +func (a *apexBundle) SetPreventInstall() { a.properties.PreventInstall = true } diff --git a/cc/cc.go b/cc/cc.go index 16a49d343..2520705fd 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -841,6 +841,10 @@ func (c *Module) SetHideFromMake() { c.Properties.HideFromMake = true } +func (c *Module) HiddenFromMake() bool { + return c.Properties.HideFromMake +} + func (c *Module) Toc() android.OptionalPath { if c.linker != nil { if library, ok := c.linker.(libraryInterface); ok { @@ -1088,12 +1092,6 @@ func (c *Module) IsDependencyRoot() bool { return false } -// Returns true if the module is using VNDK libraries instead of the libraries in /system/lib or /system/lib64. -// "product" and "vendor" variant modules return true for this function. -// When BOARD_VNDK_VERSION is set, vendor variants of "vendor_available: true", "vendor: true", -// "soc_specific: true" and more vendor installed modules are included here. -// When PRODUCT_PRODUCT_VNDK_VERSION is set, product variants of "product_available: true" or -// "product_specific: true" modules are included here. func (c *Module) UseVndk() bool { return c.Properties.VndkVersion != "" } @@ -1141,6 +1139,18 @@ func (c *Module) IsVendorPublicLibrary() bool { return c.VendorProperties.IsVendorPublicLibrary } +func (c *Module) HasLlndkStubs() bool { + lib := moduleLibraryInterface(c) + return lib != nil && lib.hasLLNDKStubs() +} + +func (c *Module) StubsVersion() string { + if lib, ok := c.linker.(versionedInterface); ok { + return lib.stubsVersion() + } + panic(fmt.Errorf("StubsVersion called on non-versioned module: %q", c.BaseModuleName())) +} + // 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 { @@ -1185,7 +1195,7 @@ func (c *Module) isNDKStubLibrary() bool { return false } -func (c *Module) isVndkSp() bool { +func (c *Module) IsVndkSp() bool { if vndkdep := c.vndkdep; vndkdep != nil { return vndkdep.isVndkSp() } @@ -1204,7 +1214,7 @@ func (c *Module) SubName() string { } func (c *Module) MustUseVendorVariant() bool { - return c.isVndkSp() || c.Properties.MustUseVendorVariant + return c.IsVndkSp() || c.Properties.MustUseVendorVariant } func (c *Module) getVndkExtendsModuleName() string { @@ -1343,11 +1353,11 @@ func (ctx *moduleContextImpl) header() bool { } func (ctx *moduleContextImpl) binary() bool { - return ctx.mod.binary() + return ctx.mod.Binary() } func (ctx *moduleContextImpl) object() bool { - return ctx.mod.object() + return ctx.mod.Object() } func (ctx *moduleContextImpl) canUseSdk() bool { @@ -1445,7 +1455,7 @@ func (ctx *moduleContextImpl) isNDKStubLibrary() bool { } func (ctx *moduleContextImpl) isVndkSp() bool { - return ctx.mod.isVndkSp() + return ctx.mod.IsVndkSp() } func (ctx *moduleContextImpl) IsVndkExt() bool { @@ -1786,7 +1796,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { // glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or // RECOVERY_SNAPSHOT_VERSION is current. if i, ok := c.linker.(snapshotLibraryInterface); ok { - if shouldCollectHeadersForSnapshot(ctx, c, apexInfo) { + if ShouldCollectHeadersForSnapshot(ctx, c, apexInfo) { i.collectHeadersForSnapshot(ctx) } } @@ -1799,7 +1809,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { // modules can be hidden from make as some are needed for resolving make side // dependencies. c.HideFromMake() - } else if !c.installable(apexInfo) { + } else if !installable(c, apexInfo) { c.SkipInstall() } @@ -2451,7 +2461,7 @@ func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) { return true } - if to.isVndkSp() || to.IsLlndk() { + if to.IsVndkSp() || to.IsLlndk() { return false } @@ -3064,7 +3074,7 @@ func (c *Module) Header() bool { return false } -func (c *Module) binary() bool { +func (c *Module) Binary() bool { if b, ok := c.linker.(interface { binary() bool }); ok { @@ -3073,7 +3083,7 @@ func (c *Module) binary() bool { return false } -func (c *Module) object() bool { +func (c *Module) Object() bool { if o, ok := c.linker.(interface { object() bool }); ok { @@ -3155,18 +3165,25 @@ func (c *Module) UniqueApexVariations() bool { } } -// Return true if the module is ever installable. func (c *Module) EverInstallable() bool { return c.installer != nil && // Check to see whether the module is actually ever installable. c.installer.everInstallable() } -func (c *Module) installable(apexInfo android.ApexInfo) bool { +func (c *Module) PreventInstall() bool { + return c.Properties.PreventInstall +} + +func (c *Module) Installable() *bool { + return c.Properties.Installable +} + +func installable(c LinkableInterface, apexInfo android.ApexInfo) bool { ret := c.EverInstallable() && // Check to see whether the module has been configured to not be installed. - proptools.BoolDefault(c.Properties.Installable, true) && - !c.Properties.PreventInstall && c.outputFile.Valid() + proptools.BoolDefault(c.Installable(), true) && + !c.PreventInstall() && c.OutputFile().Valid() // The platform variant doesn't need further condition. Apex variants however might not // be installable because it will likely to be included in the APEX and won't appear diff --git a/cc/cc_test.go b/cc/cc_test.go index e9daf33fc..d82619a04 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -381,8 +381,8 @@ func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string if !mod.IsVndk() { t.Errorf("%q IsVndk() must equal to true", name) } - if mod.isVndkSp() != isVndkSp { - t.Errorf("%q isVndkSp() must equal to %t", name, isVndkSp) + if mod.IsVndkSp() != isVndkSp { + t.Errorf("%q IsVndkSp() must equal to %t", name, isVndkSp) } // Check VNDK extension properties. diff --git a/cc/coverage.go b/cc/coverage.go index 5b5ccf2f0..b2788ecc6 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -203,7 +203,7 @@ func SetCoverageProperties(ctx android.BaseModuleContext, properties CoveragePro type Coverage interface { android.Module IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool - PreventInstall() + SetPreventInstall() HideFromMake() MarkAsCoverageVariant(bool) EnableCoverageIfNeeded() @@ -236,7 +236,7 @@ func coverageMutator(mctx android.BottomUpMutatorContext) { // to an APEX via 'data' property. m := mctx.CreateVariations("", "cov") m[0].(Coverage).MarkAsCoverageVariant(false) - m[0].(Coverage).PreventInstall() + m[0].(Coverage).SetPreventInstall() m[0].(Coverage).HideFromMake() m[1].(Coverage).MarkAsCoverageVariant(true) diff --git a/cc/linkable.go b/cc/linkable.go index 40a9d8b04..b583b69e7 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -48,6 +48,20 @@ type PlatformSanitizeable interface { // SanitizerSupported returns true if a sanitizer type is supported by this modules compiler. SanitizerSupported(t SanitizerType) bool + // MinimalRuntimeDep returns true if this module needs to link the minimal UBSan runtime, + // either because it requires it or because a dependent module which requires it to be linked in this module. + MinimalRuntimeDep() bool + + // UbsanRuntimeDep returns true if this module needs to link the full UBSan runtime, + // either because it requires it or because a dependent module which requires it to be linked in this module. + UbsanRuntimeDep() bool + + // UbsanRuntimeNeeded returns true if the full UBSan runtime is required by this module. + UbsanRuntimeNeeded() bool + + // MinimalRuntimeNeeded returns true if the minimal UBSan runtime is required by this module + MinimalRuntimeNeeded() bool + // SanitizableDepTagChecker returns a SantizableDependencyTagChecker function type. SanitizableDepTagChecker() SantizableDependencyTagChecker } @@ -60,14 +74,42 @@ type PlatformSanitizeable interface { // implementation should handle tags from both. type SantizableDependencyTagChecker func(tag blueprint.DependencyTag) bool +// Snapshottable defines those functions necessary for handling module snapshots. +type Snapshottable interface { + // SnapshotHeaders returns a list of header paths provided by this module. + SnapshotHeaders() android.Paths + + // ExcludeFromVendorSnapshot returns true if this module should be otherwise excluded from the vendor snapshot. + ExcludeFromVendorSnapshot() bool + + // ExcludeFromRecoverySnapshot returns true if this module should be otherwise excluded from the recovery snapshot. + ExcludeFromRecoverySnapshot() bool + + // SnapshotLibrary returns true if this module is a snapshot library. + IsSnapshotLibrary() bool + + // SnapshotRuntimeLibs returns a list of libraries needed by this module at runtime but which aren't build dependencies. + SnapshotRuntimeLibs() []string + + // SnapshotSharedLibs returns the list of shared library dependencies for this module. + SnapshotSharedLibs() []string + + // IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt. + IsSnapshotPrebuilt() bool +} + // LinkableInterface is an interface for a type of module that is linkable in a C++ library. type LinkableInterface interface { android.Module + Snapshottable Module() android.Module CcLibrary() bool CcLibraryInterface() bool + // BaseModuleName returns the android.ModuleBase.BaseModuleName() value for this module. + BaseModuleName() string + OutputFile() android.OptionalPath CoverageFiles() android.Paths @@ -79,9 +121,6 @@ type LinkableInterface interface { BuildSharedVariant() bool SetStatic() SetShared() - Static() bool - Shared() bool - Header() bool IsPrebuilt() bool Toc() android.OptionalPath @@ -106,13 +145,29 @@ type LinkableInterface interface { // IsLlndkPublic returns true only for LLNDK (public) libs. IsLlndkPublic() bool + // HasLlndkStubs returns true if this library has a variant that will build LLNDK stubs. + HasLlndkStubs() bool + // NeedsLlndkVariants returns true if this module has LLNDK stubs or provides LLNDK headers. NeedsLlndkVariants() bool // NeedsVendorPublicLibraryVariants returns true if this module has vendor public library stubs. NeedsVendorPublicLibraryVariants() bool + //StubsVersion returns the stubs version for this module. + StubsVersion() string + + // UseVndk returns true if the module is using VNDK libraries instead of the libraries in /system/lib or /system/lib64. + // "product" and "vendor" variant modules return true for this function. + // When BOARD_VNDK_VERSION is set, vendor variants of "vendor_available: true", "vendor: true", + // "soc_specific: true" and more vendor installed modules are included here. + // When PRODUCT_PRODUCT_VNDK_VERSION is set, product variants of "vendor_available: true" or + // "product_specific: true" modules are included here. UseVndk() bool + + // IsVndkSp returns true if this is a VNDK-SP module. + IsVndkSp() bool + MustUseVendorVariant() bool IsVndk() bool IsVndkExt() bool @@ -140,6 +195,51 @@ type LinkableInterface interface { // 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 + + // HiddenFromMake returns true if this module is hidden from Make. + HiddenFromMake() bool + + // RelativeInstallPath returns the relative install path for this module. + RelativeInstallPath() string + + // Binary returns true if this is a binary module. + Binary() bool + + // Object returns true if this is an object module. + Object() bool + + // Rlib returns true if this is an rlib module. + Rlib() bool + + // Dylib returns true if this is an dylib module. + Dylib() bool + + // Static returns true if this is a static library module. + Static() bool + + // Shared returns true if this is a shared library module. + Shared() bool + + // Header returns true if this is a library headers module. + Header() bool + + // EverInstallable returns true if the module is ever installable + EverInstallable() bool + + // PreventInstall returns true if this module is prevented from installation. + PreventInstall() bool + + // InstallInData returns true if this module is installed in data. + InstallInData() bool + + // Installable returns a bool pointer to the module installable property. + Installable() *bool + + // Symlinks returns a list of symlinks that should be created for this module. + Symlinks() []string + + // VndkVersion returns the VNDK version string for this module. + VndkVersion() string } var ( diff --git a/cc/sabi.go b/cc/sabi.go index c0eb57cc3..384dcc165 100644 --- a/cc/sabi.go +++ b/cc/sabi.go @@ -84,7 +84,7 @@ func classifySourceAbiDump(ctx android.BaseModuleContext) string { return "LLNDK" } if m.UseVndk() && m.IsVndk() && !m.IsVndkPrivate() { - if m.isVndkSp() { + if m.IsVndkSp() { if m.IsVndkExt() { return "VNDK-SP-ext" } else { diff --git a/cc/sanitize.go b/cc/sanitize.go index 397121ef5..605a8d094 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -1075,7 +1075,7 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { sanitizers = append(sanitizers, "shadow-call-stack") } - if Bool(c.sanitize.Properties.Sanitize.Memtag_heap) && c.binary() { + if Bool(c.sanitize.Properties.Sanitize.Memtag_heap) && c.Binary() { noteDep := "note_memtag_heap_async" if Bool(c.sanitize.Properties.Sanitize.Diag.Memtag_heap) { noteDep = "note_memtag_heap_sync" @@ -1208,6 +1208,14 @@ type Sanitizeable interface { AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string) } +func (c *Module) MinimalRuntimeDep() bool { + return c.sanitize.Properties.MinimalRuntimeDep +} + +func (c *Module) UbsanRuntimeDep() bool { + return c.sanitize.Properties.UbsanRuntimeDep +} + func (c *Module) SanitizePropDefined() bool { return c.sanitize != nil } @@ -1441,6 +1449,14 @@ func enableMinimalRuntime(sanitize *sanitize) bool { return false } +func (m *Module) UbsanRuntimeNeeded() bool { + return enableUbsanRuntime(m.sanitize) +} + +func (m *Module) MinimalRuntimeNeeded() bool { + return enableMinimalRuntime(m.sanitize) +} + func enableUbsanRuntime(sanitize *sanitize) bool { return Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) || Bool(sanitize.Properties.Sanitize.Diag.Undefined) || diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go index 885a0ce6d..0b1147ef2 100644 --- a/cc/snapshot_prebuilt.go +++ b/cc/snapshot_prebuilt.go @@ -35,12 +35,12 @@ type snapshotImage interface { // Function that returns true if the module is included in this image. // Using a function return instead of a value to prevent early // evalution of a function that may be not be defined. - inImage(m *Module) func() bool + inImage(m LinkableInterface) func() bool // Returns true if the module is private and must not be included in the // snapshot. For example VNDK-private modules must return true for the // vendor snapshots. But false for the recovery snapshots. - private(m *Module) bool + private(m LinkableInterface) bool // Returns true if a dir under source tree is an SoC-owned proprietary // directory, such as device/, vendor/, etc. @@ -56,7 +56,7 @@ type snapshotImage interface { // Whether a given module has been explicitly excluded from the // snapshot, e.g., using the exclude_from_vendor_snapshot or // exclude_from_recovery_snapshot properties. - excludeFromSnapshot(m *Module) bool + excludeFromSnapshot(m LinkableInterface) bool // Returns true if the build is using a snapshot for this image. isUsingSnapshot(cfg android.DeviceConfig) bool @@ -125,11 +125,11 @@ func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) return ctx.DeviceConfig().VndkVersion() == "current" } -func (vendorSnapshotImage) inImage(m *Module) func() bool { +func (vendorSnapshotImage) inImage(m LinkableInterface) func() bool { return m.InVendor } -func (vendorSnapshotImage) private(m *Module) bool { +func (vendorSnapshotImage) private(m LinkableInterface) bool { return m.IsVndkPrivate() } @@ -159,7 +159,7 @@ func (vendorSnapshotImage) includeVndk() bool { return true } -func (vendorSnapshotImage) excludeFromSnapshot(m *Module) bool { +func (vendorSnapshotImage) excludeFromSnapshot(m LinkableInterface) bool { return m.ExcludeFromVendorSnapshot() } @@ -206,12 +206,12 @@ func (recoverySnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext return ctx.DeviceConfig().RecoverySnapshotVersion() == "current" } -func (recoverySnapshotImage) inImage(m *Module) func() bool { +func (recoverySnapshotImage) inImage(m LinkableInterface) func() bool { return m.InRecovery } // recovery snapshot does not have private libraries. -func (recoverySnapshotImage) private(m *Module) bool { +func (recoverySnapshotImage) private(m LinkableInterface) bool { return false } @@ -224,7 +224,7 @@ func (recoverySnapshotImage) includeVndk() bool { return false } -func (recoverySnapshotImage) excludeFromSnapshot(m *Module) bool { +func (recoverySnapshotImage) excludeFromSnapshot(m LinkableInterface) bool { return m.ExcludeFromRecoverySnapshot() } diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go index c32fa364f..8eb616448 100644 --- a/cc/snapshot_utils.go +++ b/cc/snapshot_utils.go @@ -23,6 +23,36 @@ var ( headerExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"} ) +func (m *Module) IsSnapshotLibrary() bool { + if _, ok := m.linker.(snapshotLibraryInterface); ok { + return true + } + return false +} + +func (m *Module) SnapshotHeaders() android.Paths { + if m.IsSnapshotLibrary() { + return m.linker.(snapshotLibraryInterface).snapshotHeaders() + } + return android.Paths{} +} + +func (m *Module) Dylib() bool { + return false +} + +func (m *Module) Rlib() bool { + return false +} + +func (m *Module) SnapshotRuntimeLibs() []string { + return m.Properties.SnapshotRuntimeLibs +} + +func (m *Module) SnapshotSharedLibs() []string { + return m.Properties.SnapshotSharedLibs +} + // snapshotLibraryInterface is an interface for libraries captured to VNDK / vendor snapshots. type snapshotLibraryInterface interface { libraryInterface @@ -68,14 +98,14 @@ func (s *snapshotMap) get(name string, arch android.ArchType) (snapshot string, return snapshot, found } -// shouldCollectHeadersForSnapshot determines if the module is a possible candidate for snapshot. +// ShouldCollectHeadersForSnapshot determines if the module is a possible candidate for snapshot. // If it's true, collectHeadersForSnapshot will be called in GenerateAndroidBuildActions. -func shouldCollectHeadersForSnapshot(ctx android.ModuleContext, m *Module, apexInfo android.ApexInfo) bool { +func ShouldCollectHeadersForSnapshot(ctx android.ModuleContext, m LinkableInterface, apexInfo android.ApexInfo) bool { if ctx.DeviceConfig().VndkVersion() != "current" && ctx.DeviceConfig().RecoverySnapshotVersion() != "current" { return false } - if _, _, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo); ok { + if _, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo); ok { return ctx.Config().VndkSnapshotBuildArtifacts() } diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 9ad51ad77..4e59a95f8 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -115,7 +115,7 @@ func isVendorProprietaryModule(ctx android.BaseModuleContext) bool { // still be a vendor proprietary module. This happens for cc modules // that are excluded from the vendor snapshot, and it means that the // vendor has assumed control of the framework-provided module. - if c, ok := ctx.Module().(*Module); ok { + if c, ok := ctx.Module().(LinkableInterface); ok { if c.ExcludeFromVendorSnapshot() { return true } @@ -137,7 +137,7 @@ func isRecoveryProprietaryModule(ctx android.BaseModuleContext) bool { // that are excluded from the recovery snapshot, and it means that the // vendor has assumed control of the framework-provided module. - if c, ok := ctx.Module().(*Module); ok { + if c, ok := ctx.Module().(LinkableInterface); ok { if c.ExcludeFromRecoverySnapshot() { return true } @@ -147,8 +147,8 @@ func isRecoveryProprietaryModule(ctx android.BaseModuleContext) bool { } // Determines if the module is a candidate for snapshot. -func isSnapshotAware(cfg android.DeviceConfig, m *Module, inProprietaryPath bool, apexInfo android.ApexInfo, image snapshotImage) bool { - if !m.Enabled() || m.Properties.HideFromMake { +func isSnapshotAware(cfg android.DeviceConfig, m LinkableInterface, inProprietaryPath bool, apexInfo android.ApexInfo, image snapshotImage) bool { + if !m.Enabled() || m.HiddenFromMake() { return false } // When android/prebuilt.go selects between source and prebuilt, it sets @@ -177,51 +177,51 @@ func isSnapshotAware(cfg android.DeviceConfig, m *Module, inProprietaryPath bool return false } // skip kernel_headers which always depend on vendor - if _, ok := m.linker.(*kernelHeadersDecorator); ok { + if m.KernelHeadersDecorator() { return false } - // skip LLNDK libraries which are backward compatible + if m.IsLlndk() { return false } // Libraries - if l, ok := m.linker.(snapshotLibraryInterface); ok { - if m.sanitize != nil { + if sanitizable, ok := m.(PlatformSanitizeable); ok && sanitizable.IsSnapshotLibrary() { + if sanitizable.SanitizePropDefined() { // scs and hwasan export both sanitized and unsanitized variants for static and header // Always use unsanitized variants of them. for _, t := range []SanitizerType{scs, Hwasan} { - if !l.shared() && m.sanitize.isSanitizerEnabled(t) { + if !sanitizable.Shared() && sanitizable.IsSanitizerEnabled(t) { return false } } // cfi also exports both variants. But for static, we capture both. // This is because cfi static libraries can't be linked from non-cfi modules, // and vice versa. This isn't the case for scs and hwasan sanitizers. - if !l.static() && !l.shared() && m.sanitize.isSanitizerEnabled(cfi) { + if !sanitizable.Static() && !sanitizable.Shared() && sanitizable.IsSanitizerEnabled(cfi) { return false } } - if l.static() { - return m.outputFile.Valid() && !image.private(m) + if sanitizable.Static() { + return sanitizable.OutputFile().Valid() && !image.private(m) } - if l.shared() { - if !m.outputFile.Valid() { + if sanitizable.Shared() { + if !sanitizable.OutputFile().Valid() { return false } if image.includeVndk() { - if !m.IsVndk() { + if !sanitizable.IsVndk() { return true } - return m.IsVndkExt() + return sanitizable.IsVndkExt() } } return true } // Binaries and Objects - if m.binary() || m.object() { - return m.outputFile.Valid() + if m.Binary() || m.Object() { + return m.OutputFile().Valid() } return false @@ -323,7 +323,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // installSnapshot function copies prebuilt file (.so, .a, or executable) and json flag file. // For executables, init_rc and vintf_fragments files are also copied. - installSnapshot := func(m *Module, fake bool) android.Paths { + installSnapshot := func(m LinkableInterface, fake bool) android.Paths { targetArch := "arch-" + m.Target().Arch.ArchType.String() if m.Target().Arch.ArchVariant != "" { targetArch += "-" + m.Target().Arch.ArchVariant @@ -337,7 +337,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { prop.ModuleName = ctx.ModuleName(m) if c.supportsVndkExt && m.IsVndkExt() { // vndk exts are installed to /vendor/lib(64)?/vndk(-sp)? - if m.isVndkSp() { + if m.IsVndkSp() { prop.RelativeInstallPath = "vndk-sp" } else { prop.RelativeInstallPath = "vndk" @@ -345,7 +345,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { } else { prop.RelativeInstallPath = m.RelativeInstallPath() } - prop.RuntimeLibs = m.Properties.SnapshotRuntimeLibs + prop.RuntimeLibs = m.SnapshotRuntimeLibs() prop.Required = m.RequiredModuleNames() for _, path := range m.InitRc() { prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base())) @@ -365,8 +365,8 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { var propOut string - if l, ok := m.linker.(snapshotLibraryInterface); ok { - exporterInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo) + if m.IsSnapshotLibrary() { + exporterInfo := ctx.ModuleProvider(m.Module(), FlagExporterInfoProvider).(FlagExporterInfo) // library flags prop.ExportedFlags = exporterInfo.Flags @@ -376,19 +376,22 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { for _, dir := range exporterInfo.SystemIncludeDirs { prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String())) } + // shared libs dependencies aren't meaningful on static or header libs - if l.shared() { - prop.SharedLibs = m.Properties.SnapshotSharedLibs + if m.Shared() { + prop.SharedLibs = m.SnapshotSharedLibs() } - if l.static() && m.sanitize != nil { - prop.SanitizeMinimalDep = m.sanitize.Properties.MinimalRuntimeDep || enableMinimalRuntime(m.sanitize) - prop.SanitizeUbsanDep = m.sanitize.Properties.UbsanRuntimeDep || enableUbsanRuntime(m.sanitize) + if sanitizable, ok := m.(PlatformSanitizeable); ok { + if sanitizable.Static() && sanitizable.SanitizePropDefined() { + prop.SanitizeMinimalDep = sanitizable.MinimalRuntimeDep() || sanitizable.MinimalRuntimeNeeded() + prop.SanitizeUbsanDep = sanitizable.UbsanRuntimeDep() || sanitizable.UbsanRuntimeNeeded() + } } var libType string - if l.static() { + if m.Static() { libType = "static" - } else if l.shared() { + } else if m.Shared() { libType = "shared" } else { libType = "header" @@ -398,16 +401,18 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // install .a or .so if libType != "header" { - libPath := m.outputFile.Path() + libPath := m.OutputFile().Path() stem = libPath.Base() - if l.static() && m.sanitize != nil && m.sanitize.isSanitizerEnabled(cfi) { - // both cfi and non-cfi variant for static libraries can exist. - // attach .cfi to distinguish between cfi and non-cfi. - // e.g. libbase.a -> libbase.cfi.a - ext := filepath.Ext(stem) - stem = strings.TrimSuffix(stem, ext) + ".cfi" + ext - prop.Sanitize = "cfi" - prop.ModuleName += ".cfi" + if sanitizable, ok := m.(PlatformSanitizeable); ok { + if sanitizable.Static() && sanitizable.SanitizePropDefined() && sanitizable.IsSanitizerEnabled(cfi) { + // both cfi and non-cfi variant for static libraries can exist. + // attach .cfi to distinguish between cfi and non-cfi. + // e.g. libbase.a -> libbase.cfi.a + ext := filepath.Ext(stem) + stem = strings.TrimSuffix(stem, ext) + ".cfi" + ext + prop.Sanitize = "cfi" + prop.ModuleName += ".cfi" + } } snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem) ret = append(ret, copyFile(ctx, libPath, snapshotLibOut, fake)) @@ -416,20 +421,20 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { } propOut = filepath.Join(snapshotArchDir, targetArch, libType, stem+".json") - } else if m.binary() { + } else if m.Binary() { // binary flags prop.Symlinks = m.Symlinks() - prop.SharedLibs = m.Properties.SnapshotSharedLibs + prop.SharedLibs = m.SnapshotSharedLibs() // install bin - binPath := m.outputFile.Path() + binPath := m.OutputFile().Path() snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base()) ret = append(ret, copyFile(ctx, binPath, snapshotBinOut, fake)) propOut = snapshotBinOut + ".json" - } else if m.object() { + } else if m.Object() { // object files aren't installed to the device, so their names can conflict. // Use module name as stem. - objPath := m.outputFile.Path() + objPath := m.OutputFile().Path() snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object", ctx.ModuleName(m)+filepath.Ext(objPath.Base())) ret = append(ret, copyFile(ctx, objPath, snapshotObjOut, fake)) @@ -450,7 +455,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { } ctx.VisitAllModules(func(module android.Module) { - m, ok := module.(*Module) + m, ok := module.(LinkableInterface) if !ok { return } @@ -484,8 +489,8 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // installSnapshot installs prebuilts and json flag files snapshotOutputs = append(snapshotOutputs, installSnapshot(m, installAsFake)...) // just gather headers and notice files here, because they are to be deduplicated - if l, ok := m.linker.(snapshotLibraryInterface); ok { - headers = append(headers, l.snapshotHeaders()...) + if m.IsSnapshotLibrary() { + headers = append(headers, m.SnapshotHeaders()...) } if len(m.NoticeFiles()) > 0 { diff --git a/cc/vndk.go b/cc/vndk.go index 8b3788bbb..0254edc66 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -372,7 +372,7 @@ func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool { if mctx.ModuleName() == "libz" { return false } - return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.isVndkSp() + return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.IsVndkSp() } useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() && @@ -574,38 +574,37 @@ type vndkSnapshotSingleton struct { vndkSnapshotZipFile android.OptionalPath } -func isVndkSnapshotAware(config android.DeviceConfig, m *Module, - apexInfo android.ApexInfo) (i snapshotLibraryInterface, vndkType string, isVndkSnapshotLib bool) { +func isVndkSnapshotAware(config android.DeviceConfig, m LinkableInterface, + apexInfo android.ApexInfo) (vndkType string, isVndkSnapshotLib bool) { if m.Target().NativeBridge == android.NativeBridgeEnabled { - return nil, "", false + return "", false } // !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants. // !installable: Snapshot only cares about "installable" modules. // !m.IsLlndk: llndk stubs are required for building against snapshots. // IsSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense. // !outputFile.Valid: Snapshot requires valid output file. - if !m.InVendor() || (!m.installable(apexInfo) && !m.IsLlndk()) || m.IsSnapshotPrebuilt() || !m.outputFile.Valid() { - return nil, "", false + if !m.InVendor() || (!installable(m, apexInfo) && !m.IsLlndk()) || m.IsSnapshotPrebuilt() || !m.OutputFile().Valid() { + return "", false } - l, ok := m.linker.(snapshotLibraryInterface) - if !ok || !l.shared() { - return nil, "", false + if !m.IsSnapshotLibrary() || !m.Shared() { + return "", false } if m.VndkVersion() == config.PlatformVndkVersion() { if m.IsVndk() && !m.IsVndkExt() { - if m.isVndkSp() { - return l, "vndk-sp", true + if m.IsVndkSp() { + return "vndk-sp", true } else { - return l, "vndk-core", true + return "vndk-core", true } - } else if l.hasLLNDKStubs() && l.stubsVersion() == "" { + } else if m.HasLlndkStubs() && m.StubsVersion() == "" { // Use default version for the snapshot. - return l, "llndk-stub", true + return "llndk-stub", true } } - return nil, "", false + return "", false } func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { @@ -722,7 +721,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) - l, vndkType, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo) + vndkType, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo) if !ok { return } @@ -761,7 +760,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex } if ctx.Config().VndkSnapshotBuildArtifacts() { - headers = append(headers, l.snapshotHeaders()...) + headers = append(headers, m.SnapshotHeaders()...) } }) diff --git a/java/app.go b/java/app.go index 5695022f9..fc1ace07b 100755 --- a/java/app.go +++ b/java/app.go @@ -893,7 +893,7 @@ func (a *AndroidApp) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled() } -func (a *AndroidApp) PreventInstall() { +func (a *AndroidApp) SetPreventInstall() { a.appProperties.PreventInstall = true } diff --git a/rust/Android.bp b/rust/Android.bp index f45404ff2..b611672d4 100644 --- a/rust/Android.bp +++ b/rust/Android.bp @@ -31,8 +31,9 @@ bootstrap_go_package { "protobuf.go", "rust.go", "sanitize.go", - "strip.go", "source_provider.go", + "snapshot_utils.go", + "strip.go", "test.go", "testing.go", ], diff --git a/rust/compiler.go b/rust/compiler.go index a3f02c0d4..1598ebf9a 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -341,6 +341,11 @@ func (compiler *baseCompiler) crateName() string { return compiler.Properties.Crate_name } +func (compiler *baseCompiler) everInstallable() bool { + // Most modules are installable, so return true by default. + return true +} + func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath { dir := compiler.dir if ctx.toolchain().Is64Bit() && compiler.dir64 != "" { diff --git a/rust/proc_macro.go b/rust/proc_macro.go index 4eead3267..c217959cd 100644 --- a/rust/proc_macro.go +++ b/rust/proc_macro.go @@ -82,3 +82,8 @@ func (procMacro *procMacroDecorator) getStem(ctx ModuleContext) string { func (procMacro *procMacroDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep { return rlibAutoDep } + +func (procMacro *procMacroDecorator) everInstallable() bool { + // Proc_macros are never installed + return false +} diff --git a/rust/rust.go b/rust/rust.go index bb971420e..f068b3d7b 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -97,6 +97,7 @@ type BaseProperties struct { PreventInstall bool HideFromMake bool + Installable *bool } type Module struct { @@ -143,6 +144,10 @@ func (mod *Module) SetHideFromMake() { mod.Properties.HideFromMake = true } +func (c *Module) HiddenFromMake() bool { + return c.Properties.HideFromMake +} + func (mod *Module) SanitizePropDefined() bool { // Because compiler is not set for some Rust modules where sanitize might be set, check that compiler is also not // nil since we need compiler to actually sanitize. @@ -210,6 +215,38 @@ func (mod *Module) Shared() bool { return false } +func (mod *Module) Dylib() bool { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok { + return library.dylib() + } + } + return false +} + +func (mod *Module) Rlib() bool { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok { + return library.rlib() + } + } + return false +} + +func (mod *Module) Binary() bool { + if mod.compiler != nil { + if _, ok := mod.compiler.(*binaryDecorator); ok { + return true + } + } + return false +} + +func (mod *Module) Object() bool { + // Rust has no modules which produce only object files. + return false +} + func (mod *Module) Toc() android.OptionalPath { if mod.compiler != nil { if _, ok := mod.compiler.(libraryInterface); ok { @@ -223,12 +260,13 @@ func (mod *Module) UseSdk() bool { return false } -// Returns true if the module is using VNDK libraries instead of the libraries in /system/lib or /system/lib64. -// "product" and "vendor" variant modules return true for this function. -// When BOARD_VNDK_VERSION is set, vendor variants of "vendor_available: true", "vendor: true", -// "soc_specific: true" and more vendor installed modules are included here. -// When PRODUCT_PRODUCT_VNDK_VERSION is set, product variants of "vendor_available: true" or -// "product_specific: true" modules are included here. +func (mod *Module) RelativeInstallPath() string { + if mod.compiler != nil { + return mod.compiler.relativeInstallPath() + } + return "" +} + func (mod *Module) UseVndk() bool { return mod.Properties.VndkVersion != "" } @@ -250,6 +288,10 @@ func (mod *Module) IsVndkExt() bool { return false } +func (mod *Module) IsVndkSp() bool { + return false +} + func (c *Module) IsVndkPrivate() bool { return false } @@ -274,6 +316,14 @@ func (m *Module) NeedsVendorPublicLibraryVariants() bool { return false } +func (mod *Module) HasLlndkStubs() bool { + return false +} + +func (mod *Module) StubsVersion() string { + panic(fmt.Errorf("StubsVersion called on non-versioned module: %q", mod.BaseModuleName())) +} + func (mod *Module) SdkVersion() string { return "" } @@ -362,6 +412,7 @@ type compiler interface { inData() bool install(ctx ModuleContext) relativeInstallPath() string + everInstallable() bool nativeCoverage() bool @@ -423,8 +474,12 @@ func (mod *Module) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool { return mod.coverage != nil && mod.coverage.Properties.NeedCoverageVariant } -func (mod *Module) PreventInstall() { - mod.Properties.PreventInstall = true +func (mod *Module) VndkVersion() string { + return mod.Properties.VndkVersion +} + +func (mod *Module) PreventInstall() bool { + return mod.Properties.PreventInstall } func (mod *Module) HideFromMake() { @@ -676,6 +731,16 @@ func (mod *Module) nativeCoverage() bool { return mod.compiler != nil && mod.compiler.nativeCoverage() } +func (mod *Module) EverInstallable() bool { + return mod.compiler != nil && + // Check to see whether the module is actually ever installable. + mod.compiler.everInstallable() +} + +func (mod *Module) Installable() *bool { + return mod.Properties.Installable +} + func (mod *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain { if mod.cachedToolchain == nil { mod.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch()) diff --git a/rust/sanitize.go b/rust/sanitize.go index 0a53f989f..3d14d512f 100644 --- a/rust/sanitize.go +++ b/rust/sanitize.go @@ -189,6 +189,22 @@ func (sanitize *sanitize) SetSanitizer(t cc.SanitizerType, b bool) { } } +func (m *Module) UbsanRuntimeNeeded() bool { + return false +} + +func (m *Module) MinimalRuntimeNeeded() bool { + return false +} + +func (m *Module) UbsanRuntimeDep() bool { + return false +} + +func (m *Module) MinimalRuntimeDep() bool { + return false +} + // Check if the sanitizer is explicitly disabled (as opposed to nil by // virtue of not being set). func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t cc.SanitizerType) bool { diff --git a/rust/snapshot_utils.go b/rust/snapshot_utils.go new file mode 100644 index 000000000..e0ed1f711 --- /dev/null +++ b/rust/snapshot_utils.go @@ -0,0 +1,54 @@ +// Copyright 2021 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 rust + +import ( + "android/soong/android" +) + +func (mod *Module) ExcludeFromVendorSnapshot() bool { + // TODO Rust does not yet support snapshotting + return true +} + +func (mod *Module) ExcludeFromRecoverySnapshot() bool { + // TODO Rust does not yet support snapshotting + return true +} + +func (mod *Module) IsSnapshotLibrary() bool { + // TODO Rust does not yet support snapshotting + return false +} + +func (mod *Module) SnapshotRuntimeLibs() []string { + // TODO Rust does not yet support a runtime libs notion similar to CC + return []string{} +} + +func (mod *Module) SnapshotSharedLibs() []string { + // TODO Rust does not yet support snapshotting + return []string{} +} + +func (mod *Module) Symlinks() []string { + // TODO update this to return the list of symlinks when Rust supports defining symlinks + return nil +} + +func (m *Module) SnapshotHeaders() android.Paths { + // TODO Rust does not yet support snapshotting + return android.Paths{} +}