You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1504 lines
44 KiB
1504 lines
44 KiB
// Copyright 2021 Google Inc. All rights reserved.
|
|
//
|
|
// 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 (
|
|
"android/soong/android"
|
|
"fmt"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestVendorSnapshotCapture(t *testing.T) {
|
|
bp := `
|
|
cc_library {
|
|
name: "libvndk",
|
|
vendor_available: true,
|
|
product_available: true,
|
|
vndk: {
|
|
enabled: true,
|
|
},
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_library {
|
|
name: "libvendor",
|
|
vendor: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_library {
|
|
name: "libvendor_available",
|
|
vendor_available: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_library_headers {
|
|
name: "libvendor_headers",
|
|
vendor_available: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_binary {
|
|
name: "vendor_bin",
|
|
vendor: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_binary {
|
|
name: "vendor_available_bin",
|
|
vendor_available: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
toolchain_library {
|
|
name: "libb",
|
|
vendor_available: true,
|
|
src: "libb.a",
|
|
}
|
|
|
|
cc_object {
|
|
name: "obj",
|
|
vendor_available: true,
|
|
}
|
|
|
|
cc_library {
|
|
name: "libllndk",
|
|
llndk: {
|
|
symbol_file: "libllndk.map.txt",
|
|
},
|
|
}
|
|
`
|
|
|
|
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
|
|
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
|
|
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
|
|
ctx := testCcWithConfig(t, config)
|
|
|
|
// Check Vendor snapshot output.
|
|
|
|
snapshotDir := "vendor-snapshot"
|
|
snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
|
|
snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
|
|
|
|
var jsonFiles []string
|
|
|
|
for _, arch := range [][]string{
|
|
[]string{"arm64", "armv8-a"},
|
|
[]string{"arm", "armv7-a-neon"},
|
|
} {
|
|
archType := arch[0]
|
|
archVariant := arch[1]
|
|
archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
|
|
|
|
// For shared libraries, only non-VNDK vendor_available modules are captured
|
|
sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
|
|
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
|
|
jsonFiles = append(jsonFiles,
|
|
filepath.Join(sharedDir, "libvendor.so.json"),
|
|
filepath.Join(sharedDir, "libvendor_available.so.json"))
|
|
|
|
// LLNDK modules are not captured
|
|
checkSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant)
|
|
|
|
// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
|
|
// Also cfi variants are captured, except for prebuilts like toolchain_library
|
|
staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant)
|
|
staticCfiVariant := fmt.Sprintf("android_vendor.29_%s_%s_static_cfi", archType, archVariant)
|
|
staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
|
|
jsonFiles = append(jsonFiles,
|
|
filepath.Join(staticDir, "libb.a.json"),
|
|
filepath.Join(staticDir, "libvndk.a.json"),
|
|
filepath.Join(staticDir, "libvndk.cfi.a.json"),
|
|
filepath.Join(staticDir, "libvendor.a.json"),
|
|
filepath.Join(staticDir, "libvendor.cfi.a.json"),
|
|
filepath.Join(staticDir, "libvendor_available.a.json"),
|
|
filepath.Join(staticDir, "libvendor_available.cfi.a.json"))
|
|
|
|
// For binary executables, all vendor:true and vendor_available modules are captured.
|
|
if archType == "arm64" {
|
|
binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
|
|
binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
|
|
checkSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
|
|
jsonFiles = append(jsonFiles,
|
|
filepath.Join(binaryDir, "vendor_bin.json"),
|
|
filepath.Join(binaryDir, "vendor_available_bin.json"))
|
|
}
|
|
|
|
// For header libraries, all vendor:true and vendor_available modules are captured.
|
|
headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
|
|
jsonFiles = append(jsonFiles, filepath.Join(headerDir, "libvendor_headers.json"))
|
|
|
|
// For object modules, all vendor:true and vendor_available modules are captured.
|
|
objectVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
|
|
objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
|
|
checkSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
|
|
jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
|
|
}
|
|
|
|
for _, jsonFile := range jsonFiles {
|
|
// verify all json files exist
|
|
if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
|
|
t.Errorf("%q expected but not found", jsonFile)
|
|
}
|
|
}
|
|
|
|
// fake snapshot should have all outputs in the normal snapshot.
|
|
fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
|
|
for _, output := range snapshotSingleton.AllOutputs() {
|
|
fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
|
|
if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
|
|
t.Errorf("%q expected but not found", fakeOutput)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestVendorSnapshotDirected(t *testing.T) {
|
|
bp := `
|
|
cc_library_shared {
|
|
name: "libvendor",
|
|
vendor: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_library_shared {
|
|
name: "libvendor_available",
|
|
vendor_available: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
genrule {
|
|
name: "libfoo_gen",
|
|
cmd: "",
|
|
out: ["libfoo.so"],
|
|
}
|
|
|
|
cc_prebuilt_library_shared {
|
|
name: "libfoo",
|
|
vendor: true,
|
|
prefer: true,
|
|
srcs: [":libfoo_gen"],
|
|
}
|
|
|
|
cc_library_shared {
|
|
name: "libfoo",
|
|
vendor: true,
|
|
nocrt: true,
|
|
}
|
|
`
|
|
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
|
|
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
|
|
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
|
|
config.TestProductVariables.DirectedVendorSnapshot = true
|
|
config.TestProductVariables.VendorSnapshotModules = make(map[string]bool)
|
|
config.TestProductVariables.VendorSnapshotModules["libvendor"] = true
|
|
config.TestProductVariables.VendorSnapshotModules["libfoo"] = true
|
|
ctx := testCcWithConfig(t, config)
|
|
|
|
// Check Vendor snapshot output.
|
|
|
|
snapshotDir := "vendor-snapshot"
|
|
snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
|
|
snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
|
|
|
|
var includeJsonFiles []string
|
|
|
|
for _, arch := range [][]string{
|
|
[]string{"arm64", "armv8-a"},
|
|
[]string{"arm", "armv7-a-neon"},
|
|
} {
|
|
archType := arch[0]
|
|
archVariant := arch[1]
|
|
archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
|
|
|
|
sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
|
|
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
|
|
|
|
// Included modules
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
|
|
// Check that snapshot captures "prefer: true" prebuilt
|
|
checkSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
|
|
|
|
// Excluded modules. Modules not included in the directed vendor snapshot
|
|
// are still include as fake modules.
|
|
checkSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json"))
|
|
}
|
|
|
|
// Verify that each json file for an included module has a rule.
|
|
for _, jsonFile := range includeJsonFiles {
|
|
if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
|
|
t.Errorf("include json file %q not found", jsonFile)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestVendorSnapshotUse(t *testing.T) {
|
|
frameworkBp := `
|
|
cc_library {
|
|
name: "libvndk",
|
|
vendor_available: true,
|
|
product_available: true,
|
|
vndk: {
|
|
enabled: true,
|
|
},
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_library {
|
|
name: "libvendor",
|
|
vendor: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
}
|
|
|
|
cc_library {
|
|
name: "libvendor_available",
|
|
vendor_available: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
}
|
|
|
|
cc_library {
|
|
name: "lib32",
|
|
vendor: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
compile_multilib: "32",
|
|
}
|
|
|
|
cc_library {
|
|
name: "lib64",
|
|
vendor: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
compile_multilib: "64",
|
|
}
|
|
|
|
cc_library {
|
|
name: "libllndk",
|
|
llndk: {
|
|
symbol_file: "libllndk.map.txt",
|
|
},
|
|
}
|
|
|
|
cc_binary {
|
|
name: "bin",
|
|
vendor: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
}
|
|
|
|
cc_binary {
|
|
name: "bin32",
|
|
vendor: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
compile_multilib: "32",
|
|
}
|
|
`
|
|
|
|
vndkBp := `
|
|
vndk_prebuilt_shared {
|
|
name: "libvndk",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
vendor_available: true,
|
|
product_available: true,
|
|
vndk: {
|
|
enabled: true,
|
|
},
|
|
arch: {
|
|
arm64: {
|
|
srcs: ["libvndk.so"],
|
|
export_include_dirs: ["include/libvndk"],
|
|
},
|
|
arm: {
|
|
srcs: ["libvndk.so"],
|
|
export_include_dirs: ["include/libvndk"],
|
|
},
|
|
},
|
|
}
|
|
|
|
// old snapshot module which has to be ignored
|
|
vndk_prebuilt_shared {
|
|
name: "libvndk",
|
|
version: "26",
|
|
target_arch: "arm64",
|
|
vendor_available: true,
|
|
product_available: true,
|
|
vndk: {
|
|
enabled: true,
|
|
},
|
|
arch: {
|
|
arm64: {
|
|
srcs: ["libvndk.so"],
|
|
export_include_dirs: ["include/libvndk"],
|
|
},
|
|
arm: {
|
|
srcs: ["libvndk.so"],
|
|
export_include_dirs: ["include/libvndk"],
|
|
},
|
|
},
|
|
}
|
|
|
|
// different arch snapshot which has to be ignored
|
|
vndk_prebuilt_shared {
|
|
name: "libvndk",
|
|
version: "31",
|
|
target_arch: "arm",
|
|
vendor_available: true,
|
|
product_available: true,
|
|
vndk: {
|
|
enabled: true,
|
|
},
|
|
arch: {
|
|
arm: {
|
|
srcs: ["libvndk.so"],
|
|
export_include_dirs: ["include/libvndk"],
|
|
},
|
|
},
|
|
}
|
|
|
|
vndk_prebuilt_shared {
|
|
name: "libllndk",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
vendor_available: true,
|
|
product_available: true,
|
|
arch: {
|
|
arm64: {
|
|
srcs: ["libllndk.so"],
|
|
},
|
|
arm: {
|
|
srcs: ["libllndk.so"],
|
|
},
|
|
},
|
|
}
|
|
`
|
|
|
|
vendorProprietaryBp := `
|
|
cc_library {
|
|
name: "libvendor_without_snapshot",
|
|
vendor: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
}
|
|
|
|
cc_library_shared {
|
|
name: "libclient",
|
|
vendor: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
shared_libs: ["libvndk", "libvendor_available", "libllndk"],
|
|
static_libs: ["libvendor", "libvendor_without_snapshot"],
|
|
arch: {
|
|
arm64: {
|
|
shared_libs: ["lib64"],
|
|
},
|
|
arm: {
|
|
shared_libs: ["lib32"],
|
|
},
|
|
},
|
|
srcs: ["client.cpp"],
|
|
}
|
|
|
|
cc_library_shared {
|
|
name: "libclient_cfi",
|
|
vendor: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
system_shared_libs: [],
|
|
static_libs: ["libvendor"],
|
|
sanitize: {
|
|
cfi: true,
|
|
},
|
|
srcs: ["client.cpp"],
|
|
}
|
|
|
|
cc_binary {
|
|
name: "bin_without_snapshot",
|
|
vendor: true,
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "libc++_static",
|
|
system_shared_libs: [],
|
|
static_libs: ["libvndk"],
|
|
srcs: ["bin.cpp"],
|
|
}
|
|
|
|
vendor_snapshot {
|
|
name: "vendor_snapshot",
|
|
version: "31",
|
|
arch: {
|
|
arm64: {
|
|
vndk_libs: [
|
|
"libvndk",
|
|
"libllndk",
|
|
],
|
|
static_libs: [
|
|
"libc++_static",
|
|
"libc++demangle",
|
|
"libunwind",
|
|
"libvendor",
|
|
"libvendor_available",
|
|
"libvndk",
|
|
"lib64",
|
|
],
|
|
shared_libs: [
|
|
"libvendor",
|
|
"libvendor_available",
|
|
"lib64",
|
|
],
|
|
binaries: [
|
|
"bin",
|
|
],
|
|
},
|
|
arm: {
|
|
vndk_libs: [
|
|
"libvndk",
|
|
"libllndk",
|
|
],
|
|
static_libs: [
|
|
"libvendor",
|
|
"libvendor_available",
|
|
"libvndk",
|
|
"lib32",
|
|
],
|
|
shared_libs: [
|
|
"libvendor",
|
|
"libvendor_available",
|
|
"lib32",
|
|
],
|
|
binaries: [
|
|
"bin32",
|
|
],
|
|
},
|
|
}
|
|
}
|
|
|
|
vendor_snapshot_static {
|
|
name: "libvndk",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "both",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "libvndk.a",
|
|
},
|
|
arm: {
|
|
src: "libvndk.a",
|
|
},
|
|
},
|
|
shared_libs: ["libvndk"],
|
|
export_shared_lib_headers: ["libvndk"],
|
|
}
|
|
|
|
vendor_snapshot_shared {
|
|
name: "libvendor",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "both",
|
|
vendor: true,
|
|
shared_libs: [
|
|
"libvendor_without_snapshot",
|
|
"libvendor_available",
|
|
"libvndk",
|
|
],
|
|
arch: {
|
|
arm64: {
|
|
src: "libvendor.so",
|
|
export_include_dirs: ["include/libvendor"],
|
|
},
|
|
arm: {
|
|
src: "libvendor.so",
|
|
export_include_dirs: ["include/libvendor"],
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_static {
|
|
name: "lib32",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "32",
|
|
vendor: true,
|
|
arch: {
|
|
arm: {
|
|
src: "lib32.a",
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_shared {
|
|
name: "lib32",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "32",
|
|
vendor: true,
|
|
arch: {
|
|
arm: {
|
|
src: "lib32.so",
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_static {
|
|
name: "lib64",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "64",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "lib64.a",
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_shared {
|
|
name: "lib64",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "64",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "lib64.so",
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_static {
|
|
name: "libvendor",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "both",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
cfi: {
|
|
src: "libvendor.cfi.a",
|
|
export_include_dirs: ["include/libvendor_cfi"],
|
|
},
|
|
src: "libvendor.a",
|
|
export_include_dirs: ["include/libvendor"],
|
|
},
|
|
arm: {
|
|
cfi: {
|
|
src: "libvendor.cfi.a",
|
|
export_include_dirs: ["include/libvendor_cfi"],
|
|
},
|
|
src: "libvendor.a",
|
|
export_include_dirs: ["include/libvendor"],
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_shared {
|
|
name: "libvendor_available",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "both",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "libvendor_available.so",
|
|
export_include_dirs: ["include/libvendor"],
|
|
},
|
|
arm: {
|
|
src: "libvendor_available.so",
|
|
export_include_dirs: ["include/libvendor"],
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_static {
|
|
name: "libvendor_available",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "both",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "libvendor_available.a",
|
|
export_include_dirs: ["include/libvendor"],
|
|
},
|
|
arm: {
|
|
src: "libvendor_available.so",
|
|
export_include_dirs: ["include/libvendor"],
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_static {
|
|
name: "libc++_static",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "64",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "libc++_static.a",
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_static {
|
|
name: "libc++demangle",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "64",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "libc++demangle.a",
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_static {
|
|
name: "libunwind",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "64",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "libunwind.a",
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_binary {
|
|
name: "bin",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "64",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "bin",
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_binary {
|
|
name: "bin32",
|
|
version: "31",
|
|
target_arch: "arm64",
|
|
compile_multilib: "32",
|
|
vendor: true,
|
|
arch: {
|
|
arm: {
|
|
src: "bin32",
|
|
},
|
|
},
|
|
}
|
|
|
|
// old snapshot module which has to be ignored
|
|
vendor_snapshot_binary {
|
|
name: "bin",
|
|
version: "26",
|
|
target_arch: "arm64",
|
|
compile_multilib: "first",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "bin",
|
|
},
|
|
},
|
|
}
|
|
|
|
// different arch snapshot which has to be ignored
|
|
vendor_snapshot_binary {
|
|
name: "bin",
|
|
version: "31",
|
|
target_arch: "arm",
|
|
compile_multilib: "first",
|
|
vendor: true,
|
|
arch: {
|
|
arm64: {
|
|
src: "bin",
|
|
},
|
|
},
|
|
}
|
|
`
|
|
depsBp := GatherRequiredDepsForTest(android.Android)
|
|
|
|
mockFS := map[string][]byte{
|
|
"deps/Android.bp": []byte(depsBp),
|
|
"framework/Android.bp": []byte(frameworkBp),
|
|
"framework/symbol.txt": nil,
|
|
"vendor/Android.bp": []byte(vendorProprietaryBp),
|
|
"vendor/bin": nil,
|
|
"vendor/bin32": nil,
|
|
"vendor/bin.cpp": nil,
|
|
"vendor/client.cpp": nil,
|
|
"vendor/include/libvndk/a.h": nil,
|
|
"vendor/include/libvendor/b.h": nil,
|
|
"vendor/include/libvendor_cfi/c.h": nil,
|
|
"vendor/libc++_static.a": nil,
|
|
"vendor/libc++demangle.a": nil,
|
|
"vendor/libunwind.a": nil,
|
|
"vendor/libvndk.a": nil,
|
|
"vendor/libvendor.a": nil,
|
|
"vendor/libvendor.cfi.a": nil,
|
|
"vendor/libvendor.so": nil,
|
|
"vendor/lib32.a": nil,
|
|
"vendor/lib32.so": nil,
|
|
"vendor/lib64.a": nil,
|
|
"vendor/lib64.so": nil,
|
|
"vndk/Android.bp": []byte(vndkBp),
|
|
"vndk/include/libvndk/a.h": nil,
|
|
"vndk/libvndk.so": nil,
|
|
"vndk/libllndk.so": nil,
|
|
}
|
|
|
|
config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
|
|
config.TestProductVariables.DeviceVndkVersion = StringPtr("31")
|
|
config.TestProductVariables.Platform_vndk_version = StringPtr("32")
|
|
ctx := CreateTestContext(config)
|
|
ctx.Register()
|
|
|
|
_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "vendor/Android.bp", "vndk/Android.bp"})
|
|
android.FailIfErrored(t, errs)
|
|
_, errs = ctx.PrepareBuildActions(config)
|
|
android.FailIfErrored(t, errs)
|
|
|
|
sharedVariant := "android_vendor.31_arm64_armv8-a_shared"
|
|
staticVariant := "android_vendor.31_arm64_armv8-a_static"
|
|
binaryVariant := "android_vendor.31_arm64_armv8-a"
|
|
|
|
sharedCfiVariant := "android_vendor.31_arm64_armv8-a_shared_cfi"
|
|
staticCfiVariant := "android_vendor.31_arm64_armv8-a_static_cfi"
|
|
|
|
shared32Variant := "android_vendor.31_arm_armv7-a-neon_shared"
|
|
binary32Variant := "android_vendor.31_arm_armv7-a-neon"
|
|
|
|
// libclient uses libvndk.vndk.31.arm64, libvendor.vendor_static.31.arm64, libvendor_without_snapshot
|
|
libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"]
|
|
for _, includeFlags := range []string{
|
|
"-Ivndk/include/libvndk", // libvndk
|
|
"-Ivendor/include/libvendor", // libvendor
|
|
} {
|
|
if !strings.Contains(libclientCcFlags, includeFlags) {
|
|
t.Errorf("flags for libclient must contain %#v, but was %#v.",
|
|
includeFlags, libclientCcFlags)
|
|
}
|
|
}
|
|
|
|
libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"]
|
|
for _, input := range [][]string{
|
|
[]string{sharedVariant, "libvndk.vndk.31.arm64"},
|
|
[]string{sharedVariant, "libllndk.vndk.31.arm64"},
|
|
[]string{staticVariant, "libvendor.vendor_static.31.arm64"},
|
|
[]string{staticVariant, "libvendor_without_snapshot"},
|
|
} {
|
|
outputPaths := getOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
|
|
if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
|
|
t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
|
|
}
|
|
}
|
|
|
|
libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs
|
|
if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib64"}; !reflect.DeepEqual(g, w) {
|
|
t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
|
|
}
|
|
|
|
libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs
|
|
if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot"}; !reflect.DeepEqual(g, w) {
|
|
t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
|
|
}
|
|
|
|
libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs
|
|
if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib32"}; !reflect.DeepEqual(g, w) {
|
|
t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g)
|
|
}
|
|
|
|
// libclient_cfi uses libvendor.vendor_static.31.arm64's cfi variant
|
|
libclientCfiCcFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("cc").Args["cFlags"]
|
|
if !strings.Contains(libclientCfiCcFlags, "-Ivendor/include/libvendor_cfi") {
|
|
t.Errorf("flags for libclient_cfi must contain %#v, but was %#v.",
|
|
"-Ivendor/include/libvendor_cfi", libclientCfiCcFlags)
|
|
}
|
|
|
|
libclientCfiLdFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("ld").Args["libFlags"]
|
|
libvendorCfiOutputPaths := getOutputPaths(ctx, staticCfiVariant, []string{"libvendor.vendor_static.31.arm64"})
|
|
if !strings.Contains(libclientCfiLdFlags, libvendorCfiOutputPaths[0].String()) {
|
|
t.Errorf("libflags for libclientCfi must contain %#v, but was %#v", libvendorCfiOutputPaths[0], libclientCfiLdFlags)
|
|
}
|
|
|
|
// bin_without_snapshot uses libvndk.vendor_static.31.arm64 (which reexports vndk's exported headers)
|
|
binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"]
|
|
if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivndk/include/libvndk") {
|
|
t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.",
|
|
"-Ivendor/include/libvndk", binWithoutSnapshotCcFlags)
|
|
}
|
|
|
|
binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"]
|
|
libVndkStaticOutputPaths := getOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.31.arm64"})
|
|
if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
|
|
t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
|
|
libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
|
|
}
|
|
|
|
// libvendor.so is installed by libvendor.vendor_shared.31.arm64
|
|
ctx.ModuleForTests("libvendor.vendor_shared.31.arm64", sharedVariant).Output("libvendor.so")
|
|
|
|
// lib64.so is installed by lib64.vendor_shared.31.arm64
|
|
ctx.ModuleForTests("lib64.vendor_shared.31.arm64", sharedVariant).Output("lib64.so")
|
|
|
|
// lib32.so is installed by lib32.vendor_shared.31.arm64
|
|
ctx.ModuleForTests("lib32.vendor_shared.31.arm64", shared32Variant).Output("lib32.so")
|
|
|
|
// libvendor_available.so is installed by libvendor_available.vendor_shared.31.arm64
|
|
ctx.ModuleForTests("libvendor_available.vendor_shared.31.arm64", sharedVariant).Output("libvendor_available.so")
|
|
|
|
// libvendor_without_snapshot.so is installed by libvendor_without_snapshot
|
|
ctx.ModuleForTests("libvendor_without_snapshot", sharedVariant).Output("libvendor_without_snapshot.so")
|
|
|
|
// bin is installed by bin.vendor_binary.31.arm64
|
|
ctx.ModuleForTests("bin.vendor_binary.31.arm64", binaryVariant).Output("bin")
|
|
|
|
// bin32 is installed by bin32.vendor_binary.31.arm64
|
|
ctx.ModuleForTests("bin32.vendor_binary.31.arm64", binary32Variant).Output("bin32")
|
|
|
|
// bin_without_snapshot is installed by bin_without_snapshot
|
|
ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
|
|
|
|
// libvendor, libvendor_available and bin don't have vendor.31 variant
|
|
libvendorVariants := ctx.ModuleVariantsForTests("libvendor")
|
|
if inList(sharedVariant, libvendorVariants) {
|
|
t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant)
|
|
}
|
|
|
|
libvendorAvailableVariants := ctx.ModuleVariantsForTests("libvendor_available")
|
|
if inList(sharedVariant, libvendorAvailableVariants) {
|
|
t.Errorf("libvendor_available must not have variant %#v, but it does", sharedVariant)
|
|
}
|
|
|
|
binVariants := ctx.ModuleVariantsForTests("bin")
|
|
if inList(binaryVariant, binVariants) {
|
|
t.Errorf("bin must not have variant %#v, but it does", sharedVariant)
|
|
}
|
|
}
|
|
|
|
func TestVendorSnapshotSanitizer(t *testing.T) {
|
|
bp := `
|
|
vendor_snapshot {
|
|
name: "vendor_snapshot",
|
|
version: "28",
|
|
arch: {
|
|
arm64: {
|
|
static_libs: [
|
|
"libsnapshot",
|
|
"note_memtag_heap_sync",
|
|
],
|
|
},
|
|
},
|
|
}
|
|
vendor_snapshot_static {
|
|
name: "libsnapshot",
|
|
vendor: true,
|
|
target_arch: "arm64",
|
|
version: "28",
|
|
arch: {
|
|
arm64: {
|
|
src: "libsnapshot.a",
|
|
cfi: {
|
|
src: "libsnapshot.cfi.a",
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
vendor_snapshot_static {
|
|
name: "note_memtag_heap_sync",
|
|
vendor: true,
|
|
target_arch: "arm64",
|
|
version: "28",
|
|
arch: {
|
|
arm64: {
|
|
src: "note_memtag_heap_sync.a",
|
|
},
|
|
},
|
|
}
|
|
|
|
cc_test {
|
|
name: "vstest",
|
|
gtest: false,
|
|
vendor: true,
|
|
compile_multilib: "64",
|
|
nocrt: true,
|
|
no_libcrt: true,
|
|
stl: "none",
|
|
static_libs: ["libsnapshot"],
|
|
system_shared_libs: [],
|
|
}
|
|
`
|
|
|
|
mockFS := map[string][]byte{
|
|
"vendor/Android.bp": []byte(bp),
|
|
"vendor/libc++demangle.a": nil,
|
|
"vendor/libsnapshot.a": nil,
|
|
"vendor/libsnapshot.cfi.a": nil,
|
|
"vendor/note_memtag_heap_sync.a": nil,
|
|
}
|
|
|
|
config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
|
|
config.TestProductVariables.DeviceVndkVersion = StringPtr("28")
|
|
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
|
|
ctx := testCcWithConfig(t, config)
|
|
|
|
// Check non-cfi and cfi variant.
|
|
staticVariant := "android_vendor.28_arm64_armv8-a_static"
|
|
staticCfiVariant := "android_vendor.28_arm64_armv8-a_static_cfi"
|
|
|
|
staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticVariant).Module().(*Module)
|
|
assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a")
|
|
|
|
staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticCfiVariant).Module().(*Module)
|
|
assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
|
|
}
|
|
|
|
func assertExcludeFromVendorSnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool) {
|
|
t.Helper()
|
|
m := ctx.ModuleForTests(name, vendorVariant).Module().(*Module)
|
|
if m.ExcludeFromVendorSnapshot() != expected {
|
|
t.Errorf("expected %q ExcludeFromVendorSnapshot to be %t", m.String(), expected)
|
|
}
|
|
}
|
|
|
|
func assertExcludeFromRecoverySnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool) {
|
|
t.Helper()
|
|
m := ctx.ModuleForTests(name, recoveryVariant).Module().(*Module)
|
|
if m.ExcludeFromRecoverySnapshot() != expected {
|
|
t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", m.String(), expected)
|
|
}
|
|
}
|
|
|
|
func TestVendorSnapshotExclude(t *testing.T) {
|
|
|
|
// This test verifies that the exclude_from_vendor_snapshot property
|
|
// makes its way from the Android.bp source file into the module data
|
|
// structure. It also verifies that modules are correctly included or
|
|
// excluded in the vendor snapshot based on their path (framework or
|
|
// vendor) and the exclude_from_vendor_snapshot property.
|
|
|
|
frameworkBp := `
|
|
cc_library_shared {
|
|
name: "libinclude",
|
|
srcs: ["src/include.cpp"],
|
|
vendor_available: true,
|
|
}
|
|
cc_library_shared {
|
|
name: "libexclude",
|
|
srcs: ["src/exclude.cpp"],
|
|
vendor: true,
|
|
exclude_from_vendor_snapshot: true,
|
|
}
|
|
cc_library_shared {
|
|
name: "libavailable_exclude",
|
|
srcs: ["src/exclude.cpp"],
|
|
vendor_available: true,
|
|
exclude_from_vendor_snapshot: true,
|
|
}
|
|
`
|
|
|
|
vendorProprietaryBp := `
|
|
cc_library_shared {
|
|
name: "libvendor",
|
|
srcs: ["vendor.cpp"],
|
|
vendor: true,
|
|
}
|
|
`
|
|
|
|
depsBp := GatherRequiredDepsForTest(android.Android)
|
|
|
|
mockFS := map[string][]byte{
|
|
"deps/Android.bp": []byte(depsBp),
|
|
"framework/Android.bp": []byte(frameworkBp),
|
|
"framework/include.cpp": nil,
|
|
"framework/exclude.cpp": nil,
|
|
"device/Android.bp": []byte(vendorProprietaryBp),
|
|
"device/vendor.cpp": nil,
|
|
}
|
|
|
|
config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
|
|
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
|
|
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
|
|
ctx := CreateTestContext(config)
|
|
ctx.Register()
|
|
|
|
_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
|
|
android.FailIfErrored(t, errs)
|
|
_, errs = ctx.PrepareBuildActions(config)
|
|
android.FailIfErrored(t, errs)
|
|
|
|
// Test an include and exclude framework module.
|
|
assertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false)
|
|
assertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true)
|
|
assertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true)
|
|
|
|
// A vendor module is excluded, but by its path, not the
|
|
// exclude_from_vendor_snapshot property.
|
|
assertExcludeFromVendorSnapshotIs(t, ctx, "libvendor", false)
|
|
|
|
// Verify the content of the vendor snapshot.
|
|
|
|
snapshotDir := "vendor-snapshot"
|
|
snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
|
|
snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
|
|
|
|
var includeJsonFiles []string
|
|
var excludeJsonFiles []string
|
|
|
|
for _, arch := range [][]string{
|
|
[]string{"arm64", "armv8-a"},
|
|
[]string{"arm", "armv7-a-neon"},
|
|
} {
|
|
archType := arch[0]
|
|
archVariant := arch[1]
|
|
archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
|
|
|
|
sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
|
|
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
|
|
|
|
// Included modules
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
|
|
|
|
// Excluded modules
|
|
checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
|
|
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
|
|
checkSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
|
|
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
|
|
checkSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
|
|
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
|
|
}
|
|
|
|
// Verify that each json file for an included module has a rule.
|
|
for _, jsonFile := range includeJsonFiles {
|
|
if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
|
|
t.Errorf("include json file %q not found", jsonFile)
|
|
}
|
|
}
|
|
|
|
// Verify that each json file for an excluded module has no rule.
|
|
for _, jsonFile := range excludeJsonFiles {
|
|
if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
|
|
t.Errorf("exclude json file %q found", jsonFile)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) {
|
|
|
|
// This test verifies that using the exclude_from_vendor_snapshot
|
|
// property on a module in a vendor proprietary path generates an
|
|
// error. These modules are already excluded, so we prohibit using the
|
|
// property in this way, which could add to confusion.
|
|
|
|
vendorProprietaryBp := `
|
|
cc_library_shared {
|
|
name: "libvendor",
|
|
srcs: ["vendor.cpp"],
|
|
vendor: true,
|
|
exclude_from_vendor_snapshot: true,
|
|
}
|
|
`
|
|
|
|
depsBp := GatherRequiredDepsForTest(android.Android)
|
|
|
|
mockFS := map[string][]byte{
|
|
"deps/Android.bp": []byte(depsBp),
|
|
"device/Android.bp": []byte(vendorProprietaryBp),
|
|
"device/vendor.cpp": nil,
|
|
}
|
|
|
|
config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
|
|
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
|
|
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
|
|
ctx := CreateTestContext(config)
|
|
ctx.Register()
|
|
|
|
_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "device/Android.bp"})
|
|
android.FailIfErrored(t, errs)
|
|
|
|
_, errs = ctx.PrepareBuildActions(config)
|
|
android.CheckErrorsAgainstExpectations(t, errs, []string{
|
|
`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
|
|
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
|
|
`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
|
|
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
|
|
`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
|
|
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
|
|
})
|
|
}
|
|
|
|
func TestRecoverySnapshotCapture(t *testing.T) {
|
|
bp := `
|
|
cc_library {
|
|
name: "libvndk",
|
|
vendor_available: true,
|
|
recovery_available: true,
|
|
product_available: true,
|
|
vndk: {
|
|
enabled: true,
|
|
},
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_library {
|
|
name: "librecovery",
|
|
recovery: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_library {
|
|
name: "librecovery_available",
|
|
recovery_available: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_library_headers {
|
|
name: "librecovery_headers",
|
|
recovery_available: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_binary {
|
|
name: "recovery_bin",
|
|
recovery: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_binary {
|
|
name: "recovery_available_bin",
|
|
recovery_available: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
toolchain_library {
|
|
name: "libb",
|
|
recovery_available: true,
|
|
src: "libb.a",
|
|
}
|
|
|
|
cc_object {
|
|
name: "obj",
|
|
recovery_available: true,
|
|
}
|
|
`
|
|
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
|
|
config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
|
|
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
|
|
ctx := testCcWithConfig(t, config)
|
|
|
|
// Check Recovery snapshot output.
|
|
|
|
snapshotDir := "recovery-snapshot"
|
|
snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
|
|
snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
|
|
|
|
var jsonFiles []string
|
|
|
|
for _, arch := range [][]string{
|
|
[]string{"arm64", "armv8-a"},
|
|
} {
|
|
archType := arch[0]
|
|
archVariant := arch[1]
|
|
archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
|
|
|
|
// For shared libraries, only recovery_available modules are captured.
|
|
sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
|
|
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
|
|
jsonFiles = append(jsonFiles,
|
|
filepath.Join(sharedDir, "libvndk.so.json"),
|
|
filepath.Join(sharedDir, "librecovery.so.json"),
|
|
filepath.Join(sharedDir, "librecovery_available.so.json"))
|
|
|
|
// For static libraries, all recovery:true and recovery_available modules are captured.
|
|
staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant)
|
|
staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
|
|
jsonFiles = append(jsonFiles,
|
|
filepath.Join(staticDir, "libb.a.json"),
|
|
filepath.Join(staticDir, "librecovery.a.json"),
|
|
filepath.Join(staticDir, "librecovery_available.a.json"))
|
|
|
|
// For binary executables, all recovery:true and recovery_available modules are captured.
|
|
if archType == "arm64" {
|
|
binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
|
|
binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
|
|
checkSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
|
|
checkSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
|
|
jsonFiles = append(jsonFiles,
|
|
filepath.Join(binaryDir, "recovery_bin.json"),
|
|
filepath.Join(binaryDir, "recovery_available_bin.json"))
|
|
}
|
|
|
|
// For header libraries, all vendor:true and vendor_available modules are captured.
|
|
headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
|
|
jsonFiles = append(jsonFiles, filepath.Join(headerDir, "librecovery_headers.json"))
|
|
|
|
// For object modules, all vendor:true and vendor_available modules are captured.
|
|
objectVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
|
|
objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
|
|
checkSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
|
|
jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
|
|
}
|
|
|
|
for _, jsonFile := range jsonFiles {
|
|
// verify all json files exist
|
|
if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
|
|
t.Errorf("%q expected but not found", jsonFile)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRecoverySnapshotExclude(t *testing.T) {
|
|
// This test verifies that the exclude_from_recovery_snapshot property
|
|
// makes its way from the Android.bp source file into the module data
|
|
// structure. It also verifies that modules are correctly included or
|
|
// excluded in the recovery snapshot based on their path (framework or
|
|
// vendor) and the exclude_from_recovery_snapshot property.
|
|
|
|
frameworkBp := `
|
|
cc_library_shared {
|
|
name: "libinclude",
|
|
srcs: ["src/include.cpp"],
|
|
recovery_available: true,
|
|
}
|
|
cc_library_shared {
|
|
name: "libexclude",
|
|
srcs: ["src/exclude.cpp"],
|
|
recovery: true,
|
|
exclude_from_recovery_snapshot: true,
|
|
}
|
|
cc_library_shared {
|
|
name: "libavailable_exclude",
|
|
srcs: ["src/exclude.cpp"],
|
|
recovery_available: true,
|
|
exclude_from_recovery_snapshot: true,
|
|
}
|
|
`
|
|
|
|
vendorProprietaryBp := `
|
|
cc_library_shared {
|
|
name: "librecovery",
|
|
srcs: ["recovery.cpp"],
|
|
recovery: true,
|
|
}
|
|
`
|
|
|
|
depsBp := GatherRequiredDepsForTest(android.Android)
|
|
|
|
mockFS := map[string][]byte{
|
|
"deps/Android.bp": []byte(depsBp),
|
|
"framework/Android.bp": []byte(frameworkBp),
|
|
"framework/include.cpp": nil,
|
|
"framework/exclude.cpp": nil,
|
|
"device/Android.bp": []byte(vendorProprietaryBp),
|
|
"device/recovery.cpp": nil,
|
|
}
|
|
|
|
config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
|
|
config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
|
|
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
|
|
ctx := CreateTestContext(config)
|
|
ctx.Register()
|
|
|
|
_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
|
|
android.FailIfErrored(t, errs)
|
|
_, errs = ctx.PrepareBuildActions(config)
|
|
android.FailIfErrored(t, errs)
|
|
|
|
// Test an include and exclude framework module.
|
|
assertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false)
|
|
assertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true)
|
|
assertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true)
|
|
|
|
// A recovery module is excluded, but by its path, not the
|
|
// exclude_from_recovery_snapshot property.
|
|
assertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false)
|
|
|
|
// Verify the content of the recovery snapshot.
|
|
|
|
snapshotDir := "recovery-snapshot"
|
|
snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
|
|
snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
|
|
|
|
var includeJsonFiles []string
|
|
var excludeJsonFiles []string
|
|
|
|
for _, arch := range [][]string{
|
|
[]string{"arm64", "armv8-a"},
|
|
} {
|
|
archType := arch[0]
|
|
archVariant := arch[1]
|
|
archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
|
|
|
|
sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
|
|
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
|
|
|
|
// Included modules
|
|
checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
|
|
|
|
// Excluded modules
|
|
checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
|
|
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
|
|
checkSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
|
|
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
|
|
checkSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
|
|
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
|
|
}
|
|
|
|
// Verify that each json file for an included module has a rule.
|
|
for _, jsonFile := range includeJsonFiles {
|
|
if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
|
|
t.Errorf("include json file %q not found", jsonFile)
|
|
}
|
|
}
|
|
|
|
// Verify that each json file for an excluded module has no rule.
|
|
for _, jsonFile := range excludeJsonFiles {
|
|
if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
|
|
t.Errorf("exclude json file %q found", jsonFile)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRecoverySnapshotDirected(t *testing.T) {
|
|
bp := `
|
|
cc_library_shared {
|
|
name: "librecovery",
|
|
recovery: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
cc_library_shared {
|
|
name: "librecovery_available",
|
|
recovery_available: true,
|
|
nocrt: true,
|
|
}
|
|
|
|
genrule {
|
|
name: "libfoo_gen",
|
|
cmd: "",
|
|
out: ["libfoo.so"],
|
|
}
|
|
|
|
cc_prebuilt_library_shared {
|
|
name: "libfoo",
|
|
recovery: true,
|
|
prefer: true,
|
|
srcs: [":libfoo_gen"],
|
|
}
|
|
|
|
cc_library_shared {
|
|
name: "libfoo",
|
|
recovery: true,
|
|
nocrt: true,
|
|
}
|
|
`
|
|
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
|
|
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
|
|
config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
|
|
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
|
|
config.TestProductVariables.DirectedRecoverySnapshot = true
|
|
config.TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
|
|
config.TestProductVariables.RecoverySnapshotModules["librecovery"] = true
|
|
config.TestProductVariables.RecoverySnapshotModules["libfoo"] = true
|
|
ctx := testCcWithConfig(t, config)
|
|
|
|
// Check recovery snapshot output.
|
|
|
|
snapshotDir := "recovery-snapshot"
|
|
snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
|
|
snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
|
|
|
|
var includeJsonFiles []string
|
|
|
|
for _, arch := range [][]string{
|
|
[]string{"arm64", "armv8-a"},
|
|
} {
|
|
archType := arch[0]
|
|
archVariant := arch[1]
|
|
archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
|
|
|
|
sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
|
|
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
|
|
|
|
// Included modules
|
|
checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
|
|
// Check that snapshot captures "prefer: true" prebuilt
|
|
checkSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
|
|
|
|
// Excluded modules. Modules not included in the directed recovery snapshot
|
|
// are still include as fake modules.
|
|
checkSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json"))
|
|
}
|
|
|
|
// Verify that each json file for an included module has a rule.
|
|
for _, jsonFile := range includeJsonFiles {
|
|
if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
|
|
t.Errorf("include json file %q not found", jsonFile)
|
|
}
|
|
}
|
|
}
|