diff options
Diffstat (limited to 'rust/compiler.go')
-rw-r--r-- | rust/compiler.go | 276 |
1 files changed, 216 insertions, 60 deletions
diff --git a/rust/compiler.go b/rust/compiler.go index 4593165f4..1598ebf9a 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -24,18 +24,26 @@ import ( "android/soong/rust/config" ) -func getEdition(compiler *baseCompiler) string { - return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) -} +type RustLinkage int + +const ( + DefaultLinkage RustLinkage = iota + RlibLinkage + DylibLinkage +) -func getDenyWarnings(compiler *baseCompiler) bool { - return BoolDefault(compiler.Properties.Deny_warnings, config.DefaultDenyWarnings) +func (compiler *baseCompiler) edition() string { + return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) } func (compiler *baseCompiler) setNoStdlibs() { compiler.Properties.No_stdlibs = proptools.BoolPtr(true) } +func (compiler *baseCompiler) disableLints() { + compiler.Properties.Lints = proptools.StringPtr("none") +} + func NewBaseCompiler(dir, dir64 string, location installLocation) *baseCompiler { return &baseCompiler{ Properties: BaseCompilerProperties{}, @@ -50,17 +58,29 @@ type installLocation int const ( InstallInSystem installLocation = 0 InstallInData = iota + + incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\"" + genSubDir = "out/" ) type BaseCompilerProperties struct { - // whether to pass "-D warnings" to rustc. Defaults to true. - Deny_warnings *bool + // path to the source file that is the main entry point of the program (e.g. main.rs or lib.rs) + Srcs []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 + // depending on the module's location), "android" (for the strictest + // lint set that applies to all Android platform code), "vendor" (for + // a relaxed set) and "none" (for ignoring all lint warnings and + // errors). The default value is "default". + Lints *string - // flags to pass to rustc - Flags []string `android:"path,arch_variant"` + // flags to pass to rustc. To enable configuration options or features, use the "cfgs" or "features" properties. + Flags []string `android:"arch_variant"` // flags to pass to the linker - Ld_flags []string `android:"path,arch_variant"` + Ld_flags []string `android:"arch_variant"` // list of rust rlib crate dependencies Rlibs []string `android:"arch_variant"` @@ -68,21 +88,46 @@ type BaseCompilerProperties struct { // list of rust dylib crate dependencies Dylibs []string `android:"arch_variant"` + // list of rust automatic crate dependencies + Rustlibs []string `android:"arch_variant"` + // list of rust proc_macro crate dependencies Proc_macros []string `android:"arch_variant"` // list of C shared library dependencies Shared_libs []string `android:"arch_variant"` - // list of C static library dependencies + // list of C static library dependencies. These dependencies do not normally propagate to dependents + // and may need to be redeclared. See whole_static_libs for bundling static dependencies into a library. Static_libs []string `android:"arch_variant"` - // crate name, required for libraries. This must be the expected extern crate name used in source + // Similar to static_libs, but will bundle the static library dependency into a library. This is helpful + // to avoid having to redeclare the dependency for dependents of this library, but in some cases may also + // result in bloat if multiple dependencies all include the same static library whole. + // + // The common use case for this is when the static library is unlikely to be a dependency of other modules to avoid + // having to redeclare the static library dependency for every dependent module. + // If you are not sure what to, for rust_library modules most static dependencies should go in static_libraries, + // and for rust_ffi modules most static dependencies should go into whole_static_libraries. + // + // For rust_ffi static variants, these libraries will be included in the resulting static library archive. + // + // For rust_library rlib variants, these libraries will be bundled into the resulting rlib library. This will + // include all of the static libraries symbols in any dylibs or binaries which use this rlib as well. + Whole_static_libs []string `android:"arch_variant"` + + // crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider + // modules which create library variants (rust_bindgen). This must be the expected extern crate name used in + // source, and is required to conform to an enforced format matching library output files (if the output file is + // lib<someName><suffix>, the crate_name property must be <someName>). Crate_name string `android:"arch_variant"` // list of features to enable for this crate Features []string `android:"arch_variant"` + // list of configuration options to enable for this crate. To enable features, use the "features" property. + Cfgs []string `android:"arch_variant"` + // specific rust edition that should be used if the default version is not desired Edition *string `android:"arch_variant"` @@ -97,19 +142,21 @@ type BaseCompilerProperties struct { // whether to suppress inclusion of standard crates - defaults to false No_stdlibs *bool + + // Change the rustlibs linkage to select rlib linkage by default for device targets. + // Also link libstd as an rlib as well on device targets. + // Note: This is the default behavior for host targets. + // + // This is primarily meant for rust_binary and rust_ffi modules where the default + // linkage of libstd might need to be overridden in some use cases. This should + // generally be avoided with other module types since it may cause collisions at + // linkage if all dependencies of the root binary module do not link against libstd\ + // the same way. + Prefer_rlib *bool `android:"arch_variant"` } type baseCompiler struct { - Properties BaseCompilerProperties - pathDeps android.Paths - rustFlagsDeps android.Paths - linkFlagsDeps android.Paths - flags string - linkFlags string - depFlags []string - linkDirs []string - edition string - src android.Path //rustc takes a single src file + Properties BaseCompilerProperties // Install related dir string @@ -118,6 +165,42 @@ type baseCompiler struct { relative string path android.InstallPath location installLocation + sanitize *sanitize + + distFile android.OptionalPath + // Stripped output file. If Valid(), this file will be installed instead of outputFile. + strippedOutputFile android.OptionalPath + + // 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 +} + +func (compiler *baseCompiler) Disabled() bool { + return false +} + +func (compiler *baseCompiler) SetDisabled() { + panic("baseCompiler does not implement SetDisabled()") +} + +func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath { + panic("baseCompiler does not implement coverageOutputZipPath()") +} + +func (compiler *baseCompiler) preferRlib() bool { + return Bool(compiler.Properties.Prefer_rlib) +} + +func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage { + // For devices, we always link stdlibs in as dylibs by default. + if compiler.preferRlib() { + return RlibLinkage + } else if ctx.Device() { + return DylibLinkage + } else { + return RlibLinkage + } } var _ compiler = (*baseCompiler)(nil) @@ -130,9 +213,17 @@ func (compiler *baseCompiler) compilerProps() []interface{} { return []interface{}{&compiler.Properties} } -func (compiler *baseCompiler) featuresToFlags(features []string) []string { +func (compiler *baseCompiler) cfgsToFlags() []string { flags := []string{} - for _, feature := range features { + for _, cfg := range compiler.Properties.Cfgs { + flags = append(flags, "--cfg '"+cfg+"'") + } + return flags +} + +func (compiler *baseCompiler) featuresToFlags() []string { + flags := []string{} + for _, feature := range compiler.Properties.Features { flags = append(flags, "--cfg 'feature=\""+feature+"\"'") } return flags @@ -140,21 +231,27 @@ func (compiler *baseCompiler) featuresToFlags(features []string) []string { func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags { - if getDenyWarnings(compiler) { - flags.RustFlags = append(flags.RustFlags, "-D warnings") + lintFlags, err := config.RustcLintsForDir(ctx.ModuleDir(), compiler.Properties.Lints) + if err != nil { + ctx.PropertyErrorf("lints", err.Error()) } + flags.RustFlags = append(flags.RustFlags, lintFlags) flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...) - flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...) - flags.RustFlags = append(flags.RustFlags, "--edition="+getEdition(compiler)) + flags.RustFlags = append(flags.RustFlags, compiler.cfgsToFlags()...) + flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags()...) + flags.RustdocFlags = append(flags.RustdocFlags, compiler.cfgsToFlags()...) + flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags()...) + 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()) if ctx.Host() && !ctx.Windows() { - rpath_prefix := `\$$ORIGIN/` + rpathPrefix := `\$$ORIGIN/` if ctx.Darwin() { - rpath_prefix = "@loader_path/" + rpathPrefix = "@loader_path/" } var rpath string @@ -163,8 +260,12 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flag } else { rpath = "lib" } - flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+rpath) - flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+"../"+rpath) + flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpathPrefix+rpath) + flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpathPrefix+"../"+rpath) + } + + if ctx.RustModule().UseVndk() { + flags.RustFlags = append(flags.RustFlags, "--cfg 'android_vndk'") } return flags @@ -174,42 +275,65 @@ func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathD panic(fmt.Errorf("baseCrater doesn't know how to crate things!")) } +func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags, + deps PathDeps) android.OptionalPath { + + return android.OptionalPath{} +} + +func (compiler *baseCompiler) initialize(ctx ModuleContext) { + compiler.cargoOutDir = android.PathForModuleOut(ctx, genSubDir) +} + +func (compiler *baseCompiler) CargoOutDir() android.OptionalPath { + return android.OptionalPathForPath(compiler.cargoOutDir) +} + +func (compiler *baseCompiler) isDependencyRoot() bool { + return false +} + +func (compiler *baseCompiler) strippedOutputFilePath() android.OptionalPath { + return compiler.strippedOutputFile +} + 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...) + deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...) deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...) if !Bool(compiler.Properties.No_stdlibs) { for _, stdlib := range config.Stdlibs { - // If we're building for host, use the compiler's stdlibs - if ctx.Host() { + // If we're building for the primary arch of the build host, use the compiler's stdlibs + if ctx.Target().Os == android.BuildOs { stdlib = stdlib + "_" + ctx.toolchain().RustTriple() } - - // This check is technically insufficient - on the host, where - // static linking is the default, if one of our static - // dependencies uses a dynamic library, we need to dynamically - // link the stdlib as well. - if (len(deps.Dylibs) > 0) || (!ctx.Host()) { - // Dynamically linked stdlib - deps.Dylibs = append(deps.Dylibs, stdlib) - } + deps.Stdlibs = append(deps.Stdlibs, stdlib) } } return deps } -func (compiler *baseCompiler) bionicDeps(ctx DepsContext, deps Deps) Deps { - deps.SharedLibs = append(deps.SharedLibs, "liblog") - deps.SharedLibs = append(deps.SharedLibs, "libc") - deps.SharedLibs = append(deps.SharedLibs, "libm") - deps.SharedLibs = append(deps.SharedLibs, "libdl") - - //TODO(b/141331117) libstd requires libgcc on Android - deps.StaticLibs = append(deps.StaticLibs, "libgcc") +func bionicDeps(ctx DepsContext, deps Deps, static bool) Deps { + bionicLibs := []string{} + bionicLibs = append(bionicLibs, "liblog") + bionicLibs = append(bionicLibs, "libc") + bionicLibs = append(bionicLibs, "libm") + bionicLibs = append(bionicLibs, "libdl") + + if static { + deps.StaticLibs = append(deps.StaticLibs, bionicLibs...) + } else { + deps.SharedLibs = append(deps.SharedLibs, bionicLibs...) + } + if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" { + deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins) + } return deps } @@ -217,20 +341,37 @@ func (compiler *baseCompiler) crateName() string { return compiler.Properties.Crate_name } +func (compiler *baseCompiler) everInstallable() bool { + // Most modules are installable, so return true by default. + return true +} + func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath { dir := compiler.dir if ctx.toolchain().Is64Bit() && compiler.dir64 != "" { dir = compiler.dir64 } - if !ctx.Host() || ctx.Target().NativeBridge == android.NativeBridgeEnabled { + if ctx.Target().NativeBridge == android.NativeBridgeEnabled { + dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath) + } + if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) { dir = filepath.Join(dir, ctx.Arch().ArchType.String()) } + + if compiler.location == InstallInData && ctx.RustModule().UseVndk() { + dir = filepath.Join(dir, "vendor") + } return android.PathForModuleInstall(ctx, dir, compiler.subDir, compiler.relativeInstallPath(), compiler.relative) } -func (compiler *baseCompiler) install(ctx ModuleContext, file android.Path) { - compiler.path = ctx.InstallFile(compiler.installDir(ctx), file.Base(), file) +func (compiler *baseCompiler) nativeCoverage() bool { + return false +} + +func (compiler *baseCompiler) install(ctx ModuleContext) { + path := ctx.RustModule().OutputFile() + compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path()) } func (compiler *baseCompiler) getStem(ctx ModuleContext) string { @@ -238,7 +379,7 @@ func (compiler *baseCompiler) getStem(ctx ModuleContext) string { } func (compiler *baseCompiler) getStemWithoutSuffix(ctx BaseModuleContext) string { - stem := ctx.baseModuleName() + stem := ctx.ModuleName() if String(compiler.Properties.Stem) != "" { stem = String(compiler.Properties.Stem) } @@ -250,10 +391,25 @@ func (compiler *baseCompiler) relativeInstallPath() string { return String(compiler.Properties.Relative_install_path) } -func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) android.Path { - srcPaths := android.PathsForModuleSrc(ctx, srcs) - if len(srcPaths) != 1 { - ctx.PropertyErrorf("srcs", "srcs can only contain one path for rust modules") +// 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) { + // 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. + numSrcs := 0 + srcIndex := 0 + for i, s := range srcs { + if android.SrcIsModule(s) == "" { + numSrcs++ + srcIndex = i + } + } + if numSrcs != 1 { + ctx.PropertyErrorf("srcs", incorrectSourcesError) + } + if srcIndex != 0 { + ctx.PropertyErrorf("srcs", "main source file must be the first in srcs") } - return srcPaths[0] + paths := android.PathsForModuleSrc(ctx, srcs) + return paths[srcIndex], paths[1:] } |