// 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 rust import ( "strings" "testing" "android/soong/android" "android/soong/cc" ) // Test that cc modules can link against vendor_available rust_ffi_rlib/rust_ffi_static libraries. func TestVendorLinkage(t *testing.T) { ctx := testRust(t, ` cc_binary { name: "fizz_vendor_available", static_libs: ["libfoo_vendor_static"], static_rlibs: ["libfoo_vendor"], vendor_available: true, } cc_binary { name: "fizz_soc_specific", static_rlibs: ["libfoo_vendor"], soc_specific: true, } rust_ffi_rlib { name: "libfoo_vendor", crate_name: "foo", srcs: ["foo.rs"], vendor_available: true, } rust_ffi_static { name: "libfoo_vendor_static", crate_name: "foo", srcs: ["foo.rs"], vendor_available: true, } `) vendorBinary := ctx.ModuleForTests("fizz_vendor_available", "android_vendor_arm64_armv8-a").Module().(*cc.Module) if !android.InList("libfoo_vendor_static.vendor", vendorBinary.Properties.AndroidMkStaticLibs) { t.Errorf("vendorBinary should have a dependency on libfoo_vendor_static.vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs) } } // Test that variants which use the vndk emit the appropriate cfg flag. func TestImageCfgFlag(t *testing.T) { ctx := testRust(t, ` rust_ffi_shared { name: "libfoo", crate_name: "foo", srcs: ["foo.rs"], vendor_available: true, product_available: true, } `) vendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Rule("rustc") if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vndk'") { t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"]) } if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vendor'") { t.Errorf("missing \"--cfg 'android_vendor'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"]) } if strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_product'") { t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"]) } product := ctx.ModuleForTests("libfoo", "android_product_arm64_armv8-a_shared").Rule("rustc") if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vndk'") { t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"]) } if strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vendor'") { t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"]) } if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_product'") { t.Errorf("missing \"--cfg 'android_product'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"]) } system := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("rustc") if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vndk'") { t.Errorf("unexpected \"--cfg 'android_vndk'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"]) } if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vendor'") { t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"]) } if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_product'") { t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo system variant, rustcFlags: %#v", product.Args["rustcFlags"]) } } // Test that cc modules can link against vendor_ramdisk_available rust_ffi_rlib and rust_ffi_static libraries. func TestVendorRamdiskLinkage(t *testing.T) { ctx := testRust(t, ` cc_library_shared { name: "libcc_vendor_ramdisk", static_rlibs: ["libfoo_vendor_ramdisk"], static_libs: ["libfoo_static_vendor_ramdisk"], system_shared_libs: [], vendor_ramdisk_available: true, } rust_ffi_rlib { name: "libfoo_vendor_ramdisk", crate_name: "foo", srcs: ["foo.rs"], vendor_ramdisk_available: true, } rust_ffi_static { name: "libfoo_static_vendor_ramdisk", crate_name: "foo", srcs: ["foo.rs"], vendor_ramdisk_available: true, } `) vendorRamdiskLibrary := ctx.ModuleForTests("libcc_vendor_ramdisk", "android_vendor_ramdisk_arm64_armv8-a_shared").Module().(*cc.Module) if !android.InList("libfoo_static_vendor_ramdisk.vendor_ramdisk", vendorRamdiskLibrary.Properties.AndroidMkStaticLibs) { t.Errorf("libcc_vendor_ramdisk should have a dependency on libfoo_static_vendor_ramdisk") } } // Test that prebuilt libraries cannot be made vendor available. func TestForbiddenVendorLinkage(t *testing.T) { testRustError(t, "Rust prebuilt modules not supported for non-system images.", ` rust_prebuilt_library { name: "librust_prebuilt", crate_name: "rust_prebuilt", rlib: { srcs: ["libtest.rlib"], }, dylib: { srcs: ["libtest.so"], }, vendor: true, } `) } func checkInstallPartition(t *testing.T, ctx *android.TestContext, name, variant, expected string) { mod := ctx.ModuleForTests(name, variant).Module().(*Module) partitionDefined := false checkPartition := func(specific bool, partition string) { if specific { if expected != partition && !partitionDefined { // The variant is installed to the 'partition' t.Errorf("%s variant of %q must not be installed to %s partition", variant, name, partition) } partitionDefined = true } else { // The variant is not installed to the 'partition' if expected == partition { t.Errorf("%s variant of %q must be installed to %s partition", variant, name, partition) } } } socSpecific := func(m *Module) bool { return m.SocSpecific() } deviceSpecific := func(m *Module) bool { return m.DeviceSpecific() } productSpecific := func(m *Module) bool { return m.ProductSpecific() || m.productSpecificModuleContext() } systemExtSpecific := func(m *Module) bool { return m.SystemExtSpecific() } checkPartition(socSpecific(mod), "vendor") checkPartition(deviceSpecific(mod), "odm") checkPartition(productSpecific(mod), "product") checkPartition(systemExtSpecific(mod), "system_ext") if !partitionDefined && expected != "system" { t.Errorf("%s variant of %q is expected to be installed to %s partition,"+ " but installed to system partition", variant, name, expected) } } func TestInstallPartition(t *testing.T) { t.Parallel() t.Helper() ctx := testRust(t, ` rust_binary { name: "sample_system", crate_name: "sample", srcs: ["foo.rs"], } rust_binary { name: "sample_system_ext", crate_name: "sample", srcs: ["foo.rs"], system_ext_specific: true, } rust_binary { name: "sample_product", crate_name: "sample", srcs: ["foo.rs"], product_specific: true, } rust_binary { name: "sample_vendor", crate_name: "sample", srcs: ["foo.rs"], vendor: true, } rust_binary { name: "sample_odm", crate_name: "sample", srcs: ["foo.rs"], device_specific: true, } rust_binary { name: "sample_all_available", crate_name: "sample", srcs: ["foo.rs"], vendor_available: true, product_available: true, } `) checkInstallPartition(t, ctx, "sample_system", binaryCoreVariant, "system") checkInstallPartition(t, ctx, "sample_system_ext", binaryCoreVariant, "system_ext") checkInstallPartition(t, ctx, "sample_product", binaryProductVariant, "product") checkInstallPartition(t, ctx, "sample_vendor", binaryVendorVariant, "vendor") checkInstallPartition(t, ctx, "sample_odm", binaryVendorVariant, "odm") checkInstallPartition(t, ctx, "sample_all_available", binaryCoreVariant, "system") }