diff options
author | 2024-10-30 18:15:59 +0000 | |
---|---|---|
committer | 2025-01-10 21:47:09 +0000 | |
commit | a8a1fa1096240ee059c30cad9828ea0f9d0c161d (patch) | |
tree | b1b0c415516720e5df8cd87eaff6aa97801eee02 /rust/rust.go | |
parent | 9587f45b194ad3f1a4676a7f5d24acce03efc204 (diff) |
rust: Add stub support for rust_ffi modules
This adds stubs support for rust_ffi and rust_ffi_shared modules. Usage
should match current cc usage. The stubs generator leveraged is the cc
stubs generator.
Bug: 203478530
Test: m blueprint_tests
Change-Id: I043b9714a357cd5fe17c183ccdf86900f5172e0e
Diffstat (limited to 'rust/rust.go')
-rw-r--r-- | rust/rust.go | 164 |
1 files changed, 144 insertions, 20 deletions
diff --git a/rust/rust.go b/rust/rust.go index 2332b52ec..557bdc31d 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -162,9 +162,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 +236,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 +404,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 +414,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,31 +428,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) 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 { @@ -743,19 +779,42 @@ 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 { - panic(fmt.Errorf("ApexSdkVersion called on unsupported Rust module: %q", mod.BaseModuleName())) + 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 { - return mod.Name() + name := mod.BaseModuleName() + if versioned, ok := mod.compiler.(cc.VersionedInterface); ok { + name = versioned.ImplementationModuleName(name) + } + return name } func (mod *Module) Multilib() string { @@ -903,7 +962,7 @@ func (mod *Module) SetStl(s string) { } func (mod *Module) SetSdkVersion(s string) { - panic(fmt.Errorf("SetSdkVersion called on unsupported Rust module: %q", mod.BaseModuleName())) + mod.Properties.Sdk_version = StringPtr(s) } func (mod *Module) SetMinSdkVersion(s string) { @@ -1066,6 +1125,10 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { 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{ @@ -1108,10 +1171,9 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { // does compilation and linking in one step. If this changes in the future, // move this as appropriate. ccInfo.LinkerInfo = &cc.LinkerInfo{ - WholeStaticLibs: mod.compiler.baseCompilerProps().Whole_static_libs, - StaticLibs: mod.compiler.baseCompilerProps().Static_libs, - SharedLibs: mod.compiler.baseCompilerProps().Shared_libs, - UnstrippedOutputFile: mod.UnstrippedOutputFile(), + WholeStaticLibs: mod.compiler.baseCompilerProps().Whole_static_libs, + StaticLibs: mod.compiler.baseCompilerProps().Static_libs, + SharedLibs: mod.compiler.baseCompilerProps().Shared_libs, } android.SetProvider(ctx, cc.CcInfoProvider, ccInfo) @@ -1277,6 +1339,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 { @@ -1552,9 +1629,12 @@ 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) + } } } @@ -1922,7 +2002,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 @@ -1959,6 +2039,13 @@ func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVer } // 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 { if depTag == procMacroDepTag || depTag == customBindgenDepTag { return false @@ -1971,18 +2058,55 @@ func (mod *Module) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool 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 mod.ApexExclude() { + return false + } + return true } func (mod *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool { - return !mod.ApexExclude() + // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs. + if mod.ApexExclude() { + return false + } + + if mod.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 + } + 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 |