rust: made-to-order rust staticlibs
Whenever any two Rust static libraries are included as static libraries anywhere in a CC dependency tree, we sometimes get duplicate symbol errors. To avoid this, we no longer directly link multiple rust static libs to CC modules. Instead, we build rust_ffi_rlib modules and produce the actual static library that gets linked against the CC module based on that CC module's full list of Rust rlib dependencies. This introduces a new static_rlibs property for cc modules to define the rust_ffi_rlib dependencies, which are then used to generate the module above. This CL is intended to deprecate rust_ffi_static. It leaves rust_ffi_static and rust_ffi static variants in place until the remaining rust_ffi_static declarations and uses can be removed. In the meantime, rust_ffi_static produces rust_ffi_rlib variants as well to make the transition easier. Bug: 254469782 Test: m # with no changes Test: m libapexsupport # with static_rlibs Test: m libunwindstack # with static_rlibs Test: m netsimd # with static_rlibs, no duplicate symbols Test: m blueprint_tests # New Soong tests Change-Id: I47e27ac967ef0cad46d398ebf59d8275929ae28a
This commit is contained in:
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/google/blueprint"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
"android/soong/rust/config"
|
||||
)
|
||||
|
||||
@@ -118,6 +119,7 @@ type buildOutput struct {
|
||||
|
||||
func init() {
|
||||
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
|
||||
cc.TransformRlibstoStaticlib = TransformRlibstoStaticlib
|
||||
}
|
||||
|
||||
type transformProperties struct {
|
||||
@@ -166,6 +168,48 @@ func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
|
||||
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
|
||||
}
|
||||
|
||||
func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
|
||||
outputFile android.WritablePath) android.Path {
|
||||
|
||||
var rustPathDeps PathDeps
|
||||
var rustFlags Flags
|
||||
|
||||
for _, rlibDep := range deps {
|
||||
rustPathDeps.RLibs = append(rustPathDeps.RLibs, RustLibrary{Path: rlibDep.LibPath, CrateName: rlibDep.CrateName})
|
||||
rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
|
||||
}
|
||||
|
||||
ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
|
||||
toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
|
||||
t := transformProperties{
|
||||
// Crate name can be a predefined value as this is a staticlib and
|
||||
// it does not need to be unique. The crate name is used for name
|
||||
// mangling, but it is mixed with the metadata for that purpose, which we
|
||||
// already set to the module name.
|
||||
crateName: "generated_rust_staticlib",
|
||||
is64Bit: toolchain.Is64Bit(),
|
||||
targetTriple: toolchain.RustTriple(),
|
||||
bootstrap: ccModule.Bootstrap(),
|
||||
inRecovery: ccModule.InRecovery(),
|
||||
inRamdisk: ccModule.InRamdisk(),
|
||||
inVendorRamdisk: ccModule.InVendorRamdisk(),
|
||||
|
||||
// crateType indicates what type of crate to build
|
||||
crateType: "staticlib",
|
||||
|
||||
// synthetic indicates whether this is an actual Rust module or not
|
||||
synthetic: true,
|
||||
}
|
||||
|
||||
rustFlags = CommonDefaultFlags(ctx, toolchain, rustFlags)
|
||||
rustFlags = CommonLibraryCompilerFlags(ctx, rustFlags)
|
||||
rustFlags.GlobalRustFlags = append(rustFlags.GlobalRustFlags, "-C lto=thin")
|
||||
|
||||
rustFlags.EmitXrefs = false
|
||||
|
||||
return transformSrctoCrate(ctx, mainSrc, rustPathDeps, rustFlags, outputFile, t).outputFile
|
||||
}
|
||||
|
||||
func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
|
||||
outputFile android.WritablePath) buildOutput {
|
||||
flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
|
||||
|
@@ -46,6 +46,9 @@ func TestSourceProviderCollision(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCompilationOutputFiles(t *testing.T) {
|
||||
|
||||
// Note: Rustdoc output is produced for the PrimaryModule, so if the variant
|
||||
// order changes, then it may be produced for a different variant.
|
||||
ctx := testRust(t, `
|
||||
rust_library {
|
||||
name: "libfizz_buzz",
|
||||
@@ -125,6 +128,16 @@ func TestCompilationOutputFiles(t *testing.T) {
|
||||
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/rustdoc.timestamp",
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "rust_ffi rlib",
|
||||
moduleName: "librust_ffi",
|
||||
variant: "android_arm64_armv8-a_rlib_rlib-std",
|
||||
expectedFiles: []string{
|
||||
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_rlib_rlib-std/librust_ffi.rlib",
|
||||
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_rlib_rlib-std/librust_ffi.rlib.clippy",
|
||||
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_rlib_rlib-std/meta_lic",
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "rust_ffi shared",
|
||||
moduleName: "librust_ffi",
|
||||
|
@@ -47,7 +47,7 @@ func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps {
|
||||
|
||||
// no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
|
||||
if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() {
|
||||
ctx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}, rlibDepTag, ProfilerBuiltins)
|
||||
ctx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}, {Mutator: "link", Variation: ""}}, rlibDepTag, ProfilerBuiltins)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -120,13 +120,17 @@ func TestCCFuzzDepBundling(t *testing.T) {
|
||||
}
|
||||
cc_fuzz {
|
||||
name: "fuzz_static_libtest",
|
||||
static_rlibs: ["libtest_fuzzing"],
|
||||
}
|
||||
cc_fuzz {
|
||||
name: "fuzz_staticffi_libtest",
|
||||
static_libs: ["libtest_fuzzing"],
|
||||
}
|
||||
|
||||
`)
|
||||
|
||||
fuzz_shared_libtest := ctx.ModuleForTests("fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
|
||||
fuzz_static_libtest := ctx.ModuleForTests("fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
|
||||
fuzz_staticffi_libtest := ctx.ModuleForTests("fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
|
||||
|
||||
if !strings.Contains(fuzz_shared_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
|
||||
t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", fuzz_shared_libtest.FuzzSharedLibraries().String())
|
||||
@@ -134,4 +138,7 @@ func TestCCFuzzDepBundling(t *testing.T) {
|
||||
if !strings.Contains(fuzz_static_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
|
||||
t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_static_libtest.FuzzSharedLibraries().String())
|
||||
}
|
||||
if !strings.Contains(fuzz_staticffi_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
|
||||
t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_rlib ('libcc_transitive_dep'): %#v", fuzz_staticffi_libtest.FuzzSharedLibraries().String())
|
||||
}
|
||||
}
|
||||
|
@@ -22,33 +22,45 @@ import (
|
||||
"android/soong/cc"
|
||||
)
|
||||
|
||||
// Test that cc modules can link against vendor_available rust_ffi_static libraries.
|
||||
// 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",
|
||||
static_libs: ["libfoo_vendor"],
|
||||
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_static {
|
||||
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", "android_vendor_arm64_armv8-a").Module().(*cc.Module)
|
||||
vendorBinary := ctx.ModuleForTests("fizz_vendor_available", "android_vendor_arm64_armv8-a").Module().(*cc.Module)
|
||||
|
||||
if !android.InList("libfoo_vendor.vendor", vendorBinary.Properties.AndroidMkStaticLibs) {
|
||||
t.Errorf("vendorBinary should have a dependency on libfoo_vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs)
|
||||
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_static {
|
||||
rust_ffi_shared {
|
||||
name: "libfoo",
|
||||
crate_name: "foo",
|
||||
srcs: ["foo.rs"],
|
||||
@@ -57,7 +69,7 @@ func TestImageCfgFlag(t *testing.T) {
|
||||
}
|
||||
`)
|
||||
|
||||
vendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_static").Rule("rustc")
|
||||
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"])
|
||||
@@ -69,7 +81,7 @@ func TestImageCfgFlag(t *testing.T) {
|
||||
t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
product := ctx.ModuleForTests("libfoo", "android_product_arm64_armv8-a_static").Rule("rustc")
|
||||
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"])
|
||||
}
|
||||
@@ -80,7 +92,7 @@ func TestImageCfgFlag(t *testing.T) {
|
||||
t.Errorf("missing \"--cfg 'android_product'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
system := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Rule("rustc")
|
||||
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"])
|
||||
}
|
||||
@@ -93,27 +105,34 @@ func TestImageCfgFlag(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
// Test that cc modules can link against vendor_ramdisk_available rust_ffi_static libraries.
|
||||
// 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_static {
|
||||
cc_library_shared {
|
||||
name: "libcc_vendor_ramdisk",
|
||||
static_libs: ["libfoo_vendor_ramdisk"],
|
||||
static_rlibs: ["libfoo_vendor_ramdisk"],
|
||||
static_libs: ["libfoo_static_vendor_ramdisk"],
|
||||
system_shared_libs: [],
|
||||
vendor_ramdisk_available: true,
|
||||
}
|
||||
rust_ffi_static {
|
||||
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_static").Module().(*cc.Module)
|
||||
vendorRamdiskLibrary := ctx.ModuleForTests("libcc_vendor_ramdisk", "android_vendor_ramdisk_arm64_armv8-a_shared").Module().(*cc.Module)
|
||||
|
||||
if !android.InList("libfoo_vendor_ramdisk.vendor_ramdisk", vendorRamdiskLibrary.Properties.AndroidMkStaticLibs) {
|
||||
t.Errorf("libcc_vendor_ramdisk should have a dependency on libfoo_vendor_ramdisk")
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
|
147
rust/library.go
147
rust/library.go
@@ -37,10 +37,15 @@ func init() {
|
||||
android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
|
||||
android.RegisterModuleType("rust_ffi", RustFFIFactory)
|
||||
android.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
|
||||
android.RegisterModuleType("rust_ffi_static", RustFFIStaticFactory)
|
||||
android.RegisterModuleType("rust_ffi_rlib", RustFFIRlibFactory)
|
||||
android.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
|
||||
android.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
|
||||
android.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
|
||||
android.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory)
|
||||
|
||||
// TODO: Remove when all instances of rust_ffi_static have been switched to rust_ffi_rlib
|
||||
// Alias rust_ffi_static to the combined rust_ffi_rlib factory
|
||||
android.RegisterModuleType("rust_ffi_static", RustFFIStaticRlibFactory)
|
||||
android.RegisterModuleType("rust_ffi_host_static", RustFFIStaticRlibHostFactory)
|
||||
}
|
||||
|
||||
type VariantLibraryProperties struct {
|
||||
@@ -104,6 +109,8 @@ type libraryDecorator struct {
|
||||
includeDirs android.Paths
|
||||
sourceProvider SourceProvider
|
||||
|
||||
isFFI bool
|
||||
|
||||
// table-of-contents file for cdylib crates to optimize out relinking when possible
|
||||
tocFile android.OptionalPath
|
||||
}
|
||||
@@ -143,6 +150,8 @@ type libraryInterface interface {
|
||||
BuildOnlyShared()
|
||||
|
||||
toc() android.OptionalPath
|
||||
|
||||
isFFILibrary() bool
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) nativeCoverage() bool {
|
||||
@@ -250,7 +259,7 @@ func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) aut
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
|
||||
if library.static() || library.MutatedProperties.VariantIsStaticStd {
|
||||
if library.static() || library.MutatedProperties.VariantIsStaticStd || (library.rlib() && library.isFFILibrary()) {
|
||||
return RlibLinkage
|
||||
} else if library.baseCompiler.preferRlib() {
|
||||
return RlibLinkage
|
||||
@@ -270,8 +279,8 @@ func RustLibraryFactory() android.Module {
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_ffi produces all FFI variants (rust_ffi_shared and
|
||||
// rust_ffi_static).
|
||||
// rust_ffi produces all FFI variants (rust_ffi_shared, rust_ffi_static, and
|
||||
// rust_ffi_rlib).
|
||||
func RustFFIFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
||||
library.BuildOnlyFFI()
|
||||
@@ -300,14 +309,6 @@ func RustFFISharedFactory() android.Module {
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_ffi_static produces a static library (Rust crate type
|
||||
// "staticlib").
|
||||
func RustFFIStaticFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
||||
library.BuildOnlyStatic()
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_library_host produces all Rust variants for the host
|
||||
// (rust_library_dylib_host and rust_library_rlib_host).
|
||||
func RustLibraryHostFactory() android.Module {
|
||||
@@ -317,7 +318,7 @@ func RustLibraryHostFactory() android.Module {
|
||||
}
|
||||
|
||||
// rust_ffi_host produces all FFI variants for the host
|
||||
// (rust_ffi_static_host and rust_ffi_shared_host).
|
||||
// (rust_ffi_rlib_host, rust_ffi_static_host, and rust_ffi_shared_host).
|
||||
func RustFFIHostFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostSupported)
|
||||
library.BuildOnlyFFI()
|
||||
@@ -340,14 +341,6 @@ func RustLibraryRlibHostFactory() android.Module {
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_ffi_static_host produces a static library for the host (Rust
|
||||
// crate type "staticlib").
|
||||
func RustFFIStaticHostFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostSupported)
|
||||
library.BuildOnlyStatic()
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_ffi_shared_host produces an shared library for the host (Rust
|
||||
// crate type "cdylib").
|
||||
func RustFFISharedHostFactory() android.Module {
|
||||
@@ -356,11 +349,51 @@ func RustFFISharedHostFactory() android.Module {
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_ffi_rlib_host produces an rlib for the host (Rust crate
|
||||
// type "rlib").
|
||||
func RustFFIRlibHostFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostSupported)
|
||||
library.BuildOnlyRlibStatic()
|
||||
|
||||
library.isFFI = true
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_ffi_rlib produces an rlib (Rust crate type "rlib").
|
||||
func RustFFIRlibFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
||||
library.BuildOnlyRlib()
|
||||
|
||||
library.isFFI = true
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_ffi_static produces a staticlib and an rlib variant
|
||||
func RustFFIStaticRlibFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
||||
library.BuildOnlyRlibStatic()
|
||||
|
||||
library.isFFI = true
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_ffi_static_host produces a staticlib and an rlib variant for the host
|
||||
func RustFFIStaticRlibHostFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostSupported)
|
||||
library.BuildOnlyRlibStatic()
|
||||
|
||||
library.isFFI = true
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) BuildOnlyFFI() {
|
||||
library.MutatedProperties.BuildDylib = false
|
||||
library.MutatedProperties.BuildRlib = false
|
||||
// we build rlibs for later static ffi linkage.
|
||||
library.MutatedProperties.BuildRlib = true
|
||||
library.MutatedProperties.BuildShared = true
|
||||
library.MutatedProperties.BuildStatic = true
|
||||
|
||||
library.isFFI = true
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) BuildOnlyRust() {
|
||||
@@ -384,11 +417,21 @@ func (library *libraryDecorator) BuildOnlyRlib() {
|
||||
library.MutatedProperties.BuildStatic = false
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) BuildOnlyRlibStatic() {
|
||||
library.MutatedProperties.BuildDylib = false
|
||||
library.MutatedProperties.BuildRlib = true
|
||||
library.MutatedProperties.BuildShared = false
|
||||
library.MutatedProperties.BuildStatic = true
|
||||
library.isFFI = true
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) BuildOnlyStatic() {
|
||||
library.MutatedProperties.BuildRlib = false
|
||||
library.MutatedProperties.BuildDylib = false
|
||||
library.MutatedProperties.BuildShared = false
|
||||
library.MutatedProperties.BuildStatic = true
|
||||
|
||||
library.isFFI = true
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) BuildOnlyShared() {
|
||||
@@ -396,6 +439,12 @@ func (library *libraryDecorator) BuildOnlyShared() {
|
||||
library.MutatedProperties.BuildDylib = false
|
||||
library.MutatedProperties.BuildStatic = false
|
||||
library.MutatedProperties.BuildShared = true
|
||||
|
||||
library.isFFI = true
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) isFFILibrary() bool {
|
||||
return library.isFFI
|
||||
}
|
||||
|
||||
func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
|
||||
@@ -480,10 +529,11 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) F
|
||||
|
||||
flags = CommonLibraryCompilerFlags(ctx, flags)
|
||||
|
||||
if library.shared() || library.static() {
|
||||
if library.isFFI {
|
||||
library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
|
||||
library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Export_include_dirs)...)
|
||||
}
|
||||
|
||||
if library.shared() {
|
||||
if ctx.Darwin() {
|
||||
flags.LinkFlags = append(
|
||||
@@ -509,6 +559,9 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
|
||||
deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...)
|
||||
}
|
||||
|
||||
// Ensure link dirs are not duplicated
|
||||
deps.linkDirs = android.FirstUniqueStrings(deps.linkDirs)
|
||||
|
||||
// Calculate output filename
|
||||
if library.rlib() {
|
||||
fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix()
|
||||
@@ -564,9 +617,10 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
|
||||
library.flagExporter.exportLinkObjects(deps.linkObjects...)
|
||||
}
|
||||
|
||||
if library.static() || library.shared() {
|
||||
// Since we have FFI rlibs, we need to collect their includes as well
|
||||
if library.static() || library.shared() || library.rlib() {
|
||||
android.SetProvider(ctx, cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
|
||||
IncludeDirs: library.includeDirs,
|
||||
IncludeDirs: android.FirstUniquePaths(library.includeDirs),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -681,6 +735,11 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) {
|
||||
return
|
||||
}
|
||||
|
||||
// Don't produce rlib/dylib/source variants for shared or static variants
|
||||
if library.shared() || library.static() {
|
||||
return
|
||||
}
|
||||
|
||||
var variants []string
|
||||
// The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib)
|
||||
// depend on this variant. It must be the first variant to be declared.
|
||||
@@ -720,6 +779,9 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) {
|
||||
// The source variant does not produce any library.
|
||||
// Disable the compilation steps.
|
||||
v.(*Module).compiler.SetDisabled()
|
||||
case "":
|
||||
// if there's an empty variant, alias it so it is the default variant
|
||||
mctx.AliasVariation("")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -744,20 +806,29 @@ func LibstdMutator(mctx android.BottomUpMutatorContext) {
|
||||
case libraryInterface:
|
||||
// Only create a variant if a library is actually being built.
|
||||
if library.rlib() && !library.sysroot() {
|
||||
variants := []string{"rlib-std", "dylib-std"}
|
||||
modules := mctx.CreateLocalVariations(variants...)
|
||||
// If this is a rust_ffi variant it only needs rlib-std
|
||||
if library.isFFILibrary() {
|
||||
variants := []string{"rlib-std"}
|
||||
modules := mctx.CreateLocalVariations(variants...)
|
||||
rlib := modules[0].(*Module)
|
||||
rlib.compiler.(libraryInterface).setRlibStd()
|
||||
rlib.Properties.RustSubName += RlibStdlibSuffix
|
||||
} else {
|
||||
variants := []string{"rlib-std", "dylib-std"}
|
||||
modules := mctx.CreateLocalVariations(variants...)
|
||||
|
||||
rlib := modules[0].(*Module)
|
||||
dylib := modules[1].(*Module)
|
||||
rlib.compiler.(libraryInterface).setRlibStd()
|
||||
dylib.compiler.(libraryInterface).setDylibStd()
|
||||
if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation {
|
||||
// TODO(b/165791368)
|
||||
// Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib
|
||||
// variants are properly supported.
|
||||
dylib.Disable()
|
||||
rlib := modules[0].(*Module)
|
||||
dylib := modules[1].(*Module)
|
||||
rlib.compiler.(libraryInterface).setRlibStd()
|
||||
dylib.compiler.(libraryInterface).setDylibStd()
|
||||
if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation {
|
||||
// TODO(b/165791368)
|
||||
// Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib
|
||||
// variants are properly supported.
|
||||
dylib.Disable()
|
||||
}
|
||||
rlib.Properties.RustSubName += RlibStdlibSuffix
|
||||
}
|
||||
rlib.Properties.RustSubName += RlibStdlibSuffix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -37,9 +37,10 @@ func TestLibraryVariants(t *testing.T) {
|
||||
}`)
|
||||
|
||||
// Test all variants are being built.
|
||||
libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static").Rule("rustc")
|
||||
libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
|
||||
libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
|
||||
libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static").Rule("rustc")
|
||||
libfooFFIRlib := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
|
||||
libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared").Rule("rustc")
|
||||
|
||||
rlibCrateType := "rlib"
|
||||
@@ -62,6 +63,11 @@ func TestLibraryVariants(t *testing.T) {
|
||||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", staticCrateType, libfooStatic.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Test crate type for FFI rlibs is correct
|
||||
if !strings.Contains(libfooFFIRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) {
|
||||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooFFIRlib.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Test crate type for C shared libraries is correct.
|
||||
if !strings.Contains(libfooShared.Args["rustcFlags"], "crate-type="+sharedCrateType) {
|
||||
t.Errorf("missing crate-type for shared variant, expecting %#v, got rustcFlags: %#v", sharedCrateType, libfooShared.Args["rustcFlags"])
|
||||
@@ -182,15 +188,20 @@ func TestSharedLibraryToc(t *testing.T) {
|
||||
|
||||
func TestStaticLibraryLinkage(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
rust_ffi_static {
|
||||
rust_ffi {
|
||||
name: "libfoo",
|
||||
srcs: ["foo.rs"],
|
||||
crate_name: "foo",
|
||||
}`)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_rlib-std")
|
||||
libfooStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
|
||||
|
||||
if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Static libstd rlib expected to be a dependency of Rust rlib libraries. Rlib deps are: %#v",
|
||||
libfoo.Module().(*Module).Properties.AndroidMkDylibs)
|
||||
}
|
||||
if !android.InList("libstd", libfooStatic.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Static libstd rlib expected to be a dependency of Rust static libraries. Rlib deps are: %#v",
|
||||
libfoo.Module().(*Module).Properties.AndroidMkDylibs)
|
||||
}
|
||||
@@ -198,6 +209,12 @@ func TestStaticLibraryLinkage(t *testing.T) {
|
||||
|
||||
func TestNativeDependencyOfRlib(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
rust_ffi_rlib {
|
||||
name: "libffi_rlib",
|
||||
crate_name: "ffi_rlib",
|
||||
rlibs: ["librust_rlib"],
|
||||
srcs: ["foo.rs"],
|
||||
}
|
||||
rust_ffi_static {
|
||||
name: "libffi_static",
|
||||
crate_name: "ffi_static",
|
||||
@@ -224,10 +241,12 @@ func TestNativeDependencyOfRlib(t *testing.T) {
|
||||
rustRlibRlibStd := ctx.ModuleForTests("librust_rlib", "android_arm64_armv8-a_rlib_rlib-std")
|
||||
rustRlibDylibStd := ctx.ModuleForTests("librust_rlib", "android_arm64_armv8-a_rlib_dylib-std")
|
||||
ffiStatic := ctx.ModuleForTests("libffi_static", "android_arm64_armv8-a_static")
|
||||
ffiRlib := ctx.ModuleForTests("libffi_rlib", "android_arm64_armv8-a_rlib_rlib-std")
|
||||
|
||||
modules := []android.TestingModule{
|
||||
rustRlibRlibStd,
|
||||
rustRlibDylibStd,
|
||||
ffiRlib,
|
||||
ffiStatic,
|
||||
}
|
||||
|
||||
@@ -290,27 +309,28 @@ func TestAutoDeps(t *testing.T) {
|
||||
|
||||
libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std")
|
||||
libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib")
|
||||
libfooFFIRlib := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std")
|
||||
libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static")
|
||||
libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared")
|
||||
|
||||
for _, static := range []android.TestingModule{libfooRlib, libfooStatic} {
|
||||
for _, static := range []android.TestingModule{libfooRlib, libfooStatic, libfooFFIRlib} {
|
||||
if !android.InList("libbar.rlib-std", static.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("libbar not present as rlib dependency in static lib")
|
||||
t.Errorf("libbar not present as rlib dependency in static lib: %s", static.Module().Name())
|
||||
}
|
||||
if android.InList("libbar", static.Module().(*Module).Properties.AndroidMkDylibs) {
|
||||
t.Errorf("libbar present as dynamic dependency in static lib")
|
||||
t.Errorf("libbar present as dynamic dependency in static lib: %s", static.Module().Name())
|
||||
}
|
||||
}
|
||||
|
||||
for _, dyn := range []android.TestingModule{libfooDylib, libfooShared} {
|
||||
if !android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkDylibs) {
|
||||
t.Errorf("libbar not present as dynamic dependency in dynamic lib")
|
||||
t.Errorf("libbar not present as dynamic dependency in dynamic lib: %s", dyn.Module().Name())
|
||||
}
|
||||
if android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("libbar present as rlib dependency in dynamic lib")
|
||||
t.Errorf("libbar present as rlib dependency in dynamic lib: %s", dyn.Module().Name())
|
||||
}
|
||||
if !android.InList("librlib_only", dyn.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("librlib_only should be selected by rustlibs as an rlib.")
|
||||
t.Errorf("librlib_only should be selected by rustlibs as an rlib: %s.", dyn.Module().Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -375,6 +395,7 @@ func TestLibstdLinkage(t *testing.T) {
|
||||
|
||||
libbarShared := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module().(*Module)
|
||||
libbarStatic := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Module().(*Module)
|
||||
libbarFFIRlib := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module)
|
||||
|
||||
// prefer_rlib works the same for both rust_library and rust_ffi, so a single check is sufficient here.
|
||||
libbarRlibStd := ctx.ModuleForTests("libbar.prefer_rlib", "android_arm64_armv8-a_shared").Module().(*Module)
|
||||
@@ -398,6 +419,12 @@ func TestLibstdLinkage(t *testing.T) {
|
||||
if !android.InList("libfoo.rlib-std", libbarStatic.Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Device rust_ffi_static does not link dependent rustlib rlib-std variant")
|
||||
}
|
||||
if !android.InList("libstd", libbarFFIRlib.Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Device rust_ffi_rlib does not link libstd as an rlib")
|
||||
}
|
||||
if !android.InList("libfoo.rlib-std", libbarFFIRlib.Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Device rust_ffi_rlib does not link dependent rustlib rlib-std variant")
|
||||
}
|
||||
if !android.InList("libstd", libbarRlibStd.Properties.AndroidMkRlibs) {
|
||||
t.Errorf("rust_ffi with prefer_rlib does not link libstd as an rlib")
|
||||
}
|
||||
|
@@ -76,6 +76,7 @@ func (procMacro *procMacroDecorator) compile(ctx ModuleContext, flags Flags, dep
|
||||
srcPath := crateRootPath(ctx, procMacro)
|
||||
ret := TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile)
|
||||
procMacro.baseCompiler.unstrippedOutputFile = outputFile
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
59
rust/rust.go
59
rust/rust.go
@@ -158,6 +158,8 @@ type Module struct {
|
||||
sourceProvider SourceProvider
|
||||
subAndroidMkOnce map[SubAndroidMkProvider]bool
|
||||
|
||||
exportedLinkDirs []string
|
||||
|
||||
// Output file to be installed, may be stripped or unstripped.
|
||||
outputFile android.OptionalPath
|
||||
|
||||
@@ -234,8 +236,8 @@ func (mod *Module) SelectedStl() string {
|
||||
|
||||
func (mod *Module) NonCcVariants() bool {
|
||||
if mod.compiler != nil {
|
||||
if _, ok := mod.compiler.(libraryInterface); ok {
|
||||
return false
|
||||
if library, ok := mod.compiler.(libraryInterface); ok {
|
||||
return library.buildRlib() || library.buildDylib()
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName()))
|
||||
@@ -465,6 +467,11 @@ type PathDeps struct {
|
||||
linkDirs []string
|
||||
linkObjects []string
|
||||
|
||||
// exportedLinkDirs are exported linkDirs for direct rlib dependencies to
|
||||
// cc_library_static dependants of rlibs.
|
||||
// Track them separately from linkDirs so superfluous -L flags don't get emitted.
|
||||
exportedLinkDirs []string
|
||||
|
||||
// Used by bindgen modules which call clang
|
||||
depClangFlags []string
|
||||
depIncludePaths android.Paths
|
||||
@@ -477,6 +484,9 @@ type PathDeps struct {
|
||||
// Paths to generated source files
|
||||
SrcDeps android.Paths
|
||||
srcProviderFiles android.Paths
|
||||
|
||||
// Used by Generated Libraries
|
||||
depExportedRlibs []cc.RustRlibDep
|
||||
}
|
||||
|
||||
type RustLibraries []RustLibrary
|
||||
@@ -543,6 +553,10 @@ func (mod *Module) VndkVersion() string {
|
||||
return mod.Properties.VndkVersion
|
||||
}
|
||||
|
||||
func (mod *Module) ExportedCrateLinkDirs() []string {
|
||||
return mod.exportedLinkDirs
|
||||
}
|
||||
|
||||
func (mod *Module) PreventInstall() bool {
|
||||
return mod.Properties.PreventInstall
|
||||
}
|
||||
@@ -657,15 +671,6 @@ func (mod *Module) UnstrippedOutputFile() android.Path {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mod *Module) IncludeDirs() android.Paths {
|
||||
if mod.compiler != nil {
|
||||
if library, ok := mod.compiler.(*libraryDecorator); ok {
|
||||
return library.includeDirs
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("IncludeDirs called on non-library module: %q", mod.BaseModuleName()))
|
||||
}
|
||||
|
||||
func (mod *Module) SetStatic() {
|
||||
if mod.compiler != nil {
|
||||
if library, ok := mod.compiler.(libraryInterface); ok {
|
||||
@@ -914,6 +919,10 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||
}
|
||||
|
||||
deps := mod.depsToPaths(ctx)
|
||||
// Export linkDirs for CC rust generatedlibs
|
||||
mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.exportedLinkDirs...)
|
||||
mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.linkDirs...)
|
||||
|
||||
flags := Flags{
|
||||
Toolchain: toolchain,
|
||||
}
|
||||
@@ -991,6 +1000,9 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||
if ctx.Failed() {
|
||||
return
|
||||
}
|
||||
// Export your own directory as a linkDir
|
||||
mod.exportedLinkDirs = append(mod.exportedLinkDirs, linkPathFromFilePath(mod.OutputFile().Path()))
|
||||
|
||||
}
|
||||
|
||||
ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
|
||||
@@ -1223,7 +1235,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||
return
|
||||
}
|
||||
|
||||
if rustDep, ok := dep.(*Module); ok && !rustDep.CcLibraryInterface() {
|
||||
if rustDep, ok := dep.(*Module); ok && !rustDep.Static() && !rustDep.Shared() {
|
||||
//Handle Rust Modules
|
||||
makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName)
|
||||
|
||||
@@ -1249,9 +1261,16 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||
mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName)
|
||||
mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName))
|
||||
|
||||
// rust_ffi rlibs may export include dirs, so collect those here.
|
||||
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
|
||||
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
|
||||
depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
|
||||
|
||||
case procMacroDepTag:
|
||||
directProcMacroDeps = append(directProcMacroDeps, rustDep)
|
||||
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
|
||||
// proc_macro link dirs need to be exported, so collect those here.
|
||||
depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
|
||||
|
||||
case sourceDepTag:
|
||||
if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
|
||||
@@ -1281,12 +1300,12 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||
directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep)
|
||||
}
|
||||
|
||||
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
|
||||
//Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
|
||||
if depTag != procMacroDepTag {
|
||||
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
|
||||
depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
|
||||
depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
|
||||
depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...)
|
||||
depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
|
||||
}
|
||||
|
||||
if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
|
||||
@@ -1296,6 +1315,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||
lib.exportLinkDirs(linkDir)
|
||||
}
|
||||
}
|
||||
|
||||
if depTag == sourceDepTag {
|
||||
if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() {
|
||||
if _, ok := rustDep.sourceProvider.(*protobufDecorator); ok {
|
||||
@@ -1560,6 +1580,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
||||
}
|
||||
|
||||
rlibDepVariations := commonDepVariations
|
||||
rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""})
|
||||
|
||||
if lib, ok := mod.compiler.(libraryInterface); !ok || !lib.sysroot() {
|
||||
rlibDepVariations = append(rlibDepVariations,
|
||||
@@ -1575,6 +1596,8 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
||||
|
||||
// dylibs
|
||||
dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation})
|
||||
dylibDepVariations = append(dylibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""})
|
||||
|
||||
for _, lib := range deps.Dylibs {
|
||||
actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib)
|
||||
}
|
||||
@@ -1594,7 +1617,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
||||
// otherwise select the rlib variant.
|
||||
autoDepVariations := append(commonDepVariations,
|
||||
blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation})
|
||||
|
||||
autoDepVariations = append(autoDepVariations, blueprint.Variation{Mutator: "link", Variation: ""})
|
||||
if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) {
|
||||
actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib)
|
||||
|
||||
@@ -1609,7 +1632,11 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
||||
for _, lib := range deps.Rustlibs {
|
||||
srcProviderVariations := append(commonDepVariations,
|
||||
blueprint.Variation{Mutator: "rust_libraries", Variation: "source"})
|
||||
srcProviderVariations = append(srcProviderVariations, blueprint.Variation{Mutator: "link", Variation: ""})
|
||||
|
||||
// Only add rustlib dependencies if they're source providers themselves.
|
||||
// This is used to track which crate names need to be added to the source generated
|
||||
// in the rust_protobuf mod.rs.
|
||||
if actx.OtherModuleDependencyVariantExists(srcProviderVariations, lib) {
|
||||
actx.AddVariationDependencies(srcProviderVariations, sourceDepTag, lib)
|
||||
}
|
||||
@@ -1621,7 +1648,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
||||
if deps.Stdlibs != nil {
|
||||
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
|
||||
for _, lib := range deps.Stdlibs {
|
||||
actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...),
|
||||
actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}, {Mutator: "link", Variation: ""}}...),
|
||||
rlibDepTag, lib)
|
||||
}
|
||||
} else {
|
||||
|
@@ -150,15 +150,11 @@ func TestDepsTracking(t *testing.T) {
|
||||
host_supported: true,
|
||||
name: "cc_stubs_dep",
|
||||
}
|
||||
rust_ffi_host_static {
|
||||
cc_library_host_static {
|
||||
name: "libstatic",
|
||||
srcs: ["foo.rs"],
|
||||
crate_name: "static",
|
||||
}
|
||||
rust_ffi_host_static {
|
||||
cc_library_host_static {
|
||||
name: "libwholestatic",
|
||||
srcs: ["foo.rs"],
|
||||
crate_name: "wholestatic",
|
||||
}
|
||||
rust_ffi_host_shared {
|
||||
name: "libshared",
|
||||
@@ -435,6 +431,105 @@ func TestRustAliases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRustRlibs(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
rust_ffi_rlib {
|
||||
name: "libbar",
|
||||
crate_name: "bar",
|
||||
srcs: ["src/lib.rs"],
|
||||
export_include_dirs: ["bar_includes"]
|
||||
}
|
||||
|
||||
rust_ffi_rlib {
|
||||
name: "libfoo",
|
||||
crate_name: "foo",
|
||||
srcs: ["src/lib.rs"],
|
||||
export_include_dirs: ["foo_includes"]
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libcc_shared",
|
||||
srcs:["foo.c"],
|
||||
static_rlibs: ["libbar"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libcc_static",
|
||||
srcs:["foo.c"],
|
||||
static_rlibs: ["libfoo"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "ccBin",
|
||||
srcs:["foo.c"],
|
||||
static_rlibs: ["libbar"],
|
||||
static_libs: ["libcc_static"],
|
||||
}
|
||||
`)
|
||||
|
||||
libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_rlib_rlib-std").Rule("rustc")
|
||||
libcc_shared_rustc := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("rustc")
|
||||
libcc_shared_ld := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("ld")
|
||||
libcc_shared_cc := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("cc")
|
||||
ccbin_rustc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("rustc")
|
||||
ccbin_ld := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("ld")
|
||||
ccbin_cc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("cc")
|
||||
|
||||
if !strings.Contains(libbar.Args["rustcFlags"], "crate-type=rlib") {
|
||||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", "rlib", libbar.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Make sure there's a rustc command, and it's producing a staticlib
|
||||
if !strings.Contains(libcc_shared_rustc.Args["rustcFlags"], "crate-type=staticlib") {
|
||||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v",
|
||||
"staticlib", libcc_shared_rustc.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Make sure the static lib is included in the ld command
|
||||
if !strings.Contains(libcc_shared_ld.Args["libFlags"], "generated_rust_staticlib/liblibcc_shared_rust_staticlib.a") {
|
||||
t.Errorf("missing generated static library in linker step libFlags %#v, libFlags: %#v",
|
||||
"libcc_shared.generated_rust_staticlib.a", libcc_shared_ld.Args["libFlags"])
|
||||
}
|
||||
|
||||
// Make sure the static lib includes are in the cc command
|
||||
if !strings.Contains(libcc_shared_cc.Args["cFlags"], "-Ibar_includes") {
|
||||
t.Errorf("missing rlibs includes, expecting %#v, cFlags: %#v",
|
||||
"-Ibar_includes", libcc_shared_cc.Args["cFlags"])
|
||||
}
|
||||
|
||||
// Make sure there's a rustc command, and it's producing a staticlib
|
||||
if !strings.Contains(ccbin_rustc.Args["rustcFlags"], "crate-type=staticlib") {
|
||||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", "staticlib", ccbin_rustc.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Make sure the static lib is included in the cc command
|
||||
if !strings.Contains(ccbin_ld.Args["libFlags"], "generated_rust_staticlib/libccBin_rust_staticlib.a") {
|
||||
t.Errorf("missing generated static library in linker step libFlags, expecting %#v, libFlags: %#v",
|
||||
"ccBin.generated_rust_staticlib.a", ccbin_ld.Args["libFlags"])
|
||||
}
|
||||
|
||||
// Make sure the static lib includes are in the ld command
|
||||
if !strings.Contains(ccbin_cc.Args["cFlags"], "-Ibar_includes") {
|
||||
t.Errorf("missing rlibs includes, expecting %#v, cFlags: %#v",
|
||||
"-Ibar_includes", ccbin_cc.Args)
|
||||
}
|
||||
|
||||
// Make sure that direct dependencies and indirect dependencies are
|
||||
// propagating correctly to the generated rlib.
|
||||
if !strings.Contains(ccbin_rustc.Args["libFlags"], "--extern foo=") {
|
||||
t.Errorf("Missing indirect dependency libfoo when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
|
||||
}
|
||||
if !strings.Contains(ccbin_rustc.Args["libFlags"], "--extern bar=") {
|
||||
t.Errorf("Missing direct dependency libbar when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
|
||||
}
|
||||
|
||||
// Test indirect includes propagation
|
||||
if !strings.Contains(ccbin_cc.Args["cFlags"], "-Ifoo_includes") {
|
||||
t.Errorf("missing rlibs includes, expecting %#v, cFlags: %#v",
|
||||
"-Ifoo_includes", ccbin_cc.Args)
|
||||
}
|
||||
}
|
||||
|
||||
func assertString(t *testing.T, got, expected string) {
|
||||
t.Helper()
|
||||
if got != expected {
|
||||
|
@@ -49,16 +49,28 @@ var PrepareForIntegrationTestWithRust = android.GroupFixturePreparers(
|
||||
func GatherRequiredDepsForTest() string {
|
||||
bp := `
|
||||
rust_prebuilt_library {
|
||||
name: "libstd",
|
||||
crate_name: "std",
|
||||
rlib: {
|
||||
srcs: ["libstd.rlib"],
|
||||
},
|
||||
dylib: {
|
||||
srcs: ["libstd.so"],
|
||||
},
|
||||
host_supported: true,
|
||||
sysroot: true,
|
||||
name: "libstd",
|
||||
crate_name: "std",
|
||||
rlib: {
|
||||
srcs: ["libstd/libstd.rlib"],
|
||||
},
|
||||
dylib: {
|
||||
srcs: ["libstd/libstd.so"],
|
||||
},
|
||||
host_supported: true,
|
||||
sysroot: true,
|
||||
}
|
||||
rust_prebuilt_library {
|
||||
name: "libcore.sysroot",
|
||||
crate_name: "core",
|
||||
rlib: {
|
||||
srcs: ["libcore/libcore.rlib"],
|
||||
},
|
||||
dylib: {
|
||||
srcs: ["libcore/libcore.so"],
|
||||
},
|
||||
host_supported: true,
|
||||
sysroot: true,
|
||||
}
|
||||
//////////////////////////////
|
||||
// Device module requirements
|
||||
@@ -176,10 +188,12 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
|
||||
ctx.RegisterModuleType("rust_fuzz_host", RustFuzzHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi", RustFFIFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_static", RustFFIStaticFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_rlib", RustFFIRlibFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_static", RustFFIStaticRlibFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host_static", RustFFIStaticRlibHostFactory)
|
||||
ctx.RegisterModuleType("rust_proc_macro", ProcMacroFactory)
|
||||
ctx.RegisterModuleType("rust_protobuf", RustProtobufFactory)
|
||||
ctx.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)
|
||||
|
Reference in New Issue
Block a user