diff options
Diffstat (limited to 'rust/rust.go')
| -rw-r--r-- | rust/rust.go | 665 |
1 files changed, 512 insertions, 153 deletions
diff --git a/rust/rust.go b/rust/rust.go index a044a99dd..4fd800282 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -20,9 +20,9 @@ import ( "strings" "android/soong/bloaty" - "android/soong/testing" "github.com/google/blueprint" + "github.com/google/blueprint/depset" "github.com/google/blueprint/proptools" "android/soong/android" @@ -34,6 +34,36 @@ import ( var pctx = android.NewPackageContext("android/soong/rust") +type LibraryInfo struct { + Rlib bool + Dylib bool +} + +type CompilerInfo struct { + StdLinkageForDevice RustLinkage + StdLinkageForNonDevice RustLinkage + NoStdlibs bool + LibraryInfo *LibraryInfo +} + +type ProtobufDecoratorInfo struct{} + +type SourceProviderInfo struct { + Srcs android.Paths + ProtobufDecoratorInfo *ProtobufDecoratorInfo +} + +type RustInfo struct { + AndroidMkSuffix string + RustSubName string + TransitiveAndroidMkSharedLibs depset.DepSet[string] + CompilerInfo *CompilerInfo + SnapshotInfo *cc.SnapshotInfo + SourceProviderInfo *SourceProviderInfo +} + +var RustInfoProvider = blueprint.NewProvider[*RustInfo]() + func init() { android.RegisterModuleType("rust_defaults", defaultsFactory) android.PreDepsMutators(registerPreDepsMutators) @@ -47,11 +77,11 @@ func init() { func registerPreDepsMutators(ctx android.RegisterMutatorsContext) { ctx.Transition("rust_libraries", &libraryTransitionMutator{}) ctx.Transition("rust_stdlinkage", &libstdTransitionMutator{}) - ctx.BottomUp("rust_begin", BeginMutator).Parallel() + ctx.BottomUp("rust_begin", BeginMutator) } func registerPostDepsMutators(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel() + ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator) } type Flags struct { @@ -133,9 +163,36 @@ type BaseProperties struct { // Make this module available when building for recovery Recovery_available *bool - // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX). + // 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 + + // 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 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"` @@ -179,7 +236,10 @@ type Module struct { // For apex variants, this is set as apex.min_sdk_version apexSdkVersion android.ApiLevel - transitiveAndroidMkSharedLibs *android.DepSet[string] + transitiveAndroidMkSharedLibs depset.DepSet[string] + + // Shared flags among stubs build rules of this module + sharedFlags cc.SharedFlags } func (mod *Module) Header() bool { @@ -345,7 +405,8 @@ func (mod *Module) IsVndkPrebuiltLibrary() bool { } func (mod *Module) IsVendorPublicLibrary() bool { - return mod.VendorProperties.IsVendorPublicLibrary + // Rust modules do not currently support vendor_public_library + return false } func (mod *Module) SdkAndPlatformVariantVisibleToMake() bool { @@ -354,10 +415,12 @@ func (mod *Module) SdkAndPlatformVariantVisibleToMake() bool { } 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 } @@ -366,35 +429,34 @@ func (mod *Module) KernelHeadersDecorator() bool { } 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) StubsVersion() string { - panic(fmt.Errorf("StubsVersion called on non-versioned module: %q", mod.BaseModuleName())) -} - func (mod *Module) SdkVersion() string { - return "" + return String(mod.Properties.Sdk_version) } func (mod *Module) AlwaysSdk() bool { - return false + return mod.Properties.AlwaysSdk } func (mod *Module) IsSdkVariant() bool { - return false + return mod.Properties.IsSdkVariant } func (mod *Module) SplitPerApiLevel() bool { - return false + return cc.CanUseSdk(mod) && mod.IsCrt() } func (mod *Module) XrefRustFiles() android.Paths { @@ -427,15 +489,23 @@ type PathDeps struct { 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 + 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 - linkObjects []string + linkDirs []string + rustLibObjects []string + staticLibObjects []string + wholeStaticLibObjects []string + sharedLibObjects []string // exportedLinkDirs are exported linkDirs for direct rlib dependencies to // cc_library_static dependants of rlibs. @@ -454,6 +524,9 @@ type PathDeps struct { // Paths to generated source files SrcDeps android.Paths srcProviderFiles android.Paths + + directImplementationDeps android.Paths + transitiveImplementationDeps []depset.DepSet[android.Path] } type RustLibraries []RustLibrary @@ -465,7 +538,10 @@ type RustLibrary struct { type exportedFlagsProducer interface { exportLinkDirs(...string) - exportLinkObjects(...string) + exportRustLibs(...string) + exportStaticLibs(...string) + exportWholeStaticLibs(...string) + exportSharedLibs(...string) } type xref interface { @@ -473,23 +549,41 @@ type xref interface { } type flagExporter struct { - linkDirs []string - ccLinkDirs []string - linkObjects []string + linkDirs []string + ccLinkDirs []string + rustLibPaths []string + staticLibObjects []string + sharedLibObjects []string + wholeStaticLibObjects []string } func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) { flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...)) } -func (flagExporter *flagExporter) exportLinkObjects(flags ...string) { - flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...)) +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) setProvider(ctx ModuleContext) { - android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{ - LinkDirs: flagExporter.linkDirs, - LinkObjects: flagExporter.linkObjects, +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, + RustLibObjects: flagExporter.rustLibPaths, + StaticLibObjects: flagExporter.staticLibObjects, + WholeStaticLibObjects: flagExporter.wholeStaticLibObjects, + SharedLibPaths: flagExporter.sharedLibObjects, }) } @@ -499,13 +593,16 @@ func NewFlagExporter() *flagExporter { return &flagExporter{} } -type FlagExporterInfo struct { - Flags []string - LinkDirs []string // TODO: this should be android.Paths - LinkObjects []string // TODO: this should be android.Paths +type RustFlagExporterInfo struct { + Flags []string + LinkDirs []string + RustLibObjects []string + StaticLibObjects []string + WholeStaticLibObjects []string + SharedLibPaths []string } -var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]() +var RustFlagExporterInfoProvider = blueprint.NewProvider[RustFlagExporterInfo]() func (mod *Module) isCoverageVariant() bool { return mod.coverage.Properties.IsCoverageVariant @@ -528,6 +625,9 @@ func (mod *Module) ExportedCrateLinkDirs() []string { 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 @@ -591,7 +691,7 @@ 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()) { + if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic() || lib.buildRlib()) { return true } } @@ -677,15 +777,6 @@ func (mod *Module) BuildRlibVariant() bool { panic(fmt.Errorf("BuildRlibVariant called on non-library module: %q", mod.BaseModuleName())) } -func (mod *Module) IsRustFFI() bool { - if mod.compiler != nil { - if library, ok := mod.compiler.(libraryInterface); ok { - return library.isFFILibrary() - } - } - return false -} - func (mod *Module) BuildSharedVariant() bool { if mod.compiler != nil { if library, ok := mod.compiler.(libraryInterface); ok { @@ -720,6 +811,50 @@ func (mod *Module) IsNdk(config android.Config) bool { } 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(ctx android.BaseModuleContext) 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 { + // Rust does not currently provide any crt modules. return false } @@ -743,6 +878,7 @@ func (ctx moduleContext) apexVariationName() string { } var _ cc.LinkableInterface = (*Module)(nil) +var _ cc.VersionedLinkableInterface = (*Module)(nil) func (mod *Module) Init() android.Module { mod.AddProperties(&mod.Properties) @@ -853,6 +989,25 @@ func (mod *Module) nativeCoverage() bool { 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 = StringPtr(s) +} + +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. @@ -942,12 +1097,11 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { mod.sourceProvider.GenerateSource(ctx, deps) mod.sourceProvider.setSubName(ctx.ModuleSubDir()) } else { - sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag) - sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator) - mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs()) + sourceMod := actx.GetDirectDepProxyWithTag(mod.Name(), sourceDepTag) + sourceLib := android.OtherModuleProviderOrDefault(ctx, sourceMod, RustInfoProvider).SourceProviderInfo + mod.sourceProvider.setOutputFiles(sourceLib.Srcs) } ctx.CheckbuildFile(mod.sourceProvider.Srcs()...) - android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: mod.sourceProvider.Srcs().Strings()}) } if mod.compiler != nil && !mod.compiler.Disabled() { @@ -974,6 +1128,7 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { // 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() } @@ -990,15 +1145,81 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { } + android.SetProvider(ctx, cc.ImplementationDepInfoProvider, &cc.ImplementationDepInfo{ + ImplementationDeps: depset.New(depset.PREORDER, deps.directImplementationDeps, deps.transitiveImplementationDeps), + }) + ctx.Phony("rust", ctx.RustModule().OutputFile().Path()) } - if mod.testModule { - android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{}) + + linkableInfo := cc.CreateCommonLinkableInfo(ctx, mod) + linkableInfo.Static = mod.Static() + linkableInfo.Shared = mod.Shared() + linkableInfo.CrateName = mod.CrateName() + linkableInfo.ExportedCrateLinkDirs = mod.ExportedCrateLinkDirs() + if lib, ok := mod.compiler.(cc.VersionedInterface); ok { + linkableInfo.StubsVersion = lib.StubsVersion() } + android.SetProvider(ctx, cc.LinkableInfoProvider, linkableInfo) + + rustInfo := &RustInfo{ + AndroidMkSuffix: mod.AndroidMkSuffix(), + RustSubName: mod.Properties.RustSubName, + TransitiveAndroidMkSharedLibs: mod.transitiveAndroidMkSharedLibs, + } + if mod.compiler != nil { + rustInfo.CompilerInfo = &CompilerInfo{ + NoStdlibs: mod.compiler.noStdlibs(), + StdLinkageForDevice: mod.compiler.stdLinkage(true), + StdLinkageForNonDevice: mod.compiler.stdLinkage(false), + } + 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{} + } + } + android.SetProvider(ctx, RustInfoProvider, rustInfo) + + ccInfo := &cc.CcInfo{ + IsPrebuilt: mod.IsPrebuilt(), + } + + // Define the linker info if compiler != nil because Rust currently + // does compilation and linking in one step. If this changes in the future, + // move this as appropriate. + baseCompilerProps := mod.compiler.baseCompilerProps() + ccInfo.LinkerInfo = &cc.LinkerInfo{ + WholeStaticLibs: baseCompilerProps.Whole_static_libs.GetOrDefault(ctx, nil), + StaticLibs: baseCompilerProps.Static_libs.GetOrDefault(ctx, nil), + SharedLibs: baseCompilerProps.Shared_libs.GetOrDefault(ctx, nil), + } + + android.SetProvider(ctx, cc.CcInfoProvider, ccInfo) + mod.setOutputFiles(ctx) buildComplianceMetadataInfo(ctx, mod, deps) + + moduleInfoJSON := ctx.ModuleInfoJSON() + if mod.compiler != nil { + mod.compiler.moduleInfoJSON(ctx, moduleInfoJSON) + } } func (mod *Module) setOutputFiles(ctx ModuleContext) { @@ -1021,12 +1242,12 @@ func buildComplianceMetadataInfo(ctx *moduleContext, mod *Module, deps PathDeps) metadataInfo.SetStringValue(android.ComplianceMetadataProp.BUILT_FILES, mod.outputFile.String()) // Static libs - staticDeps := ctx.GetDirectDepsWithTag(rlibDepTag) + staticDeps := ctx.GetDirectDepsProxyWithTag(rlibDepTag) staticDepNames := make([]string, 0, len(staticDeps)) for _, dep := range staticDeps { staticDepNames = append(staticDepNames, dep.Name()) } - ccStaticDeps := ctx.GetDirectDepsWithTag(cc.StaticDepTag(false)) + ccStaticDeps := ctx.GetDirectDepsProxyWithTag(cc.StaticDepTag(false)) for _, dep := range ccStaticDeps { staticDepNames = append(staticDepNames, dep.Name()) } @@ -1044,7 +1265,7 @@ func buildComplianceMetadataInfo(ctx *moduleContext, mod *Module, deps PathDeps) metadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEP_FILES, android.FirstUniqueStrings(staticDepPaths)) // C Whole static libs - ccWholeStaticDeps := ctx.GetDirectDepsWithTag(cc.StaticDepTag(true)) + ccWholeStaticDeps := ctx.GetDirectDepsProxyWithTag(cc.StaticDepTag(true)) wholeStaticDepNames := make([]string, 0, len(ccWholeStaticDeps)) for _, dep := range ccStaticDeps { wholeStaticDepNames = append(wholeStaticDepNames, dep.Name()) @@ -1157,6 +1378,21 @@ func (mod *Module) begin(ctx BaseModuleContext) { if mod.sanitize != nil { mod.sanitize.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 { @@ -1171,21 +1407,21 @@ func (mod *Module) Symlinks() []string { return nil } -func rustMakeLibName(ctx android.ModuleContext, c cc.LinkableInterface, dep cc.LinkableInterface, depName string) string { - if rustDep, ok := dep.(*Module); ok { +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 snapshotPrebuilt, ok := rustDep.compiler.(cc.SnapshotInterface); ok { - baseName := rustDep.BaseModuleName() - return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix() + rustDep.AndroidMkSuffix() + if rustInfo.SnapshotInfo != nil { + baseName := linkableInfo.BaseModuleName + return baseName + rustInfo.SnapshotInfo.SnapshotAndroidMkSuffix + rustInfo.AndroidMkSuffix } } - return cc.MakeLibName(ctx, c, dep, depName) + return cc.MakeLibName(nil, linkableInfo, commonInfo, depName) } -func collectIncludedProtos(mod *Module, dep *Module) { +func collectIncludedProtos(mod *Module, rustInfo *RustInfo, linkableInfo *cc.LinkableInfo) { if protoMod, ok := mod.sourceProvider.(*protobufDecorator); ok { - if _, ok := dep.sourceProvider.(*protobufDecorator); ok { - protoMod.additionalCrates = append(protoMod.additionalCrates, dep.CrateName()) + if rustInfo.SourceProviderInfo.ProtobufDecoratorInfo != nil { + protoMod.additionalCrates = append(protoMod.additionalCrates, linkableInfo.CrateName) } } } @@ -1193,13 +1429,13 @@ func collectIncludedProtos(mod *Module, dep *Module) { func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { var depPaths PathDeps - directRlibDeps := []*Module{} - directDylibDeps := []*Module{} - directProcMacroDeps := []*Module{} + directRlibDeps := []*cc.LinkableInfo{} + directDylibDeps := []*cc.LinkableInfo{} + directProcMacroDeps := []*cc.LinkableInfo{} directSharedLibDeps := []cc.SharedLibraryInfo{} - directStaticLibDeps := [](cc.LinkableInterface){} - directSrcProvidersDeps := []*Module{} - directSrcDeps := [](android.SourceFileProducer){} + directStaticLibDeps := [](*cc.LinkableInfo){} + directSrcProvidersDeps := []*android.ModuleProxy{} + directSrcDeps := []android.SourceFilesInfo{} // For the dependency from platform to apex, use the latest stubs mod.apexSdkVersion = android.FutureApiLevel @@ -1217,12 +1453,14 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { skipModuleList := map[string]bool{} - var transitiveAndroidMkSharedLibs []*android.DepSet[string] + var transitiveAndroidMkSharedLibs []depset.DepSet[string] var directAndroidMkSharedLibs []string - ctx.VisitDirectDeps(func(dep android.Module) { + 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 } @@ -1231,45 +1469,88 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - if rustDep, ok := dep.(*Module); ok && !rustDep.Static() && !rustDep.Shared() { + rustInfo, hasRustInfo := android.OtherModuleProvider(ctx, dep, RustInfoProvider) + ccInfo, _ := android.OtherModuleProvider(ctx, dep, cc.CcInfoProvider) + linkableInfo, hasLinkableInfo := android.OtherModuleProvider(ctx, dep, cc.LinkableInfoProvider) + commonInfo := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey) + if hasRustInfo && !linkableInfo.Static && !linkableInfo.Shared { //Handle Rust Modules - makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName) + makeLibName := rustMakeLibName(rustInfo, linkableInfo, &commonInfo, depName+rustInfo.RustSubName) switch { case depTag == dylibDepTag: - dylib, ok := rustDep.compiler.(libraryInterface) - if !ok || !dylib.dylib() { + dylib := rustInfo.CompilerInfo.LibraryInfo + if dylib == nil || !dylib.Dylib { ctx.ModuleErrorf("mod %q not an dylib library", depName) return } - directDylibDeps = append(directDylibDeps, rustDep) + directDylibDeps = append(directDylibDeps, linkableInfo) mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName) mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName)) + depPaths.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, "")) + if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok { + depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps) + } + + if !rustInfo.CompilerInfo.NoStdlibs { + rustDepStdLinkage := rustInfo.CompilerInfo.StdLinkageForNonDevice + if ctx.Device() { + rustDepStdLinkage = rustInfo.CompilerInfo.StdLinkageForDevice + } + if rustDepStdLinkage != modStdLinkage { + ctx.ModuleErrorf("Rust dependency %q has the wrong StdLinkage; expected %#v, got %#v", depName, modStdLinkage, rustDepStdLinkage) + return + } + } + case depTag == rlibDepTag: - rlib, ok := rustDep.compiler.(libraryInterface) - if !ok || !rlib.rlib() { + rlib := rustInfo.CompilerInfo.LibraryInfo + if rlib == nil || !rlib.Rlib { ctx.ModuleErrorf("mod %q not an rlib library", makeLibName) return } - directRlibDeps = append(directRlibDeps, rustDep) + 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(rustDep.OutputFile().Path())) + depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path())) + + // rlibs are not installed, so don't add the output file to directImplementationDeps + if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok { + depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps) + } + + if !rustInfo.CompilerInfo.NoStdlibs { + rustDepStdLinkage := rustInfo.CompilerInfo.StdLinkageForNonDevice + if ctx.Device() { + rustDepStdLinkage = rustInfo.CompilerInfo.StdLinkageForDevice + } + if rustDepStdLinkage != modStdLinkage { + 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, rustDep) + 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(rustDep.OutputFile().Path())) + depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path())) case depTag == sourceDepTag: if _, ok := mod.sourceProvider.(*protobufDecorator); ok { - collectIncludedProtos(mod, rustDep) + collectIncludedProtos(mod, rustInfo, linkableInfo) } case cc.IsStaticDepTag(depTag): // Rust FFI rlibs should not be declared in a Rust modules @@ -1282,7 +1563,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } - transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustDep.transitiveAndroidMkSharedLibs) + 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 @@ -1294,26 +1575,30 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { helper = "device module defined?" } - if dep.Target().Os != ctx.Os() { + if commonInfo.Target.Os != ctx.Os() { ctx.ModuleErrorf("OS mismatch on dependency %q (%s)", dep.Name(), helper) return - } else if dep.Target().Arch.ArchType != ctx.Arch().ArchType { + } else if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType { ctx.ModuleErrorf("Arch mismatch on dependency %q (%s)", dep.Name(), helper) return } - directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep) + directSrcProvidersDeps = append(directSrcProvidersDeps, &dep) } - exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider) - //Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS + 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.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...) + 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...) } if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag { - linkFile := rustDep.UnstrippedOutputFile() + linkFile := linkableInfo.UnstrippedOutputFile linkDir := linkPathFromFilePath(linkFile) if lib, ok := mod.compiler.(exportedFlagsProducer); ok { lib.exportLinkDirs(linkDir) @@ -1322,27 +1607,27 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { if depTag == sourceDepTag { if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() { - if _, ok := rustDep.sourceProvider.(*protobufDecorator); ok { + if rustInfo.SourceProviderInfo.ProtobufDecoratorInfo != nil { exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) } } } - } else if ccDep, ok := dep.(cc.LinkableInterface); ok { + } else if hasLinkableInfo { //Handle C dependencies - makeLibName := cc.MakeLibName(ctx, mod, ccDep, depName) - if _, ok := ccDep.(*Module); !ok { - if ccDep.Module().Target().Os != ctx.Os() { + makeLibName := cc.MakeLibName(ccInfo, linkableInfo, &commonInfo, depName) + if !hasRustInfo { + if commonInfo.Target.Os != ctx.Os() { ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName) return } - if ccDep.Module().Target().Arch.ArchType != ctx.Arch().ArchType { + if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType { ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName) return } } - linkObject := ccDep.OutputFile() - if !linkObject.Valid() { + 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 { @@ -1351,7 +1636,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - linkPath := linkPathFromFilePath(linkObject.Path()) + linkPath := linkPathFromFilePath(ccLibPath.Path()) exportDep := false switch { @@ -1360,20 +1645,25 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // 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() { - // Binaries may sometimes need to link whole static libraries that don't start with 'lib'. // 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", linkObject.Path().String(), "-Wl,--no-whole-archive"}...) - } else if libName, ok := libNameFromFilePath(linkObject.Path()); ok { - depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName) + 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()) } } - // Add this to linkObjects to pass the library directly to the linker as well. This propagates - // to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant. - depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) + if cc.IsWholeStaticLib(depTag) { + // Add whole staticlibs to wholeStaticLibObjects to propagate to Rust all dependents. + depPaths.wholeStaticLibObjects = append(depPaths.wholeStaticLibObjects, ccLibPath.String()) + } else { + // Otherwise add to staticLibObjects, which only propagate through rlibs to their dependents. + depPaths.staticLibObjects = append(depPaths.staticLibObjects, ccLibPath.String()) + } + depPaths.linkDirs = append(depPaths.linkDirs, linkPath) exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) @@ -1381,7 +1671,15 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...) depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) - directStaticLibDeps = append(directStaticLibDeps, ccDep) + + if !mod.Rlib() { + // rlibs don't need to build the generated static library, so they don't need to track these. + depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...) + } else { + depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...) + } + + directStaticLibDeps = append(directStaticLibDeps, linkableInfo) // Record baseLibName for snapshots. mod.Properties.SnapshotStaticLibs = append(mod.Properties.SnapshotStaticLibs, cc.BaseLibName(depName)) @@ -1393,10 +1691,20 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // 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.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, "")) + if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok { + depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps) + } + } + } + // Re-get linkObject as ChooseStubOrImpl actually tells us which // object (either from stub or non-stub) to use. - linkObject = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary) - if !linkObject.Valid() { + 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 { @@ -1404,10 +1712,10 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } return } - linkPath = linkPathFromFilePath(linkObject.Path()) + linkPath = linkPathFromFilePath(ccLibPath.Path()) depPaths.linkDirs = append(depPaths.linkDirs, linkPath) - depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) + 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...) @@ -1426,15 +1734,15 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) mod.Properties.AndroidMkHeaderLibs = append(mod.Properties.AndroidMkHeaderLibs, makeLibName) case depTag == cc.CrtBeginDepTag: - depPaths.CrtBegin = append(depPaths.CrtBegin, linkObject.Path()) + depPaths.CrtBegin = append(depPaths.CrtBegin, ccLibPath.Path()) case depTag == cc.CrtEndDepTag: - depPaths.CrtEnd = append(depPaths.CrtEnd, linkObject.Path()) + depPaths.CrtEnd = append(depPaths.CrtEnd, ccLibPath.Path()) } - // Make sure these dependencies are propagated + // Make sure shared dependencies are propagated if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep { lib.exportLinkDirs(linkPath) - lib.exportLinkObjects(linkObject.String()) + lib.exportSharedLibs(ccLibPath.String()) } } else { switch { @@ -1445,7 +1753,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } - if srcDep, ok := dep.(android.SourceFileProducer); ok { + if srcDep, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoProvider); ok { if android.IsSourceDepTagWithOutputTag(depTag, "") { // These are usually genrules which don't have per-target variants. directSrcDeps = append(directSrcDeps, srcDep) @@ -1453,37 +1761,37 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } }) - mod.transitiveAndroidMkSharedLibs = android.NewDepSet[string](android.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs) + mod.transitiveAndroidMkSharedLibs = depset.New[string](depset.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs) var rlibDepFiles RustLibraries aliases := mod.compiler.Aliases() for _, dep := range directRlibDeps { - crateName := dep.CrateName() + crateName := dep.CrateName if alias, aliased := aliases[crateName]; aliased { crateName = alias } - rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName}) + rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName}) } var dylibDepFiles RustLibraries for _, dep := range directDylibDeps { - crateName := dep.CrateName() + crateName := dep.CrateName if alias, aliased := aliases[crateName]; aliased { crateName = alias } - dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName}) + dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName}) } var procMacroDepFiles RustLibraries for _, dep := range directProcMacroDeps { - crateName := dep.CrateName() + crateName := dep.CrateName if alias, aliased := aliases[crateName]; aliased { crateName = alias } - procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName}) + procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName}) } var staticLibDepFiles android.Paths for _, dep := range directStaticLibDeps { - staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile().Path()) + staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile.Path()) } var sharedLibFiles android.Paths @@ -1499,11 +1807,11 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { var srcProviderDepFiles android.Paths for _, dep := range directSrcProvidersDeps { - srcs := android.OutputFilesForModule(ctx, dep, "") + srcs := android.OutputFilesForModule(ctx, *dep, "") srcProviderDepFiles = append(srcProviderDepFiles, srcs...) } for _, dep := range directSrcDeps { - srcs := dep.Srcs() + srcs := dep.Srcs srcProviderDepFiles = append(srcProviderDepFiles, srcs...) } @@ -1517,11 +1825,17 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // Dedup exported flags from dependencies depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs) - depPaths.linkObjects = android.FirstUniqueStrings(depPaths.linkObjects) + 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.ccRlibDeps = android.FirstUniqueFunc(depPaths.ccRlibDeps, cc.EqRustRlibDeps) return depPaths } @@ -1572,7 +1886,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { } stdLinkage := "dylib-std" - if mod.compiler.stdLinkage(ctx) == RlibLinkage { + if mod.compiler.stdLinkage(ctx.Device()) == RlibLinkage { stdLinkage = "rlib-std" } @@ -1639,7 +1953,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { // stdlibs if deps.Stdlibs != nil { - if mod.compiler.stdLinkage(ctx) == RlibLinkage { + if mod.compiler.stdLinkage(ctx.Device()) == RlibLinkage { for _, lib := range deps.Stdlibs { actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...), rlibDepTag, lib) @@ -1757,7 +2071,7 @@ func (mod *Module) HostToolPath() 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 stubs are properly supported by rust_ffi targets. +// TODO(b/362509506): remove this once all apex_exclude usages are removed. func (m *Module) CanHaveApexVariants() bool { if m.ApexExclude() { return false @@ -1794,48 +2108,93 @@ func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVer } // Implements android.ApexModule -func (mod *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - depTag := ctx.OtherModuleDependencyTag(dep) - - if ccm, ok := dep.(*cc.Module); ok { - if ccm.HasStubsVariants() { - if cc.IsSharedDepTag(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 - } +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() +} - if cc.IsHeaderDepTag(depTag) { - return false - } - } - if mod.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 - } +// Implements android.ApexModule +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 rustDep, ok := dep.(*Module); ok && rustDep.ApexExclude() { + 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 && (lib.shared() || lib.dylib()) { - return true + if lib, ok := mod.compiler.(libraryInterface); ok { + return (lib.shared() || lib.dylib()) && !lib.BuildStubs() } if _, ok := mod.compiler.(*binaryDecorator); ok { return true |