Merge "Support for recovery snapshot."

This commit is contained in:
Jose "Pepe" Galmes
2020-11-17 20:51:54 +00:00
committed by Gerrit Code Review
7 changed files with 445 additions and 76 deletions

View File

@@ -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 // 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. // and the version of the prebuilt is same as BOARD_VNDK_VERSION.
if c.shared() { 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" entries.Class = "EXECUTABLES"
if c.androidMkVendorSuffix { 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" entries.Class = "STATIC_LIBRARIES"
if c.androidMkVendorSuffix { if c.androidMkVendorSuffix {

View File

@@ -305,10 +305,11 @@ type BaseProperties struct {
// Normally Soong uses the directory structure to decide which modules // Normally Soong uses the directory structure to decide which modules
// should be included (framework) or excluded (non-framework) from the // should be included (framework) or excluded (non-framework) from the
// vendor snapshot, but this property allows a partner to exclude a // different snapshots (vendor, recovery, etc.), but these properties
// module normally thought of as a framework module from the vendor // allow a partner to exclude a module normally thought of as a
// snapshot. // framework module from a snapshot.
Exclude_from_vendor_snapshot *bool Exclude_from_vendor_snapshot *bool
Exclude_from_recovery_snapshot *bool
} }
type VendorProperties struct { type VendorProperties struct {
@@ -1051,6 +1052,10 @@ func (c *Module) ExcludeFromVendorSnapshot() bool {
return Bool(c.Properties.Exclude_from_vendor_snapshot) 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 { func isBionic(name string) bool {
switch name { switch name {
case "libc", "libm", "libdl", "libdl_android", "linker": case "libc", "libm", "libdl", "libdl_android", "linker":

View File

@@ -1551,6 +1551,8 @@ func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) {
android.CheckErrorsAgainstExpectations(t, errs, []string{ 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: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: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) { func TestDoubleLoadableDepError(t *testing.T) {
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib. // 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", ` testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `

View File

@@ -847,7 +847,7 @@ func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
return true return true
} }
if p, ok := d.linker.(*vendorSnapshotLibraryDecorator); ok { if p, ok := d.linker.(*snapshotLibraryDecorator); ok {
if Bool(p.properties.Sanitize_minimal_dep) { if Bool(p.properties.Sanitize_minimal_dep) {
c.sanitize.Properties.MinimalRuntimeDep = true c.sanitize.Properties.MinimalRuntimeDep = true
} }

View File

@@ -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 { func isSnapshotAware(ctx android.ModuleContext, m *Module, apexInfo android.ApexInfo) bool {
if _, _, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m, apexInfo); ok { if _, _, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m, apexInfo); ok {
return ctx.Config().VndkSnapshotBuildArtifacts() 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 true
} }
return false return false

View File

@@ -563,6 +563,7 @@ func CreateTestContext(config android.Config) *android.TestContext {
RegisterRequiredBuildComponentsForTest(ctx) RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton) ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton) ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
return ctx return ctx
} }

View File

@@ -25,6 +25,115 @@ import (
"android/soong/android" "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 ( const (
vendorSnapshotHeaderSuffix = ".vendor_header." vendorSnapshotHeaderSuffix = ".vendor_header."
vendorSnapshotSharedSuffix = ".vendor_shared." vendorSnapshotSharedSuffix = ".vendor_shared."
@@ -33,6 +142,14 @@ const (
vendorSnapshotObjectSuffix = ".vendor_object." vendorSnapshotObjectSuffix = ".vendor_object."
) )
const (
recoverySnapshotHeaderSuffix = ".recovery_header."
recoverySnapshotSharedSuffix = ".recovery_shared."
recoverySnapshotStaticSuffix = ".recovery_static."
recoverySnapshotBinarySuffix = ".recovery_binary."
recoverySnapshotObjectSuffix = ".recovery_object."
)
var ( var (
vendorSnapshotsLock sync.Mutex vendorSnapshotsLock sync.Mutex
vendorSuffixModulesKey = android.NewOnceKey("vendorSuffixModules") 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. // Prebuilt file for each arch.
Src *string `android:"arch_variant"` Src *string `android:"arch_variant"`
@@ -161,25 +278,25 @@ type snapshotSanitizer interface {
setSanitizerVariation(t sanitizerType, enabled bool) setSanitizerVariation(t sanitizerType, enabled bool)
} }
type vendorSnapshotLibraryDecorator struct { type snapshotLibraryDecorator struct {
vendorSnapshotModuleBase vendorSnapshotModuleBase
*libraryDecorator *libraryDecorator
properties vendorSnapshotLibraryProperties properties snapshotLibraryProperties
sanitizerProperties struct { sanitizerProperties struct {
CfiEnabled bool `blueprint:"mutated"` CfiEnabled bool `blueprint:"mutated"`
// Library flags for cfi variant. // Library flags for cfi variant.
Cfi vendorSnapshotLibraryProperties `android:"arch_variant"` Cfi snapshotLibraryProperties `android:"arch_variant"`
} }
androidMkVendorSuffix bool 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()) p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix())
return p.libraryDecorator.linkerFlags(ctx, flags) 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() arches := config.Arches()
if len(arches) == 0 || arches[0].ArchType.String() != p.arch() { if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
return false return false
@@ -190,7 +307,7 @@ func (p *vendorSnapshotLibraryDecorator) matchesWithDevice(config android.Device
return true return true
} }
func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext, func (p *snapshotLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path { flags Flags, deps PathDeps, objs Objects) android.Path {
m := ctx.Module().(*Module) m := ctx.Module().(*Module)
p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()] p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
@@ -246,17 +363,17 @@ func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext,
return in 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()) { if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
p.baseInstaller.install(ctx, file) p.baseInstaller.install(ctx, file)
} }
} }
func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool { func (p *snapshotLibraryDecorator) nativeCoverage() bool {
return false return false
} }
func (p *vendorSnapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool { func (p *snapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool {
switch t { switch t {
case cfi: case cfi:
return p.sanitizerProperties.Cfi.Src != nil 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 { if !enabled {
return 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, library := NewLibrary(android.DeviceSupported)
module.stl = nil module.stl = nil
module.sanitize = nil module.sanitize = nil
library.disableStripping() library.disableStripping()
prebuilt := &vendorSnapshotLibraryDecorator{ prebuilt := &snapshotLibraryDecorator{
libraryDecorator: library, libraryDecorator: library,
} }
@@ -310,38 +427,56 @@ func vendorSnapshotLibrary(suffix string) (*Module, *vendorSnapshotLibraryDecora
} }
func VendorSnapshotSharedFactory() android.Module { 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() prebuilt.libraryDecorator.BuildOnlyShared()
return module.Init() return module.Init()
} }
func VendorSnapshotStaticFactory() android.Module { 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() prebuilt.libraryDecorator.BuildOnlyStatic()
return module.Init() return module.Init()
} }
func VendorSnapshotHeaderFactory() android.Module { func VendorSnapshotHeaderFactory() android.Module {
module, prebuilt := vendorSnapshotLibrary(vendorSnapshotHeaderSuffix) module, prebuilt := snapshotLibrary(vendorSnapshotHeaderSuffix)
prebuilt.libraryDecorator.HeaderOnly() prebuilt.libraryDecorator.HeaderOnly()
return module.Init() 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. // Prebuilt file for each arch.
Src *string `android:"arch_variant"` Src *string `android:"arch_variant"`
} }
type vendorSnapshotBinaryDecorator struct { type snapshotBinaryDecorator struct {
vendorSnapshotModuleBase vendorSnapshotModuleBase
*binaryDecorator *binaryDecorator
properties vendorSnapshotBinaryProperties properties snapshotBinaryProperties
androidMkVendorSuffix bool androidMkVendorSuffix bool
} }
func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool { func (p *snapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
if config.DeviceArch() != p.arch() { if config.DeviceArch() != p.arch() {
return false return false
} }
@@ -351,7 +486,7 @@ func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceC
return true return true
} }
func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext, func (p *snapshotBinaryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path { flags Flags, deps PathDeps, objs Objects) android.Path {
if !p.matchesWithDevice(ctx.DeviceConfig()) { if !p.matchesWithDevice(ctx.DeviceConfig()) {
return nil return nil
@@ -382,11 +517,19 @@ func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext,
return outputFile return outputFile
} }
func (p *vendorSnapshotBinaryDecorator) nativeCoverage() bool { func (p *snapshotBinaryDecorator) nativeCoverage() bool {
return false return false
} }
func VendorSnapshotBinaryFactory() android.Module { 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) module, binary := NewBinary(android.DeviceSupported)
binary.baseLinker.Properties.No_libcrt = BoolPtr(true) binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
binary.baseLinker.Properties.Nocrt = BoolPtr(true) binary.baseLinker.Properties.Nocrt = BoolPtr(true)
@@ -396,7 +539,7 @@ func VendorSnapshotBinaryFactory() android.Module {
binary.baseLinker.Properties.System_shared_libs = []string{} binary.baseLinker.Properties.System_shared_libs = []string{}
} }
prebuilt := &vendorSnapshotBinaryDecorator{ prebuilt := &snapshotBinaryDecorator{
binaryDecorator: binary, binaryDecorator: binary,
} }
@@ -405,7 +548,7 @@ func VendorSnapshotBinaryFactory() android.Module {
module.stl = nil module.stl = nil
module.linker = prebuilt module.linker = prebuilt
prebuilt.init(module, vendorSnapshotBinarySuffix) prebuilt.init(module, suffix)
module.AddProperties(&prebuilt.properties) module.AddProperties(&prebuilt.properties)
return module.Init() return module.Init()
} }
@@ -415,14 +558,14 @@ type vendorSnapshotObjectProperties struct {
Src *string `android:"arch_variant"` Src *string `android:"arch_variant"`
} }
type vendorSnapshotObjectLinker struct { type snapshotObjectLinker struct {
vendorSnapshotModuleBase vendorSnapshotModuleBase
objectLinker objectLinker
properties vendorSnapshotObjectProperties properties vendorSnapshotObjectProperties
androidMkVendorSuffix bool androidMkVendorSuffix bool
} }
func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool { func (p *snapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
if config.DeviceArch() != p.arch() { if config.DeviceArch() != p.arch() {
return false return false
} }
@@ -432,7 +575,7 @@ func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConf
return true return true
} }
func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext, func (p *snapshotObjectLinker) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path { flags Flags, deps PathDeps, objs Objects) android.Path {
if !p.matchesWithDevice(ctx.DeviceConfig()) { if !p.matchesWithDevice(ctx.DeviceConfig()) {
return nil return nil
@@ -444,14 +587,14 @@ func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext,
return android.PathForModuleSrc(ctx, *p.properties.Src) return android.PathForModuleSrc(ctx, *p.properties.Src)
} }
func (p *vendorSnapshotObjectLinker) nativeCoverage() bool { func (p *snapshotObjectLinker) nativeCoverage() bool {
return false return false
} }
func VendorSnapshotObjectFactory() android.Module { func VendorSnapshotObjectFactory() android.Module {
module := newObject() module := newObject()
prebuilt := &vendorSnapshotObjectLinker{ prebuilt := &snapshotObjectLinker{
objectLinker: objectLinker{ objectLinker: objectLinker{
baseLinker: NewBaseLinker(nil), baseLinker: NewBaseLinker(nil),
}, },
@@ -463,21 +606,68 @@ func VendorSnapshotObjectFactory() android.Module {
return module.Init() 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() { func init() {
android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton) vendorImageSingleton.init()
android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory) recoveryImageSingleton.init()
android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory) }
android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory) var vendorSnapshotSingleton = snapshotSingleton{
android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory) "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 { func VendorSnapshotSingleton() android.Singleton {
return &vendorSnapshotSingleton{} return &vendorSnapshotSingleton
} }
type vendorSnapshotSingleton struct { func RecoverySnapshotSingleton() android.Singleton {
vendorSnapshotZipFile android.OptionalPath 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 ( var (
@@ -491,6 +681,17 @@ var (
"hardware", "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, // Modules under following directories are included as they are in AOSP,
// although hardware/ and kernel/ are normally for vendor's own. // although hardware/ and kernel/ are normally for vendor's own.
// TODO(b/65377115): Clean up these with more maintainable way // 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 // Determine if a dir under source tree is an SoC-owned proprietary directory, such as
// device/, vendor/, etc. // device/, vendor/, etc.
func isVendorProprietaryPath(dir string) bool { 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) { if strings.HasPrefix(dir, p) {
// filter out AOSP defined directories, e.g. hardware/interfaces/ // filter out AOSP defined directories, e.g. hardware/interfaces/
aosp := false 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 // depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
// image and newer system image altogether. // image and newer system image altogether.
func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool, apexInfo android.ApexInfo) bool { 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 { if !m.Enabled() || m.Properties.HideFromMake {
return false return false
} }
@@ -564,8 +783,9 @@ func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool, apexInfo an
if m.IsSkipInstall() { if m.IsSkipInstall() {
return false return false
} }
// skip proprietary modules, but include all VNDK (static) // skip proprietary modules, but (for the vendor snapshot only)
if inVendorProprietaryPath && !m.IsVndk() { // include all VNDK (static)
if inProprietaryPath && (!image.includeVndk() || !m.IsVndk()) {
return false return false
} }
// If the module would be included based on its path, check to see if // 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 return false
} }
// the module must be installed in /vendor // the module must be installed in /vendor
if !apexInfo.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() { if !apexInfo.IsForPlatform() || m.isSnapshotPrebuilt() || !image.inImage(m)() {
return false return false
} }
// skip kernel_headers which always depend on vendor // skip kernel_headers which always depend on vendor
@@ -612,29 +832,31 @@ func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool, apexInfo an
} }
} }
if l.static() { 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 l.shared() {
if !m.outputFile.Valid() { if !m.outputFile.Valid() {
return false return false
} }
if image.includeVndk() {
if !m.IsVndk() { if !m.IsVndk() {
return true return true
} }
return m.isVndkExt() return m.isVndkExt()
} }
}
return true return true
} }
// Binaries and Objects // Binaries and Objects
if m.binary() || m.object() { 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 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. // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot.
if ctx.DeviceConfig().VndkVersion() != "current" { if ctx.DeviceConfig().VndkVersion() != "current" {
return return
@@ -675,7 +897,7 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont
(header files of same directory structure with source tree) (header files of same directory structure with source tree)
*/ */
snapshotDir := "vendor-snapshot" snapshotDir := c.name + "-snapshot"
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch()) snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
includeDir := filepath.Join(snapshotArchDir, "include") includeDir := filepath.Join(snapshotArchDir, "include")
@@ -722,7 +944,7 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont
// Common properties among snapshots. // Common properties among snapshots.
prop.ModuleName = ctx.ModuleName(m) prop.ModuleName = ctx.ModuleName(m)
if m.isVndkExt() { if c.supportsVndkExt && m.isVndkExt() {
// vndk exts are installed to /vendor/lib(64)?/vndk(-sp)? // vndk exts are installed to /vendor/lib(64)?/vndk(-sp)?
if m.isVndkSp() { if m.isVndkSp() {
prop.RelativeInstallPath = "vndk-sp" prop.RelativeInstallPath = "vndk-sp"
@@ -843,26 +1065,30 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont
} }
moduleDir := ctx.ModuleDir(module) moduleDir := ctx.ModuleDir(module)
inVendorProprietaryPath := isVendorProprietaryPath(moduleDir) inProprietaryPath := c.image.isProprietaryPath(moduleDir)
apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
if m.ExcludeFromVendorSnapshot() { if m.ExcludeFromVendorSnapshot() {
if inVendorProprietaryPath { if inProprietaryPath {
// Error: exclude_from_vendor_snapshot applies // Error: exclude_from_vendor_snapshot applies
// to framework-path modules only. // 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) ctx.Errorf("module %q in vendor proprietary path %q may not use \"exclude_from_vendor_snapshot: true\"", m.String(), moduleDir)
return return
} }
if Bool(m.VendorProperties.Vendor_available) { if Bool(c.image.available(m)) {
// Error: may not combine "vendor_available: // Error: may not combine "vendor_available:
// true" with "exclude_from_vendor_snapshot: // true" with "exclude_from_vendor_snapshot:
// true". // 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 return
} }
} }
if !isVendorSnapshotModule(m, inVendorProprietaryPath, apexInfo) { if !isSnapshotModule(m, inProprietaryPath, apexInfo, c.image) {
return return
} }
@@ -894,11 +1120,17 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont
return snapshotOutputs[i].String() < snapshotOutputs[j].String() 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() zipRule := android.NewRuleBuilder()
// filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr // 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(). zipRule.Command().
Text("tr"). Text("tr").
FlagWithArg("-d ", "\\'"). FlagWithArg("-d ", "\\'").
@@ -913,13 +1145,15 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont
FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()). FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
FlagWithInput("-l ", snapshotOutputList) 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() zipRule.DeleteTemporaryFiles()
c.vendorSnapshotZipFile = android.OptionalPathForPath(zipPath) c.snapshotZipFile = android.OptionalPathForPath(zipPath)
} }
func (c *vendorSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) { func (c *snapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict("SOONG_VENDOR_SNAPSHOT_ZIP", c.vendorSnapshotZipFile.String()) ctx.Strict(
c.makeVar,
c.snapshotZipFile.String())
} }
type snapshotInterface interface { type snapshotInterface interface {
@@ -927,9 +1161,9 @@ type snapshotInterface interface {
} }
var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil) var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil) var _ snapshotInterface = (*snapshotLibraryDecorator)(nil)
var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil) var _ snapshotInterface = (*snapshotBinaryDecorator)(nil)
var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil) var _ snapshotInterface = (*snapshotObjectLinker)(nil)
// gathers all snapshot modules for vendor, and disable unnecessary snapshots // gathers all snapshot modules for vendor, and disable unnecessary snapshots
// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules // TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
@@ -970,9 +1204,9 @@ func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) {
// header // header
snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
} }
} else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok { } else if _, ok := module.linker.(*snapshotBinaryDecorator); ok {
snapshotMap = vendorSnapshotBinaries(ctx.Config()) snapshotMap = vendorSnapshotBinaries(ctx.Config())
} else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok { } else if _, ok := module.linker.(*snapshotObjectLinker); ok {
snapshotMap = vendorSnapshotObjects(ctx.Config()) snapshotMap = vendorSnapshotObjects(ctx.Config())
} else { } else {
return return