rust: Add rustlibs auto dependency selection

Adds the rustlibs dependency type which will automatically select
between rlib and dylib based on the type of the library.

Bug: 143217452
Test: cd external/rust; mma
Change-Id: I97faadae98bf957090a32939cfb2d3a10f74a057
diff --git a/rust/binary.go b/rust/binary.go
index 56d6f0b..a1cd410 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -131,3 +131,11 @@
 func (binary *binaryDecorator) coverageOutputZipPath() android.OptionalPath {
 	return binary.coverageOutputZipFile
 }
+
+func (binary *binaryDecorator) autoDep() autoDep {
+	if binary.preferDynamic() {
+		return dylibAutoDep
+	} else {
+		return rlibAutoDep
+	}
+}
diff --git a/rust/compiler.go b/rust/compiler.go
index 51d7180..2aee17b 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -67,6 +67,9 @@
 	// list of rust dylib crate dependencies
 	Dylibs []string `android:"arch_variant"`
 
+	// list of rust automatic crate dependencies
+	Rustlibs []string `android:"arch_variant"`
+
 	// list of rust proc_macro crate dependencies
 	Proc_macros []string `android:"arch_variant"`
 
@@ -178,6 +181,7 @@
 func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
 	deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
 	deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...)
+	deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...)
 	deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...)
 	deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
 	deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...)
diff --git a/rust/library.go b/rust/library.go
index a53df85..b266d04 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -186,6 +186,16 @@
 	library.MutatedProperties.VariantIsDylib = false
 }
 
+func (library *libraryDecorator) autoDep() autoDep {
+	if library.rlib() || library.static() {
+		return rlibAutoDep
+	} else if library.dylib() || library.shared() {
+		return dylibAutoDep
+	} else {
+		return rlibAutoDep
+	}
+}
+
 var _ compiler = (*libraryDecorator)(nil)
 var _ libraryInterface = (*libraryDecorator)(nil)
 
diff --git a/rust/library_test.go b/rust/library_test.go
index bc3d870..8a91cf1 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -143,3 +143,50 @@
 			libfoo.Module().(*Module).Properties.AndroidMkDylibs)
 	}
 }
+
+// Test that variants pull in the right type of rustlib autodep
+func TestAutoDeps(t *testing.T) {
+
+	ctx := testRust(t, `
+                rust_library_host {
+                        name: "libbar",
+                        srcs: ["bar.rs"],
+                        crate_name: "bar",
+                }
+		rust_library_host {
+			name: "libfoo",
+			srcs: ["foo.rs"],
+			crate_name: "foo",
+                        rustlibs: ["libbar"],
+		}
+                rust_ffi_host {
+                        name: "libfoo.ffi",
+                        srcs: ["foo.rs"],
+                        crate_name: "foo",
+                        rustlibs: ["libbar"],
+                }`)
+
+	libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib")
+	libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib")
+	libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static")
+	libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared")
+
+	for _, static := range []android.TestingModule{libfooRlib, libfooStatic} {
+		if !android.InList("libbar", static.Module().(*Module).Properties.AndroidMkRlibs) {
+			t.Errorf("libbar not present as static dependency in static lib")
+		}
+		if android.InList("libbar", static.Module().(*Module).Properties.AndroidMkDylibs) {
+			t.Errorf("libbar present as dynamic dependency in static lib")
+		}
+	}
+
+	for _, dyn := range []android.TestingModule{libfooDylib, libfooShared} {
+		if !android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkDylibs) {
+			t.Errorf("libbar not present as dynamic dependency in dynamic lib")
+		}
+		if android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkRlibs) {
+			t.Errorf("libbar present as static dependency in dynamic lib")
+		}
+
+	}
+}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 42c8537..b048087 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -76,3 +76,7 @@
 
 	return stem + String(procMacro.baseCompiler.Properties.Suffix)
 }
+
+func (procMacro *procMacroDecorator) autoDep() autoDep {
+	return rlibAutoDep
+}
diff --git a/rust/rust.go b/rust/rust.go
index 6c60348..df323e3 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -217,6 +217,7 @@
 type Deps struct {
 	Dylibs     []string
 	Rlibs      []string
+	Rustlibs   []string
 	ProcMacros []string
 	SharedLibs []string
 	StaticLibs []string
@@ -617,6 +618,7 @@
 
 	deps.Rlibs = android.LastUniqueStrings(deps.Rlibs)
 	deps.Dylibs = android.LastUniqueStrings(deps.Dylibs)
+	deps.Rustlibs = android.LastUniqueStrings(deps.Rustlibs)
 	deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros)
 	deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
 	deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
@@ -639,6 +641,20 @@
 	testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"}
 )
 
+type autoDep struct {
+	variation string
+	depTag    dependencyTag
+}
+
+var (
+	rlibAutoDep  = autoDep{variation: "rlib", depTag: rlibDepTag}
+	dylibAutoDep = autoDep{variation: "dylib", depTag: dylibDepTag}
+)
+
+type autoDeppable interface {
+	autoDep() autoDep
+}
+
 func (mod *Module) begin(ctx BaseModuleContext) {
 	if mod.coverage != nil {
 		mod.coverage.begin(ctx)
@@ -844,6 +860,15 @@
 			{Mutator: "link", Variation: ""}}...),
 		dylibDepTag, deps.Dylibs...)
 
+	if deps.Rustlibs != nil {
+		autoDep := mod.compiler.(autoDeppable).autoDep()
+		actx.AddVariationDependencies(
+			append(commonDepVariations, []blueprint.Variation{
+				{Mutator: "rust_libraries", Variation: autoDep.variation},
+				{Mutator: "link", Variation: ""}}...),
+			autoDep.depTag, deps.Rustlibs...)
+	}
+
 	actx.AddVariationDependencies(append(commonDepVariations,
 		blueprint.Variation{Mutator: "link", Variation: "shared"}),
 		cc.SharedDepTag, deps.SharedLibs...)
diff --git a/rust/test.go b/rust/test.go
index 416c557..e27a70c 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -105,6 +105,10 @@
 	return flags
 }
 
+func (test *testDecorator) autoDep() autoDep {
+	return rlibAutoDep
+}
+
 func init() {
 	// Rust tests are binary files built with --test.
 	android.RegisterModuleType("rust_test", RustTestFactory)