Merge "rust: Pass cc static libs to rustc."
diff --git a/rust/binary.go b/rust/binary.go
index 0334acc..df48916 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -119,6 +119,7 @@
 	outputFile := android.PathForModuleOut(ctx, fileName)
 
 	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
+	flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
 	flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
 
 	TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
diff --git a/rust/compiler.go b/rust/compiler.go
index c921824..586063e 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -96,7 +96,11 @@
 	// list of C shared library dependencies
 	Shared_libs []string `android:"arch_variant"`
 
-	// list of C static library dependencies
+	// list of C static library dependencies. Note, static libraries prefixed by "lib" will be passed to rustc
+	// along with "-lstatic=<name>". This will bundle the static library into rlib/static libraries so dependents do
+	// not need to also declare the static library as a dependency. Static libraries which are not prefixed by "lib"
+	// cannot be passed to rustc with this flag and will not be bundled into rlib/static libraries, and thus must
+	// be redeclared in dependents.
 	Static_libs []string `android:"arch_variant"`
 
 	// crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
diff --git a/rust/library.go b/rust/library.go
index b5749a2..7ff13ec 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -443,6 +443,7 @@
 	}
 
 	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
+	flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
 	flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
 
 	if library.dylib() {
@@ -482,7 +483,6 @@
 
 	if library.rlib() || library.dylib() {
 		library.flagExporter.exportLinkDirs(deps.linkDirs...)
-		library.flagExporter.exportDepFlags(deps.depFlags...)
 		library.flagExporter.exportLinkObjects(deps.linkObjects...)
 	}
 
diff --git a/rust/rust.go b/rust/rust.go
index 504b7a9..e1af776 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -280,10 +280,15 @@
 	SharedLibDeps android.Paths
 	StaticLibs    android.Paths
 	ProcMacros    RustLibraries
-	linkDirs      []string
-	depFlags      []string
-	linkObjects   []string
-	//ReexportedDeps android.Paths
+
+	// depFlags and depLinkFlags are rustc and linker (clang) flags.
+	depFlags     []string
+	depLinkFlags []string
+
+	// 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
+	linkObjects []string
 
 	// Used by bindgen modules which call clang
 	depClangFlags         []string
@@ -328,12 +333,10 @@
 
 type exportedFlagsProducer interface {
 	exportLinkDirs(...string)
-	exportDepFlags(...string)
 	exportLinkObjects(...string)
 }
 
 type flagExporter struct {
-	depFlags    []string
 	linkDirs    []string
 	linkObjects []string
 }
@@ -342,17 +345,12 @@
 	flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
 }
 
-func (flagExporter *flagExporter) exportDepFlags(flags ...string) {
-	flagExporter.depFlags = android.FirstUniqueStrings(append(flagExporter.depFlags, flags...))
-}
-
 func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
 	flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
 }
 
 func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
 	ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
-		Flags:       flagExporter.depFlags,
 		LinkDirs:    flagExporter.linkDirs,
 		LinkObjects: flagExporter.linkObjects,
 	})
@@ -898,8 +896,21 @@
 			exportDep := false
 			switch {
 			case cc.IsStaticDepTag(depTag):
-				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
+				// Link cc static libraries using "-lstatic" so rustc can reason about how to handle these
+				// (for example, bundling them into rlibs).
+				//
+				// rustc does not support linking libraries with the "-l" flag unless they are prefixed by "lib".
+				// If we need to link a library that isn't prefixed by "lib", we'll just link to it directly through
+				// linkObjects; such a library may need to be redeclared by static dependents.
+				if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
+					depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
+				}
+
+				// Add this to linkObjects to pass the library directly to the linker as well. This propagates
+				// to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant.
 				depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
+				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
+
 				exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
 				depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
 				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
@@ -1213,6 +1224,16 @@
 	return false
 }
 
+// If a library file has a "lib" prefix, extract the library name without the prefix.
+func libNameFromFilePath(filepath android.Path) (string, bool) {
+	libName := strings.TrimSuffix(filepath.Base(), filepath.Ext())
+	if strings.HasPrefix(libName, "lib") {
+		libName = libName[3:]
+		return libName, true
+	}
+	return "", false
+}
+
 var Bool = proptools.Bool
 var BoolDefault = proptools.BoolDefault
 var String = proptools.String
diff --git a/rust/rust_test.go b/rust/rust_test.go
index abc9af9..a32c6a7 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -230,6 +230,7 @@
 		}
 	`)
 	module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
+	rustc := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustc")
 
 	// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
 	if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
@@ -251,6 +252,11 @@
 	if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) {
 		t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
 	}
+
+	if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic=static") {
+		t.Errorf("-lstatic flag not being passed to rustc for static library")
+	}
+
 }
 
 func TestSourceProviderDeps(t *testing.T) {