summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ivan Lozano <ivanlozano@google.com> 2024-12-11 21:38:53 +0000
committer Ivan Lozano <ivanlozano@google.com> 2024-12-13 19:53:20 +0000
commit806efd3885d6eecfa1b1bd1697431c0ab073a76a (patch)
treea63dc4cae01bd6371745cdcce8fc979250fff654
parentf7bbd2fe40e43f7fda7e08d08eeb9c2a93552ad9 (diff)
rust: Alias rust_ffi_rlib to rust_library_rlib
With the new transition mutators, the distinctions between rust_ffi_rlib and rust_library_rlib are not necessary. This CL removes the remaining distinctions to allow an unusual use case where a rust_library and a rust_ffi_rlib would otherwise be created from the same source. This would allow defining a single rust_library_rlib that works for both rust modules and cc modules. One key change is that rust_ffi_rlibs only produced an rlib-std variant previously, and now produce dylib-std variants as well.This surfaced an issue where a libstd linkage mismatch would cause rustc to throw a consufing missing crate error. We instead add logic to catch this in Soong and provide a more useful error message. Bug: 383552450 Test: m rust Test: m blueprint_tests Change-Id: I611ca46934059735d06229952cfd8e0ab7050486
-rw-r--r--cc/cc.go5
-rw-r--r--cc/library.go4
-rw-r--r--cc/linkable.go3
-rw-r--r--rust/benchmark.go2
-rw-r--r--rust/binary.go4
-rw-r--r--rust/compiler.go9
-rw-r--r--rust/fuzz.go2
-rw-r--r--rust/library.go63
-rw-r--r--rust/rust.go33
-rw-r--r--rust/rust_test.go28
-rw-r--r--rust/test.go2
-rw-r--r--rust/testing.go8
12 files changed, 78 insertions, 85 deletions
diff --git a/cc/cc.go b/cc/cc.go
index 04b66d479..812d1c38e 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1197,11 +1197,6 @@ func (c *Module) BuildRlibVariant() bool {
return false
}
-func (c *Module) IsRustFFI() bool {
- // cc modules are not Rust modules
- return false
-}
-
func (c *Module) Module() android.Module {
return c
}
diff --git a/cc/library.go b/cc/library.go
index ebc65efbd..ad8128e30 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -2112,7 +2112,7 @@ func (linkageTransitionMutator) Split(ctx android.BaseModuleContext) []string {
} else {
// Header only
}
- } else if library, ok := ctx.Module().(LinkableInterface); ok && (library.CcLibraryInterface() || library.RustLibraryInterface()) {
+ } else if library, ok := ctx.Module().(LinkableInterface); ok && (library.CcLibraryInterface()) {
// Non-cc.Modules may need an empty variant for their mutators.
variations := []string{}
if library.NonCcVariants() {
@@ -2167,7 +2167,7 @@ func (linkageTransitionMutator) IncomingTransition(ctx android.IncomingTransitio
}
buildStatic := library.BuildStaticVariant() && !isLLNDK
buildShared := library.BuildSharedVariant()
- if library.BuildRlibVariant() && library.IsRustFFI() && !buildStatic && (incomingVariation == "static" || incomingVariation == "") {
+ if library.BuildRlibVariant() && !buildStatic && (incomingVariation == "static" || incomingVariation == "") {
// Rust modules do not build static libs, but rlibs are used as if they
// were via `static_libs`. Thus we need to alias the BuildRlibVariant
// to "static" for Rust FFI libraries.
diff --git a/cc/linkable.go b/cc/linkable.go
index 1fade717a..d0f03c523 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -102,9 +102,6 @@ type LinkableInterface interface {
IsPrebuilt() bool
Toc() android.OptionalPath
- // IsRustFFI returns true if this is a Rust FFI library.
- IsRustFFI() bool
-
// IsFuzzModule returns true if this a *_fuzz module.
IsFuzzModule() bool
diff --git a/rust/benchmark.go b/rust/benchmark.go
index 8c3e5151e..eaa2176a2 100644
--- a/rust/benchmark.go
+++ b/rust/benchmark.go
@@ -89,7 +89,7 @@ func (benchmark *benchmarkDecorator) autoDep(ctx android.BottomUpMutatorContext)
return rlibAutoDep
}
-func (benchmark *benchmarkDecorator) stdLinkage(ctx *depsContext) RustLinkage {
+func (benchmark *benchmarkDecorator) stdLinkage(device bool) RustLinkage {
return RlibLinkage
}
diff --git a/rust/binary.go b/rust/binary.go
index cba29a023..d22041b27 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -165,11 +165,11 @@ func (binary *binaryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoD
}
}
-func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
+func (binary *binaryDecorator) stdLinkage(device bool) RustLinkage {
if binary.preferRlib() {
return RlibLinkage
}
- return binary.baseCompiler.stdLinkage(ctx)
+ return binary.baseCompiler.stdLinkage(device)
}
func (binary *binaryDecorator) binary() bool {
diff --git a/rust/compiler.go b/rust/compiler.go
index fd869174c..b93019b30 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -30,9 +30,8 @@ import (
type RustLinkage int
const (
- DefaultLinkage RustLinkage = iota
+ DylibLinkage RustLinkage = iota
RlibLinkage
- DylibLinkage
)
type compiler interface {
@@ -69,7 +68,7 @@ type compiler interface {
Disabled() bool
SetDisabled()
- stdLinkage(ctx *depsContext) RustLinkage
+ stdLinkage(device bool) RustLinkage
noStdlibs() bool
unstrippedOutputFilePath() android.Path
@@ -316,11 +315,11 @@ func (compiler *baseCompiler) Aliases() map[string]string {
return aliases
}
-func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage {
+func (compiler *baseCompiler) stdLinkage(device bool) RustLinkage {
// For devices, we always link stdlibs in as dylibs by default.
if compiler.preferRlib() {
return RlibLinkage
- } else if ctx.Device() {
+ } else if device {
return DylibLinkage
} else {
return RlibLinkage
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 1770d2e65..68becb581 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -121,7 +121,7 @@ func (fuzzer *fuzzDecorator) compile(ctx ModuleContext, flags Flags, deps PathDe
return out
}
-func (fuzzer *fuzzDecorator) stdLinkage(ctx *depsContext) RustLinkage {
+func (fuzzer *fuzzDecorator) stdLinkage(device bool) RustLinkage {
return RlibLinkage
}
diff --git a/rust/library.go b/rust/library.go
index bd3359b6a..93a9a3dab 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -40,15 +40,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_rlib", RustFFIRlibFactory)
+ android.RegisterModuleType("rust_ffi_rlib", RustLibraryRlibFactory)
android.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
android.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
- android.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory)
+ android.RegisterModuleType("rust_ffi_host_rlib", RustLibraryRlibHostFactory)
// TODO: Remove when all instances of rust_ffi_static have been switched to rust_ffi_rlib
// Alias rust_ffi_static to the rust_ffi_rlib factory
- android.RegisterModuleType("rust_ffi_static", RustFFIRlibFactory)
- android.RegisterModuleType("rust_ffi_host_static", RustFFIRlibHostFactory)
+ android.RegisterModuleType("rust_ffi_static", RustLibraryRlibFactory)
+ android.RegisterModuleType("rust_ffi_host_static", RustLibraryRlibHostFactory)
}
type VariantLibraryProperties struct {
@@ -114,8 +114,6 @@ 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
}
@@ -156,8 +154,6 @@ type libraryInterface interface {
BuildOnlyShared()
toc() android.OptionalPath
-
- isFFILibrary() bool
}
func (library *libraryDecorator) nativeCoverage() bool {
@@ -262,13 +258,13 @@ func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) aut
}
}
-func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
- if library.static() || library.MutatedProperties.VariantIsStaticStd || (library.rlib() && library.isFFILibrary()) {
+func (library *libraryDecorator) stdLinkage(device bool) RustLinkage {
+ if library.static() || library.MutatedProperties.VariantIsStaticStd {
return RlibLinkage
} else if library.baseCompiler.preferRlib() {
return RlibLinkage
}
- return DefaultLinkage
+ return DylibLinkage
}
var _ compiler = (*libraryDecorator)(nil)
@@ -298,7 +294,7 @@ func RustLibraryDylibFactory() android.Module {
return module.Init()
}
-// rust_library_rlib produces an rlib (Rust crate type "rlib").
+// rust_library_rlib and rust_ffi_static produces an rlib (Rust crate type "rlib").
func RustLibraryRlibFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
library.BuildOnlyRlib()
@@ -337,8 +333,8 @@ func RustLibraryDylibHostFactory() android.Module {
return module.Init()
}
-// rust_library_rlib_host produces an rlib for the host (Rust crate
-// type "rlib").
+// rust_library_rlib_host and rust_ffi_static_host produces an rlib for the host
+// (Rust crate type "rlib").
func RustLibraryRlibHostFactory() android.Module {
module, library := NewRustLibrary(android.HostSupported)
library.BuildOnlyRlib()
@@ -353,33 +349,12 @@ 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.BuildOnlyRlib()
-
- 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()
-}
-
func (library *libraryDecorator) BuildOnlyFFI() {
library.MutatedProperties.BuildDylib = false
// we build rlibs for later static ffi linkage.
library.MutatedProperties.BuildRlib = true
library.MutatedProperties.BuildShared = true
library.MutatedProperties.BuildStatic = false
-
- library.isFFI = true
}
func (library *libraryDecorator) BuildOnlyRust() {
@@ -408,8 +383,6 @@ func (library *libraryDecorator) BuildOnlyStatic() {
library.MutatedProperties.BuildDylib = false
library.MutatedProperties.BuildShared = false
library.MutatedProperties.BuildStatic = true
-
- library.isFFI = true
}
func (library *libraryDecorator) BuildOnlyShared() {
@@ -417,12 +390,6 @@ 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) {
@@ -511,7 +478,9 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) F
flags = CommonLibraryCompilerFlags(ctx, flags)
- if library.isFFI {
+ if library.rlib() || library.shared() {
+ // rlibs collect include dirs as well since they are used to
+ // produce staticlibs in the final C linkages
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)...)
}
@@ -821,11 +790,7 @@ func (libstdTransitionMutator) Split(ctx android.BaseModuleContext) []string {
// Only create a variant if a library is actually being built.
if library, ok := m.compiler.(libraryInterface); ok {
if library.rlib() && !library.sysroot() {
- if library.isFFILibrary() {
- return []string{"rlib-std"}
- } else {
- return []string{"rlib-std", "dylib-std"}
- }
+ return []string{"rlib-std", "dylib-std"}
}
}
}
diff --git a/rust/rust.go b/rust/rust.go
index 64cfa40d2..cd4bd4355 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -594,7 +594,7 @@ func (mod *Module) CcLibraryInterface() bool {
if mod.compiler != nil {
// use build{Static,Shared}() instead of {static,shared}() here because this might be called before
// VariantIs{Static,Shared} is set.
- if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic()) {
+ if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic() || lib.buildRlib()) {
return true
}
}
@@ -680,15 +680,6 @@ func (mod *Module) BuildRlibVariant() bool {
panic(fmt.Errorf("BuildRlibVariant called on non-library module: %q", mod.BaseModuleName()))
}
-func (mod *Module) IsRustFFI() bool {
- if mod.compiler != nil {
- if library, ok := mod.compiler.(libraryInterface); ok {
- return library.isFFILibrary()
- }
- }
- return false
-}
-
func (mod *Module) BuildSharedVariant() bool {
if mod.compiler != nil {
if library, ok := mod.compiler.(libraryInterface); ok {
@@ -1236,6 +1227,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
+ modStdLinkage := mod.compiler.stdLinkage(ctx.Device())
+
if _, exists := skipModuleList[depName]; exists {
return
}
@@ -1264,6 +1257,14 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
}
+ if !rustDep.compiler.noStdlibs() {
+ rustDepStdLinkage := rustDep.compiler.stdLinkage(ctx.Device())
+ if rustDepStdLinkage != modStdLinkage {
+ ctx.ModuleErrorf("Rust dependency %q has the wrong StdLinkage; expected %#v, got %#v", depName, modStdLinkage, rustDepStdLinkage)
+ return
+ }
+ }
+
case depTag == rlibDepTag:
rlib, ok := rustDep.compiler.(libraryInterface)
if !ok || !rlib.rlib() {
@@ -1284,6 +1285,14 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
}
+ if !rustDep.compiler.noStdlibs() {
+ rustDepStdLinkage := rustDep.compiler.stdLinkage(ctx.Device())
+ if rustDepStdLinkage != modStdLinkage {
+ ctx.ModuleErrorf("Rust dependency %q has the wrong StdLinkage; expected %#v, got %#v", depName, modStdLinkage, rustDepStdLinkage)
+ return
+ }
+ }
+
case depTag == procMacroDepTag:
directProcMacroDeps = append(directProcMacroDeps, rustDep)
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
@@ -1602,7 +1611,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
}
stdLinkage := "dylib-std"
- if mod.compiler.stdLinkage(ctx) == RlibLinkage {
+ if mod.compiler.stdLinkage(ctx.Device()) == RlibLinkage {
stdLinkage = "rlib-std"
}
@@ -1669,7 +1678,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
// stdlibs
if deps.Stdlibs != nil {
- if mod.compiler.stdLinkage(ctx) == RlibLinkage {
+ if mod.compiler.stdLinkage(ctx.Device()) == RlibLinkage {
for _, lib := range deps.Stdlibs {
actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...),
rlibDepTag, lib)
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 767508d5f..7e64c0a9e 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -547,3 +547,31 @@ func assertString(t *testing.T, got, expected string) {
t.Errorf("expected %q got %q", expected, got)
}
}
+
+func TestStdLinkMismatch(t *testing.T) {
+ // Test that we catch cases where the std linkage mismatches. This leads to
+ // a confusing rustc error where a crate is declared missing despite being
+ // passed in as a rustlib dependency / via the --extern flag. Thus, we want
+ // to make sure we detect it in Soong.
+
+ // libfoo depends on libbar as an rlib, but does not link libstd as an rlib.
+ // libbar only links libstd as an rlib (prefer_rlib).
+ testRustError(t, "wrong StdLinkage", `
+ rust_library {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: [
+ "foo.rs",
+ ],
+ rlibs: ["libbar"],
+ }
+ rust_library {
+ name: "libbar",
+ crate_name: "bar",
+ srcs: [
+ "bar.rs",
+ ],
+ prefer_rlib: true,
+ }
+ `)
+}
diff --git a/rust/test.go b/rust/test.go
index 20ccfb31c..dce5e0391 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -238,7 +238,7 @@ func RustTestHostFactory() android.Module {
return module.Init()
}
-func (test *testDecorator) stdLinkage(ctx *depsContext) RustLinkage {
+func (test *testDecorator) stdLinkage(device bool) RustLinkage {
return RlibLinkage
}
diff --git a/rust/testing.go b/rust/testing.go
index 32cc82354..2e50e1e68 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -188,12 +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_rlib", RustFFIRlibFactory)
- ctx.RegisterModuleType("rust_ffi_static", RustFFIRlibFactory)
+ ctx.RegisterModuleType("rust_ffi_rlib", RustLibraryRlibFactory)
+ ctx.RegisterModuleType("rust_ffi_static", RustLibraryRlibFactory)
ctx.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
ctx.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
- ctx.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory)
- ctx.RegisterModuleType("rust_ffi_host_static", RustFFIRlibHostFactory)
+ ctx.RegisterModuleType("rust_ffi_host_rlib", RustLibraryRlibHostFactory)
+ ctx.RegisterModuleType("rust_ffi_host_static", RustLibraryRlibHostFactory)
ctx.RegisterModuleType("rust_proc_macro", ProcMacroFactory)
ctx.RegisterModuleType("rust_protobuf", RustProtobufFactory)
ctx.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)