diff --git a/cc/androidmk.go b/cc/androidmk.go index 38269cb8f..2ade4e8f3 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -505,7 +505,7 @@ func (c *vndkPrebuiltLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, en }) } -func (c *vendorSnapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { +func (c *snapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { // Each vendor snapshot is exported to androidMk only when BOARD_VNDK_VERSION != current // and the version of the prebuilt is same as BOARD_VNDK_VERSION. if c.shared() { @@ -549,7 +549,7 @@ func (c *vendorSnapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, }) } -func (c *vendorSnapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { +func (c *snapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { entries.Class = "EXECUTABLES" if c.androidMkVendorSuffix { @@ -563,7 +563,7 @@ func (c *vendorSnapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, e }) } -func (c *vendorSnapshotObjectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { +func (c *snapshotObjectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { entries.Class = "STATIC_LIBRARIES" if c.androidMkVendorSuffix { diff --git a/cc/cc.go b/cc/cc.go index 5e4faf268..a2d6cd931 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -305,10 +305,11 @@ type BaseProperties struct { // Normally Soong uses the directory structure to decide which modules // should be included (framework) or excluded (non-framework) from the - // vendor snapshot, but this property allows a partner to exclude a - // module normally thought of as a framework module from the vendor - // snapshot. - Exclude_from_vendor_snapshot *bool + // different snapshots (vendor, recovery, etc.), but these properties + // allow a partner to exclude a module normally thought of as a + // framework module from a snapshot. + Exclude_from_vendor_snapshot *bool + Exclude_from_recovery_snapshot *bool } type VendorProperties struct { @@ -1051,6 +1052,10 @@ func (c *Module) ExcludeFromVendorSnapshot() bool { return Bool(c.Properties.Exclude_from_vendor_snapshot) } +func (c *Module) ExcludeFromRecoverySnapshot() bool { + return Bool(c.Properties.Exclude_from_recovery_snapshot) +} + func isBionic(name string) bool { switch name { case "libc", "libm", "libdl", "libdl_android", "linker": diff --git a/cc/cc_test.go b/cc/cc_test.go index f616cf3a7..f5ce86711 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -1551,6 +1551,8 @@ func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) { android.CheckErrorsAgainstExpectations(t, errs, []string{ `module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, `module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, + `module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, + `module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`, }) } @@ -1597,6 +1599,132 @@ func TestVendorSnapshotExcludeWithVendorAvailable(t *testing.T) { }) } +func TestRecoverySnapshotCapture(t *testing.T) { + bp := ` + cc_library { + name: "libvndk", + vendor_available: true, + recovery_available: true, + product_available: true, + vndk: { + enabled: true, + }, + nocrt: true, + } + + cc_library { + name: "librecovery", + recovery: true, + nocrt: true, + } + + cc_library { + name: "librecovery_available", + recovery_available: true, + nocrt: true, + } + + cc_library_headers { + name: "librecovery_headers", + recovery_available: true, + nocrt: true, + } + + cc_binary { + name: "recovery_bin", + recovery: true, + nocrt: true, + } + + cc_binary { + name: "recovery_available_bin", + recovery_available: true, + nocrt: true, + } + + toolchain_library { + name: "libb", + recovery_available: true, + src: "libb.a", + } + + cc_object { + name: "obj", + recovery_available: true, + } +` + config := TestConfig(buildDir, android.Android, nil, bp, nil) + config.TestProductVariables.DeviceVndkVersion = StringPtr("current") + config.TestProductVariables.Platform_vndk_version = StringPtr("VER") + ctx := testCcWithConfig(t, config) + + // Check Recovery snapshot output. + + snapshotDir := "recovery-snapshot" + snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64") + snapshotSingleton := ctx.SingletonForTests("recovery-snapshot") + + var jsonFiles []string + + for _, arch := range [][]string{ + []string{"arm64", "armv8-a"}, + } { + archType := arch[0] + archVariant := arch[1] + archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) + + // For shared libraries, only recovery_available modules are captured. + sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant) + sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") + checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant) + checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant) + checkSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant) + jsonFiles = append(jsonFiles, + filepath.Join(sharedDir, "libvndk.so.json"), + filepath.Join(sharedDir, "librecovery.so.json"), + filepath.Join(sharedDir, "librecovery_available.so.json")) + + // For static libraries, all recovery:true and recovery_available modules are captured. + staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant) + staticDir := filepath.Join(snapshotVariantPath, archDir, "static") + checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant) + checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant) + checkSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant) + jsonFiles = append(jsonFiles, + filepath.Join(staticDir, "libb.a.json"), + filepath.Join(staticDir, "librecovery.a.json"), + filepath.Join(staticDir, "librecovery_available.a.json")) + + // For binary executables, all recovery:true and recovery_available modules are captured. + if archType == "arm64" { + binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant) + binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary") + checkSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant) + checkSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant) + jsonFiles = append(jsonFiles, + filepath.Join(binaryDir, "recovery_bin.json"), + filepath.Join(binaryDir, "recovery_available_bin.json")) + } + + // For header libraries, all vendor:true and vendor_available modules are captured. + headerDir := filepath.Join(snapshotVariantPath, archDir, "header") + jsonFiles = append(jsonFiles, filepath.Join(headerDir, "librecovery_headers.json")) + + // For object modules, all vendor:true and vendor_available modules are captured. + objectVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant) + objectDir := filepath.Join(snapshotVariantPath, archDir, "object") + checkSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant) + jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json")) + } + + for _, jsonFile := range jsonFiles { + // verify all json files exist + if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil { + t.Errorf("%q expected but not found", jsonFile) + } + } +} + func TestDoubleLoadableDepError(t *testing.T) { // Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib. testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", ` diff --git a/cc/sanitize.go b/cc/sanitize.go index b1326d968..eb6152577 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -847,7 +847,7 @@ func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) { return true } - if p, ok := d.linker.(*vendorSnapshotLibraryDecorator); ok { + if p, ok := d.linker.(*snapshotLibraryDecorator); ok { if Bool(p.properties.Sanitize_minimal_dep) { c.sanitize.Properties.MinimalRuntimeDep = true } diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go index 05c06ac25..a3d52e621 100644 --- a/cc/snapshot_utils.go +++ b/cc/snapshot_utils.go @@ -60,7 +60,8 @@ func (s *snapshotMap) get(name string, arch android.ArchType) (snapshot string, func isSnapshotAware(ctx android.ModuleContext, m *Module, apexInfo android.ApexInfo) bool { if _, _, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m, apexInfo); ok { return ctx.Config().VndkSnapshotBuildArtifacts() - } else if isVendorSnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) { + } else if isVendorSnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) || + isRecoverySnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) { return true } return false diff --git a/cc/testing.go b/cc/testing.go index 5a311f4b9..716131300 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -563,6 +563,7 @@ func CreateTestContext(config android.Config) *android.TestContext { RegisterRequiredBuildComponentsForTest(ctx) ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton) ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton) + ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton) return ctx } diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 78bde3816..6563f6e74 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -25,6 +25,115 @@ import ( "android/soong/android" ) +// Defines the specifics of different images to which the snapshot process is +// applicable, e.g., vendor, recovery, ramdisk. +type image interface { + // Used to register callbacks with the build system. + init() + + // 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 + + // Returns the value of the "available" property for a given module for + // and snapshot, e.g., "vendor_available", "recovery_available", etc. + // or nil if the property is not defined. + available(m *Module) *bool + + // Returns true if a dir under source tree is an SoC-owned proprietary + // directory, such as device/, vendor/, etc. + // + // For a given snapshot (e.g., vendor, recovery, etc.) if + // isProprietaryPath(dir) returns true, then the module in dir will be + // built from sources. + isProprietaryPath(dir string) bool + + // Whether to include VNDK in the snapshot for this image. + includeVndk() bool + + // 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 +} + +type vendorImage struct{} +type recoveryImage struct{} + +func (vendorImage) init() { + android.RegisterSingletonType( + "vendor-snapshot", VendorSnapshotSingleton) + android.RegisterModuleType( + "vendor_snapshot_shared", VendorSnapshotSharedFactory) + android.RegisterModuleType( + "vendor_snapshot_static", VendorSnapshotStaticFactory) + android.RegisterModuleType( + "vendor_snapshot_header", VendorSnapshotHeaderFactory) + android.RegisterModuleType( + "vendor_snapshot_binary", VendorSnapshotBinaryFactory) + android.RegisterModuleType( + "vendor_snapshot_object", VendorSnapshotObjectFactory) +} + +func (vendorImage) inImage(m *Module) func() bool { + return m.inVendor +} + +func (vendorImage) available(m *Module) *bool { + return m.VendorProperties.Vendor_available +} + +func (vendorImage) isProprietaryPath(dir string) bool { + return isVendorProprietaryPath(dir) +} + +func (vendorImage) includeVndk() bool { + return true +} + +func (vendorImage) excludeFromSnapshot(m *Module) bool { + return m.ExcludeFromVendorSnapshot() +} + +func (recoveryImage) init() { + android.RegisterSingletonType( + "recovery-snapshot", RecoverySnapshotSingleton) + android.RegisterModuleType( + "recovery_snapshot_shared", RecoverySnapshotSharedFactory) + android.RegisterModuleType( + "recovery_snapshot_static", RecoverySnapshotStaticFactory) + android.RegisterModuleType( + "recovery_snapshot_header", RecoverySnapshotHeaderFactory) + android.RegisterModuleType( + "recovery_snapshot_binary", RecoverySnapshotBinaryFactory) + android.RegisterModuleType( + "recovery_snapshot_object", RecoverySnapshotObjectFactory) +} + +func (recoveryImage) inImage(m *Module) func() bool { + return m.InRecovery +} + +func (recoveryImage) available(m *Module) *bool { + return m.Properties.Recovery_available +} + +func (recoveryImage) isProprietaryPath(dir string) bool { + return isRecoveryProprietaryPath(dir) +} + +func (recoveryImage) includeVndk() bool { + return false +} + +func (recoveryImage) excludeFromSnapshot(m *Module) bool { + return m.ExcludeFromRecoverySnapshot() +} + +var vendorImageSingleton vendorImage +var recoveryImageSingleton recoveryImage + const ( vendorSnapshotHeaderSuffix = ".vendor_header." vendorSnapshotSharedSuffix = ".vendor_shared." @@ -33,6 +142,14 @@ const ( vendorSnapshotObjectSuffix = ".vendor_object." ) +const ( + recoverySnapshotHeaderSuffix = ".recovery_header." + recoverySnapshotSharedSuffix = ".recovery_shared." + recoverySnapshotStaticSuffix = ".recovery_static." + recoverySnapshotBinarySuffix = ".recovery_binary." + recoverySnapshotObjectSuffix = ".recovery_object." +) + var ( vendorSnapshotsLock sync.Mutex vendorSuffixModulesKey = android.NewOnceKey("vendorSuffixModules") @@ -136,7 +253,7 @@ func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *vendorSnapshotModule } } -type vendorSnapshotLibraryProperties struct { +type snapshotLibraryProperties struct { // Prebuilt file for each arch. Src *string `android:"arch_variant"` @@ -161,25 +278,25 @@ type snapshotSanitizer interface { setSanitizerVariation(t sanitizerType, enabled bool) } -type vendorSnapshotLibraryDecorator struct { +type snapshotLibraryDecorator struct { vendorSnapshotModuleBase *libraryDecorator - properties vendorSnapshotLibraryProperties + properties snapshotLibraryProperties sanitizerProperties struct { CfiEnabled bool `blueprint:"mutated"` // Library flags for cfi variant. - Cfi vendorSnapshotLibraryProperties `android:"arch_variant"` + Cfi snapshotLibraryProperties `android:"arch_variant"` } androidMkVendorSuffix bool } -func (p *vendorSnapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { +func (p *snapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix()) return p.libraryDecorator.linkerFlags(ctx, flags) } -func (p *vendorSnapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool { +func (p *snapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool { arches := config.Arches() if len(arches) == 0 || arches[0].ArchType.String() != p.arch() { return false @@ -190,7 +307,7 @@ func (p *vendorSnapshotLibraryDecorator) matchesWithDevice(config android.Device return true } -func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext, +func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { m := ctx.Module().(*Module) p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()] @@ -246,17 +363,17 @@ func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext, return in } -func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) { +func (p *snapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) { if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) { p.baseInstaller.install(ctx, file) } } -func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool { +func (p *snapshotLibraryDecorator) nativeCoverage() bool { return false } -func (p *vendorSnapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool { +func (p *snapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool { switch t { case cfi: return p.sanitizerProperties.Cfi.Src != nil @@ -265,7 +382,7 @@ func (p *vendorSnapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) boo } } -func (p *vendorSnapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) { +func (p *snapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) { if !enabled { return } @@ -277,14 +394,14 @@ func (p *vendorSnapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, } } -func vendorSnapshotLibrary(suffix string) (*Module, *vendorSnapshotLibraryDecorator) { +func snapshotLibrary(suffix string) (*Module, *snapshotLibraryDecorator) { module, library := NewLibrary(android.DeviceSupported) module.stl = nil module.sanitize = nil library.disableStripping() - prebuilt := &vendorSnapshotLibraryDecorator{ + prebuilt := &snapshotLibraryDecorator{ libraryDecorator: library, } @@ -310,38 +427,56 @@ func vendorSnapshotLibrary(suffix string) (*Module, *vendorSnapshotLibraryDecora } func VendorSnapshotSharedFactory() android.Module { - module, prebuilt := vendorSnapshotLibrary(vendorSnapshotSharedSuffix) + module, prebuilt := snapshotLibrary(vendorSnapshotSharedSuffix) + prebuilt.libraryDecorator.BuildOnlyShared() + return module.Init() +} + +func RecoverySnapshotSharedFactory() android.Module { + module, prebuilt := snapshotLibrary(recoverySnapshotSharedSuffix) prebuilt.libraryDecorator.BuildOnlyShared() return module.Init() } func VendorSnapshotStaticFactory() android.Module { - module, prebuilt := vendorSnapshotLibrary(vendorSnapshotStaticSuffix) + module, prebuilt := snapshotLibrary(vendorSnapshotStaticSuffix) + prebuilt.libraryDecorator.BuildOnlyStatic() + return module.Init() +} + +func RecoverySnapshotStaticFactory() android.Module { + module, prebuilt := snapshotLibrary(recoverySnapshotStaticSuffix) prebuilt.libraryDecorator.BuildOnlyStatic() return module.Init() } func VendorSnapshotHeaderFactory() android.Module { - module, prebuilt := vendorSnapshotLibrary(vendorSnapshotHeaderSuffix) + module, prebuilt := snapshotLibrary(vendorSnapshotHeaderSuffix) prebuilt.libraryDecorator.HeaderOnly() return module.Init() } -var _ snapshotSanitizer = (*vendorSnapshotLibraryDecorator)(nil) +func RecoverySnapshotHeaderFactory() android.Module { + module, prebuilt := snapshotLibrary(recoverySnapshotHeaderSuffix) + prebuilt.libraryDecorator.HeaderOnly() + return module.Init() +} -type vendorSnapshotBinaryProperties struct { +var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil) + +type snapshotBinaryProperties struct { // Prebuilt file for each arch. Src *string `android:"arch_variant"` } -type vendorSnapshotBinaryDecorator struct { +type snapshotBinaryDecorator struct { vendorSnapshotModuleBase *binaryDecorator - properties vendorSnapshotBinaryProperties + properties snapshotBinaryProperties androidMkVendorSuffix bool } -func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool { +func (p *snapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool { if config.DeviceArch() != p.arch() { return false } @@ -351,7 +486,7 @@ func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceC return true } -func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext, +func (p *snapshotBinaryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { if !p.matchesWithDevice(ctx.DeviceConfig()) { return nil @@ -382,11 +517,19 @@ func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext, return outputFile } -func (p *vendorSnapshotBinaryDecorator) nativeCoverage() bool { +func (p *snapshotBinaryDecorator) nativeCoverage() bool { return false } func VendorSnapshotBinaryFactory() android.Module { + return snapshotBinaryFactory(vendorSnapshotBinarySuffix) +} + +func RecoverySnapshotBinaryFactory() android.Module { + return snapshotBinaryFactory(recoverySnapshotBinarySuffix) +} + +func snapshotBinaryFactory(suffix string) android.Module { module, binary := NewBinary(android.DeviceSupported) binary.baseLinker.Properties.No_libcrt = BoolPtr(true) binary.baseLinker.Properties.Nocrt = BoolPtr(true) @@ -396,7 +539,7 @@ func VendorSnapshotBinaryFactory() android.Module { binary.baseLinker.Properties.System_shared_libs = []string{} } - prebuilt := &vendorSnapshotBinaryDecorator{ + prebuilt := &snapshotBinaryDecorator{ binaryDecorator: binary, } @@ -405,7 +548,7 @@ func VendorSnapshotBinaryFactory() android.Module { module.stl = nil module.linker = prebuilt - prebuilt.init(module, vendorSnapshotBinarySuffix) + prebuilt.init(module, suffix) module.AddProperties(&prebuilt.properties) return module.Init() } @@ -415,14 +558,14 @@ type vendorSnapshotObjectProperties struct { Src *string `android:"arch_variant"` } -type vendorSnapshotObjectLinker struct { +type snapshotObjectLinker struct { vendorSnapshotModuleBase objectLinker properties vendorSnapshotObjectProperties androidMkVendorSuffix bool } -func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool { +func (p *snapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool { if config.DeviceArch() != p.arch() { return false } @@ -432,7 +575,7 @@ func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConf return true } -func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext, +func (p *snapshotObjectLinker) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { if !p.matchesWithDevice(ctx.DeviceConfig()) { return nil @@ -444,14 +587,14 @@ func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext, return android.PathForModuleSrc(ctx, *p.properties.Src) } -func (p *vendorSnapshotObjectLinker) nativeCoverage() bool { +func (p *snapshotObjectLinker) nativeCoverage() bool { return false } func VendorSnapshotObjectFactory() android.Module { module := newObject() - prebuilt := &vendorSnapshotObjectLinker{ + prebuilt := &snapshotObjectLinker{ objectLinker: objectLinker{ baseLinker: NewBaseLinker(nil), }, @@ -463,21 +606,68 @@ func VendorSnapshotObjectFactory() android.Module { return module.Init() } +func RecoverySnapshotObjectFactory() android.Module { + module := newObject() + + prebuilt := &snapshotObjectLinker{ + objectLinker: objectLinker{ + baseLinker: NewBaseLinker(nil), + }, + } + module.linker = prebuilt + + prebuilt.init(module, recoverySnapshotObjectSuffix) + module.AddProperties(&prebuilt.properties) + return module.Init() +} + func init() { - android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton) - android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory) - android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory) - android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory) - android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory) - android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory) + vendorImageSingleton.init() + recoveryImageSingleton.init() +} + +var vendorSnapshotSingleton = snapshotSingleton{ + "vendor", + "SOONG_VENDOR_SNAPSHOT_ZIP", + android.OptionalPath{}, + true, + vendorImageSingleton, +} + +var recoverySnapshotSingleton = snapshotSingleton{ + "recovery", + "SOONG_RECOVERY_SNAPSHOT_ZIP", + android.OptionalPath{}, + false, + recoveryImageSingleton, } func VendorSnapshotSingleton() android.Singleton { - return &vendorSnapshotSingleton{} + return &vendorSnapshotSingleton } -type vendorSnapshotSingleton struct { - vendorSnapshotZipFile android.OptionalPath +func RecoverySnapshotSingleton() android.Singleton { + return &recoverySnapshotSingleton +} + +type snapshotSingleton struct { + // Name, e.g., "vendor", "recovery", "ramdisk". + name string + + // Make variable that points to the snapshot file, e.g., + // "SOONG_RECOVERY_SNAPSHOT_ZIP". + makeVar string + + // Path to the snapshot zip file. + snapshotZipFile android.OptionalPath + + // Whether the image supports VNDK extension modules. + supportsVndkExt bool + + // Implementation of the image interface specific to the image + // associated with this snapshot (e.g., specific to the vendor image, + // recovery image, etc.). + image image } var ( @@ -491,6 +681,17 @@ var ( "hardware", } + // Modules under following directories are ignored. They are OEM's and vendor's + // proprietary modules(device/, kernel/, vendor/, and hardware/). + // TODO(b/65377115): Clean up these with more maintainable way + recoveryProprietaryDirs = []string{ + "bootable/recovery", + "device", + "hardware", + "kernel", + "vendor", + } + // Modules under following directories are included as they are in AOSP, // although hardware/ and kernel/ are normally for vendor's own. // TODO(b/65377115): Clean up these with more maintainable way @@ -508,7 +709,17 @@ var ( // Determine if a dir under source tree is an SoC-owned proprietary directory, such as // device/, vendor/, etc. func isVendorProprietaryPath(dir string) bool { - for _, p := range vendorProprietaryDirs { + return isProprietaryPath(dir, vendorProprietaryDirs) +} + +func isRecoveryProprietaryPath(dir string) bool { + return isProprietaryPath(dir, recoveryProprietaryDirs) +} + +// Determine if a dir under source tree is an SoC-owned proprietary directory, such as +// device/, vendor/, etc. +func isProprietaryPath(dir string, proprietaryDirs []string) bool { + for _, p := range proprietaryDirs { if strings.HasPrefix(dir, p) { // filter out AOSP defined directories, e.g. hardware/interfaces/ aosp := false @@ -556,6 +767,14 @@ func isVendorProprietaryModule(ctx android.BaseModuleContext) bool { // depend on newer VNDK) So they are captured as vendor snapshot To build older vendor // image and newer system image altogether. func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool, apexInfo android.ApexInfo) bool { + return isSnapshotModule(m, inVendorProprietaryPath, apexInfo, vendorImageSingleton) +} + +func isRecoverySnapshotModule(m *Module, inRecoveryProprietaryPath bool, apexInfo android.ApexInfo) bool { + return isSnapshotModule(m, inRecoveryProprietaryPath, apexInfo, recoveryImageSingleton) +} + +func isSnapshotModule(m *Module, inProprietaryPath bool, apexInfo android.ApexInfo, image image) bool { if !m.Enabled() || m.Properties.HideFromMake { return false } @@ -564,8 +783,9 @@ func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool, apexInfo an if m.IsSkipInstall() { return false } - // skip proprietary modules, but include all VNDK (static) - if inVendorProprietaryPath && !m.IsVndk() { + // skip proprietary modules, but (for the vendor snapshot only) + // include all VNDK (static) + if inProprietaryPath && (!image.includeVndk() || !m.IsVndk()) { return false } // If the module would be included based on its path, check to see if @@ -580,7 +800,7 @@ func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool, apexInfo an return false } // the module must be installed in /vendor - if !apexInfo.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() { + if !apexInfo.IsForPlatform() || m.isSnapshotPrebuilt() || !image.inImage(m)() { return false } // skip kernel_headers which always depend on vendor @@ -612,29 +832,31 @@ func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool, apexInfo an } } if l.static() { - return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true) + return m.outputFile.Valid() && proptools.BoolDefault(image.available(m), true) } if l.shared() { if !m.outputFile.Valid() { return false } - if !m.IsVndk() { - return true + if image.includeVndk() { + if !m.IsVndk() { + return true + } + return m.isVndkExt() } - return m.isVndkExt() } return true } // Binaries and Objects if m.binary() || m.object() { - return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true) + return m.outputFile.Valid() && proptools.BoolDefault(image.available(m), true) } return false } -func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { +func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot. if ctx.DeviceConfig().VndkVersion() != "current" { return @@ -675,7 +897,7 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont (header files of same directory structure with source tree) */ - snapshotDir := "vendor-snapshot" + snapshotDir := c.name + "-snapshot" snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch()) includeDir := filepath.Join(snapshotArchDir, "include") @@ -722,7 +944,7 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont // Common properties among snapshots. prop.ModuleName = ctx.ModuleName(m) - if m.isVndkExt() { + if c.supportsVndkExt && m.isVndkExt() { // vndk exts are installed to /vendor/lib(64)?/vndk(-sp)? if m.isVndkSp() { prop.RelativeInstallPath = "vndk-sp" @@ -843,26 +1065,30 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont } moduleDir := ctx.ModuleDir(module) - inVendorProprietaryPath := isVendorProprietaryPath(moduleDir) + inProprietaryPath := c.image.isProprietaryPath(moduleDir) apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) if m.ExcludeFromVendorSnapshot() { - if inVendorProprietaryPath { + if inProprietaryPath { // Error: exclude_from_vendor_snapshot applies // to framework-path modules only. ctx.Errorf("module %q in vendor proprietary path %q may not use \"exclude_from_vendor_snapshot: true\"", m.String(), moduleDir) return } - if Bool(m.VendorProperties.Vendor_available) { + if Bool(c.image.available(m)) { // Error: may not combine "vendor_available: // true" with "exclude_from_vendor_snapshot: // true". - ctx.Errorf("module %q may not use both \"vendor_available: true\" and \"exclude_from_vendor_snapshot: true\"", m.String()) + ctx.Errorf( + "module %q may not use both \""+ + c.name+ + "_available: true\" and \"exclude_from_vendor_snapshot: true\"", + m.String()) return } } - if !isVendorSnapshotModule(m, inVendorProprietaryPath, apexInfo) { + if !isSnapshotModule(m, inProprietaryPath, apexInfo, c.image) { return } @@ -894,11 +1120,17 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont return snapshotOutputs[i].String() < snapshotOutputs[j].String() }) - zipPath := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+".zip") + zipPath := android.PathForOutput( + ctx, + snapshotDir, + c.name+"-"+ctx.Config().DeviceName()+".zip") zipRule := android.NewRuleBuilder() // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr - snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+"_list") + snapshotOutputList := android.PathForOutput( + ctx, + snapshotDir, + c.name+"-"+ctx.Config().DeviceName()+"_list") zipRule.Command(). Text("tr"). FlagWithArg("-d ", "\\'"). @@ -913,13 +1145,15 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()). FlagWithInput("-l ", snapshotOutputList) - zipRule.Build(pctx, ctx, zipPath.String(), "vendor snapshot "+zipPath.String()) + zipRule.Build(pctx, ctx, zipPath.String(), c.name+" snapshot "+zipPath.String()) zipRule.DeleteTemporaryFiles() - c.vendorSnapshotZipFile = android.OptionalPathForPath(zipPath) + c.snapshotZipFile = android.OptionalPathForPath(zipPath) } -func (c *vendorSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) { - ctx.Strict("SOONG_VENDOR_SNAPSHOT_ZIP", c.vendorSnapshotZipFile.String()) +func (c *snapshotSingleton) MakeVars(ctx android.MakeVarsContext) { + ctx.Strict( + c.makeVar, + c.snapshotZipFile.String()) } type snapshotInterface interface { @@ -927,9 +1161,9 @@ type snapshotInterface interface { } var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil) -var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil) -var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil) -var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil) +var _ snapshotInterface = (*snapshotLibraryDecorator)(nil) +var _ snapshotInterface = (*snapshotBinaryDecorator)(nil) +var _ snapshotInterface = (*snapshotObjectLinker)(nil) // gathers all snapshot modules for vendor, and disable unnecessary snapshots // TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules @@ -970,9 +1204,9 @@ func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) { // header snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) } - } else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok { + } else if _, ok := module.linker.(*snapshotBinaryDecorator); ok { snapshotMap = vendorSnapshotBinaries(ctx.Config()) - } else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok { + } else if _, ok := module.linker.(*snapshotObjectLinker); ok { snapshotMap = vendorSnapshotObjects(ctx.Config()) } else { return