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 "android/soong/cc" 19 "errors" 20 "fmt" 21 "path/filepath" 22 "strings" 23 24 "github.com/google/blueprint/proptools" 25 26 "android/soong/android" 27 "android/soong/rust/config" 28) 29 30type RustLinkage int 31 32const ( 33 DefaultLinkage RustLinkage = iota 34 RlibLinkage 35 DylibLinkage 36) 37 38type compiler interface { 39 initialize(ctx ModuleContext) 40 compilerFlags(ctx ModuleContext, flags Flags) Flags 41 cfgFlags(ctx ModuleContext, flags Flags) Flags 42 featureFlags(ctx ModuleContext, module *Module, flags Flags) Flags 43 compilerProps() []interface{} 44 compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput 45 compilerDeps(ctx DepsContext, deps Deps) Deps 46 crateName() string 47 edition() string 48 features(ctx android.ConfigurableEvaluatorContext, module *Module) []string 49 rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath 50 Thinlto() bool 51 52 // Output directory in which source-generated code from dependencies is 53 // copied. This is equivalent to Cargo's OUT_DIR variable. 54 cargoOutDir() android.OptionalPath 55 56 // cargoPkgVersion returns the value of the Cargo_pkg_version property. 57 cargoPkgVersion() string 58 59 // cargoEnvCompat returns whether Cargo environment variables should be used. 60 cargoEnvCompat() bool 61 62 inData() bool 63 install(ctx ModuleContext) 64 relativeInstallPath() string 65 everInstallable() bool 66 67 nativeCoverage() bool 68 69 Disabled() bool 70 SetDisabled() 71 72 stdLinkage(ctx *depsContext) RustLinkage 73 noStdlibs() bool 74 75 unstrippedOutputFilePath() android.Path 76 strippedOutputFilePath() android.OptionalPath 77 78 checkedCrateRootPath() (android.Path, error) 79 80 Aliases() map[string]string 81} 82 83func (compiler *baseCompiler) edition() string { 84 return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) 85} 86 87func (compiler *baseCompiler) setNoStdlibs() { 88 compiler.Properties.No_stdlibs = proptools.BoolPtr(true) 89} 90 91func (compiler *baseCompiler) disableLints() { 92 compiler.Properties.Lints = proptools.StringPtr("none") 93} 94 95func NewBaseCompiler(dir, dir64 string, location installLocation) *baseCompiler { 96 return &baseCompiler{ 97 Properties: BaseCompilerProperties{}, 98 dir: dir, 99 dir64: dir64, 100 location: location, 101 } 102} 103 104type installLocation int 105 106const ( 107 InstallInSystem installLocation = 0 108 InstallInData = iota 109 110 incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\"" 111 genSubDir = "out/" 112) 113 114type BaseCompilerProperties struct { 115 // path to the source file that is the main entry point of the program (e.g. main.rs or lib.rs). 116 // Only a single source file can be defined. Modules which generate source can be included by prefixing 117 // the module name with ":", for example ":libfoo_bindgen" 118 // 119 // If no source file is defined, a single generated source module can be defined to be used as the main source. 120 Srcs []string `android:"path,arch_variant"` 121 122 // Entry point that is passed to rustc to begin the compilation. E.g. main.rs or lib.rs. 123 // When this property is set, 124 // * sandboxing is enabled for this module, and 125 // * the srcs attribute is interpreted as a list of all source files potentially 126 // used in compilation, including the entrypoint, and 127 // * compile_data can be used to add additional files used in compilation that 128 // not directly used as source files. 129 Crate_root *string `android:"path,arch_variant"` 130 131 // name of the lint set that should be used to validate this module. 132 // 133 // Possible values are "default" (for using a sensible set of lints 134 // depending on the module's location), "android" (for the strictest 135 // lint set that applies to all Android platform code), "vendor" (for 136 // a relaxed set) and "none" (for ignoring all lint warnings and 137 // errors). The default value is "default". 138 Lints *string 139 140 // flags to pass to rustc. To enable configuration options or features, use the "cfgs" or "features" properties. 141 Flags []string `android:"arch_variant"` 142 143 // flags to pass to the linker 144 Ld_flags []string `android:"arch_variant"` 145 146 // Rust crate dependencies to rename. Each entry should be a string of the form "dependencyname:alias". 147 // 148 // "dependencyname" here should be the name of the crate, not the Android module. This is 149 // equivalent to writing `alias = { package = "dependencyname" }` in a `Cargo.toml`. 150 Aliases []string 151 152 // list of rust rlib crate dependencies 153 Rlibs []string `android:"arch_variant"` 154 155 // list of rust automatic crate dependencies. 156 // Rustlibs linkage is rlib for host targets and dylib for device targets. 157 Rustlibs proptools.Configurable[[]string] `android:"arch_variant"` 158 159 // list of rust proc_macro crate dependencies 160 Proc_macros []string `android:"arch_variant"` 161 162 // list of C shared library dependencies 163 Shared_libs []string `android:"arch_variant"` 164 165 // list of C static library dependencies. These dependencies do not normally propagate to dependents 166 // and may need to be redeclared. See whole_static_libs for bundling static dependencies into a library. 167 Static_libs []string `android:"arch_variant"` 168 169 // Similar to static_libs, but will bundle the static library dependency into a library. This is helpful 170 // to avoid having to redeclare the dependency for dependents of this library, but in some cases may also 171 // result in bloat if multiple dependencies all include the same static library whole. 172 // 173 // The common use case for this is when the static library is unlikely to be a dependency of other modules to avoid 174 // having to redeclare the static library dependency for every dependent module. 175 // If you are not sure what to, for rust_library modules most static dependencies should go in static_libraries, 176 // and for rust_ffi modules most static dependencies should go into whole_static_libraries. 177 // 178 // For rust_ffi static variants, these libraries will be included in the resulting static library archive. 179 // 180 // For rust_library rlib variants, these libraries will be bundled into the resulting rlib library. This will 181 // include all of the static libraries symbols in any dylibs or binaries which use this rlib as well. 182 Whole_static_libs []string `android:"arch_variant"` 183 184 // list of Rust system library dependencies. 185 // 186 // This is usually only needed when `no_stdlibs` is true, in which case it can be used to depend on system crates 187 // like `core` and `alloc`. 188 Stdlibs []string `android:"arch_variant"` 189 190 // crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider 191 // modules which create library variants (rust_bindgen). This must be the expected extern crate name used in 192 // source, and is required to conform to an enforced format matching library output files (if the output file is 193 // lib<someName><suffix>, the crate_name property must be <someName>). 194 Crate_name string `android:"arch_variant"` 195 196 // list of features to enable for this crate 197 Features proptools.Configurable[[]string] `android:"arch_variant"` 198 199 // list of configuration options to enable for this crate. To enable features, use the "features" property. 200 Cfgs proptools.Configurable[[]string] `android:"arch_variant"` 201 202 // specific rust edition that should be used if the default version is not desired 203 Edition *string `android:"arch_variant"` 204 205 // sets name of the output 206 Stem *string `android:"arch_variant"` 207 208 // append to name of output 209 Suffix *string `android:"arch_variant"` 210 211 // install to a subdirectory of the default install path for the module 212 Relative_install_path *string `android:"arch_variant"` 213 214 // whether to suppress inclusion of standard crates - defaults to false 215 No_stdlibs *bool `android:"arch_variant"` 216 217 // Change the rustlibs linkage to select rlib linkage by default for device targets. 218 // Also link libstd as an rlib as well on device targets. 219 // Note: This is the default behavior for host targets. 220 // 221 // This is primarily meant for rust_binary and rust_ffi modules where the default 222 // linkage of libstd might need to be overridden in some use cases. This should 223 // generally be avoided with other module types since it may cause collisions at 224 // linkage if all dependencies of the root binary module do not link against libstd 225 // the same way. 226 Prefer_rlib *bool `android:"arch_variant"` 227 228 // Enables emitting certain Cargo environment variables. Only intended to be used for compatibility purposes. 229 // Will set CARGO_CRATE_NAME to the crate_name property's value. 230 // Will set CARGO_BIN_NAME to the output filename value without the extension. 231 Cargo_env_compat *bool 232 233 // If cargo_env_compat is true, sets the CARGO_PKG_VERSION env var to this value. 234 Cargo_pkg_version *string 235 236 // Control whether LTO is used for the final (Rust) linkage. This does not impact 237 // cross-language LTO. 238 Lto struct { 239 // Whether thin LTO should be enabled. By default this is true. 240 // LTO provides such a large code size benefit for Rust, this should always 241 // be enabled for production builds unless there's a clear need to disable it. 242 Thin *bool `android:"arch_variant"` 243 } `android:"arch_variant"` 244} 245 246type baseCompiler struct { 247 Properties BaseCompilerProperties 248 249 // Install related 250 dir string 251 dir64 string 252 subDir string 253 relative string 254 path android.InstallPath 255 location installLocation 256 sanitize *sanitize 257 258 distFile android.OptionalPath 259 260 installDeps android.InstallPaths 261 262 // unstripped output file. 263 unstrippedOutputFile android.Path 264 265 // stripped output file. 266 strippedOutputFile android.OptionalPath 267 268 // If a crate has a source-generated dependency, a copy of the source file 269 // will be available in cargoOutDir (equivalent to Cargo OUT_DIR). 270 // This is stored internally because it may not be available during 271 // singleton-generation passes like rustdoc/rust_project.json, but should 272 // be stashed during initial generation. 273 cachedCargoOutDir android.ModuleOutPath 274 // Calculated crate root cached internally because ModuleContext is not 275 // available to singleton targets like rustdoc/rust_project.json 276 cachedCrateRootPath android.Path 277 // If cachedCrateRootPath is nil after initialization, this will contain 278 // an explanation of why 279 cachedCrateRootError error 280} 281 282func (compiler *baseCompiler) Disabled() bool { 283 return false 284} 285 286// Thin LTO is enabled by default. 287func (compiler *baseCompiler) Thinlto() bool { 288 return BoolDefault(compiler.Properties.Lto.Thin, true) 289} 290 291func (compiler *baseCompiler) SetDisabled() { 292 panic("baseCompiler does not implement SetDisabled()") 293} 294 295func (compiler *baseCompiler) noStdlibs() bool { 296 return Bool(compiler.Properties.No_stdlibs) 297} 298 299func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath { 300 panic("baseCompiler does not implement coverageOutputZipPath()") 301} 302 303func (compiler *baseCompiler) preferRlib() bool { 304 return Bool(compiler.Properties.Prefer_rlib) 305} 306 307func (compiler *baseCompiler) Aliases() map[string]string { 308 aliases := map[string]string{} 309 for _, entry := range compiler.Properties.Aliases { 310 dep, alias, found := strings.Cut(entry, ":") 311 if !found { 312 panic(fmt.Errorf("invalid aliases entry %q missing ':'", entry)) 313 } 314 aliases[dep] = alias 315 } 316 return aliases 317} 318 319func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage { 320 // For devices, we always link stdlibs in as dylibs by default. 321 if compiler.preferRlib() { 322 return RlibLinkage 323 } else if ctx.Device() { 324 return DylibLinkage 325 } else { 326 return RlibLinkage 327 } 328} 329 330var _ compiler = (*baseCompiler)(nil) 331 332func (compiler *baseCompiler) inData() bool { 333 return compiler.location == InstallInData 334} 335 336func (compiler *baseCompiler) compilerProps() []interface{} { 337 return []interface{}{&compiler.Properties} 338} 339 340func cfgsToFlags(cfgs []string) []string { 341 flags := make([]string, 0, len(cfgs)) 342 for _, cfg := range cfgs { 343 flags = append(flags, "--cfg '"+cfg+"'") 344 } 345 346 return flags 347} 348 349func (compiler *baseCompiler) features(ctx android.ConfigurableEvaluatorContext, module *Module) []string { 350 eval := module.ConfigurableEvaluator(ctx) 351 return compiler.Properties.Features.GetOrDefault(eval, nil) 352} 353 354func (compiler *baseCompiler) featuresToFlags(ctx android.ConfigurableEvaluatorContext, module *Module) []string { 355 flags := []string{} 356 for _, feature := range compiler.features(ctx, module) { 357 flags = append(flags, "--cfg 'feature=\""+feature+"\"'") 358 } 359 360 return flags 361} 362 363func (compiler *baseCompiler) featureFlags(ctx ModuleContext, module *Module, flags Flags) Flags { 364 flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(ctx, module)...) 365 flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags(ctx, module)...) 366 367 return flags 368} 369 370func CommonDefaultCfgFlags(flags Flags, vendor bool, product bool) Flags { 371 var cfgs []string 372 if vendor || product { 373 cfgs = append(cfgs, "android_vndk") 374 if vendor { 375 cfgs = append(cfgs, "android_vendor") 376 } else if product { 377 cfgs = append(cfgs, "android_product") 378 } 379 } 380 381 flags.RustFlags = append(flags.RustFlags, cfgsToFlags(cfgs)...) 382 flags.RustdocFlags = append(flags.RustdocFlags, cfgsToFlags(cfgs)...) 383 return flags 384} 385 386func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags { 387 flags = CommonDefaultCfgFlags(flags, ctx.RustModule().InVendor(), ctx.RustModule().InProduct()) 388 389 cfgFlags := cfgsToFlags(compiler.Properties.Cfgs.GetOrDefault(ctx, nil)) 390 flags.RustFlags = append(flags.RustFlags, cfgFlags...) 391 flags.RustdocFlags = append(flags.RustdocFlags, cfgFlags...) 392 393 return flags 394} 395 396func CommonDefaultFlags(ctx android.ModuleContext, toolchain config.Toolchain, flags Flags) Flags { 397 flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...) 398 flags.GlobalRustFlags = append(flags.GlobalRustFlags, toolchain.ToolchainRustFlags()) 399 flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, toolchain.ToolchainLinkFlags()) 400 flags.EmitXrefs = ctx.Config().EmitXrefRules() 401 402 if ctx.Host() && !ctx.Windows() { 403 flags.LinkFlags = append(flags.LinkFlags, cc.RpathFlags(ctx)...) 404 } 405 406 if ctx.Os() == android.Linux { 407 // Add -lc, -lrt, -ldl, -lpthread, -lm and -lgcc_s to glibc builds to match 408 // the default behavior of device builds. 409 flags.LinkFlags = append(flags.LinkFlags, config.LinuxHostGlobalLinkFlags...) 410 } else if ctx.Os() == android.Darwin { 411 // Add -lc, -ldl, -lpthread and -lm to glibc darwin builds to match the default 412 // behavior of device builds. 413 flags.LinkFlags = append(flags.LinkFlags, 414 "-lc", 415 "-ldl", 416 "-lpthread", 417 "-lm", 418 ) 419 } 420 return flags 421} 422 423func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags { 424 425 flags = CommonDefaultFlags(ctx, ctx.toolchain(), flags) 426 lintFlags, err := config.RustcLintsForDir(ctx.ModuleDir(), compiler.Properties.Lints) 427 if err != nil { 428 ctx.PropertyErrorf("lints", err.Error()) 429 } 430 431 // linkage-related flags are disallowed. 432 for _, s := range compiler.Properties.Ld_flags { 433 if strings.HasPrefix(s, "-Wl,-l") || strings.HasPrefix(s, "-Wl,-L") { 434 ctx.PropertyErrorf("ld_flags", "'-Wl,-l' and '-Wl,-L' flags cannot be manually specified") 435 } 436 } 437 for _, s := range compiler.Properties.Flags { 438 if strings.HasPrefix(s, "-l") || strings.HasPrefix(s, "-L") { 439 ctx.PropertyErrorf("flags", "'-l' and '-L' flags cannot be manually specified") 440 } 441 if strings.HasPrefix(s, "--extern") { 442 ctx.PropertyErrorf("flags", "'--extern' flag cannot be manually specified") 443 } 444 if strings.HasPrefix(s, "-Clink-args=") || strings.HasPrefix(s, "-C link-args=") { 445 ctx.PropertyErrorf("flags", "'-C link-args' flag cannot be manually specified") 446 } 447 } 448 449 flags.RustFlags = append(flags.RustFlags, lintFlags) 450 flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...) 451 flags.RustFlags = append(flags.RustFlags, "--edition="+compiler.edition()) 452 flags.RustdocFlags = append(flags.RustdocFlags, "--edition="+compiler.edition()) 453 flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...) 454 455 return flags 456} 457 458func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { 459 panic(fmt.Errorf("baseCrater doesn't know how to crate things!")) 460} 461 462func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags, 463 deps PathDeps) android.OptionalPath { 464 465 return android.OptionalPath{} 466} 467 468func (compiler *baseCompiler) initialize(ctx ModuleContext) { 469 compiler.cachedCargoOutDir = android.PathForModuleOut(ctx, genSubDir) 470 if compiler.Properties.Crate_root == nil { 471 compiler.cachedCrateRootPath, compiler.cachedCrateRootError = srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs) 472 } else { 473 compiler.cachedCrateRootPath = android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root) 474 compiler.cachedCrateRootError = nil 475 } 476} 477 478func (compiler *baseCompiler) cargoOutDir() android.OptionalPath { 479 return android.OptionalPathForPath(compiler.cachedCargoOutDir) 480} 481 482func (compiler *baseCompiler) cargoEnvCompat() bool { 483 return Bool(compiler.Properties.Cargo_env_compat) 484} 485 486func (compiler *baseCompiler) cargoPkgVersion() string { 487 return String(compiler.Properties.Cargo_pkg_version) 488} 489 490func (compiler *baseCompiler) unstrippedOutputFilePath() android.Path { 491 return compiler.unstrippedOutputFile 492} 493 494func (compiler *baseCompiler) strippedOutputFilePath() android.OptionalPath { 495 return compiler.strippedOutputFile 496} 497 498func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { 499 deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...) 500 deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs.GetOrDefault(ctx, nil)...) 501 deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...) 502 deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...) 503 deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...) 504 deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...) 505 deps.Stdlibs = append(deps.Stdlibs, compiler.Properties.Stdlibs...) 506 507 if !Bool(compiler.Properties.No_stdlibs) { 508 for _, stdlib := range config.Stdlibs { 509 // If we're building for the build host, use the prebuilt stdlibs, unless the host 510 // is linux_bionic which doesn't have prebuilts. 511 if ctx.Host() && !ctx.Target().HostCross && ctx.Target().Os != android.LinuxBionic { 512 stdlib = "prebuilt_" + stdlib 513 } 514 deps.Stdlibs = append(deps.Stdlibs, stdlib) 515 } 516 } 517 return deps 518} 519 520func bionicDeps(ctx DepsContext, deps Deps, static bool) Deps { 521 bionicLibs := []string{} 522 bionicLibs = append(bionicLibs, "liblog") 523 bionicLibs = append(bionicLibs, "libc") 524 bionicLibs = append(bionicLibs, "libm") 525 bionicLibs = append(bionicLibs, "libdl") 526 527 if static { 528 deps.StaticLibs = append(deps.StaticLibs, bionicLibs...) 529 } else { 530 deps.SharedLibs = append(deps.SharedLibs, bionicLibs...) 531 } 532 if ctx.RustModule().StaticExecutable() { 533 deps.StaticLibs = append(deps.StaticLibs, "libunwind") 534 } 535 if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" { 536 deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins) 537 } 538 return deps 539} 540 541func muslDeps(ctx DepsContext, deps Deps, static bool) Deps { 542 muslLibs := []string{"libc_musl"} 543 if static { 544 deps.StaticLibs = append(deps.StaticLibs, muslLibs...) 545 } else { 546 deps.SharedLibs = append(deps.SharedLibs, muslLibs...) 547 } 548 if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" { 549 deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins) 550 } 551 552 return deps 553} 554 555func (compiler *baseCompiler) crateName() string { 556 return compiler.Properties.Crate_name 557} 558 559func (compiler *baseCompiler) everInstallable() bool { 560 // Most modules are installable, so return true by default. 561 return true 562} 563 564func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath { 565 dir := compiler.dir 566 if ctx.toolchain().Is64Bit() && compiler.dir64 != "" { 567 dir = compiler.dir64 568 } 569 if ctx.Target().NativeBridge == android.NativeBridgeEnabled { 570 dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath) 571 } 572 if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) { 573 dir = filepath.Join(dir, ctx.Arch().ArchType.String()) 574 } 575 576 if compiler.location == InstallInData && ctx.RustModule().InVendorOrProduct() { 577 if ctx.RustModule().InProduct() { 578 dir = filepath.Join(dir, "product") 579 } else if ctx.RustModule().InVendor() { 580 dir = filepath.Join(dir, "vendor") 581 } else { 582 ctx.ModuleErrorf("Unknown data+VNDK installation kind") 583 } 584 } 585 586 return android.PathForModuleInstall(ctx, dir, compiler.subDir, 587 compiler.relativeInstallPath(), compiler.relative) 588} 589 590func (compiler *baseCompiler) nativeCoverage() bool { 591 return false 592} 593 594func (compiler *baseCompiler) install(ctx ModuleContext) { 595 path := ctx.RustModule().OutputFile() 596 compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path(), compiler.installDeps...) 597} 598 599func (compiler *baseCompiler) installTestData(ctx ModuleContext, data []android.DataPath) { 600 installedData := ctx.InstallTestData(compiler.installDir(ctx), data) 601 compiler.installDeps = append(compiler.installDeps, installedData...) 602} 603 604func (compiler *baseCompiler) getStem(ctx android.ModuleContext) string { 605 return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix) 606} 607 608func (compiler *baseCompiler) getStemWithoutSuffix(ctx android.BaseModuleContext) string { 609 stem := ctx.ModuleName() 610 if String(compiler.Properties.Stem) != "" { 611 stem = String(compiler.Properties.Stem) 612 } 613 614 return stem 615} 616 617func (compiler *baseCompiler) relativeInstallPath() string { 618 return String(compiler.Properties.Relative_install_path) 619} 620 621func (compiler *baseCompiler) checkedCrateRootPath() (android.Path, error) { 622 return compiler.cachedCrateRootPath, compiler.cachedCrateRootError 623} 624 625func crateRootPath(ctx ModuleContext, compiler compiler) android.Path { 626 root, err := compiler.checkedCrateRootPath() 627 if err != nil { 628 ctx.PropertyErrorf("srcs", err.Error()) 629 } 630 return root 631} 632 633// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs. 634func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, error) { 635 // The srcs can contain strings with prefix ":". 636 // They are dependent modules of this module, with android.SourceDepTag. 637 // They are not the main source file compiled by rustc. 638 numSrcs := 0 639 srcIndex := 0 640 for i, s := range srcs { 641 if android.SrcIsModule(s) == "" { 642 numSrcs++ 643 srcIndex = i 644 } 645 } 646 if numSrcs > 1 { 647 return nil, errors.New(incorrectSourcesError) 648 } 649 650 // If a main source file is not provided we expect only a single SourceProvider module to be defined 651 // within srcs, with the expectation that the first source it provides is the entry point. 652 if srcIndex != 0 { 653 return nil, errors.New("main source file must be the first in srcs") 654 } else if numSrcs > 1 { 655 return nil, errors.New("only a single generated source module can be defined without a main source file.") 656 } 657 658 // TODO: b/297264540 - once all modules are sandboxed, we need to select the proper 659 // entry point file from Srcs rather than taking the first one 660 paths := android.PathsForModuleSrc(ctx, srcs) 661 if len(paths) == 0 { 662 return nil, errors.New("srcs must not be empty") 663 } 664 return paths[srcIndex], nil 665} 666