rust: Add vendor and recovery dylib support.

Adds dylib support for vendor and recovery images.

This changes the default linkage for vendor and recovery images to
dylib, which matches the platform default linkage. This also means that
by default, dylib-std variants are used for rlib dependencies.

Bug: 204303985
Test: Soong tests.
Test: m dist vendor-snapshot
Test: RECOVERY_SNAPSHOT_VERSION=current m dist recovery-snapshot
Change-Id: If84074b8615a70c45e7e162abeb853dc8c34d49a
diff --git a/apex/apex_test.go b/apex/apex_test.go
index f7a4dea..df138e0 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -10553,6 +10553,7 @@
 			src: "libc.so",
 			min_sdk_version: "29",
 			recovery_available: true,
+			vendor_available: true,
 		}
 		api_imports {
 			name: "api_imports",
diff --git a/cc/cc.go b/cc/cc.go
index 6087970..c13f7c9 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1079,6 +1079,10 @@
 	return false
 }
 
+func (c *Module) RlibStd() bool {
+	panic(fmt.Errorf("RlibStd called on non-Rust module: %q", c.BaseModuleName()))
+}
+
 func (c *Module) RustLibraryInterface() bool {
 	return false
 }
diff --git a/cc/linkable.go b/cc/linkable.go
index 19e6501..2099399 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -87,6 +87,12 @@
 	// SnapshotStaticLibs returns the list of static library dependencies for this module.
 	SnapshotStaticLibs() []string
 
+	// SnapshotDylibs returns the list of dylib library dependencies for this module.
+	SnapshotDylibs() []string
+
+	// SnapshotRlibs returns the list of rlib library dependencies for this module.
+	SnapshotRlibs() []string
+
 	// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
 	IsSnapshotPrebuilt() bool
 }
@@ -239,6 +245,9 @@
 	// Dylib returns true if this is an dylib module.
 	Dylib() bool
 
+	// RlibStd returns true if this is an rlib which links against an rlib libstd.
+	RlibStd() bool
+
 	// Static returns true if this is a static library module.
 	Static() bool
 
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index a5729df..bb13310 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -100,6 +100,7 @@
 	snapshotBinarySuffix = "_binary."
 	snapshotObjectSuffix = "_object."
 	SnapshotRlibSuffix   = "_rlib."
+	SnapshotDylibSuffix  = "_dylib."
 )
 
 type SnapshotProperties struct {
@@ -107,6 +108,7 @@
 	Static_libs []string `android:"arch_variant"`
 	Shared_libs []string `android:"arch_variant"`
 	Rlibs       []string `android:"arch_variant"`
+	Dylibs      []string `android:"arch_variant"`
 	Vndk_libs   []string `android:"arch_variant"`
 	Binaries    []string `android:"arch_variant"`
 	Objects     []string `android:"arch_variant"`
@@ -186,6 +188,7 @@
 	staticLibs := collectSnapshotMap(s.properties.Static_libs, snapshotSuffix, SnapshotStaticSuffix)
 	sharedLibs := collectSnapshotMap(s.properties.Shared_libs, snapshotSuffix, SnapshotSharedSuffix)
 	rlibs := collectSnapshotMap(s.properties.Rlibs, snapshotSuffix, SnapshotRlibSuffix)
+	dylibs := collectSnapshotMap(s.properties.Dylibs, snapshotSuffix, SnapshotDylibSuffix)
 	vndkLibs := collectSnapshotMap(s.properties.Vndk_libs, "", vndkSuffix)
 	for k, v := range vndkLibs {
 		sharedLibs[k] = v
@@ -198,11 +201,12 @@
 		StaticLibs: staticLibs,
 		SharedLibs: sharedLibs,
 		Rlibs:      rlibs,
+		Dylibs:     dylibs,
 	})
 }
 
 type SnapshotInfo struct {
-	HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs, Rlibs map[string]string
+	HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs, Rlibs, Dylibs map[string]string
 }
 
 var SnapshotInfoProvider = blueprint.NewMutatorProvider(SnapshotInfo{}, "deps")
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index cf4617d..1ee120e 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -57,6 +57,14 @@
 	return m.Properties.SnapshotStaticLibs
 }
 
+func (m *Module) SnapshotRlibs() []string {
+	return []string{}
+}
+
+func (m *Module) SnapshotDylibs() []string {
+	return []string{}
+}
+
 // snapshotLibraryInterface is an interface for libraries captured to VNDK / vendor snapshots.
 type snapshotLibraryInterface interface {
 	libraryInterface
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index d2531c0..9ea337b 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -108,10 +108,10 @@
 				return false
 			}
 		}
-		if sanitizable.Static() {
+		if sanitizable.Static() || sanitizable.Rlib() {
 			return sanitizable.OutputFile().Valid() && !isPrivate(image, m)
 		}
-		if sanitizable.Shared() || sanitizable.Rlib() {
+		if sanitizable.Shared() || sanitizable.Dylib() {
 			if !sanitizable.OutputFile().Valid() {
 				return false
 			}
@@ -153,6 +153,8 @@
 	SharedLibs  []string `json:",omitempty"`
 	StaticLibs  []string `json:",omitempty"`
 	RuntimeLibs []string `json:",omitempty"`
+	Dylibs      []string `json:",omitempty"`
+	Rlibs       []string `json:",omitempty"`
 
 	// extra config files
 	InitRc         []string `json:",omitempty"`
@@ -283,8 +285,17 @@
 			if m.Shared() {
 				prop.SharedLibs = m.SnapshotSharedLibs()
 			}
-			// static libs dependencies are required to collect the NOTICE files.
+
+			// dylibs collect both shared and dylib dependencies.
+			if m.Dylib() {
+				prop.SharedLibs = m.SnapshotSharedLibs()
+				prop.Dylibs = m.SnapshotDylibs()
+			}
+
+			// static and rlib libs dependencies are required to collect the NOTICE files.
 			prop.StaticLibs = m.SnapshotStaticLibs()
+			prop.Rlibs = m.SnapshotRlibs()
+
 			if sanitizable, ok := m.(PlatformSanitizeable); ok {
 				if sanitizable.Static() && sanitizable.SanitizePropDefined() {
 					prop.SanitizeMinimalDep = sanitizable.MinimalRuntimeDep() || sanitizable.MinimalRuntimeNeeded()
@@ -299,13 +310,15 @@
 				libType = "shared"
 			} else if m.Rlib() {
 				libType = "rlib"
+			} else if m.Dylib() {
+				libType = "dylib"
 			} else {
 				libType = "header"
 			}
 
 			var stem string
 
-			// install .a or .so
+			// install .a, .rlib, .dylib.so, or .so
 			if libType != "header" {
 				libPath := m.OutputFile().Path()
 				stem = libPath.Base()
@@ -328,6 +341,12 @@
 						}
 					}
 				}
+				if m.Rlib() && m.RlibStd() {
+					// rlibs produce both rlib-std and dylib-std variants
+					ext := filepath.Ext(stem)
+					stem = strings.TrimSuffix(stem, ext) + ".rlib-std" + ext
+					prop.ModuleName += ".rlib-std"
+				}
 				snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, m.RelativeInstallPath(), stem)
 				ret = append(ret, copyFile(ctx, libPath, snapshotLibOut, fake))
 			} else {
@@ -341,8 +360,12 @@
 			prop.StaticExecutable = m.StaticExecutable()
 			prop.InstallInRoot = m.InstallInRoot()
 			prop.SharedLibs = m.SnapshotSharedLibs()
-			// static libs dependencies are required to collect the NOTICE files.
+			prop.Dylibs = m.SnapshotDylibs()
+
+			// static and rlib dependencies are required to collect the NOTICE files.
 			prop.StaticLibs = m.SnapshotStaticLibs()
+			prop.Rlibs = m.SnapshotRlibs()
+
 			// install bin
 			binPath := m.OutputFile().Path()
 			snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
diff --git a/rust/binary.go b/rust/binary.go
index 2de92c1..e6f1539 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -158,9 +158,6 @@
 	// Binaries default to dylib dependencies for device, rlib for host.
 	if binary.preferRlib() {
 		return rlibAutoDep
-	} else if mod, ok := ctx.Module().(*Module); ok && mod.InVendor() {
-		// Vendor Rust binaries should prefer rlibs.
-		return rlibAutoDep
 	} else if ctx.Device() {
 		return dylibAutoDep
 	} else {
@@ -171,8 +168,6 @@
 func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
 	if binary.preferRlib() {
 		return RlibLinkage
-	} else if ctx.RustModule().InVendor() {
-		return RlibLinkage
 	}
 	return binary.baseCompiler.stdLinkage(ctx)
 }
diff --git a/rust/image.go b/rust/image.go
index 50bf02a..53fb5c0 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -220,9 +220,6 @@
 }
 
 func (mod *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
-	// Rust does not support installing to the product image yet.
-	vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
-
 	if Bool(mod.VendorProperties.Double_loadable) {
 		mctx.PropertyErrorf("double_loadable",
 			"Rust modules do not yet support double loading")
@@ -232,11 +229,6 @@
 			mctx.PropertyErrorf("vendor_ramdisk_available", "cannot be set for rust_ffi or rust_ffi_shared modules.")
 		}
 	}
-	if vendorSpecific {
-		if lib, ok := mod.compiler.(libraryInterface); ok && lib.buildDylib() {
-			mctx.PropertyErrorf("vendor", "Vendor-only dylibs are not yet supported, use rust_library_rlib.")
-		}
-	}
 	if mctx.ProductSpecific() {
 		if lib, ok := mod.compiler.(libraryInterface); ok && lib.buildDylib() {
 			mctx.PropertyErrorf("product", "Product-only dylibs are not yet supported, use rust_library_rlib.")
diff --git a/rust/library.go b/rust/library.go
index 331763a..3f480a2 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -21,7 +21,6 @@
 
 	"android/soong/android"
 	"android/soong/cc"
-	"android/soong/snapshot"
 )
 
 var (
@@ -236,10 +235,7 @@
 }
 
 func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
-	if ctx.Module().(*Module).InVendor() {
-		// Vendor modules should statically link libstd.
-		return rlibAutoDep
-	} else if library.preferRlib() {
+	if library.preferRlib() {
 		return rlibAutoDep
 	} else if library.rlib() || library.static() {
 		return rlibAutoDep
@@ -251,10 +247,7 @@
 }
 
 func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
-	if ctx.RustModule().InVendor() {
-		// Vendor modules should statically link libstd.
-		return RlibLinkage
-	} else if library.static() || library.MutatedProperties.VariantIsStaticStd {
+	if library.static() || library.MutatedProperties.VariantIsStaticStd {
 		return RlibLinkage
 	} else if library.baseCompiler.preferRlib() {
 		return RlibLinkage
@@ -693,24 +686,6 @@
 				v.(*Module).Disable()
 			}
 
-			variation := v.(*Module).ModuleBase.ImageVariation().Variation
-			if strings.HasPrefix(variation, cc.VendorVariationPrefix) {
-				// TODO(b/204303985)
-				// Disable vendor dylibs until they are supported
-				v.(*Module).Disable()
-			}
-
-			if strings.HasPrefix(variation, cc.VendorVariationPrefix) &&
-				m.HasVendorVariant() &&
-				!snapshot.IsVendorProprietaryModule(mctx) &&
-				strings.TrimPrefix(variation, cc.VendorVariationPrefix) == mctx.DeviceConfig().VndkVersion() {
-
-				// cc.MutateImage runs before LibraryMutator, so vendor variations which are meant for rlibs only are
-				// produced for Dylibs; however, dylibs should not be enabled for boardVndkVersion for
-				// non-vendor proprietary modules.
-				v.(*Module).Disable()
-			}
-
 		case "source":
 			v.(*Module).compiler.(libraryInterface).setSource()
 			// The source variant does not produce any library.
@@ -747,10 +722,9 @@
 				dylib := modules[1].(*Module)
 				rlib.compiler.(libraryInterface).setRlibStd()
 				dylib.compiler.(libraryInterface).setDylibStd()
-				if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation ||
-					strings.HasPrefix(dylib.ModuleBase.ImageVariation().Variation, cc.VendorVariationPrefix) {
+				if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation {
 					// TODO(b/165791368)
-					// Disable rlibs that link against dylib-std on vendor and vendor ramdisk variations until those dylib
+					// Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib
 					// variants are properly supported.
 					dylib.Disable()
 				}
diff --git a/rust/rust.go b/rust/rust.go
index e524c9f..1b8ebd9 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -91,6 +91,8 @@
 	// Used by vendor snapshot to record dependencies from snapshot modules.
 	SnapshotSharedLibs []string `blueprint:"mutated"`
 	SnapshotStaticLibs []string `blueprint:"mutated"`
+	SnapshotRlibs      []string `blueprint:"mutated"`
+	SnapshotDylibs     []string `blueprint:"mutated"`
 
 	// Make this module available when building for ramdisk.
 	// On device without a dedicated recovery partition, the module is only
@@ -258,6 +260,15 @@
 	return false
 }
 
+func (mod *Module) RlibStd() bool {
+	if mod.compiler != nil {
+		if library, ok := mod.compiler.(libraryInterface); ok && library.rlib() {
+			return library.rlibStd()
+		}
+	}
+	panic(fmt.Errorf("RlibStd() called on non-rlib module: %q", mod.BaseModuleName()))
+}
+
 func (mod *Module) Rlib() bool {
 	if mod.compiler != nil {
 		if library, ok := mod.compiler.(libraryInterface); ok {
@@ -1225,6 +1236,8 @@
 				}
 				directDylibDeps = append(directDylibDeps, rustDep)
 				mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName)
+				mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName))
+
 			case rlibDepTag:
 
 				rlib, ok := rustDep.compiler.(libraryInterface)
@@ -1234,6 +1247,8 @@
 				}
 				directRlibDeps = append(directRlibDeps, rustDep)
 				mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName)
+				mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName))
+
 			case procMacroDepTag:
 				directProcMacroDeps = append(directProcMacroDeps, rustDep)
 				mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
@@ -1518,10 +1533,10 @@
 	}
 
 	// dylibs
-	actx.AddVariationDependencies(
-		append(commonDepVariations, []blueprint.Variation{
-			{Mutator: "rust_libraries", Variation: dylibVariation}}...),
-		dylibDepTag, deps.Dylibs...)
+	dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation})
+	for _, lib := range deps.Dylibs {
+		addDylibDependency(actx, lib, mod, &snapshotInfo, dylibDepVariations, dylibDepTag)
+	}
 
 	// rustlibs
 	if deps.Rustlibs != nil && !mod.compiler.Disabled() {
@@ -1536,8 +1551,11 @@
 				// otherwise select the rlib variant.
 				autoDepVariations := append(commonDepVariations,
 					blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation})
-				if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) {
-					actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib)
+
+				replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs)
+
+				if actx.OtherModuleDependencyVariantExists(autoDepVariations, replacementLib) {
+					addDylibDependency(actx, lib, mod, &snapshotInfo, autoDepVariations, autoDep.depTag)
 				} else {
 					// If there's no dylib dependency available, try to add the rlib dependency instead.
 					addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
@@ -1549,16 +1567,14 @@
 	if deps.Stdlibs != nil {
 		if mod.compiler.stdLinkage(ctx) == RlibLinkage {
 			for _, lib := range deps.Stdlibs {
-				depTag := rlibDepTag
 				lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
-
 				actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...),
-					depTag, lib)
+					rlibDepTag, lib)
 			}
 		} else {
-			actx.AddVariationDependencies(
-				append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"}),
-				dylibDepTag, deps.Stdlibs...)
+			for _, lib := range deps.Stdlibs {
+				addDylibDependency(actx, lib, mod, &snapshotInfo, dylibDepVariations, dylibDepTag)
+			}
 		}
 	}
 
@@ -1636,6 +1652,11 @@
 	actx.AddVariationDependencies(variations, rlibDepTag, lib)
 }
 
+func addDylibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo **cc.SnapshotInfo, variations []blueprint.Variation, depTag dependencyTag) {
+	lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, snapshotInfo, actx).Dylibs)
+	actx.AddVariationDependencies(variations, depTag, lib)
+}
+
 func BeginMutator(ctx android.BottomUpMutatorContext) {
 	if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() {
 		mod.beginMutator(ctx)
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 64f90b6..3f4e296 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -79,14 +79,18 @@
 }
 
 const (
-	sharedVendorVariant   = "android_vendor.29_arm64_armv8-a_shared"
-	rlibVendorVariant     = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
-	sharedRecoveryVariant = "android_recovery_arm64_armv8-a_shared"
-	rlibRecoveryVariant   = "android_recovery_arm64_armv8-a_rlib_rlib-std"
-	binaryCoreVariant     = "android_arm64_armv8-a"
-	binaryVendorVariant   = "android_vendor.29_arm64_armv8-a"
-	binaryProductVariant  = "android_product.29_arm64_armv8-a"
-	binaryRecoveryVariant = "android_recovery_arm64_armv8-a"
+	sharedVendorVariant        = "android_vendor.29_arm64_armv8-a_shared"
+	rlibVendorVariant          = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
+	rlibDylibStdVendorVariant  = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
+	dylibVendorVariant         = "android_vendor.29_arm64_armv8-a_dylib"
+	sharedRecoveryVariant      = "android_recovery_arm64_armv8-a_shared"
+	rlibRecoveryVariant        = "android_recovery_arm64_armv8-a_rlib_dylib-std"
+	rlibRlibStdRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_rlib-std"
+	dylibRecoveryVariant       = "android_recovery_arm64_armv8-a_dylib"
+	binaryCoreVariant          = "android_arm64_armv8-a"
+	binaryVendorVariant        = "android_vendor.29_arm64_armv8-a"
+	binaryProductVariant       = "android_product.29_arm64_armv8-a"
+	binaryRecoveryVariant      = "android_recovery_arm64_armv8-a"
 )
 
 func testRustVndkFs(t *testing.T, bp string, fs android.MockFS) *android.TestContext {
diff --git a/rust/snapshot_prebuilt.go b/rust/snapshot_prebuilt.go
index 2f79cc5..32d3916 100644
--- a/rust/snapshot_prebuilt.go
+++ b/rust/snapshot_prebuilt.go
@@ -21,10 +21,6 @@
 	"github.com/google/blueprint/proptools"
 )
 
-const (
-	snapshotRlibSuffix = "_rlib."
-)
-
 type snapshotLibraryDecorator struct {
 	cc.BaseSnapshotDecorator
 	*libraryDecorator
@@ -44,6 +40,8 @@
 func registerRustSnapshotModules(ctx android.RegistrationContext) {
 	cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
 		"vendor_snapshot_rlib", VendorSnapshotRlibFactory)
+	cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
+		"vendor_snapshot_dylib", VendorSnapshotDylibFactory)
 	cc.RecoverySnapshotImageSingleton.RegisterAdditionalModule(ctx,
 		"recovery_snapshot_rlib", RecoverySnapshotRlibFactory)
 }
@@ -77,12 +75,11 @@
 		variant = cc.SnapshotSharedSuffix
 	} else if library.rlib() {
 		variant = cc.SnapshotRlibSuffix
+	} else if library.dylib() {
+		variant = cc.SnapshotDylibSuffix
 	}
 
-	if !library.dylib() {
-		// TODO(184042776): Remove this check when dylibs are supported in snapshots.
-		library.SetSnapshotAndroidMkSuffix(ctx, variant)
-	}
+	library.SetSnapshotAndroidMkSuffix(ctx, variant)
 
 	if !library.MatchesWithDevice(ctx.DeviceConfig()) {
 		return buildOutput{}
@@ -107,6 +104,17 @@
 	return module.Init()
 }
 
+// vendor_snapshot_dylib is a special prebuilt dylib library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_dylib
+// overrides the vendor variant of the rust dylib library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func VendorSnapshotDylibFactory() android.Module {
+	module, prebuilt := snapshotLibraryFactory(cc.VendorSnapshotImageSingleton, cc.SnapshotDylibSuffix)
+	prebuilt.libraryDecorator.BuildOnlyDylib()
+	prebuilt.libraryDecorator.setNoStdlibs()
+	return module.Init()
+}
+
 func RecoverySnapshotRlibFactory() android.Module {
 	module, prebuilt := snapshotLibraryFactory(cc.RecoverySnapshotImageSingleton, cc.SnapshotRlibSuffix)
 	prebuilt.libraryDecorator.BuildOnlyRlib()
diff --git a/rust/snapshot_utils.go b/rust/snapshot_utils.go
index 8dabd9b..55c85e6 100644
--- a/rust/snapshot_utils.go
+++ b/rust/snapshot_utils.go
@@ -42,8 +42,7 @@
 
 func (mod *Module) IsSnapshotLibrary() bool {
 	if lib, ok := mod.compiler.(libraryInterface); ok {
-		// Rust-native dylibs are not snapshot supported yet. Only snapshot the rlib-std variants of rlibs.
-		return lib.shared() || lib.static() || (lib.rlib() && lib.rlibStd())
+		return lib.shared() || lib.static() || lib.rlib() || lib.dylib()
 	}
 	return false
 }
@@ -61,6 +60,14 @@
 	return mod.Properties.SnapshotStaticLibs
 }
 
+func (mod *Module) SnapshotRlibs() []string {
+	return mod.Properties.SnapshotRlibs
+}
+
+func (mod *Module) SnapshotDylibs() []string {
+	return mod.Properties.SnapshotDylibs
+}
+
 func (mod *Module) Symlinks() []string {
 	// TODO update this to return the list of symlinks when Rust supports defining symlinks
 	return nil
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
index 2e7a330..387d170 100644
--- a/rust/vendor_snapshot_test.go
+++ b/rust/vendor_snapshot_test.go
@@ -48,15 +48,13 @@
 		crate_name: "rustvendor_available",
 		srcs: ["lib.rs"],
 		vendor_available: true,
-		include_dirs: ["rust_headers/"],
 	}
 
-	rust_library_rlib {
+	rust_library {
 		name: "librustvendor",
 		crate_name: "rustvendor",
 		srcs: ["lib.rs"],
 		vendor: true,
-		include_dirs: ["rust_headers/"],
 	}
 
 	rust_binary {
@@ -116,7 +114,7 @@
 			filepath.Join(staticDir, "libffivendor.a.json"))
 
 		// For rlib libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
-		rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+		rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
 		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
 		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
 		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib", rlibDir, rlibVariant)
@@ -125,6 +123,25 @@
 		jsonFiles = append(jsonFiles,
 			filepath.Join(rlibDir, "librustvendor.rlib.json"))
 
+		// For rlib libraries, all rlib-std variants vendor:true and vendor_available modules (including VNDK) are captured.
+		rlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibStdVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib-std.rlib", rlibDir, rlibStdVariant)
+		jsonFiles = append(jsonFiles,
+			filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
+		jsonFiles = append(jsonFiles,
+			filepath.Join(rlibDir, "librustvendor.rlib.json"))
+
+		// For dylib libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
+		dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
+		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.dylib.so", dylibDir, dylibVariant)
+		jsonFiles = append(jsonFiles,
+			filepath.Join(dylibDir, "librustvendor_available.dylib.so.json"))
+		jsonFiles = append(jsonFiles,
+			filepath.Join(dylibDir, "librustvendor.dylib.so.json"))
+
 		// For binary executables, all vendor:true and vendor_available modules are captured.
 		if archType == "arm64" {
 			binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
@@ -209,21 +226,32 @@
 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
 
 		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
-		rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+		rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
+		rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
 		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+		dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
+		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
 
 		// Included modules
 		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant)
 		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.so", sharedDir, sharedVariant)
 		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib-std.rlib.json"))
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_available.dylib.so.json"))
 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_available.so.json"))
 
 		// Excluded modules. Modules not included in the directed vendor snapshot
 		// are still include as fake modules.
 		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib", rlibDir, rlibVariant)
+		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.dylib.so", dylibDir, dylibVariant)
 		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "libffivendor_exclude", "libffivendor_exclude.so", sharedDir, sharedVariant)
 		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib.json"))
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib-std.rlib.json"))
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_exclude.dylib.so.json"))
 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_exclude.so.json"))
 	}
 
@@ -274,7 +302,7 @@
 			vendor_available: true,
 		}
 
-		rust_library_rlib {
+		rust_library {
 			name: "librust_exclude",
 			crate_name: "rust_exclude",
 			srcs: ["exclude.rs"],
@@ -308,6 +336,14 @@
 	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibVendorVariant)
 	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibVendorVariant)
 
+	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, rlibDylibStdVendorVariant)
+	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibDylibStdVendorVariant)
+	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibDylibStdVendorVariant)
+
+	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, dylibVendorVariant)
+	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, dylibVendorVariant)
+	cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, dylibVendorVariant)
+
 	// Verify the content of the vendor snapshot.
 
 	snapshotDir := "vendor-snapshot"
@@ -327,14 +363,22 @@
 
 		sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-		rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+
+		rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
+		rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
 		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+		dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
+		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
 
 		// Included modules
 		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
 		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib", rlibDir, rlibVariant)
 		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib.json"))
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib-std.rlib.json"))
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.dylib.so", dylibDir, dylibVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librust_include.dylib.so.json"))
 
 		// Excluded modules
 		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
@@ -345,6 +389,12 @@
 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_exclude.rlib.json"))
 		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib", rlibDir, rlibVariant)
 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.json"))
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.rlib-std.json"))
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_exclude", "librust_exclude.dylib.so", dylibDir, dylibVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_exclude.dylib.so.json"))
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.dylib.so", dylibDir, dylibVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_available_exclude.dylib.so.json"))
 	}
 
 	// Verify that each json file for an included module has a rule.
@@ -525,7 +575,7 @@
 		srcs: ["client.rs"],
 	}
 
-	rust_library_rlib {
+	rust_library {
 		name: "libclient_rust",
 		crate_name: "client_rust",
 		vendor: true,
@@ -572,6 +622,11 @@
 				rlibs: [
 					"libstd",
 					"librust_vendor_available",
+					"librust_vendor_available.rlib-std"
+				],
+				dylibs: [
+					"libstd",
+					"librust_vendor_available",
 				],
 				binaries: [
 					"bin",
@@ -600,6 +655,10 @@
 					"libstd",
 					"librust_vendor_available",
 				],
+				dylibs: [
+					"libstd",
+					"librust_vendor_available",
+				],
 				binaries: [
 					"bin32",
 				],
@@ -679,6 +738,52 @@
 		},
 	}
 
+	vendor_snapshot_rlib {
+		name: "librust_vendor_available.rlib-std",
+		version: "30",
+		target_arch: "arm64",
+		vendor: true,
+		arch: {
+			arm64: {
+				src: "librust_vendor_available.rlib-std.rlib",
+			},
+			arm: {
+				src: "librust_vendor_available.rlib-std.rlib",
+			},
+		},
+	}
+
+	vendor_snapshot_dylib {
+		name: "libstd",
+		version: "30",
+		target_arch: "arm64",
+		vendor: true,
+		sysroot: true,
+		arch: {
+			arm64: {
+				src: "libstd.dylib.so",
+			},
+			arm: {
+				src: "libstd.dylib.so",
+			},
+		},
+	}
+
+	vendor_snapshot_dylib {
+		name: "librust_vendor_available",
+		version: "30",
+		target_arch: "arm64",
+		vendor: true,
+		arch: {
+			arm64: {
+				src: "librust_vendor_available.dylib.so",
+			},
+			arm: {
+				src: "librust_vendor_available.dylib.so",
+			},
+		},
+	}
+
 	vendor_snapshot_object {
 		name: "crtend_android",
 		version: "30",
@@ -921,6 +1026,9 @@
 		"vendor/liblog.so":                              nil,
 		"vendor/libstd.rlib":                            nil,
 		"vendor/librust_vendor_available.rlib":          nil,
+		"vendor/librust_vendor_available.rlib-std.rlib": nil,
+		"vendor/libstd.dylib.so":                        nil,
+		"vendor/librust_vendor_available.dylib.so":      nil,
 		"vendor/crtbegin_so.o":                          nil,
 		"vendor/crtend_so.o":                            nil,
 		"vendor/libclang_rt.builtins-aarch64-android.a": nil,
@@ -931,7 +1039,9 @@
 	}
 
 	sharedVariant := "android_vendor.30_arm64_armv8-a_shared"
-	rlibVariant := "android_vendor.30_arm64_armv8-a_rlib_rlib-std"
+	rlibVariant := "android_vendor.30_arm64_armv8-a_rlib_dylib-std"
+	rlibRlibStdVariant := "android_vendor.30_arm64_armv8-a_rlib_rlib-std"
+	dylibVariant := "android_vendor.30_arm64_armv8-a_dylib"
 	staticVariant := "android_vendor.30_arm64_armv8-a_static"
 	binaryVariant := "android_vendor.30_arm64_armv8-a"
 
@@ -963,14 +1073,9 @@
 		t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
 	}
 
-	libclientAndroidMkRlibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkRlibs
-	if g, w := libclientAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g)
-	}
-
 	libclientAndroidMkDylibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkDylibs
-	if len(libclientAndroidMkDylibs) > 0 {
-		t.Errorf("wanted libclient libclientAndroidMkDylibs [], got %q", libclientAndroidMkDylibs)
+	if g, w := libclientAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
+		t.Errorf("wanted libclient libclientAndroidMkDylibs %q, got %q", w, libclientAndroidMkDylibs)
 	}
 
 	libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs
@@ -979,22 +1084,39 @@
 	}
 
 	libclientRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibVariant).Module().(*Module).Properties.AndroidMkRlibs
-	if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
-		t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g)
+	if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor"}; !reflect.DeepEqual(g, w) {
+		t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g)
+	}
+
+	libclientRlibStdRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibRlibStdVariant).Module().(*Module).Properties.AndroidMkRlibs
+	if g, w := libclientRlibStdRustAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
+		t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g)
+	}
+
+	libclientRustDylibAndroidMkDylibs := ctx.ModuleForTests("libclient_rust", dylibVariant).Module().(*Module).Properties.AndroidMkDylibs
+	if g, w := libclientRustDylibAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
+		t.Errorf("wanted dylib libclient libclientRustDylibAndroidMkDylibs %q, got %q", w, g)
 	}
 
 	// rust vendor snapshot must have ".vendor" suffix in AndroidMk
 	librustVendorAvailableSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_rlib.30.arm64", rlibVariant).Module()
 	librustVendorSnapshotMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0]
-	expectedRustVendorSnapshotName := "librust_vendor_available.vendor.rlib-std"
+	expectedRustVendorSnapshotName := "librust_vendor_available.vendor"
 	if librustVendorSnapshotMkName != expectedRustVendorSnapshotName {
 		t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotMkName, expectedRustVendorSnapshotName)
 	}
 
+	librustVendorAvailableDylibSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_dylib.30.arm64", dylibVariant).Module()
+	librustVendorSnapshotDylibMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableDylibSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0]
+	expectedRustVendorDylibSnapshotName := "librust_vendor_available.vendor"
+	if librustVendorSnapshotDylibMkName != expectedRustVendorDylibSnapshotName {
+		t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotDylibMkName, expectedRustVendorDylibSnapshotName)
+	}
+
 	rustVendorBinModule := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Module()
-	rustVendorBinMkRlibName := android.AndroidMkEntriesForTest(t, ctx, rustVendorBinModule)[0].EntryMap["LOCAL_RLIB_LIBRARIES"][0]
-	if rustVendorBinMkRlibName != expectedRustVendorSnapshotName {
-		t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkRlibName, expectedRustVendorSnapshotName)
+	rustVendorBinMkDylibName := android.AndroidMkEntriesForTest(t, ctx, rustVendorBinModule)[0].EntryMap["LOCAL_DYLIB_LIBRARIES"][0]
+	if rustVendorBinMkDylibName != expectedRustVendorSnapshotName {
+		t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkDylibName, expectedRustVendorSnapshotName)
 	}
 
 	binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustLink").Args["linkFlags"]
@@ -1051,18 +1173,18 @@
 		crate_name: "recovery_available",
 	}
 
-	rust_library_rlib {
-		name: "librecovery_rlib",
+	rust_library {
+		name: "librecovery_rustlib",
 		recovery: true,
 		srcs: ["foo.rs"],
-		crate_name: "recovery_rlib",
+		crate_name: "recovery_rustlib",
 	}
 
-	rust_library_rlib {
-		name: "librecovery_available_rlib",
+	rust_library {
+		name: "librecovery_available_rustlib",
 		recovery_available: true,
 		srcs: ["foo.rs"],
-		crate_name: "recovery_available_rlib",
+		crate_name: "recovery_available_rustlib",
 	}
 
 	rust_binary {
@@ -1113,13 +1235,29 @@
 			filepath.Join(staticDir, "librecovery_available.a.json"))
 
 		// For rlib libraries, all recovery:true and recovery_available modules are captured.
-		rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+		rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
 		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rlib", "librecovery_rlib.rlib", rlibDir, rlibVariant)
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rlib", "librecovery_available_rlib.rlib", rlibDir, rlibVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant)
 		jsonFiles = append(jsonFiles,
-			filepath.Join(rlibDir, "librecovery_rlib.rlib.json"),
-			filepath.Join(rlibDir, "librecovery_available_rlib.rlib.json"))
+			filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"),
+			filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json"))
+
+		rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		jsonFiles = append(jsonFiles,
+			filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"),
+			filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json"))
+
+		// For dylib libraries, all recovery:true and recovery_available modules are captured.
+		dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
+		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant)
+		jsonFiles = append(jsonFiles,
+			filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json"),
+			filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.so.json"))
 
 		// For binary executables, all recovery:true and recovery_available modules are captured.
 		if archType == "arm64" {
@@ -1169,25 +1307,25 @@
 			exclude_from_recovery_snapshot: true,
 			crate_name: "available_exclude",
 		}
-		rust_library_rlib {
-			name: "libinclude_rlib",
+		rust_library {
+			name: "libinclude_rustlib",
 			srcs: ["src/include.rs"],
 			recovery_available: true,
-			crate_name: "include_rlib",
+			crate_name: "include_rustlib",
 		}
-		rust_library_rlib {
-			name: "libexclude_rlib",
+		rust_library {
+			name: "libexclude_rustlib",
 			srcs: ["src/exclude.rs"],
 			recovery: true,
 			exclude_from_recovery_snapshot: true,
-			crate_name: "exclude_rlib",
+			crate_name: "exclude_rustlib",
 		}
-		rust_library_rlib {
-			name: "libavailable_exclude_rlib",
+		rust_library {
+			name: "libavailable_exclude_rustlib",
 			srcs: ["src/exclude.rs"],
 			recovery_available: true,
 			exclude_from_recovery_snapshot: true,
-			crate_name: "available_exclude_rlib",
+			crate_name: "available_exclude_rustlib",
 		}
 	`
 
@@ -1198,11 +1336,11 @@
 			recovery: true,
 			crate_name: "recovery",
 		}
-		rust_library_rlib {
-			name: "librecovery_rlib",
+		rust_library {
+			name: "librecovery_rustlib",
 			srcs: ["recovery.rs"],
 			recovery: true,
-			crate_name: "recovery_rlib",
+			crate_name: "recovery_rustlib",
 		}
 	`
 
@@ -1220,14 +1358,25 @@
 	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false, sharedRecoveryVariant)
 	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, sharedRecoveryVariant)
 	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, sharedRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rlib", false, rlibRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rlib", true, rlibRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rlib", true, rlibRecoveryVariant)
+
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRecoveryVariant)
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRecoveryVariant)
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant)
+
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRlibStdRecoveryVariant)
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRlibStdRecoveryVariant)
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant)
+
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, dylibRecoveryVariant)
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, dylibRecoveryVariant)
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, dylibRecoveryVariant)
 
 	// A recovery module is excluded, but by its path not the exclude_from_recovery_snapshot property
 	// ('device/' and 'vendor/' are default excluded). See snapshot/recovery_snapshot.go for more detail.
 	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, sharedRecoveryVariant)
-	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rlib", false, rlibRecoveryVariant)
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRecoveryVariant)
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRlibStdRecoveryVariant)
+	cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, dylibRecoveryVariant)
 
 	// Verify the content of the recovery snapshot.
 
@@ -1246,15 +1395,21 @@
 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
 
 		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
-		rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+		rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
+		rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+		dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
 		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
 
 		// Included modules
+
 		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rlib", "libinclude_rlib.rlib", rlibDir, rlibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rlib.rlib.json"))
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib", rlibDir, rlibVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib.json"))
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib-std.rlib.json"))
 
 		// Excluded modules
 		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
@@ -1263,12 +1418,27 @@
 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
 		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
 		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rlib", "libexclude_rlib.rlib", rlibDir, rlibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rlib.rlib.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rlib", "librecovery_rlib.rlib", rlibDir, rlibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rlib.rlib.json"))
-		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rlib", "libavailable_exclude_rlib.rlib", rlibDir, rlibVariant)
-		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rlib.rlib.json"))
+
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib", rlibDir, rlibVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib.json"))
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"))
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib", rlibDir, rlibVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib.json"))
+
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib-std.rlib.json"))
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"))
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib-std.rlib.json"))
+
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.dylib.so", dylibDir, dylibVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.dylib.so.json"))
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.dylib.so.json"))
+		cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.dylib.so", dylibDir, dylibVariant)
+		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.dylib.so.json"))
 	}
 
 	// Verify that each json file for an included module has a rule.
@@ -1302,15 +1472,15 @@
 		srcs: ["foo.rs"],
 	}
 
-	rust_library_rlib {
-		name: "librecovery_rlib",
+	rust_library {
+		name: "librecovery_rustlib",
 		recovery: true,
 		crate_name: "recovery",
 		srcs: ["foo.rs"],
 	}
 
-	rust_library_rlib {
-		name: "librecovery_available_rlib",
+	rust_library {
+		name: "librecovery_available_rustlib",
 		recovery_available: true,
 		crate_name: "recovery_available",
 		srcs: ["foo.rs"],
@@ -1335,7 +1505,7 @@
 	ctx := testRustRecoveryFsVersions(t, bp, rustMockedFiles, "current", "29", "current")
 	ctx.Config().TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
 	ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery"] = true
-	ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery_rlib"] = true
+	ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery_rustlib"] = true
 	ctx.Config().TestProductVariables.DirectedRecoverySnapshot = true
 
 	// Check recovery snapshot output.
@@ -1353,15 +1523,22 @@
 		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
 
 		sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
-		rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+		rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
+		rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+		dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
 		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
 		rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+		dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
 
 		// Included modules
 		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
-		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rlib", "librecovery_rlib.rlib", rlibDir, rlibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rlib.rlib.json"))
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"))
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"))
+		cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json"))
 
 		// TODO: When Rust supports the "prefer" property for prebuilts, perform this check.
 		/*
@@ -1374,8 +1551,12 @@
 		// are still included as fake modules.
 		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
 		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json"))
-		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rlib", "librecovery_available_rlib.rlib", rlibDir, rlibVariant)
-		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rlib.rlib.json"))
+		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json"))
+		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json"))
+		cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant)
+		includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.so.json"))
 	}
 
 	// Verify that each json file for an included module has a rule.