diff options
Diffstat (limited to 'rust/compiler.go')
-rw-r--r-- | rust/compiler.go | 170 |
1 files changed, 146 insertions, 24 deletions
diff --git a/rust/compiler.go b/rust/compiler.go index 06ae12f79..03fdf2b7a 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -16,6 +16,7 @@ package rust import ( "android/soong/cc" + "errors" "fmt" "path/filepath" "strings" @@ -34,6 +35,50 @@ const ( DylibLinkage ) +type compiler interface { + initialize(ctx ModuleContext) + compilerFlags(ctx ModuleContext, flags Flags) Flags + cfgFlags(ctx ModuleContext, flags Flags) Flags + featureFlags(ctx ModuleContext, flags Flags) Flags + compilerProps() []interface{} + compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput + compilerDeps(ctx DepsContext, deps Deps) Deps + crateName() string + edition() string + features() []string + rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath + + // Output directory in which source-generated code from dependencies is + // copied. This is equivalent to Cargo's OUT_DIR variable. + cargoOutDir() android.OptionalPath + + // cargoPkgVersion returns the value of the Cargo_pkg_version property. + cargoPkgVersion() string + + // cargoEnvCompat returns whether Cargo environment variables should be used. + cargoEnvCompat() bool + + inData() bool + install(ctx ModuleContext) + relativeInstallPath() string + everInstallable() bool + + nativeCoverage() bool + + Disabled() bool + SetDisabled() + + stdLinkage(ctx *depsContext) RustLinkage + noStdlibs() bool + + unstrippedOutputFilePath() android.Path + strippedOutputFilePath() android.OptionalPath + + checkedCrateRootPath() (android.Path, error) + + Aliases() map[string]string +} + func (compiler *baseCompiler) edition() string { return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) } @@ -73,6 +118,15 @@ type BaseCompilerProperties struct { // If no source file is defined, a single generated source module can be defined to be used as the main source. Srcs []string `android:"path,arch_variant"` + // Entry point that is passed to rustc to begin the compilation. E.g. main.rs or lib.rs. + // When this property is set, + // * sandboxing is enabled for this module, and + // * the srcs attribute is interpreted as a list of all source files potentially + // used in compilation, including the entrypoint, and + // * compile_data can be used to add additional files used in compilation that + // not directly used as source files. + Crate_root *string `android:"path,arch_variant"` + // name of the lint set that should be used to validate this module. // // Possible values are "default" (for using a sensible set of lints @@ -88,13 +142,17 @@ type BaseCompilerProperties struct { // flags to pass to the linker Ld_flags []string `android:"arch_variant"` + // Rust crate dependencies to rename. Each entry should be a string of the form "dependencyname:alias". + // + // "dependencyname" here should be the name of the crate, not the Android module. This is + // equivalent to writing `alias = { package = "dependencyname" }` in a `Cargo.toml`. + Aliases []string + // list of rust rlib crate dependencies Rlibs []string `android:"arch_variant"` - // list of rust dylib crate dependencies - Dylibs []string `android:"arch_variant"` - - // list of rust automatic crate dependencies + // list of rust automatic crate dependencies. + // Rustlibs linkage is rlib for host targets and dylib for device targets. Rustlibs []string `android:"arch_variant"` // list of rust proc_macro crate dependencies @@ -153,7 +211,7 @@ type BaseCompilerProperties struct { Relative_install_path *string `android:"arch_variant"` // whether to suppress inclusion of standard crates - defaults to false - No_stdlibs *bool + No_stdlibs *bool `android:"arch_variant"` // Change the rustlibs linkage to select rlib linkage by default for device targets. // Also link libstd as an rlib as well on device targets. @@ -189,6 +247,8 @@ type baseCompiler struct { distFile android.OptionalPath + installDeps android.InstallPaths + // unstripped output file. unstrippedOutputFile android.Path @@ -197,7 +257,16 @@ type baseCompiler struct { // If a crate has a source-generated dependency, a copy of the source file // will be available in cargoOutDir (equivalent to Cargo OUT_DIR). - cargoOutDir android.ModuleOutPath + // This is stored internally because it may not be available during + // singleton-generation passes like rustdoc/rust_project.json, but should + // be stashed during initial generation. + cachedCargoOutDir android.ModuleOutPath + // Calculated crate root cached internally because ModuleContext is not + // available to singleton targets like rustdoc/rust_project.json + cachedCrateRootPath android.Path + // If cachedCrateRootPath is nil after initialization, this will contain + // an explanation of why + cachedCrateRootError error } func (compiler *baseCompiler) Disabled() bool { @@ -220,6 +289,18 @@ func (compiler *baseCompiler) preferRlib() bool { return Bool(compiler.Properties.Prefer_rlib) } +func (compiler *baseCompiler) Aliases() map[string]string { + aliases := map[string]string{} + for _, entry := range compiler.Properties.Aliases { + dep, alias, found := strings.Cut(entry, ":") + if !found { + panic(fmt.Errorf("invalid aliases entry %q missing ':'", entry)) + } + aliases[dep] = alias + } + return aliases +} + func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage { // For devices, we always link stdlibs in as dylibs by default. if compiler.preferRlib() { @@ -250,9 +331,13 @@ func (compiler *baseCompiler) cfgsToFlags() []string { return flags } +func (compiler *baseCompiler) features() []string { + return compiler.Properties.Features +} + func (compiler *baseCompiler) featuresToFlags() []string { flags := []string{} - for _, feature := range compiler.Properties.Features { + for _, feature := range compiler.features() { flags = append(flags, "--cfg 'feature=\""+feature+"\"'") } @@ -267,7 +352,7 @@ func (compiler *baseCompiler) featureFlags(ctx ModuleContext, flags Flags) Flags } func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags { - if ctx.RustModule().UseVndk() { + 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") @@ -320,6 +405,20 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flag 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 } @@ -334,18 +433,24 @@ func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags, } func (compiler *baseCompiler) initialize(ctx ModuleContext) { - compiler.cargoOutDir = android.PathForModuleOut(ctx, genSubDir) + compiler.cachedCargoOutDir = android.PathForModuleOut(ctx, genSubDir) + if compiler.Properties.Crate_root == nil { + compiler.cachedCrateRootPath, compiler.cachedCrateRootError = srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs) + } else { + compiler.cachedCrateRootPath = android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root) + compiler.cachedCrateRootError = nil + } } -func (compiler *baseCompiler) CargoOutDir() android.OptionalPath { - return android.OptionalPathForPath(compiler.cargoOutDir) +func (compiler *baseCompiler) cargoOutDir() android.OptionalPath { + return android.OptionalPathForPath(compiler.cachedCargoOutDir) } -func (compiler *baseCompiler) CargoEnvCompat() bool { +func (compiler *baseCompiler) cargoEnvCompat() bool { return Bool(compiler.Properties.Cargo_env_compat) } -func (compiler *baseCompiler) CargoPkgVersion() string { +func (compiler *baseCompiler) cargoPkgVersion() string { return String(compiler.Properties.Cargo_pkg_version) } @@ -359,7 +464,6 @@ func (compiler *baseCompiler) strippedOutputFilePath() android.OptionalPath { func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...) - deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...) deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...) deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...) deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...) @@ -436,7 +540,7 @@ func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath dir = filepath.Join(dir, ctx.Arch().ArchType.String()) } - if compiler.location == InstallInData && ctx.RustModule().UseVndk() { + if compiler.location == InstallInData && ctx.RustModule().InVendorOrProduct() { if ctx.RustModule().InProduct() { dir = filepath.Join(dir, "product") } else if ctx.RustModule().InVendor() { @@ -456,7 +560,12 @@ func (compiler *baseCompiler) nativeCoverage() bool { func (compiler *baseCompiler) install(ctx ModuleContext) { path := ctx.RustModule().OutputFile() - compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path()) + compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path(), compiler.installDeps...) +} + +func (compiler *baseCompiler) installTestData(ctx ModuleContext, data []android.DataPath) { + installedData := ctx.InstallTestData(compiler.installDir(ctx), data) + compiler.installDeps = append(compiler.installDeps, installedData...) } func (compiler *baseCompiler) getStem(ctx ModuleContext) string { @@ -476,12 +585,20 @@ func (compiler *baseCompiler) relativeInstallPath() string { return String(compiler.Properties.Relative_install_path) } -// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs. -func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, android.Paths) { - if len(srcs) == 0 { - ctx.PropertyErrorf("srcs", "srcs must not be empty") +func (compiler *baseCompiler) checkedCrateRootPath() (android.Path, error) { + return compiler.cachedCrateRootPath, compiler.cachedCrateRootError +} + +func crateRootPath(ctx ModuleContext, compiler compiler) android.Path { + root, err := compiler.checkedCrateRootPath() + if err != nil { + ctx.PropertyErrorf("srcs", err.Error()) } + return root +} +// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs. +func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, error) { // The srcs can contain strings with prefix ":". // They are dependent modules of this module, with android.SourceDepTag. // They are not the main source file compiled by rustc. @@ -494,17 +611,22 @@ func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, andr } } if numSrcs > 1 { - ctx.PropertyErrorf("srcs", incorrectSourcesError) + return nil, errors.New(incorrectSourcesError) } // If a main source file is not provided we expect only a single SourceProvider module to be defined // within srcs, with the expectation that the first source it provides is the entry point. if srcIndex != 0 { - ctx.PropertyErrorf("srcs", "main source file must be the first in srcs") + return nil, errors.New("main source file must be the first in srcs") } else if numSrcs > 1 { - ctx.PropertyErrorf("srcs", "only a single generated source module can be defined without a main source file.") + return nil, errors.New("only a single generated source module can be defined without a main source file.") } + // TODO: b/297264540 - once all modules are sandboxed, we need to select the proper + // entry point file from Srcs rather than taking the first one paths := android.PathsForModuleSrc(ctx, srcs) - return paths[srcIndex], paths[1:] + if len(paths) == 0 { + return nil, errors.New("srcs must not be empty") + } + return paths[srcIndex], nil } |