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, 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() []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 []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 []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() []string { 350 return compiler.Properties.Features 351} 352 353func (compiler *baseCompiler) featuresToFlags() []string { 354 flags := []string{} 355 for _, feature := range compiler.features() { 356 flags = append(flags, "--cfg 'feature=\""+feature+"\"'") 357 } 358 359 return flags 360} 361 362func (compiler *baseCompiler) featureFlags(ctx ModuleContext, flags Flags) Flags { 363 flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags()...) 364 flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags()...) 365 366 return flags 367} 368 369func CommonDefaultCfgFlags(flags Flags, vendor bool, product bool) Flags { 370 var cfgs []string 371 if vendor || product { 372 cfgs = append(cfgs, "android_vndk") 373 if vendor { 374 cfgs = append(cfgs, "android_vendor") 375 } else if product { 376 cfgs = append(cfgs, "android_product") 377 } 378 } 379 380 flags.RustFlags = append(flags.RustFlags, cfgsToFlags(cfgs)...) 381 flags.RustdocFlags = append(flags.RustdocFlags, cfgsToFlags(cfgs)...) 382 return flags 383} 384 385func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags { 386 flags = CommonDefaultCfgFlags(flags, ctx.RustModule().InVendor(), ctx.RustModule().InProduct()) 387 388 cfgFlags := cfgsToFlags(compiler.Properties.Cfgs.GetOrDefault(ctx, nil)) 389 flags.RustFlags = append(flags.RustFlags, cfgFlags...) 390 flags.RustdocFlags = append(flags.RustdocFlags, cfgFlags...) 391 392 return flags 393} 394 395func CommonDefaultFlags(ctx android.ModuleContext, toolchain config.Toolchain, flags Flags) Flags { 396 flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...) 397 flags.GlobalRustFlags = append(flags.GlobalRustFlags, toolchain.ToolchainRustFlags()) 398 flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, toolchain.ToolchainLinkFlags()) 399 flags.EmitXrefs = ctx.Config().EmitXrefRules() 400 401 if ctx.Host() && !ctx.Windows() { 402 flags.LinkFlags = append(flags.LinkFlags, cc.RpathFlags(ctx)...) 403 } 404 405 if ctx.Os() == android.Linux { 406 // Add -lc, -lrt, -ldl, -lpthread, -lm and -lgcc_s to glibc builds to match 407 // the default behavior of device builds. 408 flags.LinkFlags = append(flags.LinkFlags, config.LinuxHostGlobalLinkFlags...) 409 } else if ctx.Os() == android.Darwin { 410 // Add -lc, -ldl, -lpthread and -lm to glibc darwin builds to match the default 411 // behavior of device builds. 412 flags.LinkFlags = append(flags.LinkFlags, 413 "-lc", 414 "-ldl", 415 "-lpthread", 416 "-lm", 417 ) 418 } 419 return flags 420} 421 422func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags { 423 424 flags = CommonDefaultFlags(ctx, ctx.toolchain(), flags) 425 lintFlags, err := config.RustcLintsForDir(ctx.ModuleDir(), compiler.Properties.Lints) 426 if err != nil { 427 ctx.PropertyErrorf("lints", err.Error()) 428 } 429 430 // linkage-related flags are disallowed. 431 for _, s := range compiler.Properties.Ld_flags { 432 if strings.HasPrefix(s, "-Wl,-l") || strings.HasPrefix(s, "-Wl,-L") { 433 ctx.PropertyErrorf("ld_flags", "'-Wl,-l' and '-Wl,-L' flags cannot be manually specified") 434 } 435 } 436 for _, s := range compiler.Properties.Flags { 437 if strings.HasPrefix(s, "-l") || strings.HasPrefix(s, "-L") { 438 ctx.PropertyErrorf("flags", "'-l' and '-L' flags cannot be manually specified") 439 } 440 if strings.HasPrefix(s, "--extern") { 441 ctx.PropertyErrorf("flags", "'--extern' flag cannot be manually specified") 442 } 443 if strings.HasPrefix(s, "-Clink-args=") || strings.HasPrefix(s, "-C link-args=") { 444 ctx.PropertyErrorf("flags", "'-C link-args' flag cannot be manually specified") 445 } 446 } 447 448 flags.RustFlags = append(flags.RustFlags, lintFlags) 449 flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...) 450 flags.RustFlags = append(flags.RustFlags, "--edition="+compiler.edition()) 451 flags.RustdocFlags = append(flags.RustdocFlags, "--edition="+compiler.edition()) 452 flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...) 453 454 return flags 455} 456 457func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { 458 panic(fmt.Errorf("baseCrater doesn't know how to crate things!")) 459} 460 461func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags, 462 deps PathDeps) android.OptionalPath { 463 464 return android.OptionalPath{} 465} 466 467func (compiler *baseCompiler) initialize(ctx ModuleContext) { 468 compiler.cachedCargoOutDir = android.PathForModuleOut(ctx, genSubDir) 469 if compiler.Properties.Crate_root == nil { 470 compiler.cachedCrateRootPath, compiler.cachedCrateRootError = srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs) 471 } else { 472 compiler.cachedCrateRootPath = android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root) 473 compiler.cachedCrateRootError = nil 474 } 475} 476 477func (compiler *baseCompiler) cargoOutDir() android.OptionalPath { 478 return android.OptionalPathForPath(compiler.cachedCargoOutDir) 479} 480 481func (compiler *baseCompiler) cargoEnvCompat() bool { 482 return Bool(compiler.Properties.Cargo_env_compat) 483} 484 485func (compiler *baseCompiler) cargoPkgVersion() string { 486 return String(compiler.Properties.Cargo_pkg_version) 487} 488 489func (compiler *baseCompiler) unstrippedOutputFilePath() android.Path { 490 return compiler.unstrippedOutputFile 491} 492 493func (compiler *baseCompiler) strippedOutputFilePath() android.OptionalPath { 494 return compiler.strippedOutputFile 495} 496 497func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { 498 deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...) 499 deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...) 500 deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...) 501 deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...) 502 deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...) 503 deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...) 504 deps.Stdlibs = append(deps.Stdlibs, compiler.Properties.Stdlibs...) 505 506 if !Bool(compiler.Properties.No_stdlibs) { 507 for _, stdlib := range config.Stdlibs { 508 // If we're building for the build host, use the prebuilt stdlibs, unless the host 509 // is linux_bionic which doesn't have prebuilts. 510 if ctx.Host() && !ctx.Target().HostCross && ctx.Target().Os != android.LinuxBionic { 511 stdlib = "prebuilt_" + stdlib 512 } 513 deps.Stdlibs = append(deps.Stdlibs, stdlib) 514 } 515 } 516 return deps 517} 518 519func bionicDeps(ctx DepsContext, deps Deps, static bool) Deps { 520 bionicLibs := []string{} 521 bionicLibs = append(bionicLibs, "liblog") 522 bionicLibs = append(bionicLibs, "libc") 523 bionicLibs = append(bionicLibs, "libm") 524 bionicLibs = append(bionicLibs, "libdl") 525 526 if static { 527 deps.StaticLibs = append(deps.StaticLibs, bionicLibs...) 528 } else { 529 deps.SharedLibs = append(deps.SharedLibs, bionicLibs...) 530 } 531 if ctx.RustModule().StaticExecutable() { 532 deps.StaticLibs = append(deps.StaticLibs, "libunwind") 533 } 534 if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" { 535 deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins) 536 } 537 return deps 538} 539 540func muslDeps(ctx DepsContext, deps Deps, static bool) Deps { 541 muslLibs := []string{"libc_musl"} 542 if static { 543 deps.StaticLibs = append(deps.StaticLibs, muslLibs...) 544 } else { 545 deps.SharedLibs = append(deps.SharedLibs, muslLibs...) 546 } 547 if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" { 548 deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins) 549 } 550 551 return deps 552} 553 554func (compiler *baseCompiler) crateName() string { 555 return compiler.Properties.Crate_name 556} 557 558func (compiler *baseCompiler) everInstallable() bool { 559 // Most modules are installable, so return true by default. 560 return true 561} 562 563func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath { 564 dir := compiler.dir 565 if ctx.toolchain().Is64Bit() && compiler.dir64 != "" { 566 dir = compiler.dir64 567 } 568 if ctx.Target().NativeBridge == android.NativeBridgeEnabled { 569 dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath) 570 } 571 if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) { 572 dir = filepath.Join(dir, ctx.Arch().ArchType.String()) 573 } 574 575 if compiler.location == InstallInData && ctx.RustModule().InVendorOrProduct() { 576 if ctx.RustModule().InProduct() { 577 dir = filepath.Join(dir, "product") 578 } else if ctx.RustModule().InVendor() { 579 dir = filepath.Join(dir, "vendor") 580 } else { 581 ctx.ModuleErrorf("Unknown data+VNDK installation kind") 582 } 583 } 584 585 return android.PathForModuleInstall(ctx, dir, compiler.subDir, 586 compiler.relativeInstallPath(), compiler.relative) 587} 588 589func (compiler *baseCompiler) nativeCoverage() bool { 590 return false 591} 592 593func (compiler *baseCompiler) install(ctx ModuleContext) { 594 path := ctx.RustModule().OutputFile() 595 compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path(), compiler.installDeps...) 596} 597 598func (compiler *baseCompiler) installTestData(ctx ModuleContext, data []android.DataPath) { 599 installedData := ctx.InstallTestData(compiler.installDir(ctx), data) 600 compiler.installDeps = append(compiler.installDeps, installedData...) 601} 602 603func (compiler *baseCompiler) getStem(ctx android.ModuleContext) string { 604 return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix) 605} 606 607func (compiler *baseCompiler) getStemWithoutSuffix(ctx android.BaseModuleContext) string { 608 stem := ctx.ModuleName() 609 if String(compiler.Properties.Stem) != "" { 610 stem = String(compiler.Properties.Stem) 611 } 612 613 return stem 614} 615 616func (compiler *baseCompiler) relativeInstallPath() string { 617 return String(compiler.Properties.Relative_install_path) 618} 619 620func (compiler *baseCompiler) checkedCrateRootPath() (android.Path, error) { 621 return compiler.cachedCrateRootPath, compiler.cachedCrateRootError 622} 623 624func crateRootPath(ctx ModuleContext, compiler compiler) android.Path { 625 root, err := compiler.checkedCrateRootPath() 626 if err != nil { 627 ctx.PropertyErrorf("srcs", err.Error()) 628 } 629 return root 630} 631 632// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs. 633func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, error) { 634 // The srcs can contain strings with prefix ":". 635 // They are dependent modules of this module, with android.SourceDepTag. 636 // They are not the main source file compiled by rustc. 637 numSrcs := 0 638 srcIndex := 0 639 for i, s := range srcs { 640 if android.SrcIsModule(s) == "" { 641 numSrcs++ 642 srcIndex = i 643 } 644 } 645 if numSrcs > 1 { 646 return nil, errors.New(incorrectSourcesError) 647 } 648 649 // If a main source file is not provided we expect only a single SourceProvider module to be defined 650 // within srcs, with the expectation that the first source it provides is the entry point. 651 if srcIndex != 0 { 652 return nil, errors.New("main source file must be the first in srcs") 653 } else if numSrcs > 1 { 654 return nil, errors.New("only a single generated source module can be defined without a main source file.") 655 } 656 657 // TODO: b/297264540 - once all modules are sandboxed, we need to select the proper 658 // entry point file from Srcs rather than taking the first one 659 paths := android.PathsForModuleSrc(ctx, srcs) 660 if len(paths) == 0 { 661 return nil, errors.New("srcs must not be empty") 662 } 663 return paths[srcIndex], nil 664} 665