From de5744a199cc28269ff0ad54bb20b7feab59ce71 Mon Sep 17 00:00:00 2001 From: Inseob Kim Date: Wed, 2 Dec 2020 13:14:28 +0900 Subject: [PATCH] Add some comments for VNDK / vendor snapshots Also some files are refactored: - snapshot_prebuilt.go is separated from vendor_snapshot.go. Now vendor_snapshot.go contains snapshot generation codes, while snapshot_prebuilt.go contains module definition codes. - Some helper functions are moved from snapshot_utils.go to util.go. - Some ambiguous names of types and functions are renamed. We still can add more detailed comments about the snapshots. They are to be uploaded in follow-up changes, to avoid making this change too big. Bug: 173474311 Test: generate vndk and vendor snapshot Change-Id: I18fa837ccdf44a042b7a78e5c3df25fd2de96d95 --- cc/Android.bp | 1 + cc/cc.go | 2 +- cc/snapshot_prebuilt.go | 844 +++++++++++++++++++++++++++++++++++++++ cc/snapshot_utils.go | 52 +-- cc/util.go | 49 +++ cc/vendor_snapshot.go | 850 +++------------------------------------- cc/vndk.go | 53 ++- 7 files changed, 997 insertions(+), 854 deletions(-) create mode 100644 cc/snapshot_prebuilt.go diff --git a/cc/Android.bp b/cc/Android.bp index 88104e295..33f3db22a 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -31,6 +31,7 @@ bootstrap_go_package { "sanitize.go", "sabi.go", "sdk.go", + "snapshot_prebuilt.go", "snapshot_utils.go", "stl.go", "strip.go", diff --git a/cc/cc.go b/cc/cc.go index 986bf2ba3..7baaa66b5 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -1595,7 +1595,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { // glob exported headers for snapshot, if BOARD_VNDK_VERSION is current. if i, ok := c.linker.(snapshotLibraryInterface); ok && ctx.DeviceConfig().VndkVersion() == "current" { - if isSnapshotAware(ctx, c, apexInfo) { + if shouldCollectHeadersForSnapshot(ctx, c, apexInfo) { i.collectHeadersForSnapshot(ctx) } } diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go new file mode 100644 index 000000000..b291bd0d3 --- /dev/null +++ b/cc/snapshot_prebuilt.go @@ -0,0 +1,844 @@ +// Copyright 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package cc + +// This file defines snapshot prebuilt modules, e.g. vendor snapshot and recovery snapshot. Such +// snapshot modules will override original source modules with setting BOARD_VNDK_VERSION, with +// snapshot mutators and snapshot information maps which are also defined in this file. + +import ( + "strings" + "sync" + + "android/soong/android" +) + +// Defines the specifics of different images to which the snapshot process is applicable, e.g., +// vendor, recovery, ramdisk. +type snapshotImage 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 vendorSnapshotImage struct{} +type recoverySnapshotImage struct{} + +func (vendorSnapshotImage) 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 (vendorSnapshotImage) inImage(m *Module) func() bool { + return m.inVendor +} + +func (vendorSnapshotImage) available(m *Module) *bool { + return m.VendorProperties.Vendor_available +} + +func (vendorSnapshotImage) isProprietaryPath(dir string) bool { + return isVendorProprietaryPath(dir) +} + +// vendor snapshot includes static/header libraries with vndk: {enabled: true}. +func (vendorSnapshotImage) includeVndk() bool { + return true +} + +func (vendorSnapshotImage) excludeFromSnapshot(m *Module) bool { + return m.ExcludeFromVendorSnapshot() +} + +func (recoverySnapshotImage) 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 (recoverySnapshotImage) inImage(m *Module) func() bool { + return m.InRecovery +} + +func (recoverySnapshotImage) available(m *Module) *bool { + return m.Properties.Recovery_available +} + +func (recoverySnapshotImage) isProprietaryPath(dir string) bool { + return isRecoveryProprietaryPath(dir) +} + +// recovery snapshot does NOT treat vndk specially. +func (recoverySnapshotImage) includeVndk() bool { + return false +} + +func (recoverySnapshotImage) excludeFromSnapshot(m *Module) bool { + return m.ExcludeFromRecoverySnapshot() +} + +var vendorSnapshotImageSingleton vendorSnapshotImage +var recoverySnapshotImageSingleton recoverySnapshotImage + +func init() { + vendorSnapshotImageSingleton.init() + recoverySnapshotImageSingleton.init() +} + +const ( + vendorSnapshotHeaderSuffix = ".vendor_header." + vendorSnapshotSharedSuffix = ".vendor_shared." + vendorSnapshotStaticSuffix = ".vendor_static." + vendorSnapshotBinarySuffix = ".vendor_binary." + 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") + vendorSnapshotHeaderLibsKey = android.NewOnceKey("vendorSnapshotHeaderLibs") + vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs") + vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs") + vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries") + vendorSnapshotObjectsKey = android.NewOnceKey("vendorSnapshotObjects") +) + +// vendorSuffixModules holds names of modules whose vendor variants should have the vendor suffix. +// This is determined by source modules, and then this will be used when exporting snapshot modules +// to Makefile. +// +// For example, if libbase has "vendor_available: true", the name of core variant will be "libbase" +// while the name of vendor variant will be "libbase.vendor". In such cases, the vendor snapshot of +// "libbase" should be exported with the name "libbase.vendor". +// +// Refer to VendorSnapshotSourceMutator and makeLibName which use this. +func vendorSuffixModules(config android.Config) map[string]bool { + return config.Once(vendorSuffixModulesKey, func() interface{} { + return make(map[string]bool) + }).(map[string]bool) +} + +// these are vendor snapshot maps holding names of vendor snapshot modules +func vendorSnapshotHeaderLibs(config android.Config) *snapshotMap { + return config.Once(vendorSnapshotHeaderLibsKey, func() interface{} { + return newSnapshotMap() + }).(*snapshotMap) +} + +func vendorSnapshotSharedLibs(config android.Config) *snapshotMap { + return config.Once(vendorSnapshotSharedLibsKey, func() interface{} { + return newSnapshotMap() + }).(*snapshotMap) +} + +func vendorSnapshotStaticLibs(config android.Config) *snapshotMap { + return config.Once(vendorSnapshotStaticLibsKey, func() interface{} { + return newSnapshotMap() + }).(*snapshotMap) +} + +func vendorSnapshotBinaries(config android.Config) *snapshotMap { + return config.Once(vendorSnapshotBinariesKey, func() interface{} { + return newSnapshotMap() + }).(*snapshotMap) +} + +func vendorSnapshotObjects(config android.Config) *snapshotMap { + return config.Once(vendorSnapshotObjectsKey, func() interface{} { + return newSnapshotMap() + }).(*snapshotMap) +} + +type baseSnapshotDecoratorProperties struct { + // snapshot version. + Version string + + // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64') + Target_arch string +} + +// baseSnapshotDecorator provides common basic functions for all snapshot modules, such as snapshot +// version, snapshot arch, etc. It also adds a special suffix to Soong module name, so it doesn't +// collide with source modules. e.g. the following example module, +// +// vendor_snapshot_static { +// name: "libbase", +// arch: "arm64", +// version: 30, +// ... +// } +// +// will be seen as "libbase.vendor_static.30.arm64" by Soong. +type baseSnapshotDecorator struct { + baseProperties baseSnapshotDecoratorProperties + moduleSuffix string +} + +func (p *baseSnapshotDecorator) Name(name string) string { + return name + p.NameSuffix() +} + +func (p *baseSnapshotDecorator) NameSuffix() string { + versionSuffix := p.version() + if p.arch() != "" { + versionSuffix += "." + p.arch() + } + + return p.moduleSuffix + versionSuffix +} + +func (p *baseSnapshotDecorator) version() string { + return p.baseProperties.Version +} + +func (p *baseSnapshotDecorator) arch() string { + return p.baseProperties.Target_arch +} + +func (p *baseSnapshotDecorator) isSnapshotPrebuilt() bool { + return true +} + +// Call this with a module suffix after creating a snapshot module, such as +// vendorSnapshotSharedSuffix, recoverySnapshotBinarySuffix, etc. +func (p *baseSnapshotDecorator) init(m *Module, suffix string) { + p.moduleSuffix = suffix + m.AddProperties(&p.baseProperties) + android.AddLoadHook(m, func(ctx android.LoadHookContext) { + vendorSnapshotLoadHook(ctx, p) + }) +} + +// vendorSnapshotLoadHook disables snapshots if it's not BOARD_VNDK_VERSION. +// As vendor snapshot is only for vendor, such modules won't be used at all. +func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *baseSnapshotDecorator) { + if p.version() != ctx.DeviceConfig().VndkVersion() { + ctx.Module().Disable() + return + } +} + +// +// Module definitions for snapshots of libraries (shared, static, header). +// +// Modules (vendor|recovery)_snapshot_(shared|static|header) are defined here. Shared libraries and +// static libraries have their prebuilt library files (.so for shared, .a for static) as their src, +// which can be installed or linked against. Also they export flags needed when linked, such as +// include directories, c flags, sanitize dependency information, etc. +// +// These modules are auto-generated by development/vendor_snapshot/update.py. +type snapshotLibraryProperties struct { + // Prebuilt file for each arch. + Src *string `android:"arch_variant"` + + // list of directories that will be added to the include path (using -I). + Export_include_dirs []string `android:"arch_variant"` + + // list of directories that will be added to the system path (using -isystem). + Export_system_include_dirs []string `android:"arch_variant"` + + // list of flags that will be used for any module that links against this module. + Export_flags []string `android:"arch_variant"` + + // Whether this prebuilt needs to depend on sanitize ubsan runtime or not. + Sanitize_ubsan_dep *bool `android:"arch_variant"` + + // Whether this prebuilt needs to depend on sanitize minimal runtime or not. + Sanitize_minimal_dep *bool `android:"arch_variant"` +} + +type snapshotSanitizer interface { + isSanitizerEnabled(t sanitizerType) bool + setSanitizerVariation(t sanitizerType, enabled bool) +} + +type snapshotLibraryDecorator struct { + baseSnapshotDecorator + *libraryDecorator + properties snapshotLibraryProperties + sanitizerProperties struct { + CfiEnabled bool `blueprint:"mutated"` + + // Library flags for cfi variant. + Cfi snapshotLibraryProperties `android:"arch_variant"` + } + androidMkVendorSuffix bool +} + +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 *snapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool { + arches := config.Arches() + if len(arches) == 0 || arches[0].ArchType.String() != p.arch() { + return false + } + if !p.header() && p.properties.Src == nil { + return false + } + return true +} + +// cc modules' link functions are to link compiled objects into final binaries. +// As snapshots are prebuilts, this just returns the prebuilt binary after doing things which are +// done by normal library decorator, e.g. exporting flags. +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()] + + if p.header() { + return p.libraryDecorator.link(ctx, flags, deps, objs) + } + + if p.sanitizerProperties.CfiEnabled { + p.properties = p.sanitizerProperties.Cfi + } + + if !p.matchesWithDevice(ctx.DeviceConfig()) { + return nil + } + + p.libraryDecorator.reexportDirs(android.PathsForModuleSrc(ctx, p.properties.Export_include_dirs)...) + p.libraryDecorator.reexportSystemDirs(android.PathsForModuleSrc(ctx, p.properties.Export_system_include_dirs)...) + p.libraryDecorator.reexportFlags(p.properties.Export_flags...) + + in := android.PathForModuleSrc(ctx, *p.properties.Src) + p.unstrippedOutputFile = in + + if p.shared() { + libName := in.Base() + builderFlags := flagsToBuilderFlags(flags) + + // Optimize out relinking against shared libraries whose interface hasn't changed by + // depending on a table of contents file instead of the library itself. + tocFile := android.PathForModuleOut(ctx, libName+".toc") + p.tocFile = android.OptionalPathForPath(tocFile) + transformSharedObjectToToc(ctx, in, tocFile, builderFlags) + + ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{ + SharedLibrary: in, + UnstrippedSharedLibrary: p.unstrippedOutputFile, + + TableOfContents: p.tocFile, + }) + } + + if p.static() { + depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(in).Build() + ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{ + StaticLibrary: in, + + TransitiveStaticLibrariesForOrdering: depSet, + }) + } + + p.libraryDecorator.flagExporter.setProvider(ctx) + + return in +} + +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 *snapshotLibraryDecorator) nativeCoverage() bool { + return false +} + +func (p *snapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool { + switch t { + case cfi: + return p.sanitizerProperties.Cfi.Src != nil + default: + return false + } +} + +func (p *snapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) { + if !enabled { + return + } + switch t { + case cfi: + p.sanitizerProperties.CfiEnabled = true + default: + return + } +} + +func snapshotLibraryFactory(suffix string) (*Module, *snapshotLibraryDecorator) { + module, library := NewLibrary(android.DeviceSupported) + + module.stl = nil + module.sanitize = nil + library.disableStripping() + + prebuilt := &snapshotLibraryDecorator{ + libraryDecorator: library, + } + + prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true) + prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true) + + // Prevent default system libs (libc, libm, and libdl) from being linked + if prebuilt.baseLinker.Properties.System_shared_libs == nil { + prebuilt.baseLinker.Properties.System_shared_libs = []string{} + } + + module.compiler = nil + module.linker = prebuilt + module.installer = prebuilt + + prebuilt.init(module, suffix) + module.AddProperties( + &prebuilt.properties, + &prebuilt.sanitizerProperties, + ) + + return module, prebuilt +} + +// vendor_snapshot_shared is a special prebuilt shared library which is auto-generated by +// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_shared +// overrides the vendor variant of the cc shared library with the same name, if BOARD_VNDK_VERSION +// is set. +func VendorSnapshotSharedFactory() android.Module { + module, prebuilt := snapshotLibraryFactory(vendorSnapshotSharedSuffix) + prebuilt.libraryDecorator.BuildOnlyShared() + return module.Init() +} + +// recovery_snapshot_shared is a special prebuilt shared library which is auto-generated by +// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_shared +// overrides the recovery variant of the cc shared library with the same name, if BOARD_VNDK_VERSION +// is set. +func RecoverySnapshotSharedFactory() android.Module { + module, prebuilt := snapshotLibraryFactory(recoverySnapshotSharedSuffix) + prebuilt.libraryDecorator.BuildOnlyShared() + return module.Init() +} + +// vendor_snapshot_static is a special prebuilt static library which is auto-generated by +// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_static +// overrides the vendor variant of the cc static library with the same name, if BOARD_VNDK_VERSION +// is set. +func VendorSnapshotStaticFactory() android.Module { + module, prebuilt := snapshotLibraryFactory(vendorSnapshotStaticSuffix) + prebuilt.libraryDecorator.BuildOnlyStatic() + return module.Init() +} + +// recovery_snapshot_static is a special prebuilt static library which is auto-generated by +// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_static +// overrides the recovery variant of the cc static library with the same name, if BOARD_VNDK_VERSION +// is set. +func RecoverySnapshotStaticFactory() android.Module { + module, prebuilt := snapshotLibraryFactory(recoverySnapshotStaticSuffix) + prebuilt.libraryDecorator.BuildOnlyStatic() + return module.Init() +} + +// vendor_snapshot_header is a special header library which is auto-generated by +// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_header +// overrides the vendor variant of the cc header library with the same name, if BOARD_VNDK_VERSION +// is set. +func VendorSnapshotHeaderFactory() android.Module { + module, prebuilt := snapshotLibraryFactory(vendorSnapshotHeaderSuffix) + prebuilt.libraryDecorator.HeaderOnly() + return module.Init() +} + +// recovery_snapshot_header is a special header library which is auto-generated by +// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_header +// overrides the recovery variant of the cc header library with the same name, if BOARD_VNDK_VERSION +// is set. +func RecoverySnapshotHeaderFactory() android.Module { + module, prebuilt := snapshotLibraryFactory(recoverySnapshotHeaderSuffix) + prebuilt.libraryDecorator.HeaderOnly() + return module.Init() +} + +var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil) + +// +// Module definitions for snapshots of executable binaries. +// +// Modules (vendor|recovery)_snapshot_binary are defined here. They have their prebuilt executable +// binaries (e.g. toybox, sh) as their src, which can be installed. +// +// These modules are auto-generated by development/vendor_snapshot/update.py. +type snapshotBinaryProperties struct { + // Prebuilt file for each arch. + Src *string `android:"arch_variant"` +} + +type snapshotBinaryDecorator struct { + baseSnapshotDecorator + *binaryDecorator + properties snapshotBinaryProperties + androidMkVendorSuffix bool +} + +func (p *snapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool { + if config.DeviceArch() != p.arch() { + return false + } + if p.properties.Src == nil { + return false + } + return true +} + +// cc modules' link functions are to link compiled objects into final binaries. +// As snapshots are prebuilts, this just returns the prebuilt binary +func (p *snapshotBinaryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { + if !p.matchesWithDevice(ctx.DeviceConfig()) { + return nil + } + + in := android.PathForModuleSrc(ctx, *p.properties.Src) + p.unstrippedOutputFile = in + binName := in.Base() + + m := ctx.Module().(*Module) + p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()] + + // use cpExecutable to make it executable + outputFile := android.PathForModuleOut(ctx, binName) + ctx.Build(pctx, android.BuildParams{ + Rule: android.CpExecutable, + Description: "prebuilt", + Output: outputFile, + Input: in, + }) + + return outputFile +} + +func (p *snapshotBinaryDecorator) nativeCoverage() bool { + return false +} + +// vendor_snapshot_binary is a special prebuilt executable binary which is auto-generated by +// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_binary +// overrides the vendor variant of the cc binary with the same name, if BOARD_VNDK_VERSION is set. +func VendorSnapshotBinaryFactory() android.Module { + return snapshotBinaryFactory(vendorSnapshotBinarySuffix) +} + +// recovery_snapshot_binary is a special prebuilt executable binary which is auto-generated by +// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_binary +// overrides the recovery variant of the cc binary with the same name, if BOARD_VNDK_VERSION is set. +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) + + // Prevent default system libs (libc, libm, and libdl) from being linked + if binary.baseLinker.Properties.System_shared_libs == nil { + binary.baseLinker.Properties.System_shared_libs = []string{} + } + + prebuilt := &snapshotBinaryDecorator{ + binaryDecorator: binary, + } + + module.compiler = nil + module.sanitize = nil + module.stl = nil + module.linker = prebuilt + + prebuilt.init(module, suffix) + module.AddProperties(&prebuilt.properties) + return module.Init() +} + +// +// Module definitions for snapshots of object files (*.o). +// +// Modules (vendor|recovery)_snapshot_object are defined here. They have their prebuilt object +// files (*.o) as their src. +// +// These modules are auto-generated by development/vendor_snapshot/update.py. +type vendorSnapshotObjectProperties struct { + // Prebuilt file for each arch. + Src *string `android:"arch_variant"` +} + +type snapshotObjectLinker struct { + baseSnapshotDecorator + objectLinker + properties vendorSnapshotObjectProperties + androidMkVendorSuffix bool +} + +func (p *snapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool { + if config.DeviceArch() != p.arch() { + return false + } + if p.properties.Src == nil { + return false + } + return true +} + +// cc modules' link functions are to link compiled objects into final binaries. +// As snapshots are prebuilts, this just returns the prebuilt binary +func (p *snapshotObjectLinker) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { + if !p.matchesWithDevice(ctx.DeviceConfig()) { + return nil + } + + m := ctx.Module().(*Module) + p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()] + + return android.PathForModuleSrc(ctx, *p.properties.Src) +} + +func (p *snapshotObjectLinker) nativeCoverage() bool { + return false +} + +// vendor_snapshot_object is a special prebuilt compiled object file which is auto-generated by +// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_object +// overrides the vendor variant of the cc object with the same name, if BOARD_VNDK_VERSION is set. +func VendorSnapshotObjectFactory() android.Module { + module := newObject() + + prebuilt := &snapshotObjectLinker{ + objectLinker: objectLinker{ + baseLinker: NewBaseLinker(nil), + }, + } + module.linker = prebuilt + + prebuilt.init(module, vendorSnapshotObjectSuffix) + module.AddProperties(&prebuilt.properties) + return module.Init() +} + +// recovery_snapshot_object is a special prebuilt compiled object file which is auto-generated by +// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_object +// overrides the recovery variant of the cc object with the same name, if BOARD_VNDK_VERSION is set. +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() +} + +type snapshotInterface interface { + matchesWithDevice(config android.DeviceConfig) bool +} + +var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil) +var _ snapshotInterface = (*snapshotLibraryDecorator)(nil) +var _ snapshotInterface = (*snapshotBinaryDecorator)(nil) +var _ snapshotInterface = (*snapshotObjectLinker)(nil) + +// +// Mutators that helps vendor snapshot modules override source modules. +// + +// VendorSnapshotMutator gathers all snapshots for vendor, and disable all snapshots which don't +// match with device, e.g. +// - snapshot version is different with BOARD_VNDK_VERSION +// - snapshot arch is different with device's arch (e.g. arm vs x86) +// +// This also handles vndk_prebuilt_shared, except for they won't be disabled in any cases, given +// that any versions of VNDK might be packed into vndk APEX. +// +// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules +func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) { + vndkVersion := ctx.DeviceConfig().VndkVersion() + // don't need snapshot if current + if vndkVersion == "current" || vndkVersion == "" { + return + } + + module, ok := ctx.Module().(*Module) + if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion { + return + } + + if !module.isSnapshotPrebuilt() { + return + } + + // isSnapshotPrebuilt ensures snapshotInterface + if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) { + // Disable unnecessary snapshot module, but do not disable + // vndk_prebuilt_shared because they might be packed into vndk APEX + if !module.IsVndk() { + module.Disable() + } + return + } + + var snapshotMap *snapshotMap + + if lib, ok := module.linker.(libraryInterface); ok { + if lib.static() { + snapshotMap = vendorSnapshotStaticLibs(ctx.Config()) + } else if lib.shared() { + snapshotMap = vendorSnapshotSharedLibs(ctx.Config()) + } else { + // header + snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) + } + } else if _, ok := module.linker.(*snapshotBinaryDecorator); ok { + snapshotMap = vendorSnapshotBinaries(ctx.Config()) + } else if _, ok := module.linker.(*snapshotObjectLinker); ok { + snapshotMap = vendorSnapshotObjects(ctx.Config()) + } else { + return + } + + vendorSnapshotsLock.Lock() + defer vendorSnapshotsLock.Unlock() + snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName()) +} + +// VendorSnapshotSourceMutator disables source modules which have corresponding snapshots. +func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) { + if !ctx.Device() { + return + } + + vndkVersion := ctx.DeviceConfig().VndkVersion() + // don't need snapshot if current + if vndkVersion == "current" || vndkVersion == "" { + return + } + + module, ok := ctx.Module().(*Module) + if !ok { + return + } + + // vendor suffix should be added to snapshots if the source module isn't vendor: true. + if !module.SocSpecific() { + // But we can't just check SocSpecific() since we already passed the image mutator. + // Check ramdisk and recovery to see if we are real "vendor: true" module. + ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk() + vendor_ramdisk_available := module.InVendorRamdisk() && !module.OnlyInVendorRamdisk() + recovery_available := module.InRecovery() && !module.OnlyInRecovery() + + if !ramdisk_available && !recovery_available && !vendor_ramdisk_available { + vendorSnapshotsLock.Lock() + defer vendorSnapshotsLock.Unlock() + + vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true + } + } + + if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() { + // only non-snapshot modules with BOARD_VNDK_VERSION + return + } + + // .. and also filter out llndk library + if module.isLlndk(ctx.Config()) { + return + } + + var snapshotMap *snapshotMap + + if lib, ok := module.linker.(libraryInterface); ok { + if lib.static() { + snapshotMap = vendorSnapshotStaticLibs(ctx.Config()) + } else if lib.shared() { + snapshotMap = vendorSnapshotSharedLibs(ctx.Config()) + } else { + // header + snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) + } + } else if module.binary() { + snapshotMap = vendorSnapshotBinaries(ctx.Config()) + } else if module.object() { + snapshotMap = vendorSnapshotObjects(ctx.Config()) + } else { + return + } + + if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok { + // Corresponding snapshot doesn't exist + return + } + + // Disables source modules if corresponding snapshot exists. + if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() { + // But do not disable because the shared variant depends on the static variant. + module.SkipInstall() + module.Properties.HideFromMake = true + } else { + module.Disable() + } +} diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go index a3d52e621..e841a547b 100644 --- a/cc/snapshot_utils.go +++ b/cc/snapshot_utils.go @@ -13,6 +13,8 @@ // limitations under the License. package cc +// This file contains utility types and functions for VNDK / vendor snapshot. + import ( "android/soong/android" ) @@ -21,15 +23,24 @@ var ( headerExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"} ) +// snapshotLibraryInterface is an interface for libraries captured to VNDK / vendor snapshots. type snapshotLibraryInterface interface { libraryInterface + + // collectHeadersForSnapshot is called in GenerateAndroidBuildActions for snapshot aware + // modules (See isSnapshotAware below). + // This function should gather all headers needed for snapshot. collectHeadersForSnapshot(ctx android.ModuleContext) + + // snapshotHeaders should return collected headers by collectHeadersForSnapshot. + // Calling snapshotHeaders before collectHeadersForSnapshot is an error. snapshotHeaders() android.Paths } var _ snapshotLibraryInterface = (*prebuiltLibraryLinker)(nil) var _ snapshotLibraryInterface = (*libraryDecorator)(nil) +// snapshotMap is a helper wrapper to a map from base module name to snapshot module name. type snapshotMap struct { snapshots map[string]string } @@ -57,43 +68,14 @@ func (s *snapshotMap) get(name string, arch android.ArchType) (snapshot string, return snapshot, found } -func isSnapshotAware(ctx android.ModuleContext, m *Module, apexInfo android.ApexInfo) bool { - if _, _, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m, apexInfo); ok { +// shouldCollectHeadersForSnapshot determines if the module is a possible candidate for snapshot. +// If it's true, collectHeadersForSnapshot will be called in GenerateAndroidBuildActions. +func shouldCollectHeadersForSnapshot(ctx android.ModuleContext, m *Module, apexInfo android.ApexInfo) bool { + if _, _, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo); ok { return ctx.Config().VndkSnapshotBuildArtifacts() - } else if isVendorSnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) || - isRecoverySnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) { + } else if isVendorSnapshotAware(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) || + isRecoverySnapshotAware(m, isRecoveryProprietaryPath(ctx.ModuleDir()), apexInfo) { return true } return false } - -func copyFile(ctx android.SingletonContext, path android.Path, out string) android.OutputPath { - outPath := android.PathForOutput(ctx, out) - ctx.Build(pctx, android.BuildParams{ - Rule: android.Cp, - Input: path, - Output: outPath, - Description: "Cp " + out, - Args: map[string]string{ - "cpFlags": "-f -L", - }, - }) - return outPath -} - -func combineNotices(ctx android.SingletonContext, paths android.Paths, out string) android.OutputPath { - outPath := android.PathForOutput(ctx, out) - ctx.Build(pctx, android.BuildParams{ - Rule: android.Cat, - Inputs: paths, - Output: outPath, - Description: "combine notices for " + out, - }) - return outPath -} - -func writeStringToFile(ctx android.SingletonContext, content, out string) android.OutputPath { - outPath := android.PathForOutput(ctx, out) - android.WriteFileRule(ctx, outPath, content) - return outPath -} diff --git a/cc/util.go b/cc/util.go index 40374bff7..1220d8432 100644 --- a/cc/util.go +++ b/cc/util.go @@ -125,3 +125,52 @@ func makeSymlinkCmd(linkDirOnDevice string, linkName string, target string) stri return "mkdir -p " + dir + " && " + "ln -sf " + target + " " + filepath.Join(dir, linkName) } + +func copyFileRule(ctx android.SingletonContext, path android.Path, out string) android.OutputPath { + outPath := android.PathForOutput(ctx, out) + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: path, + Output: outPath, + Description: "copy " + path.String() + " -> " + out, + Args: map[string]string{ + "cpFlags": "-f -L", + }, + }) + return outPath +} + +func combineNoticesRule(ctx android.SingletonContext, paths android.Paths, out string) android.OutputPath { + outPath := android.PathForOutput(ctx, out) + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cat, + Inputs: paths, + Output: outPath, + Description: "combine notices for " + out, + }) + return outPath +} + +func writeStringToFileRule(ctx android.SingletonContext, content, out string) android.OutputPath { + outPath := android.PathForOutput(ctx, out) + android.WriteFileRule(ctx, outPath, content) + return outPath +} + +// Dump a map to a list file as: +// +// {key1} {value1} +// {key2} {value2} +// ... +func installMapListFileRule(ctx android.SingletonContext, m map[string]string, path string) android.OutputPath { + var txtBuilder strings.Builder + for idx, k := range android.SortedStringKeys(m) { + if idx > 0 { + txtBuilder.WriteString("\n") + } + txtBuilder.WriteString(k) + txtBuilder.WriteString(" ") + txtBuilder.WriteString(m[k]) + } + return writeStringToFileRule(ctx, txtBuilder.String(), path) +} diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 3ef0b62b8..25960ab96 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -13,625 +13,27 @@ // limitations under the License. package cc +// This file contains singletons to capture vendor and recovery snapshot. They consist of prebuilt +// modules under AOSP so older vendor and recovery can be built with a newer system in a single +// source tree. + import ( "encoding/json" "path/filepath" "sort" "strings" - "sync" "github.com/google/blueprint/proptools" "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." - vendorSnapshotStaticSuffix = ".vendor_static." - vendorSnapshotBinarySuffix = ".vendor_binary." - 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") - vendorSnapshotHeaderLibsKey = android.NewOnceKey("vendorSnapshotHeaderLibs") - vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs") - vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs") - vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries") - vendorSnapshotObjectsKey = android.NewOnceKey("vendorSnapshotObjects") -) - -// vendor snapshot maps hold names of vendor snapshot modules per arch -func vendorSuffixModules(config android.Config) map[string]bool { - return config.Once(vendorSuffixModulesKey, func() interface{} { - return make(map[string]bool) - }).(map[string]bool) -} - -func vendorSnapshotHeaderLibs(config android.Config) *snapshotMap { - return config.Once(vendorSnapshotHeaderLibsKey, func() interface{} { - return newSnapshotMap() - }).(*snapshotMap) -} - -func vendorSnapshotSharedLibs(config android.Config) *snapshotMap { - return config.Once(vendorSnapshotSharedLibsKey, func() interface{} { - return newSnapshotMap() - }).(*snapshotMap) -} - -func vendorSnapshotStaticLibs(config android.Config) *snapshotMap { - return config.Once(vendorSnapshotStaticLibsKey, func() interface{} { - return newSnapshotMap() - }).(*snapshotMap) -} - -func vendorSnapshotBinaries(config android.Config) *snapshotMap { - return config.Once(vendorSnapshotBinariesKey, func() interface{} { - return newSnapshotMap() - }).(*snapshotMap) -} - -func vendorSnapshotObjects(config android.Config) *snapshotMap { - return config.Once(vendorSnapshotObjectsKey, func() interface{} { - return newSnapshotMap() - }).(*snapshotMap) -} - -type vendorSnapshotBaseProperties struct { - // snapshot version. - Version string - - // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64') - Target_arch string -} - -// vendorSnapshotModuleBase provides common basic functions for all snapshot modules. -type vendorSnapshotModuleBase struct { - baseProperties vendorSnapshotBaseProperties - moduleSuffix string -} - -func (p *vendorSnapshotModuleBase) Name(name string) string { - return name + p.NameSuffix() -} - -func (p *vendorSnapshotModuleBase) NameSuffix() string { - versionSuffix := p.version() - if p.arch() != "" { - versionSuffix += "." + p.arch() - } - - return p.moduleSuffix + versionSuffix -} - -func (p *vendorSnapshotModuleBase) version() string { - return p.baseProperties.Version -} - -func (p *vendorSnapshotModuleBase) arch() string { - return p.baseProperties.Target_arch -} - -func (p *vendorSnapshotModuleBase) isSnapshotPrebuilt() bool { - return true -} - -// Call this after creating a snapshot module with module suffix -// such as vendorSnapshotSharedSuffix -func (p *vendorSnapshotModuleBase) init(m *Module, suffix string) { - p.moduleSuffix = suffix - m.AddProperties(&p.baseProperties) - android.AddLoadHook(m, func(ctx android.LoadHookContext) { - vendorSnapshotLoadHook(ctx, p) - }) -} - -func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *vendorSnapshotModuleBase) { - if p.version() != ctx.DeviceConfig().VndkVersion() { - ctx.Module().Disable() - return - } -} - -type snapshotLibraryProperties struct { - // Prebuilt file for each arch. - Src *string `android:"arch_variant"` - - // list of directories that will be added to the include path (using -I). - Export_include_dirs []string `android:"arch_variant"` - - // list of directories that will be added to the system path (using -isystem). - Export_system_include_dirs []string `android:"arch_variant"` - - // list of flags that will be used for any module that links against this module. - Export_flags []string `android:"arch_variant"` - - // Whether this prebuilt needs to depend on sanitize ubsan runtime or not. - Sanitize_ubsan_dep *bool `android:"arch_variant"` - - // Whether this prebuilt needs to depend on sanitize minimal runtime or not. - Sanitize_minimal_dep *bool `android:"arch_variant"` -} - -type snapshotSanitizer interface { - isSanitizerEnabled(t sanitizerType) bool - setSanitizerVariation(t sanitizerType, enabled bool) -} - -type snapshotLibraryDecorator struct { - vendorSnapshotModuleBase - *libraryDecorator - properties snapshotLibraryProperties - sanitizerProperties struct { - CfiEnabled bool `blueprint:"mutated"` - - // Library flags for cfi variant. - Cfi snapshotLibraryProperties `android:"arch_variant"` - } - androidMkVendorSuffix bool -} - -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 *snapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool { - arches := config.Arches() - if len(arches) == 0 || arches[0].ArchType.String() != p.arch() { - return false - } - if !p.header() && p.properties.Src == nil { - return false - } - return true -} - -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()] - - if p.header() { - return p.libraryDecorator.link(ctx, flags, deps, objs) - } - - if p.sanitizerProperties.CfiEnabled { - p.properties = p.sanitizerProperties.Cfi - } - - if !p.matchesWithDevice(ctx.DeviceConfig()) { - return nil - } - - p.libraryDecorator.reexportDirs(android.PathsForModuleSrc(ctx, p.properties.Export_include_dirs)...) - p.libraryDecorator.reexportSystemDirs(android.PathsForModuleSrc(ctx, p.properties.Export_system_include_dirs)...) - p.libraryDecorator.reexportFlags(p.properties.Export_flags...) - - in := android.PathForModuleSrc(ctx, *p.properties.Src) - p.unstrippedOutputFile = in - - if p.shared() { - libName := in.Base() - builderFlags := flagsToBuilderFlags(flags) - - // Optimize out relinking against shared libraries whose interface hasn't changed by - // depending on a table of contents file instead of the library itself. - tocFile := android.PathForModuleOut(ctx, libName+".toc") - p.tocFile = android.OptionalPathForPath(tocFile) - transformSharedObjectToToc(ctx, in, tocFile, builderFlags) - - ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{ - SharedLibrary: in, - UnstrippedSharedLibrary: p.unstrippedOutputFile, - - TableOfContents: p.tocFile, - }) - } - - if p.static() { - depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(in).Build() - ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{ - StaticLibrary: in, - - TransitiveStaticLibrariesForOrdering: depSet, - }) - } - - p.libraryDecorator.flagExporter.setProvider(ctx) - - return in -} - -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 *snapshotLibraryDecorator) nativeCoverage() bool { - return false -} - -func (p *snapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool { - switch t { - case cfi: - return p.sanitizerProperties.Cfi.Src != nil - default: - return false - } -} - -func (p *snapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) { - if !enabled { - return - } - switch t { - case cfi: - p.sanitizerProperties.CfiEnabled = true - default: - return - } -} - -func snapshotLibrary(suffix string) (*Module, *snapshotLibraryDecorator) { - module, library := NewLibrary(android.DeviceSupported) - - module.stl = nil - module.sanitize = nil - library.disableStripping() - - prebuilt := &snapshotLibraryDecorator{ - libraryDecorator: library, - } - - prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true) - prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true) - - // Prevent default system libs (libc, libm, and libdl) from being linked - if prebuilt.baseLinker.Properties.System_shared_libs == nil { - prebuilt.baseLinker.Properties.System_shared_libs = []string{} - } - - module.compiler = nil - module.linker = prebuilt - module.installer = prebuilt - - prebuilt.init(module, suffix) - module.AddProperties( - &prebuilt.properties, - &prebuilt.sanitizerProperties, - ) - - return module, prebuilt -} - -func VendorSnapshotSharedFactory() android.Module { - 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 := 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 := snapshotLibrary(vendorSnapshotHeaderSuffix) - prebuilt.libraryDecorator.HeaderOnly() - return module.Init() -} - -func RecoverySnapshotHeaderFactory() android.Module { - module, prebuilt := snapshotLibrary(recoverySnapshotHeaderSuffix) - prebuilt.libraryDecorator.HeaderOnly() - return module.Init() -} - -var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil) - -type snapshotBinaryProperties struct { - // Prebuilt file for each arch. - Src *string `android:"arch_variant"` -} - -type snapshotBinaryDecorator struct { - vendorSnapshotModuleBase - *binaryDecorator - properties snapshotBinaryProperties - androidMkVendorSuffix bool -} - -func (p *snapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool { - if config.DeviceArch() != p.arch() { - return false - } - if p.properties.Src == nil { - return false - } - return true -} - -func (p *snapshotBinaryDecorator) link(ctx ModuleContext, - flags Flags, deps PathDeps, objs Objects) android.Path { - if !p.matchesWithDevice(ctx.DeviceConfig()) { - return nil - } - - in := android.PathForModuleSrc(ctx, *p.properties.Src) - stripFlags := flagsToStripFlags(flags) - p.unstrippedOutputFile = in - binName := in.Base() - if p.stripper.NeedsStrip(ctx) { - stripped := android.PathForModuleOut(ctx, "stripped", binName) - p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, stripFlags) - in = stripped - } - - m := ctx.Module().(*Module) - p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()] - - // use cpExecutable to make it executable - outputFile := android.PathForModuleOut(ctx, binName) - ctx.Build(pctx, android.BuildParams{ - Rule: android.CpExecutable, - Description: "prebuilt", - Output: outputFile, - Input: in, - }) - - return outputFile -} - -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) - - // Prevent default system libs (libc, libm, and libdl) from being linked - if binary.baseLinker.Properties.System_shared_libs == nil { - binary.baseLinker.Properties.System_shared_libs = []string{} - } - - prebuilt := &snapshotBinaryDecorator{ - binaryDecorator: binary, - } - - module.compiler = nil - module.sanitize = nil - module.stl = nil - module.linker = prebuilt - - prebuilt.init(module, suffix) - module.AddProperties(&prebuilt.properties) - return module.Init() -} - -type vendorSnapshotObjectProperties struct { - // Prebuilt file for each arch. - Src *string `android:"arch_variant"` -} - -type snapshotObjectLinker struct { - vendorSnapshotModuleBase - objectLinker - properties vendorSnapshotObjectProperties - androidMkVendorSuffix bool -} - -func (p *snapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool { - if config.DeviceArch() != p.arch() { - return false - } - if p.properties.Src == nil { - return false - } - return true -} - -func (p *snapshotObjectLinker) link(ctx ModuleContext, - flags Flags, deps PathDeps, objs Objects) android.Path { - if !p.matchesWithDevice(ctx.DeviceConfig()) { - return nil - } - - m := ctx.Module().(*Module) - p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()] - - return android.PathForModuleSrc(ctx, *p.properties.Src) -} - -func (p *snapshotObjectLinker) nativeCoverage() bool { - return false -} - -func VendorSnapshotObjectFactory() android.Module { - module := newObject() - - prebuilt := &snapshotObjectLinker{ - objectLinker: objectLinker{ - baseLinker: NewBaseLinker(nil), - }, - } - module.linker = prebuilt - - prebuilt.init(module, vendorSnapshotObjectSuffix) - module.AddProperties(&prebuilt.properties) - 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() { - vendorImageSingleton.init() - recoveryImageSingleton.init() -} - var vendorSnapshotSingleton = snapshotSingleton{ "vendor", "SOONG_VENDOR_SNAPSHOT_ZIP", android.OptionalPath{}, true, - vendorImageSingleton, + vendorSnapshotImageSingleton, } var recoverySnapshotSingleton = snapshotSingleton{ @@ -639,7 +41,7 @@ var recoverySnapshotSingleton = snapshotSingleton{ "SOONG_RECOVERY_SNAPSHOT_ZIP", android.OptionalPath{}, false, - recoveryImageSingleton, + recoverySnapshotImageSingleton, } func VendorSnapshotSingleton() android.Singleton { @@ -667,13 +69,12 @@ type snapshotSingleton struct { // 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 + image snapshotImage } var ( // 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 vendorProprietaryDirs = []string{ "device", "kernel", @@ -683,7 +84,6 @@ var ( // 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", @@ -694,7 +94,6 @@ var ( // 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 aospDirsUnderProprietary = []string{ "kernel/configs", "kernel/prebuilts", @@ -738,10 +137,8 @@ func isProprietaryPath(dir string, proprietaryDirs []string) bool { } func isVendorProprietaryModule(ctx android.BaseModuleContext) bool { - // Any module in a vendor proprietary path is a vendor proprietary // module. - if isVendorProprietaryPath(ctx.ModuleDir()) { return true } @@ -750,7 +147,6 @@ func isVendorProprietaryModule(ctx android.BaseModuleContext) bool { // still be a vendor proprietary module. This happens for cc modules // that are excluded from the vendor snapshot, and it means that the // vendor has assumed control of the framework-provided module. - if c, ok := ctx.Module().(*Module); ok { if c.ExcludeFromVendorSnapshot() { return true @@ -766,15 +162,21 @@ func isVendorProprietaryModule(ctx android.BaseModuleContext) bool { // AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might // 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 isVendorSnapshotAware(m *Module, inVendorProprietaryPath bool, apexInfo android.ApexInfo) bool { + return isSnapshotAware(m, inVendorProprietaryPath, apexInfo, vendorSnapshotImageSingleton) } -func isRecoverySnapshotModule(m *Module, inRecoveryProprietaryPath bool, apexInfo android.ApexInfo) bool { - return isSnapshotModule(m, inRecoveryProprietaryPath, apexInfo, recoveryImageSingleton) +// Determine if a module is going to be included in recovery snapshot or not. +// +// Targets of recovery snapshot are "recovery: true" or "recovery_available: true" +// modules in AOSP. They are not guaranteed to be compatible with older recovery images. +// So they are captured as recovery snapshot To build older recovery image. +func isRecoverySnapshotAware(m *Module, inRecoveryProprietaryPath bool, apexInfo android.ApexInfo) bool { + return isSnapshotAware(m, inRecoveryProprietaryPath, apexInfo, recoverySnapshotImageSingleton) } -func isSnapshotModule(m *Module, inProprietaryPath bool, apexInfo android.ApexInfo, image image) bool { +// Determines if the module is a candidate for snapshot. +func isSnapshotAware(m *Module, inProprietaryPath bool, apexInfo android.ApexInfo, image snapshotImage) bool { if !m.Enabled() || m.Properties.HideFromMake { return false } @@ -799,7 +201,7 @@ func isSnapshotModule(m *Module, inProprietaryPath bool, apexInfo android.ApexIn if m.Target().NativeBridge == android.NativeBridgeEnabled { return false } - // the module must be installed in /vendor + // the module must be installed in target image if !apexInfo.IsForPlatform() || m.isSnapshotPrebuilt() || !image.inImage(m)() { return false } @@ -817,7 +219,6 @@ func isSnapshotModule(m *Module, inProprietaryPath bool, apexInfo android.ApexIn // Libraries if l, ok := m.linker.(snapshotLibraryInterface); ok { - // TODO(b/65377115): add full support for sanitizer if m.sanitize != nil { // scs and hwasan export both sanitized and unsanitized variants for static and header // Always use unsanitized variants of them. @@ -827,6 +228,8 @@ func isSnapshotModule(m *Module, inProprietaryPath bool, apexInfo android.ApexIn } } // cfi also exports both variants. But for static, we capture both. + // This is because cfi static libraries can't be linked from non-cfi modules, + // and vice versa. This isn't the case for scs and hwasan sanitizers. if !l.static() && !l.shared() && m.sanitize.isSanitizerEnabled(cfi) { return false } @@ -856,6 +259,33 @@ func isSnapshotModule(m *Module, inProprietaryPath bool, apexInfo android.ApexIn return false } +// This is to be saved as .json files, which is for development/vendor_snapshot/update.py. +// These flags become Android.bp snapshot module properties. +type snapshotJsonFlags struct { + ModuleName string `json:",omitempty"` + RelativeInstallPath string `json:",omitempty"` + + // library flags + ExportedDirs []string `json:",omitempty"` + ExportedSystemDirs []string `json:",omitempty"` + ExportedFlags []string `json:",omitempty"` + Sanitize string `json:",omitempty"` + SanitizeMinimalDep bool `json:",omitempty"` + SanitizeUbsanDep bool `json:",omitempty"` + + // binary flags + Symlinks []string `json:",omitempty"` + + // dependencies + SharedLibs []string `json:",omitempty"` + RuntimeLibs []string `json:",omitempty"` + Required []string `json:",omitempty"` + + // extra config files + InitRc []string `json:",omitempty"` + VintfFragments []string `json:",omitempty"` +} + 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" { @@ -909,6 +339,8 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { var headers android.Paths + // installSnapshot function copies prebuilt file (.so, .a, or executable) and json flag file. + // For executables, init_rc and vintf_fragments files are also copied. installSnapshot := func(m *Module) android.Paths { targetArch := "arch-" + m.Target().Arch.ArchType.String() if m.Target().Arch.ArchVariant != "" { @@ -917,30 +349,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { var ret android.Paths - prop := struct { - ModuleName string `json:",omitempty"` - RelativeInstallPath string `json:",omitempty"` - - // library flags - ExportedDirs []string `json:",omitempty"` - ExportedSystemDirs []string `json:",omitempty"` - ExportedFlags []string `json:",omitempty"` - Sanitize string `json:",omitempty"` - SanitizeMinimalDep bool `json:",omitempty"` - SanitizeUbsanDep bool `json:",omitempty"` - - // binary flags - Symlinks []string `json:",omitempty"` - - // dependencies - SharedLibs []string `json:",omitempty"` - RuntimeLibs []string `json:",omitempty"` - Required []string `json:",omitempty"` - - // extra config files - InitRc []string `json:",omitempty"` - VintfFragments []string `json:",omitempty"` - }{} + prop := snapshotJsonFlags{} // Common properties among snapshots. prop.ModuleName = ctx.ModuleName(m) @@ -968,7 +377,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { out := filepath.Join(configsDir, path.Base()) if !installedConfigs[out] { installedConfigs[out] = true - ret = append(ret, copyFile(ctx, path, out)) + ret = append(ret, copyFileRule(ctx, path, out)) } } @@ -1019,7 +428,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { prop.ModuleName += ".cfi" } snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem) - ret = append(ret, copyFile(ctx, libPath, snapshotLibOut)) + ret = append(ret, copyFileRule(ctx, libPath, snapshotLibOut)) } else { stem = ctx.ModuleName(m) } @@ -1033,7 +442,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // install bin binPath := m.outputFile.Path() snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base()) - ret = append(ret, copyFile(ctx, binPath, snapshotBinOut)) + ret = append(ret, copyFileRule(ctx, binPath, snapshotBinOut)) propOut = snapshotBinOut + ".json" } else if m.object() { // object files aren't installed to the device, so their names can conflict. @@ -1041,7 +450,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { objPath := m.outputFile.Path() snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object", ctx.ModuleName(m)+filepath.Ext(objPath.Base())) - ret = append(ret, copyFile(ctx, objPath, snapshotObjOut)) + ret = append(ret, copyFileRule(ctx, objPath, snapshotObjOut)) propOut = snapshotObjOut + ".json" } else { ctx.Errorf("unknown module %q in vendor snapshot", m.String()) @@ -1053,7 +462,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { ctx.Errorf("json marshal to %q failed: %#v", propOut, err) return nil } - ret = append(ret, writeStringToFile(ctx, string(j), propOut)) + ret = append(ret, writeStringToFileRule(ctx, string(j), propOut)) return ret } @@ -1088,11 +497,14 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { } } - if !isSnapshotModule(m, inProprietaryPath, apexInfo, c.image) { + if !isSnapshotAware(m, inProprietaryPath, apexInfo, c.image) { return } + // installSnapshot installs prebuilts and json flag files snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...) + + // just gather headers and notice files here, because they are to be deduplicated if l, ok := m.linker.(snapshotLibraryInterface); ok { headers = append(headers, l.snapshotHeaders()...) } @@ -1103,7 +515,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // skip already copied notice file if !installedNotices[noticeOut] { installedNotices[noticeOut] = true - snapshotOutputs = append(snapshotOutputs, combineNotices( + snapshotOutputs = append(snapshotOutputs, combineNoticesRule( ctx, m.NoticeFiles(), noticeOut)) } } @@ -1111,7 +523,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // install all headers after removing duplicates for _, header := range android.FirstUniquePaths(headers) { - snapshotOutputs = append(snapshotOutputs, copyFile( + snapshotOutputs = append(snapshotOutputs, copyFileRule( ctx, header, filepath.Join(includeDir, header.String()))) } @@ -1155,141 +567,3 @@ func (c *snapshotSingleton) MakeVars(ctx android.MakeVarsContext) { c.makeVar, c.snapshotZipFile.String()) } - -type snapshotInterface interface { - matchesWithDevice(config android.DeviceConfig) bool -} - -var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(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 -func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) { - vndkVersion := ctx.DeviceConfig().VndkVersion() - // don't need snapshot if current - if vndkVersion == "current" || vndkVersion == "" { - return - } - - module, ok := ctx.Module().(*Module) - if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion { - return - } - - if !module.isSnapshotPrebuilt() { - return - } - - // isSnapshotPrebuilt ensures snapshotInterface - if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) { - // Disable unnecessary snapshot module, but do not disable - // vndk_prebuilt_shared because they might be packed into vndk APEX - if !module.IsVndk() { - module.Disable() - } - return - } - - var snapshotMap *snapshotMap - - if lib, ok := module.linker.(libraryInterface); ok { - if lib.static() { - snapshotMap = vendorSnapshotStaticLibs(ctx.Config()) - } else if lib.shared() { - snapshotMap = vendorSnapshotSharedLibs(ctx.Config()) - } else { - // header - snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) - } - } else if _, ok := module.linker.(*snapshotBinaryDecorator); ok { - snapshotMap = vendorSnapshotBinaries(ctx.Config()) - } else if _, ok := module.linker.(*snapshotObjectLinker); ok { - snapshotMap = vendorSnapshotObjects(ctx.Config()) - } else { - return - } - - vendorSnapshotsLock.Lock() - defer vendorSnapshotsLock.Unlock() - snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName()) -} - -// Disables source modules which have snapshots -func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) { - if !ctx.Device() { - return - } - - vndkVersion := ctx.DeviceConfig().VndkVersion() - // don't need snapshot if current - if vndkVersion == "current" || vndkVersion == "" { - return - } - - module, ok := ctx.Module().(*Module) - if !ok { - return - } - - // vendor suffix should be added to snapshots if the source module isn't vendor: true. - if !module.SocSpecific() { - // But we can't just check SocSpecific() since we already passed the image mutator. - // Check ramdisk and recovery to see if we are real "vendor: true" module. - ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk() - vendor_ramdisk_available := module.InVendorRamdisk() && !module.OnlyInVendorRamdisk() - recovery_available := module.InRecovery() && !module.OnlyInRecovery() - - if !ramdisk_available && !recovery_available && !vendor_ramdisk_available { - vendorSnapshotsLock.Lock() - defer vendorSnapshotsLock.Unlock() - - vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true - } - } - - if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() { - // only non-snapshot modules with BOARD_VNDK_VERSION - return - } - - // .. and also filter out llndk library - if module.isLlndk(ctx.Config()) { - return - } - - var snapshotMap *snapshotMap - - if lib, ok := module.linker.(libraryInterface); ok { - if lib.static() { - snapshotMap = vendorSnapshotStaticLibs(ctx.Config()) - } else if lib.shared() { - snapshotMap = vendorSnapshotSharedLibs(ctx.Config()) - } else { - // header - snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) - } - } else if module.binary() { - snapshotMap = vendorSnapshotBinaries(ctx.Config()) - } else if module.object() { - snapshotMap = vendorSnapshotObjects(ctx.Config()) - } else { - return - } - - if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok { - // Corresponding snapshot doesn't exist - return - } - - // Disables source modules if corresponding snapshot exists. - if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() { - // But do not disable because the shared variant depends on the static variant. - module.SkipInstall() - module.Properties.HideFromMake = true - } else { - module.Disable() - } -} diff --git a/cc/vndk.go b/cc/vndk.go index d57cdf79d..eca1cdfdb 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -533,7 +533,7 @@ type vndkSnapshotSingleton struct { vndkSnapshotZipFile android.OptionalPath } -func isVndkSnapshotLibrary(config android.DeviceConfig, m *Module, +func isVndkSnapshotAware(config android.DeviceConfig, m *Module, apexInfo android.ApexInfo) (i snapshotLibraryInterface, vndkType string, isVndkSnapshotLib bool) { if m.Target().NativeBridge == android.NativeBridgeEnabled { @@ -622,6 +622,9 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex var headers android.Paths + // installVndkSnapshotLib copies built .so file from the module. + // Also, if the build artifacts is on, write a json file which contains all exported flags + // with FlagExporterInfo. installVndkSnapshotLib := func(m *Module, vndkType string) (android.Paths, bool) { var ret android.Paths @@ -632,7 +635,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex libPath := m.outputFile.Path() snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base()) - ret = append(ret, copyFile(ctx, libPath, snapshotLibOut)) + ret = append(ret, copyFileRule(ctx, libPath, snapshotLibOut)) if ctx.Config().VndkSnapshotBuildArtifacts() { prop := struct { @@ -654,7 +657,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex ctx.Errorf("json marshal to %q failed: %#v", propOut, err) return nil, false } - ret = append(ret, writeStringToFile(ctx, string(j), propOut)) + ret = append(ret, writeStringToFileRule(ctx, string(j), propOut)) } return ret, true } @@ -667,11 +670,21 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) - l, vndkType, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m, apexInfo) + l, vndkType, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo) if !ok { return } + // For all snapshot candidates, the followings are captured. + // - .so files + // - notice files + // + // The followings are also captured if VNDK_SNAPSHOT_BUILD_ARTIFACTS. + // - .json files containing exported flags + // - exported headers from collectHeadersForSnapshot() + // + // Headers are deduplicated after visiting all modules. + // install .so files for appropriate modules. // Also install .json files if VNDK_SNAPSHOT_BUILD_ARTIFACTS libs, ok := installVndkSnapshotLib(m, vndkType) @@ -690,7 +703,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex // skip already copied notice file if _, ok := noticeBuilt[noticeName]; !ok { noticeBuilt[noticeName] = true - snapshotOutputs = append(snapshotOutputs, combineNotices( + snapshotOutputs = append(snapshotOutputs, combineNoticesRule( ctx, m.NoticeFiles(), filepath.Join(noticeDir, noticeName))) } } @@ -702,7 +715,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex // install all headers after removing duplicates for _, header := range android.FirstUniquePaths(headers) { - snapshotOutputs = append(snapshotOutputs, copyFile( + snapshotOutputs = append(snapshotOutputs, copyFileRule( ctx, header, filepath.Join(includeDir, header.String()))) } @@ -712,30 +725,10 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt { return } - snapshotOutputs = append(snapshotOutputs, copyFile( + snapshotOutputs = append(snapshotOutputs, copyFileRule( ctx, m.OutputFile(), filepath.Join(configsDir, m.Name()))) }) - /* - Dump a map to a list file as: - - {key1} {value1} - {key2} {value2} - ... - */ - installMapListFile := func(m map[string]string, path string) android.OutputPath { - var txtBuilder strings.Builder - for idx, k := range android.SortedStringKeys(m) { - if idx > 0 { - txtBuilder.WriteString("\n") - } - txtBuilder.WriteString(k) - txtBuilder.WriteString(" ") - txtBuilder.WriteString(m[k]) - } - return writeStringToFile(ctx, txtBuilder.String(), path) - } - /* module_paths.txt contains paths on which VNDK modules are defined. e.g., @@ -743,7 +736,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex libc.so bionic/libc ... */ - snapshotOutputs = append(snapshotOutputs, installMapListFile(modulePaths, filepath.Join(configsDir, "module_paths.txt"))) + snapshotOutputs = append(snapshotOutputs, installMapListFileRule(ctx, modulePaths, filepath.Join(configsDir, "module_paths.txt"))) /* module_names.txt contains names as which VNDK modules are defined, @@ -754,7 +747,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex libprotobuf-cpp-full-3.9.2.so libprotobuf-cpp-full ... */ - snapshotOutputs = append(snapshotOutputs, installMapListFile(moduleNames, filepath.Join(configsDir, "module_names.txt"))) + snapshotOutputs = append(snapshotOutputs, installMapListFileRule(ctx, moduleNames, filepath.Join(configsDir, "module_names.txt"))) // All artifacts are ready. Sort them to normalize ninja and then zip. sort.Slice(snapshotOutputs, func(i, j int) bool { @@ -764,7 +757,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex zipPath := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+".zip") zipRule := android.NewRuleBuilder(pctx, ctx) - // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with xargs + // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+"_list") zipRule.Command(). Text("tr").