summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
author Ivan Lozano <ivanlozano@google.com> 2025-02-12 10:16:56 -0800
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2025-02-12 10:16:56 -0800
commitd604240a568f94ae6edbba7c1a38ebc28e1653f3 (patch)
tree0c36a15795d5d8686063989c572ee0d3a03e1726 /rust
parent080e810c9f3ee8056d1d1ac2990d9508928d4eeb (diff)
parent85f00cff18b0a1f23ed8acf3186a5b5316919be6 (diff)
Merge "rust:Add Rust support for made-to-order staticlibs" into main
Diffstat (limited to 'rust')
-rw-r--r--rust/builder.go17
-rw-r--r--rust/library.go9
-rw-r--r--rust/rust.go23
-rw-r--r--rust/rust_test.go75
4 files changed, 112 insertions, 12 deletions
diff --git a/rust/builder.go b/rust/builder.go
index 8a869aad8..1b6a6c117 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -171,7 +171,7 @@ func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
}
-// TransformRlibstoStaticlib is assumed to be called from the cc module, and
+// TransformRlibstoStaticlib is assumed to be callable from the cc module, and
// thus needs to reconstruct the common set of flags which need to be passed
// to the rustc compiler.
func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
@@ -185,7 +185,7 @@ func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path,
rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
}
- ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
+ mod := ctx.Module().(cc.LinkableInterface)
toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
t := transformProperties{
// Crate name can be a predefined value as this is a staticlib and
@@ -195,10 +195,10 @@ func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path,
crateName: "generated_rust_staticlib",
is64Bit: toolchain.Is64Bit(),
targetTriple: toolchain.RustTriple(),
- bootstrap: ccModule.Bootstrap(),
- inRecovery: ccModule.InRecovery(),
- inRamdisk: ccModule.InRamdisk(),
- inVendorRamdisk: ccModule.InVendorRamdisk(),
+ bootstrap: mod.Bootstrap(),
+ inRecovery: mod.InRecovery(),
+ inRamdisk: mod.InRamdisk(),
+ inVendorRamdisk: mod.InVendorRamdisk(),
// crateType indicates what type of crate to build
crateType: "staticlib",
@@ -402,6 +402,11 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
linkFlags = append(linkFlags, dynamicLinker)
}
+ if generatedLib := cc.GenerateRustStaticlib(ctx, deps.ccRlibDeps); generatedLib != nil {
+ deps.StaticLibs = append(deps.StaticLibs, generatedLib)
+ linkFlags = append(linkFlags, generatedLib.String())
+ }
+
libFlags := makeLibFlags(deps)
// Collect dependencies
diff --git a/rust/library.go b/rust/library.go
index 24ae8b046..7f5861fe8 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -737,12 +737,15 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
if library.rlib() {
library.flagExporter.exportStaticLibs(deps.staticLibObjects...)
}
-
// Since we have FFI rlibs, we need to collect their includes as well
if library.static() || library.shared() || library.rlib() || library.stubs() {
- android.SetProvider(ctx, cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
+ ccExporter := cc.FlagExporterInfo{
IncludeDirs: android.FirstUniquePaths(library.includeDirs),
- })
+ }
+ if library.rlib() {
+ ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedCcRlibDeps...)
+ }
+ android.SetProvider(ctx, cc.FlagExporterInfoProvider, ccExporter)
}
if library.shared() || library.stubs() {
diff --git a/rust/rust.go b/rust/rust.go
index ad68d6041..4eec5d254 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -495,6 +495,10 @@ type PathDeps struct {
depFlags []string
depLinkFlags []string
+ // track cc static-libs that have Rlib dependencies
+ reexportedCcRlibDeps []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.
linkDirs []string
@@ -1531,6 +1535,13 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
}
}
+ if !mod.Rlib() {
+ depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...)
+ } else {
+ // rlibs need to reexport these
+ depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
+ }
+
case depTag == procMacroDepTag:
directProcMacroDeps = append(directProcMacroDeps, linkableInfo)
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
@@ -1651,8 +1662,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
} else {
// Otherwise add to staticLibObjects, which only propagate through rlibs to their dependents.
depPaths.staticLibObjects = append(depPaths.staticLibObjects, ccLibPath.String())
-
}
+
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
@@ -1660,6 +1671,14 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
+
+ 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)
// Record baseLibName for snapshots.
@@ -1815,6 +1834,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths)
depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths)
depPaths.depLinkFlags = android.FirstUniqueStrings(depPaths.depLinkFlags)
+ depPaths.reexportedCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedCcRlibDeps, 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 4390f556e..2e016f0c7 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -449,12 +449,26 @@ func TestRustFFIRlibs(t *testing.T) {
}
rust_ffi_static {
+ name: "libfoo_from_rlib",
+ crate_name: "foo_from_rlib",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["foo_includes"]
+ }
+
+ rust_ffi_static {
name: "libbuzz",
crate_name: "buzz",
srcs: ["src/lib.rs"],
export_include_dirs: ["buzz_includes"]
}
+ rust_ffi_static {
+ name: "libbuzz_from_rlib",
+ crate_name: "buzz_from_rlib",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["buzz_includes"]
+ }
+
cc_library_shared {
name: "libcc_shared",
srcs:["foo.c"],
@@ -468,12 +482,34 @@ func TestRustFFIRlibs(t *testing.T) {
whole_static_libs: ["libfoo"],
}
+ cc_library_static {
+ name: "libcc_static_from_rlib",
+ srcs:["foo.c"],
+ static_libs: ["libbuzz_from_rlib"],
+ whole_static_libs: ["libfoo_from_rlib"],
+ }
+
cc_binary {
name: "ccBin",
srcs:["foo.c"],
static_libs: ["libcc_static", "libbar"],
}
- `)
+
+ rust_library {
+ name: "librs",
+ srcs:["src/foo.rs"],
+ crate_name: "rs",
+ static_libs: ["libcc_static_from_rlib"],
+ }
+
+ rust_binary {
+ name: "rsBin",
+ srcs:["src/foo.rs"],
+ crate_name: "rsBin",
+ rlibs: ["librs", "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")
@@ -482,6 +518,9 @@ func TestRustFFIRlibs(t *testing.T) {
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")
+ rustbin_genlib := ctx.ModuleForTests("rsBin", "android_arm64_armv8-a").Output("generated_rust_staticlib/librustlibs.a")
+ rustbin := ctx.ModuleForTests("rsBin", "android_arm64_armv8-a").Output("unstripped/rsBin")
+ librs_rlib := ctx.ModuleForTests("librs", "android_arm64_armv8-a_rlib_dylib-std").MaybeOutput("generated_rust_staticlib/librustlibs.a")
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"])
@@ -513,7 +552,7 @@ func TestRustFFIRlibs(t *testing.T) {
// Make sure the static lib is included in the cc command
if !strings.Contains(ccbin_ld.Args["libFlags"], "generated_rust_staticlib/librustlibs.a") {
t.Errorf("missing generated static library in linker step libFlags, expecting %#v, libFlags: %#v",
- "ccBin.generated_rust_staticlib.a", ccbin_ld.Args["libFlags"])
+ "generated_rust_staticlib/librustlibs.a", ccbin_ld.Args["libFlags"])
}
// Make sure the static lib includes are in the ld command
@@ -534,11 +573,43 @@ func TestRustFFIRlibs(t *testing.T) {
t.Errorf("Missing direct dependency libbar when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
}
+ // Make sure the static lib is included in the rustc command
+ if !strings.Contains(rustbin.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", rustbin.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.
+ if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo from cc static_lib when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern buzz=") {
+ t.Errorf("Indirect rlib dependency libbuzz from cc static_lib found when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern bar=") {
+ t.Errorf("Direct rlib dependency libbar getting included in the generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo_from_rlib=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo_from_rlib from cc static_lib when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern buzz_from_rlib=") {
+ // While static-libs propagate for rust modules, this is not the
+ // expected behavior for cc modules. Thus, libbuzz_from_rlib would
+ // be expected to have to be re-declared as a direct rlib dependency.
+ t.Errorf("Indirect rlib dependency libbuzz_from_rlib from cc static_lib found when writing generated Rust staticlib: %#v", rustbin_genlib.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)
}
+
+ // Make sure we're not generating superfluous mto staticlibs.
+ if librs_rlib.Rule != nil {
+ t.Error("rlibs should not be generating mto staticlibs", "rlib", libbar.Args["rustcFlags"])
+ }
}
func assertString(t *testing.T, got, expected string) {