Adds support for platform vendor_available Rust FFI libraries and binaries to be included in the vendor snapshot. Because rlib and dylibs are not yet in snapshots, libstd cannot be included in a vendor snapshot. As a result, vendor-specific Rust code can't be guaranteed to work with the platform-provided vendor_available modules built with a newer toolchain. For now, a check is added indicating vendor-specific Rust code is unsupported. This changes the linkage for vendor variants of these modules to default to rlib linkage since dylibs cannot be included in the snapshot yet. Bug: 184042776 Test: m nothing # new Soong tests pass Change-Id: I502eaa4bb962eb87ff868fcf49b435f0d2f982e6
266 lines
9.1 KiB
Go
266 lines
9.1 KiB
Go
// 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"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"android/soong/android"
|
|
"android/soong/cc"
|
|
)
|
|
|
|
func TestVendorSnapshotCapture(t *testing.T) {
|
|
bp := `
|
|
rust_ffi {
|
|
name: "librustvendor_available",
|
|
crate_name: "rustvendor_available",
|
|
srcs: ["lib.rs"],
|
|
vendor_available: true,
|
|
include_dirs: ["rust_headers/"],
|
|
}
|
|
|
|
rust_binary {
|
|
name: "vendor_available_bin",
|
|
vendor_available: true,
|
|
srcs: ["srcs/lib.rs"],
|
|
}
|
|
|
|
`
|
|
skipTestIfOsNotSupported(t)
|
|
result := android.GroupFixturePreparers(
|
|
prepareForRustTest,
|
|
rustMockedFiles.AddToFixture(),
|
|
android.FixtureModifyProductVariables(
|
|
func(variables android.FixtureProductVariables) {
|
|
variables.DeviceVndkVersion = StringPtr("current")
|
|
variables.Platform_vndk_version = StringPtr("29")
|
|
},
|
|
),
|
|
).RunTestWithBp(t, bp)
|
|
ctx := result.TestContext
|
|
|
|
// 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")
|
|
cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.so", sharedDir, sharedVariant)
|
|
jsonFiles = append(jsonFiles,
|
|
filepath.Join(sharedDir, "librustvendor_available.so.json"))
|
|
|
|
// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
|
|
staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant)
|
|
staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
|
|
cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.a", staticDir, staticVariant)
|
|
jsonFiles = append(jsonFiles,
|
|
filepath.Join(staticDir, "librustvendor_available.a.json"))
|
|
|
|
// For binary executables, all vendor_available modules are captured.
|
|
if archType == "arm64" {
|
|
binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
|
|
binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
|
|
cc.CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
|
|
jsonFiles = append(jsonFiles,
|
|
filepath.Join(binaryDir, "vendor_available_bin.json"))
|
|
}
|
|
}
|
|
|
|
for _, jsonFile := range jsonFiles {
|
|
// verify all json files exist
|
|
if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
|
|
t.Errorf("%q expected but not found; #%v", jsonFile, jsonFiles)
|
|
}
|
|
}
|
|
|
|
// 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 := `
|
|
rust_ffi_shared {
|
|
name: "librustvendor_available",
|
|
crate_name: "rustvendor_available",
|
|
srcs: ["lib.rs"],
|
|
vendor_available: true,
|
|
}
|
|
|
|
rust_ffi_shared {
|
|
name: "librustvendor_exclude",
|
|
crate_name: "rustvendor_exclude",
|
|
srcs: ["lib.rs"],
|
|
vendor_available: true,
|
|
}
|
|
`
|
|
ctx := testRustVndk(t, bp)
|
|
ctx.Config().TestProductVariables.VendorSnapshotModules = make(map[string]bool)
|
|
ctx.Config().TestProductVariables.VendorSnapshotModules["librustvendor_available"] = true
|
|
ctx.Config().TestProductVariables.DirectedVendorSnapshot = true
|
|
|
|
// 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
|
|
cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librustvendor_available.so.json"))
|
|
|
|
// Excluded modules. Modules not included in the directed vendor snapshot
|
|
// are still include as fake modules.
|
|
cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librustvendor_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)
|
|
}
|
|
}
|
|
}
|
|
|
|
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.
|
|
|
|
// When vendor-specific Rust modules are available, make sure to test
|
|
// that they're excluded by path here. See cc.TestVendorSnapshotExclude
|
|
// for an example.
|
|
|
|
frameworkBp := `
|
|
rust_ffi_shared {
|
|
name: "libinclude",
|
|
crate_name: "include",
|
|
srcs: ["include.rs"],
|
|
vendor_available: true,
|
|
}
|
|
|
|
rust_ffi_shared {
|
|
name: "libexclude",
|
|
crate_name: "exclude",
|
|
srcs: ["exclude.rs"],
|
|
vendor_available: true,
|
|
exclude_from_vendor_snapshot: true,
|
|
}
|
|
|
|
rust_ffi_shared {
|
|
name: "libavailable_exclude",
|
|
crate_name: "available_exclude",
|
|
srcs: ["lib.rs"],
|
|
vendor_available: true,
|
|
exclude_from_vendor_snapshot: true,
|
|
}
|
|
`
|
|
|
|
mockFS := map[string][]byte{
|
|
"framework/Android.bp": []byte(frameworkBp),
|
|
"framework/include.rs": nil,
|
|
"framework/exclude.rs": nil,
|
|
}
|
|
|
|
ctx := testRustVndkFs(t, "", mockFS)
|
|
|
|
// Test an include and exclude framework module.
|
|
cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, vendorVariant)
|
|
cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, vendorVariant)
|
|
cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, vendorVariant)
|
|
|
|
// 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
|
|
cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
|
|
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
|
|
|
|
// Excluded modules
|
|
cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
|
|
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
|
|
cc.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)
|
|
}
|
|
}
|
|
}
|