Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/rust/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 83 kB image not shown  

Quelle  rust.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2019 The Android Open Source Project
//
// 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 rust

import (
 "fmt"
 "os"
 "path/filepath"
 "slices"
 "strconv"
 "strings"

 "github.com/google/blueprint"
 "github.com/google/blueprint/depset"
 "github.com/google/blueprint/proptools"

 "android/soong/android"
 "android/soong/cc"
 cc_config "android/soong/cc/config"
 "android/soong/fuzz"
 "android/soong/rust/config"
)

//go:generate go run ../../blueprint/gobtools/codegen

var pctx = android.NewPackageContext("android/soong/rust")

// @auto-generate: gob
type LibraryInfo struct {
 Rlib  bool
 Dylib bool
}

// @auto-generate: gob
type CompilerInfo struct {
 StdLinkageForDevice    StdLinkage
 StdLinkageForNonDevice StdLinkage
 NoStdlibs              bool
 CrateName              string
 Edition                string
 CargoOutDir            android.OptionalPath
 Features               []string
 CrateRootPath          android.Path
 LibraryInfo            *LibraryInfo
 BuildTarget            android.Path
 CheckTarget            android.OptionalPath
}

// @auto-generate: gob
type ProtobufDecoratorInfo struct{}

// @auto-generate: gob
type SourceProviderInfo struct {
 Srcs                  android.Paths
 ProtobufDecoratorInfo *ProtobufDecoratorInfo
}

// @auto-generate: gob
type ProcMacroInfo struct {
 Dylib android.Path
}

// @auto-generate: gob
type RustInfo struct {
 AndroidMkSuffix               string
 RustSubName                   string
 TransitiveAndroidMkSharedLibs depset.DepSet[string]
 CompilerInfo                  *CompilerInfo
 SnapshotInfo                  *cc.SnapshotInfo
 SourceProviderInfo            *SourceProviderInfo
 ProcMacroInfo                 *ProcMacroInfo
 XrefRustFiles                 android.Paths
 DocTimestampFile              android.OptionalPath
 CollectDoc                    bool
}

var RustInfoProvider = blueprint.NewProvider[*RustInfo]()

func init() {
 android.RegisterModuleType("rust_defaults", defaultsFactory)
 android.PreDepsMutators(registerPreDepsMutators)
 android.PostDepsMutators(registerPostDepsMutators)
 pctx.Import("android/soong/android")
 pctx.Import("android/soong/rust/config")
 pctx.ImportAs("cc_config", "android/soong/cc/config")
}

func registerPreDepsMutators(ctx android.RegisterMutatorsContext) {
 ctx.Transition("rust_libraries", &libraryTransitionMutator{})
 ctx.Transition("rust_stdlinkage", &libstdTransitionMutator{})
 ctx.BottomUp("rust_begin", BeginMutator)
}

func registerPostDepsMutators(ctx android.RegisterMutatorsContext) {
 ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator)
}

type Flags struct {
 GlobalRustFlags   cc_config.FlagsWithDeps // Flags that apply globally to rust
 GlobalLinkFlags   cc_config.FlagsWithDeps // Flags that apply globally to linker
 RustFlags         []string                // Flags that apply to rust
 LinkFlags         cc_config.FlagsWithDeps // Flags that apply to linker
 LinkerScriptFlags []string                // Flags that should be visible to the android linker script
 ClippyFlags       []string                // Flags that apply to clippy-driver, during the linting
 RustdocFlags      []string                // Flags that apply to rustdoc
 Toolchain         config.Toolchain
 Coverage          bool
 Clippy            bool
 EmitXrefs         bool // If true, emit rules to aid cross-referencing
}

type BaseProperties struct {
 AndroidMkRlibs         []string `blueprint:"mutated"`
 AndroidMkDylibs        []string `blueprint:"mutated"`
 AndroidMkProcMacroLibs []string `blueprint:"mutated"`
 AndroidMkStaticLibs    []string `blueprint:"mutated"`
 AndroidMkHeaderLibs    []string `blueprint:"mutated"`

 ImageVariation string `blueprint:"mutated"`
 VndkVersion    string `blueprint:"mutated"`
 SubName        string `blueprint:"mutated"`

 // SubName is used by CC for tracking image variants / SDK versions. RustSubName is used for Rust-specific
 // subnaming which shouldn't be visible to CC modules (such as the rlib stdlinkage subname). This should be
 // appended before SubName.
 RustSubName string `blueprint:"mutated"`

 // Set by imageMutator
 ProductVariantNeeded       bool     `blueprint:"mutated"`
 VendorVariantNeeded        bool     `blueprint:"mutated"`
 CoreVariantNeeded          bool     `blueprint:"mutated"`
 VendorRamdiskVariantNeeded bool     `blueprint:"mutated"`
 RamdiskVariantNeeded       bool     `blueprint:"mutated"`
 RecoveryVariantNeeded      bool     `blueprint:"mutated"`
 ExtraVariants              []string `blueprint:"mutated"`

 // Allows this module to use non-APEX version of libraries. Useful
 // for building binaries that are started before APEXes are activated.
 Bootstrap *bool

 // 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
 // available after switching root into
 // /first_stage_ramdisk. To expose the module before switching root, install
 // the recovery variant instead.
 Ramdisk_available *bool

 // Make this module available when building for vendor ramdisk.
 // On device without a dedicated recovery partition, the module is only
 // available after switching root into
 // /first_stage_ramdisk. To expose the module before switching root, install
 // the recovery variant instead
 Vendor_ramdisk_available *bool

 // Normally Soong uses the directory structure to decide which modules
 // should be included (framework) or excluded (non-framework) from the
 // different snapshots (vendor, recovery, etc.), but this property
 // allows a partner to exclude a module normally thought of as a
 // framework module from the vendor snapshot.
 Exclude_from_vendor_snapshot *bool

 // Normally Soong uses the directory structure to decide which modules
 // should be included (framework) or excluded (non-framework) from the
 // different snapshots (vendor, recovery, etc.), but this property
 // allows a partner to exclude a module normally thought of as a
 // framework module from the recovery snapshot.
 Exclude_from_recovery_snapshot *bool

 // Make this module available when building for recovery
 Recovery_available *bool

 // The API level that this module is built against. The APIs of this API level will be
 // visible at build time, but use of any APIs newer than min_sdk_version will render the
 // module unloadable on older devices.  In the future it will be possible to weakly-link new
 // APIs, making the behavior match Java: such modules will load on older devices, but
 // calling new APIs on devices that do not support them will result in a crash.
 //
 // This property has the same behavior as sdk_version does for Java modules. For those
 // familiar with Android Gradle, the property behaves similarly to how compileSdkVersion
 // does for Java code.
 //
 // In addition, setting this property causes two variants to be built, one for the platform
 // and one for apps.
 Sdk_version *string

 // If true, always create an sdk variant and don't create a platform variant.
 Sdk_variant_only *bool

 // Minimum OS API level supported by this C or C++ module. This property becomes the value
 // of the __ANDROID_API__ macro. When the C or C++ module is included in an APEX or an APK,
 // this property is also used to ensure that the min_sdk_version of the containing module is
 // not older (i.e. less) than this module's min_sdk_version. When not set, this property
 // defaults to the value of sdk_version.  When this is set to "apex_inherit", this tracks
 // min_sdk_version of the containing APEX. When the module
 // is not built for an APEX, "apex_inherit" defaults to sdk_version.
 Min_sdk_version *string

 // Variant is an SDK variant created by sdkMutator
 IsSdkVariant bool `blueprint:"mutated"`
 // Set when both SDK and platform variants are exported to Make to trigger renaming the SDK
 // variant to have a ".sdk" suffix.
 SdkAndPlatformVariantVisibleToMake bool `blueprint:"mutated"`

 // Set by factories of module types that can only be referenced from variants compiled against
 // the SDK.
 AlwaysSdk bool `blueprint:"mutated"`

 HideFromMake   bool `blueprint:"mutated"`
 PreventInstall bool `blueprint:"mutated"`

 Installable *bool
}

type Module struct {
 fuzz.FuzzModule

 VendorProperties cc.VendorProperties

 Properties BaseProperties

 hod        android.HostOrDeviceSupported
 multilib   android.Multilib
 testModule bool

 makeLinkType string

 afdo             *afdo
 compiler         compiler
 coverage         *coverage
 clippy           *clippy
 sanitize         *sanitize
 cachedToolchain  config.Toolchain
 sourceProvider   SourceProvider
 subAndroidMkOnce map[SubAndroidMkProvider]bool

 exportedLinkDirs     []string
 exportedLinkDirsDeps []android.Path

 // Output file to be installed, may be stripped or unstripped.
 outputFile android.OptionalPath

 // Cross-reference input file
 kytheFiles android.Paths

 docTimestampFile android.OptionalPath

 // For apex variants, this is set as apex.min_sdk_version
 apexSdkVersion android.ApiLevel

 transitiveAndroidMkSharedLibs depset.DepSet[string]

 // Shared flags among stubs build rules of this module
 sharedFlags cc.SharedFlags
}

func (mod *Module) Header() bool {
 //TODO: If Rust libraries provide header variants, this needs to be updated.
 return false
}

func (mod *Module) SetPreventInstall() {
 mod.Properties.PreventInstall = true
}

func (mod *Module) SetHideFromMake() {
 mod.Properties.HideFromMake = true
 mod.ModuleBase.HideFromMake()
}

func (mod *Module) HiddenFromMake() bool {
 return mod.Properties.HideFromMake
}

func (mod *Module) SanitizePropDefined() bool {
 // Because compiler is not set for some Rust modules where sanitize might be set, check that compiler is also not
 // nil since we need compiler to actually sanitize.
 return mod.sanitize != nil && mod.compiler != nil
}

func (mod *Module) IsPrebuilt() bool {
 if _, ok := mod.compiler.(*prebuiltLibraryDecorator); ok {
  return true
 }
 return false
}

func (mod *Module) SelectedStl() string {
 return ""
}

func (mod *Module) NonCcVariants() bool {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   return library.buildRlib() || library.buildDylib()
  }
 }
 panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName()))
}

func (mod *Module) Static() bool {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   return library.static()
  }
 }
 return false
}

func (mod *Module) Shared() bool {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   return library.shared()
  }
 }
 return false
}

func (mod *Module) Dylib() bool {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   return library.dylib()
  }
 }
 return false
}

func (mod *Module) Source() bool {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok && mod.sourceProvider != nil {
   return library.source()
  }
 }
 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 {
   return library.rlib()
  }
 }
 return false
}

func (mod *Module) Binary() bool {
 if binary, ok := mod.compiler.(binaryInterface); ok {
  return binary.binary()
 }
 return false
}

func (mod *Module) StaticExecutable() bool {
 if !mod.Binary() {
  return false
 }
 return mod.StaticallyLinked()
}

func (mod *Module) Xom() *bool {
 if mod.compiler == nil {
  return nil
 }
 return mod.compiler.Xom()
}

func (mod *Module) ApexExclude() bool {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   return library.apexExclude()
  }
 }
 return false
}

func (mod *Module) Object() bool {
 // Rust has no modules which produce only object files.
 return false
}

func (mod *Module) Toc() android.OptionalPath {
 if mod.compiler != nil {
  if lib, ok := mod.compiler.(libraryInterface); ok {
   return lib.toc()
  }
 }
 panic(fmt.Errorf("Toc() called on non-library module: %q", mod.BaseModuleName()))
}

func (mod *Module) UseSdk() bool {
 if cc.CanUseSdk(mod) {
  return String(mod.Properties.Sdk_version) != ""
 }
 return false
}

func (mod *Module) RelativeInstallPath() string {
 if mod.compiler != nil {
  return mod.compiler.relativeInstallPath()
 }
 return ""
}

func (mod *Module) UseVndk() bool {
 return mod.Properties.VndkVersion != ""
}

func (mod *Module) Bootstrap() bool {
 return Bool(mod.Properties.Bootstrap)
}

func (mod *Module) SubName() string {
 return mod.Properties.SubName
}

func (mod *Module) IsVndkPrebuiltLibrary() bool {
 // Rust modules do not provide VNDK prebuilts
 return false
}

func (mod *Module) IsVendorPublicLibrary() bool {
 // Rust modules do not currently support vendor_public_library
 return false
}

func (mod *Module) SdkAndPlatformVariantVisibleToMake() bool {
 return mod.Properties.SdkAndPlatformVariantVisibleToMake
}

func (c *Module) IsVndkPrivate() bool {
 // Rust modules do not currently support VNDK variants
 return false
}

func (c *Module) IsLlndk() bool {
 // Rust modules do not currently support LLNDK variants
 return false
}

func (mod *Module) KernelHeadersDecorator() bool {
 return false
}

func (m *Module) NeedsLlndkVariants() bool {
 // Rust modules do not currently support LLNDK variants
 return false
}

func (m *Module) NeedsVendorPublicLibraryVariants() bool {
 // Rust modules do not currently support vendor_public_library
 return false
}

func (mod *Module) HasLlndkStubs() bool {
 // Rust modules do not currently support LLNDK stubs
 return false
}

func (mod *Module) SdkVersion() string {
 return String(mod.Properties.Sdk_version)
}

func (mod *Module) AlwaysSdk() bool {
 return mod.Properties.AlwaysSdk || Bool(mod.Properties.Sdk_variant_only)
}

func (mod *Module) IsSdkVariant() bool {
 return mod.Properties.IsSdkVariant
}

func (mod *Module) SplitPerApiLevel() bool {
 return cc.CanUseSdk(mod) && mod.IsCrt()
}

func (mod *Module) XrefRustFiles() android.Paths {
 return mod.kytheFiles
}

type Deps struct {
 Dylibs          []string
 Rlibs           []string
 Rustlibs        []string
 NoStdRlibs      []string
 Stdlibs         []string
 ProcMacros      []string
 SharedLibs      []string
 StaticLibs      []string
 WholeStaticLibs []string
 HeaderLibs      []string

 // Used for data dependencies adjacent to tests
 DataLibs []string
 DataBins []string

 CrtBegin, CrtEnd []string
}

type PathDeps struct {
 DyLibs        RustLibraries
 RLibs         RustLibraries
 SharedLibs    android.Paths
 SharedLibDeps android.Paths
 StaticLibs    android.Paths
 ProcMacros    RustLibraries
 AfdoProfiles  android.Paths
 LinkerDeps    android.Paths

 // depFlags and depLinkFlags are rustc and linker (clang) flags.
 depFlags     []string
 depLinkFlags []string

 // track cc static-libs that have Rlib dependencies
 reexportedCcRlibDeps      []cc.RustRlibDep
 reexportedWholeCcRlibDeps []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
 linkDirsDeps          []android.Path
 rustLibObjects        []string
 staticLibObjects      []string
 wholeStaticLibObjects []string
 sharedLibObjects      []string

 // exportedLinkDirs are exported linkDirs for direct rlib dependencies to
 // cc_library_static dependants of rlibs.
 // Track them separately from linkDirs so superfluous -L flags don't get emitted.
 exportedLinkDirs     []string
 exportedLinkDirsDeps []android.Path

 // Used by bindgen modules which call clang
 depClangFlags         []string
 depIncludePaths       android.Paths
 depGeneratedHeaders   android.Paths
 depSystemIncludePaths android.Paths

 CrtBegin android.Paths
 CrtEnd   android.Paths

 SrcFiles android.Paths

 // Paths to generated source files
 SrcDeps          android.Paths
 srcProviderFiles android.Paths

 directApexImplementationDeps        android.Paths
 transitiveApexImplementationDeps    []depset.DepSet[android.Path]
 directNonApexImplementationDeps     android.Paths
 transitiveNonApexImplementationDeps []depset.DepSet[android.Path]
}

type RustLibraries []RustLibrary

type RustLibrary struct {
 Path      android.Path
 CrateName string
}

type exportedFlagsProducer interface {
 exportLinkDirs(dirs []string, deps []android.Path)
 exportRustLibs(...string)
 exportStaticLibs(...string)
 exportWholeStaticLibs(...string)
 exportSharedLibs(...string)
}

type xref interface {
 XrefRustFiles() android.Paths
}

type flagExporter struct {
 linkDirs              []string
 linkDirsDeps          []android.Path
 ccLinkDirs            []string
 rustLibPaths          []string
 staticLibObjects      []string
 sharedLibObjects      []string
 wholeStaticLibObjects []string
 wholeRustRlibDeps     []cc.RustRlibDep
}

func (flagExporter *flagExporter) exportLinkDirs(dirs []string, deps []android.Path) {
 flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
 flagExporter.linkDirsDeps = android.FirstUniquePaths(append(flagExporter.linkDirsDeps, deps...))
}

func (flagExporter *flagExporter) exportRustLibs(flags ...string) {
 flagExporter.rustLibPaths = android.FirstUniqueStrings(append(flagExporter.rustLibPaths, flags...))
}

func (flagExporter *flagExporter) exportStaticLibs(flags ...string) {
 flagExporter.staticLibObjects = android.FirstUniqueStrings(append(flagExporter.staticLibObjects, flags...))
}

func (flagExporter *flagExporter) exportSharedLibs(flags ...string) {
 flagExporter.sharedLibObjects = android.FirstUniqueStrings(append(flagExporter.sharedLibObjects, flags...))
}

func (flagExporter *flagExporter) exportWholeStaticLibs(flags ...string) {
 flagExporter.wholeStaticLibObjects = android.FirstUniqueStrings(append(flagExporter.wholeStaticLibObjects, flags...))
}

func (flagExporter *flagExporter) setRustProvider(ctx ModuleContext) {
 android.SetProvider(ctx, RustFlagExporterInfoProvider, RustFlagExporterInfo{
  LinkDirs:              flagExporter.linkDirs,
  LinkDirsDeps:          flagExporter.linkDirsDeps,
  RustLibObjects:        flagExporter.rustLibPaths,
  StaticLibObjects:      flagExporter.staticLibObjects,
  WholeStaticLibObjects: flagExporter.wholeStaticLibObjects,
  SharedLibPaths:        flagExporter.sharedLibObjects,
  WholeRustRlibDeps:     flagExporter.wholeRustRlibDeps,
 })
}

var _ exportedFlagsProducer = (*flagExporter)(nil)

func NewFlagExporter() *flagExporter {
 return &flagExporter{}
}

// @auto-generate: gob
type RustFlagExporterInfo struct {
 Flags                 []string
 LinkDirs              []string
 LinkDirsDeps          []android.Path
 RustLibObjects        []string
 StaticLibObjects      []string
 WholeStaticLibObjects []string
 SharedLibPaths        []string
 WholeRustRlibDeps     []cc.RustRlibDep
}

var RustFlagExporterInfoProvider = blueprint.NewProvider[RustFlagExporterInfo]()

var _ cc.Coverage = (*Module)(nil)

func (mod *Module) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool {
 return mod.coverage != nil && mod.coverage.Properties.NeedCoverageVariant
}

func (mod *Module) VndkVersion() string {
 return mod.Properties.VndkVersion
}

func (mod *Module) ExportedCrateLinkDirs() ([]string, android.Paths) {
 return mod.exportedLinkDirs, mod.exportedLinkDirsDeps
}

func (mod *Module) PreventInstall() bool {
 return mod.Properties.PreventInstall
}
func (c *Module) ForceDisableSanitizers() {
 c.sanitize.Properties.ForceDisable = true
}

func (mod *Module) MarkAsCoverageVariant(coverage bool) {
 mod.coverage.Properties.IsCoverageVariant = coverage
}

func (mod *Module) EnableCoverageIfNeeded() {
 mod.coverage.Properties.CoverageEnabled = mod.coverage.Properties.NeedCoverageBuild
}

func defaultsFactory() android.Module {
 return DefaultsFactory()
}

type Defaults struct {
 android.ModuleBase
 android.DefaultsModuleBase
}

func DefaultsFactory(props ...any) android.Module {
 module := &Defaults{}

 module.AddProperties(props...)
 module.AddProperties(
  &BaseProperties{},
  &cc.AfdoProperties{},
  &cc.VendorProperties{},
  &BenchmarkProperties{},
  &BindgenProperties{},
  &BaseCompilerProperties{},
  &ObjectProperties{},
  &BinaryCompilerProperties{},
  &LibraryCompilerProperties{},
  &ProcMacroCompilerProperties{},
  &PrebuiltProperties{},
  &SourceProviderProperties{},
  &TestProperties{},
  &cc.CoverageProperties{},
  &cc.RustBindgenClangProperties{},
  &ClippyProperties{},
  &SanitizeProperties{},
  &cc.StripProperties{},
  &fuzz.FuzzProperties{},
 )

 android.InitDefaultsModule(module)
 return module
}

func (mod *Module) CrateName() string {
 return mod.compiler.crateName()
}

func (mod *Module) CcLibrary() bool {
 if mod.compiler != nil {
  if _, ok := mod.compiler.(libraryInterface); ok {
   return true
  }
 }
 return false
}

func (mod *Module) CcLibraryInterface() bool {
 if mod.compiler != nil {
  // use build{Static,Shared}() instead of {static,shared}() here because this might be called before
  // VariantIs{Static,Shared} is set.
  if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic() || lib.buildRlib()) {
   return true
  }
 }
 return false
}

func (mod *Module) RustLibraryInterface() bool {
 if mod.compiler != nil {
  if _, ok := mod.compiler.(libraryInterface); ok {
   return true
  }
 }
 return false
}

func (mod *Module) IsFuzzModule() bool {
 if _, ok := mod.compiler.(*fuzzDecorator); ok {
  return true
 }
 return false
}

func (mod *Module) FuzzModuleStruct() fuzz.FuzzModule {
 return mod.FuzzModule
}

func (mod *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule {
 if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok {
  return fuzzer.fuzzPackagedModule
 }
 panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", mod.BaseModuleName()))
}

func (mod *Module) FuzzSharedLibraries() cc.InstallPairs {
 if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok {
  return fuzzer.sharedLibraries
 }
 panic(fmt.Errorf("FuzzSharedLibraries called on non-fuzz module: %q", mod.BaseModuleName()))
}

func (mod *Module) UnstrippedOutputFile() android.Path {
 if mod.compiler != nil {
  return mod.compiler.unstrippedOutputFilePath()
 }
 return nil
}

func (mod *Module) CheckJsonFilePath() android.OptionalPath {
 if mod.compiler != nil {
  return mod.compiler.checkJsonFilePath()
 }
 return android.OptionalPath{}
}

func (mod *Module) SetStatic() {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   library.setStatic()
   return
  }
 }
 panic(fmt.Errorf("SetStatic called on non-library module: %q", mod.BaseModuleName()))
}

func (mod *Module) SetShared() {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   library.setShared()
   return
  }
 }
 panic(fmt.Errorf("SetShared called on non-library module: %q", mod.BaseModuleName()))
}

func (mod *Module) BuildStaticVariant() bool {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   return library.buildStatic()
  }
 }
 panic(fmt.Errorf("BuildStaticVariant called on non-library module: %q", mod.BaseModuleName()))
}

func (mod *Module) BuildRlibVariant() bool {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   return library.buildRlib()
  }
 }
 panic(fmt.Errorf("BuildRlibVariant called on non-library module: %q", mod.BaseModuleName()))
}

func (mod *Module) BuildSharedVariant() bool {
 if mod.compiler != nil {
  if library, ok := mod.compiler.(libraryInterface); ok {
   return library.buildShared()
  }
 }
 panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", mod.BaseModuleName()))
}

func (mod *Module) Module() android.Module {
 return mod
}

func (mod *Module) OutputFile() android.OptionalPath {
 return mod.outputFile
}

func (mod *Module) CoverageFiles() android.Paths {
 if mod.compiler != nil {
  return android.Paths{}
 }
 panic(fmt.Errorf("CoverageFiles called on non-library module: %q", mod.BaseModuleName()))
}

// Rust does not produce gcno files, and therefore does not produce a coverage archive.
func (mod *Module) CoverageOutputFile() android.OptionalPath {
 return android.OptionalPath{}
}

func (c *Module) LinkCoverage() bool {
 return false
}

func (mod *Module) IsNdk(config android.Config) bool {
 return false
}

func (mod *Module) IsStubs() bool {
 if lib, ok := mod.compiler.(libraryInterface); ok {
  return lib.BuildStubs()
 }
 return false
}

func (mod *Module) HasStubsVariants() bool {
 if lib, ok := mod.compiler.(libraryInterface); ok {
  return lib.HasStubsVariants()
 }
 return false
}

func (mod *Module) ApexSdkVersion() android.ApiLevel {
 return mod.apexSdkVersion
}

func (mod *Module) RustApexExclude() bool {
 return mod.ApexExclude()
}

func (mod *Module) getSharedFlags() *cc.SharedFlags {
 shared := &mod.sharedFlags
 if shared.FlagsMap == nil {
  shared.NumSharedFlags = 0
  shared.FlagsMap = make(map[string]string)
 }
 return shared
}

func (mod *Module) ImplementationModuleNameForMake() string {
 name := mod.BaseModuleName()
 if versioned, ok := mod.compiler.(cc.VersionedInterface); ok {
  name = versioned.ImplementationModuleName(name)
 }
 return name
}

func (mod *Module) Multilib() string {
 return mod.Arch().ArchType.Multilib
}

func (mod *Module) IsCrt() bool {
 if obj, ok := mod.compiler.(objectInterface); ok {
  return obj.crt()
 }
 return false
}

func (mod *Module) installable(apexInfo android.ApexInfo) bool {
 if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) {
  return false
 }
 if mod.PreventInstall() {
  return false
 }
 // The apex variant is not installable because it is included in the APEX and won't appear
 // in the system partition as a standalone file.
 if !apexInfo.IsForPlatform() {
  return false
 }

 return mod.OutputFile().Valid() && !mod.Properties.PreventInstall
}

func (ctx moduleContext) apexVariationName() string {
 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
 return apexInfo.ApexVariationName
}

var _ cc.LinkableInterface = (*Module)(nil)
var _ cc.VersionedLinkableInterface = (*Module)(nil)

func (mod *Module) Init() android.Module {
 mod.AddProperties(&mod.Properties)
 mod.AddProperties(&mod.VendorProperties)

 if mod.afdo != nil {
  mod.AddProperties(mod.afdo.props()...)
 }
 if mod.compiler != nil {
  mod.AddProperties(mod.compiler.compilerProps()...)
 }
 if mod.coverage != nil {
  mod.AddProperties(mod.coverage.props()...)
 }
 if mod.clippy != nil {
  mod.AddProperties(mod.clippy.props()...)
 }
 if mod.sourceProvider != nil {
  mod.AddProperties(mod.sourceProvider.SourceProviderProps()...)
 }
 if mod.sanitize != nil {
  mod.AddProperties(mod.sanitize.props()...)
 }

 android.InitAndroidArchModule(mod, mod.hod, mod.multilib)
 android.InitApexModule(mod)

 android.InitDefaultableModule(mod)
 return mod
}

func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
 return &Module{
  hod:      hod,
  multilib: multilib,
 }
}
func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
 module := newBaseModule(hod, multilib)
 module.afdo = &afdo{}
 module.coverage = &coverage{}
 module.clippy = &clippy{}
 module.sanitize = &sanitize{}
 return module
}

type ModuleContext interface {
 android.ModuleContext
 ModuleContextIntf
}

type BaseModuleContext interface {
 android.BaseModuleContext
 ModuleContextIntf
}

type DepsContext interface {
 android.BottomUpMutatorContext
 ModuleContextIntf
}

type ModuleContextIntf interface {
 RustModule() *Module
 toolchain() config.Toolchain
}

type depsContext struct {
 android.BottomUpMutatorContext
}

type moduleContext struct {
 android.ModuleContext
}

type baseModuleContext struct {
 android.BaseModuleContext
}

func (ctx *moduleContext) RustModule() *Module {
 return ctx.Module().(*Module)
}

func (ctx *moduleContext) toolchain() config.Toolchain {
 return ctx.RustModule().toolchain(ctx)
}

func (ctx *depsContext) RustModule() *Module {
 return ctx.Module().(*Module)
}

func (ctx *depsContext) toolchain() config.Toolchain {
 return ctx.RustModule().toolchain(ctx)
}

func (ctx *baseModuleContext) RustModule() *Module {
 return ctx.Module().(*Module)
}

func (ctx *baseModuleContext) toolchain() config.Toolchain {
 return ctx.RustModule().toolchain(ctx)
}

func (mod *Module) nativeCoverage() bool {
 // Bug: http://b/137883967 - native-bridge modules do not currently work with coverage
 if mod.Target().NativeBridge == android.NativeBridgeEnabled {
  return false
 }
 return mod.compiler != nil && mod.compiler.nativeCoverage()
}

func (mod *Module) SetStl(s string) {
 // STL is a CC concept; do nothing for Rust
}

func (mod *Module) SetSdkVersion(s *string) {
 mod.Properties.Sdk_version = s
}

func (mod *Module) SetSdkAndPlatformVariantVisibleToMake() {
 mod.Properties.SdkAndPlatformVariantVisibleToMake = true
}

func (mod *Module) SetSdkVariant() {
 mod.Properties.IsSdkVariant = true
}

func (mod *Module) SetMinSdkVersion(s string) {
 mod.Properties.Min_sdk_version = StringPtr(s)
}

func (mod *Module) VersionedInterface() cc.VersionedInterface {
 if _, ok := mod.compiler.(cc.VersionedInterface); ok {
  return mod.compiler.(cc.VersionedInterface)
 }
 return nil
}

func (mod *Module) EverInstallable() bool {
 return mod.compiler != nil &&
  // Check to see whether the module is actually ever installable.
  mod.compiler.everInstallable()
}

func (mod *Module) Installable() *bool {
 return mod.Properties.Installable
}

func (mod *Module) ProcMacro() bool {
 if pm, ok := mod.compiler.(procMacroInterface); ok {
  return pm.ProcMacro()
 }
 return false
}

func (mod *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
 if mod.cachedToolchain == nil {
  mod.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch())
 }
 return mod.cachedToolchain
}

func (mod *Module) ccToolchain(ctx android.BaseModuleContext) cc_config.Toolchain {
 return cc_config.FindToolchain(ctx.Os(), ctx.Arch(), false)
}

func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}

func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
 ctx := &moduleContext{
  ModuleContext: actx,
 }

 apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider)
 if !apexInfo.IsForPlatform() {
  mod.SetHideFromMake()
 }

 toolchain := mod.toolchain(ctx)
 mod.makeLinkType = cc.GetMakeLinkType(actx, mod)

 mod.Properties.SubName = cc.GetSubnameProperty(actx, mod)

 if !toolchain.Supported() {
  // This toolchain's unsupported, there's nothing to do for this mod.
  return
 }

 deps, testSuiteSharedLibs := mod.depsToPaths(ctx)
 // Export linkDirs for CC rust generatedlibs
 mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.exportedLinkDirs...)
 mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.linkDirs...)
 mod.exportedLinkDirsDeps = append(mod.exportedLinkDirsDeps, deps.exportedLinkDirsDeps...)
 mod.exportedLinkDirsDeps = append(mod.exportedLinkDirsDeps, deps.linkDirsDeps...)

 flags := Flags{
  Toolchain: toolchain,
 }

 // Calculate rustc flags
 if mod.afdo != nil {
  flags, deps = mod.afdo.flags(actx, flags, deps)
 }
 if mod.compiler != nil {
  flags = mod.compiler.compilerFlags(ctx, flags)
  flags = mod.compiler.cfgFlags(ctx, flags)
  flags = mod.compiler.featureFlags(ctx, flags)
 }
 if mod.coverage != nil {
  flags, deps = mod.coverage.flags(ctx, flags, deps)
 }
 if mod.clippy != nil {
  flags, deps = mod.clippy.flags(ctx, flags, deps)
 }
 if mod.sanitize != nil {
  flags, deps = mod.sanitize.flags(ctx, flags, deps)
 }

 // SourceProvider needs to call GenerateSource() before compiler calls
 // compile() so it can provide the source. A SourceProvider has
 // multiple variants (e.g. source, rlib, dylib). Only the "source"
 // variant is responsible for effectively generating the source. The
 // remaining variants relies on the "source" variant output.
 if mod.sourceProvider != nil {
  if mod.compiler.(libraryInterface).source() {
   mod.sourceProvider.GenerateSource(ctx, deps)
   mod.sourceProvider.setSubName(ctx.ModuleSubDir())
  } else {
   sourceMod := actx.GetDirectDepProxyWithTag(mod.Name(), sourceDepTag)
   sourceLib := android.OtherModuleProviderOrDefault(ctx, sourceMod, RustInfoProvider).SourceProviderInfo
   mod.sourceProvider.setOutputFiles(sourceLib.Srcs)
  }
  ctx.CheckbuildFile(mod.sourceProvider.Srcs()...)
 }

 if mod.compiler != nil && !mod.compiler.Disabled() {
  buildOutput := mod.compiler.compile(ctx, flags, deps)
  if ctx.Failed() {
   return
  }
  mod.outputFile = android.OptionalPathForPath(buildOutput.outputFile)
  ctx.CheckbuildFile(buildOutput.outputFile)
  if buildOutput.kytheFile != nil {
   mod.kytheFiles = append(mod.kytheFiles, buildOutput.kytheFile)
  }

  deps.SrcFiles = append(deps.SrcFiles, mod.compiler.crateSources(ctx)...)
  mod.docTimestampFile = mod.compiler.rustdoc(ctx, flags, deps)

  apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider)
  if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) && !mod.ProcMacro() {
   // If the module has been specifically configure to not be installed then
   // hide from make as otherwise it will break when running inside make as the
   // output path to install will not be specified. Not all uninstallable
   // modules can be hidden from make as some are needed for resolving make
   // side dependencies. In particular, proc-macros need to be captured in the
   // host snapshot.
   mod.HideFromMake()
   mod.SkipInstall()
  } else if !mod.installable(apexInfo) {
   mod.SkipInstall()
  }

  // Still call install though, the installs will be stored as PackageSpecs to allow
  // using the outputs in a genrule.
  if mod.OutputFile().Valid() {
   mod.compiler.install(ctx)
   if ctx.Failed() {
    return
   }
   // Export your own directory as a linkDir
   mod.exportedLinkDirs = append(mod.exportedLinkDirs, linkPathFromFilePath(mod.OutputFile().Path()))
   mod.exportedLinkDirsDeps = append(mod.exportedLinkDirsDeps, mod.OutputFile().Path())
  }

  android.SetProvider(ctx, cc.ImplementationDepInfoProvider, &cc.ImplementationDepInfo{
   ImplementationDeps: depset.New(depset.PREORDER, deps.directApexImplementationDeps, deps.transitiveApexImplementationDeps),
  })
  android.SetProvider(ctx, RustImplementationDepInfoProvider, &RustImplementationDepInfo{
   NonApexImplementationDeps: depset.New(depset.PREORDER, deps.directNonApexImplementationDeps, deps.transitiveNonApexImplementationDeps),
  })

  ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
 }

 linkableInfo := cc.CreateCommonLinkableInfo(ctx, mod)
 linkableInfo.Static = mod.Static()
 linkableInfo.Shared = mod.Shared()
 linkableInfo.Rlib = mod.Rlib()
 linkableInfo.CrateName = mod.CrateName()
 exportedLinkDirs, exportedLinkDirsDeps := mod.ExportedCrateLinkDirs()
 linkableInfo.ExportedCrateLinkDirs = android.FirstUniqueStrings(exportedLinkDirs)
 linkableInfo.ExportedCrateLinkDirsDeps = android.FirstUniquePaths(exportedLinkDirsDeps)
 if lib, ok := mod.compiler.(cc.VersionedInterface); ok {
  linkableInfo.StubsVersion = lib.StubsVersion()
 }
 linkableInfo.FuzzDependencies = cc.PropagateSharedLibraryFuzzerDependencies(ctx, android.OptionalPath{}, false)

 android.SetProvider(ctx, cc.LinkableInfoProvider, linkableInfo)

 rustInfo := &RustInfo{
  AndroidMkSuffix:               mod.AndroidMkSuffix(),
  RustSubName:                   mod.Properties.RustSubName,
  TransitiveAndroidMkSharedLibs: mod.transitiveAndroidMkSharedLibs,
  XrefRustFiles:                 mod.XrefRustFiles(),
  DocTimestampFile:              mod.docTimestampFile,
  CollectDoc:                    config.DocConfigForDir(ctx.ModuleDir()),
 }
 if mod.compiler != nil {
  rustInfo.CompilerInfo = &CompilerInfo{
   NoStdlibs:              mod.compiler.noStdlibs(),
   CrateName:              mod.compiler.crateName(),
   Edition:                mod.compiler.edition(),
   CargoOutDir:            mod.compiler.cargoOutDir(ctx),
   Features:               mod.compiler.features(ctx),
   CrateRootPath:          mod.compiler.crateRootPath(ctx),
   StdLinkageForDevice:    mod.compiler.stdLinkage(true),
   StdLinkageForNonDevice: mod.compiler.stdLinkage(false),
   BuildTarget:            mod.compiler.unstrippedOutputFilePath(),
   CheckTarget:            mod.compiler.checkJsonFilePath(),
  }
  if lib, ok := mod.compiler.(libraryInterface); ok {
   rustInfo.CompilerInfo.LibraryInfo = &LibraryInfo{
    Dylib: lib.dylib(),
    Rlib:  lib.rlib(),
   }
  }
  if lib, ok := mod.compiler.(cc.SnapshotInterface); ok {
   rustInfo.SnapshotInfo = &cc.SnapshotInfo{
    SnapshotAndroidMkSuffix: lib.SnapshotAndroidMkSuffix(),
   }
  }
 }
 if mod.sourceProvider != nil {
  rustInfo.SourceProviderInfo = &SourceProviderInfo{
   Srcs: mod.sourceProvider.Srcs(),
  }
  if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
   rustInfo.SourceProviderInfo.ProtobufDecoratorInfo = &ProtobufDecoratorInfo{}
  }
 }
 if _, ok := mod.compiler.(*procMacroDecorator); ok {
  rustInfo.ProcMacroInfo = &ProcMacroInfo{
   Dylib: mod.compiler.unstrippedOutputFilePath(),
  }
 }
 android.SetProvider(ctx, RustInfoProvider, rustInfo)

 // TODO: Refactor rustMakeLibName so we don't have to fake CommonModuleInfo like this
 myCommonInfo := android.CommonModuleInfo{
  BaseModuleName: mod.BaseModuleName(),
  Target:         ctx.Target(),
 }
 ctx.SetMakeNamesInfo(&android.MakeNamesInfo{
  SharedLibsMakeNames: testSuiteSharedLibs,
  MakeName:            rustMakeLibName(rustInfo, linkableInfo, &myCommonInfo, ctx.ModuleName()),
 })

 mod.setOutputFiles(ctx)

 buildComplianceMetadataInfo(ctx, mod, deps)

 moduleInfoJSON := ctx.ModuleInfoJSON()
 if mod.compiler != nil {
  mod.compiler.moduleInfoJSON(ctx, moduleInfoJSON)
 }

 mod.setSymbolsInfoProvider(ctx)
}

func (mod *Module) baseSymbolInfo(ctx android.ModuleContext) *cc.SymbolInfo {
 return &cc.SymbolInfo{
  Name:          mod.BaseModuleName() + mod.Properties.SubName,
  ModuleDir:     ctx.ModuleDir(),
  Uninstallable: mod.IsSkipInstall() || !proptools.BoolDefault(mod.Properties.Installable, true) || mod.NoFullInstall(),
 }
}

func (mod *Module) getSymbolInfo(ctx android.ModuleContext, t any, info *cc.SymbolInfo) *cc.SymbolInfo {
 switch tt := t.(type) {
 case *binaryDecorator:
  mod.getSymbolInfo(ctx, tt.baseCompiler, info)
 case *testDecorator:
  mod.getSymbolInfo(ctx, tt.binaryDecorator, info)
 case *benchmarkDecorator:
  mod.getSymbolInfo(ctx, tt.binaryDecorator, info)
 case *libraryDecorator:
  mod.getSymbolInfo(ctx, tt.baseCompiler, info)
 case *procMacroDecorator:
  mod.getSymbolInfo(ctx, tt.baseCompiler, info)
 case *BaseSourceProvider:
  outFile := tt.OutputFiles[0]
  _, file := filepath.Split(outFile.String())
  stem, suffix, _ := android.SplitFileExt(file)
  info.Suffix = suffix
  info.Stem = stem
  info.Uninstallable = true
 case *bindgenDecorator:
  mod.getSymbolInfo(ctx, tt.BaseSourceProvider, info)
 case *protobufDecorator:
  mod.getSymbolInfo(ctx, tt.BaseSourceProvider, info)
 case *baseCompiler:
  if tt.path != (android.InstallPath{}) {
   info.UnstrippedBinaryPath = tt.unstrippedOutputFile
   path, file := filepath.Split(tt.path.String())
   stem, suffix, _ := android.SplitFileExt(file)
   info.Suffix = suffix
   info.ModuleDir = path
   info.Stem = stem
  }
 case *fuzzDecorator:
  mod.getSymbolInfo(ctx, tt.binaryDecorator, info)
 case *prebuiltLibraryDecorator:
  mod.getSymbolInfo(ctx, tt.baseCompiler, info)
 case *toolchainLibraryDecorator:
  mod.getSymbolInfo(ctx, tt.baseCompiler, info)
 }
 return info
}

func (mod *Module) setSymbolsInfoProvider(ctx android.ModuleContext) {
 if !mod.Properties.HideFromMake {
  infos := &cc.SymbolInfos{}
  if mod.compiler != nil && !mod.compiler.Disabled() {
   infos.AppendSymbols(mod.getSymbolInfo(ctx, mod.compiler, mod.baseSymbolInfo(ctx)))
  } else if mod.sourceProvider != nil {
   infos.AppendSymbols(mod.getSymbolInfo(ctx, mod.sourceProvider, mod.baseSymbolInfo(ctx)))
  }

  if mod.sanitize != nil {
   infos.AppendSymbols(mod.getSymbolInfo(ctx, mod.sanitize, mod.baseSymbolInfo(ctx)))
  }

  cc.CopySymbolsAndSetSymbolsInfoProvider(ctx, infos)
 }
}

func (mod *Module) setOutputFiles(ctx ModuleContext) {
 if mod.sourceProvider != nil && (mod.compiler == nil || mod.compiler.Disabled()) {
  ctx.SetOutputFiles(mod.sourceProvider.Srcs(), "")
 } else if mod.OutputFile().Valid() {
  ctx.SetOutputFiles(android.Paths{mod.OutputFile().Path()}, "")
 } else {
  ctx.SetOutputFiles(android.Paths{}, "")
 }
 if mod.compiler != nil {
  ctx.SetOutputFiles(android.PathsIfNonNil(mod.compiler.unstrippedOutputFilePath()), "unstripped")
 }
}

func buildComplianceMetadataInfo(ctx *moduleContext, mod *Module, deps PathDeps) {
 // Dump metadata that can not be done in android/compliance-metadata.go
 metadataInfo := ctx.ComplianceMetadataInfo()
 metadataInfo.SetStringValue(android.ComplianceMetadataProp.IS_STATIC_LIB, strconv.FormatBool(mod.Static()))
 metadataInfo.AddBuiltFiles(mod.outputFile.String())

 // Static libs
 staticDeps := ctx.GetDirectDepsProxyWithTag(rlibDepTag)
 staticDepNames := make([]string, 0, len(staticDeps))
 for _, dep := range staticDeps {
  staticDepNames = append(staticDepNames, dep.Name())
 }
 ccStaticDeps := ctx.GetDirectDepsProxyWithTag(cc.StaticDepTag(false))
 for _, dep := range ccStaticDeps {
  staticDepNames = append(staticDepNames, dep.Name())
 }

 staticDepPaths := make([]string, 0, len(deps.StaticLibs)+len(deps.RLibs))
 // C static libraries
 for _, dep := range deps.StaticLibs {
  staticDepPaths = append(staticDepPaths, dep.String())
 }
 // Rust static libraries
 for _, dep := range deps.RLibs {
  staticDepPaths = append(staticDepPaths, dep.Path.String())
 }
 metadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEP_FILES, android.FirstUniqueStrings(staticDepPaths))

 // C Whole static libs
 ccWholeStaticDeps := ctx.GetDirectDepsProxyWithTag(cc.StaticDepTag(true))
 wholeStaticDepNames := make([]string, 0, len(ccWholeStaticDeps))
 for _, dep := range ccStaticDeps {
  wholeStaticDepNames = append(wholeStaticDepNames, dep.Name())
 }

 allStaticDepNames := append(staticDepNames, wholeStaticDepNames...)
 metadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEPS, android.FirstUniqueStrings(allStaticDepNames))
}

func (mod *Module) deps(ctx DepsContext) Deps {
 deps := Deps{}

 if mod.compiler != nil {
  deps = mod.compiler.compilerDeps(ctx, deps)
 }
 if mod.sourceProvider != nil {
  deps = mod.sourceProvider.SourceProviderDeps(ctx, deps)
 }

 if mod.coverage != nil {
  deps = mod.coverage.deps(ctx, deps)
 }

 deps.Rlibs = android.LastUniqueStrings(deps.Rlibs)
 deps.Dylibs = android.LastUniqueStrings(deps.Dylibs)
 deps.Rustlibs = android.LastUniqueStrings(deps.Rustlibs)
 deps.NoStdRlibs = android.LastUniqueStrings(deps.NoStdRlibs)
 deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros)
 deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
 deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
 deps.Stdlibs = android.LastUniqueStrings(deps.Stdlibs)
 deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
 return deps

}

type dependencyTag struct {
 blueprint.BaseDependencyTag
 name      string
 library   bool
 procMacro bool
 dynamic   bool
}

// InstallDepNeeded returns true for rlibs, dylibs, and proc macros so that they or their transitive
// dependencies (especially C/C++ shared libs) are installed as dependencies of a rust binary.
func (d dependencyTag) InstallDepNeeded() bool {
 return d.library || d.procMacro
}

var _ android.InstallNeededDependencyTag = dependencyTag{}

func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
 if d.library && d.dynamic {
  return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
 }
 return nil
}

func (d dependencyTag) PropagateAconfigValidation() bool {
 return d == rlibDepTag || d == sourceDepTag
}

func (d dependencyTag) IsNativeCoverageNeededDepTag(ctx cc.IsNativeCoverageNeededContext) bool {
 return d.dynamic
}

var _ cc.UseCoverageDeptag = dependencyTag{}

var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{}

var _ android.LicenseAnnotationsDependencyTag = dependencyTag{}

var (
 customBindgenDepTag = dependencyTag{name: "customBindgenTag"}
 rlibDepTag          = dependencyTag{name: "rlibTag", library: true}
 dylibDepTag         = dependencyTag{name: "dylib", library: true, dynamic: true}
 procMacroDepTag     = dependencyTag{name: "procMacro", procMacro: true}
 sourceDepTag        = dependencyTag{name: "source"}
 dataLibDepTag       = dependencyTag{name: "data lib"}
 dataBinDepTag       = dependencyTag{name: "data bin"}
)

func IsDylibDepTag(depTag blueprint.DependencyTag) bool {
 tag, ok := depTag.(dependencyTag)
 return ok && tag == dylibDepTag
}

func IsRlibDepTag(depTag blueprint.DependencyTag) bool {
 tag, ok := depTag.(dependencyTag)
 return ok && tag == rlibDepTag
}

type autoDep struct {
 variation string
 depTag    dependencyTag
}

var (
 sourceVariation = "source"
 rlibVariation   = "rlib"
 dylibVariation  = "dylib"
 rlibAutoDep     = autoDep{variation: rlibVariation, depTag: rlibDepTag}
 dylibAutoDep    = autoDep{variation: dylibVariation, depTag: dylibDepTag}
)

type autoDeppable interface {
 autoDep(ctx android.BottomUpMutatorContext) autoDep
}

func (mod *Module) begin(ctx BaseModuleContext) {
 if mod.coverage != nil {
  mod.coverage.begin(ctx, mod.Binary(), mod.testModule)
 }
 if mod.sanitize != nil {
  mod.sanitize.begin(ctx)
 }
 if mod.compiler != nil {
  mod.compiler.begin(ctx)
 }

 if mod.UseSdk() && mod.IsSdkVariant() {
  sdkVersion := ""
  if ctx.Device() {
   sdkVersion = mod.SdkVersion()
  }
  version, err := cc.NativeApiLevelFromUser(ctx, sdkVersion)
  if err != nil {
   ctx.PropertyErrorf("sdk_version", err.Error())
   mod.Properties.Sdk_version = nil
  } else {
   mod.Properties.Sdk_version = StringPtr(version.String())
  }
 }

}

func (mod *Module) Prebuilt() *android.Prebuilt {
 if p, ok := mod.compiler.(rustPrebuilt); ok {
  return p.prebuilt()
 }
 return nil
}

func (mod *Module) Symlinks() []string {
 // TODO update this to return the list of symlinks when Rust supports defining symlinks
 return nil
}

func rustMakeLibName(rustInfo *RustInfo, linkableInfo *cc.LinkableInfo, commonInfo *android.CommonModuleInfo, depName string) string {
 if rustInfo != nil {
  // Use base module name for snapshots when exporting to Makefile.
  if rustInfo.SnapshotInfo != nil {
   baseName := commonInfo.BaseModuleName
   return baseName + rustInfo.SnapshotInfo.SnapshotAndroidMkSuffix + rustInfo.AndroidMkSuffix
  }
 }
 return cc.MakeLibName(nil, linkableInfo, commonInfo, depName)
}

func collectIncludedProtos(mod *Module, rustInfo *RustInfo, linkableInfo *cc.LinkableInfo) {
 if protoMod, ok := mod.sourceProvider.(*protobufDecorator); ok {
  if rustInfo.SourceProviderInfo.ProtobufDecoratorInfo != nil {
   protoMod.additionalCrates = append(protoMod.additionalCrates, linkableInfo.CrateName)
  }
 }
}

func (mod *Module) depsToPaths(ctx android.ModuleContext) (PathDeps, []string) {
 var depPaths PathDeps

 directRlibDeps := []*cc.LinkableInfo{}
 directDylibDeps := []*cc.LinkableInfo{}
 directProcMacroDeps := []*cc.LinkableInfo{}
 directSharedLibDeps := []cc.SharedLibraryInfo{}
 directStaticLibDeps := [](*cc.LinkableInfo){}
 directSrcProvidersDeps := []*android.ModuleProxy{}
 directSrcDeps := []android.SourceFilesInfo{}

 // For the dependency from platform to apex, use the latest stubs
 mod.apexSdkVersion = android.FutureApiLevel
 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
 if !apexInfo.IsForPlatform() {
  mod.apexSdkVersion = apexInfo.MinSdkVersion
 }

 if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
  // In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000)
  // so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)).
  // (b/144430859)
  mod.apexSdkVersion = android.FutureApiLevel
 }

 skipModuleList := map[string]bool{}

 var transitiveAndroidMkSharedLibs []depset.DepSet[string]
 var directAndroidMkSharedLibs []string

 ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
  depName := ctx.OtherModuleName(dep)
  depTag := ctx.OtherModuleDependencyTag(dep)
  modStdLinkage := mod.compiler.stdLinkage(ctx.Device())

  if _, exists := skipModuleList[depName]; exists {
   return
  }

  if depTag == android.DarwinUniversalVariantTag {
   return
  }

  rustInfo, hasRustInfo := android.OtherModuleProvider(ctx, dep, RustInfoProvider)
  ccInfo, _ := android.OtherModuleProvider(ctx, dep, cc.CcInfoProvider)
  linkableInfo, hasLinkableInfo := android.OtherModuleProvider(ctx, dep, cc.LinkableInfoProvider)
  commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider)
  if hasRustInfo && !linkableInfo.Static && !linkableInfo.Shared {
   //Handle Rust Modules
   makeLibName := rustMakeLibName(rustInfo, linkableInfo, commonInfo, depName+rustInfo.RustSubName)

   switch {
   case depTag == dylibDepTag:
    dylib := rustInfo.CompilerInfo.LibraryInfo
    if dylib == nil || !dylib.Dylib {
     ctx.ModuleErrorf("mod %q not an dylib library", depName)
     return
    }
    directDylibDeps = append(directDylibDeps, linkableInfo)
    mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName)
    mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName))

    depPaths.directApexImplementationDeps = append(depPaths.directApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
    if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
     depPaths.transitiveApexImplementationDeps = append(depPaths.transitiveApexImplementationDeps, info.ImplementationDeps)
    }
    if info, ok := android.OtherModuleProvider(ctx, dep, RustImplementationDepInfoProvider); ok {
     depPaths.transitiveNonApexImplementationDeps = append(depPaths.transitiveNonApexImplementationDeps, info.NonApexImplementationDeps)
    }

    if !rustInfo.CompilerInfo.NoStdlibs {
     rustDepStdLinkage := rustInfo.CompilerInfo.StdLinkageForNonDevice
     if ctx.Device() {
      rustDepStdLinkage = rustInfo.CompilerInfo.StdLinkageForDevice
     }
     if !slices.Contains(modStdLinkage.compatChoices(), rustDepStdLinkage) {
      ctx.ModuleErrorf("Rust dependency %q has the wrong StdLinkage; expected %#v, got %#v", depName, modStdLinkage, rustDepStdLinkage)
      return
     }
    }

   case depTag == rlibDepTag:
    rlib := rustInfo.CompilerInfo.LibraryInfo
    if rlib == nil || !rlib.Rlib {
     ctx.ModuleErrorf("mod %q not an rlib library", makeLibName)
     return
    }
    directRlibDeps = append(directRlibDeps, linkableInfo)
    mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName)
    mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName))

    // rust_ffi rlibs may export include dirs, so collect those here.
    exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
    depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
    depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path()))
    depPaths.exportedLinkDirsDeps = append(depPaths.exportedLinkDirsDeps, linkableInfo.OutputFile.Path())

    // rlibs are not installed, so don't add the output file to apexDirectImplementationDeps. Track them for RBE however.
    depPaths.directNonApexImplementationDeps = append(depPaths.directNonApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
    if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
     depPaths.transitiveApexImplementationDeps = append(depPaths.transitiveApexImplementationDeps, info.ImplementationDeps)
    }
    if info, ok := android.OtherModuleProvider(ctx, dep, RustImplementationDepInfoProvider); ok {
     depPaths.transitiveNonApexImplementationDeps = append(depPaths.transitiveNonApexImplementationDeps, info.NonApexImplementationDeps)
    }

    if !rustInfo.CompilerInfo.NoStdlibs {
     rustDepStdLinkage := rustInfo.CompilerInfo.StdLinkageForNonDevice
     if ctx.Device() {
      rustDepStdLinkage = rustInfo.CompilerInfo.StdLinkageForDevice
     }
     if !slices.Contains(modStdLinkage.compatChoices(), rustDepStdLinkage) {
      ctx.ModuleErrorf("Rust dependency %q has the wrong StdLinkage; expected %#v, got %#v", depName, modStdLinkage, rustDepStdLinkage)
      return
     }
    }

    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)
    // proc_macro link dirs need to be exported, so collect those here.
    depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path()))
    depPaths.exportedLinkDirsDeps = append(depPaths.exportedLinkDirsDeps, linkableInfo.OutputFile.Path())

    depPaths.directNonApexImplementationDeps = append(depPaths.directNonApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
    if info, ok := android.OtherModuleProvider(ctx, dep, RustImplementationDepInfoProvider); ok {
     depPaths.transitiveNonApexImplementationDeps = append(depPaths.transitiveNonApexImplementationDeps, info.NonApexImplementationDeps)
    }

   case depTag == sourceDepTag:
    if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
     collectIncludedProtos(mod, rustInfo, linkableInfo)
    }
   case cc.IsStaticDepTag(depTag):
    // Rust FFI rlibs should not be declared in a Rust modules
    // "static_libs" list as we can't handle them properly at the
    // moment (for example, they only produce an rlib-std variant).
    // Instead, a normal rust_library variant should be used.
    ctx.PropertyErrorf("static_libs",
     "found '%s' in static_libs; use a rust_library module in rustlibs instead of a rust_ffi module in static_libs",
     depName)

   }

   transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustInfo.TransitiveAndroidMkSharedLibs)

   if android.IsSourceDepTagWithOutputTag(depTag, "") {
    // Since these deps are added in path_properties.go via AddDependencies, we need to ensure the correct
    // OS/Arch variant is used.
    var helper string
    if ctx.Host() {
     helper = "missing 'host_supported'?"
    } else {
     helper = "device module defined?"
    }

    if commonInfo.Target.Os != ctx.Os() {
     ctx.ModuleErrorf("OS mismatch on dependency %q (%s)", dep.Name(), helper)
     return
    } else if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType {
     ctx.ModuleErrorf("Arch mismatch on dependency %q (%s)", dep.Name(), helper)
     return
    }
    directSrcProvidersDeps = append(directSrcProvidersDeps, &dep)
   }

   exportedRustInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider)
   exportedInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider)
   //Append the dependencies exported objects, except for proc-macros which target a different arch/OS
   if depTag != procMacroDepTag {
    depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
    depPaths.rustLibObjects = append(depPaths.rustLibObjects, exportedInfo.RustLibObjects...)
    depPaths.sharedLibObjects = append(depPaths.sharedLibObjects, exportedInfo.SharedLibPaths...)
    depPaths.staticLibObjects = append(depPaths.staticLibObjects, exportedInfo.StaticLibObjects...)
    depPaths.wholeStaticLibObjects = append(depPaths.wholeStaticLibObjects, exportedInfo.WholeStaticLibObjects...)
    depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
    depPaths.linkDirsDeps = append(depPaths.linkDirsDeps, exportedInfo.LinkDirsDeps...)

    depPaths.reexportedWholeCcRlibDeps = append(depPaths.reexportedWholeCcRlibDeps, exportedRustInfo.WholeRustRlibDeps...)
    if !mod.Rlib() {
     depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedRustInfo.WholeRustRlibDeps...)
    }
   }

   if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
    linkFile := linkableInfo.UnstrippedOutputFile
    linkDir := linkPathFromFilePath(linkFile)
    if lib, ok := mod.compiler.(exportedFlagsProducer); ok {
     lib.exportLinkDirs([]string{linkDir}, []android.Path{linkFile})
    }
   }

   if depTag == sourceDepTag {
    if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() {
     if rustInfo.SourceProviderInfo.ProtobufDecoratorInfo != nil {
      exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
      depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
     }
    }
   }
  } else if hasLinkableInfo {
   //Handle C dependencies
   makeLibName := cc.MakeLibName(ccInfo, linkableInfo, commonInfo, depName)
   if !hasRustInfo {
    if commonInfo.Target.Os != ctx.Os() {
     ctx.ModuleErrorf("OS mismatch between %q (%s) and %q (%s)",
      ctx.ModuleName(), ctx.Os().Name, depName, commonInfo.Target.Os.Name)
     return
    }
    if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType {
     ctx.ModuleErrorf("Arch mismatch between %q(%v) and %q(%v)",
      ctx.ModuleName(), ctx.Arch().ArchType, depName, commonInfo.Target.Arch.ArchType)
     return
    }
   }
   ccLibPath := linkableInfo.OutputFile
   if !ccLibPath.Valid() {
    if !ctx.Config().AllowMissingDependencies() {
     ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
    } else {
     ctx.AddMissingDependencies([]string{depName})
    }
    return
   }

   linkPath := linkPathFromFilePath(ccLibPath.Path())

   exportDep := false
   switch {
   case cc.IsStaticDepTag(depTag):
    if cc.IsWholeStaticLib(depTag) {
     // rustc will bundle static libraries when they're passed with "-lstatic=<lib>". This will fail
     // if the library is not prefixed by "lib".
     if mod.Binary() {
      // Since binaries don't need to 'rebundle' these like libraries and only use these for the
      // final linkage, pass the args directly to the linker to handle these cases.
      depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", ccLibPath.Path().String(), "-Wl,--no-whole-archive"}...)
     } else if libName, ok := libNameFromFilePath(ccLibPath.Path()); ok {
      depPaths.depFlags = append(depPaths.depFlags, "-lstatic:+whole-archive="+libName)
      depPaths.depLinkFlags = append(depPaths.depLinkFlags, ccLibPath.Path().String())
     } else {
      ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName())
     }
    }

    exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
    if cc.IsWholeStaticLib(depTag) {
     // Add whole staticlibs to wholeStaticLibObjects to propagate to Rust all dependents.
     depPaths.wholeStaticLibObjects = append(depPaths.wholeStaticLibObjects, ccLibPath.String())

     // We also propagate forward whole-static'd cc staticlibs with rust_ffi_rlib dependencies
     // We don't need to check a hypothetical exportedRustInfo.WholeRustRlibDeps because we
     // wouldn't expect a rust_ffi_rlib to be listed in `static_libs` (Soong explicitly disallows this)
     depPaths.reexportedWholeCcRlibDeps = append(depPaths.reexportedWholeCcRlibDeps, exportedInfo.RustRlibDeps...)
    } else {
     // If not whole_static, add to staticLibObjects, which only propagate through rlibs to their dependents.
     depPaths.staticLibObjects = append(depPaths.staticLibObjects, ccLibPath.String())

     if mod.Rlib() {
      // rlibs propagate their inherited rust_ffi_rlibs forward.
      depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
     }
    }

    depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
    depPaths.linkDirsDeps = append(depPaths.linkDirsDeps, ccLibPath.Path())
    depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
    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...)
    }

    directStaticLibDeps = append(directStaticLibDeps, linkableInfo)

    // Record baseLibName for snapshots.
    mod.Properties.SnapshotStaticLibs = append(mod.Properties.SnapshotStaticLibs, cc.BaseLibName(depName))

    mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, makeLibName)
   case cc.IsSharedDepTag(depTag):
    // For the shared lib dependencies, we may link to the stub variant
    // of the dependency depending on the context (e.g. if this
    // dependency crosses the APEX boundaries).
    sharedLibraryInfo, exportedInfo := cc.ChooseStubOrImpl(ctx, dep)

    if !sharedLibraryInfo.IsStubs {
     // TODO(b/362509506): remove this additional check once all apex_exclude uses are switched to stubs.
     if !linkableInfo.RustApexExclude {
      depPaths.directApexImplementationDeps = append(depPaths.directApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
      if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
       depPaths.transitiveApexImplementationDeps = append(depPaths.transitiveApexImplementationDeps, info.ImplementationDeps)
      }
     }
    }

    // Re-get linkObject as ChooseStubOrImpl actually tells us which
    // object (either from stub or non-stub) to use.
    ccLibPath = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary)
    if !ccLibPath.Valid() {
     if !ctx.Config().AllowMissingDependencies() {
      ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
     } else {
      ctx.AddMissingDependencies([]string{depName})
     }
     return
    }
    linkPath = linkPathFromFilePath(ccLibPath.Path())

    depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
    depPaths.linkDirsDeps = append(depPaths.linkDirsDeps, ccLibPath.Path())
    depPaths.sharedLibObjects = append(depPaths.sharedLibObjects, ccLibPath.String())
    depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
    depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
    depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
    depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
    directSharedLibDeps = append(directSharedLibDeps, sharedLibraryInfo)

    // Record baseLibName for snapshots.
    mod.Properties.SnapshotSharedLibs = append(mod.Properties.SnapshotSharedLibs, cc.BaseLibName(depName))

    directAndroidMkSharedLibs = append(directAndroidMkSharedLibs, makeLibName)
    exportDep = true
   case cc.IsHeaderDepTag(depTag):
    exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
    depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
    depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
    depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
    mod.Properties.AndroidMkHeaderLibs = append(mod.Properties.AndroidMkHeaderLibs, makeLibName)
   case depTag == cc.CrtBeginDepTag:
    depPaths.CrtBegin = append(depPaths.CrtBegin, ccLibPath.Path())
   case depTag == cc.CrtEndDepTag:
    depPaths.CrtEnd = append(depPaths.CrtEnd, ccLibPath.Path())
   }

   // Make sure shared dependencies are propagated
   if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep {
    lib.exportLinkDirs([]string{linkPath}, []android.Path{ccLibPath.Path()})
    lib.exportSharedLibs(ccLibPath.String())
   }
  } else {
   switch depTag {
   case cc.CrtBeginDepTag:
    depPaths.CrtBegin = append(depPaths.CrtBegin, android.OutputFileForModule(ctx, dep, ""))
    depPaths.directNonApexImplementationDeps = append(depPaths.directNonApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
   case cc.CrtEndDepTag:
    depPaths.directNonApexImplementationDeps = append(depPaths.directNonApexImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
    depPaths.CrtEnd = append(depPaths.CrtEnd, android.OutputFileForModule(ctx, dep, ""))
   }
  }

  if srcDep := commonInfo.SourceFiles; srcDep != nil {
   if android.IsSourceDepTagWithOutputTag(depTag, "") {
    // These are usually genrules which don't have per-target variants.
    directSrcDeps = append(directSrcDeps, *srcDep)
   }
  }
 })

 mod.transitiveAndroidMkSharedLibs = depset.New(depset.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs)

 var rlibDepFiles RustLibraries
 aliases := mod.compiler.Aliases()
 for _, dep := range directRlibDeps {
  crateName := dep.CrateName
  if alias, aliased := aliases[crateName]; aliased {
   crateName = alias
  }
  rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName})
 }
 var dylibDepFiles RustLibraries
 for _, dep := range directDylibDeps {
  crateName := dep.CrateName
  if alias, aliased := aliases[crateName]; aliased {
   crateName = alias
  }
  dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName})
 }
 var procMacroDepFiles RustLibraries
 for _, dep := range directProcMacroDeps {
  crateName := dep.CrateName
  if alias, aliased := aliases[crateName]; aliased {
   crateName = alias
  }
  procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName})
 }

 var staticLibDepFiles android.Paths
 for _, dep := range directStaticLibDeps {
  staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile.Path())
 }

 var sharedLibFiles android.Paths
 var sharedLibDepFiles android.Paths
 for _, dep := range directSharedLibDeps {
  sharedLibFiles = append(sharedLibFiles, dep.SharedLibrary)
  if dep.TableOfContents.Valid() {
   sharedLibDepFiles = append(sharedLibDepFiles, dep.TableOfContents.Path())
  } else {
   sharedLibDepFiles = append(sharedLibDepFiles, dep.SharedLibrary)
  }
 }

 var srcProviderDepFiles android.Paths
 for _, dep := range directSrcProvidersDeps {
  srcs := android.OutputFilesForModule(ctx, *dep, "")
  srcProviderDepFiles = append(srcProviderDepFiles, srcs...)
 }
 for _, dep := range directSrcDeps {
  srcs := dep.Srcs
  outDir := android.PathForOutput(ctx).String() + string(os.PathSeparator)
  for _, srcFile := range srcs {
   if strings.HasPrefix(srcFile.String(), outDir) {
    // Only append generated files from genrules and other source file
    // producers. This is to ensure filegroups aren't included in this
    // list and later copied
    srcProviderDepFiles = append(srcProviderDepFiles, srcFile)
   }
  }
 }

 depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...)
 depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...)
 depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibFiles...)
 depPaths.SharedLibDeps = append(depPaths.SharedLibDeps, sharedLibDepFiles...)
 depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...)
 depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...)
 depPaths.SrcDeps = append(depPaths.SrcDeps, srcProviderDepFiles...)

 // Dedup exported flags from dependencies
 depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs)
 depPaths.linkDirsDeps = android.FirstUniquePaths(depPaths.linkDirsDeps)
 depPaths.rustLibObjects = android.FirstUniqueStrings(depPaths.rustLibObjects)
 depPaths.staticLibObjects = android.FirstUniqueStrings(depPaths.staticLibObjects)
 depPaths.wholeStaticLibObjects = android.FirstUniqueStrings(depPaths.wholeStaticLibObjects)
 depPaths.sharedLibObjects = android.FirstUniqueStrings(depPaths.sharedLibObjects)
 depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags)
 depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags)
 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.reexportedWholeCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedWholeCcRlibDeps, cc.EqRustRlibDeps)
 depPaths.ccRlibDeps = android.FirstUniqueFunc(depPaths.ccRlibDeps, cc.EqRustRlibDeps)

 makeNames := append(mod.transitiveAndroidMkSharedLibs.ToList(), mod.Properties.AndroidMkDylibs...)
 return depPaths, makeNames
}

func (mod *Module) InstallInData() bool {
 if mod.compiler == nil {
  return false
 }
 return mod.compiler.inData()
}

func (mod *Module) InstallInRamdisk() bool {
 return mod.InRamdisk()
}

func (mod *Module) InstallInVendorRamdisk() bool {
 return mod.InVendorRamdisk()
}

func (mod *Module) InstallInRecovery() bool {
 return mod.InRecovery()
}

func linkPathFromFilePath(filepath android.Path) string {
 return strings.Split(filepath.String(), filepath.Base())[0]
}

func (mod *Module) StdLinkageIsRlibLinkage(device bool) bool {
 if mod.compiler != nil {
  switch mod.compiler.stdLinkage(device) {
  case NoCore, RlibCore, RlibStd:
   return true
  }
 }
 return false
}

// Go remains uncivilized for not having this as a default method on their slice.
func sliceMap[E1 any, E2 any](base []E1, f func(E1) E2) []E2 {
 out := make([]E2, len(base))
 for i, v := range base {
  out[i] = f(v)
 }
 return out
}

func (linkage StdLinkage) compatChoices() []StdLinkage {
 switch linkage {
 case DylibStd:
  // dylib-std should only takes its own linkage, but there are cases in the build
  // today that are depending on no-std modules.
  // TODO migrate so that dylib-std only pulls in dylib-std
  return []StdLinkage{linkage, RlibCore}
 case RlibStd:
  // rlib-std can also accept rlib-core libraries, but should prefer std libraries.
  return []StdLinkage{linkage, RlibCore}
 case RlibCore:
  // rlib-core should only support its own linkage, but there are a variety of cases
  // in the build today where a no-std build is depending on a std build, so we need
  // to allow it, at least for now.
  // TODO migrate existing builds to not have rlib-core libraries depend on rlib-std
  return []StdLinkage{linkage, RlibStd}
 case NoCore:
  // Sysroots can only accept other sysroot (e.g. non-mutated) libraries
  return []StdLinkage{linkage}
 }
 panic(fmt.Errorf("unrecognized linkage %v", linkage))
}

func (mod *Module) stdLinkageOptions(ctx DepsContext) [][]blueprint.Variation {
 stdLinkage := mod.compiler.stdLinkage(ctx.Device())
 switch stdLinkage {
 case NoCore:
  // NoCore is currently unmutated, so there's no variation here
  return [][]blueprint.Variation{{}}
 default:
  return sliceMap(stdLinkage.compatChoices(), func(choice StdLinkage) []blueprint.Variation { return []blueprint.Variation{choice.variation()} })
 }
}

func (mod *Module) addNoStdDep(ctx DepsContext, lib string) {
 variations := []blueprint.Variation{RlibCore.variation(), rlibDepTag.libraryVariation()}

 if ctx.OtherModuleDependencyVariantExists(variations, lib) {
  ctx.AddVariationDependencies(variations, rlibDepTag, lib)
  return
 }
 // To allow migration of custom nostd modules to no_std variants, temporarily support
 // stripping _nostd suffixes if the library is not present.
 // This is made safe by the enforcement that no_std libraries can no longer depend on
 // stdful libraries, which works transitively.
 if strings.HasSuffix(lib, "_nostd") {
  mod.addNoStdDep(ctx, strings.TrimSuffix(lib, "_nostd"))
  return
 }
 if !ctx.Config().AllowMissingDependencies() {
  ctx.ModuleErrorf("unable to find no_std variation for lib %#v", lib)
 }
}

func (mod *Module) addVariantDep(ctx DepsContext, depTags []dependencyTag, lib string) {
 // Preference order is to get the preferred depTag, then to get preferred stdLinkage.
 for _, depTag := range depTags {
  for _, stdLinkage := range mod.stdLinkageOptions(ctx) {
   variations := append(stdLinkage, depTag.libraryVariation())
   // If the stdlinkage + depTag choice exists, select it and return
   if ctx.OtherModuleDependencyVariantExists(variations, lib) {
    ctx.AddVariationDependencies(variations, depTag, lib)
    return
   }
  }
 }
 // To allow migration of custom nostd modules to no_std variants, temporarily support
 // stripping _nostd suffixes if the library is not present.
 // This is made safe by the enforcement that no_std libraries can no longer depend on
 // stdful libraries, which works transitively.
 if strings.HasSuffix(lib, "_nostd") {
  mod.addVariantDep(ctx, depTags, strings.TrimSuffix(lib, "_nostd"))
  return
 }
 if !ctx.Config().AllowMissingDependencies() {
  // Intentionally add a missing dependency to trigger a more user-friendly error
  depTag := depTags[0]
  stdLinkage := mod.stdLinkageOptions(ctx)[0]
  variations := append(stdLinkage, depTag.libraryVariation())
  ctx.AddVariationDependencies(variations, depTag, lib)
 }
}

func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
 ctx := &depsContext{
  BottomUpMutatorContext: actx,
 }

 deps := mod.deps(ctx)
 var commonDepVariations []blueprint.Variation

 variantNdkLibs := []string{}
 if ctx.Os() == android.Android {
  deps.SharedLibs, variantNdkLibs = cc.FilterNdkLibs(mod, ctx.Config(), deps.SharedLibs)
 }

 // rlibs
 for _, lib := range deps.Rlibs {
  mod.addVariantDep(ctx, []dependencyTag{rlibDepTag}, lib)
 }

 // dylibs
 for _, lib := range deps.Dylibs {
  mod.addVariantDep(ctx, []dependencyTag{dylibDepTag}, lib)
 }

 // rustlibs
 if deps.Rustlibs != nil {
  if !mod.compiler.Disabled() {
   for _, lib := range deps.Rustlibs {
    autoDep := mod.compiler.(autoDeppable).autoDep(ctx)
    switch autoDep.depTag {
    case rlibDepTag:
     mod.addVariantDep(ctx, []dependencyTag{rlibDepTag}, lib)
    case dylibDepTag:
     // autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however.
     // Check for the existence of the dylib deptag variant. Select it if available,
     // otherwise select the rlib variant.
     mod.addVariantDep(ctx, []dependencyTag{dylibDepTag, rlibDepTag}, lib)
    default:
     panic(fmt.Errorf("unknown depTag: %v", autoDep.depTag))
    }
   }
  } else if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
   for _, lib := range deps.Rustlibs {
    srcProviderVariations := append(commonDepVariations,
     blueprint.Variation{Mutator: "rust_libraries", Variation: sourceVariation})

    // Only add rustlib dependencies if they're source providers themselves.
    // This is used to track which crate names need to be added to the source generated
    // in the rust_protobuf mod.rs.
    if actx.OtherModuleDependencyVariantExists(srcProviderVariations, lib) {
     actx.AddVariationDependencies(srcProviderVariations, sourceDepTag, lib)
    }
   }
  }
 }

 if deps.NoStdRlibs != nil {
  for _, lib := range deps.NoStdRlibs {
   mod.addNoStdDep(ctx, lib)
  }
 }

 // stdlibs
 if deps.Stdlibs != nil {
  stdLinkage := mod.compiler.stdLinkage(ctx.Device())
  for _, lib := range deps.Stdlibs {
   actx.AddVariationDependencies(stdLinkage.libraryVariations(), stdLinkage.depTag(), lib)
  }
 }

 for _, lib := range deps.SharedLibs {
  depTag := cc.SharedDepTag()
  name, version := cc.StubsLibNameAndVersion(lib)

  variations := []blueprint.Variation{
   {Mutator: "link", Variation: "shared"},
  }
  cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false)
 }

 for _, lib := range deps.WholeStaticLibs {
  depTag := cc.StaticDepTag(true)

  actx.AddVariationDependencies([]blueprint.Variation{
   {Mutator: "link", Variation: "static"},
  }, depTag, lib)
 }

 for _, lib := range deps.StaticLibs {
  depTag := cc.StaticDepTag(false)

  actx.AddVariationDependencies([]blueprint.Variation{
   {Mutator: "link", Variation: "static"},
  }, depTag, lib)
 }

 actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...)

 crtVariations := cc.GetCrtVariations(ctx, mod)
 for _, crt := range deps.CrtBegin {
  actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag, crt)
 }
 for _, crt := range deps.CrtEnd {
  actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag, crt)
 }

 if mod.sourceProvider != nil {
  if bindgen, ok := mod.sourceProvider.(*bindgenDecorator); ok &&
   bindgen.Properties.Custom_bindgen != "" {
   actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), customBindgenDepTag,
    bindgen.Properties.Custom_bindgen)
  }
 }

 actx.AddVariationDependencies([]blueprint.Variation{
  {Mutator: "link", Variation: "shared"},
 }, dataLibDepTag, deps.DataLibs...)

 version := ""
 if ctx.Device() {
  version = String(mod.Properties.Sdk_version)
 }

 ndkStubDepTag := cc.NdkSharedLibDepTag(version)
 actx.AddVariationDependencies([]blueprint.Variation{
  {Mutator: "version", Variation: version},
  {Mutator: "link", Variation: "shared"},
 }, ndkStubDepTag, variantNdkLibs...)

 actx.AddVariationDependencies(nil, dataBinDepTag, deps.DataBins...)

 // proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
 actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)

 mod.afdo.addDep(ctx, actx)
}

func BeginMutator(ctx android.BottomUpMutatorContext) {
 if mod, ok := ctx.Module().(*Module); ok && mod.Enabled(ctx) {
  mod.beginMutator(ctx)
 }
}

func (mod *Module) beginMutator(actx android.BottomUpMutatorContext) {
 ctx := &baseModuleContext{
  BaseModuleContext: actx,
 }

 mod.begin(ctx)
}

func (mod *Module) Name() string {
 name := mod.ModuleBase.Name()
 if p, ok := mod.compiler.(interface {
  Name(string) string
 }); ok {
  name = p.Name(name)
 }
 return name
}

func (mod *Module) disableClippy() {
 if mod.clippy != nil {
  mod.clippy.Properties.Clippy_lints = proptools.StringPtr("none")
 }
}

var _ android.HostToolProvider = (*Module)(nil)

func (mod *Module) HostToolPath() android.OptionalPath {
 if !mod.Host() {
  return android.OptionalPath{}
 }
 if binary, ok := mod.compiler.(*binaryDecorator); ok {
  return android.OptionalPathForPath(binary.path)
 } else if pm, ok := mod.compiler.(*procMacroDecorator); ok {
  // Even though proc-macros aren't strictly "tools", since they target the compiler
  // and act as compiler plugins, we treat them similarly.
  return android.OptionalPathForPath(pm.path)
 }
 return android.OptionalPath{}
}

var _ android.ApexModule = (*Module)(nil)

// If a module is marked for exclusion from apexes, don't provide apex variants.
// TODO(b/362509506): remove this once all apex_exclude usages are removed.
func (m *Module) CanHaveApexVariants() bool {
 if m.ApexExclude() {
  return false
 } else {
  return m.ApexModuleBase.CanHaveApexVariants()
 }
}

func (mod *Module) MinSdkVersion(ctx android.ConfigurableEvaluatorContext) string {
 return String(mod.Properties.Min_sdk_version)
}

// Implements android.ApexModule
func (mod *Module) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
 minSdkVersion := mod.MinSdkVersion(ctx)
 if minSdkVersion == "apex_inherit" {
  return android.MinApiLevel
 }

 if minSdkVersion == "" {
  return android.NoneApiLevel
 }
 // Not using nativeApiLevelFromUser because the context here is not
 // necessarily a native context.
 ver, err := android.ApiLevelFromUserWithConfig(ctx.Config(), minSdkVersion)
 if err != nil {
  return android.NoneApiLevel
 }

 return ver
}

// Implements android.ApexModule
func (mod *Module) AlwaysRequiresPlatformApexVariant() bool {
 // stub libraries and native bridge libraries are always available to platform
 // TODO(b/362509506): remove the ApexExclude() check once all apex_exclude uses are switched to stubs.
 return mod.IsStubs() || mod.Target().NativeBridge == android.NativeBridgeEnabled || mod.ApexExclude()
}

// Implements android.ApexModule
// @auto-generate: gob
type RustDepInSameApexChecker struct {
 Static           bool
 HasStubsVariants bool
 ApexExclude      bool
 Host             bool
}

func (mod *Module) GetDepInSameApexChecker() android.DepInSameApexChecker {
 return RustDepInSameApexChecker{
  Static:           mod.Static(),
  HasStubsVariants: mod.HasStubsVariants(),
  ApexExclude:      mod.ApexExclude(),
  Host:             mod.Host(),
 }
}

func (r RustDepInSameApexChecker) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
 if depTag == procMacroDepTag || depTag == customBindgenDepTag {
  return false
 }

 if r.Static && cc.IsSharedDepTag(depTag) {
  // shared_lib dependency from a static lib is considered as crossing
  // the APEX boundary because the dependency doesn't actually is
  // linked; the dependency is used only during the compilation phase.
  return false
 }

 if depTag == cc.StubImplDepTag {
  // We don't track from an implementation library to its stubs.
  return false
 }

 if cc.ExcludeInApexDepTag(depTag) {
  return false
 }

 // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs.
 if r.ApexExclude {
  return false
 }

 return true
}

func (r RustDepInSameApexChecker) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
 if r.Host {
  return false
 }
 // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs.
 if r.ApexExclude {
  return false
 }

 if r.HasStubsVariants {
  if cc.IsSharedDepTag(depTag) && !cc.IsExplicitImplSharedDepTag(depTag) {
   // dynamic dep to a stubs lib crosses APEX boundary
   return false
  }
  if cc.IsRuntimeDepTag(depTag) {
   // runtime dep to a stubs lib also crosses APEX boundary
   return false
  }
  if cc.IsHeaderDepTag(depTag) {
   return false
  }
 }
 return true
}

// Overrides ApexModule.IsInstallabeToApex()
func (mod *Module) IsInstallableToApex() bool {
 // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs.
 if mod.ApexExclude() {
  return false
 }

 if mod.compiler != nil {
  if lib, ok := mod.compiler.(libraryInterface); ok {
   return (lib.shared() || lib.dylib()) && !lib.BuildStubs()
  }
  if _, ok := mod.compiler.(*binaryDecorator); ok {
   return true
  }
 }
 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
}

func (c *Module) Partition() string {
 return ""
}

// @auto-generate: gob
type RustImplementationDepInfo struct {
 NonApexImplementationDeps depset.DepSet[android.Path]
}

func (linkage StdLinkage) libraryVariations() []blueprint.Variation {
 switch linkage {
 case RlibCore, RlibStd:
  return []blueprint.Variation{{Mutator: "rust_libraries", Variation: rlibVariation}}
 case DylibStd:
  return []blueprint.Variation{{Mutator: "rust_libraries", Variation: dylibVariation}}
 case NoCore:
  panic("trying to link stdlibs for no-core library")
 default:
  panic(fmt.Errorf("unknown linkage: %v", linkage))
 }
}

func (linkage StdLinkage) depTag() dependencyTag {
 switch linkage {
 case RlibCore, RlibStd:
  return rlibDepTag
 case DylibStd:
  return dylibDepTag
 default:
  panic(fmt.Errorf("unknown linkage: %v", linkage))
 }
}

func (depTag dependencyTag) libraryVariation() blueprint.Variation {
 switch depTag {
 case rlibDepTag:
  return blueprint.Variation{Mutator: "rust_libraries", Variation: rlibVariation}
 case dylibDepTag:
  return blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation}
 default:
  panic(fmt.Errorf("creating variation for unknown depTag: %v", depTag))
 }
}

var RustImplementationDepInfoProvider = blueprint.NewProvider[*RustImplementationDepInfo]()

var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String
var StringPtr = proptools.StringPtr

[Dauer der Verarbeitung: 0.37 Sekunden, vorverarbeitet 2026-06-28]