blob: f6e952a75f557e63356ce2661a5f87d647e421c9 [file] [log] [blame]
Ivan Lozanoffee3342019-08-27 12:03:00 -07001// Copyright 2019 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package rust
16
17import (
18 "fmt"
19 "path/filepath"
20
21 "android/soong/android"
22 "android/soong/rust/config"
Chih-Hung Hsieh961a30c2019-10-03 09:47:06 -070023 "github.com/google/blueprint/proptools"
Ivan Lozanoffee3342019-08-27 12:03:00 -070024)
25
Chih-Hung Hsieh961a30c2019-10-03 09:47:06 -070026func getEdition(compiler *baseCompiler) string {
27 return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition)
28}
29
30func getDenyWarnings(compiler *baseCompiler) bool {
31 return BoolDefault(compiler.Properties.Deny_warnings, config.DefaultDenyWarnings)
32}
33
Matthew Maurer99020b02019-10-31 10:44:40 -070034func (compiler *baseCompiler) setNoStdlibs() {
35 compiler.Properties.No_stdlibs = proptools.BoolPtr(true)
36}
37
Ivan Lozanoffee3342019-08-27 12:03:00 -070038func NewBaseCompiler(dir, dir64 string) *baseCompiler {
39 return &baseCompiler{
Chih-Hung Hsieh961a30c2019-10-03 09:47:06 -070040 Properties: BaseCompilerProperties{},
41 dir: dir,
42 dir64: dir64,
Ivan Lozanoffee3342019-08-27 12:03:00 -070043 }
44}
45
46type BaseCompilerProperties struct {
Chih-Hung Hsiehefdd7ac2019-09-26 18:59:27 -070047 // whether to pass "-D warnings" to rustc. Defaults to true.
48 Deny_warnings *bool
49
Ivan Lozanoffee3342019-08-27 12:03:00 -070050 // flags to pass to rustc
51 Flags []string `android:"path,arch_variant"`
52
53 // flags to pass to the linker
54 Ld_flags []string `android:"path,arch_variant"`
55
56 // list of rust rlib crate dependencies
57 Rlibs []string `android:"arch_variant"`
58
59 // list of rust dylib crate dependencies
60 Dylibs []string `android:"arch_variant"`
61
62 // list of rust proc_macro crate dependencies
63 Proc_macros []string `android:"arch_variant"`
64
65 // list of C shared library dependencies
66 Shared_libs []string `android:"arch_variant"`
67
68 // list of C static library dependencies
69 Static_libs []string `android:"arch_variant"`
70
71 // crate name (defaults to module name); if library, this must be the expected extern crate name
72 Crate_name string `android:"arch_variant"`
73
74 // list of features to enable for this crate
75 Features []string `android:"arch_variant"`
76
77 // specific rust edition that should be used if the default version is not desired
78 Edition *string `android:"arch_variant"`
79
80 // sets name of the output
81 Stem *string `android:"arch_variant"`
82
83 // append to name of output
84 Suffix *string `android:"arch_variant"`
85
86 // install to a subdirectory of the default install path for the module
87 Relative_install_path *string `android:"arch_variant"`
Matthew Maurer99020b02019-10-31 10:44:40 -070088
89 // whether to suppress inclusion of standard crates - defaults to false
90 No_stdlibs *bool
Ivan Lozanoffee3342019-08-27 12:03:00 -070091}
92
93type baseCompiler struct {
94 Properties BaseCompilerProperties
95 pathDeps android.Paths
96 rustFlagsDeps android.Paths
97 linkFlagsDeps android.Paths
98 flags string
99 linkFlags string
100 depFlags []string
101 linkDirs []string
102 edition string
103 src android.Path //rustc takes a single src file
104
105 // Install related
106 dir string
107 dir64 string
108 subDir string
109 relative string
Colin Cross70dda7e2019-10-01 22:05:35 -0700110 path android.InstallPath
Ivan Lozanoffee3342019-08-27 12:03:00 -0700111}
112
113var _ compiler = (*baseCompiler)(nil)
114
115func (compiler *baseCompiler) compilerProps() []interface{} {
116 return []interface{}{&compiler.Properties}
117}
118
119func (compiler *baseCompiler) featuresToFlags(features []string) []string {
120 flags := []string{}
121 for _, feature := range features {
122 flags = append(flags, "--cfg 'feature=\""+feature+"\"'")
123 }
124 return flags
125}
126
127func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags {
128
Chih-Hung Hsieh961a30c2019-10-03 09:47:06 -0700129 if getDenyWarnings(compiler) {
Chih-Hung Hsiehefdd7ac2019-09-26 18:59:27 -0700130 flags.RustFlags = append(flags.RustFlags, "-D warnings")
131 }
Ivan Lozanoffee3342019-08-27 12:03:00 -0700132 flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...)
133 flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...)
Chih-Hung Hsieh961a30c2019-10-03 09:47:06 -0700134 flags.RustFlags = append(flags.RustFlags, "--edition="+getEdition(compiler))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700135 flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
Joel Galenson724286c2019-09-30 13:01:37 -0700136 flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
Ivan Lozanof1c84332019-09-20 11:00:37 -0700137 flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
138 flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())
Ivan Lozanoffee3342019-08-27 12:03:00 -0700139
140 if ctx.Host() && !ctx.Windows() {
141 rpath_prefix := `\$$ORIGIN/`
142 if ctx.Darwin() {
143 rpath_prefix = "@loader_path/"
144 }
145
146 var rpath string
147 if ctx.toolchain().Is64Bit() {
148 rpath = "lib64"
149 } else {
150 rpath = "lib"
151 }
152 flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
153 flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+"../"+rpath)
154 }
155
156 return flags
157}
158
159func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
160 panic(fmt.Errorf("baseCrater doesn't know how to crate things!"))
161}
162
163func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
164 deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
165 deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...)
166 deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...)
167 deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
168 deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...)
169
Matthew Maurer99020b02019-10-31 10:44:40 -0700170 if !Bool(compiler.Properties.No_stdlibs) {
171 for _, stdlib := range config.Stdlibs {
172 // If we're building for host, use the compiler's stdlibs
173 if ctx.Host() {
174 stdlib = stdlib + "_" + ctx.toolchain().RustTriple()
175 }
176
177 // This check is technically insufficient - on the host, where
178 // static linking is the default, if one of our static
179 // dependencies uses a dynamic library, we need to dynamically
180 // link the stdlib as well.
181 if (len(deps.Dylibs) > 0) || (!ctx.Host()) {
182 // Dynamically linked stdlib
183 deps.Dylibs = append(deps.Dylibs, stdlib)
184 }
185 }
186 }
Ivan Lozanoffee3342019-08-27 12:03:00 -0700187 return deps
188}
189
Ivan Lozanof1c84332019-09-20 11:00:37 -0700190func (compiler *baseCompiler) bionicDeps(ctx DepsContext, deps Deps) Deps {
191 deps.SharedLibs = append(deps.SharedLibs, "liblog")
192 deps.SharedLibs = append(deps.SharedLibs, "libc")
193 deps.SharedLibs = append(deps.SharedLibs, "libm")
194 deps.SharedLibs = append(deps.SharedLibs, "libdl")
195
196 //TODO(b/141331117) libstd requires libgcc on Android
197 deps.StaticLibs = append(deps.StaticLibs, "libgcc")
198
199 return deps
200}
201
Ivan Lozanoffee3342019-08-27 12:03:00 -0700202func (compiler *baseCompiler) crateName() string {
203 return compiler.Properties.Crate_name
204}
205
Colin Cross70dda7e2019-10-01 22:05:35 -0700206func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700207 dir := compiler.dir
208 if ctx.toolchain().Is64Bit() && compiler.dir64 != "" {
209 dir = compiler.dir64
210 }
Colin Cross3b19f5d2019-09-17 14:45:31 -0700211 if !ctx.Host() || ctx.Target().NativeBridge == android.NativeBridgeEnabled {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700212 dir = filepath.Join(dir, ctx.Arch().ArchType.String())
213 }
214 return android.PathForModuleInstall(ctx, dir, compiler.subDir,
215 compiler.relativeInstallPath(), compiler.relative)
216}
217
218func (compiler *baseCompiler) install(ctx ModuleContext, file android.Path) {
219 compiler.path = ctx.InstallFile(compiler.installDir(ctx), file.Base(), file)
220}
221
222func (compiler *baseCompiler) getStem(ctx ModuleContext) string {
223 return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix)
224}
225
226func (compiler *baseCompiler) getStemWithoutSuffix(ctx BaseModuleContext) string {
227 stem := ctx.baseModuleName()
228 if String(compiler.Properties.Stem) != "" {
229 stem = String(compiler.Properties.Stem)
230 }
231
232 return stem
233}
234func (compiler *baseCompiler) relativeInstallPath() string {
235 return String(compiler.Properties.Relative_install_path)
236}
237
238func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) android.Path {
239 srcPaths := android.PathsForModuleSrc(ctx, srcs)
240 if len(srcPaths) != 1 {
241 ctx.PropertyErrorf("srcs", "srcs can only contain one path for rust modules")
242 }
243 return srcPaths[0]
244}