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 "strings" 21 22 "github.com/google/blueprint/proptools" 23 24 "android/soong/android" 25 "android/soong/rust/config" 26) 27 28type RustLinkage int 29 30const ( 31 DefaultLinkage RustLinkage = iota 32 RlibLinkage 33 DylibLinkage 34) 35 36func (compiler *baseCompiler) edition() string { 37 return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) 38} 39 40func (compiler *baseCompiler) setNoStdlibs() { 41 compiler.Properties.No_stdlibs = proptools.BoolPtr(true) 42} 43 44func (compiler *baseCompiler) disableLints() { 45 compiler.Properties.Lints = proptools.StringPtr("none") 46} 47 48func NewBaseCompiler(dir, dir64 string, location installLocation) *baseCompiler { 49 return &baseCompiler{ 50 Properties: BaseCompilerProperties{}, 51 dir: dir, 52 dir64: dir64, 53 location: location, 54 } 55} 56 57type installLocation int 58 59const ( 60 InstallInSystem installLocation = 0 61 InstallInData = iota 62 63 incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\"" 64 genSubDir = "out/" 65) 66 67type BaseCompilerProperties struct { 68 // path to the source file that is the main entry point of the program (e.g. main.rs or lib.rs). 69 // Only a single source file can be defined. Modules which generate source can be included by prefixing 70 // the module name with ":", for example ":libfoo_bindgen" 71 // 72 // If no source file is defined, a single generated source module can be defined to be used as the main source. 73 Srcs []string `android:"path,arch_variant"` 74 75 // name of the lint set that should be used to validate this module. 76 // 77 // Possible values are "default" (for using a sensible set of lints 78 // depending on the module's location), "android" (for the strictest 79 // lint set that applies to all Android platform code), "vendor" (for 80 // a relaxed set) and "none" (for ignoring all lint warnings and 81 // errors). The default value is "default". 82 Lints *string 83 84 // flags to pass to rustc. To enable configuration options or features, use the "cfgs" or "features" properties. 85 Flags []string `android:"arch_variant"` 86 87 // flags to pass to the linker 88 Ld_flags []string `android:"arch_variant"` 89 90 // list of rust rlib crate dependencies 91 Rlibs []string `android:"arch_variant"` 92 93 // list of rust dylib crate dependencies 94 Dylibs []string `android:"arch_variant"` 95 96 // list of rust automatic crate dependencies 97 Rustlibs []string `android:"arch_variant"` 98 99 // list of rust proc_macro crate dependencies 100 Proc_macros []string `android:"arch_variant"` 101 102 // list of C shared library dependencies 103 Shared_libs []string `android:"arch_variant"` 104 105 // list of C static library dependencies. These dependencies do not normally propagate to dependents 106 // and may need to be redeclared. See whole_static_libs for bundling static dependencies into a library. 107 Static_libs []string `android:"arch_variant"` 108 109 // Similar to static_libs, but will bundle the static library dependency into a library. This is helpful 110 // to avoid having to redeclare the dependency for dependents of this library, but in some cases may also 111 // result in bloat if multiple dependencies all include the same static library whole. 112 // 113 // The common use case for this is when the static library is unlikely to be a dependency of other modules to avoid 114 // having to redeclare the static library dependency for every dependent module. 115 // If you are not sure what to, for rust_library modules most static dependencies should go in static_libraries, 116 // and for rust_ffi modules most static dependencies should go into whole_static_libraries. 117 // 118 // For rust_ffi static variants, these libraries will be included in the resulting static library archive. 119 // 120 // For rust_library rlib variants, these libraries will be bundled into the resulting rlib library. This will 121 // include all of the static libraries symbols in any dylibs or binaries which use this rlib as well. 122 Whole_static_libs []string `android:"arch_variant"` 123 124 // list of Rust system library dependencies. 125 // 126 // This is usually only needed when `no_stdlibs` is true, in which case it can be used to depend on system crates 127 // like `core` and `alloc`. 128 Stdlibs []string `android:"arch_variant"` 129 130 // crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider 131 // modules which create library variants (rust_bindgen). This must be the expected extern crate name used in 132 // source, and is required to conform to an enforced format matching library output files (if the output file is 133 // lib<someName><suffix>, the crate_name property must be <someName>). 134 Crate_name string `android:"arch_variant"` 135 136 // list of features to enable for this crate 137 Features []string `android:"arch_variant"` 138 139 // list of configuration options to enable for this crate. To enable features, use the "features" property. 140 Cfgs []string `android:"arch_variant"` 141 142 // specific rust edition that should be used if the default version is not desired 143 Edition *string `android:"arch_variant"` 144 145 // sets name of the output 146 Stem *string `android:"arch_variant"` 147 148 // append to name of output 149 Suffix *string `android:"arch_variant"` 150 151 // install to a subdirectory of the default install path for the module 152 Relative_install_path *string `android:"arch_variant"` 153 154 // whether to suppress inclusion of standard crates - defaults to false 155 No_stdlibs *bool 156 157 // Change the rustlibs linkage to select rlib linkage by default for device targets. 158 // Also link libstd as an rlib as well on device targets. 159 // Note: This is the default behavior for host targets. 160 // 161 // This is primarily meant for rust_binary and rust_ffi modules where the default 162 // linkage of libstd might need to be overridden in some use cases. This should 163 // generally be avoided with other module types since it may cause collisions at 164 // linkage if all dependencies of the root binary module do not link against libstd\ 165 // the same way. 166 Prefer_rlib *bool `android:"arch_variant"` 167 168 // Enables emitting certain Cargo environment variables. Only intended to be used for compatibility purposes. 169 // Will set CARGO_CRATE_NAME to the crate_name property's value. 170 // Will set CARGO_BIN_NAME to the output filename value without the extension. 171 Cargo_env_compat *bool 172 173 // If cargo_env_compat is true, sets the CARGO_PKG_VERSION env var to this value. 174 Cargo_pkg_version *string 175} 176 177type baseCompiler struct { 178 Properties BaseCompilerProperties 179 180 // Install related 181 dir string 182 dir64 string 183 subDir string 184 relative string 185 path android.InstallPath 186 location installLocation 187 sanitize *sanitize 188 189 distFile android.OptionalPath 190 191 // unstripped output file. 192 unstrippedOutputFile android.Path 193 194 // stripped output file. 195 strippedOutputFile android.OptionalPath 196 197 // If a crate has a source-generated dependency, a copy of the source file 198 // will be available in cargoOutDir (equivalent to Cargo OUT_DIR). 199 cargoOutDir android.ModuleOutPath 200} 201 202func (compiler *baseCompiler) Disabled() bool { 203 return false 204} 205 206func (compiler *baseCompiler) SetDisabled() { 207 panic("baseCompiler does not implement SetDisabled()") 208} 209 210func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath { 211 panic("baseCompiler does not implement coverageOutputZipPath()") 212} 213 214func (compiler *baseCompiler) preferRlib() bool { 215 return Bool(compiler.Properties.Prefer_rlib) 216} 217 218func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage { 219 // For devices, we always link stdlibs in as dylibs by default. 220 if compiler.preferRlib() { 221 return RlibLinkage 222 } else if ctx.Device() { 223 return DylibLinkage 224 } else { 225 return RlibLinkage 226 } 227} 228 229var _ compiler = (*baseCompiler)(nil) 230 231func (compiler *baseCompiler) inData() bool { 232 return compiler.location == InstallInData 233} 234 235func (compiler *baseCompiler) compilerProps() []interface{} { 236 return []interface{}{&compiler.Properties} 237} 238 239func (compiler *baseCompiler) cfgsToFlags() []string { 240 flags := []string{} 241 for _, cfg := range compiler.Properties.Cfgs { 242 flags = append(flags, "--cfg '"+cfg+"'") 243 } 244 245 return flags 246} 247 248func (compiler *baseCompiler) featuresToFlags() []string { 249 flags := []string{} 250 for _, feature := range compiler.Properties.Features { 251 flags = append(flags, "--cfg 'feature=\""+feature+"\"'") 252 } 253 254 return flags 255} 256 257func (compiler *baseCompiler) featureFlags(ctx ModuleContext, flags Flags) Flags { 258 flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags()...) 259 flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags()...) 260 261 return flags 262} 263 264func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags { 265 if ctx.RustModule().UseVndk() { 266 compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_vndk") 267 } 268 269 flags.RustFlags = append(flags.RustFlags, compiler.cfgsToFlags()...) 270 flags.RustdocFlags = append(flags.RustdocFlags, compiler.cfgsToFlags()...) 271 return flags 272} 273 274func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags { 275 276 lintFlags, err := config.RustcLintsForDir(ctx.ModuleDir(), compiler.Properties.Lints) 277 if err != nil { 278 ctx.PropertyErrorf("lints", err.Error()) 279 } 280 281 // linkage-related flags are disallowed. 282 for _, s := range compiler.Properties.Ld_flags { 283 if strings.HasPrefix(s, "-Wl,-l") || strings.HasPrefix(s, "-Wl,-L") { 284 ctx.PropertyErrorf("ld_flags", "'-Wl,-l' and '-Wl,-L' flags cannot be manually specified") 285 } 286 } 287 for _, s := range compiler.Properties.Flags { 288 if strings.HasPrefix(s, "-l") || strings.HasPrefix(s, "-L") { 289 ctx.PropertyErrorf("flags", "'-l' and '-L' flags cannot be manually specified") 290 } 291 if strings.HasPrefix(s, "--extern") { 292 ctx.PropertyErrorf("flags", "'--extern' flag cannot be manually specified") 293 } 294 if strings.HasPrefix(s, "-Clink-args=") || strings.HasPrefix(s, "-C link-args=") { 295 ctx.PropertyErrorf("flags", "'-C link-args' flag cannot be manually specified") 296 } 297 } 298 299 flags.RustFlags = append(flags.RustFlags, lintFlags) 300 flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...) 301 flags.RustFlags = append(flags.RustFlags, "--edition="+compiler.edition()) 302 flags.RustdocFlags = append(flags.RustdocFlags, "--edition="+compiler.edition()) 303 flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...) 304 flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...) 305 flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags()) 306 flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags()) 307 308 if ctx.Host() && !ctx.Windows() { 309 rpathPrefix := `\$$ORIGIN/` 310 if ctx.Darwin() { 311 rpathPrefix = "@loader_path/" 312 } 313 314 var rpath string 315 if ctx.toolchain().Is64Bit() { 316 rpath = "lib64" 317 } else { 318 rpath = "lib" 319 } 320 flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpathPrefix+rpath) 321 flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpathPrefix+"../"+rpath) 322 } 323 324 return flags 325} 326 327func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path { 328 panic(fmt.Errorf("baseCrater doesn't know how to crate things!")) 329} 330 331func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags, 332 deps PathDeps) android.OptionalPath { 333 334 return android.OptionalPath{} 335} 336 337func (compiler *baseCompiler) initialize(ctx ModuleContext) { 338 compiler.cargoOutDir = android.PathForModuleOut(ctx, genSubDir) 339} 340 341func (compiler *baseCompiler) CargoOutDir() android.OptionalPath { 342 return android.OptionalPathForPath(compiler.cargoOutDir) 343} 344 345func (compiler *baseCompiler) CargoEnvCompat() bool { 346 return Bool(compiler.Properties.Cargo_env_compat) 347} 348 349func (compiler *baseCompiler) CargoPkgVersion() string { 350 return String(compiler.Properties.Cargo_pkg_version) 351} 352 353func (compiler *baseCompiler) unstrippedOutputFilePath() android.Path { 354 return compiler.unstrippedOutputFile 355} 356 357func (compiler *baseCompiler) strippedOutputFilePath() android.OptionalPath { 358 return compiler.strippedOutputFile 359} 360 361func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { 362 deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...) 363 deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...) 364 deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...) 365 deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...) 366 deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...) 367 deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...) 368 deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...) 369 deps.Stdlibs = append(deps.Stdlibs, compiler.Properties.Stdlibs...) 370 371 if !Bool(compiler.Properties.No_stdlibs) { 372 for _, stdlib := range config.Stdlibs { 373 // If we're building for the build host, use the prebuilt stdlibs 374 if ctx.Target().Os == android.Linux || ctx.Target().Os == android.Darwin { 375 stdlib = "prebuilt_" + stdlib 376 } 377 deps.Stdlibs = append(deps.Stdlibs, stdlib) 378 } 379 } 380 return deps 381} 382 383func bionicDeps(ctx DepsContext, deps Deps, static bool) Deps { 384 bionicLibs := []string{} 385 bionicLibs = append(bionicLibs, "liblog") 386 bionicLibs = append(bionicLibs, "libc") 387 bionicLibs = append(bionicLibs, "libm") 388 bionicLibs = append(bionicLibs, "libdl") 389 390 if static { 391 deps.StaticLibs = append(deps.StaticLibs, bionicLibs...) 392 } else { 393 deps.SharedLibs = append(deps.SharedLibs, bionicLibs...) 394 } 395 if ctx.RustModule().StaticExecutable() { 396 deps.StaticLibs = append(deps.StaticLibs, "libunwind") 397 } 398 if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" { 399 deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins) 400 } 401 return deps 402} 403 404func muslDeps(ctx DepsContext, deps Deps, static bool) Deps { 405 muslLibs := []string{"libc_musl"} 406 if static { 407 deps.StaticLibs = append(deps.StaticLibs, muslLibs...) 408 } else { 409 deps.SharedLibs = append(deps.SharedLibs, muslLibs...) 410 } 411 if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" { 412 deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins) 413 } 414 415 return deps 416} 417 418func (compiler *baseCompiler) crateName() string { 419 return compiler.Properties.Crate_name 420} 421 422func (compiler *baseCompiler) everInstallable() bool { 423 // Most modules are installable, so return true by default. 424 return true 425} 426 427func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath { 428 dir := compiler.dir 429 if ctx.toolchain().Is64Bit() && compiler.dir64 != "" { 430 dir = compiler.dir64 431 } 432 if ctx.Target().NativeBridge == android.NativeBridgeEnabled { 433 dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath) 434 } 435 if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) { 436 dir = filepath.Join(dir, ctx.Arch().ArchType.String()) 437 } 438 439 if compiler.location == InstallInData && ctx.RustModule().UseVndk() { 440 if ctx.RustModule().InProduct() { 441 dir = filepath.Join(dir, "product") 442 } else if ctx.RustModule().InVendor() { 443 dir = filepath.Join(dir, "vendor") 444 } else { 445 ctx.ModuleErrorf("Unknown data+VNDK installation kind") 446 } 447 } 448 449 return android.PathForModuleInstall(ctx, dir, compiler.subDir, 450 compiler.relativeInstallPath(), compiler.relative) 451} 452 453func (compiler *baseCompiler) nativeCoverage() bool { 454 return false 455} 456 457func (compiler *baseCompiler) install(ctx ModuleContext) { 458 path := ctx.RustModule().OutputFile() 459 compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path()) 460} 461 462func (compiler *baseCompiler) getStem(ctx ModuleContext) string { 463 return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix) 464} 465 466func (compiler *baseCompiler) getStemWithoutSuffix(ctx BaseModuleContext) string { 467 stem := ctx.ModuleName() 468 if String(compiler.Properties.Stem) != "" { 469 stem = String(compiler.Properties.Stem) 470 } 471 472 return stem 473} 474 475func (compiler *baseCompiler) relativeInstallPath() string { 476 return String(compiler.Properties.Relative_install_path) 477} 478 479// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs. 480func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, android.Paths) { 481 if len(srcs) == 0 { 482 ctx.PropertyErrorf("srcs", "srcs must not be empty") 483 } 484 485 // The srcs can contain strings with prefix ":". 486 // They are dependent modules of this module, with android.SourceDepTag. 487 // They are not the main source file compiled by rustc. 488 numSrcs := 0 489 srcIndex := 0 490 for i, s := range srcs { 491 if android.SrcIsModule(s) == "" { 492 numSrcs++ 493 srcIndex = i 494 } 495 } 496 if numSrcs > 1 { 497 ctx.PropertyErrorf("srcs", incorrectSourcesError) 498 } 499 500 // If a main source file is not provided we expect only a single SourceProvider module to be defined 501 // within srcs, with the expectation that the first source it provides is the entry point. 502 if srcIndex != 0 { 503 ctx.PropertyErrorf("srcs", "main source file must be the first in srcs") 504 } else if numSrcs > 1 { 505 ctx.PropertyErrorf("srcs", "only a single generated source module can be defined without a main source file.") 506 } 507 508 paths := android.PathsForModuleSrc(ctx, srcs) 509 return paths[srcIndex], paths[1:] 510} 511