rust: Mutate prebuilt modules dylib/rlib

This change makes it possible to use a single module to provide both
dylib and rlib varieties of a library. This allows the use of libstd and
libtest from a rustlibs property, allowing linkage type to change
for different variants.

Bug: 159718669
Test: cd external crates; mma; m crosvm.experimental
Change-Id: I477c4d2faec63703fdc6dd42ba020747d6a50714
diff --git a/rust/compiler.go b/rust/compiler.go
index 2aee17b..bda2cec 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -193,17 +193,7 @@
 				stdlib = stdlib + "_" + ctx.toolchain().RustTriple()
 			}
 
-			// This check is technically insufficient - on the host, where
-			// static linking is the default, if one of our static
-			// dependencies uses a dynamic library, we need to dynamically
-			// link the stdlib as well.
-			if (len(deps.Dylibs) > 0) || ctx.Device() {
-				// Dynamically linked stdlib
-				deps.Dylibs = append(deps.Dylibs, stdlib)
-			} else if ctx.Host() && !ctx.TargetPrimary() {
-				// Otherwise use the static in-tree stdlib for host secondary arch
-				deps.Rlibs = append(deps.Rlibs, stdlib+".static")
-			}
+			deps.Rustlibs = append(deps.Rustlibs, stdlib)
 		}
 	}
 	return deps
diff --git a/rust/library.go b/rust/library.go
index b266d04..3dc2559 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -38,7 +38,8 @@
 }
 
 type VariantLibraryProperties struct {
-	Enabled *bool `android:"arch_variant"`
+	Enabled *bool    `android:"arch_variant"`
+	Srcs    []string `android:"path,arch_variant"`
 }
 
 type LibraryCompilerProperties struct {
@@ -355,7 +356,7 @@
 	if !ctx.Host() && library.static() {
 		library.setNoStdlibs()
 		for _, stdlib := range config.Stdlibs {
-			deps.Rlibs = append(deps.Rlibs, stdlib+".static")
+			deps.Rlibs = append(deps.Rlibs, stdlib)
 		}
 	}
 
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index a7f6c09..cddd447 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -19,7 +19,9 @@
 )
 
 func init() {
+	android.RegisterModuleType("rust_prebuilt_library", PrebuiltLibraryFactory)
 	android.RegisterModuleType("rust_prebuilt_dylib", PrebuiltDylibFactory)
+	android.RegisterModuleType("rust_prebuilt_rlib", PrebuiltRlibFactory)
 }
 
 type PrebuiltProperties struct {
@@ -34,16 +36,47 @@
 
 var _ compiler = (*prebuiltLibraryDecorator)(nil)
 
+func PrebuiltLibraryFactory() android.Module {
+	module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
 func PrebuiltDylibFactory() android.Module {
 	module, _ := NewPrebuiltDylib(android.HostAndDeviceSupported)
 	return module.Init()
 }
 
+func PrebuiltRlibFactory() android.Module {
+	module, _ := NewPrebuiltRlib(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
+func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibraryDecorator) {
+	module, library := NewRustLibrary(hod)
+	library.BuildOnlyRust()
+	library.setNoStdlibs()
+	prebuilt := &prebuiltLibraryDecorator{
+		libraryDecorator: library,
+	}
+	module.compiler = prebuilt
+	return module, prebuilt
+}
+
 func NewPrebuiltDylib(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibraryDecorator) {
 	module, library := NewRustLibrary(hod)
 	library.BuildOnlyDylib()
 	library.setNoStdlibs()
-	library.setDylib()
+	prebuilt := &prebuiltLibraryDecorator{
+		libraryDecorator: library,
+	}
+	module.compiler = prebuilt
+	return module, prebuilt
+}
+
+func NewPrebuiltRlib(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibraryDecorator) {
+	module, library := NewRustLibrary(hod)
+	library.BuildOnlyRlib()
+	library.setNoStdlibs()
 	prebuilt := &prebuiltLibraryDecorator{
 		libraryDecorator: library,
 	}
@@ -57,7 +90,7 @@
 }
 
 func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
-	srcPath := srcPathFromModuleSrcs(ctx, prebuilt.Properties.Srcs)
+	srcPath := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
 
 	prebuilt.unstrippedOutputFile = srcPath
 
@@ -72,3 +105,15 @@
 func (prebuilt *prebuiltLibraryDecorator) nativeCoverage() bool {
 	return false
 }
+
+func (prebuilt *prebuiltLibraryDecorator) prebuiltSrcs() []string {
+	srcs := prebuilt.Properties.Srcs
+	if prebuilt.rlib() {
+		srcs = append(srcs, prebuilt.libraryDecorator.Properties.Rlib.Srcs...)
+	}
+	if prebuilt.dylib() {
+		srcs = append(srcs, prebuilt.libraryDecorator.Properties.Dylib.Srcs...)
+	}
+
+	return srcs
+}
diff --git a/rust/rust.go b/rust/rust.go
index df323e3..c80ede2 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -440,6 +440,9 @@
 
 func (mod *Module) CoverageFiles() android.Paths {
 	if mod.compiler != nil {
+		if !mod.compiler.nativeCoverage() {
+			return android.Paths{}
+		}
 		if library, ok := mod.compiler.(*libraryDecorator); ok {
 			if library.coverageFile != nil {
 				return android.Paths{library.coverageFile}
diff --git a/rust/testing.go b/rust/testing.go
index 00cd807..3d583e1 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -21,14 +21,26 @@
 
 func GatherRequiredDepsForTest() string {
 	bp := `
-		rust_prebuilt_dylib {
+		rust_prebuilt_library {
 				name: "libstd_x86_64-unknown-linux-gnu",
-				srcs: [""],
+                                crate_name: "std",
+                                rlib: {
+                                    srcs: ["libstd.rlib"],
+                                },
+                                dylib: {
+                                    srcs: ["libstd.so"],
+                                },
 				host_supported: true,
 		}
-		rust_prebuilt_dylib {
+		rust_prebuilt_library {
 				name: "libtest_x86_64-unknown-linux-gnu",
-				srcs: [""],
+                                crate_name: "test",
+                                rlib: {
+                                    srcs: ["libtest.rlib"],
+                                },
+                                dylib: {
+                                    srcs: ["libtest.so"],
+                                },
 				host_supported: true,
 		}
 
@@ -41,34 +53,21 @@
 			nocrt: true,
 			system_shared_libs: [],
 		}
-		rust_library_dylib {
+		rust_library {
 			name: "libstd",
 			crate_name: "std",
 			srcs: ["foo.rs"],
 			no_stdlibs: true,
 			host_supported: true,
+                        native_coverage: false,
 		}
-		rust_library_rlib {
-			name: "libstd.static",
-			crate_name: "std",
-			srcs: ["foo.rs"],
-			no_stdlibs: true,
-			host_supported: true,
-		}
-		rust_library_dylib {
+		rust_library {
 			name: "libtest",
 			crate_name: "test",
 			srcs: ["foo.rs"],
 			no_stdlibs: true,
 			host_supported: true,
-
-		}
-		rust_library_rlib {
-			name: "libtest.static",
-			crate_name: "test",
-			srcs: ["foo.rs"],
-			no_stdlibs: true,
-			host_supported: true,
+                        native_coverage: false,
 		}
 
 ` + cc.GatherRequiredDepsForTest(android.NoOsType)
@@ -95,7 +94,9 @@
 	ctx.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
 	ctx.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
 	ctx.RegisterModuleType("rust_proc_macro", ProcMacroFactory)
+	ctx.RegisterModuleType("rust_prebuilt_library", PrebuiltLibraryFactory)
 	ctx.RegisterModuleType("rust_prebuilt_dylib", PrebuiltDylibFactory)
+	ctx.RegisterModuleType("rust_prebuilt_rlib", PrebuiltRlibFactory)
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		// rust mutators
 		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()