rust: made-to-order rust staticlibs
Whenever any two Rust static libraries are included as static libraries anywhere in a CC dependency tree, we sometimes get duplicate symbol errors. To avoid this, we no longer directly link multiple rust static libs to CC modules. Instead, we build rust_ffi_rlib modules and produce the actual static library that gets linked against the CC module based on that CC module's full list of Rust rlib dependencies. This introduces a new static_rlibs property for cc modules to define the rust_ffi_rlib dependencies, which are then used to generate the module above. This CL is intended to deprecate rust_ffi_static. It leaves rust_ffi_static and rust_ffi static variants in place until the remaining rust_ffi_static declarations and uses can be removed. In the meantime, rust_ffi_static produces rust_ffi_rlib variants as well to make the transition easier. Bug: 254469782 Test: m # with no changes Test: m libapexsupport # with static_rlibs Test: m libunwindstack # with static_rlibs Test: m netsimd # with static_rlibs, no duplicate symbols Test: m blueprint_tests # New Soong tests Change-Id: I47e27ac967ef0cad46d398ebf59d8275929ae28a
This commit is contained in:
parent
28ed8f4f83
commit
0a468a4f3b
22 changed files with 643 additions and 127 deletions
|
@ -302,6 +302,24 @@ func RemoveFromList(s string, list []string) (bool, []string) {
|
|||
return removed, result
|
||||
}
|
||||
|
||||
// FirstUniqueFunc returns all unique elements of a slice, keeping the first copy of
|
||||
// each. It does not modify the input slice. The eq function should return true
|
||||
// if two elements can be considered equal.
|
||||
func FirstUniqueFunc[SortableList ~[]Sortable, Sortable any](list SortableList, eq func(a, b Sortable) bool) SortableList {
|
||||
k := 0
|
||||
outer:
|
||||
for i := 0; i < len(list); i++ {
|
||||
for j := 0; j < k; j++ {
|
||||
if eq(list[i], list[j]) {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
list[k] = list[i]
|
||||
k++
|
||||
}
|
||||
return list[:k]
|
||||
}
|
||||
|
||||
// FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
|
||||
// each. It does not modify the input slice.
|
||||
func FirstUniqueStrings(list []string) []string {
|
||||
|
|
|
@ -702,7 +702,12 @@ var (
|
|||
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ApexNativeDependencies, target android.Target, imageVariation string) {
|
||||
binVariations := target.Variations()
|
||||
libVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
|
||||
rustLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"})
|
||||
rustLibVariations := append(
|
||||
target.Variations(), []blueprint.Variation{
|
||||
{Mutator: "rust_libraries", Variation: "dylib"},
|
||||
{Mutator: "link", Variation: ""},
|
||||
}...,
|
||||
)
|
||||
|
||||
// Append "image" variation
|
||||
binVariations = append(binVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation})
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"android/soong/android"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
|
@ -425,6 +426,10 @@ func (binary *binaryDecorator) link(ctx ModuleContext,
|
|||
validations = append(validations, objs.tidyDepFiles...)
|
||||
linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
|
||||
|
||||
if generatedLib := generateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
|
||||
deps.StaticLibs = append(deps.StaticLibs, generatedLib)
|
||||
}
|
||||
|
||||
// Register link action.
|
||||
transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs,
|
||||
deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
|
||||
|
|
|
@ -19,6 +19,7 @@ package cc
|
|||
// functions.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
@ -330,6 +331,15 @@ var (
|
|||
CommandDeps: []string{"$cxxExtractor", "$kytheVnames"},
|
||||
},
|
||||
"cFlags")
|
||||
|
||||
// Function pointer for producting staticlibs from rlibs. Corresponds to
|
||||
// rust.TransformRlibstoStaticlib(), initialized in soong-rust (rust/builder.go init())
|
||||
//
|
||||
// This is required since soong-rust depends on soong-cc, so soong-cc cannot depend on soong-rust
|
||||
// without resulting in a circular dependency. Setting this function pointer in soong-rust allows
|
||||
// soong-cc to call into this particular function.
|
||||
TransformRlibstoStaticlib (func(ctx android.ModuleContext, mainSrc android.Path, deps []RustRlibDep,
|
||||
outputFile android.WritablePath) android.Path) = nil
|
||||
)
|
||||
|
||||
func PwdPrefix() string {
|
||||
|
@ -774,6 +784,47 @@ func transformObjToStaticLib(ctx android.ModuleContext,
|
|||
}
|
||||
}
|
||||
|
||||
// Generate a Rust staticlib from a list of rlibDeps. Returns nil if TransformRlibstoStaticlib is nil or rlibDeps is empty.
|
||||
func generateRustStaticlib(ctx android.ModuleContext, rlibDeps []RustRlibDep) android.Path {
|
||||
if TransformRlibstoStaticlib == nil && len(rlibDeps) > 0 {
|
||||
// This should only be reachable if a module defines static_rlibs and
|
||||
// soong-rust hasn't been loaded alongside soong-cc (e.g. in soong-cc tests).
|
||||
panic(fmt.Errorf("TransformRlibstoStaticlib is not set and static_rlibs is defined in %s", ctx.ModuleName()))
|
||||
} else if len(rlibDeps) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
output := android.PathForModuleOut(ctx, "generated_rust_staticlib", "lib"+ctx.ModuleName()+"_rust_staticlib.a")
|
||||
stemFile := output.ReplaceExtension(ctx, "rs")
|
||||
crateNames := []string{}
|
||||
|
||||
// Collect crate names
|
||||
for _, lib := range rlibDeps {
|
||||
// Exclude libstd so this can support no_std builds.
|
||||
if lib.CrateName != "libstd" {
|
||||
crateNames = append(crateNames, lib.CrateName)
|
||||
}
|
||||
}
|
||||
|
||||
// Deduplicate any crateNames just to be safe
|
||||
crateNames = android.FirstUniqueStrings(crateNames)
|
||||
|
||||
// Write the source file
|
||||
android.WriteFileRule(ctx, stemFile, genRustStaticlibSrcFile(crateNames))
|
||||
|
||||
return TransformRlibstoStaticlib(ctx, stemFile, rlibDeps, output)
|
||||
}
|
||||
|
||||
func genRustStaticlibSrcFile(crateNames []string) string {
|
||||
lines := []string{
|
||||
"// @Soong generated Source",
|
||||
}
|
||||
for _, crate := range crateNames {
|
||||
lines = append(lines, fmt.Sprintf("extern crate %s;", crate))
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
|
||||
// and shared libraries, to a shared library (.so) or dynamic executable
|
||||
func transformObjToDynamicBinary(ctx android.ModuleContext,
|
||||
|
|
65
cc/cc.go
65
cc/cc.go
|
@ -99,6 +99,7 @@ type Deps struct {
|
|||
StaticLibs, LateStaticLibs, WholeStaticLibs []string
|
||||
HeaderLibs []string
|
||||
RuntimeLibs []string
|
||||
Rlibs []string
|
||||
|
||||
// UnexportedStaticLibs are static libraries that are also passed to -Wl,--exclude-libs= to
|
||||
// prevent automatically exporting symbols.
|
||||
|
@ -144,6 +145,17 @@ type Deps struct {
|
|||
LlndkHeaderLibs []string
|
||||
}
|
||||
|
||||
// A struct which to collect flags for rlib dependencies
|
||||
type RustRlibDep struct {
|
||||
LibPath android.Path // path to the rlib
|
||||
LinkDirs []string // flags required for dependency (e.g. -L flags)
|
||||
CrateName string // crateNames associated with rlibDeps
|
||||
}
|
||||
|
||||
func EqRustRlibDeps(a RustRlibDep, b RustRlibDep) bool {
|
||||
return a.LibPath == b.LibPath
|
||||
}
|
||||
|
||||
// PathDeps is a struct containing file paths to dependencies of a module.
|
||||
// It's constructed in depsToPath() by traversing the direct dependencies of the current module.
|
||||
// It's used to construct flags for various build statements (such as for compiling and linking).
|
||||
|
@ -156,6 +168,8 @@ type PathDeps struct {
|
|||
SharedLibsDeps, EarlySharedLibsDeps, LateSharedLibsDeps android.Paths
|
||||
// Paths to .a files
|
||||
StaticLibs, LateStaticLibs, WholeStaticLibs android.Paths
|
||||
// Paths and crateNames for RustStaticLib dependencies
|
||||
RustRlibDeps []RustRlibDep
|
||||
|
||||
// Transitive static library dependencies of static libraries for use in ordering.
|
||||
TranstiveStaticLibrariesForOrdering *android.DepSet[android.Path]
|
||||
|
@ -184,6 +198,7 @@ type PathDeps struct {
|
|||
ReexportedFlags []string
|
||||
ReexportedGeneratedHeaders android.Paths
|
||||
ReexportedDeps android.Paths
|
||||
ReexportedRustRlibDeps []RustRlibDep
|
||||
|
||||
// Paths to crt*.o files
|
||||
CrtBegin, CrtEnd android.Paths
|
||||
|
@ -297,6 +312,7 @@ type BaseProperties struct {
|
|||
|
||||
AndroidMkSharedLibs []string `blueprint:"mutated"`
|
||||
AndroidMkStaticLibs []string `blueprint:"mutated"`
|
||||
AndroidMkRlibs []string `blueprint:"mutated"`
|
||||
AndroidMkRuntimeLibs []string `blueprint:"mutated"`
|
||||
AndroidMkWholeStaticLibs []string `blueprint:"mutated"`
|
||||
AndroidMkHeaderLibs []string `blueprint:"mutated"`
|
||||
|
@ -653,6 +669,7 @@ const (
|
|||
headerLibraryDependency = iota
|
||||
sharedLibraryDependency
|
||||
staticLibraryDependency
|
||||
rlibLibraryDependency
|
||||
)
|
||||
|
||||
func (k libraryDependencyKind) String() string {
|
||||
|
@ -663,6 +680,8 @@ func (k libraryDependencyKind) String() string {
|
|||
return "sharedLibraryDependency"
|
||||
case staticLibraryDependency:
|
||||
return "staticLibraryDependency"
|
||||
case rlibLibraryDependency:
|
||||
return "rlibLibraryDependency"
|
||||
default:
|
||||
panic(fmt.Errorf("unknown libraryDependencyKind %d", k))
|
||||
}
|
||||
|
@ -740,6 +759,11 @@ func (d libraryDependencyTag) static() bool {
|
|||
return d.Kind == staticLibraryDependency
|
||||
}
|
||||
|
||||
// rlib returns true if the libraryDependencyTag is tagging an rlib dependency.
|
||||
func (d libraryDependencyTag) rlib() bool {
|
||||
return d.Kind == rlibLibraryDependency
|
||||
}
|
||||
|
||||
func (d libraryDependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
|
||||
if d.shared() {
|
||||
return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
|
||||
|
@ -1108,6 +1132,14 @@ func (c *Module) RustLibraryInterface() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (c *Module) CrateName() string {
|
||||
panic(fmt.Errorf("CrateName called on non-Rust module: %q", c.BaseModuleName()))
|
||||
}
|
||||
|
||||
func (c *Module) ExportedCrateLinkDirs() []string {
|
||||
panic(fmt.Errorf("ExportedCrateLinkDirs called on non-Rust module: %q", c.BaseModuleName()))
|
||||
}
|
||||
|
||||
func (c *Module) IsFuzzModule() bool {
|
||||
if _, ok := c.compiler.(*fuzzBinary); ok {
|
||||
return true
|
||||
|
@ -2300,6 +2332,7 @@ func (c *Module) deps(ctx DepsContext) Deps {
|
|||
|
||||
deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
|
||||
deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
|
||||
deps.Rlibs = android.LastUniqueStrings(deps.Rlibs)
|
||||
deps.LateStaticLibs = android.LastUniqueStrings(deps.LateStaticLibs)
|
||||
deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
|
||||
deps.LateSharedLibs = android.LastUniqueStrings(deps.LateSharedLibs)
|
||||
|
@ -2607,6 +2640,15 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
}, depTag, lib)
|
||||
}
|
||||
|
||||
for _, lib := range deps.Rlibs {
|
||||
depTag := libraryDependencyTag{Kind: rlibLibraryDependency}
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{Mutator: "link", Variation: ""},
|
||||
{Mutator: "rust_libraries", Variation: "rlib"},
|
||||
{Mutator: "rust_stdlinkage", Variation: "rlib-std"},
|
||||
}, depTag, lib)
|
||||
}
|
||||
|
||||
// staticUnwinderDep is treated as staticDep for Q apexes
|
||||
// so that native libraries/binaries are linked with static unwinder
|
||||
// because Q libc doesn't have unwinder APIs
|
||||
|
@ -3216,6 +3258,14 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
default:
|
||||
panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
|
||||
}
|
||||
|
||||
case libDepTag.rlib():
|
||||
rlibDep := RustRlibDep{LibPath: linkFile.Path(), CrateName: ccDep.CrateName(), LinkDirs: ccDep.ExportedCrateLinkDirs()}
|
||||
depPaths.ReexportedRustRlibDeps = append(depPaths.ReexportedRustRlibDeps, rlibDep)
|
||||
depPaths.RustRlibDeps = append(depPaths.RustRlibDeps, rlibDep)
|
||||
depPaths.IncludeDirs = append(depPaths.IncludeDirs, depExporterInfo.IncludeDirs...)
|
||||
depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, depExporterInfo.IncludeDirs...)
|
||||
|
||||
case libDepTag.static():
|
||||
staticLibraryInfo, isStaticLib := android.OtherModuleProvider(ctx, dep, StaticLibraryInfoProvider)
|
||||
if !isStaticLib {
|
||||
|
@ -3268,6 +3318,12 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
|
||||
}
|
||||
}
|
||||
|
||||
// We re-export the Rust static_rlibs so rlib dependencies don't need to be redeclared by cc_library_static dependents.
|
||||
// E.g. libfoo (cc_library_static) depends on libfoo.ffi (a rust_ffi rlib), libbar depending on libfoo shouldn't have to also add libfoo.ffi to static_rlibs.
|
||||
depPaths.ReexportedRustRlibDeps = append(depPaths.ReexportedRustRlibDeps, depExporterInfo.RustRlibDeps...)
|
||||
depPaths.RustRlibDeps = append(depPaths.RustRlibDeps, depExporterInfo.RustRlibDeps...)
|
||||
|
||||
if libDepTag.unexportedSymbols {
|
||||
depPaths.LdFlags = append(depPaths.LdFlags,
|
||||
"-Wl,--exclude-libs="+staticLibraryInfo.StaticLibrary.Base())
|
||||
|
@ -3320,6 +3376,12 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, depExporterInfo.SystemIncludeDirs...)
|
||||
depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, depExporterInfo.Deps...)
|
||||
depPaths.Flags = append(depPaths.Flags, depExporterInfo.Flags...)
|
||||
depPaths.RustRlibDeps = append(depPaths.RustRlibDeps, depExporterInfo.RustRlibDeps...)
|
||||
|
||||
// Only re-export RustRlibDeps for cc static libs
|
||||
if c.static() {
|
||||
depPaths.ReexportedRustRlibDeps = append(depPaths.ReexportedRustRlibDeps, depExporterInfo.RustRlibDeps...)
|
||||
}
|
||||
|
||||
if libDepTag.reexportFlags {
|
||||
reexportExporter(depExporterInfo)
|
||||
|
@ -3392,11 +3454,14 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
depPaths.IncludeDirs = android.FirstUniquePaths(depPaths.IncludeDirs)
|
||||
depPaths.SystemIncludeDirs = android.FirstUniquePaths(depPaths.SystemIncludeDirs)
|
||||
depPaths.GeneratedDeps = android.FirstUniquePaths(depPaths.GeneratedDeps)
|
||||
depPaths.RustRlibDeps = android.FirstUniqueFunc(depPaths.RustRlibDeps, EqRustRlibDeps)
|
||||
|
||||
depPaths.ReexportedDirs = android.FirstUniquePaths(depPaths.ReexportedDirs)
|
||||
depPaths.ReexportedSystemDirs = android.FirstUniquePaths(depPaths.ReexportedSystemDirs)
|
||||
depPaths.ReexportedFlags = android.FirstUniqueStrings(depPaths.ReexportedFlags)
|
||||
depPaths.ReexportedDeps = android.FirstUniquePaths(depPaths.ReexportedDeps)
|
||||
depPaths.ReexportedGeneratedHeaders = android.FirstUniquePaths(depPaths.ReexportedGeneratedHeaders)
|
||||
depPaths.ReexportedRustRlibDeps = android.FirstUniqueFunc(depPaths.ReexportedRustRlibDeps, EqRustRlibDeps)
|
||||
|
||||
if c.sabi != nil {
|
||||
c.sabi.Properties.ReexportedIncludes = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludes)
|
||||
|
|
|
@ -772,6 +772,9 @@ type RustBindgenClangProperties struct {
|
|||
// be added to the include path using -I
|
||||
Local_include_dirs []string `android:"arch_variant,variant_prepend"`
|
||||
|
||||
// list of Rust static libraries.
|
||||
Static_rlibs []string `android:"arch_variant,variant_prepend"`
|
||||
|
||||
// list of static libraries that provide headers for this binding.
|
||||
Static_libs []string `android:"arch_variant,variant_prepend"`
|
||||
|
||||
|
|
|
@ -597,7 +597,7 @@ func CollectAllSharedDependencies(ctx android.ModuleContext) (android.RuleBuilde
|
|||
ctx.WalkDeps(func(child, parent android.Module) bool {
|
||||
|
||||
// If this is a Rust module which is not rust_ffi_shared, we still want to bundle any transitive
|
||||
// shared dependencies (even for rust_ffi_static)
|
||||
// shared dependencies (even for rust_ffi_rlib or rust_ffi_static)
|
||||
if rustmod, ok := child.(LinkableInterface); ok && rustmod.RustLibraryInterface() && !rustmod.Shared() {
|
||||
if recursed[ctx.OtherModuleName(child)] {
|
||||
return false
|
||||
|
|
|
@ -274,11 +274,12 @@ func LibraryHostSharedFactory() android.Module {
|
|||
type flagExporter struct {
|
||||
Properties FlagExporterProperties
|
||||
|
||||
dirs android.Paths // Include directories to be included with -I
|
||||
systemDirs android.Paths // System include directories to be included with -isystem
|
||||
flags []string // Exported raw flags.
|
||||
deps android.Paths
|
||||
headers android.Paths
|
||||
dirs android.Paths // Include directories to be included with -I
|
||||
systemDirs android.Paths // System include directories to be included with -isystem
|
||||
flags []string // Exported raw flags.
|
||||
deps android.Paths
|
||||
headers android.Paths
|
||||
rustRlibDeps []RustRlibDep
|
||||
}
|
||||
|
||||
// exportedIncludes returns the effective include paths for this module and
|
||||
|
@ -339,6 +340,10 @@ func (f *flagExporter) reexportDeps(deps ...android.Path) {
|
|||
f.deps = append(f.deps, deps...)
|
||||
}
|
||||
|
||||
func (f *flagExporter) reexportRustStaticDeps(deps ...RustRlibDep) {
|
||||
f.rustRlibDeps = append(f.rustRlibDeps, deps...)
|
||||
}
|
||||
|
||||
// addExportedGeneratedHeaders does nothing but collects generated header files.
|
||||
// This can be differ to exportedDeps which may contain phony files to minimize ninja.
|
||||
func (f *flagExporter) addExportedGeneratedHeaders(headers ...android.Path) {
|
||||
|
@ -356,6 +361,8 @@ func (f *flagExporter) setProvider(ctx android.ModuleContext) {
|
|||
// Used sparingly, for extra files that need to be explicitly exported to dependers,
|
||||
// or for phony files to minimize ninja.
|
||||
Deps: f.deps,
|
||||
// Used for exporting rlib deps of static libraries to dependents.
|
||||
RustRlibDeps: f.rustRlibDeps,
|
||||
// For exported generated headers, such as exported aidl headers, proto headers, or
|
||||
// sysprop headers.
|
||||
GeneratedHeaders: f.headers,
|
||||
|
@ -1132,9 +1139,14 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
|
|||
linkerDeps = append(linkerDeps, deps.EarlySharedLibsDeps...)
|
||||
linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
|
||||
linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
|
||||
|
||||
if generatedLib := generateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
|
||||
deps.StaticLibs = append(deps.StaticLibs, generatedLib)
|
||||
}
|
||||
|
||||
transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
|
||||
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
|
||||
linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, objs.tidyDepFiles)
|
||||
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin,
|
||||
deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, objs.tidyDepFiles)
|
||||
|
||||
objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
|
||||
objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
|
||||
|
@ -1594,6 +1606,10 @@ func (library *libraryDecorator) link(ctx ModuleContext,
|
|||
library.reexportDeps(deps.ReexportedDeps...)
|
||||
library.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
|
||||
|
||||
if library.static() && len(deps.ReexportedRustRlibDeps) > 0 {
|
||||
library.reexportRustStaticDeps(deps.ReexportedRustRlibDeps...)
|
||||
}
|
||||
|
||||
// Optionally export aidl headers.
|
||||
if Bool(library.Properties.Aidl.Export_aidl_headers) {
|
||||
if library.baseCompiler.hasAidl(deps) {
|
||||
|
@ -2121,14 +2137,12 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) {
|
|||
// Header only
|
||||
}
|
||||
|
||||
} else if library, ok := mctx.Module().(LinkableInterface); ok && library.CcLibraryInterface() {
|
||||
|
||||
} else if library, ok := mctx.Module().(LinkableInterface); ok && (library.CcLibraryInterface() || library.RustLibraryInterface()) {
|
||||
// Non-cc.Modules may need an empty variant for their mutators.
|
||||
variations := []string{}
|
||||
if library.NonCcVariants() {
|
||||
variations = append(variations, "")
|
||||
}
|
||||
|
||||
isLLNDK := false
|
||||
if m, ok := mctx.Module().(*Module); ok {
|
||||
isLLNDK = m.IsLlndk()
|
||||
|
|
|
@ -73,6 +73,12 @@ type LinkableInterface interface {
|
|||
// RustLibraryInterface returns true if this is a Rust library module
|
||||
RustLibraryInterface() bool
|
||||
|
||||
// CrateName returns the crateName for a Rust library, panics if not a Rust library.
|
||||
CrateName() string
|
||||
|
||||
// DepFlags returns a slice of Rustc string flags, panics if not a Rust library
|
||||
ExportedCrateLinkDirs() []string
|
||||
|
||||
// BaseModuleName returns the android.ModuleBase.BaseModuleName() value for this module.
|
||||
BaseModuleName() string
|
||||
|
||||
|
@ -380,6 +386,7 @@ type FlagExporterInfo struct {
|
|||
SystemIncludeDirs android.Paths // System include directories to be included with -isystem
|
||||
Flags []string // Exported raw flags.
|
||||
Deps android.Paths
|
||||
RustRlibDeps []RustRlibDep
|
||||
GeneratedHeaders android.Paths
|
||||
}
|
||||
|
||||
|
|
35
cc/linker.go
35
cc/linker.go
|
@ -39,6 +39,9 @@ type BaseLinkerProperties struct {
|
|||
// the dependency's .a file will be linked into this module using -Wl,--whole-archive.
|
||||
Whole_static_libs []string `android:"arch_variant,variant_prepend"`
|
||||
|
||||
// list of Rust libs that should be statically linked into this module.
|
||||
Static_rlibs []string `android:"arch_variant"`
|
||||
|
||||
// list of modules that should be statically linked into this module.
|
||||
Static_libs []string `android:"arch_variant,variant_prepend"`
|
||||
|
||||
|
@ -116,10 +119,14 @@ type BaseLinkerProperties struct {
|
|||
// product variant of the C/C++ module.
|
||||
Static_libs []string
|
||||
|
||||
// list of ehader libs that only should be used to build vendor or product
|
||||
// list of header libs that only should be used to build vendor or product
|
||||
// variant of the C/C++ module.
|
||||
Header_libs []string
|
||||
|
||||
// list of Rust libs that should be statically linked to build vendor or product
|
||||
// variant.
|
||||
Static_rlibs []string
|
||||
|
||||
// list of shared libs that should not be used to build vendor or
|
||||
// product variant of the C/C++ module.
|
||||
Exclude_shared_libs []string
|
||||
|
@ -148,6 +155,10 @@ type BaseLinkerProperties struct {
|
|||
// variant of the C/C++ module.
|
||||
Static_libs []string
|
||||
|
||||
// list of Rust libs that should be statically linked to build the recovery
|
||||
// variant.
|
||||
Static_rlibs []string
|
||||
|
||||
// list of shared libs that should not be used to build
|
||||
// the recovery variant of the C/C++ module.
|
||||
Exclude_shared_libs []string
|
||||
|
@ -165,10 +176,14 @@ type BaseLinkerProperties struct {
|
|||
Exclude_runtime_libs []string
|
||||
}
|
||||
Ramdisk struct {
|
||||
// list of static libs that only should be used to build the recovery
|
||||
// list of static libs that only should be used to build the ramdisk
|
||||
// variant of the C/C++ module.
|
||||
Static_libs []string
|
||||
|
||||
// list of Rust libs that should be statically linked to build the ramdisk
|
||||
// variant.
|
||||
Static_rlibs []string
|
||||
|
||||
// list of shared libs that should not be used to build
|
||||
// the ramdisk variant of the C/C++ module.
|
||||
Exclude_shared_libs []string
|
||||
|
@ -183,9 +198,13 @@ type BaseLinkerProperties struct {
|
|||
}
|
||||
Vendor_ramdisk struct {
|
||||
// list of shared libs that should not be used to build
|
||||
// the recovery variant of the C/C++ module.
|
||||
// the vendor ramdisk variant of the C/C++ module.
|
||||
Exclude_shared_libs []string
|
||||
|
||||
// list of Rust libs that should be statically linked to build the vendor ramdisk
|
||||
// variant.
|
||||
Static_rlibs []string
|
||||
|
||||
// list of static libs that should not be used to build
|
||||
// the vendor ramdisk variant of the C/C++ module.
|
||||
Exclude_static_libs []string
|
||||
|
@ -201,6 +220,10 @@ type BaseLinkerProperties struct {
|
|||
// variants.
|
||||
Shared_libs []string
|
||||
|
||||
// list of Rust libs that should be statically linked to build the vendor ramdisk
|
||||
// variant.
|
||||
Static_rlibs []string
|
||||
|
||||
// list of ehader libs that only should be used to build platform variant of
|
||||
// the C/C++ module.
|
||||
Header_libs []string
|
||||
|
@ -291,6 +314,7 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
|
|||
deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
|
||||
deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...)
|
||||
deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
|
||||
deps.Rlibs = append(deps.Rlibs, linker.Properties.Static_rlibs...)
|
||||
deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
|
||||
deps.RuntimeLibs = append(deps.RuntimeLibs, linker.Properties.Runtime_libs...)
|
||||
|
||||
|
@ -333,6 +357,7 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
|
|||
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor.Exclude_static_libs)
|
||||
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
|
||||
deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor.Exclude_runtime_libs)
|
||||
deps.Rlibs = append(deps.Rlibs, linker.Properties.Target.Vendor.Static_rlibs...)
|
||||
}
|
||||
|
||||
if ctx.inProduct() {
|
||||
|
@ -345,6 +370,7 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
|
|||
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Product.Exclude_static_libs)
|
||||
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Product.Exclude_static_libs)
|
||||
deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Product.Exclude_runtime_libs)
|
||||
deps.Rlibs = append(deps.Rlibs, linker.Properties.Target.Product.Static_rlibs...)
|
||||
}
|
||||
|
||||
if ctx.inRecovery() {
|
||||
|
@ -358,6 +384,7 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
|
|||
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs)
|
||||
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
|
||||
deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Recovery.Exclude_runtime_libs)
|
||||
deps.Rlibs = append(deps.Rlibs, linker.Properties.Target.Recovery.Static_rlibs...)
|
||||
}
|
||||
|
||||
if ctx.inRamdisk() {
|
||||
|
@ -368,6 +395,7 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
|
|||
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Ramdisk.Exclude_static_libs)
|
||||
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Ramdisk.Exclude_static_libs)
|
||||
deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Ramdisk.Exclude_runtime_libs)
|
||||
deps.Rlibs = append(deps.Rlibs, linker.Properties.Target.Ramdisk.Static_rlibs...)
|
||||
}
|
||||
|
||||
if ctx.inVendorRamdisk() {
|
||||
|
@ -377,6 +405,7 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
|
|||
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
|
||||
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
|
||||
deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_runtime_libs)
|
||||
deps.Rlibs = append(deps.Rlibs, linker.Properties.Target.Vendor_ramdisk.Static_rlibs...)
|
||||
}
|
||||
|
||||
if !ctx.useSdk() {
|
||||
|
|
|
@ -299,6 +299,7 @@ func commonDefaultModules() string {
|
|||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
vendor_available: true,
|
||||
vendor_ramdisk_available: true,
|
||||
product_available: true,
|
||||
recovery_available: true,
|
||||
host_supported: true,
|
||||
|
@ -570,17 +571,17 @@ var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers(
|
|||
|
||||
// Additional files needed in tests that disallow non-existent source.
|
||||
android.MockFS{
|
||||
"defaults/cc/common/libc.map.txt": nil,
|
||||
"defaults/cc/common/libdl.map.txt": nil,
|
||||
"defaults/cc/common/libft2.map.txt": nil,
|
||||
"defaults/cc/common/libm.map.txt": nil,
|
||||
"defaults/cc/common/ndk_libc++_shared": nil,
|
||||
"defaults/cc/common/crtbegin_so.c": nil,
|
||||
"defaults/cc/common/crtbegin.c": nil,
|
||||
"defaults/cc/common/crtend_so.c": nil,
|
||||
"defaults/cc/common/crtend.c": nil,
|
||||
"defaults/cc/common/crtbrand.c": nil,
|
||||
"external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil,
|
||||
"defaults/cc/common/libc.map.txt": nil,
|
||||
"defaults/cc/common/libdl.map.txt": nil,
|
||||
"defaults/cc/common/libft2.map.txt": nil,
|
||||
"defaults/cc/common/libm.map.txt": nil,
|
||||
"defaults/cc/common/ndk_libc++_shared": nil,
|
||||
"defaults/cc/common/crtbegin_so.c": nil,
|
||||
"defaults/cc/common/crtbegin.c": nil,
|
||||
"defaults/cc/common/crtend_so.c": nil,
|
||||
"defaults/cc/common/crtend.c": nil,
|
||||
"defaults/cc/common/crtbrand.c": nil,
|
||||
"external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil,
|
||||
|
||||
"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil,
|
||||
"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a": nil,
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"github.com/google/blueprint"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
"android/soong/rust/config"
|
||||
)
|
||||
|
||||
|
@ -118,6 +119,7 @@ type buildOutput struct {
|
|||
|
||||
func init() {
|
||||
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
|
||||
cc.TransformRlibstoStaticlib = TransformRlibstoStaticlib
|
||||
}
|
||||
|
||||
type transformProperties struct {
|
||||
|
@ -166,6 +168,48 @@ func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
|
|||
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
|
||||
}
|
||||
|
||||
func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
|
||||
outputFile android.WritablePath) android.Path {
|
||||
|
||||
var rustPathDeps PathDeps
|
||||
var rustFlags Flags
|
||||
|
||||
for _, rlibDep := range deps {
|
||||
rustPathDeps.RLibs = append(rustPathDeps.RLibs, RustLibrary{Path: rlibDep.LibPath, CrateName: rlibDep.CrateName})
|
||||
rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
|
||||
}
|
||||
|
||||
ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
|
||||
toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
|
||||
t := transformProperties{
|
||||
// Crate name can be a predefined value as this is a staticlib and
|
||||
// it does not need to be unique. The crate name is used for name
|
||||
// mangling, but it is mixed with the metadata for that purpose, which we
|
||||
// already set to the module name.
|
||||
crateName: "generated_rust_staticlib",
|
||||
is64Bit: toolchain.Is64Bit(),
|
||||
targetTriple: toolchain.RustTriple(),
|
||||
bootstrap: ccModule.Bootstrap(),
|
||||
inRecovery: ccModule.InRecovery(),
|
||||
inRamdisk: ccModule.InRamdisk(),
|
||||
inVendorRamdisk: ccModule.InVendorRamdisk(),
|
||||
|
||||
// crateType indicates what type of crate to build
|
||||
crateType: "staticlib",
|
||||
|
||||
// synthetic indicates whether this is an actual Rust module or not
|
||||
synthetic: true,
|
||||
}
|
||||
|
||||
rustFlags = CommonDefaultFlags(ctx, toolchain, rustFlags)
|
||||
rustFlags = CommonLibraryCompilerFlags(ctx, rustFlags)
|
||||
rustFlags.GlobalRustFlags = append(rustFlags.GlobalRustFlags, "-C lto=thin")
|
||||
|
||||
rustFlags.EmitXrefs = false
|
||||
|
||||
return transformSrctoCrate(ctx, mainSrc, rustPathDeps, rustFlags, outputFile, t).outputFile
|
||||
}
|
||||
|
||||
func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
|
||||
outputFile android.WritablePath) buildOutput {
|
||||
flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
|
||||
|
|
|
@ -46,6 +46,9 @@ func TestSourceProviderCollision(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCompilationOutputFiles(t *testing.T) {
|
||||
|
||||
// Note: Rustdoc output is produced for the PrimaryModule, so if the variant
|
||||
// order changes, then it may be produced for a different variant.
|
||||
ctx := testRust(t, `
|
||||
rust_library {
|
||||
name: "libfizz_buzz",
|
||||
|
@ -125,6 +128,16 @@ func TestCompilationOutputFiles(t *testing.T) {
|
|||
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/rustdoc.timestamp",
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "rust_ffi rlib",
|
||||
moduleName: "librust_ffi",
|
||||
variant: "android_arm64_armv8-a_rlib_rlib-std",
|
||||
expectedFiles: []string{
|
||||
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_rlib_rlib-std/librust_ffi.rlib",
|
||||
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_rlib_rlib-std/librust_ffi.rlib.clippy",
|
||||
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_rlib_rlib-std/meta_lic",
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "rust_ffi shared",
|
||||
moduleName: "librust_ffi",
|
||||
|
|
|
@ -47,7 +47,7 @@ func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps {
|
|||
|
||||
// no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
|
||||
if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() {
|
||||
ctx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}, rlibDepTag, ProfilerBuiltins)
|
||||
ctx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}, {Mutator: "link", Variation: ""}}, rlibDepTag, ProfilerBuiltins)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -120,13 +120,17 @@ func TestCCFuzzDepBundling(t *testing.T) {
|
|||
}
|
||||
cc_fuzz {
|
||||
name: "fuzz_static_libtest",
|
||||
static_rlibs: ["libtest_fuzzing"],
|
||||
}
|
||||
cc_fuzz {
|
||||
name: "fuzz_staticffi_libtest",
|
||||
static_libs: ["libtest_fuzzing"],
|
||||
}
|
||||
|
||||
`)
|
||||
|
||||
fuzz_shared_libtest := ctx.ModuleForTests("fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
|
||||
fuzz_static_libtest := ctx.ModuleForTests("fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
|
||||
fuzz_staticffi_libtest := ctx.ModuleForTests("fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
|
||||
|
||||
if !strings.Contains(fuzz_shared_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
|
||||
t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", fuzz_shared_libtest.FuzzSharedLibraries().String())
|
||||
|
@ -134,4 +138,7 @@ func TestCCFuzzDepBundling(t *testing.T) {
|
|||
if !strings.Contains(fuzz_static_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
|
||||
t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_static_libtest.FuzzSharedLibraries().String())
|
||||
}
|
||||
if !strings.Contains(fuzz_staticffi_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
|
||||
t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_rlib ('libcc_transitive_dep'): %#v", fuzz_staticffi_libtest.FuzzSharedLibraries().String())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,33 +22,45 @@ import (
|
|||
"android/soong/cc"
|
||||
)
|
||||
|
||||
// Test that cc modules can link against vendor_available rust_ffi_static libraries.
|
||||
// Test that cc modules can link against vendor_available rust_ffi_rlib/rust_ffi_static libraries.
|
||||
func TestVendorLinkage(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
cc_binary {
|
||||
name: "fizz_vendor",
|
||||
static_libs: ["libfoo_vendor"],
|
||||
name: "fizz_vendor_available",
|
||||
static_libs: ["libfoo_vendor_static"],
|
||||
static_rlibs: ["libfoo_vendor"],
|
||||
vendor_available: true,
|
||||
}
|
||||
cc_binary {
|
||||
name: "fizz_soc_specific",
|
||||
static_rlibs: ["libfoo_vendor"],
|
||||
soc_specific: true,
|
||||
}
|
||||
rust_ffi_static {
|
||||
rust_ffi_rlib {
|
||||
name: "libfoo_vendor",
|
||||
crate_name: "foo",
|
||||
srcs: ["foo.rs"],
|
||||
vendor_available: true,
|
||||
}
|
||||
rust_ffi_static {
|
||||
name: "libfoo_vendor_static",
|
||||
crate_name: "foo",
|
||||
srcs: ["foo.rs"],
|
||||
vendor_available: true,
|
||||
}
|
||||
`)
|
||||
|
||||
vendorBinary := ctx.ModuleForTests("fizz_vendor", "android_vendor_arm64_armv8-a").Module().(*cc.Module)
|
||||
vendorBinary := ctx.ModuleForTests("fizz_vendor_available", "android_vendor_arm64_armv8-a").Module().(*cc.Module)
|
||||
|
||||
if !android.InList("libfoo_vendor.vendor", vendorBinary.Properties.AndroidMkStaticLibs) {
|
||||
t.Errorf("vendorBinary should have a dependency on libfoo_vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs)
|
||||
if !android.InList("libfoo_vendor_static.vendor", vendorBinary.Properties.AndroidMkStaticLibs) {
|
||||
t.Errorf("vendorBinary should have a dependency on libfoo_vendor_static.vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs)
|
||||
}
|
||||
}
|
||||
|
||||
// Test that variants which use the vndk emit the appropriate cfg flag.
|
||||
func TestImageCfgFlag(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
rust_ffi_static {
|
||||
rust_ffi_shared {
|
||||
name: "libfoo",
|
||||
crate_name: "foo",
|
||||
srcs: ["foo.rs"],
|
||||
|
@ -57,7 +69,7 @@ func TestImageCfgFlag(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
|
||||
vendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_static").Rule("rustc")
|
||||
vendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Rule("rustc")
|
||||
|
||||
if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vndk'") {
|
||||
t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"])
|
||||
|
@ -69,7 +81,7 @@ func TestImageCfgFlag(t *testing.T) {
|
|||
t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
product := ctx.ModuleForTests("libfoo", "android_product_arm64_armv8-a_static").Rule("rustc")
|
||||
product := ctx.ModuleForTests("libfoo", "android_product_arm64_armv8-a_shared").Rule("rustc")
|
||||
if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vndk'") {
|
||||
t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"])
|
||||
}
|
||||
|
@ -80,7 +92,7 @@ func TestImageCfgFlag(t *testing.T) {
|
|||
t.Errorf("missing \"--cfg 'android_product'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
system := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Rule("rustc")
|
||||
system := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("rustc")
|
||||
if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vndk'") {
|
||||
t.Errorf("unexpected \"--cfg 'android_vndk'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"])
|
||||
}
|
||||
|
@ -93,27 +105,34 @@ func TestImageCfgFlag(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
// Test that cc modules can link against vendor_ramdisk_available rust_ffi_static libraries.
|
||||
// Test that cc modules can link against vendor_ramdisk_available rust_ffi_rlib and rust_ffi_static libraries.
|
||||
func TestVendorRamdiskLinkage(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
cc_library_static {
|
||||
cc_library_shared {
|
||||
name: "libcc_vendor_ramdisk",
|
||||
static_libs: ["libfoo_vendor_ramdisk"],
|
||||
static_rlibs: ["libfoo_vendor_ramdisk"],
|
||||
static_libs: ["libfoo_static_vendor_ramdisk"],
|
||||
system_shared_libs: [],
|
||||
vendor_ramdisk_available: true,
|
||||
}
|
||||
rust_ffi_static {
|
||||
rust_ffi_rlib {
|
||||
name: "libfoo_vendor_ramdisk",
|
||||
crate_name: "foo",
|
||||
srcs: ["foo.rs"],
|
||||
vendor_ramdisk_available: true,
|
||||
}
|
||||
rust_ffi_static {
|
||||
name: "libfoo_static_vendor_ramdisk",
|
||||
crate_name: "foo",
|
||||
srcs: ["foo.rs"],
|
||||
vendor_ramdisk_available: true,
|
||||
}
|
||||
`)
|
||||
|
||||
vendorRamdiskLibrary := ctx.ModuleForTests("libcc_vendor_ramdisk", "android_vendor_ramdisk_arm64_armv8-a_static").Module().(*cc.Module)
|
||||
vendorRamdiskLibrary := ctx.ModuleForTests("libcc_vendor_ramdisk", "android_vendor_ramdisk_arm64_armv8-a_shared").Module().(*cc.Module)
|
||||
|
||||
if !android.InList("libfoo_vendor_ramdisk.vendor_ramdisk", vendorRamdiskLibrary.Properties.AndroidMkStaticLibs) {
|
||||
t.Errorf("libcc_vendor_ramdisk should have a dependency on libfoo_vendor_ramdisk")
|
||||
if !android.InList("libfoo_static_vendor_ramdisk.vendor_ramdisk", vendorRamdiskLibrary.Properties.AndroidMkStaticLibs) {
|
||||
t.Errorf("libcc_vendor_ramdisk should have a dependency on libfoo_static_vendor_ramdisk")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
147
rust/library.go
147
rust/library.go
|
@ -37,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 combined rust_ffi_rlib factory
|
||||
android.RegisterModuleType("rust_ffi_static", RustFFIStaticRlibFactory)
|
||||
android.RegisterModuleType("rust_ffi_host_static", RustFFIStaticRlibHostFactory)
|
||||
}
|
||||
|
||||
type VariantLibraryProperties struct {
|
||||
|
@ -104,6 +109,8 @@ type libraryDecorator struct {
|
|||
includeDirs android.Paths
|
||||
sourceProvider SourceProvider
|
||||
|
||||
isFFI bool
|
||||
|
||||
// table-of-contents file for cdylib crates to optimize out relinking when possible
|
||||
tocFile android.OptionalPath
|
||||
}
|
||||
|
@ -143,6 +150,8 @@ type libraryInterface interface {
|
|||
BuildOnlyShared()
|
||||
|
||||
toc() android.OptionalPath
|
||||
|
||||
isFFILibrary() bool
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) nativeCoverage() bool {
|
||||
|
@ -250,7 +259,7 @@ func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) aut
|
|||
}
|
||||
|
||||
func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
|
||||
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
|
||||
|
@ -270,8 +279,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()
|
||||
|
@ -300,14 +309,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 {
|
||||
|
@ -317,7 +318,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()
|
||||
|
@ -340,14 +341,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 {
|
||||
|
@ -356,11 +349,51 @@ 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.BuildOnlyRlibStatic()
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
// rust_ffi_static produces a staticlib and an rlib variant
|
||||
func RustFFIStaticRlibFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostAndDeviceSupported)
|
||||
library.BuildOnlyRlibStatic()
|
||||
|
||||
library.isFFI = true
|
||||
return module.Init()
|
||||
}
|
||||
|
||||
// rust_ffi_static_host produces a staticlib and an rlib variant for the host
|
||||
func RustFFIStaticRlibHostFactory() android.Module {
|
||||
module, library := NewRustLibrary(android.HostSupported)
|
||||
library.BuildOnlyRlibStatic()
|
||||
|
||||
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.isFFI = true
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) BuildOnlyRust() {
|
||||
|
@ -384,11 +417,21 @@ func (library *libraryDecorator) BuildOnlyRlib() {
|
|||
library.MutatedProperties.BuildStatic = false
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) BuildOnlyRlibStatic() {
|
||||
library.MutatedProperties.BuildDylib = false
|
||||
library.MutatedProperties.BuildRlib = true
|
||||
library.MutatedProperties.BuildShared = false
|
||||
library.MutatedProperties.BuildStatic = true
|
||||
library.isFFI = true
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) BuildOnlyStatic() {
|
||||
library.MutatedProperties.BuildRlib = false
|
||||
library.MutatedProperties.BuildDylib = false
|
||||
library.MutatedProperties.BuildShared = false
|
||||
library.MutatedProperties.BuildStatic = true
|
||||
|
||||
library.isFFI = true
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) BuildOnlyShared() {
|
||||
|
@ -396,6 +439,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) {
|
||||
|
@ -480,10 +529,11 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) F
|
|||
|
||||
flags = CommonLibraryCompilerFlags(ctx, flags)
|
||||
|
||||
if library.shared() || library.static() {
|
||||
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() {
|
||||
if ctx.Darwin() {
|
||||
flags.LinkFlags = append(
|
||||
|
@ -509,6 +559,9 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
|
|||
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()
|
||||
|
@ -564,9 +617,10 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
|
|||
library.flagExporter.exportLinkObjects(deps.linkObjects...)
|
||||
}
|
||||
|
||||
if library.static() || library.shared() {
|
||||
// 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: library.includeDirs,
|
||||
IncludeDirs: android.FirstUniquePaths(library.includeDirs),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -681,6 +735,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.
|
||||
|
@ -720,6 +779,9 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) {
|
|||
// The source variant does not produce any library.
|
||||
// Disable the compilation steps.
|
||||
v.(*Module).compiler.SetDisabled()
|
||||
case "":
|
||||
// if there's an empty variant, alias it so it is the default variant
|
||||
mctx.AliasVariation("")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -744,20 +806,29 @@ 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...)
|
||||
// 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
|
||||
} 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 := 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,9 +37,10 @@ func TestLibraryVariants(t *testing.T) {
|
|||
}`)
|
||||
|
||||
// Test all variants are being built.
|
||||
libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static").Rule("rustc")
|
||||
libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
|
||||
libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
|
||||
libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static").Rule("rustc")
|
||||
libfooFFIRlib := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
|
||||
libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared").Rule("rustc")
|
||||
|
||||
rlibCrateType := "rlib"
|
||||
|
@ -62,6 +63,11 @@ func TestLibraryVariants(t *testing.T) {
|
|||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", staticCrateType, libfooStatic.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Test crate type for FFI rlibs is correct
|
||||
if !strings.Contains(libfooFFIRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) {
|
||||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooFFIRlib.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Test crate type for C shared libraries is correct.
|
||||
if !strings.Contains(libfooShared.Args["rustcFlags"], "crate-type="+sharedCrateType) {
|
||||
t.Errorf("missing crate-type for shared variant, expecting %#v, got rustcFlags: %#v", sharedCrateType, libfooShared.Args["rustcFlags"])
|
||||
|
@ -182,15 +188,20 @@ func TestSharedLibraryToc(t *testing.T) {
|
|||
|
||||
func TestStaticLibraryLinkage(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
rust_ffi_static {
|
||||
rust_ffi {
|
||||
name: "libfoo",
|
||||
srcs: ["foo.rs"],
|
||||
crate_name: "foo",
|
||||
}`)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_rlib-std")
|
||||
libfooStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
|
||||
|
||||
if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Static libstd rlib expected to be a dependency of Rust rlib libraries. Rlib deps are: %#v",
|
||||
libfoo.Module().(*Module).Properties.AndroidMkDylibs)
|
||||
}
|
||||
if !android.InList("libstd", libfooStatic.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Static libstd rlib expected to be a dependency of Rust static libraries. Rlib deps are: %#v",
|
||||
libfoo.Module().(*Module).Properties.AndroidMkDylibs)
|
||||
}
|
||||
|
@ -198,6 +209,12 @@ func TestStaticLibraryLinkage(t *testing.T) {
|
|||
|
||||
func TestNativeDependencyOfRlib(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
rust_ffi_rlib {
|
||||
name: "libffi_rlib",
|
||||
crate_name: "ffi_rlib",
|
||||
rlibs: ["librust_rlib"],
|
||||
srcs: ["foo.rs"],
|
||||
}
|
||||
rust_ffi_static {
|
||||
name: "libffi_static",
|
||||
crate_name: "ffi_static",
|
||||
|
@ -224,10 +241,12 @@ func TestNativeDependencyOfRlib(t *testing.T) {
|
|||
rustRlibRlibStd := ctx.ModuleForTests("librust_rlib", "android_arm64_armv8-a_rlib_rlib-std")
|
||||
rustRlibDylibStd := ctx.ModuleForTests("librust_rlib", "android_arm64_armv8-a_rlib_dylib-std")
|
||||
ffiStatic := ctx.ModuleForTests("libffi_static", "android_arm64_armv8-a_static")
|
||||
ffiRlib := ctx.ModuleForTests("libffi_rlib", "android_arm64_armv8-a_rlib_rlib-std")
|
||||
|
||||
modules := []android.TestingModule{
|
||||
rustRlibRlibStd,
|
||||
rustRlibDylibStd,
|
||||
ffiRlib,
|
||||
ffiStatic,
|
||||
}
|
||||
|
||||
|
@ -290,27 +309,28 @@ func TestAutoDeps(t *testing.T) {
|
|||
|
||||
libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std")
|
||||
libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib")
|
||||
libfooFFIRlib := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std")
|
||||
libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static")
|
||||
libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared")
|
||||
|
||||
for _, static := range []android.TestingModule{libfooRlib, libfooStatic} {
|
||||
for _, static := range []android.TestingModule{libfooRlib, libfooStatic, libfooFFIRlib} {
|
||||
if !android.InList("libbar.rlib-std", static.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("libbar not present as rlib dependency in static lib")
|
||||
t.Errorf("libbar not present as rlib dependency in static lib: %s", static.Module().Name())
|
||||
}
|
||||
if android.InList("libbar", static.Module().(*Module).Properties.AndroidMkDylibs) {
|
||||
t.Errorf("libbar present as dynamic dependency in static lib")
|
||||
t.Errorf("libbar present as dynamic dependency in static lib: %s", static.Module().Name())
|
||||
}
|
||||
}
|
||||
|
||||
for _, dyn := range []android.TestingModule{libfooDylib, libfooShared} {
|
||||
if !android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkDylibs) {
|
||||
t.Errorf("libbar not present as dynamic dependency in dynamic lib")
|
||||
t.Errorf("libbar not present as dynamic dependency in dynamic lib: %s", dyn.Module().Name())
|
||||
}
|
||||
if android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("libbar present as rlib dependency in dynamic lib")
|
||||
t.Errorf("libbar present as rlib dependency in dynamic lib: %s", dyn.Module().Name())
|
||||
}
|
||||
if !android.InList("librlib_only", dyn.Module().(*Module).Properties.AndroidMkRlibs) {
|
||||
t.Errorf("librlib_only should be selected by rustlibs as an rlib.")
|
||||
t.Errorf("librlib_only should be selected by rustlibs as an rlib: %s.", dyn.Module().Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -375,6 +395,7 @@ func TestLibstdLinkage(t *testing.T) {
|
|||
|
||||
libbarShared := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module().(*Module)
|
||||
libbarStatic := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Module().(*Module)
|
||||
libbarFFIRlib := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module)
|
||||
|
||||
// prefer_rlib works the same for both rust_library and rust_ffi, so a single check is sufficient here.
|
||||
libbarRlibStd := ctx.ModuleForTests("libbar.prefer_rlib", "android_arm64_armv8-a_shared").Module().(*Module)
|
||||
|
@ -398,6 +419,12 @@ func TestLibstdLinkage(t *testing.T) {
|
|||
if !android.InList("libfoo.rlib-std", libbarStatic.Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Device rust_ffi_static does not link dependent rustlib rlib-std variant")
|
||||
}
|
||||
if !android.InList("libstd", libbarFFIRlib.Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Device rust_ffi_rlib does not link libstd as an rlib")
|
||||
}
|
||||
if !android.InList("libfoo.rlib-std", libbarFFIRlib.Properties.AndroidMkRlibs) {
|
||||
t.Errorf("Device rust_ffi_rlib does not link dependent rustlib rlib-std variant")
|
||||
}
|
||||
if !android.InList("libstd", libbarRlibStd.Properties.AndroidMkRlibs) {
|
||||
t.Errorf("rust_ffi with prefer_rlib does not link libstd as an rlib")
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ func (procMacro *procMacroDecorator) compile(ctx ModuleContext, flags Flags, dep
|
|||
srcPath := crateRootPath(ctx, procMacro)
|
||||
ret := TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile)
|
||||
procMacro.baseCompiler.unstrippedOutputFile = outputFile
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
|
59
rust/rust.go
59
rust/rust.go
|
@ -158,6 +158,8 @@ type Module struct {
|
|||
sourceProvider SourceProvider
|
||||
subAndroidMkOnce map[SubAndroidMkProvider]bool
|
||||
|
||||
exportedLinkDirs []string
|
||||
|
||||
// Output file to be installed, may be stripped or unstripped.
|
||||
outputFile android.OptionalPath
|
||||
|
||||
|
@ -234,8 +236,8 @@ func (mod *Module) SelectedStl() string {
|
|||
|
||||
func (mod *Module) NonCcVariants() bool {
|
||||
if mod.compiler != nil {
|
||||
if _, ok := mod.compiler.(libraryInterface); ok {
|
||||
return false
|
||||
if library, ok := mod.compiler.(libraryInterface); ok {
|
||||
return library.buildRlib() || library.buildDylib()
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName()))
|
||||
|
@ -465,6 +467,11 @@ type PathDeps struct {
|
|||
linkDirs []string
|
||||
linkObjects []string
|
||||
|
||||
// exportedLinkDirs are exported linkDirs for direct rlib dependencies to
|
||||
// cc_library_static dependants of rlibs.
|
||||
// Track them separately from linkDirs so superfluous -L flags don't get emitted.
|
||||
exportedLinkDirs []string
|
||||
|
||||
// Used by bindgen modules which call clang
|
||||
depClangFlags []string
|
||||
depIncludePaths android.Paths
|
||||
|
@ -477,6 +484,9 @@ type PathDeps struct {
|
|||
// Paths to generated source files
|
||||
SrcDeps android.Paths
|
||||
srcProviderFiles android.Paths
|
||||
|
||||
// Used by Generated Libraries
|
||||
depExportedRlibs []cc.RustRlibDep
|
||||
}
|
||||
|
||||
type RustLibraries []RustLibrary
|
||||
|
@ -543,6 +553,10 @@ func (mod *Module) VndkVersion() string {
|
|||
return mod.Properties.VndkVersion
|
||||
}
|
||||
|
||||
func (mod *Module) ExportedCrateLinkDirs() []string {
|
||||
return mod.exportedLinkDirs
|
||||
}
|
||||
|
||||
func (mod *Module) PreventInstall() bool {
|
||||
return mod.Properties.PreventInstall
|
||||
}
|
||||
|
@ -657,15 +671,6 @@ func (mod *Module) UnstrippedOutputFile() android.Path {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (mod *Module) IncludeDirs() android.Paths {
|
||||
if mod.compiler != nil {
|
||||
if library, ok := mod.compiler.(*libraryDecorator); ok {
|
||||
return library.includeDirs
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("IncludeDirs called on non-library module: %q", mod.BaseModuleName()))
|
||||
}
|
||||
|
||||
func (mod *Module) SetStatic() {
|
||||
if mod.compiler != nil {
|
||||
if library, ok := mod.compiler.(libraryInterface); ok {
|
||||
|
@ -914,6 +919,10 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||
}
|
||||
|
||||
deps := mod.depsToPaths(ctx)
|
||||
// Export linkDirs for CC rust generatedlibs
|
||||
mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.exportedLinkDirs...)
|
||||
mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.linkDirs...)
|
||||
|
||||
flags := Flags{
|
||||
Toolchain: toolchain,
|
||||
}
|
||||
|
@ -991,6 +1000,9 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||
if ctx.Failed() {
|
||||
return
|
||||
}
|
||||
// Export your own directory as a linkDir
|
||||
mod.exportedLinkDirs = append(mod.exportedLinkDirs, linkPathFromFilePath(mod.OutputFile().Path()))
|
||||
|
||||
}
|
||||
|
||||
ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
|
||||
|
@ -1223,7 +1235,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
return
|
||||
}
|
||||
|
||||
if rustDep, ok := dep.(*Module); ok && !rustDep.CcLibraryInterface() {
|
||||
if rustDep, ok := dep.(*Module); ok && !rustDep.Static() && !rustDep.Shared() {
|
||||
//Handle Rust Modules
|
||||
makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName)
|
||||
|
||||
|
@ -1249,9 +1261,16 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName)
|
||||
mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName))
|
||||
|
||||
// rust_ffi rlibs may export include dirs, so collect those here.
|
||||
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
|
||||
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
|
||||
depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
|
||||
|
||||
case procMacroDepTag:
|
||||
directProcMacroDeps = append(directProcMacroDeps, rustDep)
|
||||
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
|
||||
// proc_macro link dirs need to be exported, so collect those here.
|
||||
depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
|
||||
|
||||
case sourceDepTag:
|
||||
if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
|
||||
|
@ -1281,12 +1300,12 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep)
|
||||
}
|
||||
|
||||
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
|
||||
//Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
|
||||
if depTag != procMacroDepTag {
|
||||
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
|
||||
depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
|
||||
depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
|
||||
depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...)
|
||||
depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
|
||||
}
|
||||
|
||||
if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
|
||||
|
@ -1296,6 +1315,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
lib.exportLinkDirs(linkDir)
|
||||
}
|
||||
}
|
||||
|
||||
if depTag == sourceDepTag {
|
||||
if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() {
|
||||
if _, ok := rustDep.sourceProvider.(*protobufDecorator); ok {
|
||||
|
@ -1560,6 +1580,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
}
|
||||
|
||||
rlibDepVariations := commonDepVariations
|
||||
rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""})
|
||||
|
||||
if lib, ok := mod.compiler.(libraryInterface); !ok || !lib.sysroot() {
|
||||
rlibDepVariations = append(rlibDepVariations,
|
||||
|
@ -1575,6 +1596,8 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
|
||||
// dylibs
|
||||
dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation})
|
||||
dylibDepVariations = append(dylibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""})
|
||||
|
||||
for _, lib := range deps.Dylibs {
|
||||
actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib)
|
||||
}
|
||||
|
@ -1594,7 +1617,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
// otherwise select the rlib variant.
|
||||
autoDepVariations := append(commonDepVariations,
|
||||
blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation})
|
||||
|
||||
autoDepVariations = append(autoDepVariations, blueprint.Variation{Mutator: "link", Variation: ""})
|
||||
if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) {
|
||||
actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib)
|
||||
|
||||
|
@ -1609,7 +1632,11 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
for _, lib := range deps.Rustlibs {
|
||||
srcProviderVariations := append(commonDepVariations,
|
||||
blueprint.Variation{Mutator: "rust_libraries", Variation: "source"})
|
||||
srcProviderVariations = append(srcProviderVariations, blueprint.Variation{Mutator: "link", Variation: ""})
|
||||
|
||||
// Only add rustlib dependencies if they're source providers themselves.
|
||||
// This is used to track which crate names need to be added to the source generated
|
||||
// in the rust_protobuf mod.rs.
|
||||
if actx.OtherModuleDependencyVariantExists(srcProviderVariations, lib) {
|
||||
actx.AddVariationDependencies(srcProviderVariations, sourceDepTag, lib)
|
||||
}
|
||||
|
@ -1621,7 +1648,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
if deps.Stdlibs != nil {
|
||||
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
|
||||
for _, lib := range deps.Stdlibs {
|
||||
actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...),
|
||||
actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}, {Mutator: "link", Variation: ""}}...),
|
||||
rlibDepTag, lib)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -150,15 +150,11 @@ func TestDepsTracking(t *testing.T) {
|
|||
host_supported: true,
|
||||
name: "cc_stubs_dep",
|
||||
}
|
||||
rust_ffi_host_static {
|
||||
cc_library_host_static {
|
||||
name: "libstatic",
|
||||
srcs: ["foo.rs"],
|
||||
crate_name: "static",
|
||||
}
|
||||
rust_ffi_host_static {
|
||||
cc_library_host_static {
|
||||
name: "libwholestatic",
|
||||
srcs: ["foo.rs"],
|
||||
crate_name: "wholestatic",
|
||||
}
|
||||
rust_ffi_host_shared {
|
||||
name: "libshared",
|
||||
|
@ -435,6 +431,105 @@ func TestRustAliases(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRustRlibs(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
rust_ffi_rlib {
|
||||
name: "libbar",
|
||||
crate_name: "bar",
|
||||
srcs: ["src/lib.rs"],
|
||||
export_include_dirs: ["bar_includes"]
|
||||
}
|
||||
|
||||
rust_ffi_rlib {
|
||||
name: "libfoo",
|
||||
crate_name: "foo",
|
||||
srcs: ["src/lib.rs"],
|
||||
export_include_dirs: ["foo_includes"]
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libcc_shared",
|
||||
srcs:["foo.c"],
|
||||
static_rlibs: ["libbar"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libcc_static",
|
||||
srcs:["foo.c"],
|
||||
static_rlibs: ["libfoo"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "ccBin",
|
||||
srcs:["foo.c"],
|
||||
static_rlibs: ["libbar"],
|
||||
static_libs: ["libcc_static"],
|
||||
}
|
||||
`)
|
||||
|
||||
libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_rlib_rlib-std").Rule("rustc")
|
||||
libcc_shared_rustc := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("rustc")
|
||||
libcc_shared_ld := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("ld")
|
||||
libcc_shared_cc := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("cc")
|
||||
ccbin_rustc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("rustc")
|
||||
ccbin_ld := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("ld")
|
||||
ccbin_cc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("cc")
|
||||
|
||||
if !strings.Contains(libbar.Args["rustcFlags"], "crate-type=rlib") {
|
||||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", "rlib", libbar.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Make sure there's a rustc command, and it's producing a staticlib
|
||||
if !strings.Contains(libcc_shared_rustc.Args["rustcFlags"], "crate-type=staticlib") {
|
||||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v",
|
||||
"staticlib", libcc_shared_rustc.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Make sure the static lib is included in the ld command
|
||||
if !strings.Contains(libcc_shared_ld.Args["libFlags"], "generated_rust_staticlib/liblibcc_shared_rust_staticlib.a") {
|
||||
t.Errorf("missing generated static library in linker step libFlags %#v, libFlags: %#v",
|
||||
"libcc_shared.generated_rust_staticlib.a", libcc_shared_ld.Args["libFlags"])
|
||||
}
|
||||
|
||||
// Make sure the static lib includes are in the cc command
|
||||
if !strings.Contains(libcc_shared_cc.Args["cFlags"], "-Ibar_includes") {
|
||||
t.Errorf("missing rlibs includes, expecting %#v, cFlags: %#v",
|
||||
"-Ibar_includes", libcc_shared_cc.Args["cFlags"])
|
||||
}
|
||||
|
||||
// Make sure there's a rustc command, and it's producing a staticlib
|
||||
if !strings.Contains(ccbin_rustc.Args["rustcFlags"], "crate-type=staticlib") {
|
||||
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", "staticlib", ccbin_rustc.Args["rustcFlags"])
|
||||
}
|
||||
|
||||
// Make sure the static lib is included in the cc command
|
||||
if !strings.Contains(ccbin_ld.Args["libFlags"], "generated_rust_staticlib/libccBin_rust_staticlib.a") {
|
||||
t.Errorf("missing generated static library in linker step libFlags, expecting %#v, libFlags: %#v",
|
||||
"ccBin.generated_rust_staticlib.a", ccbin_ld.Args["libFlags"])
|
||||
}
|
||||
|
||||
// Make sure the static lib includes are in the ld command
|
||||
if !strings.Contains(ccbin_cc.Args["cFlags"], "-Ibar_includes") {
|
||||
t.Errorf("missing rlibs includes, expecting %#v, cFlags: %#v",
|
||||
"-Ibar_includes", ccbin_cc.Args)
|
||||
}
|
||||
|
||||
// Make sure that direct dependencies and indirect dependencies are
|
||||
// propagating correctly to the generated rlib.
|
||||
if !strings.Contains(ccbin_rustc.Args["libFlags"], "--extern foo=") {
|
||||
t.Errorf("Missing indirect dependency libfoo when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
|
||||
}
|
||||
if !strings.Contains(ccbin_rustc.Args["libFlags"], "--extern bar=") {
|
||||
t.Errorf("Missing direct dependency libbar when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
|
||||
}
|
||||
|
||||
// Test indirect includes propagation
|
||||
if !strings.Contains(ccbin_cc.Args["cFlags"], "-Ifoo_includes") {
|
||||
t.Errorf("missing rlibs includes, expecting %#v, cFlags: %#v",
|
||||
"-Ifoo_includes", ccbin_cc.Args)
|
||||
}
|
||||
}
|
||||
|
||||
func assertString(t *testing.T, got, expected string) {
|
||||
t.Helper()
|
||||
if got != expected {
|
||||
|
|
|
@ -49,16 +49,28 @@ var PrepareForIntegrationTestWithRust = android.GroupFixturePreparers(
|
|||
func GatherRequiredDepsForTest() string {
|
||||
bp := `
|
||||
rust_prebuilt_library {
|
||||
name: "libstd",
|
||||
crate_name: "std",
|
||||
rlib: {
|
||||
srcs: ["libstd.rlib"],
|
||||
},
|
||||
dylib: {
|
||||
srcs: ["libstd.so"],
|
||||
},
|
||||
host_supported: true,
|
||||
sysroot: true,
|
||||
name: "libstd",
|
||||
crate_name: "std",
|
||||
rlib: {
|
||||
srcs: ["libstd/libstd.rlib"],
|
||||
},
|
||||
dylib: {
|
||||
srcs: ["libstd/libstd.so"],
|
||||
},
|
||||
host_supported: true,
|
||||
sysroot: true,
|
||||
}
|
||||
rust_prebuilt_library {
|
||||
name: "libcore.sysroot",
|
||||
crate_name: "core",
|
||||
rlib: {
|
||||
srcs: ["libcore/libcore.rlib"],
|
||||
},
|
||||
dylib: {
|
||||
srcs: ["libcore/libcore.so"],
|
||||
},
|
||||
host_supported: true,
|
||||
sysroot: true,
|
||||
}
|
||||
//////////////////////////////
|
||||
// Device module requirements
|
||||
|
@ -176,10 +188,12 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
|
|||
ctx.RegisterModuleType("rust_fuzz_host", RustFuzzHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi", RustFFIFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_static", RustFFIStaticFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_rlib", RustFFIRlibFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_static", RustFFIStaticRlibFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory)
|
||||
ctx.RegisterModuleType("rust_ffi_host_static", RustFFIStaticRlibHostFactory)
|
||||
ctx.RegisterModuleType("rust_proc_macro", ProcMacroFactory)
|
||||
ctx.RegisterModuleType("rust_protobuf", RustProtobufFactory)
|
||||
ctx.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)
|
||||
|
|
Loading…
Reference in a new issue