Support for recovery snapshot.

Bug: 171231437
Test: source build/envsetup.sh
Test: ALLOW_MISSING_DEPENDENCIES=true m -j nothing

Change-Id: I6b35fbb0b90ffffa941ea108cbd31a454b2dd403
This commit is contained in:
Jose Galmes 2020-11-13 12:07:36 -08:00
parent 9414a8be12
commit f729458e69
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
// 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 {

View File

@ -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":

View File

@ -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", `

View File

@ -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
}

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 {
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

View File

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

View File

@ -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