// 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" "android/soong/android" "android/soong/rust/config" ) func NewBaseCompiler(dir, dir64 string) *baseCompiler { return &baseCompiler{ Properties: BaseCompilerProperties{ Edition: &config.DefaultEdition, }, dir: dir, dir64: dir64, } } type BaseCompilerProperties struct { // 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 (defaults to module name); if library, this must be the expected extern crate name 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"` } 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.OutputPath } var _ compiler = (*baseCompiler)(nil) 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 { flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...) flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...) flags.RustFlags = append(flags.RustFlags, "--edition="+*compiler.Properties.Edition) flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...) flags.GlobalFlags = append(flags.GlobalFlags, ctx.toolchain().ToolchainRustFlags()) 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...) return deps } func (compiler *baseCompiler) crateName() string { return compiler.Properties.Crate_name } func (compiler *baseCompiler) installDir(ctx ModuleContext) android.OutputPath { dir := compiler.dir if ctx.toolchain().Is64Bit() && compiler.dir64 != "" { dir = compiler.dir64 } if (!ctx.Host() && !ctx.Arch().Native) || 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] }