1// 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 "github.com/google/blueprint/proptools" 22 23 "android/soong/android" 24 "android/soong/rust/config" 25) 26 27func getEdition(compiler *baseCompiler) string { 28 return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) 29} 30 31func (compiler *baseCompiler) setNoStdlibs() { 32 compiler.Properties.No_stdlibs = proptools.BoolPtr(true) 33} 34 35func NewBaseCompiler(dir, dir64 string, location installLocation) *baseCompiler { 36 return &baseCompiler{ 37 Properties: BaseCompilerProperties{}, 38 dir: dir, 39 dir64: dir64, 40 location: location, 41 } 42} 43 44type installLocation int 45 46const ( 47 InstallInSystem installLocation = 0 48 InstallInData = iota 49 50 incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\"" 51) 52 53type BaseCompilerProperties struct { 54 // path to the source file that is the main entry point of the program (e.g. main.rs or lib.rs) 55 Srcs []string `android:"path,arch_variant"` 56 57 // whether to suppress the standard lint flags - default to false 58 No_lint *bool 59 60 // flags to pass to rustc 61 Flags []string `android:"path,arch_variant"` 62 63 // flags to pass to the linker 64 Ld_flags []string `android:"path,arch_variant"` 65 66 // list of rust rlib crate dependencies 67 Rlibs []string `android:"arch_variant"` 68 69 // list of rust dylib crate dependencies 70 Dylibs []string `android:"arch_variant"` 71 72 // list of rust automatic crate dependencies 73 Rustlibs []string `android:"arch_variant"` 74 75 // list of rust proc_macro crate dependencies 76 Proc_macros []string `android:"arch_variant"` 77 78 // list of C shared library dependencies 79 Shared_libs []string `android:"arch_variant"` 80 81 // list of C static library dependencies 82 Static_libs []string `android:"arch_variant"` 83 84 // crate name, required for libraries. This must be the expected extern crate name used in source 85 Crate_name string `android:"arch_variant"` 86 87 // list of features to enable for this crate 88 Features []string `android:"arch_variant"` 89 90 // specific rust edition that should be used if the default version is not desired 91 Edition *string `android:"arch_variant"` 92 93 // sets name of the output 94 Stem *string `android:"arch_variant"` 95 96 // append to name of output 97 Suffix *string `android:"arch_variant"` 98 99 // install to a subdirectory of the default install path for the module 100 Relative_install_path *string `android:"arch_variant"` 101 102 // whether to suppress inclusion of standard crates - defaults to false 103 No_stdlibs *bool 104} 105 106type baseCompiler struct { 107 Properties BaseCompilerProperties 108 coverageFile android.Path //rustc generates a single gcno file 109 110 // Install related 111 dir string 112 dir64 string 113 subDir string 114 relative string 115 path android.InstallPath 116 location installLocation 117 118 coverageOutputZipFile android.OptionalPath 119 unstrippedOutputFile android.Path 120 distFile android.OptionalPath 121} 122 123func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath { 124 panic("baseCompiler does not implement coverageOutputZipPath()") 125} 126 127var _ compiler = (*baseCompiler)(nil) 128 129func (compiler *baseCompiler) inData() bool { 130 return compiler.location == InstallInData 131} 132 133func (compiler *baseCompiler) compilerProps() []interface{} { 134 return []interface{}{&compiler.Properties} 135} 136 137func (compiler *baseCompiler) featuresToFlags(features []string) []string { 138 flags := []string{} 139 for _, feature := range features { 140 flags = append(flags, "--cfg 'feature=\""+feature+"\"'") 141 } 142 return flags 143} 144 145func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags { 146 147 if !Bool(compiler.Properties.No_lint) { 148 flags.RustFlags = append(flags.RustFlags, config.RustcLintsForDir(ctx.ModuleDir())) 149 } 150 flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...) 151 flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...) 152 flags.RustFlags = append(flags.RustFlags, "--edition="+getEdition(compiler)) 153 flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...) 154 flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...) 155 flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags()) 156 flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags()) 157 158 if ctx.Host() && !ctx.Windows() { 159 rpath_prefix := `\$$ORIGIN/` 160 if ctx.Darwin() { 161 rpath_prefix = "@loader_path/" 162 } 163 164 var rpath string 165 if ctx.toolchain().Is64Bit() { 166 rpath = "lib64" 167 } else { 168 rpath = "lib" 169 } 170 flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+rpath) 171 flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+"../"+rpath) 172 } 173 174 return flags 175} 176 177func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path { 178 panic(fmt.Errorf("baseCrater doesn't know how to crate things!")) 179} 180 181func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { 182 deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...) 183 deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...) 184 deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...) 185 deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...) 186 deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...) 187 deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...) 188 189 if !Bool(compiler.Properties.No_stdlibs) { 190 for _, stdlib := range config.Stdlibs { 191 // If we're building for the primary host target, use the compiler's stdlibs 192 if ctx.Host() && ctx.TargetPrimary() { 193 stdlib = stdlib + "_" + ctx.toolchain().RustTriple() 194 } 195 196 deps.Rustlibs = append(deps.Rustlibs, stdlib) 197 } 198 } 199 return deps 200} 201 202func bionicDeps(deps Deps) Deps { 203 deps.SharedLibs = append(deps.SharedLibs, "liblog") 204 deps.SharedLibs = append(deps.SharedLibs, "libc") 205 deps.SharedLibs = append(deps.SharedLibs, "libm") 206 deps.SharedLibs = append(deps.SharedLibs, "libdl") 207 208 //TODO(b/141331117) libstd requires libgcc on Android 209 deps.StaticLibs = append(deps.StaticLibs, "libgcc") 210 211 return deps 212} 213 214func (compiler *baseCompiler) crateName() string { 215 return compiler.Properties.Crate_name 216} 217 218func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath { 219 dir := compiler.dir 220 if ctx.toolchain().Is64Bit() && compiler.dir64 != "" { 221 dir = compiler.dir64 222 } 223 if ctx.Target().NativeBridge == android.NativeBridgeEnabled { 224 dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath) 225 } 226 if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) { 227 dir = filepath.Join(dir, ctx.Arch().ArchType.String()) 228 } 229 return android.PathForModuleInstall(ctx, dir, compiler.subDir, 230 compiler.relativeInstallPath(), compiler.relative) 231} 232 233func (compiler *baseCompiler) nativeCoverage() bool { 234 return false 235} 236 237func (compiler *baseCompiler) install(ctx ModuleContext, file android.Path) { 238 compiler.path = ctx.InstallFile(compiler.installDir(ctx), file.Base(), file) 239} 240 241func (compiler *baseCompiler) getStem(ctx ModuleContext) string { 242 return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix) 243} 244 245func (compiler *baseCompiler) getStemWithoutSuffix(ctx BaseModuleContext) string { 246 stem := ctx.ModuleName() 247 if String(compiler.Properties.Stem) != "" { 248 stem = String(compiler.Properties.Stem) 249 } 250 251 return stem 252} 253 254func (compiler *baseCompiler) relativeInstallPath() string { 255 return String(compiler.Properties.Relative_install_path) 256} 257 258// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs. 259func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, android.Paths) { 260 // The srcs can contain strings with prefix ":". 261 // They are dependent modules of this module, with android.SourceDepTag. 262 // They are not the main source file compiled by rustc. 263 numSrcs := 0 264 srcIndex := 0 265 for i, s := range srcs { 266 if android.SrcIsModule(s) == "" { 267 numSrcs++ 268 srcIndex = i 269 } 270 } 271 if numSrcs != 1 { 272 ctx.PropertyErrorf("srcs", incorrectSourcesError) 273 } 274 if srcIndex != 0 { 275 ctx.PropertyErrorf("srcs", "main source file must be the first in srcs") 276 } 277 paths := android.PathsForModuleSrc(ctx, srcs) 278 return paths[srcIndex], paths[1:] 279} 280