summaryrefslogtreecommitdiff
path: root/rust/compiler.go
diff options
context:
space:
mode:
Diffstat (limited to 'rust/compiler.go')
-rw-r--r--rust/compiler.go259
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]
+}