8d10fc39af
Rust installed files reside in "$MODULE_OUT/stripped/" when they are stripped, otherwise they reside in "$MODULE_OUT". However, other parts of Soong assume that installed files are always in $MODULE_OUT (cc_modules place *unstripped* files in $MODULE_OUT/unstripped). This notably causes problems when adding Rust modules as test data in AndroidMkDataPaths. When Rust modules are parsed by AndroidMkDataPaths, if they are stripped then they incorrectly get installed as test data with the path: <install_root>/<relative_install_path>/stripped/file. This CL refactors how we handle Rust stripped output such that the installed file always resides in $MODULE_OUT. Bug: 171710847 Test: Installed files now always reside in $MODULE_OUT Change-Id: I53a6ff57a0a5a55cd95ea78ae592ce22abfa20c9
794 lines
26 KiB
Go
794 lines
26 KiB
Go
// Copyright 2019 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package rust
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"android/soong/android"
|
|
"android/soong/cc"
|
|
"android/soong/snapshot"
|
|
)
|
|
|
|
var (
|
|
DylibStdlibSuffix = ".dylib-std"
|
|
RlibStdlibSuffix = ".rlib-std"
|
|
)
|
|
|
|
func init() {
|
|
android.RegisterModuleType("rust_library", RustLibraryFactory)
|
|
android.RegisterModuleType("rust_library_dylib", RustLibraryDylibFactory)
|
|
android.RegisterModuleType("rust_library_rlib", RustLibraryRlibFactory)
|
|
android.RegisterModuleType("rust_library_host", RustLibraryHostFactory)
|
|
android.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory)
|
|
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_host", RustFFIHostFactory)
|
|
android.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
|
|
android.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
|
|
}
|
|
|
|
type VariantLibraryProperties struct {
|
|
Enabled *bool `android:"arch_variant"`
|
|
Srcs []string `android:"path,arch_variant"`
|
|
}
|
|
|
|
type LibraryCompilerProperties struct {
|
|
Rlib VariantLibraryProperties `android:"arch_variant"`
|
|
Dylib VariantLibraryProperties `android:"arch_variant"`
|
|
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.
|
|
Include_dirs []string `android:"path,arch_variant"`
|
|
|
|
// Whether this library is part of the Rust toolchain sysroot.
|
|
Sysroot *bool
|
|
}
|
|
|
|
type LibraryMutatedProperties struct {
|
|
// Build a dylib variant
|
|
BuildDylib bool `blueprint:"mutated"`
|
|
// Build an rlib variant
|
|
BuildRlib bool `blueprint:"mutated"`
|
|
// Build a shared library variant
|
|
BuildShared bool `blueprint:"mutated"`
|
|
// Build a static library variant
|
|
BuildStatic bool `blueprint:"mutated"`
|
|
|
|
// This variant is a dylib
|
|
VariantIsDylib bool `blueprint:"mutated"`
|
|
// This variant is an rlib
|
|
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"`
|
|
|
|
// This variant is disabled and should not be compiled
|
|
// (used for SourceProvider variants that produce only source)
|
|
VariantIsDisabled bool `blueprint:"mutated"`
|
|
|
|
// Whether this library variant should be link libstd via rlibs
|
|
VariantIsStaticStd bool `blueprint:"mutated"`
|
|
}
|
|
|
|
type libraryDecorator struct {
|
|
*baseCompiler
|
|
*flagExporter
|
|
stripper Stripper
|
|
|
|
Properties LibraryCompilerProperties
|
|
MutatedProperties LibraryMutatedProperties
|
|
includeDirs android.Paths
|
|
sourceProvider SourceProvider
|
|
|
|
collectedSnapshotHeaders android.Paths
|
|
|
|
// table-of-contents file for cdylib crates to optimize out relinking when possible
|
|
tocFile android.OptionalPath
|
|
}
|
|
|
|
type libraryInterface interface {
|
|
rlib() bool
|
|
dylib() bool
|
|
static() bool
|
|
shared() bool
|
|
sysroot() bool
|
|
source() bool
|
|
|
|
// Returns true if the build options for the module have selected a particular build type
|
|
buildRlib() bool
|
|
buildDylib() bool
|
|
buildShared() bool
|
|
buildStatic() bool
|
|
|
|
// Sets a particular variant type
|
|
setRlib()
|
|
setDylib()
|
|
setShared()
|
|
setStatic()
|
|
setSource()
|
|
|
|
// libstd linkage functions
|
|
rlibStd() bool
|
|
setRlibStd()
|
|
setDylibStd()
|
|
|
|
// Build a specific library variant
|
|
BuildOnlyFFI()
|
|
BuildOnlyRust()
|
|
BuildOnlyRlib()
|
|
BuildOnlyDylib()
|
|
BuildOnlyStatic()
|
|
BuildOnlyShared()
|
|
|
|
toc() android.OptionalPath
|
|
}
|
|
|
|
func (library *libraryDecorator) nativeCoverage() bool {
|
|
return true
|
|
}
|
|
|
|
func (library *libraryDecorator) toc() android.OptionalPath {
|
|
return library.tocFile
|
|
}
|
|
|
|
func (library *libraryDecorator) rlib() bool {
|
|
return library.MutatedProperties.VariantIsRlib
|
|
}
|
|
|
|
func (library *libraryDecorator) sysroot() bool {
|
|
return Bool(library.Properties.Sysroot)
|
|
}
|
|
|
|
func (library *libraryDecorator) dylib() bool {
|
|
return library.MutatedProperties.VariantIsDylib
|
|
}
|
|
|
|
func (library *libraryDecorator) shared() bool {
|
|
return library.MutatedProperties.VariantIsShared
|
|
}
|
|
|
|
func (library *libraryDecorator) static() bool {
|
|
return library.MutatedProperties.VariantIsStatic
|
|
}
|
|
|
|
func (library *libraryDecorator) source() bool {
|
|
return library.MutatedProperties.VariantIsSource
|
|
}
|
|
|
|
func (library *libraryDecorator) buildRlib() bool {
|
|
return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true)
|
|
}
|
|
|
|
func (library *libraryDecorator) buildDylib() bool {
|
|
return library.MutatedProperties.BuildDylib && BoolDefault(library.Properties.Dylib.Enabled, true)
|
|
}
|
|
|
|
func (library *libraryDecorator) buildShared() bool {
|
|
return library.MutatedProperties.BuildShared && BoolDefault(library.Properties.Shared.Enabled, true)
|
|
}
|
|
|
|
func (library *libraryDecorator) buildStatic() bool {
|
|
return library.MutatedProperties.BuildStatic && BoolDefault(library.Properties.Static.Enabled, true)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (library *libraryDecorator) rlibStd() bool {
|
|
return library.MutatedProperties.VariantIsStaticStd
|
|
}
|
|
|
|
func (library *libraryDecorator) setRlibStd() {
|
|
library.MutatedProperties.VariantIsStaticStd = true
|
|
}
|
|
|
|
func (library *libraryDecorator) setDylibStd() {
|
|
library.MutatedProperties.VariantIsStaticStd = false
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (library *libraryDecorator) setSource() {
|
|
library.MutatedProperties.VariantIsSource = true
|
|
}
|
|
|
|
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() {
|
|
return rlibAutoDep
|
|
} else if library.rlib() || library.static() {
|
|
return rlibAutoDep
|
|
} else if library.dylib() || library.shared() {
|
|
return dylibAutoDep
|
|
} else if ctx.BazelConversionMode() {
|
|
// In Bazel conversion mode, we are currently ignoring the deptag, so we just need to supply a
|
|
// compatible tag in order to add the dependency.
|
|
return rlibAutoDep
|
|
} else {
|
|
panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName()))
|
|
}
|
|
}
|
|
|
|
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 {
|
|
return RlibLinkage
|
|
} else if library.baseCompiler.preferRlib() {
|
|
return RlibLinkage
|
|
}
|
|
return DefaultLinkage
|
|
}
|
|
|
|
var _ compiler = (*libraryDecorator)(nil)
|
|
var _ libraryInterface = (*libraryDecorator)(nil)
|
|
var _ exportedFlagsProducer = (*libraryDecorator)(nil)
|
|
|
|
// rust_library produces all rust variants.
|
|
func RustLibraryFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
|
library.BuildOnlyRust()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_ffi produces all ffi variants.
|
|
func RustFFIFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
|
library.BuildOnlyFFI()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_library_dylib produces a dylib.
|
|
func RustLibraryDylibFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
|
library.BuildOnlyDylib()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_library_rlib produces an rlib.
|
|
func RustLibraryRlibFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
|
library.BuildOnlyRlib()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_ffi_shared produces a shared library.
|
|
func RustFFISharedFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
|
library.BuildOnlyShared()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_ffi_static produces a static library.
|
|
func RustFFIStaticFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
|
library.BuildOnlyStatic()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_library_host produces all rust variants.
|
|
func RustLibraryHostFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostSupported)
|
|
library.BuildOnlyRust()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_ffi_host produces all FFI variants.
|
|
func RustFFIHostFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostSupported)
|
|
library.BuildOnlyFFI()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_library_dylib_host produces a dylib.
|
|
func RustLibraryDylibHostFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostSupported)
|
|
library.BuildOnlyDylib()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_library_rlib_host produces an rlib.
|
|
func RustLibraryRlibHostFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostSupported)
|
|
library.BuildOnlyRlib()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_ffi_static_host produces a static library.
|
|
func RustFFIStaticHostFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostSupported)
|
|
library.BuildOnlyStatic()
|
|
return module.Init()
|
|
}
|
|
|
|
// rust_ffi_shared_host produces an shared library.
|
|
func RustFFISharedHostFactory() android.Module {
|
|
module, library := NewRustLibrary(android.HostSupported)
|
|
library.BuildOnlyShared()
|
|
return module.Init()
|
|
}
|
|
|
|
func (library *libraryDecorator) BuildOnlyFFI() {
|
|
library.MutatedProperties.BuildDylib = false
|
|
library.MutatedProperties.BuildRlib = false
|
|
library.MutatedProperties.BuildShared = true
|
|
library.MutatedProperties.BuildStatic = true
|
|
}
|
|
|
|
func (library *libraryDecorator) BuildOnlyRust() {
|
|
library.MutatedProperties.BuildDylib = true
|
|
library.MutatedProperties.BuildRlib = true
|
|
library.MutatedProperties.BuildShared = false
|
|
library.MutatedProperties.BuildStatic = false
|
|
}
|
|
|
|
func (library *libraryDecorator) BuildOnlyDylib() {
|
|
library.MutatedProperties.BuildDylib = true
|
|
library.MutatedProperties.BuildRlib = false
|
|
library.MutatedProperties.BuildShared = false
|
|
library.MutatedProperties.BuildStatic = false
|
|
}
|
|
|
|
func (library *libraryDecorator) BuildOnlyRlib() {
|
|
library.MutatedProperties.BuildDylib = false
|
|
library.MutatedProperties.BuildRlib = true
|
|
library.MutatedProperties.BuildShared = false
|
|
library.MutatedProperties.BuildStatic = false
|
|
}
|
|
|
|
func (library *libraryDecorator) BuildOnlyStatic() {
|
|
library.MutatedProperties.BuildRlib = false
|
|
library.MutatedProperties.BuildDylib = false
|
|
library.MutatedProperties.BuildShared = false
|
|
library.MutatedProperties.BuildStatic = true
|
|
}
|
|
|
|
func (library *libraryDecorator) BuildOnlyShared() {
|
|
library.MutatedProperties.BuildRlib = false
|
|
library.MutatedProperties.BuildDylib = false
|
|
library.MutatedProperties.BuildStatic = false
|
|
library.MutatedProperties.BuildShared = true
|
|
}
|
|
|
|
func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
|
|
module := newModule(hod, android.MultilibBoth)
|
|
|
|
library := &libraryDecorator{
|
|
MutatedProperties: LibraryMutatedProperties{
|
|
BuildDylib: false,
|
|
BuildRlib: false,
|
|
BuildShared: false,
|
|
BuildStatic: false,
|
|
},
|
|
baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem),
|
|
flagExporter: NewFlagExporter(),
|
|
}
|
|
|
|
module.compiler = library
|
|
|
|
return module, library
|
|
}
|
|
|
|
func (library *libraryDecorator) compilerProps() []interface{} {
|
|
return append(library.baseCompiler.compilerProps(),
|
|
&library.Properties,
|
|
&library.MutatedProperties,
|
|
&library.stripper.StripProperties)
|
|
}
|
|
|
|
func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
|
|
deps = library.baseCompiler.compilerDeps(ctx, deps)
|
|
|
|
if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) {
|
|
deps = bionicDeps(ctx, deps, false)
|
|
deps.CrtBegin = "crtbegin_so"
|
|
deps.CrtEnd = "crtend_so"
|
|
}
|
|
|
|
return deps
|
|
}
|
|
|
|
func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string {
|
|
return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
|
|
}
|
|
|
|
func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags {
|
|
flags = library.baseCompiler.cfgFlags(ctx, flags)
|
|
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")
|
|
}
|
|
|
|
flags.RustFlags = append(flags.RustFlags, library.baseCompiler.cfgsToFlags()...)
|
|
flags.RustdocFlags = append(flags.RustdocFlags, library.baseCompiler.cfgsToFlags()...)
|
|
|
|
return 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() {
|
|
library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
|
|
}
|
|
if library.shared() {
|
|
flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
|
|
}
|
|
|
|
return flags
|
|
}
|
|
|
|
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
|
|
var outputFile, ret android.ModuleOutPath
|
|
var fileName string
|
|
srcPath := library.srcPath(ctx, deps)
|
|
|
|
if library.sourceProvider != nil {
|
|
deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...)
|
|
}
|
|
|
|
// Calculate output filename
|
|
if library.rlib() {
|
|
fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix()
|
|
outputFile = android.PathForModuleOut(ctx, fileName)
|
|
ret = outputFile
|
|
} else if library.dylib() {
|
|
fileName = library.getStem(ctx) + ctx.toolchain().DylibSuffix()
|
|
outputFile = android.PathForModuleOut(ctx, fileName)
|
|
ret = outputFile
|
|
} else if library.static() {
|
|
fileName = library.getStem(ctx) + ctx.toolchain().StaticLibSuffix()
|
|
outputFile = android.PathForModuleOut(ctx, fileName)
|
|
ret = outputFile
|
|
} else if library.shared() {
|
|
fileName = library.sharedLibFilename(ctx)
|
|
outputFile = android.PathForModuleOut(ctx, fileName)
|
|
ret = outputFile
|
|
}
|
|
|
|
if !library.rlib() && !library.static() && library.stripper.NeedsStrip(ctx) {
|
|
strippedOutputFile := outputFile
|
|
outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
|
|
library.stripper.StripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile)
|
|
|
|
library.baseCompiler.strippedOutputFile = android.OptionalPathForPath(strippedOutputFile)
|
|
}
|
|
library.baseCompiler.unstrippedOutputFile = outputFile
|
|
|
|
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
|
|
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
|
|
flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
|
|
|
|
if library.dylib() {
|
|
// We need prefer-dynamic for now to avoid linking in the static stdlib. See:
|
|
// https://github.com/rust-lang/rust/issues/19680
|
|
// https://github.com/rust-lang/rust/issues/34909
|
|
flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
|
|
}
|
|
|
|
// Call the appropriate builder for this library type
|
|
if library.rlib() {
|
|
TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile)
|
|
} else if library.dylib() {
|
|
TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile)
|
|
} else if library.static() {
|
|
TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile)
|
|
} else if library.shared() {
|
|
TransformSrctoShared(ctx, srcPath, deps, flags, outputFile)
|
|
}
|
|
|
|
if library.rlib() || library.dylib() {
|
|
library.flagExporter.exportLinkDirs(deps.linkDirs...)
|
|
library.flagExporter.exportLinkObjects(deps.linkObjects...)
|
|
}
|
|
|
|
if library.static() || library.shared() {
|
|
ctx.SetProvider(cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
|
|
IncludeDirs: library.includeDirs,
|
|
})
|
|
}
|
|
|
|
if library.shared() {
|
|
// 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")
|
|
library.tocFile = android.OptionalPathForPath(tocFile)
|
|
cc.TransformSharedObjectToToc(ctx, outputFile, tocFile)
|
|
|
|
ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{
|
|
TableOfContents: android.OptionalPathForPath(tocFile),
|
|
SharedLibrary: outputFile,
|
|
Target: ctx.Target(),
|
|
})
|
|
}
|
|
|
|
if library.static() {
|
|
depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build()
|
|
ctx.SetProvider(cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{
|
|
StaticLibrary: outputFile,
|
|
|
|
TransitiveStaticLibrariesForOrdering: depSet,
|
|
})
|
|
}
|
|
|
|
library.flagExporter.setProvider(ctx)
|
|
|
|
return ret
|
|
}
|
|
|
|
func (library *libraryDecorator) srcPath(ctx ModuleContext, deps PathDeps) android.Path {
|
|
if library.sourceProvider != nil {
|
|
// Assume the first source from the source provider is the library entry point.
|
|
return library.sourceProvider.Srcs()[0]
|
|
} else {
|
|
path, _ := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
|
|
return path
|
|
}
|
|
}
|
|
|
|
func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags,
|
|
deps PathDeps) android.OptionalPath {
|
|
// rustdoc has builtin support for documenting config specific information
|
|
// regardless of the actual config it was given
|
|
// (https://doc.rust-lang.org/rustdoc/advanced-features.html#cfgdoc-documenting-platform-specific-or-feature-specific-information),
|
|
// so we generate the rustdoc for only the primary module so that we have a
|
|
// single set of docs to refer to.
|
|
if ctx.Module() != ctx.PrimaryModule() {
|
|
return android.OptionalPath{}
|
|
}
|
|
|
|
return android.OptionalPathForPath(Rustdoc(ctx, library.srcPath(ctx, deps),
|
|
deps, flags))
|
|
}
|
|
|
|
func (library *libraryDecorator) getStem(ctx ModuleContext) string {
|
|
stem := library.baseCompiler.getStemWithoutSuffix(ctx)
|
|
validateLibraryStem(ctx, stem, library.crateName())
|
|
|
|
return stem + String(library.baseCompiler.Properties.Suffix)
|
|
}
|
|
|
|
func (library *libraryDecorator) install(ctx ModuleContext) {
|
|
// Only shared and dylib variants make sense to install.
|
|
if library.shared() || library.dylib() {
|
|
library.baseCompiler.install(ctx)
|
|
}
|
|
}
|
|
|
|
func (library *libraryDecorator) Disabled() bool {
|
|
return library.MutatedProperties.VariantIsDisabled
|
|
}
|
|
|
|
func (library *libraryDecorator) SetDisabled() {
|
|
library.MutatedProperties.VariantIsDisabled = true
|
|
}
|
|
|
|
var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+")
|
|
|
|
func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) {
|
|
if crate_name == "" {
|
|
ctx.PropertyErrorf("crate_name", "crate_name must be defined.")
|
|
}
|
|
|
|
// crate_names are used for the library output file, and rustc expects these
|
|
// to be alphanumeric with underscores allowed.
|
|
if validCrateName.MatchString(crate_name) {
|
|
ctx.PropertyErrorf("crate_name",
|
|
"library crate_names must be alphanumeric with underscores allowed")
|
|
}
|
|
|
|
// Libraries are expected to begin with "lib" followed by the crate_name
|
|
if !strings.HasPrefix(filename, "lib"+crate_name) {
|
|
ctx.ModuleErrorf("Invalid name or stem property; library filenames must start with lib<crate_name>")
|
|
}
|
|
}
|
|
|
|
// LibraryMutator mutates the libraries into variants according to the
|
|
// build{Rlib,Dylib} attributes.
|
|
func LibraryMutator(mctx android.BottomUpMutatorContext) {
|
|
// Only mutate on Rust libraries.
|
|
m, ok := mctx.Module().(*Module)
|
|
if !ok || m.compiler == nil {
|
|
return
|
|
}
|
|
library, ok := m.compiler.(libraryInterface)
|
|
if !ok {
|
|
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.
|
|
sourceVariant := false
|
|
if m.sourceProvider != nil {
|
|
variants = append(variants, "source")
|
|
sourceVariant = true
|
|
}
|
|
if library.buildRlib() {
|
|
variants = append(variants, rlibVariation)
|
|
}
|
|
if library.buildDylib() {
|
|
variants = append(variants, dylibVariation)
|
|
}
|
|
|
|
if len(variants) == 0 {
|
|
return
|
|
}
|
|
modules := mctx.CreateLocalVariations(variants...)
|
|
|
|
// The order of the variations (modules) matches the variant names provided. Iterate
|
|
// through the new variation modules and set their mutated properties.
|
|
for i, v := range modules {
|
|
switch variants[i] {
|
|
case rlibVariation:
|
|
v.(*Module).compiler.(libraryInterface).setRlib()
|
|
case dylibVariation:
|
|
v.(*Module).compiler.(libraryInterface).setDylib()
|
|
if v.(*Module).ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation {
|
|
// TODO(b/165791368)
|
|
// Disable dylib Vendor Ramdisk variations until we support these.
|
|
v.(*Module).Disable()
|
|
}
|
|
|
|
variation := v.(*Module).ModuleBase.ImageVariation().Variation
|
|
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()
|
|
}
|
|
}
|
|
|
|
// 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() {
|
|
continue
|
|
}
|
|
mctx.AddInterVariantDependency(sourceDepTag, v, sv)
|
|
}
|
|
// Alias the source variation so it can be named directly in "srcs" properties.
|
|
mctx.AliasVariation("source")
|
|
}
|
|
}
|
|
|
|
func LibstdMutator(mctx android.BottomUpMutatorContext) {
|
|
if m, ok := mctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() {
|
|
switch library := m.compiler.(type) {
|
|
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()
|
|
}
|
|
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()
|
|
glob, err := ctx.GlobWithDeps(dir+"/**/*", nil)
|
|
if err != nil {
|
|
ctx.ModuleErrorf("glob failed: %#v", 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
|
|
}
|