Merge "Include hermetic .img files in target_files.zip" into main
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index 6e2964a..40aeee4 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -17,6 +17,7 @@
         "aconfig_values.go",
         "aconfig_value_set.go",
         "all_aconfig_declarations.go",
+        "all_aconfig_declarations_extension.go",
         "exported_java_aconfig_library.go",
         "init.go",
         "testing.go",
@@ -25,6 +26,7 @@
         "aconfig_declarations_test.go",
         "aconfig_values_test.go",
         "aconfig_value_set_test.go",
+        "all_aconfig_declarations_extension_test.go",
     ],
     pluginFor: ["soong_build"],
 }
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go
index ec20099..b17820e 100644
--- a/aconfig/all_aconfig_declarations.go
+++ b/aconfig/all_aconfig_declarations.go
@@ -20,6 +20,7 @@
 
 	"android/soong/android"
 
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -37,12 +38,18 @@
 	return module
 }
 
+type allAconfigDeclarationsInfo struct {
+	parsedFlagsFile android.Path
+}
+
+var allAconfigDeclarationsInfoProvider = blueprint.NewProvider[allAconfigDeclarationsInfo]()
+
 type allAconfigReleaseDeclarationsSingleton struct {
 	intermediateBinaryProtoPath android.OutputPath
 	intermediateTextProtoPath   android.OutputPath
 }
 
-type allAconfigReleaseDeclarationsProperties struct {
+type ApiSurfaceContributorProperties struct {
 	Api_signature_files  proptools.Configurable[[]string] `android:"arch_variant,path"`
 	Finalized_flags_file string                           `android:"arch_variant,path"`
 }
@@ -51,7 +58,9 @@
 	android.SingletonModuleBase
 
 	releaseMap map[string]allAconfigReleaseDeclarationsSingleton
-	properties allAconfigReleaseDeclarationsProperties
+	properties ApiSurfaceContributorProperties
+
+	finalizedFlags android.OutputPath
 }
 
 func (this *allAconfigDeclarationsSingleton) sortedConfigNames() []string {
@@ -63,29 +72,38 @@
 	return names
 }
 
-func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func GenerateFinalizedFlagsForApiSurface(ctx android.ModuleContext, outputPath android.WritablePath,
+	parsedFlagsFile android.Path, apiSurface ApiSurfaceContributorProperties) {
+
 	apiSignatureFiles := android.Paths{}
-	for _, apiSignatureFile := range this.properties.Api_signature_files.GetOrDefault(ctx, nil) {
+	for _, apiSignatureFile := range apiSurface.Api_signature_files.GetOrDefault(ctx, nil) {
 		if path := android.PathForModuleSrc(ctx, apiSignatureFile); path != nil {
 			apiSignatureFiles = append(apiSignatureFiles, path)
 		}
 	}
-	finalizedFlagsFile := android.PathForModuleSrc(ctx, this.properties.Finalized_flags_file)
-	parsedFlagsFile := android.PathForIntermediates(ctx, "all_aconfig_declarations.pb")
-
-	output := android.PathForIntermediates(ctx, "finalized-flags.txt")
+	finalizedFlagsFile := android.PathForModuleSrc(ctx, apiSurface.Finalized_flags_file)
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   RecordFinalizedFlagsRule,
 		Inputs: append(apiSignatureFiles, finalizedFlagsFile, parsedFlagsFile),
-		Output: output,
+		Output: outputPath,
 		Args: map[string]string{
 			"api_signature_files":  android.JoinPathsWithPrefix(apiSignatureFiles, "--api-signature-file "),
 			"finalized_flags_file": "--finalized-flags-file " + finalizedFlagsFile.String(),
 			"parsed_flags_file":    "--parsed-flags-file " + parsedFlagsFile.String(),
 		},
 	})
-	ctx.Phony("all_aconfig_declarations", output)
+}
+
+func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	parsedFlagsFile := android.PathForIntermediates(ctx, "all_aconfig_declarations.pb")
+	this.finalizedFlags = android.PathForIntermediates(ctx, "finalized-flags.txt")
+	GenerateFinalizedFlagsForApiSurface(ctx, this.finalizedFlags, parsedFlagsFile, this.properties)
+	ctx.Phony("all_aconfig_declarations", this.finalizedFlags)
+
+	android.SetProvider(ctx, allAconfigDeclarationsInfoProvider, allAconfigDeclarationsInfo{
+		parsedFlagsFile: parsedFlagsFile,
+	})
 }
 
 func (this *allAconfigDeclarationsSingleton) GenerateSingletonBuildActions(ctx android.SingletonContext) {
@@ -154,5 +172,5 @@
 			ctx.DistForGoalWithFilename(goal, this.releaseMap[rcName].intermediateTextProtoPath, assembleFileName(rcName, "flags.textproto"))
 		}
 	}
-	ctx.DistForGoalWithFilename("sdk", android.PathForIntermediates(ctx, "finalized-flags.txt"), "finalized-flags.txt")
+	ctx.DistForGoalWithFilename("sdk", this.finalizedFlags, "finalized-flags.txt")
 }
diff --git a/aconfig/all_aconfig_declarations_extension.go b/aconfig/all_aconfig_declarations_extension.go
new file mode 100644
index 0000000..44992cd
--- /dev/null
+++ b/aconfig/all_aconfig_declarations_extension.go
@@ -0,0 +1,90 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package aconfig
+
+import (
+	"android/soong/android"
+	"path"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+)
+
+func AllAconfigDeclarationsExtensionFactory() android.Module {
+	module := &allAconfigDeclarationsExtension{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	return module
+}
+
+type allAconfigDeclarationsExtensionProperties struct {
+	// all_aconfig_declarations module that this module extends. Defaults to
+	// all_aconfig_declarations.
+	Base *string
+
+	// Directory where the dist artifact should be placed in.
+	Dist_dir *string
+
+	ApiSurfaceContributorProperties
+}
+
+type allAconfigDeclarationsExtension struct {
+	android.ModuleBase
+
+	properties allAconfigDeclarationsExtensionProperties
+
+	finalizedFlags android.ModuleOutPath
+}
+
+type allAconfigDeclarationsDependencyTagStruct struct {
+	blueprint.BaseDependencyTag
+}
+
+var allAconfigDeclarationsDependencyTag allAconfigDeclarationsDependencyTagStruct
+
+func (ext *allAconfigDeclarationsExtension) DepsMutator(ctx android.BottomUpMutatorContext) {
+	ctx.AddDependency(ctx.Module(), allAconfigDeclarationsDependencyTag, proptools.StringDefault(ext.properties.Base, "all_aconfig_declarations"))
+}
+
+func (ext *allAconfigDeclarationsExtension) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+
+	var parsedFlagsFile android.Path
+	ctx.VisitDirectDepsProxyWithTag(allAconfigDeclarationsDependencyTag, func(proxy android.ModuleProxy) {
+		if info, ok := android.OtherModuleProvider(ctx, proxy, allAconfigDeclarationsInfoProvider); ok {
+			parsedFlagsFile = info.parsedFlagsFile
+		} else {
+			ctx.PropertyErrorf("base", "base must provide allAconfigDeclarationsInfo")
+		}
+	})
+
+	ext.finalizedFlags = android.PathForModuleOut(ctx, "finalized-flags.txt")
+
+	GenerateFinalizedFlagsForApiSurface(ctx,
+		ext.finalizedFlags,
+		parsedFlagsFile,
+		ext.properties.ApiSurfaceContributorProperties,
+	)
+
+	ctx.Phony(ctx.ModuleName(), ext.finalizedFlags)
+
+	// This module must not set any provider or call `ctx.SetOutputFiles`!
+	// This module is only used to depend on the singleton module all_aconfig_declarations and
+	// generate the custom finalized-flags.txt file in dist builds, and should not be depended
+	// by other modules.
+}
+
+func (ext *allAconfigDeclarationsExtension) MakeVars(ctx android.MakeVarsContext) {
+	ctx.DistForGoalWithFilename("sdk", ext.finalizedFlags, path.Join(proptools.String(ext.properties.Dist_dir), "finalized-flags.txt"))
+}
diff --git a/aconfig/all_aconfig_declarations_extension_test.go b/aconfig/all_aconfig_declarations_extension_test.go
new file mode 100644
index 0000000..1207096
--- /dev/null
+++ b/aconfig/all_aconfig_declarations_extension_test.go
@@ -0,0 +1,50 @@
+// Copyright 2025 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package aconfig
+
+import (
+	"strings"
+	"testing"
+
+	"android/soong/android"
+)
+
+func TestAllAconfigDeclarationsExtension(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		PrepareForTestWithAconfigBuildComponents,
+		android.FixtureMergeMockFs(
+			android.MockFS{
+				"a.txt":     nil,
+				"flags.txt": nil,
+			},
+		),
+	).RunTestWithBp(t, `
+		all_aconfig_declarations {
+			name: "all_aconfig_declarations",
+		}
+
+		all_aconfig_declarations_extension {
+			name: "custom_aconfig_declarations",
+			base: "all_aconfig_declarations",
+			api_signature_files: [
+				"a.txt",
+			],
+			finalized_flags_file: "flags.txt",
+		}
+	`)
+
+	finalizedFlags := result.ModuleForTests("custom_aconfig_declarations", "").Output("finalized-flags.txt")
+	android.AssertStringContainsEquals(t, "must depend on all_aconfig_declarations", strings.Join(finalizedFlags.Inputs.Strings(), " "), "all_aconfig_declarations.pb", true)
+}
diff --git a/aconfig/init.go b/aconfig/init.go
index 3dcec5c..210aec3 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -131,4 +131,5 @@
 	ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
 	ctx.RegisterSingletonModuleType("all_aconfig_declarations", AllAconfigDeclarationsFactory)
 	ctx.RegisterParallelSingletonType("exported_java_aconfig_library", ExportedJavaDeclarationsLibraryFactory)
+	ctx.RegisterModuleType("all_aconfig_declarations_extension", AllAconfigDeclarationsExtensionFactory)
 }
diff --git a/cc/binary.go b/cc/binary.go
index 4b77bea..c4791c5 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -426,7 +426,7 @@
 	validations = append(validations, objs.tidyDepFiles...)
 	linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
 
-	if generatedLib := generateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
+	if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
 		deps.StaticLibs = append(deps.StaticLibs, generatedLib)
 	}
 
diff --git a/cc/builder.go b/cc/builder.go
index 16f006d..f4f8596 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -817,7 +817,7 @@
 }
 
 // Generate a Rust staticlib from a list of rlibDeps. Returns nil if TransformRlibstoStaticlib is nil or rlibDeps is empty.
-func generateRustStaticlib(ctx android.ModuleContext, rlibDeps []RustRlibDep) android.Path {
+func GenerateRustStaticlib(ctx android.ModuleContext, rlibDeps []RustRlibDep) android.Path {
 	if TransformRlibstoStaticlib == nil && len(rlibDeps) > 0 {
 		// This should only be reachable if a module defines Rust deps in static_libs and
 		// soong-rust hasn't been loaded alongside soong-cc (e.g. in soong-cc tests).
diff --git a/cc/library.go b/cc/library.go
index dce3b92..532b7e9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1237,7 +1237,7 @@
 	linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
 	linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
 
-	if generatedLib := generateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil && !library.BuildStubs() {
+	if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil && !library.BuildStubs() {
 		if ctx.Module().(*Module).WholeRustStaticlib {
 			deps.WholeStaticLibs = append(deps.WholeStaticLibs, generatedLib)
 		} else {
diff --git a/rust/builder.go b/rust/builder.go
index 8a869aa..1b6a6c1 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -171,7 +171,7 @@
 	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
 }
 
-// TransformRlibstoStaticlib is assumed to be called from the cc module, and
+// TransformRlibstoStaticlib is assumed to be callable from the cc module, and
 // thus needs to reconstruct the common set of flags which need to be passed
 // to the rustc compiler.
 func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
@@ -185,7 +185,7 @@
 		rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
 	}
 
-	ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
+	mod := ctx.Module().(cc.LinkableInterface)
 	toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
 	t := transformProperties{
 		// Crate name can be a predefined value as this is a staticlib and
@@ -195,10 +195,10 @@
 		crateName:       "generated_rust_staticlib",
 		is64Bit:         toolchain.Is64Bit(),
 		targetTriple:    toolchain.RustTriple(),
-		bootstrap:       ccModule.Bootstrap(),
-		inRecovery:      ccModule.InRecovery(),
-		inRamdisk:       ccModule.InRamdisk(),
-		inVendorRamdisk: ccModule.InVendorRamdisk(),
+		bootstrap:       mod.Bootstrap(),
+		inRecovery:      mod.InRecovery(),
+		inRamdisk:       mod.InRamdisk(),
+		inVendorRamdisk: mod.InVendorRamdisk(),
 
 		// crateType indicates what type of crate to build
 		crateType: "staticlib",
@@ -402,6 +402,11 @@
 		linkFlags = append(linkFlags, dynamicLinker)
 	}
 
+	if generatedLib := cc.GenerateRustStaticlib(ctx, deps.ccRlibDeps); generatedLib != nil {
+		deps.StaticLibs = append(deps.StaticLibs, generatedLib)
+		linkFlags = append(linkFlags, generatedLib.String())
+	}
+
 	libFlags := makeLibFlags(deps)
 
 	// Collect dependencies
diff --git a/rust/library.go b/rust/library.go
index 24ae8b0..7f5861f 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -737,12 +737,15 @@
 	if library.rlib() {
 		library.flagExporter.exportStaticLibs(deps.staticLibObjects...)
 	}
-
 	// Since we have FFI rlibs, we need to collect their includes as well
 	if library.static() || library.shared() || library.rlib() || library.stubs() {
-		android.SetProvider(ctx, cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
+		ccExporter := cc.FlagExporterInfo{
 			IncludeDirs: android.FirstUniquePaths(library.includeDirs),
-		})
+		}
+		if library.rlib() {
+			ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedCcRlibDeps...)
+		}
+		android.SetProvider(ctx, cc.FlagExporterInfoProvider, ccExporter)
 	}
 
 	if library.shared() || library.stubs() {
diff --git a/rust/rust.go b/rust/rust.go
index ad68d60..4eec5d2 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -495,6 +495,10 @@
 	depFlags     []string
 	depLinkFlags []string
 
+	// track cc static-libs that have Rlib dependencies
+	reexportedCcRlibDeps []cc.RustRlibDep
+	ccRlibDeps           []cc.RustRlibDep
+
 	// 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
@@ -1531,6 +1535,13 @@
 					}
 				}
 
+				if !mod.Rlib() {
+					depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...)
+				} else {
+					// rlibs need to reexport these
+					depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
+				}
+
 			case depTag == procMacroDepTag:
 				directProcMacroDeps = append(directProcMacroDeps, linkableInfo)
 				mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
@@ -1651,8 +1662,8 @@
 				} else {
 					// Otherwise add to staticLibObjects, which only propagate through rlibs to their dependents.
 					depPaths.staticLibObjects = append(depPaths.staticLibObjects, ccLibPath.String())
-
 				}
+
 				depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
 
 				exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
@@ -1660,6 +1671,14 @@
 				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
 				depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
 				depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
+
+				if !mod.Rlib() {
+					// rlibs don't need to build the generated static library, so they don't need to track these.
+					depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...)
+				} else {
+					depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
+				}
+
 				directStaticLibDeps = append(directStaticLibDeps, linkableInfo)
 
 				// Record baseLibName for snapshots.
@@ -1815,6 +1834,8 @@
 	depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths)
 	depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths)
 	depPaths.depLinkFlags = android.FirstUniqueStrings(depPaths.depLinkFlags)
+	depPaths.reexportedCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedCcRlibDeps, cc.EqRustRlibDeps)
+	depPaths.ccRlibDeps = android.FirstUniqueFunc(depPaths.ccRlibDeps, cc.EqRustRlibDeps)
 
 	return depPaths
 }
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 4390f55..2e016f0 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -449,12 +449,26 @@
 		}
 
 		rust_ffi_static {
+			name: "libfoo_from_rlib",
+			crate_name: "foo_from_rlib",
+			srcs: ["src/lib.rs"],
+			export_include_dirs: ["foo_includes"]
+		}
+
+		rust_ffi_static {
 			name: "libbuzz",
 			crate_name: "buzz",
 			srcs: ["src/lib.rs"],
 			export_include_dirs: ["buzz_includes"]
 		}
 
+		rust_ffi_static {
+			name: "libbuzz_from_rlib",
+			crate_name: "buzz_from_rlib",
+			srcs: ["src/lib.rs"],
+			export_include_dirs: ["buzz_includes"]
+		}
+
 		cc_library_shared {
 			name: "libcc_shared",
 			srcs:["foo.c"],
@@ -468,12 +482,34 @@
 			whole_static_libs: ["libfoo"],
 		}
 
+		cc_library_static {
+			name: "libcc_static_from_rlib",
+			srcs:["foo.c"],
+			static_libs: ["libbuzz_from_rlib"],
+			whole_static_libs: ["libfoo_from_rlib"],
+		}
+
 		cc_binary {
 			name: "ccBin",
 			srcs:["foo.c"],
 			static_libs: ["libcc_static", "libbar"],
 		}
-		`)
+
+		rust_library {
+			name: "librs",
+			srcs:["src/foo.rs"],
+			crate_name: "rs",
+			static_libs: ["libcc_static_from_rlib"],
+		}
+
+		rust_binary {
+			name: "rsBin",
+			srcs:["src/foo.rs"],
+			crate_name: "rsBin",
+			rlibs: ["librs", "libbar"],
+			static_libs: ["libcc_static"],
+		}
+	`)
 
 	libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_rlib_rlib-std").Rule("rustc")
 	libcc_shared_rustc := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("rustc")
@@ -482,6 +518,9 @@
 	ccbin_rustc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("rustc")
 	ccbin_ld := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("ld")
 	ccbin_cc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("cc")
+	rustbin_genlib := ctx.ModuleForTests("rsBin", "android_arm64_armv8-a").Output("generated_rust_staticlib/librustlibs.a")
+	rustbin := ctx.ModuleForTests("rsBin", "android_arm64_armv8-a").Output("unstripped/rsBin")
+	librs_rlib := ctx.ModuleForTests("librs", "android_arm64_armv8-a_rlib_dylib-std").MaybeOutput("generated_rust_staticlib/librustlibs.a")
 
 	if !strings.Contains(libbar.Args["rustcFlags"], "crate-type=rlib") {
 		t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", "rlib", libbar.Args["rustcFlags"])
@@ -513,7 +552,7 @@
 	// Make sure the static lib is included in the cc command
 	if !strings.Contains(ccbin_ld.Args["libFlags"], "generated_rust_staticlib/librustlibs.a") {
 		t.Errorf("missing generated static library in linker step libFlags, expecting %#v, libFlags: %#v",
-			"ccBin.generated_rust_staticlib.a", ccbin_ld.Args["libFlags"])
+			"generated_rust_staticlib/librustlibs.a", ccbin_ld.Args["libFlags"])
 	}
 
 	// Make sure the static lib includes are in the ld command
@@ -534,11 +573,43 @@
 		t.Errorf("Missing direct dependency libbar when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
 	}
 
+	// Make sure the static lib is included in the rustc command
+	if !strings.Contains(rustbin.Args["linkFlags"], "generated_rust_staticlib/librustlibs.a") {
+		t.Errorf("missing generated static library in linker step libFlags in Rust module, expecting %#v, libFlags: %#v",
+			"generated_rust_staticlib/librustlibs.a", rustbin.Args["libFlags"])
+	}
+
+	// Make sure that direct dependencies and indirect whole static dependencies are
+	// propagating correctly for the rlib -> cc_library_static -> rust_* generated library example.
+	if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo=") {
+		t.Errorf("Missing indirect whole_static_lib dependency libfoo from cc static_lib when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+	}
+	if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern buzz=") {
+		t.Errorf("Indirect rlib dependency libbuzz from cc static_lib found when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+	}
+	if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern bar=") {
+		t.Errorf("Direct rlib dependency libbar getting included in the generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+	}
+	if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo_from_rlib=") {
+		t.Errorf("Missing indirect whole_static_lib dependency libfoo_from_rlib from cc static_lib when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+	}
+	if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern buzz_from_rlib=") {
+		// While static-libs propagate for rust modules, this is not the
+		// expected behavior for cc modules. Thus, libbuzz_from_rlib would
+		// be expected to have to be re-declared as a direct rlib dependency.
+		t.Errorf("Indirect rlib dependency libbuzz_from_rlib from cc static_lib found when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+	}
+
 	// Test indirect includes propagation
 	if !strings.Contains(ccbin_cc.Args["cFlags"], "-Ifoo_includes") {
 		t.Errorf("missing rlibs includes, expecting %#v, cFlags: %#v",
 			"-Ifoo_includes", ccbin_cc.Args)
 	}
+
+	// Make sure we're not generating superfluous mto staticlibs.
+	if librs_rlib.Rule != nil {
+		t.Error("rlibs should not be generating mto staticlibs", "rlib", libbar.Args["rustcFlags"])
+	}
 }
 
 func assertString(t *testing.T, got, expected string) {