diff options
Diffstat (limited to 'rust/library.go')
| -rw-r--r-- | rust/library.go | 314 |
1 files changed, 158 insertions, 156 deletions
diff --git a/rust/library.go b/rust/library.go index a3a567281..ba73f27fd 100644 --- a/rust/library.go +++ b/rust/library.go @@ -15,18 +15,17 @@ package rust import ( + "errors" "fmt" "regexp" "strings" "android/soong/android" "android/soong/cc" - "android/soong/snapshot" ) var ( - DylibStdlibSuffix = ".dylib-std" - RlibStdlibSuffix = ".rlib-std" + RlibStdlibSuffix = ".rlib-std" ) func init() { @@ -38,10 +37,15 @@ func init() { android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory) android.RegisterModuleType("rust_ffi", RustFFIFactory) android.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory) - android.RegisterModuleType("rust_ffi_static", RustFFIStaticFactory) + android.RegisterModuleType("rust_ffi_rlib", RustFFIRlibFactory) android.RegisterModuleType("rust_ffi_host", RustFFIHostFactory) android.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory) - android.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory) + android.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory) + + // TODO: Remove when all instances of rust_ffi_static have been switched to rust_ffi_rlib + // Alias rust_ffi_static to the rust_ffi_rlib factory + android.RegisterModuleType("rust_ffi_static", RustFFIRlibFactory) + android.RegisterModuleType("rust_ffi_host_static", RustFFIRlibHostFactory) } type VariantLibraryProperties struct { @@ -55,9 +59,13 @@ type LibraryCompilerProperties struct { Shared VariantLibraryProperties `android:"arch_variant"` Static VariantLibraryProperties `android:"arch_variant"` - // path to include directories to pass to cc_* modules, only relevant for static/shared variants. + // TODO: Remove this when all instances of Include_dirs have been removed from rust_ffi modules. + // path to include directories to pass to cc_* modules, only relevant for static/shared variants (deprecated, use export_include_dirs instead). Include_dirs []string `android:"path,arch_variant"` + // path to include directories to export to cc_* modules, only relevant for static/shared variants. + Export_include_dirs []string `android:"path,arch_variant"` + // Whether this library is part of the Rust toolchain sysroot. Sysroot *bool } @@ -78,8 +86,6 @@ type LibraryMutatedProperties struct { VariantIsRlib bool `blueprint:"mutated"` // This variant is a shared library VariantIsShared bool `blueprint:"mutated"` - // This variant is a static library - VariantIsStatic bool `blueprint:"mutated"` // This variant is a source provider VariantIsSource bool `blueprint:"mutated"` @@ -101,7 +107,7 @@ type libraryDecorator struct { includeDirs android.Paths sourceProvider SourceProvider - collectedSnapshotHeaders android.Paths + isFFI bool // table-of-contents file for cdylib crates to optimize out relinking when possible tocFile android.OptionalPath @@ -142,6 +148,8 @@ type libraryInterface interface { BuildOnlyShared() toc() android.OptionalPath + + isFFILibrary() bool } func (library *libraryDecorator) nativeCoverage() bool { @@ -169,7 +177,7 @@ func (library *libraryDecorator) shared() bool { } func (library *libraryDecorator) static() bool { - return library.MutatedProperties.VariantIsStatic + return false } func (library *libraryDecorator) source() bool { @@ -195,14 +203,12 @@ func (library *libraryDecorator) buildStatic() bool { func (library *libraryDecorator) setRlib() { library.MutatedProperties.VariantIsRlib = true library.MutatedProperties.VariantIsDylib = false - library.MutatedProperties.VariantIsStatic = false library.MutatedProperties.VariantIsShared = false } func (library *libraryDecorator) setDylib() { library.MutatedProperties.VariantIsRlib = false library.MutatedProperties.VariantIsDylib = true - library.MutatedProperties.VariantIsStatic = false library.MutatedProperties.VariantIsShared = false } @@ -219,17 +225,13 @@ func (library *libraryDecorator) setDylibStd() { } func (library *libraryDecorator) setShared() { - library.MutatedProperties.VariantIsStatic = false library.MutatedProperties.VariantIsShared = true library.MutatedProperties.VariantIsRlib = false library.MutatedProperties.VariantIsDylib = false } func (library *libraryDecorator) setStatic() { - library.MutatedProperties.VariantIsStatic = true - library.MutatedProperties.VariantIsShared = false - library.MutatedProperties.VariantIsRlib = false - library.MutatedProperties.VariantIsDylib = false + panic(fmt.Errorf("static variant is not supported for rust modules, use the rlib variant instead")) } func (library *libraryDecorator) setSource() { @@ -237,10 +239,7 @@ func (library *libraryDecorator) setSource() { } func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep { - if ctx.Module().(*Module).InVendor() { - // Vendor modules should statically link libstd. - return rlibAutoDep - } else if library.preferRlib() { + if library.preferRlib() { return rlibAutoDep } else if library.rlib() || library.static() { return rlibAutoDep @@ -252,10 +251,7 @@ func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) aut } func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage { - if ctx.RustModule().InVendor() { - // Vendor modules should statically link libstd. - return RlibLinkage - } else if library.static() || library.MutatedProperties.VariantIsStaticStd { + if library.static() || library.MutatedProperties.VariantIsStaticStd || (library.rlib() && library.isFFILibrary()) { return RlibLinkage } else if library.baseCompiler.preferRlib() { return RlibLinkage @@ -275,8 +271,8 @@ func RustLibraryFactory() android.Module { return module.Init() } -// rust_ffi produces all FFI variants (rust_ffi_shared and -// rust_ffi_static). +// rust_ffi produces all FFI variants (rust_ffi_shared, rust_ffi_static, and +// rust_ffi_rlib). func RustFFIFactory() android.Module { module, library := NewRustLibrary(android.HostAndDeviceSupported) library.BuildOnlyFFI() @@ -305,14 +301,6 @@ func RustFFISharedFactory() android.Module { return module.Init() } -// rust_ffi_static produces a static library (Rust crate type -// "staticlib"). -func RustFFIStaticFactory() android.Module { - module, library := NewRustLibrary(android.HostAndDeviceSupported) - library.BuildOnlyStatic() - return module.Init() -} - // rust_library_host produces all Rust variants for the host // (rust_library_dylib_host and rust_library_rlib_host). func RustLibraryHostFactory() android.Module { @@ -322,7 +310,7 @@ func RustLibraryHostFactory() android.Module { } // rust_ffi_host produces all FFI variants for the host -// (rust_ffi_static_host and rust_ffi_shared_host). +// (rust_ffi_rlib_host, rust_ffi_static_host, and rust_ffi_shared_host). func RustFFIHostFactory() android.Module { module, library := NewRustLibrary(android.HostSupported) library.BuildOnlyFFI() @@ -345,14 +333,6 @@ func RustLibraryRlibHostFactory() android.Module { return module.Init() } -// rust_ffi_static_host produces a static library for the host (Rust -// crate type "staticlib"). -func RustFFIStaticHostFactory() android.Module { - module, library := NewRustLibrary(android.HostSupported) - library.BuildOnlyStatic() - return module.Init() -} - // rust_ffi_shared_host produces an shared library for the host (Rust // crate type "cdylib"). func RustFFISharedHostFactory() android.Module { @@ -361,11 +341,33 @@ func RustFFISharedHostFactory() android.Module { return module.Init() } +// rust_ffi_rlib_host produces an rlib for the host (Rust crate +// type "rlib"). +func RustFFIRlibHostFactory() android.Module { + module, library := NewRustLibrary(android.HostSupported) + library.BuildOnlyRlib() + + library.isFFI = true + return module.Init() +} + +// rust_ffi_rlib produces an rlib (Rust crate type "rlib"). +func RustFFIRlibFactory() android.Module { + module, library := NewRustLibrary(android.HostAndDeviceSupported) + library.BuildOnlyRlib() + + library.isFFI = true + return module.Init() +} + func (library *libraryDecorator) BuildOnlyFFI() { library.MutatedProperties.BuildDylib = false - library.MutatedProperties.BuildRlib = false + // we build rlibs for later static ffi linkage. + library.MutatedProperties.BuildRlib = true library.MutatedProperties.BuildShared = true - library.MutatedProperties.BuildStatic = true + library.MutatedProperties.BuildStatic = false + + library.isFFI = true } func (library *libraryDecorator) BuildOnlyRust() { @@ -394,6 +396,8 @@ func (library *libraryDecorator) BuildOnlyStatic() { library.MutatedProperties.BuildDylib = false library.MutatedProperties.BuildShared = false library.MutatedProperties.BuildStatic = true + + library.isFFI = true } func (library *libraryDecorator) BuildOnlyShared() { @@ -401,6 +405,12 @@ func (library *libraryDecorator) BuildOnlyShared() { library.MutatedProperties.BuildDylib = false library.MutatedProperties.BuildStatic = false library.MutatedProperties.BuildShared = true + + library.isFFI = true +} + +func (library *libraryDecorator) isFFILibrary() bool { + return library.isFFI } func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { @@ -451,17 +461,35 @@ func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string { return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix() } +// Library cfg flags common to all variants +func CommonLibraryCfgFlags(ctx android.ModuleContext, flags Flags) Flags { + return flags +} + func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags { flags = library.baseCompiler.cfgFlags(ctx, flags) + flags = CommonLibraryCfgFlags(ctx, flags) + + cfgs := library.baseCompiler.Properties.Cfgs.GetOrDefault(ctx, nil) + if library.dylib() { // We need to add a dependency on std in order to link crates as dylibs. // The hack to add this dependency is guarded by the following cfg so // that we don't force a dependency when it isn't needed. - library.baseCompiler.Properties.Cfgs = append(library.baseCompiler.Properties.Cfgs, "android_dylib") + cfgs = append(cfgs, "android_dylib") } - flags.RustFlags = append(flags.RustFlags, library.baseCompiler.cfgsToFlags()...) - flags.RustdocFlags = append(flags.RustdocFlags, library.baseCompiler.cfgsToFlags()...) + cfgFlags := cfgsToFlags(cfgs) + + flags.RustFlags = append(flags.RustFlags, cfgFlags...) + flags.RustdocFlags = append(flags.RustdocFlags, cfgFlags...) + + return flags +} + +// Common flags applied to all libraries irrespective of properties or variant should be included here +func CommonLibraryCompilerFlags(ctx android.ModuleContext, flags Flags) Flags { + flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName()) return flags } @@ -469,12 +497,23 @@ func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { flags = library.baseCompiler.compilerFlags(ctx, flags) - flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName()) - if library.shared() || library.static() { + flags = CommonLibraryCompilerFlags(ctx, flags) + + if library.isFFI { library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...) + library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Export_include_dirs)...) } + if library.shared() { - flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx)) + if ctx.Darwin() { + flags.LinkFlags = append( + flags.LinkFlags, + "-dynamic_lib", + "-install_name @rpath/"+library.sharedLibFilename(ctx), + ) + } else { + flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx)) + } } return flags @@ -484,12 +523,15 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa var outputFile android.ModuleOutPath var ret buildOutput var fileName string - srcPath := library.srcPath(ctx, deps) + crateRootPath := crateRootPath(ctx, library) if library.sourceProvider != nil { deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...) } + // Ensure link dirs are not duplicated + deps.linkDirs = android.FirstUniqueStrings(deps.linkDirs) + // Calculate output filename if library.rlib() { fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix() @@ -520,7 +562,7 @@ 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.Strings()...) + flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...) if library.dylib() { // We need prefer-dynamic for now to avoid linking in the static stdlib. See: @@ -531,24 +573,24 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa // Call the appropriate builder for this library type if library.rlib() { - ret.kytheFile = TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoRlib(ctx, crateRootPath, deps, flags, outputFile).kytheFile } else if library.dylib() { - ret.kytheFile = TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoDylib(ctx, crateRootPath, deps, flags, outputFile).kytheFile } else if library.static() { - ret.kytheFile = TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoStatic(ctx, crateRootPath, deps, flags, outputFile).kytheFile } else if library.shared() { - ret.kytheFile = TransformSrctoShared(ctx, srcPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoShared(ctx, crateRootPath, deps, flags, outputFile).kytheFile } if library.rlib() || library.dylib() { library.flagExporter.exportLinkDirs(deps.linkDirs...) library.flagExporter.exportLinkObjects(deps.linkObjects...) - library.flagExporter.exportLibDeps(deps.LibDeps...) } - if library.static() || library.shared() { - ctx.SetProvider(cc.FlagExporterInfoProvider, cc.FlagExporterInfo{ - IncludeDirs: library.includeDirs, + // 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{ + IncludeDirs: android.FirstUniquePaths(library.includeDirs), }) } @@ -559,7 +601,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa library.tocFile = android.OptionalPathForPath(tocFile) cc.TransformSharedObjectToToc(ctx, outputFile, tocFile) - ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{ + android.SetProvider(ctx, cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{ TableOfContents: android.OptionalPathForPath(tocFile), SharedLibrary: outputFile, Target: ctx.Target(), @@ -567,8 +609,8 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa } if library.static() { - depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build() - ctx.SetProvider(cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{ + depSet := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(outputFile).Build() + android.SetProvider(ctx, cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{ StaticLibrary: outputFile, TransitiveStaticLibrariesForOrdering: depSet, @@ -580,13 +622,16 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa return ret } -func (library *libraryDecorator) srcPath(ctx ModuleContext, _ PathDeps) android.Path { +func (library *libraryDecorator) checkedCrateRootPath() (android.Path, error) { if library.sourceProvider != nil { + srcs := library.sourceProvider.Srcs() + if len(srcs) == 0 { + return nil, errors.New("Source provider generated 0 sources") + } // Assume the first source from the source provider is the library entry point. - return library.sourceProvider.Srcs()[0] + return srcs[0], nil } else { - path, _ := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs) - return path + return library.baseCompiler.checkedCrateRootPath() } } @@ -601,7 +646,7 @@ func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags, return android.OptionalPath{} } - return android.OptionalPathForPath(Rustdoc(ctx, library.srcPath(ctx, deps), + return android.OptionalPathForPath(Rustdoc(ctx, crateRootPath(ctx, library), deps, flags)) } @@ -660,6 +705,11 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) { return } + // Don't produce rlib/dylib/source variants for shared or static variants + if library.shared() || library.static() { + return + } + var variants []string // The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib) // depend on this variant. It must be the first variant to be declared. @@ -682,10 +732,13 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) { // The order of the variations (modules) matches the variant names provided. Iterate // through the new variation modules and set their mutated properties. + var emptyVariant = false + var rlibVariant = false for i, v := range modules { switch variants[i] { case rlibVariation: v.(*Module).compiler.(libraryInterface).setRlib() + rlibVariant = true case dylibVariation: v.(*Module).compiler.(libraryInterface).setDylib() if v.(*Module).ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { @@ -694,38 +747,31 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) { v.(*Module).Disable() } - variation := v.(*Module).ModuleBase.ImageVariation().Variation - if strings.HasPrefix(variation, cc.VendorVariationPrefix) { - // TODO(b/204303985) - // Disable vendor dylibs until they are supported - v.(*Module).Disable() - } - - if strings.HasPrefix(variation, cc.VendorVariationPrefix) && - m.HasVendorVariant() && - !snapshot.IsVendorProprietaryModule(mctx) && - strings.TrimPrefix(variation, cc.VendorVariationPrefix) == mctx.DeviceConfig().VndkVersion() { - - // cc.MutateImage runs before LibraryMutator, so vendor variations which are meant for rlibs only are - // produced for Dylibs; however, dylibs should not be enabled for boardVndkVersion for - // non-vendor proprietary modules. - v.(*Module).Disable() - } - case "source": v.(*Module).compiler.(libraryInterface).setSource() // The source variant does not produce any library. // Disable the compilation steps. v.(*Module).compiler.SetDisabled() + case "": + emptyVariant = true } } + if rlibVariant && library.isFFILibrary() { + // If an rlib variant is set and this is an FFI library, make it the + // default variant so CC can link against it appropriately. + mctx.AliasVariation(rlibVariation) + } else if emptyVariant { + // If there's an empty variant, alias it so it is the default variant + mctx.AliasVariation("") + } + // If a source variant is created, add an inter-variant dependency // between the other variants and the source variant. if sourceVariant { sv := modules[0] for _, v := range modules[1:] { - if !v.Enabled() { + if !v.Enabled(mctx) { continue } mctx.AddInterVariantDependency(sourceDepTag, v, sv) @@ -741,75 +787,31 @@ func LibstdMutator(mctx android.BottomUpMutatorContext) { case libraryInterface: // Only create a variant if a library is actually being built. if library.rlib() && !library.sysroot() { - variants := []string{"rlib-std", "dylib-std"} - modules := mctx.CreateLocalVariations(variants...) - - rlib := modules[0].(*Module) - dylib := modules[1].(*Module) - rlib.compiler.(libraryInterface).setRlibStd() - dylib.compiler.(libraryInterface).setDylibStd() - if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation || - strings.HasPrefix(dylib.ModuleBase.ImageVariation().Variation, cc.VendorVariationPrefix) { - // TODO(b/165791368) - // Disable rlibs that link against dylib-std on vendor and vendor ramdisk variations until those dylib - // variants are properly supported. - dylib.Disable() + // If this is a rust_ffi variant it only needs rlib-std + if library.isFFILibrary() { + variants := []string{"rlib-std"} + modules := mctx.CreateLocalVariations(variants...) + rlib := modules[0].(*Module) + rlib.compiler.(libraryInterface).setRlibStd() + rlib.Properties.RustSubName += RlibStdlibSuffix + mctx.AliasVariation("rlib-std") + } else { + variants := []string{"rlib-std", "dylib-std"} + modules := mctx.CreateLocalVariations(variants...) + + rlib := modules[0].(*Module) + dylib := modules[1].(*Module) + rlib.compiler.(libraryInterface).setRlibStd() + dylib.compiler.(libraryInterface).setDylibStd() + if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { + // TODO(b/165791368) + // Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib + // variants are properly supported. + dylib.Disable() + } + rlib.Properties.RustSubName += RlibStdlibSuffix } - rlib.Properties.RustSubName += RlibStdlibSuffix - dylib.Properties.RustSubName += DylibStdlibSuffix } } } } - -func (l *libraryDecorator) snapshotHeaders() android.Paths { - if l.collectedSnapshotHeaders == nil { - panic("snapshotHeaders() must be called after collectHeadersForSnapshot()") - } - return l.collectedSnapshotHeaders -} - -// collectHeadersForSnapshot collects all exported headers from library. -// It globs header files in the source tree for exported include directories, -// and tracks generated header files separately. -// -// This is to be called from GenerateAndroidBuildActions, and then collected -// header files can be retrieved by snapshotHeaders(). -func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext, deps PathDeps) { - ret := android.Paths{} - - // Glob together the headers from the modules include_dirs property - for _, path := range android.CopyOfPaths(l.includeDirs) { - dir := path.String() - globDir := dir + "/**/*" - glob, err := ctx.GlobWithDeps(globDir, nil) - if err != nil { - ctx.ModuleErrorf("glob of %q failed: %s", globDir, err) - return - } - - for _, header := range glob { - // Filter out only the files with extensions that are headers. - found := false - for _, ext := range cc.HeaderExts { - if strings.HasSuffix(header, ext) { - found = true - break - } - } - if !found { - continue - } - ret = append(ret, android.PathForSource(ctx, header)) - } - } - - // Glob together the headers from C dependencies as well, starting with non-generated headers. - ret = append(ret, cc.GlobHeadersForSnapshot(ctx, append(android.CopyOfPaths(deps.depIncludePaths), deps.depSystemIncludePaths...))...) - - // Collect generated headers from C dependencies. - ret = append(ret, cc.GlobGeneratedHeadersForSnapshot(ctx, deps.depGeneratedHeaders)...) - - // TODO(185577950): If support for generated headers is added, they need to be collected here as well. - l.collectedSnapshotHeaders = ret -} |