diff options
Diffstat (limited to 'rust/library.go')
-rw-r--r-- | rust/library.go | 255 |
1 files changed, 242 insertions, 13 deletions
diff --git a/rust/library.go b/rust/library.go index 2d62dcfe4..415785a16 100644 --- a/rust/library.go +++ b/rust/library.go @@ -25,6 +25,7 @@ import ( "android/soong/android" "android/soong/cc" + cc_config "android/soong/cc/config" ) var ( @@ -79,9 +80,13 @@ type LibraryCompilerProperties struct { // Whether this library is part of the Rust toolchain sysroot. Sysroot *bool - // Exclude this rust_ffi target from being included in APEXes. - // TODO(b/362509506): remove this once stubs are properly supported by rust_ffi targets. + // Deprecated - exclude this rust_ffi target from being included in APEXes. + // TODO(b/362509506): remove this once all apex_exclude uses are switched to stubs. Apex_exclude *bool + + // Generate stubs to make this library accessible to APEXes. + // Can only be set for modules producing shared libraries. + Stubs cc.StubsProperties `android:"arch_variant"` } type LibraryMutatedProperties struct { @@ -109,6 +114,15 @@ type LibraryMutatedProperties struct { // Whether this library variant should be link libstd via rlibs VariantIsStaticStd bool `blueprint:"mutated"` + + // This variant is a stubs lib + BuildStubs bool `blueprint:"mutated"` + // This variant is the latest version + IsLatestVersion bool `blueprint:"mutated"` + // Version of the stubs lib + StubsVersion string `blueprint:"mutated"` + // List of all stubs versions associated with an implementation lib + AllStubsVersions []string `blueprint:"mutated"` } type libraryDecorator struct { @@ -123,9 +137,28 @@ type libraryDecorator struct { // table-of-contents file for cdylib crates to optimize out relinking when possible tocFile android.OptionalPath + + // Path to the file containing the APIs exported by this library + stubsSymbolFilePath android.Path + apiListCoverageXmlPath android.ModuleOutPath + versionScriptPath android.OptionalPath +} + +func (library *libraryDecorator) stubs() bool { + return library.MutatedProperties.BuildStubs +} + +func (library *libraryDecorator) setAPIListCoverageXMLPath(xml android.ModuleOutPath) { + library.apiListCoverageXmlPath = xml +} + +func (library *libraryDecorator) libraryProperties() LibraryCompilerProperties { + return library.Properties } type libraryInterface interface { + cc.VersionedInterface + rlib() bool dylib() bool static() bool @@ -161,9 +194,17 @@ type libraryInterface interface { BuildOnlyShared() toc() android.OptionalPath + + IsStubsImplementationRequired() bool + setAPIListCoverageXMLPath(out android.ModuleOutPath) + + libraryProperties() LibraryCompilerProperties } func (library *libraryDecorator) nativeCoverage() bool { + if library.BuildStubs() { + return false + } return true } @@ -276,7 +317,85 @@ func (library *libraryDecorator) stdLinkage(device bool) RustLinkage { var _ compiler = (*libraryDecorator)(nil) var _ libraryInterface = (*libraryDecorator)(nil) +var _ cc.VersionedInterface = (*libraryDecorator)(nil) var _ exportedFlagsProducer = (*libraryDecorator)(nil) +var _ cc.VersionedInterface = (*libraryDecorator)(nil) + +func (library *libraryDecorator) HasLLNDKStubs() bool { + // Rust LLNDK is currently unsupported + return false +} + +func (library *libraryDecorator) HasVendorPublicLibrary() bool { + // Rust does not support vendor_public_library yet. + return false +} + +func (library *libraryDecorator) HasLLNDKHeaders() bool { + // Rust LLNDK is currently unsupported + return false +} + +func (library *libraryDecorator) HasStubsVariants() bool { + // Just having stubs.symbol_file is enough to create a stub variant. In that case + // the stub for the future API level is created. + return library.Properties.Stubs.Symbol_file != nil || + len(library.Properties.Stubs.Versions) > 0 +} + +func (library *libraryDecorator) IsStubsImplementationRequired() bool { + return BoolDefault(library.Properties.Stubs.Implementation_installable, true) +} + +func (library *libraryDecorator) GetAPIListCoverageXMLPath() android.ModuleOutPath { + return library.apiListCoverageXmlPath +} + +func (library *libraryDecorator) AllStubsVersions() []string { + return library.MutatedProperties.AllStubsVersions +} + +func (library *libraryDecorator) SetAllStubsVersions(versions []string) { + library.MutatedProperties.AllStubsVersions = versions +} + +func (library *libraryDecorator) SetStubsVersion(version string) { + library.MutatedProperties.StubsVersion = version +} + +func (library *libraryDecorator) SetBuildStubs(isLatest bool) { + library.MutatedProperties.BuildStubs = true + library.MutatedProperties.IsLatestVersion = isLatest +} + +func (library *libraryDecorator) BuildStubs() bool { + return library.MutatedProperties.BuildStubs +} + +func (library *libraryDecorator) ImplementationModuleName(name string) string { + return name +} + +func (library *libraryDecorator) IsLLNDKMovedToApex() bool { + // Rust does not support LLNDK. + return false +} + +func (library *libraryDecorator) StubsVersion() string { + return library.MutatedProperties.StubsVersion +} + +// stubsVersions implements cc.VersionedInterface. +func (library *libraryDecorator) StubsVersions(ctx android.BaseModuleContext) []string { + if !library.HasStubsVariants() { + return nil + } + + // Future API level is implicitly added if there isn't + versions := cc.AddCurrentVersionIfNotPresent(library.Properties.Stubs.Versions) + cc.NormalizeVersions(ctx, versions) + return versions +} // rust_library produces all Rust variants (rust_library_dylib and // rust_library_rlib). @@ -355,6 +474,18 @@ func RustFFISharedHostFactory() android.Module { return module.Init() } +func CheckRustLibraryProperties(mctx android.DefaultableHookContext) { + lib := mctx.Module().(*Module).compiler.(libraryInterface) + if !lib.buildShared() { + if lib.libraryProperties().Stubs.Symbol_file != nil || + lib.libraryProperties().Stubs.Implementation_installable != nil || + len(lib.libraryProperties().Stubs.Versions) > 0 { + + mctx.PropertyErrorf("stubs", "stubs properties can only be set for rust_ffi or rust_ffi_shared modules") + } + } +} + func (library *libraryDecorator) BuildOnlyFFI() { library.MutatedProperties.BuildDylib = false // we build rlibs for later static ffi linkage. @@ -414,6 +545,7 @@ func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorat module.compiler = library + module.SetDefaultableHook(CheckRustLibraryProperties) return module, library } @@ -542,7 +674,10 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa flags.RustFlags = append(flags.RustFlags, deps.depFlags...) flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...) - flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...) + flags.LinkFlags = append(flags.LinkFlags, deps.rustLibObjects...) + flags.LinkFlags = append(flags.LinkFlags, deps.sharedLibObjects...) + flags.LinkFlags = append(flags.LinkFlags, deps.staticLibObjects...) + flags.LinkFlags = append(flags.LinkFlags, deps.wholeStaticLibObjects...) if String(library.Properties.Version_script) != "" { if String(library.Properties.Extra_exported_symbols) != "" { @@ -576,7 +711,11 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa } // Call the appropriate builder for this library type - if library.rlib() { + if library.stubs() { + ccFlags := library.getApiStubsCcFlags(ctx) + stubObjs := library.compileModuleLibApiStubs(ctx, ccFlags) + cc.BuildRustStubs(ctx, outputFile, stubObjs, ccFlags) + } else if library.rlib() { ret.kytheFile = TransformSrctoRlib(ctx, crateRootPath, deps, flags, outputFile).kytheFile } else if library.dylib() { ret.kytheFile = TransformSrctoDylib(ctx, crateRootPath, deps, flags, outputFile).kytheFile @@ -586,19 +725,36 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa ret.kytheFile = TransformSrctoShared(ctx, crateRootPath, deps, flags, outputFile).kytheFile } + // rlibs and dylibs propagate their shared, whole static, and rustlib dependencies if library.rlib() || library.dylib() { library.flagExporter.exportLinkDirs(deps.linkDirs...) - library.flagExporter.exportLinkObjects(deps.linkObjects...) + library.flagExporter.exportRustLibs(deps.rustLibObjects...) + library.flagExporter.exportSharedLibs(deps.sharedLibObjects...) + library.flagExporter.exportWholeStaticLibs(deps.wholeStaticLibObjects...) } + // rlibs also propagate their staticlibs dependencies + if library.rlib() { + library.flagExporter.exportStaticLibs(deps.staticLibObjects...) + } // Since we have FFI rlibs, we need to collect their includes as well - if library.static() || library.shared() || library.rlib() { - android.SetProvider(ctx, cc.FlagExporterInfoProvider, cc.FlagExporterInfo{ + if library.static() || library.shared() || library.rlib() || library.stubs() { + ccExporter := cc.FlagExporterInfo{ IncludeDirs: android.FirstUniquePaths(library.includeDirs), - }) + } + if library.rlib() { + ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedCcRlibDeps...) + ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedWholeCcRlibDeps...) + } + android.SetProvider(ctx, cc.FlagExporterInfoProvider, ccExporter) } - if library.shared() { + if library.dylib() { + // reexport whole-static'd dependencies for dylibs. + library.flagExporter.wholeRustRlibDeps = append(library.flagExporter.wholeRustRlibDeps, deps.reexportedWholeCcRlibDeps...) + } + + if library.shared() || library.stubs() { // Optimize out relinking against shared libraries whose interface hasn't changed by // depending on a table of contents file instead of the library itself. tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.SharedLibSuffix()[1:]+".toc") @@ -609,9 +765,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa TableOfContents: android.OptionalPathForPath(tocFile), SharedLibrary: outputFile, Target: ctx.Target(), - // TODO: when rust supports stubs uses the stubs state rather than inferring it from - // apex_exclude. - IsStubs: Bool(library.Properties.Apex_exclude), + IsStubs: library.BuildStubs(), }) } @@ -623,8 +777,10 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa TransitiveStaticLibrariesForOrdering: depSet, }) } + cc.AddStubDependencyProviders(ctx) - library.flagExporter.setProvider(ctx) + // Set our flagexporter provider to export relevant Rust flags + library.flagExporter.setRustProvider(ctx) return ret } @@ -642,6 +798,53 @@ func (library *libraryDecorator) checkedCrateRootPath() (android.Path, error) { } } +func (library *libraryDecorator) getApiStubsCcFlags(ctx ModuleContext) cc.Flags { + ccFlags := cc.Flags{} + toolchain := cc_config.FindToolchain(ctx.Os(), ctx.Arch()) + + platformSdkVersion := "" + if ctx.Device() { + platformSdkVersion = ctx.Config().PlatformSdkVersion().String() + } + minSdkVersion := cc.MinSdkVersion(ctx.RustModule(), cc.CtxIsForPlatform(ctx), ctx.Device(), platformSdkVersion) + + // Collect common CC compilation flags + ccFlags = cc.CommonLinkerFlags(ctx, ccFlags, true, toolchain, false) + ccFlags = cc.CommonLibraryLinkerFlags(ctx, ccFlags, toolchain, library.getStem(ctx)) + ccFlags = cc.AddStubLibraryCompilerFlags(ccFlags) + ccFlags = cc.AddTargetFlags(ctx, ccFlags, toolchain, minSdkVersion, false) + + return ccFlags +} + +func (library *libraryDecorator) compileModuleLibApiStubs(ctx ModuleContext, ccFlags cc.Flags) cc.Objects { + mod := ctx.RustModule() + + symbolFile := String(library.Properties.Stubs.Symbol_file) + library.stubsSymbolFilePath = android.PathForModuleSrc(ctx, symbolFile) + + apiParams := cc.ApiStubsParams{ + NotInPlatform: mod.NotInPlatform(), + IsNdk: mod.IsNdk(ctx.Config()), + BaseModuleName: mod.BaseModuleName(), + ModuleName: ctx.ModuleName(), + } + flag := cc.GetApiStubsFlags(apiParams) + + nativeAbiResult := cc.ParseNativeAbiDefinition(ctx, symbolFile, + android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag) + objs := cc.CompileStubLibrary(ctx, ccFlags, nativeAbiResult.StubSrc, mod.getSharedFlags()) + + library.versionScriptPath = android.OptionalPathForPath(nativeAbiResult.VersionScript) + + // Parse symbol file to get API list for coverage + if library.StubsVersion() == "current" && ctx.PrimaryArch() && !mod.InRecovery() && !mod.InProduct() && !mod.InVendor() { + library.apiListCoverageXmlPath = cc.ParseSymbolFileForAPICoverage(ctx, symbolFile) + } + + return objs +} + func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath { // rustdoc has builtin support for documenting config specific information @@ -679,6 +882,20 @@ func (library *libraryDecorator) SetDisabled() { library.MutatedProperties.VariantIsDisabled = true } +func (library *libraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) { + library.baseCompiler.moduleInfoJSON(ctx, moduleInfoJSON) + + if library.rlib() { + moduleInfoJSON.Class = []string{"RLIB_LIBRARIES"} + } else if library.dylib() { + moduleInfoJSON.Class = []string{"DYLIB_LIBRARIES"} + } else if library.static() { + moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"} + } else if library.shared() { + moduleInfoJSON.Class = []string{"SHARED_LIBRARIES"} + } +} + var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+") func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) { @@ -737,6 +954,9 @@ func (libraryTransitionMutator) Split(ctx android.BaseModuleContext) []string { } func (libraryTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + if ctx.DepTag() == android.PrebuiltDepTag { + return sourceVariation + } return "" } @@ -804,6 +1024,12 @@ func (libraryTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, varia }, sourceDepTag, ctx.ModuleName()) } + + if prebuilt, ok := m.compiler.(*prebuiltLibraryDecorator); ok { + if Bool(prebuilt.Properties.Force_use_prebuilt) && len(prebuilt.prebuiltSrcs()) > 0 { + m.Prebuilt().SetUsePrebuilt(true) + } + } } type libstdTransitionMutator struct{} @@ -821,6 +1047,9 @@ func (libstdTransitionMutator) Split(ctx android.BaseModuleContext) []string { } func (libstdTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + if ctx.DepTag() == android.PrebuiltDepTag { + return sourceVariation + } return "" } |