diff options
Diffstat (limited to 'rust/compiler.go')
| -rw-r--r-- | rust/compiler.go | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/rust/compiler.go b/rust/compiler.go new file mode 100644 index 000000000..4593165f4 --- /dev/null +++ b/rust/compiler.go @@ -0,0 +1,259 @@ +// Copyright 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rust + +import ( + "fmt" + "path/filepath" + + "github.com/google/blueprint/proptools" + + "android/soong/android" + "android/soong/rust/config" +) + +func getEdition(compiler *baseCompiler) string { + return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) +} + +func getDenyWarnings(compiler *baseCompiler) bool { + return BoolDefault(compiler.Properties.Deny_warnings, config.DefaultDenyWarnings) +} + +func (compiler *baseCompiler) setNoStdlibs() { + compiler.Properties.No_stdlibs = proptools.BoolPtr(true) +} + +func NewBaseCompiler(dir, dir64 string, location installLocation) *baseCompiler { + return &baseCompiler{ + Properties: BaseCompilerProperties{}, + dir: dir, + dir64: dir64, + location: location, + } +} + +type installLocation int + +const ( + InstallInSystem installLocation = 0 + InstallInData = iota +) + +type BaseCompilerProperties struct { + // whether to pass "-D warnings" to rustc. Defaults to true. + Deny_warnings *bool + + // flags to pass to rustc + Flags []string `android:"path,arch_variant"` + + // flags to pass to the linker + Ld_flags []string `android:"path,arch_variant"` + + // 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 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 + Static_libs []string `android:"arch_variant"` + + // crate name, required for libraries. This must be the expected extern crate name used in source + Crate_name string `android:"arch_variant"` + + // list of features to enable for this crate + Features []string `android:"arch_variant"` + + // specific rust edition that should be used if the default version is not desired + Edition *string `android:"arch_variant"` + + // sets name of the output + Stem *string `android:"arch_variant"` + + // append to name of output + Suffix *string `android:"arch_variant"` + + // install to a subdirectory of the default install path for the module + Relative_install_path *string `android:"arch_variant"` + + // whether to suppress inclusion of standard crates - defaults to false + No_stdlibs *bool +} + +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 + + // Install related + dir string + dir64 string + subDir string + relative string + path android.InstallPath + location installLocation +} + +var _ compiler = (*baseCompiler)(nil) + +func (compiler *baseCompiler) inData() bool { + return compiler.location == InstallInData +} + +func (compiler *baseCompiler) compilerProps() []interface{} { + return []interface{}{&compiler.Properties} +} + +func (compiler *baseCompiler) featuresToFlags(features []string) []string { + flags := []string{} + for _, feature := range features { + flags = append(flags, "--cfg 'feature=\""+feature+"\"'") + } + return flags +} + +func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags { + + if getDenyWarnings(compiler) { + flags.RustFlags = append(flags.RustFlags, "-D warnings") + } + 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.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/` + if ctx.Darwin() { + rpath_prefix = "@loader_path/" + } + + var rpath string + if ctx.toolchain().Is64Bit() { + rpath = "lib64" + } else { + rpath = "lib" + } + flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+rpath) + flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+"../"+rpath) + } + + return flags +} + +func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path { + panic(fmt.Errorf("baseCrater doesn't know how to crate things!")) +} + +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.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...) + deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.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() { + 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) + } + } + } + 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") + + return deps +} + +func (compiler *baseCompiler) crateName() string { + return compiler.Properties.Crate_name +} + +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 { + dir = filepath.Join(dir, ctx.Arch().ArchType.String()) + } + 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) getStem(ctx ModuleContext) string { + return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix) +} + +func (compiler *baseCompiler) getStemWithoutSuffix(ctx BaseModuleContext) string { + stem := ctx.baseModuleName() + if String(compiler.Properties.Stem) != "" { + stem = String(compiler.Properties.Stem) + } + + return stem +} + +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") + } + return srcPaths[0] +} |