diff --git a/rust/binary.go b/rust/binary.go index 146c683fb..5e7e922cf 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -137,7 +137,7 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path fileName := binary.getStem(ctx) + ctx.toolchain().ExecutableSuffix() outputFile := android.PathForModuleOut(ctx, fileName) ret := buildOutput{outputFile: outputFile} - crateRootPath := binary.crateRootPath(ctx) + crateRootPath := crateRootPath(ctx, binary) flags.RustFlags = append(flags.RustFlags, deps.depFlags...) flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...) diff --git a/rust/compiler.go b/rust/compiler.go index 899502a64..e2415a4a7 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -16,6 +16,7 @@ package rust import ( "android/soong/cc" + "errors" "fmt" "path/filepath" "strings" @@ -71,7 +72,7 @@ type compiler interface { unstrippedOutputFilePath() android.Path strippedOutputFilePath() android.OptionalPath - crateRootPath(ctx ModuleContext) android.Path + checkedCrateRootPath() (android.Path, error) } func (compiler *baseCompiler) edition() string { @@ -248,6 +249,12 @@ type baseCompiler struct { // singleton-generation passes like rustdoc/rust_project.json, but should // be stashed during initial generation. cachedCargoOutDir android.ModuleOutPath + // Calculated crate root cached internally because ModuleContext is not + // available to singleton targets like rustdoc/rust_project.json + cachedCrateRootPath android.Path + // If cachedCrateRootPath is nil after initialization, this will contain + // an explanation of why + cachedCrateRootError error } func (compiler *baseCompiler) Disabled() bool { @@ -399,6 +406,12 @@ func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags, func (compiler *baseCompiler) initialize(ctx ModuleContext) { compiler.cachedCargoOutDir = android.PathForModuleOut(ctx, genSubDir) + if compiler.Properties.Crate_root == nil { + compiler.cachedCrateRootPath, compiler.cachedCrateRootError = srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs) + } else { + compiler.cachedCrateRootPath = android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root) + compiler.cachedCrateRootError = nil + } } func (compiler *baseCompiler) cargoOutDir() android.OptionalPath { @@ -539,21 +552,20 @@ func (compiler *baseCompiler) relativeInstallPath() string { return String(compiler.Properties.Relative_install_path) } -func (compiler *baseCompiler) crateRootPath(ctx ModuleContext) android.Path { - if compiler.Properties.Crate_root == nil { - path := srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs) - return path - } else { - return android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root) +func (compiler *baseCompiler) checkedCrateRootPath() (android.Path, error) { + return compiler.cachedCrateRootPath, compiler.cachedCrateRootError +} + +func crateRootPath(ctx ModuleContext, compiler compiler) android.Path { + root, err := compiler.checkedCrateRootPath() + if err != nil { + ctx.PropertyErrorf("srcs", err.Error()) } + return root } // Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs. -func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) android.Path { - if len(srcs) == 0 { - ctx.PropertyErrorf("srcs", "srcs must not be empty") - } - +func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, error) { // The srcs can contain strings with prefix ":". // They are dependent modules of this module, with android.SourceDepTag. // They are not the main source file compiled by rustc. @@ -566,19 +578,22 @@ func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) android.Path { } } if numSrcs > 1 { - ctx.PropertyErrorf("srcs", incorrectSourcesError) + return nil, errors.New(incorrectSourcesError) } // If a main source file is not provided we expect only a single SourceProvider module to be defined // within srcs, with the expectation that the first source it provides is the entry point. if srcIndex != 0 { - ctx.PropertyErrorf("srcs", "main source file must be the first in srcs") + return nil, errors.New("main source file must be the first in srcs") } else if numSrcs > 1 { - ctx.PropertyErrorf("srcs", "only a single generated source module can be defined without a main source file.") + return nil, errors.New("only a single generated source module can be defined without a main source file.") } // TODO: b/297264540 - once all modules are sandboxed, we need to select the proper // entry point file from Srcs rather than taking the first one paths := android.PathsForModuleSrc(ctx, srcs) - return paths[srcIndex] + if len(paths) == 0 { + return nil, errors.New("srcs must not be empty") + } + return paths[srcIndex], nil } diff --git a/rust/library.go b/rust/library.go index 613e9b76f..c0ff741db 100644 --- a/rust/library.go +++ b/rust/library.go @@ -15,6 +15,7 @@ package rust import ( + "errors" "fmt" "regexp" "strings" @@ -489,7 +490,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa var outputFile android.ModuleOutPath var ret buildOutput var fileName string - crateRootPath := library.crateRootPath(ctx) + crateRootPath := crateRootPath(ctx, library) if library.sourceProvider != nil { deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...) @@ -584,12 +585,16 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa return ret } -func (library *libraryDecorator) crateRootPath(ctx ModuleContext) android.Path { +func (library *libraryDecorator) checkedCrateRootPath() (android.Path, error) { if library.sourceProvider != nil { + srcs := library.sourceProvider.Srcs() + if len(srcs) == 0 { + return nil, errors.New("Source provider generated 0 sources") + } // Assume the first source from the source provider is the library entry point. - return library.sourceProvider.Srcs()[0] + return srcs[0], nil } else { - return library.baseCompiler.crateRootPath(ctx) + return library.baseCompiler.checkedCrateRootPath() } } @@ -604,7 +609,7 @@ func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags, return android.OptionalPath{} } - return android.OptionalPathForPath(Rustdoc(ctx, library.crateRootPath(ctx), + return android.OptionalPathForPath(Rustdoc(ctx, crateRootPath(ctx, library), deps, flags)) } diff --git a/rust/proc_macro.go b/rust/proc_macro.go index e3a48bff6..8a0543dcd 100644 --- a/rust/proc_macro.go +++ b/rust/proc_macro.go @@ -79,7 +79,7 @@ func (procMacro *procMacroDecorator) compile(ctx ModuleContext, flags Flags, dep fileName := procMacro.getStem(ctx) + ctx.toolchain().ProcMacroSuffix() outputFile := android.PathForModuleOut(ctx, fileName) - srcPath := procMacro.crateRootPath(ctx) + srcPath := crateRootPath(ctx, procMacro) ret := TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile) procMacro.baseCompiler.unstrippedOutputFile = outputFile return ret