Deprecate Snapshot build

Existing snapshot code will no longer work from VNDK deprecation, but it
can give confusion to users if we keep code for the snapshot - and it
adds complexity on existing code while it is not in use. This change
removes all snapshot definition except host snapshot and its usage.

Bug: 330100430
Bug: 332986564
Test: AOSP CF build succeeded
Change-Id: Ieb6fa43d5e38315c662ce997bc305b744b367c24
This commit is contained in:
Kiyoung Kim 2024-04-04 09:56:15 +09:00
parent 4caca1d797
commit 37693d0a27
37 changed files with 85 additions and 3853 deletions

View file

@ -3905,174 +3905,6 @@ func TestVndkApexWithBinder32(t *testing.T) {
})
}
func TestVendorApexWithVndkPrebuilts(t *testing.T) {
ctx := testApex(t, "",
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.DeviceVndkVersion = proptools.StringPtr("27")
}),
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
cc.RegisterVendorSnapshotModules(ctx)
}),
withFiles(map[string][]byte{
"vendor/foo/Android.bp": []byte(`
apex {
name: "myapex",
binaries: ["foo"],
key: "myapex.key",
min_sdk_version: "27",
vendor: true,
}
cc_binary {
name: "foo",
vendor: true,
srcs: ["abc.cpp"],
shared_libs: [
"libllndk",
"libvndk",
],
nocrt: true,
system_shared_libs: [],
min_sdk_version: "27",
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
`),
// Simulate VNDK prebuilts with vendor_snapshot
"prebuilts/vndk/Android.bp": []byte(`
vndk_prebuilt_shared {
name: "libllndk",
version: "27",
vendor_available: true,
product_available: true,
target_arch: "arm64",
arch: {
arm64: {
srcs: ["libllndk.so"],
},
},
}
vndk_prebuilt_shared {
name: "libvndk",
version: "27",
vendor_available: true,
product_available: true,
target_arch: "arm64",
arch: {
arm64: {
srcs: ["libvndk.so"],
},
},
vndk: {
enabled: true,
},
min_sdk_version: "27",
}
vndk_prebuilt_shared {
name: "libc++",
version: "27",
target_arch: "arm64",
vendor_available: true,
product_available: true,
vndk: {
enabled: true,
support_system_process: true,
},
arch: {
arm64: {
srcs: ["libc++.so"],
},
},
min_sdk_version: "apex_inherit",
}
vendor_snapshot {
name: "vendor_snapshot",
version: "27",
arch: {
arm64: {
vndk_libs: [
"libc++",
"libllndk",
"libvndk",
],
static_libs: [
"libc++demangle",
"libclang_rt.builtins",
"libunwind",
],
},
}
}
vendor_snapshot_static {
name: "libclang_rt.builtins",
version: "27",
target_arch: "arm64",
vendor: true,
arch: {
arm64: {
src: "libclang_rt.builtins-aarch64-android.a",
},
},
}
vendor_snapshot_static {
name: "libc++demangle",
version: "27",
target_arch: "arm64",
compile_multilib: "64",
vendor: true,
arch: {
arm64: {
src: "libc++demangle.a",
},
},
min_sdk_version: "apex_inherit",
}
vendor_snapshot_static {
name: "libunwind",
version: "27",
target_arch: "arm64",
compile_multilib: "64",
vendor: true,
arch: {
arm64: {
src: "libunwind.a",
},
},
min_sdk_version: "apex_inherit",
}
`),
}))
// Should embed the prebuilt VNDK libraries in the apex
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
"bin/foo",
"prebuilts/vndk/libc++.so:lib64/libc++.so",
"prebuilts/vndk/libvndk.so:lib64/libvndk.so",
})
// Should link foo with prebuilt libraries (shared/static)
ldRule := ctx.ModuleForTests("foo", "android_vendor.27_arm64_armv8-a_myapex").Rule("ld")
android.AssertStringDoesContain(t, "should link to prebuilt llndk", ldRule.Args["libFlags"], "prebuilts/vndk/libllndk.so")
android.AssertStringDoesContain(t, "should link to prebuilt vndk", ldRule.Args["libFlags"], "prebuilts/vndk/libvndk.so")
android.AssertStringDoesContain(t, "should link to prebuilt libc++demangle", ldRule.Args["libFlags"], "prebuilts/vndk/libc++demangle.a")
android.AssertStringDoesContain(t, "should link to prebuilt libunwind", ldRule.Args["libFlags"], "prebuilts/vndk/libunwind.a")
// Should declare the LLNDK library as a "required" external dependency
manifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
requireNativeLibs := names(manifestRule.Args["requireNativeLibs"])
ensureListContains(t, requireNativeLibs, "libllndk.so")
}
func TestDependenciesInApexManifest(t *testing.T) {
ctx := testApex(t, `
apex {

View file

@ -17,7 +17,6 @@ bootstrap_go_package {
"soong-fuzz",
"soong-genrule",
"soong-multitree",
"soong-snapshot",
"soong-testing",
"soong-tradefed",
],
@ -45,12 +44,10 @@ bootstrap_go_package {
"sabi.go",
"sdk.go",
"snapshot_prebuilt.go",
"snapshot_utils.go",
"stl.go",
"strip.go",
"tidy.go",
"util.go",
"vendor_snapshot.go",
"vndk.go",
"vndk_prebuilt.go",

View file

@ -15,8 +15,6 @@
package cc
import (
"github.com/google/blueprint/proptools"
"fmt"
"io"
"path/filepath"
@ -477,79 +475,6 @@ func (c *vndkPrebuiltLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, en
})
}
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() {
entries.Class = "SHARED_LIBRARIES"
} else if c.static() {
entries.Class = "STATIC_LIBRARIES"
} else if c.header() {
entries.Class = "HEADER_LIBRARIES"
}
entries.SubName = ""
if c.IsSanitizerEnabled(cfi) {
entries.SubName += ".cfi"
} else if c.IsSanitizerEnabled(Hwasan) {
entries.SubName += ".hwasan"
}
entries.SubName += c.baseProperties.Androidmk_suffix
entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
c.libraryDecorator.androidMkWriteExportedFlags(entries)
if c.shared() || c.static() {
src := c.path.String()
// For static libraries which aren't installed, directly use Src to extract filename.
// This is safe: generated snapshot modules have a real path as Src, not a module
if c.static() {
src = proptools.String(c.properties.Src)
}
path, file := filepath.Split(src)
stem, suffix, ext := android.SplitFileExt(file)
entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
entries.SetString("LOCAL_MODULE_STEM", stem)
if c.shared() {
entries.SetString("LOCAL_MODULE_PATH", path)
}
if c.tocFile.Valid() {
entries.SetString("LOCAL_SOONG_TOC", c.tocFile.String())
}
if c.shared() && len(c.Properties.Overrides) > 0 {
entries.SetString("LOCAL_OVERRIDES_MODULES", strings.Join(makeOverrideModuleNames(ctx, c.Properties.Overrides), " "))
}
}
if !c.shared() { // static or header
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
}
})
}
func (c *snapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "EXECUTABLES"
entries.SubName = c.baseProperties.Androidmk_suffix
}
func (c *snapshotObjectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "STATIC_LIBRARIES"
entries.SubName = c.baseProperties.Androidmk_suffix
entries.ExtraFooters = append(entries.ExtraFooters,
func(w io.Writer, name, prefix, moduleDir string) {
out := entries.OutputFile.Path()
varname := fmt.Sprintf("SOONG_%sOBJECT_%s%s", prefix, name, entries.SubName)
fmt.Fprintf(w, "\n%s := %s\n", varname, out.String())
fmt.Fprintln(w, ".KATI_READONLY: "+varname)
})
}
func (c *ndkPrebuiltStlLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "SHARED_LIBRARIES"
}

129
cc/cc.go
View file

@ -35,7 +35,6 @@ import (
"android/soong/fuzz"
"android/soong/genrule"
"android/soong/multitree"
"android/soong/snapshot"
)
func init() {
@ -347,11 +346,6 @@ type BaseProperties struct {
// see soong/cc/config/vndk.go
MustUseVendorVariant bool `blueprint:"mutated"`
// Used by vendor snapshot to record dependencies from snapshot modules.
SnapshotSharedLibs []string `blueprint:"mutated"`
SnapshotStaticLibs []string `blueprint:"mutated"`
SnapshotRuntimeLibs []string `blueprint:"mutated"`
Installable *bool `android:"arch_variant"`
// Set by factories of module types that can only be referenced from variants compiled against
@ -364,20 +358,6 @@ type BaseProperties struct {
// variant to have a ".sdk" suffix.
SdkAndPlatformVariantVisibleToMake bool `blueprint:"mutated"`
// Normally Soong uses the directory structure to decide which modules
// should be included (framework) or excluded (non-framework) from the
// different snapshots (vendor, recovery, etc.), 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
// Normally Soong uses the directory structure to decide which modules
// should be included (framework) or excluded (non-framework) from the
// different snapshots (vendor, recovery, etc.), but this property
// allows a partner to exclude a module normally thought of as a
// framework module from the recovery snapshot.
Exclude_from_recovery_snapshot *bool
// List of APEXes that this module has private access to for testing purpose. The module
// can depend on libraries that are not exported by the APEXes and use private symbols
// from the exported libraries.
@ -960,8 +940,6 @@ func (c *Module) AddJSONData(d *map[string]interface{}) {
"IsVndkSp": c.IsVndkSp(),
"IsLlndk": c.IsLlndk(),
"IsLlndkPublic": c.IsLlndkPublic(),
"IsSnapshotLibrary": c.IsSnapshotLibrary(),
"IsSnapshotPrebuilt": c.IsSnapshotPrebuilt(),
"IsVendorPublicLibrary": c.IsVendorPublicLibrary(),
"ApexSdkVersion": c.apexSdkVersion,
"TestFor": c.TestFor(),
@ -1513,14 +1491,6 @@ func (c *Module) IsSnapshotPrebuilt() bool {
return false
}
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":
@ -2152,14 +2122,6 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
c.outputFile = android.OptionalPathForPath(outputFile)
c.maybeUnhideFromMake()
// glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or
// RECOVERY_SNAPSHOT_VERSION is current.
if i, ok := c.linker.(snapshotLibraryInterface); ok {
if ShouldCollectHeadersForSnapshot(ctx, c, apexInfo) {
i.collectHeadersForSnapshot(ctx)
}
}
}
if c.testModule {
android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
@ -2438,31 +2400,6 @@ func GetApiImports(c LinkableInterface, actx android.BottomUpMutatorContext) mul
return apiImportInfo
}
func GetSnapshot(c LinkableInterface, snapshotInfo **SnapshotInfo, actx android.BottomUpMutatorContext) SnapshotInfo {
// Only device modules with BOARD_VNDK_VERSION uses snapshot. Others use the zero value of
// SnapshotInfo, which provides no mappings.
if *snapshotInfo == nil && c.Device() {
// Only retrieve the snapshot on demand in order to avoid circular dependencies
// between the modules in the snapshot and the snapshot itself.
var snapshotModule []blueprint.Module
if c.InVendor() && c.VndkVersion() == actx.DeviceConfig().VndkVersion() && actx.OtherModuleExists("vendor_snapshot") {
snapshotModule = actx.AddVariationDependencies(nil, nil, "vendor_snapshot")
} else if recoverySnapshotVersion := actx.DeviceConfig().RecoverySnapshotVersion(); recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" && c.InRecovery() && actx.OtherModuleExists("recovery_snapshot") {
snapshotModule = actx.AddVariationDependencies(nil, nil, "recovery_snapshot")
}
if len(snapshotModule) > 0 && snapshotModule[0] != nil {
snapshot, _ := android.OtherModuleProvider(actx, snapshotModule[0], SnapshotInfoProvider)
*snapshotInfo = &snapshot
// republish the snapshot for use in later mutators on this module
android.SetProvider(actx, SnapshotInfoProvider, snapshot)
}
}
if *snapshotInfo == nil {
*snapshotInfo = &SnapshotInfo{}
}
return **snapshotInfo
}
func GetReplaceModuleName(lib string, replaceMap map[string]string) string {
if snapshot, ok := replaceMap[lib]; ok {
return snapshot
@ -2471,44 +2408,35 @@ func GetReplaceModuleName(lib string, replaceMap map[string]string) string {
return lib
}
// RewriteLibs takes a list of names of shared libraries and scans it for three types
// FilterNdkLibs takes a list of names of shared libraries and scans it for two types
// of names:
//
// 1. Name of an NDK library that refers to a prebuilt module.
//
// For each of these, it adds the name of the prebuilt module (which will be in
// prebuilts/ndk) to the list of nonvariant libs.
//
// 2. Name of an NDK library that refers to an ndk_library module.
// 1. Name of an NDK library that refers to an ndk_library module.
//
// For each of these, it adds the name of the ndk_library module to the list of
// variant libs.
//
// 3. Anything else (so anything that isn't an NDK library).
// 2. Anything else (so anything that isn't an NDK library).
//
// It adds these to the nonvariantLibs list.
//
// The caller can then know to add the variantLibs dependencies differently from the
// nonvariantLibs
func RewriteLibs(c LinkableInterface, snapshotInfo **SnapshotInfo, actx android.BottomUpMutatorContext, config android.Config, list []string) (nonvariantLibs []string, variantLibs []string) {
func FilterNdkLibs(c LinkableInterface, config android.Config, list []string) (nonvariantLibs []string, variantLibs []string) {
variantLibs = []string{}
nonvariantLibs = []string{}
for _, entry := range list {
// strip #version suffix out
name, _ := StubsLibNameAndVersion(entry)
if c.InRecovery() {
nonvariantLibs = append(nonvariantLibs, GetReplaceModuleName(entry, GetSnapshot(c, snapshotInfo, actx).SharedLibs))
} else if c.UseSdk() && inList(name, *getNDKKnownLibs(config)) {
if c.UseSdk() && inList(name, *getNDKKnownLibs(config)) {
variantLibs = append(variantLibs, name+ndkLibrarySuffix)
} else if c.UseVndk() {
nonvariantLibs = append(nonvariantLibs, GetReplaceModuleName(entry, GetSnapshot(c, snapshotInfo, actx).SharedLibs))
} else {
// put name#version back
nonvariantLibs = append(nonvariantLibs, entry)
}
}
return nonvariantLibs, variantLibs
}
func rewriteLibsForApiImports(c LinkableInterface, libs []string, replaceList map[string]string, config android.Config) ([]string, []string) {
@ -2580,18 +2508,12 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
var snapshotInfo *SnapshotInfo
variantNdkLibs := []string{}
variantLateNdkLibs := []string{}
if ctx.Os() == android.Android {
deps.SharedLibs, variantNdkLibs = RewriteLibs(c, &snapshotInfo, actx, ctx.Config(), deps.SharedLibs)
deps.LateSharedLibs, variantLateNdkLibs = RewriteLibs(c, &snapshotInfo, actx, ctx.Config(), deps.LateSharedLibs)
deps.ReexportSharedLibHeaders, _ = RewriteLibs(c, &snapshotInfo, actx, ctx.Config(), deps.ReexportSharedLibHeaders)
for idx, lib := range deps.RuntimeLibs {
deps.RuntimeLibs[idx] = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).SharedLibs)
}
deps.SharedLibs, variantNdkLibs = FilterNdkLibs(c, ctx.Config(), deps.SharedLibs)
deps.LateSharedLibs, variantLateNdkLibs = FilterNdkLibs(c, ctx.Config(), deps.LateSharedLibs)
deps.ReexportSharedLibHeaders, _ = FilterNdkLibs(c, ctx.Config(), deps.ReexportSharedLibHeaders)
}
for _, lib := range deps.HeaderLibs {
@ -2604,7 +2526,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
if c.shouldUseApiSurface() {
lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
}
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs)
if c.isNDKStubLibrary() {
// ndk_headers do not have any variations
@ -2630,8 +2551,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
for _, lib := range deps.WholeStaticLibs {
depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true, reexportFlags: true}
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, lib)
@ -2646,8 +2565,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
depTag.excludeInApex = true
}
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, lib)
@ -2660,7 +2577,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, GetReplaceModuleName(staticUnwinder(actx), GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
}, depTag, staticUnwinder(actx))
}
// shared lib names without the #version suffix
@ -2701,14 +2618,14 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
}, depTag, lib)
}
for _, lib := range deps.UnexportedStaticLibs {
depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency, unexportedSymbols: true}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
}, depTag, lib)
}
for _, lib := range deps.LateSharedLibs {
@ -2749,11 +2666,11 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
for _, crt := range deps.CrtBegin {
actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
GetReplaceModuleName(crt, GetSnapshot(c, &snapshotInfo, actx).Objects))
crt)
}
for _, crt := range deps.CrtEnd {
actx.AddVariationDependencies(crtVariations, CrtEndDepTag,
GetReplaceModuleName(crt, GetSnapshot(c, &snapshotInfo, actx).Objects))
crt)
}
if deps.DynamicLinker != "" {
actx.AddDependency(c, dynamicLinkerDepTag, deps.DynamicLinker)
@ -2786,7 +2703,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
actx.AddVariationDependencies([]blueprint.Variation{
c.ImageVariation(),
{Mutator: "link", Variation: "shared"},
}, vndkExtDepTag, GetReplaceModuleName(vndkdep.getVndkExtendsModuleName(), GetSnapshot(c, &snapshotInfo, actx).SharedLibs))
}, vndkExtDepTag, vndkdep.getVndkExtendsModuleName())
}
}
@ -3394,8 +3311,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
// they merely serve as Make dependencies and do not affect this lib itself.
c.Properties.AndroidMkSharedLibs = append(
c.Properties.AndroidMkSharedLibs, makeLibName)
// Record BaseLibName for snapshots.
c.Properties.SnapshotSharedLibs = append(c.Properties.SnapshotSharedLibs, BaseLibName(depName))
case libDepTag.static():
if libDepTag.wholeStatic {
c.Properties.AndroidMkWholeStaticLibs = append(
@ -3404,8 +3319,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
c.Properties.AndroidMkStaticLibs = append(
c.Properties.AndroidMkStaticLibs, makeLibName)
}
// Record BaseLibName for snapshots.
c.Properties.SnapshotStaticLibs = append(c.Properties.SnapshotStaticLibs, BaseLibName(depName))
}
} else if !c.IsStubs() {
// Stubs lib doesn't link to the runtime lib, object, crt, etc. dependencies.
@ -3414,8 +3327,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
case runtimeDepTag:
c.Properties.AndroidMkRuntimeLibs = append(
c.Properties.AndroidMkRuntimeLibs, MakeLibName(ctx, c, ccDep, ccDep.BaseModuleName())+libDepTag.makeSuffix)
// Record BaseLibName for snapshots.
c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, BaseLibName(depName))
case objDepTag:
depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path())
case CrtBeginDepTag:
@ -3799,6 +3710,14 @@ func (c *Module) Object() bool {
return false
}
func (m *Module) Dylib() bool {
return false
}
func (m *Module) Rlib() bool {
return false
}
func GetMakeLinkType(actx android.ModuleContext, c LinkableInterface) string {
if c.InVendorOrProduct() {
if c.IsLlndk() {
@ -4030,8 +3949,6 @@ func (c *Module) overriddenModules() []string {
return nil
}
var _ snapshot.RelativeInstallPath = (*Module)(nil)
type moduleType int
const (

View file

@ -19,7 +19,6 @@ import (
"android/soong/android"
"android/soong/genrule"
"android/soong/snapshot"
)
func init() {
@ -97,14 +96,8 @@ func (g *GenruleExtraProperties) DebugRamdiskVariantNeeded(ctx android.BaseModul
func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
// If the build is using a snapshot, the recovery variant under AOSP directories
// is not needed.
recoverySnapshotVersion := ctx.DeviceConfig().RecoverySnapshotVersion()
if recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" &&
!snapshot.IsRecoveryProprietaryModule(ctx) {
return false
} else {
return Bool(g.Recovery_available)
}
}
func (g *GenruleExtraProperties) ExtraImageVariations(ctx android.BaseModuleContext) []string {
var variants []string

View file

@ -22,7 +22,6 @@ import (
"strings"
"android/soong/android"
"android/soong/snapshot"
"github.com/google/blueprint/proptools"
)
@ -430,9 +429,6 @@ func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) {
var productVariants []string
boardVndkVersion := mctx.DeviceConfig().VndkVersion()
recoverySnapshotVersion := mctx.DeviceConfig().RecoverySnapshotVersion()
usingRecoverySnapshot := recoverySnapshotVersion != "current" &&
recoverySnapshotVersion != ""
needVndkVersionVendorVariantForLlndk := false
if boardVndkVersion != "" {
boardVndkApiLevel, err := android.ApiLevelFromUser(mctx, boardVndkVersion)
@ -478,12 +474,8 @@ func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) {
// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
// PLATFORM_VNDK_VERSION.
if m.HasVendorVariant() {
if snapshot.IsVendorProprietaryModule(mctx) {
vendorVariants = append(vendorVariants, boardVndkVersion)
} else {
vendorVariants = append(vendorVariants, "")
}
}
// product_available modules are available to /product.
if m.HasProductVariant() {
@ -503,8 +495,6 @@ func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) {
"",
boardVndkVersion,
)
} else if snapshot.IsVendorProprietaryModule(mctx) {
vendorVariants = append(vendorVariants, boardVndkVersion)
} else {
vendorVariants = append(vendorVariants, "")
}
@ -548,15 +538,6 @@ func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) {
coreVariantNeeded = false
}
// If using a snapshot, the recovery variant under AOSP directories is not needed,
// except for kernel headers, which needs all variants.
if !m.KernelHeadersDecorator() &&
!m.IsSnapshotPrebuilt() &&
usingRecoverySnapshot &&
!snapshot.IsRecoveryProprietaryModule(mctx) {
recoveryVariantNeeded = false
}
for _, variant := range android.FirstUniqueStrings(vendorVariants) {
if variant == "" {
m.AppendExtraVariant(VendorVariation)

View file

@ -424,126 +424,9 @@ type libraryDecorator struct {
*baseLinker
*baseInstaller
collectedSnapshotHeaders android.Paths
apiListCoverageXmlPath android.ModuleOutPath
}
func GlobHeadersForSnapshot(ctx android.ModuleContext, paths android.Paths) android.Paths {
ret := android.Paths{}
// Headers in the source tree should be globbed. On the contrast, generated headers
// can't be globbed, and they should be manually collected.
// So, we first filter out intermediate directories (which contains generated headers)
// from exported directories, and then glob headers under remaining directories.
for _, path := range paths {
dir := path.String()
// Skip if dir is for generated headers
if strings.HasPrefix(dir, ctx.Config().OutDir()) {
continue
}
// libeigen wrongly exports the root directory "external/eigen". But only two
// subdirectories "Eigen" and "unsupported" contain exported header files. Even worse
// some of them have no extension. So we need special treatment for libeigen in order
// to glob correctly.
if dir == "external/eigen" {
// Only these two directories contains exported headers.
for _, subdir := range []string{"Eigen", "unsupported/Eigen"} {
globDir := "external/eigen/" + subdir + "/**/*"
glob, err := ctx.GlobWithDeps(globDir, nil)
if err != nil {
ctx.ModuleErrorf("glob of %q failed: %s", globDir, err)
return nil
}
for _, header := range glob {
if strings.HasSuffix(header, "/") {
continue
}
ext := filepath.Ext(header)
if ext != "" && ext != ".h" {
continue
}
ret = append(ret, android.PathForSource(ctx, header))
}
}
continue
}
globDir := dir + "/**/*"
glob, err := ctx.GlobWithDeps(globDir, nil)
if err != nil {
ctx.ModuleErrorf("glob of %q failed: %s", globDir, err)
return nil
}
isLibcxx := strings.HasPrefix(dir, "external/libcxx/include")
for _, header := range glob {
if isLibcxx {
// Glob all files under this special directory, because of C++ headers with no
// extension.
if strings.HasSuffix(header, "/") {
continue
}
} else {
// Filter out only the files with extensions that are headers.
found := false
for _, ext := range HeaderExts {
if strings.HasSuffix(header, ext) {
found = true
break
}
}
if !found {
continue
}
}
ret = append(ret, android.PathForSource(ctx, header))
}
}
return ret
}
func GlobGeneratedHeadersForSnapshot(_ android.ModuleContext, paths android.Paths) android.Paths {
ret := android.Paths{}
for _, header := range paths {
// TODO(b/148123511): remove exportedDeps after cleaning up genrule
if strings.HasSuffix(header.Base(), "-phony") {
continue
}
ret = append(ret, header)
}
return ret
}
// collectHeadersForSnapshot collects all exported headers from library.
// It globs header files in the source tree for exported include directories,
// and tracks generated header files separately.
//
// This is to be called from GenerateAndroidBuildActions, and then collected
// header files can be retrieved by snapshotHeaders().
func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext) {
ret := android.Paths{}
// Headers in the source tree should be globbed. On the contrast, generated headers
// can't be globbed, and they should be manually collected.
// So, we first filter out intermediate directories (which contains generated headers)
// from exported directories, and then glob headers under remaining directories.
ret = append(ret, GlobHeadersForSnapshot(ctx, append(android.CopyOfPaths(l.flagExporter.dirs), l.flagExporter.systemDirs...))...)
// Collect generated headers
ret = append(ret, GlobGeneratedHeadersForSnapshot(ctx, append(android.CopyOfPaths(l.flagExporter.headers), l.flagExporter.deps...))...)
l.collectedSnapshotHeaders = ret
}
// This returns all exported header files, both generated ones and headers from source tree.
// collectHeadersForSnapshot() must be called before calling this.
func (l *libraryDecorator) snapshotHeaders() android.Paths {
if l.collectedSnapshotHeaders == nil {
panic("snapshotHeaders() must be called after collectHeadersForSnapshot()")
}
return l.collectedSnapshotHeaders
}
// linkerProps returns the list of properties structs relevant for this library. (For example, if
// the library is cc_shared_library, then static-library properties are omitted.)
func (library *libraryDecorator) linkerProps() []interface{} {

View file

@ -3,7 +3,6 @@ package cc
import (
"android/soong/android"
"android/soong/fuzz"
"android/soong/snapshot"
"github.com/google/blueprint"
)
@ -63,55 +62,9 @@ type PlatformSanitizeable interface {
// implementation should handle tags from both.
type SantizableDependencyTagChecker func(tag blueprint.DependencyTag) bool
// Snapshottable defines those functions necessary for handling module snapshots.
type Snapshottable interface {
snapshot.VendorSnapshotModuleInterface
snapshot.RecoverySnapshotModuleInterface
// SnapshotHeaders returns a list of header paths provided by this module.
SnapshotHeaders() android.Paths
// SnapshotLibrary returns true if this module is a snapshot library.
IsSnapshotLibrary() bool
// EffectiveLicenseFiles returns the list of License files for this module.
EffectiveLicenseFiles() android.Paths
// SnapshotRuntimeLibs returns a list of libraries needed by this module at runtime but which aren't build dependencies.
SnapshotRuntimeLibs() []string
// SnapshotSharedLibs returns the list of shared library dependencies for this module.
SnapshotSharedLibs() []string
// SnapshotStaticLibs returns the list of static library dependencies for this module.
SnapshotStaticLibs() []string
// SnapshotDylibs returns the list of dylib library dependencies for this module.
SnapshotDylibs() []string
// SnapshotRlibs returns the list of rlib library dependencies for this module.
SnapshotRlibs() []string
// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
IsSnapshotPrebuilt() bool
// IsSnapshotSanitizer returns true if this snapshot module implements SnapshotSanitizer.
IsSnapshotSanitizer() bool
// IsSnapshotSanitizerAvailable returns true if this snapshot module has a sanitizer source available (cfi, hwasan).
IsSnapshotSanitizerAvailable(t SanitizerType) bool
// SetSnapshotSanitizerVariation sets the sanitizer variation type for this snapshot module.
SetSnapshotSanitizerVariation(t SanitizerType, enabled bool)
// IsSnapshotUnsanitizedVariant returns true if this is the unsanitized snapshot module variant.
IsSnapshotUnsanitizedVariant() bool
}
// LinkableInterface is an interface for a type of module that is linkable in a C++ library.
type LinkableInterface interface {
android.Module
Snapshottable
Module() android.Module
CcLibrary() bool

View file

@ -14,6 +14,11 @@
package cc
import (
"android/soong/android"
"strings"
)
var (
llndkLibrarySuffix = ".llndk"
llndkHeadersSuffix = ".llndk"
@ -55,3 +60,21 @@ type llndkLibraryProperties struct {
// llndk.symbol_file.
Llndk_headers *bool
}
func makeLlndkVars(ctx android.MakeVarsContext) {
// Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
// they been moved to an apex.
movedToApexLlndkLibraries := make(map[string]bool)
ctx.VisitAllModules(func(module android.Module) {
if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() {
// Skip bionic libs, they are handled in different manner
name := library.implementationModuleName(module.(*Module).BaseModuleName())
if module.(android.ApexModule).DirectlyInAnyApex() && !isBionic(name) {
movedToApexLlndkLibraries[name] = true
}
}
})
ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES",
strings.Join(android.SortedKeys(movedToApexLlndkLibraries), " "))
}

View file

@ -98,7 +98,6 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
ctx.Strict("GLOBAL_CLANG_EXTERNAL_CFLAGS_NO_OVERRIDE", "${config.NoOverrideExternalGlobalCflags}")
ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion())
ctx.Strict("RECOVERY_SNAPSHOT_VERSION", ctx.DeviceConfig().RecoverySnapshotVersion())
// Filter vendor_public_library that are exported to make
exportedVendorPublicLibraries := []string{}
@ -184,6 +183,8 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
if len(deviceTargets) > 1 {
makeVarsToolchain(ctx, "2ND_", deviceTargets[1])
}
makeLlndkVars(ctx)
}
func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string,

View file

@ -25,7 +25,6 @@ import (
"android/soong/android"
"android/soong/cc/config"
"android/soong/snapshot"
)
var (
@ -1141,42 +1140,6 @@ func (m *Module) SanitizableDepTagChecker() SantizableDependencyTagChecker {
return IsSanitizableDependencyTag
}
// Determines if the current module is a static library going to be captured
// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
// except for ones which explicitly disable cfi.
func needsCfiForVendorSnapshot(mctx android.BaseModuleContext) bool {
if inList("hwaddress", mctx.Config().SanitizeDevice()) {
// cfi will not be built if SANITIZE_TARGET=hwaddress is set
return false
}
if snapshot.IsVendorProprietaryModule(mctx) {
return false
}
c := mctx.Module().(PlatformSanitizeable)
if !c.InVendor() {
return false
}
if !c.StaticallyLinked() {
return false
}
if c.IsPrebuilt() {
return false
}
if !c.SanitizerSupported(cfi) {
return false
}
return c.SanitizePropDefined() &&
!c.SanitizeNever() &&
!c.IsSanitizerExplicitlyDisabled(cfi)
}
type sanitizerSplitMutator struct {
sanitizer SanitizerType
}
@ -1201,10 +1164,6 @@ func (s *sanitizerSplitMutator) markSanitizableApexesMutator(ctx android.TopDown
func (s *sanitizerSplitMutator) Split(ctx android.BaseModuleContext) []string {
if c, ok := ctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
if s.sanitizer == cfi && needsCfiForVendorSnapshot(ctx) {
return []string{"", s.sanitizer.variationName()}
}
// If the given sanitizer is not requested in the .bp file for a module, it
// won't automatically build the sanitized variation.
if !c.IsSanitizerEnabled(s.sanitizer) {
@ -1242,17 +1201,6 @@ func (s *sanitizerSplitMutator) Split(ctx android.BaseModuleContext) []string {
}
}
if c, ok := ctx.Module().(LinkableInterface); ok {
// Check if it's a snapshot module supporting sanitizer
if c.IsSnapshotSanitizer() {
if c.IsSnapshotSanitizerAvailable(s.sanitizer) {
return []string{"", s.sanitizer.variationName()}
} else {
return []string{""}
}
}
}
return []string{""}
}
@ -1277,12 +1225,6 @@ func (s *sanitizerSplitMutator) OutgoingTransition(ctx android.OutgoingTransitio
func (s *sanitizerSplitMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
if d, ok := ctx.Module().(PlatformSanitizeable); ok {
if dm, ok := ctx.Module().(LinkableInterface); ok {
if dm.IsSnapshotSanitizerAvailable(s.sanitizer) {
return incomingVariation
}
}
if !d.SanitizePropDefined() ||
d.SanitizeNever() ||
d.IsSanitizerExplicitlyDisabled(s.sanitizer) ||
@ -1393,57 +1335,7 @@ func (s *sanitizerSplitMutator) Mutate(mctx android.BottomUpMutatorContext, vari
if sanitizerVariation {
sanitizeable.AddSanitizerDependencies(mctx, s.sanitizer.name())
}
} else if c, ok := mctx.Module().(LinkableInterface); ok {
if c.IsSnapshotSanitizerAvailable(s.sanitizer) {
if !c.IsSnapshotUnsanitizedVariant() {
// Snapshot sanitizer may have only one variantion.
// Skip exporting the module if it already has a sanitizer variation.
c.SetPreventInstall()
c.SetHideFromMake()
return
}
c.SetSnapshotSanitizerVariation(s.sanitizer, sanitizerVariation)
// Export the static lib name to make
if c.Static() && c.ExportedToMake() {
// use BaseModuleName which is the name for Make.
if s.sanitizer == cfi {
cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
} else if s.sanitizer == Hwasan {
hwasanStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
}
}
}
}
}
func (c *Module) IsSnapshotSanitizer() bool {
if _, ok := c.linker.(SnapshotSanitizer); ok {
return true
}
return false
}
func (c *Module) IsSnapshotSanitizerAvailable(t SanitizerType) bool {
if ss, ok := c.linker.(SnapshotSanitizer); ok {
return ss.IsSanitizerAvailable(t)
}
return false
}
func (c *Module) SetSnapshotSanitizerVariation(t SanitizerType, enabled bool) {
if ss, ok := c.linker.(SnapshotSanitizer); ok {
ss.SetSanitizerVariation(t, enabled)
} else {
panic(fmt.Errorf("Calling SetSnapshotSanitizerVariation on a non-snapshotLibraryDecorator: %s", c.Name()))
}
}
func (c *Module) IsSnapshotUnsanitizedVariant() bool {
if ss, ok := c.linker.(SnapshotSanitizer); ok {
return ss.IsUnsanitizedVariant()
}
return false
}
func (c *Module) SanitizeNever() bool {
@ -1492,15 +1384,6 @@ func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
return true
}
if p, ok := d.linker.(*snapshotLibraryDecorator); ok {
if Bool(p.properties.Sanitize_minimal_dep) {
c.sanitize.Properties.MinimalRuntimeDep = true
}
if Bool(p.properties.Sanitize_ubsan_dep) {
c.sanitize.Properties.UbsanRuntimeDep = true
}
}
return false
})
}
@ -1626,12 +1509,6 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
}
addStaticDeps := func(dep string, hideSymbols bool) {
// If we're using snapshots, redirect to snapshot whenever possible
snapshot, _ := android.ModuleProvider(mctx, SnapshotInfoProvider)
if lib, ok := snapshot.StaticLibs[dep]; ok {
dep = lib
}
// static executable gets static runtime libs
depTag := libraryDependencyTag{Kind: staticLibraryDependency, unexportedSymbols: hideSymbols}
variations := append(mctx.Target().Variations(),
@ -1713,12 +1590,6 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
// the best.
addStaticDeps(runtimeSharedLibrary, true)
} else if !c.static() && !c.Header() {
// If we're using snapshots, redirect to snapshot whenever possible
snapshot, _ := android.ModuleProvider(mctx, SnapshotInfoProvider)
if lib, ok := snapshot.SharedLibs[runtimeSharedLibrary]; ok {
runtimeSharedLibrary = lib
}
// Skip apex dependency check for sharedLibraryDependency
// when sanitizer diags are enabled. Skipping the check will allow
// building with diag libraries without having to list the

View file

@ -106,8 +106,6 @@ func sdkMutator(ctx android.BottomUpMutatorContext) {
}
ctx.AliasVariation("")
}
case *snapshotModule:
ctx.CreateVariations("")
case *CcApiVariant:
ccApiVariant, _ := ctx.Module().(*CcApiVariant)
if String(ccApiVariant.properties.Variant) == "ndk" {

View file

@ -18,818 +18,9 @@ package cc
// snapshot mutators and snapshot information maps which are also defined in this file.
import (
"fmt"
"strings"
"android/soong/android"
"android/soong/snapshot"
"github.com/google/blueprint"
)
// This interface overrides snapshot.SnapshotImage to implement cc module specific functions
type SnapshotImage interface {
snapshot.SnapshotImage
// The image variant name for this snapshot image.
// For example, recovery snapshot image will return "recovery", and vendor snapshot image will
// return "vendor." + version.
imageVariantName(cfg android.DeviceConfig) string
// The variant suffix for snapshot modules. For example, vendor snapshot modules will have
// ".vendor" as their suffix.
moduleNameSuffix() string
}
type vendorSnapshotImage struct {
*snapshot.VendorSnapshotImage
}
type recoverySnapshotImage struct {
*snapshot.RecoverySnapshotImage
}
func (vendorSnapshotImage) imageVariantName(cfg android.DeviceConfig) string {
return VendorVariationPrefix + cfg.VndkVersion()
}
func (vendorSnapshotImage) moduleNameSuffix() string {
return VendorSuffix
}
func (recoverySnapshotImage) imageVariantName(cfg android.DeviceConfig) string {
return android.RecoveryVariation
}
func (recoverySnapshotImage) moduleNameSuffix() string {
return RecoverySuffix
}
// Override existing vendor and recovery snapshot for cc module specific extra functions
var VendorSnapshotImageSingleton vendorSnapshotImage = vendorSnapshotImage{&snapshot.VendorSnapshotImageSingleton}
var RecoverySnapshotImageSingleton recoverySnapshotImage = recoverySnapshotImage{&snapshot.RecoverySnapshotImageSingleton}
func RegisterVendorSnapshotModules(ctx android.RegistrationContext) {
ctx.RegisterModuleType("vendor_snapshot", vendorSnapshotFactory)
ctx.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
ctx.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
ctx.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
ctx.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
ctx.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
}
func RegisterRecoverySnapshotModules(ctx android.RegistrationContext) {
ctx.RegisterModuleType("recovery_snapshot", recoverySnapshotFactory)
ctx.RegisterModuleType("recovery_snapshot_shared", RecoverySnapshotSharedFactory)
ctx.RegisterModuleType("recovery_snapshot_static", RecoverySnapshotStaticFactory)
ctx.RegisterModuleType("recovery_snapshot_header", RecoverySnapshotHeaderFactory)
ctx.RegisterModuleType("recovery_snapshot_binary", RecoverySnapshotBinaryFactory)
ctx.RegisterModuleType("recovery_snapshot_object", RecoverySnapshotObjectFactory)
}
func init() {
RegisterVendorSnapshotModules(android.InitRegistrationContext)
RegisterRecoverySnapshotModules(android.InitRegistrationContext)
android.RegisterMakeVarsProvider(pctx, snapshotMakeVarsProvider)
}
const (
snapshotHeaderSuffix = "_header."
SnapshotSharedSuffix = "_shared."
SnapshotStaticSuffix = "_static."
snapshotBinarySuffix = "_binary."
snapshotObjectSuffix = "_object."
SnapshotRlibSuffix = "_rlib."
SnapshotDylibSuffix = "_dylib."
)
type SnapshotProperties struct {
Header_libs []string `android:"arch_variant"`
Static_libs []string `android:"arch_variant"`
Shared_libs []string `android:"arch_variant"`
Rlibs []string `android:"arch_variant"`
Dylibs []string `android:"arch_variant"`
Vndk_libs []string `android:"arch_variant"`
Binaries []string `android:"arch_variant"`
Objects []string `android:"arch_variant"`
}
type snapshotModule struct {
android.ModuleBase
properties SnapshotProperties
baseSnapshot BaseSnapshotDecorator
image SnapshotImage
}
func (s *snapshotModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
cfg := ctx.DeviceConfig()
if !s.image.IsUsingSnapshot(cfg) || s.image.TargetSnapshotVersion(cfg) != s.baseSnapshot.Version() {
s.Disable()
}
}
func (s *snapshotModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
func (s *snapshotModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
func (s *snapshotModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
func (s *snapshotModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
func (s *snapshotModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
func (s *snapshotModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
return []string{s.image.imageVariantName(ctx.DeviceConfig())}
}
func (s *snapshotModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
}
func (s *snapshotModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Nothing, the snapshot module is only used to forward dependency information in DepsMutator.
}
func getSnapshotNameSuffix(moduleSuffix, version, arch string) string {
versionSuffix := version
if arch != "" {
versionSuffix += "." + arch
}
return moduleSuffix + versionSuffix
}
func (s *snapshotModule) DepsMutator(ctx android.BottomUpMutatorContext) {
collectSnapshotMap := func(names []string, snapshotSuffix, moduleSuffix string) map[string]string {
snapshotMap := make(map[string]string)
for _, name := range names {
snapshotMap[name] = name +
getSnapshotNameSuffix(snapshotSuffix+moduleSuffix,
s.baseSnapshot.Version(),
ctx.DeviceConfig().Arches()[0].ArchType.String())
}
return snapshotMap
}
snapshotSuffix := s.image.moduleNameSuffix()
headers := collectSnapshotMap(s.properties.Header_libs, snapshotSuffix, snapshotHeaderSuffix)
binaries := collectSnapshotMap(s.properties.Binaries, snapshotSuffix, snapshotBinarySuffix)
objects := collectSnapshotMap(s.properties.Objects, snapshotSuffix, snapshotObjectSuffix)
staticLibs := collectSnapshotMap(s.properties.Static_libs, snapshotSuffix, SnapshotStaticSuffix)
sharedLibs := collectSnapshotMap(s.properties.Shared_libs, snapshotSuffix, SnapshotSharedSuffix)
rlibs := collectSnapshotMap(s.properties.Rlibs, snapshotSuffix, SnapshotRlibSuffix)
dylibs := collectSnapshotMap(s.properties.Dylibs, snapshotSuffix, SnapshotDylibSuffix)
vndkLibs := collectSnapshotMap(s.properties.Vndk_libs, "", vndkSuffix)
for k, v := range vndkLibs {
sharedLibs[k] = v
}
android.SetProvider(ctx, SnapshotInfoProvider, SnapshotInfo{
HeaderLibs: headers,
Binaries: binaries,
Objects: objects,
StaticLibs: staticLibs,
SharedLibs: sharedLibs,
Rlibs: rlibs,
Dylibs: dylibs,
})
}
type SnapshotInfo struct {
HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs, Rlibs, Dylibs map[string]string
}
var SnapshotInfoProvider = blueprint.NewMutatorProvider[SnapshotInfo]("deps")
var _ android.ImageInterface = (*snapshotModule)(nil)
func snapshotMakeVarsProvider(ctx android.MakeVarsContext) {
snapshotSet := map[string]struct{}{}
ctx.VisitAllModules(func(m android.Module) {
if s, ok := m.(*snapshotModule); ok {
if _, ok := snapshotSet[s.Name()]; ok {
// arch variant generates duplicated modules
// skip this as we only need to know the path of the module.
return
}
snapshotSet[s.Name()] = struct{}{}
imageNameVersion := strings.Split(s.image.imageVariantName(ctx.DeviceConfig()), ".")
ctx.Strict(
strings.Join([]string{strings.ToUpper(imageNameVersion[0]), s.baseSnapshot.Version(), "SNAPSHOT_DIR"}, "_"),
ctx.ModuleDir(s))
}
})
}
func vendorSnapshotFactory() android.Module {
return snapshotFactory(VendorSnapshotImageSingleton)
}
func recoverySnapshotFactory() android.Module {
return snapshotFactory(RecoverySnapshotImageSingleton)
}
func snapshotFactory(image SnapshotImage) android.Module {
snapshotModule := &snapshotModule{}
snapshotModule.image = image
snapshotModule.AddProperties(
&snapshotModule.properties,
&snapshotModule.baseSnapshot.baseProperties)
android.InitAndroidArchModule(snapshotModule, android.DeviceSupported, android.MultilibBoth)
return snapshotModule
}
type BaseSnapshotDecoratorProperties struct {
// snapshot version.
Version string
// Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
Target_arch string
// Suffix to be added to the module name when exporting to Android.mk, e.g. ".vendor".
Androidmk_suffix string `blueprint:"mutated"`
// Suffix to be added to the module name, e.g., vendor_shared,
// recovery_shared, etc.
ModuleSuffix string `blueprint:"mutated"`
}
// 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
Image SnapshotImage
}
func (p *BaseSnapshotDecorator) Name(name string) string {
return name + p.NameSuffix()
}
func (p *BaseSnapshotDecorator) NameSuffix() string {
return getSnapshotNameSuffix(p.moduleSuffix(), p.Version(), p.Arch())
}
func (p *BaseSnapshotDecorator) Version() string {
return p.baseProperties.Version
}
func (p *BaseSnapshotDecorator) Arch() string {
return p.baseProperties.Target_arch
}
func (p *BaseSnapshotDecorator) moduleSuffix() string {
return p.baseProperties.ModuleSuffix
}
func (p *BaseSnapshotDecorator) IsSnapshotPrebuilt() bool {
return true
}
func (p *BaseSnapshotDecorator) SnapshotAndroidMkSuffix() string {
return p.baseProperties.Androidmk_suffix
}
func (p *BaseSnapshotDecorator) SetSnapshotAndroidMkSuffix(ctx android.ModuleContext, variant string) {
// If there are any 2 or more variations among {core, product, vendor, recovery}
// we have to add the androidmk suffix to avoid duplicate modules with the same
// name.
variations := append(ctx.Target().Variations(), blueprint.Variation{
Mutator: "image",
Variation: android.CoreVariation})
if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(LinkableInterface).BaseModuleName()) {
p.baseProperties.Androidmk_suffix = p.Image.moduleNameSuffix()
return
}
variations = append(ctx.Target().Variations(), blueprint.Variation{
Mutator: "image",
Variation: ProductVariation})
if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(LinkableInterface).BaseModuleName()) {
p.baseProperties.Androidmk_suffix = p.Image.moduleNameSuffix()
return
}
images := []SnapshotImage{VendorSnapshotImageSingleton, RecoverySnapshotImageSingleton}
for _, image := range images {
if p.Image == image {
continue
}
variations = append(ctx.Target().Variations(), blueprint.Variation{
Mutator: "image",
Variation: image.imageVariantName(ctx.DeviceConfig())})
if ctx.OtherModuleFarDependencyVariantExists(variations,
ctx.Module().(LinkableInterface).BaseModuleName()+
getSnapshotNameSuffix(
image.moduleNameSuffix()+variant,
p.Version(),
ctx.DeviceConfig().Arches()[0].ArchType.String())) {
p.baseProperties.Androidmk_suffix = p.Image.moduleNameSuffix()
return
}
}
p.baseProperties.Androidmk_suffix = ""
}
// Call this with a module suffix after creating a snapshot module, such as
// vendorSnapshotSharedSuffix, recoverySnapshotBinarySuffix, etc.
func (p *BaseSnapshotDecorator) Init(m LinkableInterface, image SnapshotImage, moduleSuffix string) {
p.Image = image
p.baseProperties.ModuleSuffix = image.moduleNameSuffix() + moduleSuffix
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 {
IsSanitizerAvailable(t SanitizerType) bool
SetSanitizerVariation(t SanitizerType, enabled bool)
IsSanitizerEnabled(t SanitizerType) bool
IsUnsanitizedVariant() bool
}
type snapshotLibraryDecorator struct {
BaseSnapshotDecorator
*libraryDecorator
properties SnapshotLibraryProperties
sanitizerProperties struct {
SanitizerVariation SanitizerType `blueprint:"mutated"`
// Library flags for cfi variant.
Cfi SnapshotLibraryProperties `android:"arch_variant"`
// Library flags for hwasan variant.
Hwasan SnapshotLibraryProperties `android:"arch_variant"`
}
}
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 {
var variant string
if p.shared() {
variant = SnapshotSharedSuffix
} else if p.static() {
variant = SnapshotStaticSuffix
} else {
variant = snapshotHeaderSuffix
}
p.SetSnapshotAndroidMkSuffix(ctx, variant)
if p.header() {
return p.libraryDecorator.link(ctx, flags, deps, objs)
}
if p.IsSanitizerEnabled(cfi) {
p.properties = p.sanitizerProperties.Cfi
} else if p.IsSanitizerEnabled(Hwasan) {
p.properties = p.sanitizerProperties.Hwasan
}
if !p.MatchesWithDevice(ctx.DeviceConfig()) {
return nil
}
// Flags specified directly to this module.
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...)
// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
p.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
p.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
p.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
p.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
in := android.PathForModuleSrc(ctx, *p.properties.Src)
p.unstrippedOutputFile = in
if p.shared() {
libName := in.Base()
// 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)
android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
SharedLibrary: in,
Target: ctx.Target(),
TableOfContents: p.tocFile,
})
}
if p.static() {
depSet := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(in).Build()
android.SetProvider(ctx, 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.baseInstaller.install(ctx, file)
}
}
func (p *snapshotLibraryDecorator) nativeCoverage() bool {
return false
}
var _ SnapshotSanitizer = (*snapshotLibraryDecorator)(nil)
func (p *snapshotLibraryDecorator) IsSanitizerAvailable(t SanitizerType) bool {
switch t {
case cfi:
return p.sanitizerProperties.Cfi.Src != nil
case Hwasan:
return p.sanitizerProperties.Hwasan.Src != nil
default:
return false
}
}
func (p *snapshotLibraryDecorator) SetSanitizerVariation(t SanitizerType, enabled bool) {
if !enabled || p.IsSanitizerEnabled(t) {
return
}
if !p.IsUnsanitizedVariant() {
panic(fmt.Errorf("snapshot Sanitizer must be one of Cfi or Hwasan but not both"))
}
p.sanitizerProperties.SanitizerVariation = t
}
func (p *snapshotLibraryDecorator) IsSanitizerEnabled(t SanitizerType) bool {
return p.sanitizerProperties.SanitizerVariation == t
}
func (p *snapshotLibraryDecorator) IsUnsanitizedVariant() bool {
return !p.IsSanitizerEnabled(Asan) &&
!p.IsSanitizerEnabled(Hwasan)
}
func snapshotLibraryFactory(image SnapshotImage, moduleSuffix 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, image, moduleSuffix)
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(VendorSnapshotImageSingleton, SnapshotSharedSuffix)
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(RecoverySnapshotImageSingleton, SnapshotSharedSuffix)
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(VendorSnapshotImageSingleton, SnapshotStaticSuffix)
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(RecoverySnapshotImageSingleton, SnapshotStaticSuffix)
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(VendorSnapshotImageSingleton, snapshotHeaderSuffix)
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(RecoverySnapshotImageSingleton, snapshotHeaderSuffix)
prebuilt.libraryDecorator.HeaderOnly()
return module.Init()
}
// 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
}
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 {
p.SetSnapshotAndroidMkSuffix(ctx, snapshotBinarySuffix)
if !p.MatchesWithDevice(ctx.DeviceConfig()) {
return nil
}
in := android.PathForModuleSrc(ctx, *p.properties.Src)
p.unstrippedOutputFile = in
binName := in.Base()
// 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,
})
// binary snapshots need symlinking
p.setSymlinkList(ctx)
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(VendorSnapshotImageSingleton, snapshotBinarySuffix)
}
// 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(RecoverySnapshotImageSingleton, snapshotBinarySuffix)
}
func snapshotBinaryFactory(image SnapshotImage, moduleSuffix 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, image, moduleSuffix)
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
}
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 {
p.SetSnapshotAndroidMkSuffix(ctx, snapshotObjectSuffix)
if !p.MatchesWithDevice(ctx.DeviceConfig()) {
return nil
}
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(android.DeviceSupported)
prebuilt := &snapshotObjectLinker{
objectLinker: objectLinker{
baseLinker: NewBaseLinker(nil),
},
}
module.linker = prebuilt
prebuilt.Init(module, VendorSnapshotImageSingleton, snapshotObjectSuffix)
module.AddProperties(&prebuilt.properties)
// vendor_snapshot_object module does not provide sanitizer variants
module.sanitize.Properties.Sanitize.Never = BoolPtr(true)
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(android.DeviceSupported)
prebuilt := &snapshotObjectLinker{
objectLinker: objectLinker{
baseLinker: NewBaseLinker(nil),
},
}
module.linker = prebuilt
prebuilt.Init(module, RecoverySnapshotImageSingleton, snapshotObjectSuffix)
module.AddProperties(&prebuilt.properties)
return module.Init()
}
type SnapshotInterface interface {
MatchesWithDevice(config android.DeviceConfig) bool
IsSnapshotPrebuilt() bool
@ -838,6 +29,3 @@ type SnapshotInterface interface {
}
var _ SnapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
var _ SnapshotInterface = (*snapshotLibraryDecorator)(nil)
var _ SnapshotInterface = (*snapshotBinaryDecorator)(nil)
var _ SnapshotInterface = (*snapshotObjectLinker)(nil)

View file

@ -1,130 +0,0 @@
// 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 contains utility types and functions for VNDK / vendor snapshot.
import (
"android/soong/android"
)
var (
HeaderExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"}
)
func (m *Module) IsSnapshotLibrary() bool {
if _, ok := m.linker.(snapshotLibraryInterface); ok {
return true
}
return false
}
func (m *Module) SnapshotHeaders() android.Paths {
if m.IsSnapshotLibrary() {
return m.linker.(snapshotLibraryInterface).snapshotHeaders()
}
return android.Paths{}
}
func (m *Module) Dylib() bool {
return false
}
func (m *Module) Rlib() bool {
return false
}
func (m *Module) SnapshotRuntimeLibs() []string {
return m.Properties.SnapshotRuntimeLibs
}
func (m *Module) SnapshotSharedLibs() []string {
return m.Properties.SnapshotSharedLibs
}
func (m *Module) SnapshotStaticLibs() []string {
return m.Properties.SnapshotStaticLibs
}
func (m *Module) SnapshotRlibs() []string {
return []string{}
}
func (m *Module) SnapshotDylibs() []string {
return []string{}
}
// 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
}
func newSnapshotMap() *snapshotMap {
return &snapshotMap{
snapshots: make(map[string]string),
}
}
func snapshotMapKey(name string, arch android.ArchType) string {
return name + ":" + arch.String()
}
// Adds a snapshot name for given module name and architecture.
// e.g. add("libbase", X86, "libbase.vndk.29.x86")
func (s *snapshotMap) add(name string, arch android.ArchType, snapshot string) {
s.snapshots[snapshotMapKey(name, arch)] = snapshot
}
// Returns snapshot name for given module name and architecture, if found.
// e.g. get("libcutils", X86) => "libcutils.vndk.29.x86", true
func (s *snapshotMap) get(name string, arch android.ArchType) (snapshot string, found bool) {
snapshot, found = s.snapshots[snapshotMapKey(name, arch)]
return snapshot, found
}
// 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 LinkableInterface, apexInfo android.ApexInfo) bool {
if ctx.DeviceConfig().VndkVersion() != "current" &&
ctx.DeviceConfig().RecoverySnapshotVersion() != "current" {
return false
}
if _, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo); ok {
return ctx.Config().VndkSnapshotBuildArtifacts()
}
for _, image := range []SnapshotImage{VendorSnapshotImageSingleton, RecoverySnapshotImageSingleton} {
if isSnapshotAware(ctx.DeviceConfig(), m, image.IsProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()), apexInfo, image) {
return true
}
}
return false
}

View file

@ -15,14 +15,12 @@
package cc
import (
"encoding/json"
"path/filepath"
"testing"
"android/soong/android"
"android/soong/genrule"
"android/soong/multitree"
"android/soong/snapshot"
)
func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
@ -702,10 +700,6 @@ func CreateTestContext(config android.Config) *android.TestContext {
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
snapshot.VendorSnapshotImageSingleton.Init(ctx)
snapshot.RecoverySnapshotImageSingleton.Init(ctx)
RegisterVendorSnapshotModules(ctx)
RegisterRecoverySnapshotModules(ctx)
RegisterVndkLibraryTxtTypes(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
@ -759,14 +753,6 @@ func CheckSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android
checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true)
}
func AssertExcludeFromVendorSnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool, variant string) {
t.Helper()
m := ctx.ModuleForTests(name, variant).Module().(LinkableInterface)
if m.ExcludeFromVendorSnapshot() != expected {
t.Errorf("expected %q ExcludeFromVendorSnapshot to be %t", m.String(), expected)
}
}
func GetOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
for _, moduleName := range moduleNames {
module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
@ -775,30 +761,3 @@ func GetOutputPaths(ctx *android.TestContext, variant string, moduleNames []stri
}
return paths
}
func AssertExcludeFromRecoverySnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool, variant string) {
t.Helper()
m := ctx.ModuleForTests(name, variant).Module().(LinkableInterface)
if m.ExcludeFromRecoverySnapshot() != expected {
t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", m.String(), expected)
}
}
func checkOverrides(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, jsonPath string, expected []string) {
t.Helper()
out := singleton.MaybeOutput(jsonPath)
content := android.ContentFromFileRuleForTests(t, ctx, out)
var flags snapshotJsonFlags
if err := json.Unmarshal([]byte(content), &flags); err != nil {
t.Errorf("Error while unmarshalling json %q: %s", jsonPath, err.Error())
return
}
for _, moduleName := range expected {
if !android.InList(moduleName, flags.Overrides) {
t.Errorf("expected %q to be in %q: %q", moduleName, flags.Overrides, content)
return
}
}
}

View file

@ -19,7 +19,6 @@ import (
"strings"
"android/soong/android"
"android/soong/snapshot"
)
// Efficiently converts a list of include directories to a single string
@ -101,6 +100,12 @@ func makeSymlinkCmd(linkDirOnDevice string, linkName string, target string) stri
"ln -sf " + target + " " + filepath.Join(dir, linkName)
}
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}
@ -116,5 +121,5 @@ func installMapListFileRule(ctx android.SingletonContext, m map[string]string, p
txtBuilder.WriteString(" ")
txtBuilder.WriteString(m[k])
}
return snapshot.WriteStringToFileRule(ctx, txtBuilder.String(), path)
return WriteStringToFileRule(ctx, txtBuilder.String(), path)
}

View file

@ -1,459 +0,0 @@
// 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
import (
"encoding/json"
"path/filepath"
"strings"
"android/soong/android"
"android/soong/snapshot"
)
// This file defines how to capture cc modules into snapshot package.
// Checks if the target image would contain VNDK
func includeVndk(image snapshot.SnapshotImage) bool {
if image.ImageName() == snapshot.VendorSnapshotImageName {
return true
}
return false
}
// Check if the module is VNDK private
func isPrivate(image snapshot.SnapshotImage, m LinkableInterface) bool {
if image.ImageName() == snapshot.VendorSnapshotImageName && m.IsVndkPrivate() {
return true
}
return false
}
// Checks if target image supports VNDK Ext
func supportsVndkExt(image snapshot.SnapshotImage) bool {
if image.ImageName() == snapshot.VendorSnapshotImageName {
return true
}
return false
}
// Determines if the module is a candidate for snapshot.
func isSnapshotAware(cfg android.DeviceConfig, m LinkableInterface, inProprietaryPath bool, apexInfo android.ApexInfo, image snapshot.SnapshotImage) bool {
if !m.Enabled() || m.HiddenFromMake() {
return false
}
// When android/prebuilt.go selects between source and prebuilt, it sets
// HideFromMake on the other one to avoid duplicate install rules in make.
if m.IsHideFromMake() {
return false
}
// skip proprietary modules, but (for the vendor snapshot only)
// include all VNDK (static)
if inProprietaryPath && (!includeVndk(image) || !m.IsVndk()) {
return false
}
// If the module would be included based on its path, check to see if
// the module is marked to be excluded. If so, skip it.
if image.ExcludeFromSnapshot(m) {
return false
}
if m.Target().Os.Class != android.Device {
return false
}
if m.Target().NativeBridge == android.NativeBridgeEnabled {
return false
}
// the module must be installed in target image
if !apexInfo.IsForPlatform() || m.IsSnapshotPrebuilt() || !image.InImage(m)() {
return false
}
// skip kernel_headers which always depend on vendor
if m.KernelHeadersDecorator() {
return false
}
if m.IsLlndk() {
return false
}
// Libraries
if sanitizable, ok := m.(PlatformSanitizeable); ok && sanitizable.IsSnapshotLibrary() {
if sanitizable.SanitizePropDefined() {
// scs exports both sanitized and unsanitized variants for static and header
// Always use unsanitized variant of it.
if !sanitizable.Shared() && sanitizable.IsSanitizerEnabled(scs) {
return false
}
// cfi and hwasan cannot be enabled at the same time.
// Skip variants that have both cfi and hwasan enabled.
if sanitizable.IsSanitizerEnabled(cfi) && sanitizable.IsSanitizerEnabled(Hwasan) {
return false
}
// cfi and hwasan also export 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.
// hwasan is captured as well to support hwasan build.
if !sanitizable.Static() &&
!sanitizable.Shared() &&
(sanitizable.IsSanitizerEnabled(cfi) || sanitizable.IsSanitizerEnabled(Hwasan)) {
return false
}
}
if sanitizable.Static() || sanitizable.Rlib() {
return sanitizable.OutputFile().Valid() && !isPrivate(image, m)
}
if sanitizable.Shared() || sanitizable.Dylib() {
if !sanitizable.OutputFile().Valid() {
return false
}
if includeVndk(image) {
if !sanitizable.IsVndk() {
return true
}
return sanitizable.IsVndkExt()
}
}
return true
}
// Binaries and Objects
if m.Binary() || m.Object() {
return m.OutputFile().Valid()
}
return false
}
// Extend the snapshot.SnapshotJsonFlags to include cc specific fields.
type snapshotJsonFlags struct {
snapshot.SnapshotJsonFlags
// 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"`
StaticExecutable bool `json:",omitempty"`
InstallInRoot bool `json:",omitempty"`
// dependencies
SharedLibs []string `json:",omitempty"`
StaticLibs []string `json:",omitempty"`
RuntimeLibs []string `json:",omitempty"`
Dylibs []string `json:",omitempty"`
Rlibs []string `json:",omitempty"`
// extra config files
InitRc []string `json:",omitempty"`
VintfFragments []string `json:",omitempty"`
MinSdkVersion string `json:",omitempty"`
}
var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) snapshot.SnapshotPaths {
/*
Vendor snapshot zipped artifacts directory structure for cc modules:
{SNAPSHOT_ARCH}/
arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
shared/
(.so shared libraries)
static/
(.a static libraries)
header/
(header only libraries)
binary/
(executable binaries)
object/
(.o object files)
arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
shared/
(.so shared libraries)
static/
(.a static libraries)
header/
(header only libraries)
binary/
(executable binaries)
object/
(.o object files)
NOTICE_FILES/
(notice files, e.g. libbase.txt)
configs/
(config files, e.g. init.rc files, vintf_fragments.xml files, etc.)
include/
(header files of same directory structure with source tree)
*/
var snapshotOutputs android.Paths
var snapshotNotices android.Paths
includeDir := filepath.Join(snapshotArchDir, "include")
configsDir := filepath.Join(snapshotArchDir, "configs")
installedNotices := make(map[string]bool)
installedConfigs := make(map[string]bool)
var headers android.Paths
copyFile := func(ctx android.SingletonContext, path android.Path, out string, fake bool) android.OutputPath {
if fake {
// All prebuilt binaries and headers are installed by copyFile function. This makes a fake
// snapshot just touch prebuilts and headers, rather than installing real files.
return snapshot.WriteStringToFileRule(ctx, "", out)
} else {
return snapshot.CopyFileRule(pctx, ctx, path, out)
}
}
// 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 LinkableInterface, fake bool) android.Paths {
targetArch := "arch-" + m.Target().Arch.ArchType.String()
if m.Target().Arch.ArchVariant != "" {
targetArch += "-" + m.Target().Arch.ArchVariant
}
var ret android.Paths
prop := snapshotJsonFlags{}
// Common properties among snapshots.
prop.InitBaseSnapshotPropsWithName(m, ctx.ModuleName(m))
if supportsVndkExt(s.Image) && m.IsVndkExt() {
// vndk exts are installed to /vendor/lib(64)?/vndk(-sp)?
if m.IsVndkSp() {
prop.RelativeInstallPath = "vndk-sp"
} else {
prop.RelativeInstallPath = "vndk"
}
} else {
prop.RelativeInstallPath = m.RelativeInstallPath()
}
prop.RuntimeLibs = m.SnapshotRuntimeLibs()
prop.Required = m.RequiredModuleNames()
if o, ok := m.(overridable); ok {
prop.Overrides = o.overriddenModules()
}
for _, path := range m.InitRc() {
prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base()))
}
for _, path := range m.VintfFragments() {
prop.VintfFragments = append(prop.VintfFragments, filepath.Join("configs", path.Base()))
}
if m.IsPrebuilt() {
prop.MinSdkVersion = "apex_inherit"
} else {
prop.MinSdkVersion = m.MinSdkVersion()
}
// install config files. ignores any duplicates.
for _, path := range append(m.InitRc(), m.VintfFragments()...) {
out := filepath.Join(configsDir, path.Base())
if !installedConfigs[out] {
installedConfigs[out] = true
ret = append(ret, copyFile(ctx, path, out, fake))
}
}
var propOut string
if m.IsSnapshotLibrary() {
exporterInfo, _ := android.SingletonModuleProvider(ctx, m.Module(), FlagExporterInfoProvider)
// library flags
prop.ExportedFlags = exporterInfo.Flags
for _, dir := range exporterInfo.IncludeDirs {
prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String()))
}
for _, dir := range exporterInfo.SystemIncludeDirs {
prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String()))
}
// shared libs dependencies aren't meaningful on static or header libs
if m.Shared() {
prop.SharedLibs = m.SnapshotSharedLibs()
}
// dylibs collect both shared and dylib dependencies.
if m.Dylib() {
prop.SharedLibs = m.SnapshotSharedLibs()
prop.Dylibs = m.SnapshotDylibs()
}
// static and rlib libs dependencies are required to collect the NOTICE files.
prop.StaticLibs = m.SnapshotStaticLibs()
prop.Rlibs = m.SnapshotRlibs()
if sanitizable, ok := m.(PlatformSanitizeable); ok {
if sanitizable.Static() && sanitizable.SanitizePropDefined() {
prop.SanitizeMinimalDep = sanitizable.MinimalRuntimeDep() || sanitizable.MinimalRuntimeNeeded()
prop.SanitizeUbsanDep = sanitizable.UbsanRuntimeDep() || sanitizable.UbsanRuntimeNeeded()
}
}
var libType string
if m.Static() {
libType = "static"
} else if m.Shared() {
libType = "shared"
} else if m.Rlib() {
libType = "rlib"
} else if m.Dylib() {
libType = "dylib"
} else {
libType = "header"
}
var stem string
// install .a, .rlib, .dylib.so, or .so
if libType != "header" {
libPath := m.OutputFile().Path()
stem = libPath.Base()
if sanitizable, ok := m.(PlatformSanitizeable); ok {
if (sanitizable.Static() || sanitizable.Rlib()) && sanitizable.SanitizePropDefined() {
if sanitizable.IsSanitizerEnabled(cfi) {
// both cfi and non-cfi variant for static libraries can exist.
// attach .cfi to distinguish between cfi and non-cfi.
// e.g. libbase.a -> libbase.cfi.a
ext := filepath.Ext(stem)
stem = strings.TrimSuffix(stem, ext) + ".cfi" + ext
prop.Sanitize = "cfi"
prop.ModuleName += ".cfi"
} else if sanitizable.IsSanitizerEnabled(Hwasan) {
// Same for the hwasan
ext := filepath.Ext(stem)
stem = strings.TrimSuffix(stem, ext) + ".hwasan" + ext
prop.Sanitize = "hwasan"
prop.ModuleName += ".hwasan"
}
}
}
if m.Rlib() && m.RlibStd() {
// rlibs produce both rlib-std and dylib-std variants
ext := filepath.Ext(stem)
stem = strings.TrimSuffix(stem, ext) + ".rlib-std" + ext
prop.ModuleName += ".rlib-std"
}
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, m.RelativeInstallPath(), stem)
ret = append(ret, copyFile(ctx, libPath, snapshotLibOut, fake))
} else {
stem = ctx.ModuleName(m)
}
propOut = filepath.Join(snapshotArchDir, targetArch, libType, m.RelativeInstallPath(), stem+".json")
} else if m.Binary() {
// binary flags
prop.Symlinks = m.Symlinks()
prop.StaticExecutable = m.StaticExecutable()
prop.InstallInRoot = m.InstallInRoot()
prop.SharedLibs = m.SnapshotSharedLibs()
prop.Dylibs = m.SnapshotDylibs()
// static and rlib dependencies are required to collect the NOTICE files.
prop.StaticLibs = m.SnapshotStaticLibs()
prop.Rlibs = m.SnapshotRlibs()
// install bin
binPath := m.OutputFile().Path()
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
ret = append(ret, copyFile(ctx, binPath, snapshotBinOut, fake))
propOut = snapshotBinOut + ".json"
} else if m.Object() {
// object files aren't installed to the device, so their names can conflict.
// Use module name as stem.
objPath := m.OutputFile().Path()
snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
ret = append(ret, copyFile(ctx, objPath, snapshotObjOut, fake))
propOut = snapshotObjOut + ".json"
} else {
ctx.Errorf("unknown module %q in vendor snapshot", m.String())
return nil
}
j, err := json.Marshal(prop)
if err != nil {
ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
return nil
}
ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
return ret
}
ctx.VisitAllModules(func(module android.Module) {
m, ok := module.(LinkableInterface)
if !ok {
return
}
moduleDir := ctx.ModuleDir(module)
inProprietaryPath := s.Image.IsProprietaryPath(moduleDir, ctx.DeviceConfig())
apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
if s.Image.ExcludeFromSnapshot(m) {
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 !isSnapshotAware(ctx.DeviceConfig(), m, inProprietaryPath, apexInfo, s.Image) {
return
}
// If we are using directed snapshot and a module is not included in the
// list, we will still include the module as if it was a fake module.
// The reason is that soong needs all the dependencies to be present, even
// if they are not using during the build.
installAsFake := s.Fake
if s.Image.ExcludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) {
installAsFake = true
}
// installSnapshot installs prebuilts and json flag files
snapshotOutputs = append(snapshotOutputs, installSnapshot(m, installAsFake)...)
// just gather headers and notice files here, because they are to be deduplicated
if m.IsSnapshotLibrary() {
headers = append(headers, m.SnapshotHeaders()...)
}
for _, notice := range m.EffectiveLicenseFiles() {
if _, ok := installedNotices[notice.String()]; !ok {
installedNotices[notice.String()] = true
snapshotNotices = append(snapshotNotices, notice)
}
}
})
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String()), s.Fake))
}
return snapshot.SnapshotPaths{OutputFiles: snapshotOutputs, NoticeFiles: snapshotNotices}
}
func init() {
snapshot.RegisterSnapshotAction(ccSnapshotAction)
}

View file

@ -15,17 +15,13 @@
package cc
import (
"encoding/json"
"errors"
"fmt"
"path/filepath"
"sort"
"strings"
"android/soong/android"
"android/soong/cc/config"
"android/soong/etc"
"android/soong/snapshot"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@ -405,7 +401,6 @@ func VndkMutator(mctx android.BottomUpMutatorContext) {
func init() {
RegisterVndkLibraryTxtTypes(android.InitRegistrationContext)
android.RegisterParallelSingletonType("vndk-snapshot", VndkSnapshotSingleton)
}
func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) {
@ -582,248 +577,6 @@ func (txt *vndkLibrariesTxt) SubDir() string {
func (txt *vndkLibrariesTxt) OutputFiles(tag string) (android.Paths, error) {
return android.Paths{txt.outputFile}, nil
}
func VndkSnapshotSingleton() android.Singleton {
return &vndkSnapshotSingleton{}
}
type vndkSnapshotSingleton struct {
vndkLibrariesFile android.OutputPath
vndkSnapshotZipFile android.OptionalPath
}
func isVndkSnapshotAware(config android.DeviceConfig, m LinkableInterface,
apexInfo android.ApexInfo) (vndkType string, isVndkSnapshotLib bool) {
return "", false
}
func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
// build these files even if PlatformVndkVersion or BoardVndkVersion is not set
c.buildVndkLibrariesTxtFiles(ctx)
// BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot.
if ctx.DeviceConfig().VndkVersion() != "current" {
return
}
var snapshotOutputs android.Paths
/*
VNDK snapshot zipped artifacts directory structure:
{SNAPSHOT_ARCH}/
arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
shared/
vndk-core/
(VNDK-core libraries, e.g. libbinder.so)
vndk-sp/
(VNDK-SP libraries, e.g. libc++.so)
llndk-stub/
(LLNDK stub libraries)
arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
shared/
vndk-core/
(VNDK-core libraries, e.g. libbinder.so)
vndk-sp/
(VNDK-SP libraries, e.g. libc++.so)
llndk-stub/
(LLNDK stub libraries)
binder32/
(This directory is newly introduced in v28 (Android P) to hold
prebuilts built for 32-bit binder interface.)
arch-{TARGET_ARCH}-{TARGE_ARCH_VARIANT}/
...
configs/
(various *.txt configuration files)
include/
(header files of same directory structure with source tree)
NOTICE_FILES/
(notice files of libraries, e.g. libcutils.so.txt)
*/
snapshotDir := "vndk-snapshot"
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
configsDir := filepath.Join(snapshotArchDir, "configs")
noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
includeDir := filepath.Join(snapshotArchDir, "include")
// set of notice files copied.
noticeBuilt := make(map[string]bool)
// paths of VNDK modules for GPL license checking
modulePaths := make(map[string]string)
// actual module names of .so files
// e.g. moduleNames["libprotobuf-cpp-full-3.9.1.so"] = "libprotobuf-cpp-full"
moduleNames := make(map[string]string)
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
targetArch := "arch-" + m.Target().Arch.ArchType.String()
if m.Target().Arch.ArchVariant != "" {
targetArch += "-" + m.Target().Arch.ArchVariant
}
libPath := m.outputFile.Path()
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base())
ret = append(ret, snapshot.CopyFileRule(pctx, ctx, libPath, snapshotLibOut))
// json struct to export snapshot information
prop := struct {
MinSdkVersion string `json:",omitempty"`
LicenseKinds []string `json:",omitempty"`
LicenseTexts []string `json:",omitempty"`
ExportedDirs []string `json:",omitempty"`
ExportedSystemDirs []string `json:",omitempty"`
ExportedFlags []string `json:",omitempty"`
RelativeInstallPath string `json:",omitempty"`
}{}
prop.LicenseKinds = m.EffectiveLicenseKinds()
prop.LicenseTexts = m.EffectiveLicenseFiles().Strings()
prop.MinSdkVersion = m.MinSdkVersion()
if ctx.Config().VndkSnapshotBuildArtifacts() {
exportedInfo, _ := android.SingletonModuleProvider(ctx, m, FlagExporterInfoProvider)
prop.ExportedFlags = exportedInfo.Flags
prop.ExportedDirs = exportedInfo.IncludeDirs.Strings()
prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings()
prop.RelativeInstallPath = m.RelativeInstallPath()
}
propOut := snapshotLibOut + ".json"
j, err := json.Marshal(prop)
if err != nil {
ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
return nil, false
}
ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
return ret, true
}
ctx.VisitAllModules(func(module android.Module) {
m, ok := module.(*Module)
if !ok || !m.Enabled() {
return
}
apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
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)
if !ok {
return
}
snapshotOutputs = append(snapshotOutputs, libs...)
// These are for generating module_names.txt and module_paths.txt
stem := m.outputFile.Path().Base()
moduleNames[stem] = ctx.ModuleName(m)
modulePaths[stem] = ctx.ModuleDir(m)
for _, notice := range m.EffectiveLicenseFiles() {
if _, ok := noticeBuilt[notice.String()]; !ok {
noticeBuilt[notice.String()] = true
snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
pctx, ctx, notice, filepath.Join(noticeDir, notice.String())))
}
}
if ctx.Config().VndkSnapshotBuildArtifacts() {
headers = append(headers, m.SnapshotHeaders()...)
}
})
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
pctx, ctx, header, filepath.Join(includeDir, header.String())))
}
// install *.libraries.txt except vndkcorevariant.libraries.txt
ctx.VisitAllModules(func(module android.Module) {
m, ok := module.(*vndkLibrariesTxt)
if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt {
return
}
snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
pctx, ctx, m.OutputFile(), filepath.Join(configsDir, m.Name())))
})
/*
module_paths.txt contains paths on which VNDK modules are defined.
e.g.,
libbase.so system/libbase
libc.so bionic/libc
...
*/
snapshotOutputs = append(snapshotOutputs, installMapListFileRule(ctx, modulePaths, filepath.Join(configsDir, "module_paths.txt")))
/*
module_names.txt contains names as which VNDK modules are defined,
because output filename and module name can be different with stem and suffix properties.
e.g.,
libcutils.so libcutils
libprotobuf-cpp-full-3.9.2.so libprotobuf-cpp-full
...
*/
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 {
return snapshotOutputs[i].String() < snapshotOutputs[j].String()
})
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 tr
snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+"_list")
rspFile := snapshotOutputList.ReplaceExtension(ctx, "rsp")
zipRule.Command().
Text("tr").
FlagWithArg("-d ", "\\'").
FlagWithRspFileInputList("< ", rspFile, snapshotOutputs).
FlagWithOutput("> ", snapshotOutputList)
zipRule.Temporary(snapshotOutputList)
zipRule.Command().
BuiltTool("soong_zip").
FlagWithOutput("-o ", zipPath).
FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
FlagWithInput("-l ", snapshotOutputList)
zipRule.Build(zipPath.String(), "vndk snapshot "+zipPath.String())
zipRule.DeleteTemporaryFiles()
c.vndkSnapshotZipFile = android.OptionalPathForPath(zipPath)
}
func getVndkFileName(m *Module) (string, error) {
if library, ok := m.linker.(*libraryDecorator); ok {
return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
@ -833,43 +586,3 @@ func getVndkFileName(m *Module) (string, error) {
}
return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker)
}
func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) {
// Build list of vndk libs as merged & tagged & filter-out(libclang_rt):
// Since each target have different set of libclang_rt.* files,
// keep the common set of files in vndk.libraries.txt
_, llndk := vndkModuleListRemover(llndkLibraries, "libclang_rt.")(ctx)
_, vndkcore := vndkModuleListRemover(vndkCoreLibraries, "libclang_rt.")(ctx)
_, vndksp := vndkSPLibraries(ctx)
_, vndkprivate := vndkPrivateLibraries(ctx)
_, vndkproduct := vndkModuleListRemover(vndkProductLibraries, "libclang_rt.")(ctx)
var merged []string
merged = append(merged, addPrefix(llndk, "LLNDK: ")...)
merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
merged = append(merged, addPrefix(vndkcore, "VNDK-core: ")...)
merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
merged = append(merged, addPrefix(vndkproduct, "VNDK-product: ")...)
c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt")
android.WriteFileRule(ctx, c.vndkLibrariesFile, strings.Join(merged, "\n"))
}
func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
// Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
// they been moved to an apex.
movedToApexLlndkLibraries := make(map[string]bool)
ctx.VisitAllModules(func(module android.Module) {
if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() {
// Skip bionic libs, they are handled in different manner
name := library.implementationModuleName(module.(*Module).BaseModuleName())
if module.(android.ApexModule).DirectlyInAnyApex() && !isBionic(name) {
movedToApexLlndkLibraries[name] = true
}
}
})
ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES",
strings.Join(android.SortedKeys(movedToApexLlndkLibraries), " "))
ctx.Strict("VNDK_LIBRARIES_FILE", c.vndkLibrariesFile.String())
ctx.Strict("SOONG_VNDK_SNAPSHOT_ZIP", c.vndkSnapshotZipFile.String())
}

View file

@ -9,16 +9,13 @@ bootstrap_go_package {
"blueprint",
"soong",
"soong-android",
"soong-snapshot",
],
srcs: [
"prebuilt_etc.go",
"snapshot_etc.go",
"install_symlink.go",
],
testSrcs: [
"prebuilt_etc_test.go",
"snapshot_etc_test.go",
"install_symlink_test.go",
],
pluginFor: ["soong_build"],

View file

@ -28,7 +28,6 @@ package etc
// various `prebuilt_*` mutators.
import (
"encoding/json"
"fmt"
"path/filepath"
"strings"
@ -36,7 +35,6 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/snapshot"
)
var pctx = android.NewPackageContext("android/soong/etc")
@ -46,7 +44,6 @@ var pctx = android.NewPackageContext("android/soong/etc")
func init() {
pctx.Import("android/soong/android")
RegisterPrebuiltEtcBuildComponents(android.InitRegistrationContext)
snapshot.RegisterSnapshotAction(generatePrebuiltSnapshot)
}
func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) {
@ -142,9 +139,6 @@ type PrebuiltEtc struct {
android.ModuleBase
android.DefaultableModuleBase
snapshot.VendorSnapshotModuleInterface
snapshot.RecoverySnapshotModuleInterface
properties prebuiltEtcProperties
subdirProperties prebuiltSubdirProperties
@ -305,14 +299,6 @@ func (p *PrebuiltEtc) InVendor() bool {
return p.ModuleBase.InstallInVendor()
}
func (p *PrebuiltEtc) ExcludeFromVendorSnapshot() bool {
return false
}
func (p *PrebuiltEtc) ExcludeFromRecoverySnapshot() bool {
return false
}
func (p *PrebuiltEtc) installBaseDir(ctx android.ModuleContext) string {
// If soc install dir was specified and SOC specific is set, set the installDirPath to the
// specified socInstallDirBase.
@ -686,121 +672,3 @@ func PrebuiltRFSAFactory() android.Module {
android.InitDefaultableModule(module)
return module
}
// Copy file into the snapshot
func copyFile(ctx android.SingletonContext, path android.Path, out string, fake bool) android.OutputPath {
if fake {
// Create empty file instead for the fake snapshot
return snapshot.WriteStringToFileRule(ctx, "", out)
} else {
return snapshot.CopyFileRule(pctx, ctx, path, out)
}
}
// Check if the module is target of the snapshot
func isSnapshotAware(ctx android.SingletonContext, m *PrebuiltEtc, image snapshot.SnapshotImage) bool {
if !m.Enabled() {
return false
}
// Skip if the module is not included in the image
if !image.InImage(m)() {
return false
}
// When android/prebuilt.go selects between source and prebuilt, it sets
// HideFromMake on the other one to avoid duplicate install rules in make.
if m.IsHideFromMake() {
return false
}
// There are some prebuilt_etc module with multiple definition of same name.
// Check if the target would be included from the build
if !m.ExportedToMake() {
return false
}
// Skip if the module is in the predefined path list to skip
if image.IsProprietaryPath(ctx.ModuleDir(m), ctx.DeviceConfig()) {
return false
}
// Skip if the module should be excluded
if image.ExcludeFromSnapshot(m) || image.ExcludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) {
return false
}
// Skip from other exceptional cases
if m.Target().Os.Class != android.Device {
return false
}
if m.Target().NativeBridge == android.NativeBridgeEnabled {
return false
}
return true
}
func generatePrebuiltSnapshot(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) snapshot.SnapshotPaths {
/*
Snapshot zipped artifacts directory structure for etc modules:
{SNAPSHOT_ARCH}/
arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
etc/
(prebuilt etc files)
arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
etc/
(prebuilt etc files)
NOTICE_FILES/
(notice files)
*/
var snapshotOutputs android.Paths
var snapshotNotices android.Paths
installedNotices := make(map[string]bool)
ctx.VisitAllModules(func(module android.Module) {
m, ok := module.(*PrebuiltEtc)
if !ok {
return
}
if !isSnapshotAware(ctx, m, s.Image) {
return
}
targetArch := "arch-" + m.Target().Arch.ArchType.String()
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "etc", m.BaseModuleName())
outputs, _ := m.OutputFiles("")
for _, output := range outputs {
cp := copyFile(ctx, output, snapshotLibOut, s.Fake)
snapshotOutputs = append(snapshotOutputs, cp)
}
prop := snapshot.SnapshotJsonFlags{}
propOut := snapshotLibOut + ".json"
prop.InitBaseSnapshotProps(m)
prop.RelativeInstallPath = m.SubDir()
if m.properties.Filename != nil {
prop.Filename = *m.properties.Filename
}
j, err := json.Marshal(prop)
if err != nil {
ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
return
}
snapshotOutputs = append(snapshotOutputs, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
for _, notice := range m.EffectiveLicenseFiles() {
if _, ok := installedNotices[notice.String()]; !ok {
installedNotices[notice.String()] = true
snapshotNotices = append(snapshotNotices, notice)
}
}
})
return snapshot.SnapshotPaths{OutputFiles: snapshotOutputs, NoticeFiles: snapshotNotices}
}

View file

@ -1,186 +0,0 @@
// Copyright 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package etc
// This file implements snapshot module of 'prebuilt_etc' type
// 'snapshot_etc' module defines android.PrebuiltInterface so it can be handled
// as prebuilt of 'prebuilt_etc' type.
// Properties of 'snapshot_etc' follows properties from snapshotJsonFlags type
import (
"android/soong/android"
"fmt"
"strings"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
func RegisterSnapshotEtcModule(ctx android.RegistrationContext) {
ctx.RegisterModuleType("snapshot_etc", SnapshotEtcFactory)
}
func init() {
RegisterSnapshotEtcModule(android.InitRegistrationContext)
}
// snapshot_etc is a prebuilt module type to be installed under etc which is auto-generated by
// development/vendor_snapshot/update.py. This module will override prebuilt_etc module with same
// name when 'prefer' property is true.
func SnapshotEtcFactory() android.Module {
module := &SnapshotEtc{}
module.AddProperties(&module.properties)
var srcsSupplier = func(_ android.BaseModuleContext, prebuilt android.Module) []string {
s, ok := prebuilt.(*SnapshotEtc)
if !ok || s.properties.Src == nil {
return []string{}
}
return []string{*s.properties.Src}
}
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "src")
return module
}
type snapshotEtcProperties struct {
Src *string `android:"path,arch_variant"` // Source of snapshot_etc file
Filename *string `android:"arch_variant"` // Target file name when it differs from module name
Relative_install_path *string `android:"arch_variant"` // Relative install path when it should be installed subdirectory of etc
}
type SnapshotEtc struct {
android.ModuleBase
prebuilt android.Prebuilt
properties snapshotEtcProperties
outputFilePath android.OutputPath
installDirPath android.InstallPath
}
func (s *SnapshotEtc) Prebuilt() *android.Prebuilt {
return &s.prebuilt
}
func (s *SnapshotEtc) Name() string {
return s.prebuilt.Name(s.BaseModuleName())
}
func (s *SnapshotEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if s.properties.Src == nil {
ctx.PropertyErrorf("src", "missing prebuilt source file")
return
}
sourceFilePath := s.prebuilt.SingleSourcePath(ctx)
// Determine the output file basename.
// If Filename is set, use the name specified by the property.
// Otherwise use the module name.
filename := proptools.String(s.properties.Filename)
if filename == "" {
filename = ctx.ModuleName()
}
s.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
if strings.Contains(filename, "/") {
ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
return
}
subDir := ""
if s.properties.Relative_install_path != nil {
subDir = *s.properties.Relative_install_path
}
s.installDirPath = android.PathForModuleInstall(ctx, "etc", subDir)
// This ensures that outputFilePath has the correct name for others to
// use, as the source file may have a different name.
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Input: sourceFilePath,
Output: s.outputFilePath,
Description: "Install snapshot etc module " + s.BaseModuleName(),
})
ctx.InstallFile(s.installDirPath, s.outputFilePath.Base(), sourceFilePath)
}
func (p *SnapshotEtc) AndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{{
Class: "ETC",
OutputFile: android.OptionalPathForPath(p.outputFilePath),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_MODULE_TAGS", "optional")
entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.String())
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
},
},
}}
}
type snapshotEtcDependencyTag struct {
blueprint.DependencyTag
}
var tag = snapshotEtcDependencyTag{}
func (s *SnapshotEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
return !s.ModuleBase.InstallInRecovery() && !s.ModuleBase.InstallInRamdisk() &&
!s.ModuleBase.InstallInVendorRamdisk() && !s.ModuleBase.InstallInDebugRamdisk()
}
func (p *SnapshotEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return p.ModuleBase.InstallInRamdisk()
}
func (p *SnapshotEtc) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return p.ModuleBase.InstallInVendorRamdisk()
}
func (p *SnapshotEtc) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return p.ModuleBase.InstallInDebugRamdisk()
}
func (p *SnapshotEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return p.ModuleBase.InstallInRecovery()
}
func (p *SnapshotEtc) ExtraImageVariations(ctx android.BaseModuleContext) []string {
return nil
}
func (p *SnapshotEtc) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
}
func (p *SnapshotEtc) ImageMutatorBegin(ctx android.BaseModuleContext) {}
func (p *SnapshotEtc) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":
return android.Paths{p.outputFilePath}, nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
}
var _ android.PrebuiltInterface = (*SnapshotEtc)(nil)
var _ android.ImageInterface = (*SnapshotEtc)(nil)
var _ android.OutputFileProducer = (*SnapshotEtc)(nil)

View file

@ -1,185 +0,0 @@
// Copyright 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package etc
import (
"android/soong/android"
"testing"
"github.com/google/blueprint"
)
var registerSourceModule = func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("source", newSourceModule)
}
type sourceModuleProperties struct {
Deps []string `android:"path,arch_variant"`
}
type sourceModule struct {
android.ModuleBase
android.OverridableModuleBase
properties sourceModuleProperties
dependsOnSourceModule, dependsOnPrebuiltModule bool
deps android.Paths
src android.Path
}
func newSourceModule() android.Module {
m := &sourceModule{}
m.AddProperties(&m.properties)
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibFirst)
android.InitOverridableModule(m, nil)
return m
}
func (s *sourceModule) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
// s.properties.Deps are annotated with android:path, so they are
// automatically added to the dependency by pathDeps mutator
}
func (s *sourceModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
s.deps = android.PathsForModuleSrc(ctx, s.properties.Deps)
s.src = android.PathForModuleSrc(ctx, "source_file")
}
func (s *sourceModule) Srcs() android.Paths {
return android.Paths{s.src}
}
var prepareForSnapshotEtcTest = android.GroupFixturePreparers(
android.PrepareForTestWithArchMutator,
android.PrepareForTestWithPrebuilts,
PrepareForTestWithPrebuiltEtc,
android.FixtureRegisterWithContext(RegisterSnapshotEtcModule),
android.FixtureRegisterWithContext(registerSourceModule),
android.FixtureMergeMockFs(android.MockFS{
"foo.conf": nil,
"bar.conf": nil,
}),
)
func TestSnapshotWithFilename(t *testing.T) {
var androidBp = `
snapshot_etc {
name: "etc_module",
src: "foo.conf",
filename: "bar.conf",
}
`
result := prepareForSnapshotEtcTest.RunTestWithBp(t, androidBp)
for _, variant := range result.ModuleVariantsForTests("etc_module") {
module := result.ModuleForTests("etc_module", variant)
s, ok := module.Module().(*SnapshotEtc)
if !ok {
t.Errorf("Expected snapshot_etc module type")
}
if s.outputFilePath.Base() != "bar.conf" {
t.Errorf("Output file path does not match with specified filename")
}
}
}
func TestSnapshotEtcWithOrigin(t *testing.T) {
var androidBp = `
prebuilt_etc {
name: "etc_module",
src: "foo.conf",
}
snapshot_etc {
name: "etc_module",
src: "bar.conf",
}
source {
name: "source",
deps: [":etc_module"],
}
`
result := prepareForSnapshotEtcTest.RunTestWithBp(t, androidBp)
for _, variant := range result.ModuleVariantsForTests("source") {
source := result.ModuleForTests("source", variant)
result.VisitDirectDeps(source.Module(), func(m blueprint.Module) {
if _, ok := m.(*PrebuiltEtc); !ok {
t.Errorf("Original prebuilt_etc module expected.")
}
})
}
}
func TestSnapshotEtcWithOriginAndPrefer(t *testing.T) {
var androidBp = `
prebuilt_etc {
name: "etc_module",
src: "foo.conf",
}
snapshot_etc {
name: "etc_module",
src: "bar.conf",
prefer: true,
}
source {
name: "source",
deps: [":etc_module"],
}
`
result := prepareForSnapshotEtcTest.RunTestWithBp(t, androidBp)
for _, variant := range result.ModuleVariantsForTests("source") {
source := result.ModuleForTests("source", variant)
result.VisitDirectDeps(source.Module(), func(m blueprint.Module) {
if _, ok := m.(*SnapshotEtc); !ok {
t.Errorf("Preferred snapshot_etc module expected.")
}
})
}
}
func TestSnapshotEtcWithoutOrigin(t *testing.T) {
var androidBp = `
snapshot_etc {
name: "etc_module",
src: "bar.conf",
}
source {
name: "source",
deps: [":etc_module"],
}
`
result := prepareForSnapshotEtcTest.RunTestWithBp(t, androidBp)
for _, variant := range result.ModuleVariantsForTests("source") {
source := result.ModuleForTests("source", variant)
result.VisitDirectDeps(source.Module(), func(m blueprint.Module) {
if _, ok := m.(*SnapshotEtc); !ok {
t.Errorf("Only source snapshot_etc module expected.")
}
})
}
}

View file

@ -12,7 +12,6 @@ bootstrap_go_package {
"soong-bloaty",
"soong-cc",
"soong-rust-config",
"soong-snapshot",
"soong-testing",
],
srcs: [
@ -36,8 +35,6 @@ bootstrap_go_package {
"rust.go",
"sanitize.go",
"source_provider.go",
"snapshot_prebuilt.go",
"snapshot_utils.go",
"strip.go",
"test.go",
"testing.go",

View file

@ -154,11 +154,6 @@ func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.An
})
}
func (library *snapshotLibraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
ctx.SubAndroidMk(ret, library.libraryDecorator)
ret.SubName = library.SnapshotAndroidMkSuffix()
}
func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
ctx.SubAndroidMk(ret, procMacro.baseCompiler)

View file

@ -104,8 +104,6 @@ type libraryDecorator struct {
includeDirs android.Paths
sourceProvider SourceProvider
collectedSnapshotHeaders android.Paths
// table-of-contents file for cdylib crates to optimize out relinking when possible
tocFile android.OptionalPath
}
@ -749,55 +747,3 @@ func LibstdMutator(mctx android.BottomUpMutatorContext) {
}
}
}
func (l *libraryDecorator) snapshotHeaders() android.Paths {
if l.collectedSnapshotHeaders == nil {
panic("snapshotHeaders() must be called after collectHeadersForSnapshot()")
}
return l.collectedSnapshotHeaders
}
// collectHeadersForSnapshot collects all exported headers from library.
// It globs header files in the source tree for exported include directories,
// and tracks generated header files separately.
//
// This is to be called from GenerateAndroidBuildActions, and then collected
// header files can be retrieved by snapshotHeaders().
func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext, deps PathDeps) {
ret := android.Paths{}
// Glob together the headers from the modules include_dirs property
for _, path := range android.CopyOfPaths(l.includeDirs) {
dir := path.String()
globDir := dir + "/**/*"
glob, err := ctx.GlobWithDeps(globDir, nil)
if err != nil {
ctx.ModuleErrorf("glob of %q failed: %s", globDir, err)
return
}
for _, header := range glob {
// Filter out only the files with extensions that are headers.
found := false
for _, ext := range cc.HeaderExts {
if strings.HasSuffix(header, ext) {
found = true
break
}
}
if !found {
continue
}
ret = append(ret, android.PathForSource(ctx, header))
}
}
// Glob together the headers from C dependencies as well, starting with non-generated headers.
ret = append(ret, cc.GlobHeadersForSnapshot(ctx, append(android.CopyOfPaths(deps.depIncludePaths), deps.depSystemIncludePaths...))...)
// Collect generated headers from C dependencies.
ret = append(ret, cc.GlobGeneratedHeadersForSnapshot(ctx, deps.depGeneratedHeaders)...)
// TODO(185577950): If support for generated headers is added, they need to be collected here as well.
l.collectedSnapshotHeaders = ret
}

View file

@ -30,7 +30,6 @@ import (
"android/soong/fuzz"
"android/soong/multitree"
"android/soong/rust/config"
"android/soong/snapshot"
)
var pctx = android.NewPackageContext("android/soong/rust")
@ -971,14 +970,6 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
ctx.CheckbuildFile(mod.docTimestampFile.Path())
}
// glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or
// RECOVERY_SNAPSHOT_VERSION is current.
if lib, ok := mod.compiler.(snapshotLibraryInterface); ok {
if cc.ShouldCollectHeadersForSnapshot(ctx, mod, apexInfo) {
lib.collectHeadersForSnapshot(ctx, deps)
}
}
apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider)
if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) && !mod.ProcMacro() {
// If the module has been specifically configure to not be installed then
@ -1124,6 +1115,11 @@ func (mod *Module) Prebuilt() *android.Prebuilt {
return nil
}
func (mod *Module) Symlinks() []string {
// TODO update this to return the list of symlinks when Rust supports defining symlinks
return nil
}
func rustMakeLibName(ctx android.ModuleContext, c cc.LinkableInterface, dep cc.LinkableInterface, depName string) string {
if rustDep, ok := dep.(*Module); ok {
// Use base module name for snapshots when exporting to Makefile.
@ -1544,7 +1540,6 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
deps := mod.deps(ctx)
var commonDepVariations []blueprint.Variation
var snapshotInfo *cc.SnapshotInfo
apiImportInfo := cc.GetApiImports(mod, actx)
if mod.usePublicApi() || mod.useVendorApi() {
@ -1554,7 +1549,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
}
if ctx.Os() == android.Android {
deps.SharedLibs, _ = cc.RewriteLibs(mod, &snapshotInfo, actx, ctx.Config(), deps.SharedLibs)
deps.SharedLibs, _ = cc.FilterNdkLibs(mod, ctx.Config(), deps.SharedLibs)
}
stdLinkage := "dylib-std"
@ -1573,15 +1568,13 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: rlibVariation})
for _, lib := range deps.Rlibs {
depTag := rlibDepTag
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
actx.AddVariationDependencies(rlibDepVariations, depTag, lib)
}
// dylibs
dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation})
for _, lib := range deps.Dylibs {
addDylibDependency(actx, lib, mod, &snapshotInfo, dylibDepVariations, dylibDepTag)
actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib)
}
// rustlibs
@ -1591,7 +1584,8 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
autoDep := mod.compiler.(autoDeppable).autoDep(ctx)
if autoDep.depTag == rlibDepTag {
// Handle the rlib deptag case
addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
actx.AddVariationDependencies(rlibDepVariations, rlibDepTag, lib)
} else {
// autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however.
// Check for the existence of the dylib deptag variant. Select it if available,
@ -1599,23 +1593,22 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
autoDepVariations := append(commonDepVariations,
blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation})
replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs)
if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) {
actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib)
if actx.OtherModuleDependencyVariantExists(autoDepVariations, replacementLib) {
addDylibDependency(actx, lib, mod, &snapshotInfo, autoDepVariations, autoDep.depTag)
} else {
// If there's no dylib dependency available, try to add the rlib dependency instead.
addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
actx.AddVariationDependencies(rlibDepVariations, rlibDepTag, lib)
}
}
}
} else if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
for _, lib := range deps.Rustlibs {
replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs)
srcProviderVariations := append(commonDepVariations,
blueprint.Variation{Mutator: "rust_libraries", Variation: "source"})
if actx.OtherModuleDependencyVariantExists(srcProviderVariations, replacementLib) {
if actx.OtherModuleDependencyVariantExists(srcProviderVariations, lib) {
actx.AddVariationDependencies(srcProviderVariations, sourceDepTag, lib)
}
}
@ -1626,13 +1619,13 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
if deps.Stdlibs != nil {
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
for _, lib := range deps.Stdlibs {
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...),
rlibDepTag, lib)
}
} else {
for _, lib := range deps.Stdlibs {
addDylibDependency(actx, lib, mod, &snapshotInfo, dylibDepVariations, dylibDepTag)
actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib)
}
}
}
@ -1657,7 +1650,6 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
for _, lib := range deps.WholeStaticLibs {
depTag := cc.StaticDepTag(true)
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).StaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
@ -1666,7 +1658,6 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
for _, lib := range deps.StaticLibs {
depTag := cc.StaticDepTag(false)
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).StaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
@ -1677,12 +1668,10 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
crtVariations := cc.GetCrtVariations(ctx, mod)
for _, crt := range deps.CrtBegin {
actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag,
cc.GetReplaceModuleName(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag, crt)
}
for _, crt := range deps.CrtEnd {
actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag,
cc.GetReplaceModuleName(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag, crt)
}
if mod.sourceProvider != nil {
@ -1705,17 +1694,6 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
mod.afdo.addDep(ctx, actx)
}
// addRlibDependency will add an rlib dependency, rewriting to the snapshot library if available.
func addRlibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo **cc.SnapshotInfo, variations []blueprint.Variation) {
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, snapshotInfo, actx).Rlibs)
actx.AddVariationDependencies(variations, rlibDepTag, lib)
}
func addDylibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo **cc.SnapshotInfo, variations []blueprint.Variation, depTag dependencyTag) {
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, snapshotInfo, actx).Dylibs)
actx.AddVariationDependencies(variations, depTag, lib)
}
func BeginMutator(ctx android.BottomUpMutatorContext) {
if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() {
mod.beginMutator(ctx)
@ -1747,7 +1725,6 @@ func (mod *Module) disableClippy() {
}
var _ android.HostToolProvider = (*Module)(nil)
var _ snapshot.RelativeInstallPath = (*Module)(nil)
func (mod *Module) HostToolPath() android.OptionalPath {
if !mod.Host() {

View file

@ -267,12 +267,6 @@ func rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
if Bool(mod.sanitize.Properties.Sanitize.Diag.Memtag_heap) {
noteDep = "note_memtag_heap_sync"
}
// If we're using snapshots, redirect to snapshot whenever possible
// TODO(b/178470649): clean manual snapshot redirections
snapshot, _ := android.ModuleProvider(mctx, cc.SnapshotInfoProvider)
if lib, ok := snapshot.StaticLibs[noteDep]; ok {
noteDep = lib
}
depTag := cc.StaticDepTag(true)
variations := append(mctx.Target().Variations(),
blueprint.Variation{Mutator: "link", Variation: "static"})

View file

@ -1,208 +0,0 @@
// Copyright 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package rust
import (
"fmt"
"android/soong/android"
"android/soong/cc"
"github.com/google/blueprint/proptools"
)
type snapshotLibraryDecorator struct {
cc.BaseSnapshotDecorator
*libraryDecorator
properties cc.SnapshotLibraryProperties
sanitizerProperties struct {
SanitizerVariation cc.SanitizerType `blueprint:"mutated"`
//TODO: Library flags for cfi variant when CFI is supported.
//Cfi cc.SnapshotLibraryProperties `android:"arch_variant"`
// Library flags for hwasan variant.
Hwasan cc.SnapshotLibraryProperties `android:"arch_variant"`
}
}
var _ cc.SnapshotSanitizer = (*snapshotLibraryDecorator)(nil)
func (library *snapshotLibraryDecorator) IsSanitizerAvailable(t cc.SanitizerType) bool {
switch t {
//TODO: When CFI is supported, add a check here as well
case cc.Hwasan:
return library.sanitizerProperties.Hwasan.Src != nil
default:
return false
}
}
func (library *snapshotLibraryDecorator) SetSanitizerVariation(t cc.SanitizerType, enabled bool) {
if !enabled || library.IsSanitizerEnabled(t) {
return
}
if !library.IsUnsanitizedVariant() {
panic(fmt.Errorf("snapshot Sanitizer must be one of Cfi or Hwasan but not both"))
}
library.sanitizerProperties.SanitizerVariation = t
}
func (library *snapshotLibraryDecorator) IsSanitizerEnabled(t cc.SanitizerType) bool {
return library.sanitizerProperties.SanitizerVariation == t
}
func (library *snapshotLibraryDecorator) IsUnsanitizedVariant() bool {
//TODO: When CFI is supported, add a check here as well
return !library.IsSanitizerEnabled(cc.Hwasan)
}
func init() {
registerRustSnapshotModules(android.InitRegistrationContext)
}
func (mod *Module) IsSnapshotSanitizerAvailable(t cc.SanitizerType) bool {
if ss, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
return ss.IsSanitizerAvailable(t)
}
return false
}
func (mod *Module) SetSnapshotSanitizerVariation(t cc.SanitizerType, enabled bool) {
if ss, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
ss.SetSanitizerVariation(t, enabled)
} else {
panic(fmt.Errorf("Calling SetSnapshotSanitizerVariation on a non-snapshotLibraryDecorator: %s", mod.Name()))
}
}
func (mod *Module) IsSnapshotUnsanitizedVariant() bool {
if ss, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
return ss.IsUnsanitizedVariant()
}
return false
}
func (mod *Module) IsSnapshotSanitizer() bool {
if _, ok := mod.compiler.(cc.SnapshotSanitizer); ok {
return true
}
return false
}
func registerRustSnapshotModules(ctx android.RegistrationContext) {
cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
"vendor_snapshot_rlib", VendorSnapshotRlibFactory)
cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
"vendor_snapshot_dylib", VendorSnapshotDylibFactory)
cc.RecoverySnapshotImageSingleton.RegisterAdditionalModule(ctx,
"recovery_snapshot_rlib", RecoverySnapshotRlibFactory)
}
func snapshotLibraryFactory(image cc.SnapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {
module, library := NewRustLibrary(android.DeviceSupported)
module.sanitize = nil
library.stripper.StripProperties.Strip.None = proptools.BoolPtr(true)
prebuilt := &snapshotLibraryDecorator{
libraryDecorator: library,
}
module.compiler = prebuilt
prebuilt.Init(module, image, moduleSuffix)
module.AddProperties(
&prebuilt.properties,
&prebuilt.sanitizerProperties,
)
return module, prebuilt
}
func (library *snapshotLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
var variant string
if library.static() {
variant = cc.SnapshotStaticSuffix
} else if library.shared() {
variant = cc.SnapshotSharedSuffix
} else if library.rlib() {
variant = cc.SnapshotRlibSuffix
} else if library.dylib() {
variant = cc.SnapshotDylibSuffix
}
library.SetSnapshotAndroidMkSuffix(ctx, variant)
if library.IsSanitizerEnabled(cc.Hwasan) {
library.properties = library.sanitizerProperties.Hwasan
}
if !library.MatchesWithDevice(ctx.DeviceConfig()) {
return buildOutput{}
}
outputFile := android.PathForModuleSrc(ctx, *library.properties.Src)
library.unstrippedOutputFile = outputFile
return buildOutput{outputFile: outputFile}
}
func (library *snapshotLibraryDecorator) rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath {
return android.OptionalPath{}
}
// vendor_snapshot_rlib is a special prebuilt rlib library which is auto-generated by
// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_rlib
// overrides the vendor variant of the rust rlib library with the same name, if BOARD_VNDK_VERSION
// is set.
func VendorSnapshotRlibFactory() android.Module {
module, prebuilt := snapshotLibraryFactory(cc.VendorSnapshotImageSingleton, cc.SnapshotRlibSuffix)
prebuilt.libraryDecorator.BuildOnlyRlib()
prebuilt.libraryDecorator.setNoStdlibs()
return module.Init()
}
// vendor_snapshot_dylib is a special prebuilt dylib library which is auto-generated by
// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_dylib
// overrides the vendor variant of the rust dylib library with the same name, if BOARD_VNDK_VERSION
// is set.
func VendorSnapshotDylibFactory() android.Module {
module, prebuilt := snapshotLibraryFactory(cc.VendorSnapshotImageSingleton, cc.SnapshotDylibSuffix)
prebuilt.libraryDecorator.BuildOnlyDylib()
prebuilt.libraryDecorator.setNoStdlibs()
return module.Init()
}
func RecoverySnapshotRlibFactory() android.Module {
module, prebuilt := snapshotLibraryFactory(cc.RecoverySnapshotImageSingleton, cc.SnapshotRlibSuffix)
prebuilt.libraryDecorator.BuildOnlyRlib()
prebuilt.libraryDecorator.setNoStdlibs()
return module.Init()
}
func (library *snapshotLibraryDecorator) MatchesWithDevice(config android.DeviceConfig) bool {
arches := config.Arches()
if len(arches) == 0 || arches[0].ArchType.String() != library.Arch() {
return false
}
if library.properties.Src == nil {
return false
}
return true
}
func (library *snapshotLibraryDecorator) IsSnapshotPrebuilt() bool {
return true
}
var _ cc.SnapshotInterface = (*snapshotLibraryDecorator)(nil)

View file

@ -1,81 +0,0 @@
// Copyright 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package rust
import (
"android/soong/android"
)
// 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, deps PathDeps)
// snapshotHeaders should return collected headers by collectHeadersForSnapshot.
// Calling snapshotHeaders before collectHeadersForSnapshot is an error.
snapshotHeaders() android.Paths
}
func (mod *Module) ExcludeFromVendorSnapshot() bool {
return Bool(mod.Properties.Exclude_from_vendor_snapshot)
}
func (mod *Module) ExcludeFromRecoverySnapshot() bool {
return Bool(mod.Properties.Exclude_from_recovery_snapshot)
}
func (mod *Module) IsSnapshotLibrary() bool {
if lib, ok := mod.compiler.(libraryInterface); ok {
return lib.shared() || lib.static() || lib.rlib() || lib.dylib()
}
return false
}
func (mod *Module) SnapshotRuntimeLibs() []string {
// TODO Rust does not yet support a runtime libs notion similar to CC
return []string{}
}
func (mod *Module) SnapshotSharedLibs() []string {
return mod.Properties.SnapshotSharedLibs
}
func (mod *Module) SnapshotStaticLibs() []string {
return mod.Properties.SnapshotStaticLibs
}
func (mod *Module) SnapshotRlibs() []string {
return mod.Properties.SnapshotRlibs
}
func (mod *Module) SnapshotDylibs() []string {
return mod.Properties.SnapshotDylibs
}
func (mod *Module) Symlinks() []string {
// TODO update this to return the list of symlinks when Rust supports defining symlinks
return nil
}
func (m *Module) SnapshotHeaders() android.Paths {
if l, ok := m.compiler.(snapshotLibraryInterface); ok {
return l.snapshotHeaders()
}
return android.Paths{}
}

View file

@ -197,5 +197,4 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel()
})
registerRustSnapshotModules(ctx)
}

View file

@ -20,12 +20,12 @@ import (
"strings"
"android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/cc"
"android/soong/snapshot"
"android/soong/tradefed"
)
@ -535,5 +535,3 @@ func ShTestHostFactory() android.Module {
}
var Bool = proptools.Bool
var _ snapshot.RelativeInstallPath = (*ShBinary)(nil)

View file

@ -16,15 +16,11 @@ bootstrap_go_package {
srcs: [
"host_fake_snapshot.go",
"host_snapshot.go",
"recovery_snapshot.go",
"snapshot.go",
"snapshot_base.go",
"util.go",
"vendor_snapshot.go",
],
testSrcs: [
"host_test.go",
"test.go",
],
pluginFor: ["soong_build"],
}

View file

@ -1,132 +0,0 @@
// Copyright 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package snapshot
import "android/soong/android"
// Interface for modules which can be captured in the recovery snapshot.
type RecoverySnapshotModuleInterface interface {
SnapshotModuleInterfaceBase
InRecovery() bool
ExcludeFromRecoverySnapshot() bool
}
func RecoverySnapshotSingleton() android.Singleton {
return &SnapshotSingleton{
"recovery", // name
"SOONG_RECOVERY_SNAPSHOT_ZIP", // makeVar
android.OptionalPath{}, // snapshotZipFile
RecoverySnapshotImageSingleton, // Image
false, // Fake
}
}
// Determine if a dir under source tree is an SoC-owned proprietary directory based
// on recovery snapshot configuration
// Examples: device/, vendor/
func isRecoveryProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
return RecoverySnapshotSingleton().(*SnapshotSingleton).Image.IsProprietaryPath(dir, deviceConfig)
}
func IsRecoveryProprietaryModule(ctx android.BaseModuleContext) bool {
// Any module in a recovery proprietary path is a recovery proprietary
// module.
if isRecoveryProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
return true
}
// However if the module is not in a recovery proprietary path, it may
// still be a recovery proprietary module. This happens for cc modules
// that are excluded from the recovery snapshot, and it means that the
// vendor has assumed control of the framework-provided module.
if c, ok := ctx.Module().(RecoverySnapshotModuleInterface); ok {
if c.ExcludeFromRecoverySnapshot() {
return true
}
}
return false
}
var RecoverySnapshotImageName = "recovery"
type RecoverySnapshotImage struct{}
func (RecoverySnapshotImage) Init(ctx android.RegistrationContext) {
ctx.RegisterParallelSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
}
func (RecoverySnapshotImage) RegisterAdditionalModule(ctx android.RegistrationContext, name string, factory android.ModuleFactory) {
ctx.RegisterModuleType(name, factory)
}
func (RecoverySnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
// RECOVERY_SNAPSHOT_VERSION must be set to 'current' in order to generate a
// snapshot.
return ctx.DeviceConfig().RecoverySnapshotVersion() == "current"
}
func (RecoverySnapshotImage) InImage(m SnapshotModuleInterfaceBase) func() bool {
r, ok := m.(RecoverySnapshotModuleInterface)
if !ok {
// This module does not support recovery snapshot
return func() bool { return false }
}
return r.InRecovery
}
func (RecoverySnapshotImage) IsProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
return isDirectoryExcluded(dir, deviceConfig.RecoverySnapshotDirsExcludedMap(), deviceConfig.RecoverySnapshotDirsIncludedMap())
}
func (RecoverySnapshotImage) ExcludeFromSnapshot(m SnapshotModuleInterfaceBase) bool {
r, ok := m.(RecoverySnapshotModuleInterface)
if !ok {
// This module does not support recovery snapshot
return true
}
return r.ExcludeFromRecoverySnapshot()
}
func (RecoverySnapshotImage) IsUsingSnapshot(cfg android.DeviceConfig) bool {
recoverySnapshotVersion := cfg.RecoverySnapshotVersion()
return recoverySnapshotVersion != "current" && recoverySnapshotVersion != ""
}
func (RecoverySnapshotImage) TargetSnapshotVersion(cfg android.DeviceConfig) string {
return cfg.RecoverySnapshotVersion()
}
func (RecoverySnapshotImage) ExcludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool {
// If we're using full snapshot, not directed snapshot, capture every module
if !cfg.DirectedRecoverySnapshot() {
return false
}
// Else, checks if name is in RECOVERY_SNAPSHOT_MODULES.
return !cfg.RecoverySnapshotModules()[name]
}
func (RecoverySnapshotImage) ImageName() string {
return RecoverySnapshotImageName
}
var RecoverySnapshotImageSingleton RecoverySnapshotImage
func init() {
RecoverySnapshotImageSingleton.Init(android.InitRegistrationContext)
}

View file

@ -1,146 +0,0 @@
// Copyright 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package snapshot
import (
"path/filepath"
"sort"
"android/soong/android"
)
// This file contains singletons to capture snapshots. This singleton will generate snapshot of each target
// image, and capturing snapshot module will be delegated to each module which implements GenerateSnapshotAction
// function and register with RegisterSnapshotAction.
var pctx = android.NewPackageContext("android/soong/snapshot")
func init() {
pctx.Import("android/soong/android")
}
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
// Implementation of the image interface specific to the image
// associated with this snapshot (e.g., specific to the vendor image,
// recovery image, etc.).
Image SnapshotImage
// Whether this singleton is for fake snapshot or not.
// Fake snapshot is a snapshot whose prebuilt binaries and headers are empty.
// It is much faster to generate, and can be used to inspect dependencies.
Fake bool
}
// The output files to be included in the snapshot.
type SnapshotPaths struct {
// All files to be included in the snapshot
OutputFiles android.Paths
// Notice files of the snapshot output files
NoticeFiles android.Paths
}
// Interface of function to capture snapshot from each module
// Returns snapshot ouputs and notice files.
type GenerateSnapshotAction func(snapshot SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) SnapshotPaths
var snapshotActionList []GenerateSnapshotAction
// Register GenerateSnapshotAction function so it can be called while generating snapshot
func RegisterSnapshotAction(x GenerateSnapshotAction) {
snapshotActionList = append(snapshotActionList, x)
}
func (c *SnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
if !c.Image.shouldGenerateSnapshot(ctx) {
return
}
var snapshotOutputs android.Paths
// Snapshot zipped artifacts will be captured under {SNAPSHOT_ARCH} directory
snapshotDir := c.name + "-snapshot"
if c.Fake {
// If this is a fake snapshot singleton, place all files under fake/ subdirectory to avoid
// collision with real snapshot files
snapshotDir = filepath.Join("fake", snapshotDir)
}
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
installedNotices := make(map[string]bool)
for _, f := range snapshotActionList {
snapshotPaths := f(*c, ctx, snapshotArchDir)
snapshotOutputs = append(snapshotOutputs, snapshotPaths.OutputFiles...)
for _, notice := range snapshotPaths.NoticeFiles {
if _, ok := installedNotices[notice.String()]; !ok {
installedNotices[notice.String()] = true
snapshotOutputs = append(snapshotOutputs, CopyFileRule(
pctx, ctx, notice, filepath.Join(noticeDir, notice.String())))
}
}
}
// All artifacts are ready. Sort them to normalize ninja and then zip.
sort.Slice(snapshotOutputs, func(i, j int) bool {
return snapshotOutputs[i].String() < snapshotOutputs[j].String()
})
zipPath := android.PathForOutput(
ctx,
snapshotDir,
c.name+"-"+ctx.Config().DeviceName()+".zip")
zipRule := android.NewRuleBuilder(pctx, ctx)
// filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
snapshotOutputList := android.PathForOutput(
ctx,
snapshotDir,
c.name+"-"+ctx.Config().DeviceName()+"_list")
rspFile := snapshotOutputList.ReplaceExtension(ctx, "rsp")
zipRule.Command().
Text("tr").
FlagWithArg("-d ", "\\'").
FlagWithRspFileInputList("< ", rspFile, snapshotOutputs).
FlagWithOutput("> ", snapshotOutputList)
zipRule.Temporary(snapshotOutputList)
zipRule.Command().
BuiltTool("soong_zip").
FlagWithOutput("-o ", zipPath).
FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
FlagWithInput("-l ", snapshotOutputList)
zipRule.Build(zipPath.String(), c.name+" snapshot "+zipPath.String())
zipRule.DeleteTemporaryFiles()
c.snapshotZipFile = android.OptionalPathForPath(zipPath)
}
func (c *SnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict(
c.makeVar,
c.snapshotZipFile.String())
}

View file

@ -15,92 +15,12 @@ package snapshot
import (
"android/soong/android"
"path/filepath"
)
// Interface for modules which can be captured in the snapshot.
type SnapshotModuleInterfaceBase interface{}
var pctx = android.NewPackageContext("android/soong/snapshot")
// Defines the specifics of different images to which the snapshot process is applicable, e.g.,
// vendor, recovery, ramdisk.
type SnapshotImage interface {
// Returns true if a snapshot should be generated for this image.
shouldGenerateSnapshot(ctx android.SingletonContext) bool
// 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 SnapshotModuleInterfaceBase) func() 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, deviceConfig) returns true, then the module in dir
// will be built from sources.
IsProprietaryPath(dir string, deviceConfig android.DeviceConfig) 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 SnapshotModuleInterfaceBase) bool
// Returns true if the build is using a snapshot for this image.
IsUsingSnapshot(cfg android.DeviceConfig) bool
// Returns a version of which the snapshot should be used in this target.
// This will only be meaningful when isUsingSnapshot is true.
TargetSnapshotVersion(cfg android.DeviceConfig) string
// Whether to exclude a given module from the directed snapshot or not.
// If the makefile variable DIRECTED_{IMAGE}_SNAPSHOT is true, directed snapshot is turned on,
// and only modules listed in {IMAGE}_SNAPSHOT_MODULES will be captured.
ExcludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool
// Returns target image name
ImageName() string
}
type directoryMap map[string]bool
var (
// Modules under following directories are ignored. They are OEM's and vendor's
// proprietary modules(device/, kernel/, vendor/, and hardware/).
defaultDirectoryExcludedMap = directoryMap{
"device": true,
"hardware": true,
"kernel": true,
"vendor": true,
}
// Modules under following directories are included as they are in AOSP,
// although hardware/ and kernel/ are normally for vendor's own.
defaultDirectoryIncludedMap = directoryMap{
"kernel/configs": true,
"kernel/prebuilts": true,
"kernel/tests": true,
"hardware/interfaces": true,
"hardware/libhardware": true,
"hardware/libhardware_legacy": true,
"hardware/ril": true,
}
)
func isDirectoryExcluded(dir string, excludedMap directoryMap, includedMap directoryMap) bool {
if dir == "." || dir == "/" {
return false
}
if includedMap[dir] {
return false
} else if excludedMap[dir] {
return true
} else if defaultDirectoryIncludedMap[dir] {
return false
} else if defaultDirectoryExcludedMap[dir] {
return true
} else {
return isDirectoryExcluded(filepath.Dir(dir), excludedMap, includedMap)
}
func init() {
pctx.Import("android/soong/android")
}
// This is to be saved as .json files, which is for development/vendor_snapshot/update.py.

View file

@ -1,24 +0,0 @@
// Copyright 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package snapshot
import (
"os"
"testing"
)
func TestMain(m *testing.M) {
os.Exit(m.Run())
}

View file

@ -1,143 +0,0 @@
// Copyright 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package snapshot
import "android/soong/android"
// Interface for modules which can be captured in the vendor snapshot.
type VendorSnapshotModuleInterface interface {
SnapshotModuleInterfaceBase
InVendor() bool
ExcludeFromVendorSnapshot() bool
}
func VendorSnapshotSingleton() android.Singleton {
return &SnapshotSingleton{
"vendor", // name
"SOONG_VENDOR_SNAPSHOT_ZIP", // makeVar
android.OptionalPath{}, // snapshotZipFile
VendorSnapshotImageSingleton, // Image
false, // Fake
}
}
func VendorFakeSnapshotSingleton() android.Singleton {
return &SnapshotSingleton{
"vendor", // name
"SOONG_VENDOR_FAKE_SNAPSHOT_ZIP", // makeVar
android.OptionalPath{}, // snapshotZipFile
VendorSnapshotImageSingleton, // Image
true, // Fake
}
}
// Determine if a dir under source tree is an SoC-owned proprietary directory based
// on vendor snapshot configuration
// Examples: device/, vendor/
func isVendorProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
return VendorSnapshotSingleton().(*SnapshotSingleton).Image.IsProprietaryPath(dir, deviceConfig)
}
func IsVendorProprietaryModule(ctx android.BaseModuleContext) bool {
// Any module in a vendor proprietary path is a vendor proprietary
// module.
if isVendorProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
return true
}
// However if the module is not in a vendor proprietary path, it may
// 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().(VendorSnapshotModuleInterface); ok {
if c.ExcludeFromVendorSnapshot() {
return true
}
}
return false
}
var VendorSnapshotImageName = "vendor"
type VendorSnapshotImage struct{}
func (VendorSnapshotImage) Init(ctx android.RegistrationContext) {
ctx.RegisterParallelSingletonType("vendor-snapshot", VendorSnapshotSingleton)
ctx.RegisterParallelSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
}
func (VendorSnapshotImage) RegisterAdditionalModule(ctx android.RegistrationContext, name string, factory android.ModuleFactory) {
ctx.RegisterModuleType(name, factory)
}
func (VendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
// BOARD_VNDK_VERSION must be set to 'current' in order to generate a snapshot.
return ctx.DeviceConfig().VndkVersion() == "current"
}
func (VendorSnapshotImage) InImage(m SnapshotModuleInterfaceBase) func() bool {
v, ok := m.(VendorSnapshotModuleInterface)
if !ok {
// This module does not support Vendor snapshot
return func() bool { return false }
}
return v.InVendor
}
func (VendorSnapshotImage) IsProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
return isDirectoryExcluded(dir, deviceConfig.VendorSnapshotDirsExcludedMap(), deviceConfig.VendorSnapshotDirsIncludedMap())
}
func (VendorSnapshotImage) ExcludeFromSnapshot(m SnapshotModuleInterfaceBase) bool {
v, ok := m.(VendorSnapshotModuleInterface)
if !ok {
// This module does not support Vendor snapshot
return true
}
return v.ExcludeFromVendorSnapshot()
}
func (VendorSnapshotImage) IsUsingSnapshot(cfg android.DeviceConfig) bool {
vndkVersion := cfg.VndkVersion()
return vndkVersion != "current" && vndkVersion != ""
}
func (VendorSnapshotImage) TargetSnapshotVersion(cfg android.DeviceConfig) string {
return cfg.VndkVersion()
}
// returns true iff a given module SHOULD BE EXCLUDED, false if included
func (VendorSnapshotImage) ExcludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool {
// If we're using full snapshot, not directed snapshot, capture every module
if !cfg.DirectedVendorSnapshot() {
return false
}
// Else, checks if name is in VENDOR_SNAPSHOT_MODULES.
return !cfg.VendorSnapshotModules()[name]
}
func (VendorSnapshotImage) ImageName() string {
return VendorSnapshotImageName
}
var VendorSnapshotImageSingleton VendorSnapshotImage
func init() {
VendorSnapshotImageSingleton.Init(android.InitRegistrationContext)
}