rust: refactored transformSrctoCrate

Refactor transformSrctoCrate and the functions it calls to not rely
on rust.ModuleContext, preparing it to be callable from soong-cc
context to build a Rust staticlib.

This also refactors out common default flags used when building
libraries, again to prepare for building a Rust staticlib from
a soong-cc context.

Bug: 254469782
Test: m blueprint_tests && m
Change-Id: I678f6fee989c61bb15c340b9887e4d1934991907
This commit is contained in:
Ivan Lozano
2024-05-06 21:46:39 -04:00
parent 08f670ab4a
commit 28ed8f4f83
3 changed files with 200 additions and 125 deletions

View File

@@ -120,40 +120,74 @@ func init() {
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
}
type transformProperties struct {
crateName string
targetTriple string
is64Bit bool
bootstrap bool
inRecovery bool
inRamdisk bool
inVendorRamdisk bool
cargoOutDir android.OptionalPath
synthetic bool
crateType string
}
// Populates a standard transformProperties struct for Rust modules
func getTransformProperties(ctx ModuleContext, crateType string) transformProperties {
module := ctx.RustModule()
return transformProperties{
crateName: module.CrateName(),
is64Bit: ctx.toolchain().Is64Bit(),
targetTriple: ctx.toolchain().RustTriple(),
bootstrap: module.Bootstrap(),
inRecovery: module.InRecovery(),
inRamdisk: module.InRamdisk(),
inVendorRamdisk: module.InVendorRamdisk(),
cargoOutDir: module.compiler.cargoOutDir(),
// crateType indicates what type of crate to build
crateType: crateType,
// synthetic indicates whether this is an actual Rust module or not
synthetic: false,
}
}
func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
outputFile android.WritablePath) buildOutput {
flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "bin"))
}
func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
outputFile android.WritablePath) buildOutput {
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "rlib")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
}
func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
outputFile android.WritablePath) buildOutput {
flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "dylib")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "dylib"))
}
func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
outputFile android.WritablePath) buildOutput {
flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "staticlib"))
}
func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
outputFile android.WritablePath) buildOutput {
flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "cdylib"))
}
func TransformSrctoProcMacro(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
flags Flags, outputFile android.WritablePath) buildOutput {
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "proc-macro")
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "proc-macro"))
}
func rustLibsToPaths(libs RustLibraries) android.Paths {
@@ -185,18 +219,18 @@ func makeLibFlags(deps PathDeps) []string {
return libFlags
}
func rustEnvVars(ctx ModuleContext, deps PathDeps) []string {
func rustEnvVars(ctx android.ModuleContext, deps PathDeps, crateName string, cargoOutDir android.OptionalPath) []string {
var envVars []string
// libstd requires a specific environment variable to be set. This is
// not officially documented and may be removed in the future. See
// https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
if ctx.RustModule().CrateName() == "std" {
envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.RustModule().Arch().ArchType])
if crateName == "std" {
envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.Arch().ArchType])
}
if len(deps.SrcDeps) > 0 {
moduleGenDir := ctx.RustModule().compiler.cargoOutDir()
if len(deps.SrcDeps) > 0 && cargoOutDir.Valid() {
moduleGenDir := cargoOutDir
// We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this)
// assumes that paths are relative to the source file.
var outDirPrefix string
@@ -215,13 +249,15 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps) []string {
envVars = append(envVars, "ANDROID_RUST_VERSION="+config.GetRustVersion(ctx))
if ctx.RustModule().compiler.cargoEnvCompat() {
if bin, ok := ctx.RustModule().compiler.(*binaryDecorator); ok {
if rustMod, ok := ctx.Module().(*Module); ok && rustMod.compiler.cargoEnvCompat() {
// We only emulate cargo environment variables for 3p code, which is only ever built
// by defining a Rust module, so we only need to set these for true Rust modules.
if bin, ok := rustMod.compiler.(*binaryDecorator); ok {
envVars = append(envVars, "CARGO_BIN_NAME="+bin.getStem(ctx))
}
envVars = append(envVars, "CARGO_CRATE_NAME="+ctx.RustModule().CrateName())
envVars = append(envVars, "CARGO_PKG_NAME="+ctx.RustModule().CrateName())
pkgVersion := ctx.RustModule().compiler.cargoPkgVersion()
envVars = append(envVars, "CARGO_CRATE_NAME="+crateName)
envVars = append(envVars, "CARGO_PKG_NAME="+crateName)
pkgVersion := rustMod.compiler.cargoPkgVersion()
if pkgVersion != "" {
envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
@@ -245,8 +281,8 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps) []string {
return envVars
}
func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags,
outputFile android.WritablePath, crateType string) buildOutput {
func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps PathDeps, flags Flags,
outputFile android.WritablePath, t transformProperties) buildOutput {
var inputs android.Paths
var implicits android.Paths
@@ -256,23 +292,21 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
var earlyLinkFlags string
output.outputFile = outputFile
crateName := ctx.RustModule().CrateName()
targetTriple := ctx.toolchain().RustTriple()
envVars := rustEnvVars(ctx, deps)
envVars := rustEnvVars(ctx, deps, t.crateName, t.cargoOutDir)
inputs = append(inputs, main)
// Collect rustc flags
rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
rustcFlags = append(rustcFlags, flags.RustFlags...)
rustcFlags = append(rustcFlags, "--crate-type="+crateType)
if crateName != "" {
rustcFlags = append(rustcFlags, "--crate-name="+crateName)
rustcFlags = append(rustcFlags, "--crate-type="+t.crateType)
if t.crateName != "" {
rustcFlags = append(rustcFlags, "--crate-name="+t.crateName)
}
if targetTriple != "" {
rustcFlags = append(rustcFlags, "--target="+targetTriple)
linkFlags = append(linkFlags, "-target "+targetTriple)
if t.targetTriple != "" {
rustcFlags = append(rustcFlags, "--target="+t.targetTriple)
linkFlags = append(linkFlags, "-target "+t.targetTriple)
}
// Suppress an implicit sysroot
@@ -302,9 +336,9 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
linkFlags = append(linkFlags, flags.LinkFlags...)
// Check if this module needs to use the bootstrap linker
if ctx.RustModule().Bootstrap() && !ctx.RustModule().InRecovery() && !ctx.RustModule().InRamdisk() && !ctx.RustModule().InVendorRamdisk() {
if t.bootstrap && !t.inRecovery && !t.inRamdisk && !t.inVendorRamdisk {
dynamicLinker := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker"
if ctx.toolchain().Is64Bit() {
if t.is64Bit {
dynamicLinker += "64"
}
linkFlags = append(linkFlags, dynamicLinker)
@@ -326,49 +360,56 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
orderOnly = append(orderOnly, deps.SharedLibs...)
if len(deps.SrcDeps) > 0 {
moduleGenDir := ctx.RustModule().compiler.cargoOutDir()
var outputs android.WritablePaths
if !t.synthetic {
// Only worry about OUT_DIR for actual Rust modules.
// Libraries built from cc use generated source, and do not utilize OUT_DIR.
if len(deps.SrcDeps) > 0 {
var outputs android.WritablePaths
for _, genSrc := range deps.SrcDeps {
if android.SuffixInList(outputs.Strings(), genSubDir+genSrc.Base()) {
ctx.PropertyErrorf("srcs",
"multiple source providers generate the same filename output: "+genSrc.Base())
for _, genSrc := range deps.SrcDeps {
if android.SuffixInList(outputs.Strings(), genSubDir+genSrc.Base()) {
ctx.PropertyErrorf("srcs",
"multiple source providers generate the same filename output: "+genSrc.Base())
}
outputs = append(outputs, android.PathForModuleOut(ctx, genSubDir+genSrc.Base()))
}
outputs = append(outputs, android.PathForModuleOut(ctx, genSubDir+genSrc.Base()))
}
ctx.Build(pctx, android.BuildParams{
Rule: cp,
Description: "cp " + moduleGenDir.Path().Rel(),
Outputs: outputs,
Inputs: deps.SrcDeps,
Args: map[string]string{
"outDir": moduleGenDir.String(),
},
})
implicits = append(implicits, outputs.Paths()...)
ctx.Build(pctx, android.BuildParams{
Rule: cp,
Description: "cp " + t.cargoOutDir.Path().Rel(),
Outputs: outputs,
Inputs: deps.SrcDeps,
Args: map[string]string{
"outDir": t.cargoOutDir.String(),
},
})
implicits = append(implicits, outputs.Paths()...)
}
}
if flags.Clippy {
clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
ctx.Build(pctx, android.BuildParams{
Rule: clippyDriver,
Description: "clippy " + main.Rel(),
Output: clippyFile,
ImplicitOutputs: nil,
Inputs: inputs,
Implicits: implicits,
OrderOnly: orderOnly,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
"libFlags": strings.Join(libFlags, " "),
"clippyFlags": strings.Join(flags.ClippyFlags, " "),
"envVars": strings.Join(envVars, " "),
},
})
// Declare the clippy build as an implicit dependency of the original crate.
implicits = append(implicits, clippyFile)
if !t.synthetic {
// Only worry about clippy for actual Rust modules.
// Libraries built from cc use generated source, and don't need to run clippy.
if flags.Clippy {
clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
ctx.Build(pctx, android.BuildParams{
Rule: clippyDriver,
Description: "clippy " + main.Rel(),
Output: clippyFile,
ImplicitOutputs: nil,
Inputs: inputs,
Implicits: implicits,
OrderOnly: orderOnly,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
"libFlags": strings.Join(libFlags, " "),
"clippyFlags": strings.Join(flags.ClippyFlags, " "),
"envVars": strings.Join(envVars, " "),
},
})
// Declare the clippy build as an implicit dependency of the original crate.
implicits = append(implicits, clippyFile)
}
}
ctx.Build(pctx, android.BuildParams{
@@ -389,25 +430,28 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
},
})
if flags.EmitXrefs {
kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
ctx.Build(pctx, android.BuildParams{
Rule: kytheExtract,
Description: "Xref Rust extractor " + main.Rel(),
Output: kytheFile,
Inputs: inputs,
Implicits: implicits,
OrderOnly: orderOnly,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
"linkFlags": strings.Join(linkFlags, " "),
"libFlags": strings.Join(libFlags, " "),
"crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
"crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
"envVars": strings.Join(envVars, " "),
},
})
output.kytheFile = kytheFile
if !t.synthetic {
// Only emit xrefs for true Rust modules.
if flags.EmitXrefs {
kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
ctx.Build(pctx, android.BuildParams{
Rule: kytheExtract,
Description: "Xref Rust extractor " + main.Rel(),
Output: kytheFile,
Inputs: inputs,
Implicits: implicits,
OrderOnly: orderOnly,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
"linkFlags": strings.Join(linkFlags, " "),
"libFlags": strings.Join(libFlags, " "),
"crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
"crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
"envVars": strings.Join(envVars, " "),
},
})
output.kytheFile = kytheFile
}
}
return output
}
@@ -457,7 +501,7 @@ func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps,
Args: map[string]string{
"rustdocFlags": strings.Join(rustdocFlags, " "),
"outDir": docDir.String(),
"envVars": strings.Join(rustEnvVars(ctx, deps), " "),
"envVars": strings.Join(rustEnvVars(ctx, deps, crateName, ctx.RustModule().compiler.cargoOutDir()), " "),
},
})

View File

@@ -322,9 +322,9 @@ func (compiler *baseCompiler) compilerProps() []interface{} {
return []interface{}{&compiler.Properties}
}
func (compiler *baseCompiler) cfgsToFlags() []string {
func cfgsToFlags(cfgs []string) []string {
flags := []string{}
for _, cfg := range compiler.Properties.Cfgs {
for _, cfg := range cfgs {
flags = append(flags, "--cfg '"+cfg+"'")
}
@@ -351,23 +351,61 @@ func (compiler *baseCompiler) featureFlags(ctx ModuleContext, flags Flags) Flags
return flags
}
func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags {
if ctx.RustModule().InVendorOrProduct() {
compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_vndk")
if ctx.RustModule().InVendor() {
compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_vendor")
} else if ctx.RustModule().InProduct() {
compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_product")
func CommonDefaultCfgFlags(flags Flags, vendor bool, product bool) Flags {
var cfgs []string
if vendor || product {
cfgs = append(cfgs, "android_vndk")
if vendor {
cfgs = append(cfgs, "android_vendor")
} else if product {
cfgs = append(cfgs, "android_product")
}
}
flags.RustFlags = append(flags.RustFlags, compiler.cfgsToFlags()...)
flags.RustdocFlags = append(flags.RustdocFlags, compiler.cfgsToFlags()...)
flags.RustFlags = append(flags.RustFlags, cfgsToFlags(cfgs)...)
flags.RustdocFlags = append(flags.RustdocFlags, cfgsToFlags(cfgs)...)
return flags
}
func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags {
flags = CommonDefaultCfgFlags(flags, ctx.RustModule().InVendor(), ctx.RustModule().InProduct())
flags.RustFlags = append(flags.RustFlags, cfgsToFlags(compiler.Properties.Cfgs)...)
flags.RustdocFlags = append(flags.RustdocFlags, cfgsToFlags(compiler.Properties.Cfgs)...)
return flags
}
func CommonDefaultFlags(ctx android.ModuleContext, toolchain config.Toolchain, flags Flags) Flags {
flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
flags.GlobalRustFlags = append(flags.GlobalRustFlags, toolchain.ToolchainRustFlags())
flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, toolchain.ToolchainLinkFlags())
flags.EmitXrefs = ctx.Config().EmitXrefRules()
if ctx.Host() && !ctx.Windows() {
flags.LinkFlags = append(flags.LinkFlags, cc.RpathFlags(ctx)...)
}
if ctx.Os() == android.Linux {
// Add -lc, -lrt, -ldl, -lpthread, -lm and -lgcc_s to glibc builds to match
// the default behavior of device builds.
flags.LinkFlags = append(flags.LinkFlags, config.LinuxHostGlobalLinkFlags...)
} else if ctx.Os() == android.Darwin {
// Add -lc, -ldl, -lpthread and -lm to glibc darwin builds to match the default
// behavior of device builds.
flags.LinkFlags = append(flags.LinkFlags,
"-lc",
"-ldl",
"-lpthread",
"-lm",
)
}
return flags
}
func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = CommonDefaultFlags(ctx, ctx.toolchain(), flags)
lintFlags, err := config.RustcLintsForDir(ctx.ModuleDir(), compiler.Properties.Lints)
if err != nil {
ctx.PropertyErrorf("lints", err.Error())
@@ -396,29 +434,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flag
flags.RustFlags = append(flags.RustFlags, "--edition="+compiler.edition())
flags.RustdocFlags = append(flags.RustdocFlags, "--edition="+compiler.edition())
flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())
flags.EmitXrefs = ctx.Config().EmitXrefRules()
if ctx.Host() && !ctx.Windows() {
flags.LinkFlags = append(flags.LinkFlags, cc.RpathFlags(ctx)...)
}
if ctx.Os() == android.Linux {
// Add -lc, -lrt, -ldl, -lpthread, -lm and -lgcc_s to glibc builds to match
// the default behavior of device builds.
flags.LinkFlags = append(flags.LinkFlags, config.LinuxHostGlobalLinkFlags...)
} else if ctx.Os() == android.Darwin {
// Add -lc, -ldl, -lpthread and -lm to glibc darwin builds to match the default
// behavior of device builds.
flags.LinkFlags = append(flags.LinkFlags,
"-lc",
"-ldl",
"-lpthread",
"-lm",
)
}
return flags
}
@@ -568,11 +584,11 @@ func (compiler *baseCompiler) installTestData(ctx ModuleContext, data []android.
compiler.installDeps = append(compiler.installDeps, installedData...)
}
func (compiler *baseCompiler) getStem(ctx ModuleContext) string {
func (compiler *baseCompiler) getStem(ctx android.ModuleContext) string {
return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix)
}
func (compiler *baseCompiler) getStemWithoutSuffix(ctx BaseModuleContext) string {
func (compiler *baseCompiler) getStemWithoutSuffix(ctx android.BaseModuleContext) string {
stem := ctx.ModuleName()
if String(compiler.Properties.Stem) != "" {
stem = String(compiler.Properties.Stem)

View File

@@ -446,8 +446,15 @@ func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string {
return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
}
// Library cfg flags common to all variants
func CommonLibraryCfgFlags(ctx android.ModuleContext, flags Flags) Flags {
return flags
}
func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags {
flags = library.baseCompiler.cfgFlags(ctx, flags)
flags = CommonLibraryCfgFlags(ctx, flags)
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
@@ -455,8 +462,15 @@ func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags
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()...)
flags.RustFlags = append(flags.RustFlags, cfgsToFlags(library.baseCompiler.Properties.Cfgs)...)
flags.RustdocFlags = append(flags.RustdocFlags, cfgsToFlags(library.baseCompiler.Properties.Cfgs)...)
return flags
}
// Common flags applied to all libraries irrespective of properties or variant should be included here
func CommonLibraryCompilerFlags(ctx android.ModuleContext, flags Flags) Flags {
flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName())
return flags
}
@@ -464,7 +478,8 @@ func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags
func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = library.baseCompiler.compilerFlags(ctx, flags)
flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName())
flags = CommonLibraryCompilerFlags(ctx, flags)
if library.shared() || library.static() {
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)...)