Merge "rust: Propagate MTO libs linked whole through dylibs." into main
diff --git a/rust/library.go b/rust/library.go
index 7f5861f..415785a 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -744,10 +744,16 @@
}
if library.rlib() {
ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedCcRlibDeps...)
+ ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedWholeCcRlibDeps...)
}
android.SetProvider(ctx, cc.FlagExporterInfoProvider, ccExporter)
}
+ if library.dylib() {
+ // reexport whole-static'd dependencies for dylibs.
+ library.flagExporter.wholeRustRlibDeps = append(library.flagExporter.wholeRustRlibDeps, deps.reexportedWholeCcRlibDeps...)
+ }
+
if library.shared() || library.stubs() {
// Optimize out relinking against shared libraries whose interface hasn't changed by
// depending on a table of contents file instead of the library itself.
diff --git a/rust/rust.go b/rust/rust.go
index 713cacc..4eebda3 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -496,8 +496,9 @@
depLinkFlags []string
// track cc static-libs that have Rlib dependencies
- reexportedCcRlibDeps []cc.RustRlibDep
- ccRlibDeps []cc.RustRlibDep
+ reexportedCcRlibDeps []cc.RustRlibDep
+ reexportedWholeCcRlibDeps []cc.RustRlibDep
+ ccRlibDeps []cc.RustRlibDep
// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker
// Both of these are exported and propagate to dependencies.
@@ -555,6 +556,7 @@
staticLibObjects []string
sharedLibObjects []string
wholeStaticLibObjects []string
+ wholeRustRlibDeps []cc.RustRlibDep
}
func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
@@ -584,6 +586,7 @@
StaticLibObjects: flagExporter.staticLibObjects,
WholeStaticLibObjects: flagExporter.wholeStaticLibObjects,
SharedLibPaths: flagExporter.sharedLibObjects,
+ WholeRustRlibDeps: flagExporter.wholeRustRlibDeps,
})
}
@@ -600,6 +603,7 @@
StaticLibObjects []string
WholeStaticLibObjects []string
SharedLibPaths []string
+ WholeRustRlibDeps []cc.RustRlibDep
}
var RustFlagExporterInfoProvider = blueprint.NewProvider[RustFlagExporterInfo]()
@@ -1585,8 +1589,8 @@
directSrcProvidersDeps = append(directSrcProvidersDeps, &dep)
}
+ exportedRustInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider)
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider)
-
//Append the dependencies exported objects, except for proc-macros which target a different arch/OS
if depTag != procMacroDepTag {
depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
@@ -1595,6 +1599,11 @@
depPaths.staticLibObjects = append(depPaths.staticLibObjects, exportedInfo.StaticLibObjects...)
depPaths.wholeStaticLibObjects = append(depPaths.wholeStaticLibObjects, exportedInfo.WholeStaticLibObjects...)
depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
+
+ depPaths.reexportedWholeCcRlibDeps = append(depPaths.reexportedWholeCcRlibDeps, exportedRustInfo.WholeRustRlibDeps...)
+ if !mod.Rlib() {
+ depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedRustInfo.WholeRustRlibDeps...)
+ }
}
if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
@@ -1656,17 +1665,26 @@
}
}
+ exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
if cc.IsWholeStaticLib(depTag) {
// Add whole staticlibs to wholeStaticLibObjects to propagate to Rust all dependents.
depPaths.wholeStaticLibObjects = append(depPaths.wholeStaticLibObjects, ccLibPath.String())
+
+ // We also propagate forward whole-static'd cc staticlibs with rust_ffi_rlib dependencies
+ // We don't need to check a hypothetical exportedRustInfo.WholeRustRlibDeps because we
+ // wouldn't expect a rust_ffi_rlib to be listed in `static_libs` (Soong explicitly disallows this)
+ depPaths.reexportedWholeCcRlibDeps = append(depPaths.reexportedWholeCcRlibDeps, exportedInfo.RustRlibDeps...)
} else {
- // Otherwise add to staticLibObjects, which only propagate through rlibs to their dependents.
+ // If not whole_static, add to staticLibObjects, which only propagate through rlibs to their dependents.
depPaths.staticLibObjects = append(depPaths.staticLibObjects, ccLibPath.String())
+
+ if mod.Rlib() {
+ // rlibs propagate their inherited rust_ffi_rlibs forward.
+ depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
+ }
}
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
-
- exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
@@ -1675,8 +1693,6 @@
if !mod.Rlib() {
// rlibs don't need to build the generated static library, so they don't need to track these.
depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...)
- } else {
- depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
}
directStaticLibDeps = append(directStaticLibDeps, linkableInfo)
@@ -1835,6 +1851,7 @@
depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths)
depPaths.depLinkFlags = android.FirstUniqueStrings(depPaths.depLinkFlags)
depPaths.reexportedCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedCcRlibDeps, cc.EqRustRlibDeps)
+ depPaths.reexportedWholeCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedWholeCcRlibDeps, cc.EqRustRlibDeps)
depPaths.ccRlibDeps = android.FirstUniqueFunc(depPaths.ccRlibDeps, cc.EqRustRlibDeps)
return depPaths
diff --git a/rust/rust_test.go b/rust/rust_test.go
index fbb9947..f634bb5 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -456,6 +456,13 @@
}
rust_ffi_static {
+ name: "libfoo_from_rlib_whole",
+ crate_name: "foo_from_rlib_whole",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["foo_includes"]
+ }
+
+ rust_ffi_static {
name: "libbuzz",
crate_name: "buzz",
srcs: ["src/lib.rs"],
@@ -469,6 +476,13 @@
export_include_dirs: ["buzz_includes"]
}
+ rust_ffi_static {
+ name: "libbuzz_from_rlib_whole",
+ crate_name: "buzz_from_rlib_whole",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["buzz_includes"]
+ }
+
cc_library_shared {
name: "libcc_shared",
srcs:["foo.c"],
@@ -489,6 +503,13 @@
whole_static_libs: ["libfoo_from_rlib"],
}
+ cc_library_static {
+ name: "libcc_whole_static_from_rlib",
+ srcs:["foo.c"],
+ static_libs: ["libbuzz_from_rlib_whole"],
+ whole_static_libs: ["libfoo_from_rlib_whole"],
+ }
+
cc_binary {
name: "ccBin",
srcs:["foo.c"],
@@ -500,6 +521,14 @@
srcs:["src/foo.rs"],
crate_name: "rs",
static_libs: ["libcc_static_from_rlib"],
+ whole_static_libs: ["libcc_whole_static_from_rlib"],
+ }
+
+ rust_library {
+ name: "librs2",
+ srcs:["src/foo.rs"],
+ crate_name: "rs",
+ rustlibs: ["librs"],
}
rust_binary {
@@ -509,7 +538,7 @@
rlibs: ["librs", "libbar"],
static_libs: ["libcc_static"],
}
- `)
+ `)
libbar := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_rlib_rlib-std").Rule("rustc")
libcc_shared_rustc := ctx.ModuleForTests(t, "libcc_shared", "android_arm64_armv8-a_shared").Rule("rustc")
@@ -521,6 +550,10 @@
rustbin_genlib := ctx.ModuleForTests(t, "rsBin", "android_arm64_armv8-a").Output("generated_rust_staticlib/librustlibs.a")
rustbin := ctx.ModuleForTests(t, "rsBin", "android_arm64_armv8-a").Output("unstripped/rsBin")
librs_rlib := ctx.ModuleForTests(t, "librs", "android_arm64_armv8-a_rlib_dylib-std").MaybeOutput("generated_rust_staticlib/librustlibs.a")
+ librs2_rlib := ctx.ModuleForTests(t, "librs2", "android_arm64_armv8-a_rlib_dylib-std").MaybeOutput("generated_rust_staticlib/librustlibs.a")
+ librs_genlib := ctx.ModuleForTests(t, "librs", "android_arm64_armv8-a_dylib").Output("generated_rust_staticlib/librustlibs.a")
+ librs2_genlib := ctx.ModuleForTests(t, "librs2", "android_arm64_armv8-a_dylib").Output("generated_rust_staticlib/librustlibs.a")
+ librs2_dylib := ctx.ModuleForTests(t, "librs2", "android_arm64_armv8-a_dylib").Output("unstripped/librs2.dylib.so")
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"])
@@ -578,6 +611,10 @@
t.Errorf("missing generated static library in linker step libFlags in Rust module, expecting %#v, libFlags: %#v",
"generated_rust_staticlib/librustlibs.a", rustbin.Args["libFlags"])
}
+ if !strings.Contains(librs2_dylib.Args["linkFlags"], "generated_rust_staticlib/librustlibs.a") {
+ t.Errorf("missing generated static library in linker step libFlags in Rust module, expecting %#v, libFlags: %#v",
+ "generated_rust_staticlib/librustlibs.a", librs2_dylib.Args["libFlags"])
+ }
// Make sure that direct dependencies and indirect whole static dependencies are
// propagating correctly for the rlib -> cc_library_static -> rust_* generated library example.
@@ -610,6 +647,31 @@
if librs_rlib.Rule != nil {
t.Error("rlibs should not be generating mto staticlibs", "rlib", libbar.Args["rustcFlags"])
}
+ if librs2_rlib.Rule != nil {
+ t.Error("rlibs should not be generating mto staticlibs", "rlib", libbar.Args["rustcFlags"])
+ }
+
+ // Make sure that direct whole static dependencies are propagating correctly downstream
+ // foo_from_rlib_whole --(ws)--> libcc_whole_static_from_rlib --(ws)--> librs
+ if !strings.Contains(librs_genlib.Args["libFlags"], "--extern foo_from_rlib_whole=") {
+ t.Errorf("Missing direct whole_static_lib dependency libfoo_from_rlib_whole from rust dylib when writing generated Rust staticlib: %#v", librs_genlib.Args["libFlags"])
+ }
+
+ // Make sure that indirect whole static dependencies are propagating correctly downstream
+ // foo_from_rlib_whole --(ws)--> libcc_whole_static_from_rlib --(ws)--> librs --> rust_*
+ if !strings.Contains(librs2_genlib.Args["libFlags"], "--extern foo_from_rlib_whole=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo_from_rlib_whole from rust dylib when writing generated Rust staticlib: %#v", librs2_genlib.Args["libFlags"])
+ }
+ if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo_from_rlib_whole=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo_from_rlib_whole from rust dylib in rust binary when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+
+ // Make sure that normal static dependencies are not propagating through dylib dependencies
+ // buzz_from_rlib_whole --(s)--> libcc_whole_static_from_rlib --(ws)--> librs --> rust_*
+ if strings.Contains(librs2_genlib.Args["libFlags"], "--extern buzz_from_rlib_whole=") {
+ t.Errorf("dependency from indirect cc staticlib from direct dylib dep found in rust dylib when writing generated Rust staticlib: %#v", librs2_genlib.Args["libFlags"])
+ }
+
}
func assertString(t *testing.T, got, expected string) {