diff options
Diffstat (limited to 'rust/rust.go')
-rw-r--r-- | rust/rust.go | 446 |
1 files changed, 362 insertions, 84 deletions
diff --git a/rust/rust.go b/rust/rust.go index ba6e29383..4eebda301 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -49,6 +49,7 @@ type CompilerInfo struct { type ProtobufDecoratorInfo struct{} type SourceProviderInfo struct { + Srcs android.Paths ProtobufDecoratorInfo *ProtobufDecoratorInfo } @@ -162,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"` @@ -209,6 +237,9 @@ type Module struct { apexSdkVersion android.ApiLevel transitiveAndroidMkSharedLibs depset.DepSet[string] + + // Shared flags among stubs build rules of this module + sharedFlags cc.SharedFlags } func (mod *Module) Header() bool { @@ -374,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 { @@ -383,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 } @@ -395,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 { @@ -462,10 +495,18 @@ type PathDeps struct { 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 - 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. @@ -498,7 +539,10 @@ type RustLibrary struct { type exportedFlagsProducer interface { exportLinkDirs(...string) - exportLinkObjects(...string) + exportRustLibs(...string) + exportStaticLibs(...string) + exportWholeStaticLibs(...string) + exportSharedLibs(...string) } type xref interface { @@ -506,23 +550,43 @@ type xref interface { } type flagExporter struct { - linkDirs []string - ccLinkDirs []string - linkObjects []string + linkDirs []string + ccLinkDirs []string + rustLibPaths []string + staticLibObjects []string + sharedLibObjects []string + wholeStaticLibObjects []string + wholeRustRlibDeps []cc.RustRlibDep } 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) exportSharedLibs(flags ...string) { + flagExporter.sharedLibObjects = android.FirstUniqueStrings(append(flagExporter.sharedLibObjects, flags...)) } -func (flagExporter *flagExporter) setProvider(ctx ModuleContext) { - android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{ - LinkDirs: flagExporter.linkDirs, - LinkObjects: flagExporter.linkObjects, +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, + WholeRustRlibDeps: flagExporter.wholeRustRlibDeps, }) } @@ -532,13 +596,17 @@ 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 + WholeRustRlibDeps []cc.RustRlibDep } -var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]() +var RustFlagExporterInfoProvider = blueprint.NewProvider[RustFlagExporterInfo]() func (mod *Module) isCoverageVariant() bool { return mod.coverage.Properties.IsCoverageVariant @@ -561,6 +629,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 @@ -743,11 +814,51 @@ 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) IsStubs() bool { +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 { + // Rust does not currently provide any crt modules. return false } @@ -771,6 +882,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) @@ -881,6 +993,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. @@ -970,9 +1101,9 @@ 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()...) } @@ -1025,11 +1156,15 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { ctx.Phony("rust", ctx.RustModule().OutputFile().Path()) } - linkableInfo := cc.CreateCommonLinkableInfo(mod) + 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{ @@ -1056,17 +1191,39 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { } } if mod.sourceProvider != nil { + rustInfo.SourceProviderInfo = &SourceProviderInfo{ + Srcs: mod.sourceProvider.Srcs(), + } if _, ok := mod.sourceProvider.(*protobufDecorator); ok { - rustInfo.SourceProviderInfo = &SourceProviderInfo{ - ProtobufDecoratorInfo: &ProtobufDecoratorInfo{}, - } + 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) { @@ -1089,12 +1246,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()) } @@ -1112,7 +1269,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()) @@ -1225,6 +1382,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 { @@ -1243,7 +1415,7 @@ func rustMakeLibName(rustInfo *RustInfo, linkableInfo *cc.LinkableInfo, commonIn if rustInfo != nil { // Use base module name for snapshots when exporting to Makefile. if rustInfo.SnapshotInfo != nil { - baseName := linkableInfo.BaseModuleName + baseName := commonInfo.BaseModuleName return baseName + rustInfo.SnapshotInfo.SnapshotAndroidMkSuffix + rustInfo.AndroidMkSuffix } } @@ -1367,6 +1539,13 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } + 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) @@ -1410,12 +1589,21 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { directSrcProvidersDeps = append(directSrcProvidersDeps, &dep) } - exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider) - //Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS + 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.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...) + + depPaths.reexportedWholeCcRlibDeps = append(depPaths.reexportedWholeCcRlibDeps, exportedRustInfo.WholeRustRlibDeps...) + if !mod.Rlib() { + depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedRustInfo.WholeRustRlibDeps...) + } } if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag { @@ -1447,8 +1635,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } } - linkObject := linkableInfo.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 { @@ -1457,7 +1645,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - linkPath := linkPathFromFilePath(linkObject.Path()) + linkPath := linkPathFromFilePath(ccLibPath.Path()) exportDep := false switch { @@ -1466,27 +1654,47 @@ 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()) - depPaths.linkDirs = append(depPaths.linkDirs, linkPath) - 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.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. @@ -1500,16 +1708,19 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { sharedLibraryInfo, exportedInfo := cc.ChooseStubOrImpl(ctx, dep) if !sharedLibraryInfo.IsStubs { - 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) + // 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 { @@ -1517,10 +1728,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...) @@ -1539,15 +1750,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 { @@ -1558,7 +1769,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } - if srcDep, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoKey); 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) @@ -1630,11 +1841,18 @@ 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.reexportedWholeCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedWholeCcRlibDeps, cc.EqRustRlibDeps) + depPaths.ccRlibDeps = android.FirstUniqueFunc(depPaths.ccRlibDeps, cc.EqRustRlibDeps) return depPaths } @@ -1870,7 +2088,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 @@ -1884,53 +2102,113 @@ func (mod *Module) MinSdkVersion() string { } // Implements android.ApexModule -func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { +func (mod *Module) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { minSdkVersion := mod.MinSdkVersion() if minSdkVersion == "apex_inherit" { - return nil + return android.MinApiLevel } + if minSdkVersion == "" { - return fmt.Errorf("min_sdk_version is not specificed") + return android.NoneApiLevel } - // Not using nativeApiLevelFromUser because the context here is not // necessarily a native context. - ver, err := android.ApiLevelFromUser(ctx, minSdkVersion) + ver, err := android.ApiLevelFromUserWithConfig(ctx.Config(), minSdkVersion) if err != nil { - return err + return android.NoneApiLevel } - if ver.GreaterThan(sdkVersion) { - return fmt.Errorf("newer SDK(%v)", ver) - } - return nil + 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 -func (mod *Module) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool { +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 mod.Static() && cc.IsSharedDepTag(depTag) { + 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 (mod *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool { - return !mod.ApexExclude() +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 |