Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28ed8f4f authored by Ivan Lozano's avatar Ivan Lozano
Browse files

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
parent 08f670ab
Loading
Loading
Loading
Loading
+132 −88
Original line number Diff line number Diff line
@@ -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,8 +360,10 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl

	orderOnly = append(orderOnly, deps.SharedLibs...)

	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 {
		moduleGenDir := ctx.RustModule().compiler.cargoOutDir()
			var outputs android.WritablePaths

			for _, genSrc := range deps.SrcDeps {
@@ -340,16 +376,20 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl

			ctx.Build(pctx, android.BuildParams{
				Rule:        cp,
			Description: "cp " + moduleGenDir.Path().Rel(),
				Description: "cp " + t.cargoOutDir.Path().Rel(),
				Outputs:     outputs,
				Inputs:      deps.SrcDeps,
				Args: map[string]string{
				"outDir": moduleGenDir.String(),
					"outDir": t.cargoOutDir.String(),
				},
			})
			implicits = append(implicits, outputs.Paths()...)
		}
	}

	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{
@@ -370,6 +410,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
			// Declare the clippy build as an implicit dependency of the original crate.
			implicits = append(implicits, clippyFile)
		}
	}

	ctx.Build(pctx, android.BuildParams{
		Rule:        rustc,
@@ -389,6 +430,8 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
		},
	})

	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{
@@ -409,6 +452,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
			})
			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()), " "),
		},
	})

+51 −35
Original line number Diff line number Diff line
@@ -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 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, cfgsToFlags(cfgs)...)
	flags.RustdocFlags = append(flags.RustdocFlags, cfgsToFlags(cfgs)...)
	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")
	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)...)
	}

	flags.RustFlags = append(flags.RustFlags, compiler.cfgsToFlags()...)
	flags.RustdocFlags = append(flags.RustdocFlags, compiler.cfgsToFlags()...)
	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)
+18 −3
Original line number Diff line number Diff line
@@ -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)...)