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
diff --git a/rust/library.go b/rust/library.go
index 7e5d4c4..7300001 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -37,10 +37,15 @@
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 @@
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 @@
BuildOnlyShared()
toc() android.OptionalPath
+
+ isFFILibrary() bool
}
func (library *libraryDecorator) nativeCoverage() bool {
@@ -250,7 +259,7 @@
}
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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
}
}
}