diff --git a/rust/compiler.go b/rust/compiler.go index c1bdbeb91..03fdf2b7a 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -75,6 +75,8 @@ type compiler interface { strippedOutputFilePath() android.OptionalPath checkedCrateRootPath() (android.Path, error) + + Aliases() map[string]string } func (compiler *baseCompiler) edition() string { @@ -140,6 +142,12 @@ type BaseCompilerProperties struct { // flags to pass to the linker Ld_flags []string `android:"arch_variant"` + // Rust crate dependencies to rename. Each entry should be a string of the form "dependencyname:alias". + // + // "dependencyname" here should be the name of the crate, not the Android module. This is + // equivalent to writing `alias = { package = "dependencyname" }` in a `Cargo.toml`. + Aliases []string + // list of rust rlib crate dependencies Rlibs []string `android:"arch_variant"` @@ -281,6 +289,18 @@ func (compiler *baseCompiler) preferRlib() bool { return Bool(compiler.Properties.Prefer_rlib) } +func (compiler *baseCompiler) Aliases() map[string]string { + aliases := map[string]string{} + for _, entry := range compiler.Properties.Aliases { + dep, alias, found := strings.Cut(entry, ":") + if !found { + panic(fmt.Errorf("invalid aliases entry %q missing ':'", entry)) + } + aliases[dep] = alias + } + return aliases +} + func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage { // For devices, we always link stdlibs in as dylibs by default. if compiler.preferRlib() { diff --git a/rust/rust.go b/rust/rust.go index 668dd8f08..7d81c721e 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -1142,6 +1142,7 @@ func collectIncludedProtos(mod *Module, dep *Module) { } } } + func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { var depPaths PathDeps @@ -1433,16 +1434,29 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { mod.transitiveAndroidMkSharedLibs = android.NewDepSet[string](android.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs) var rlibDepFiles RustLibraries + aliases := mod.compiler.Aliases() for _, dep := range directRlibDeps { - rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()}) + crateName := dep.CrateName() + if alias, aliased := aliases[crateName]; aliased { + crateName = alias + } + rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName}) } var dylibDepFiles RustLibraries for _, dep := range directDylibDeps { - dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()}) + crateName := dep.CrateName() + if alias, aliased := aliases[crateName]; aliased { + crateName = alias + } + dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName}) } var procMacroDepFiles RustLibraries for _, dep := range directProcMacroDeps { - procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()}) + crateName := dep.CrateName() + if alias, aliased := aliases[crateName]; aliased { + crateName = alias + } + procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName}) } var staticLibDepFiles android.Paths diff --git a/rust/rust_test.go b/rust/rust_test.go index d609c2faa..295a734b6 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -470,6 +470,35 @@ func TestLibrarySizes(t *testing.T) { m.Output("libwaldo.dylib.so.bloaty.csv") } +// Test that aliases are respected. +func TestRustAliases(t *testing.T) { + ctx := testRust(t, ` + rust_library { + name: "libbar", + crate_name: "bar", + srcs: ["src/lib.rs"], + } + rust_library { + name: "libbaz", + crate_name: "baz", + srcs: ["src/lib.rs"], + } + rust_binary { + name: "foo", + srcs: ["src/main.rs"], + rustlibs: ["libbar", "libbaz"], + aliases: ["bar:bar_renamed"], + }`) + + fooRustc := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc") + if !strings.Contains(fooRustc.Args["libFlags"], "--extern bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so") { + t.Errorf("--extern bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"]) + } + if !strings.Contains(fooRustc.Args["libFlags"], "--extern baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so") { + t.Errorf("--extern baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"]) + } +} + func assertString(t *testing.T, got, expected string) { t.Helper() if got != expected {