From 689d6f63e4cf97b30385f357dd2165207f51d0c0 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Mon, 20 Nov 2023 17:49:25 +0000 Subject: rust: Move compiler interface to compiler.go Refactor cleanup Bug: 309943184 Test: m nothing Change-Id: I7dcb0af64a4db71fdc46c0876b22e5015c02438e --- rust/compiler.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'rust/compiler.go') diff --git a/rust/compiler.go b/rust/compiler.go index b3f574d57..3c9f6d4a4 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -34,6 +34,44 @@ const ( DylibLinkage ) +type compiler interface { + initialize(ctx ModuleContext) + compilerFlags(ctx ModuleContext, flags Flags) Flags + cfgFlags(ctx ModuleContext, flags Flags) Flags + featureFlags(ctx ModuleContext, flags Flags) Flags + compilerProps() []interface{} + compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput + compilerDeps(ctx DepsContext, deps Deps) Deps + crateName() string + rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath + + // Output directory in which source-generated code from dependencies is + // copied. This is equivalent to Cargo's OUT_DIR variable. + CargoOutDir() android.OptionalPath + + // CargoPkgVersion returns the value of the Cargo_pkg_version property. + CargoPkgVersion() string + + // CargoEnvCompat returns whether Cargo environment variables should be used. + CargoEnvCompat() bool + + inData() bool + install(ctx ModuleContext) + relativeInstallPath() string + everInstallable() bool + + nativeCoverage() bool + + Disabled() bool + SetDisabled() + + stdLinkage(ctx *depsContext) RustLinkage + noStdlibs() bool + + unstrippedOutputFilePath() android.Path + strippedOutputFilePath() android.OptionalPath +} + func (compiler *baseCompiler) edition() string { return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) } -- cgit v1.2.3-59-g8ed1b From cd41653b96d2285b11b010198e453cf688b66cbe Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Mon, 20 Nov 2023 17:52:01 +0000 Subject: rust: Privatize Cargo* methods on compiler These methods aren't used outside, and probably shouldn't be. Bug: 309943184 Test: m nothing Change-Id: Ia7dd5220ccd10c0136aa16f5e21149eaf7a03ea1 --- rust/builder.go | 8 ++++---- rust/compiler.go | 25 ++++++++++++++----------- rust/project_json.go | 4 ++-- 3 files changed, 20 insertions(+), 17 deletions(-) (limited to 'rust/compiler.go') diff --git a/rust/builder.go b/rust/builder.go index 162d1aab0..c855cfbd2 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -196,7 +196,7 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps) []string { } if len(deps.SrcDeps) > 0 { - moduleGenDir := ctx.RustModule().compiler.CargoOutDir() + moduleGenDir := ctx.RustModule().compiler.cargoOutDir() // We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this) // assumes that paths are relative to the source file. var outDirPrefix string @@ -215,13 +215,13 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps) []string { envVars = append(envVars, "ANDROID_RUST_VERSION="+config.GetRustVersion(ctx)) - if ctx.RustModule().compiler.CargoEnvCompat() { + if ctx.RustModule().compiler.cargoEnvCompat() { if bin, ok := ctx.RustModule().compiler.(*binaryDecorator); ok { envVars = append(envVars, "CARGO_BIN_NAME="+bin.getStem(ctx)) } envVars = append(envVars, "CARGO_CRATE_NAME="+ctx.RustModule().CrateName()) envVars = append(envVars, "CARGO_PKG_NAME="+ctx.RustModule().CrateName()) - pkgVersion := ctx.RustModule().compiler.CargoPkgVersion() + pkgVersion := ctx.RustModule().compiler.cargoPkgVersion() if pkgVersion != "" { envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion) @@ -327,7 +327,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl orderOnly = append(orderOnly, deps.SharedLibs...) if len(deps.SrcDeps) > 0 { - moduleGenDir := ctx.RustModule().compiler.CargoOutDir() + moduleGenDir := ctx.RustModule().compiler.cargoOutDir() var outputs android.WritablePaths for _, genSrc := range deps.SrcDeps { diff --git a/rust/compiler.go b/rust/compiler.go index 3c9f6d4a4..9666ce296 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -47,13 +47,13 @@ type compiler interface { // Output directory in which source-generated code from dependencies is // copied. This is equivalent to Cargo's OUT_DIR variable. - CargoOutDir() android.OptionalPath + cargoOutDir() android.OptionalPath - // CargoPkgVersion returns the value of the Cargo_pkg_version property. - CargoPkgVersion() string + // cargoPkgVersion returns the value of the Cargo_pkg_version property. + cargoPkgVersion() string - // CargoEnvCompat returns whether Cargo environment variables should be used. - CargoEnvCompat() bool + // cargoEnvCompat returns whether Cargo environment variables should be used. + cargoEnvCompat() bool inData() bool install(ctx ModuleContext) @@ -242,7 +242,10 @@ type baseCompiler struct { // If a crate has a source-generated dependency, a copy of the source file // will be available in cargoOutDir (equivalent to Cargo OUT_DIR). - cargoOutDir android.ModuleOutPath + // This is stored internally because it may not be available during + // singleton-generation passes like rustdoc/rust_project.json, but should + // be stashed during initial generation. + cachedCargoOutDir android.ModuleOutPath } func (compiler *baseCompiler) Disabled() bool { @@ -393,18 +396,18 @@ func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags, } func (compiler *baseCompiler) initialize(ctx ModuleContext) { - compiler.cargoOutDir = android.PathForModuleOut(ctx, genSubDir) + compiler.cachedCargoOutDir = android.PathForModuleOut(ctx, genSubDir) } -func (compiler *baseCompiler) CargoOutDir() android.OptionalPath { - return android.OptionalPathForPath(compiler.cargoOutDir) +func (compiler *baseCompiler) cargoOutDir() android.OptionalPath { + return android.OptionalPathForPath(compiler.cachedCargoOutDir) } -func (compiler *baseCompiler) CargoEnvCompat() bool { +func (compiler *baseCompiler) cargoEnvCompat() bool { return Bool(compiler.Properties.Cargo_env_compat) } -func (compiler *baseCompiler) CargoPkgVersion() string { +func (compiler *baseCompiler) cargoPkgVersion() string { return String(compiler.Properties.Cargo_pkg_version) } diff --git a/rust/project_json.go b/rust/project_json.go index 40aa7c736..9a9c600a7 100644 --- a/rust/project_json.go +++ b/rust/project_json.go @@ -241,8 +241,8 @@ func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContex ProcMacro: procMacro, } - if comp.CargoOutDir().Valid() { - crate.Env["OUT_DIR"] = comp.CargoOutDir().String() + if comp.cargoOutDir().Valid() { + crate.Env["OUT_DIR"] = comp.cargoOutDir().String() } for _, feature := range comp.Properties.Features { -- cgit v1.2.3-59-g8ed1b From d221d315340476b27308e205311d458ac440e17b Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Mon, 20 Nov 2023 21:02:40 +0000 Subject: rust: move crateRootPath to compiler Test: m nothing Bug: 309943184 Change-Id: I45028945357c394301d93ca7995a4f9adf281931 --- rust/compiler.go | 11 +++++++++++ rust/library.go | 11 ++++------- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'rust/compiler.go') diff --git a/rust/compiler.go b/rust/compiler.go index 9666ce296..98bbcb645 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -70,6 +70,8 @@ type compiler interface { unstrippedOutputFilePath() android.Path strippedOutputFilePath() android.OptionalPath + + crateRootPath(ctx ModuleContext) android.Path } func (compiler *baseCompiler) edition() string { @@ -537,6 +539,15 @@ 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) + } +} + // 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, android.Paths) { if len(srcs) == 0 { diff --git a/rust/library.go b/rust/library.go index 18bf0a05b..613e9b76f 100644 --- a/rust/library.go +++ b/rust/library.go @@ -489,7 +489,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, deps) + crateRootPath := library.crateRootPath(ctx) if library.sourceProvider != nil { deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...) @@ -584,15 +584,12 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa return ret } -func (library *libraryDecorator) crateRootPath(ctx ModuleContext, _ PathDeps) android.Path { +func (library *libraryDecorator) crateRootPath(ctx ModuleContext) android.Path { if library.sourceProvider != nil { // Assume the first source from the source provider is the library entry point. return library.sourceProvider.Srcs()[0] - } else if library.baseCompiler.Properties.Crate_root == nil { - path, _ := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs) - return path } else { - return android.PathForModuleSrc(ctx, *library.baseCompiler.Properties.Crate_root) + return library.baseCompiler.crateRootPath(ctx) } } @@ -607,7 +604,7 @@ func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags, return android.OptionalPath{} } - return android.OptionalPathForPath(Rustdoc(ctx, library.crateRootPath(ctx, deps), + return android.OptionalPathForPath(Rustdoc(ctx, library.crateRootPath(ctx), deps, flags)) } -- cgit v1.2.3-59-g8ed1b From 1d8e20d744bae14ab3814125e6d9ac28b9fc97e3 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Mon, 20 Nov 2023 21:18:12 +0000 Subject: rust: internalize srcPathFromModuleSrcs This was frequently misused (for example, in the prebuilts module, it was used as a complex "assert(len(srcs))==1"), and can be superceded by getCrateRoot anywhere it was used. It's now only called from compiler.go, and can drop the second return parameter, as it was only actually used by the prebuilt assert misuse. Bug: 309943184 Test: m nothing Change-Id: I6c92580bc8f0ecb7586c544056b5409e6dd280e7 --- rust/binary.go | 7 +------ rust/compiler.go | 6 +++--- rust/compiler_test.go | 3 ++- rust/prebuilt.go | 23 +++++++++++++---------- rust/proc_macro.go | 2 +- 5 files changed, 20 insertions(+), 21 deletions(-) (limited to 'rust/compiler.go') diff --git a/rust/binary.go b/rust/binary.go index 860dc948a..146c683fb 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -137,12 +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} - var crateRootPath android.Path - if binary.baseCompiler.Properties.Crate_root == nil { - crateRootPath, _ = srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs) - } else { - crateRootPath = android.PathForModuleSrc(ctx, *binary.baseCompiler.Properties.Crate_root) - } + crateRootPath := binary.crateRootPath(ctx) 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 98bbcb645..899502a64 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -541,7 +541,7 @@ func (compiler *baseCompiler) relativeInstallPath() string { func (compiler *baseCompiler) crateRootPath(ctx ModuleContext) android.Path { if compiler.Properties.Crate_root == nil { - path, _ := srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs) + path := srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs) return path } else { return android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root) @@ -549,7 +549,7 @@ func (compiler *baseCompiler) crateRootPath(ctx ModuleContext) android.Path { } // 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, android.Paths) { +func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) android.Path { if len(srcs) == 0 { ctx.PropertyErrorf("srcs", "srcs must not be empty") } @@ -580,5 +580,5 @@ func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, andr // 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], paths[1:] + return paths[srcIndex] } diff --git a/rust/compiler_test.go b/rust/compiler_test.go index ec6829a1b..89f4d1abf 100644 --- a/rust/compiler_test.go +++ b/rust/compiler_test.go @@ -67,6 +67,7 @@ func TestCfgsToFlags(t *testing.T) { func TestEnforceSingleSourceFile(t *testing.T) { singleSrcError := "srcs can only contain one path for a rust file and source providers prefixed by \":\"" + prebuiltSingleSrcError := "prebuilt libraries can only have one entry in srcs" // Test libraries testRustError(t, singleSrcError, ` @@ -90,7 +91,7 @@ func TestEnforceSingleSourceFile(t *testing.T) { }`) // Test prebuilts - testRustError(t, singleSrcError, ` + testRustError(t, prebuiltSingleSrcError, ` rust_prebuilt_dylib { name: "foo-bar-prebuilt", srcs: ["liby.so", "libz.so"], diff --git a/rust/prebuilt.go b/rust/prebuilt.go index fe9d0b5dd..e35e510da 100644 --- a/rust/prebuilt.go +++ b/rust/prebuilt.go @@ -76,6 +76,17 @@ var _ compiler = (*prebuiltProcMacroDecorator)(nil) var _ exportedFlagsProducer = (*prebuiltProcMacroDecorator)(nil) var _ rustPrebuilt = (*prebuiltProcMacroDecorator)(nil) +func prebuiltPath(ctx ModuleContext, prebuilt rustPrebuilt) android.Path { + srcs := android.PathsForModuleSrc(ctx, prebuilt.prebuiltSrcs()) + if len(srcs) == 0 { + ctx.PropertyErrorf("srcs", "srcs must not be empty") + } + if len(srcs) > 1 { + ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)") + } + return srcs[0] +} + func PrebuiltLibraryFactory() android.Module { module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported) return module.Init() @@ -148,11 +159,7 @@ func (prebuilt *prebuiltLibraryDecorator) compilerProps() []interface{} { func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...) prebuilt.flagExporter.setProvider(ctx) - - srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs()) - if len(paths) > 0 { - ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)") - } + srcPath := prebuiltPath(ctx, prebuilt) prebuilt.baseCompiler.unstrippedOutputFile = srcPath return buildOutput{outputFile: srcPath} } @@ -205,11 +212,7 @@ func (prebuilt *prebuiltProcMacroDecorator) compilerProps() []interface{} { func (prebuilt *prebuiltProcMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...) prebuilt.flagExporter.setProvider(ctx) - - srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs()) - if len(paths) > 0 { - ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)") - } + srcPath := prebuiltPath(ctx, prebuilt) prebuilt.baseCompiler.unstrippedOutputFile = srcPath return buildOutput{outputFile: srcPath} } diff --git a/rust/proc_macro.go b/rust/proc_macro.go index b93b24f15..e3a48bff6 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, _ := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs) + srcPath := procMacro.crateRootPath(ctx) ret := TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile) procMacro.baseCompiler.unstrippedOutputFile = outputFile return ret -- cgit v1.2.3-59-g8ed1b From a28404a7b09d3fe7126f1a5863283888377885b0 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Mon, 20 Nov 2023 23:33:28 +0000 Subject: rust: Cache crateRootPath to avoid ctx This makes it possible to call crateRootPath in situations where a ModuleContext is unavailable. Test: m nothing Bug: 309943184 Change-Id: Iee20b0606954a18ca516cdac40917d0016f94a05 --- rust/binary.go | 2 +- rust/compiler.go | 47 +++++++++++++++++++++++++++++++---------------- rust/library.go | 15 ++++++++++----- rust/proc_macro.go | 2 +- 4 files changed, 43 insertions(+), 23 deletions(-) (limited to 'rust/compiler.go') 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 } -// 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 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, 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 -- cgit v1.2.3-59-g8ed1b From db72f7ed803df370951f7a03bd6f6fcad1b357e2 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 21 Nov 2023 00:20:02 +0000 Subject: rust: Resolve crate roots outside rust-project Previously, we manually re-computed crate roots inside project_json for rendering rust-project.json. In addition to added complexity, this meant that generated sources and glob sources would not render correctly - it would select e.g. `src/**.rs` or `:foo` as a crate root. Use a centralized computation of crate roots instead. Bug: 309943184 Test: SOONG_GEN_RUST_PROJECT=1 m nothing, compare rust-project.json Change-Id: I0caddbf600d025a0041f45e69812cdd6f1761234 --- rust/compiler.go | 8 ++- rust/proc_macro.go | 1 - rust/project_json.go | 154 +++++++++++---------------------------------------- 3 files changed, 40 insertions(+), 123 deletions(-) (limited to 'rust/compiler.go') diff --git a/rust/compiler.go b/rust/compiler.go index e2415a4a7..9afaec587 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -44,6 +44,8 @@ type compiler interface { compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput compilerDeps(ctx DepsContext, deps Deps) Deps crateName() string + edition() string + features() []string rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath // Output directory in which source-generated code from dependencies is @@ -307,9 +309,13 @@ func (compiler *baseCompiler) cfgsToFlags() []string { return flags } +func (compiler *baseCompiler) features() []string { + return compiler.Properties.Features +} + func (compiler *baseCompiler) featuresToFlags() []string { flags := []string{} - for _, feature := range compiler.Properties.Features { + for _, feature := range compiler.features() { flags = append(flags, "--cfg 'feature=\""+feature+"\"'") } diff --git a/rust/proc_macro.go b/rust/proc_macro.go index 8a0543dcd..c18d5ec70 100644 --- a/rust/proc_macro.go +++ b/rust/proc_macro.go @@ -78,7 +78,6 @@ func (procMacro *procMacroDecorator) compilerFlags(ctx ModuleContext, flags Flag func (procMacro *procMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { fileName := procMacro.getStem(ctx) + ctx.toolchain().ProcMacroSuffix() outputFile := android.PathForModuleOut(ctx, fileName) - srcPath := crateRootPath(ctx, procMacro) ret := TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile) procMacro.baseCompiler.unstrippedOutputFile = outputFile diff --git a/rust/project_json.go b/rust/project_json.go index 9a9c600a7..83c16ca38 100644 --- a/rust/project_json.go +++ b/rust/project_json.go @@ -17,7 +17,6 @@ package rust import ( "encoding/json" "fmt" - "path" "android/soong/android" ) @@ -60,8 +59,9 @@ type rustProjectJson struct { // crateInfo is used during the processing to keep track of the known crates. type crateInfo struct { - Idx int // Index of the crate in rustProjectJson.Crates slice. - Deps map[string]int // The keys are the module names and not the crate names. + Idx int // Index of the crate in rustProjectJson.Crates slice. + Deps map[string]int // The keys are the module names and not the crate names. + Device bool // True if the crate at idx was a device crate } type projectGeneratorSingleton struct { @@ -77,85 +77,6 @@ func init() { android.RegisterParallelSingletonType("rust_project_generator", rustProjectGeneratorSingleton) } -// sourceProviderVariantSource returns the path to the source file if this -// module variant should be used as a priority. -// -// SourceProvider modules may have multiple variants considered as source -// (e.g., x86_64 and armv8). For a module available on device, use the source -// generated for the target. For a host-only module, use the source generated -// for the host. -func sourceProviderVariantSource(ctx android.SingletonContext, rModule *Module) (string, bool) { - rustLib, ok := rModule.compiler.(*libraryDecorator) - if !ok { - return "", false - } - if rustLib.source() { - switch rModule.hod { - case android.HostSupported, android.HostSupportedNoCross: - if rModule.Target().String() == ctx.Config().BuildOSTarget.String() { - src := rustLib.sourceProvider.Srcs()[0] - return src.String(), true - } - default: - if rModule.Target().String() == ctx.Config().AndroidFirstDeviceTarget.String() { - src := rustLib.sourceProvider.Srcs()[0] - return src.String(), true - } - } - } - return "", false -} - -// sourceProviderSource finds the main source file of a source-provider crate. -func sourceProviderSource(ctx android.SingletonContext, rModule *Module) (string, bool) { - rustLib, ok := rModule.compiler.(*libraryDecorator) - if !ok { - return "", false - } - if rustLib.source() { - // This is a source-variant, check if we are the right variant - // depending on the module configuration. - if src, ok := sourceProviderVariantSource(ctx, rModule); ok { - return src, true - } - } - foundSource := false - sourceSrc := "" - // Find the variant with the source and return its. - ctx.VisitAllModuleVariants(rModule, func(variant android.Module) { - if foundSource { - return - } - // All variants of a source provider library are libraries. - rVariant, _ := variant.(*Module) - variantLib, _ := rVariant.compiler.(*libraryDecorator) - if variantLib.source() { - sourceSrc, ok = sourceProviderVariantSource(ctx, rVariant) - if ok { - foundSource = true - } - } - }) - if !foundSource { - ctx.Errorf("No valid source for source provider found: %v\n", rModule) - } - return sourceSrc, foundSource -} - -// crateSource finds the main source file (.rs) for a crate. -func crateSource(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (string, bool) { - // Basic libraries, executables and tests. - srcs := comp.Properties.Srcs - if len(srcs) != 0 { - return path.Join(ctx.ModuleDir(rModule), srcs[0]), true - } - // SourceProvider libraries. - if rModule.sourceProvider != nil { - return sourceProviderSource(ctx, rModule) - } - return "", false -} - // mergeDependencies visits all the dependencies for module and updates crate and deps // with any new dependency. func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.SingletonContext, @@ -167,7 +88,7 @@ func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.Single return } // Skip unsupported modules. - rChild, compChild, ok := isModuleSupported(ctx, child) + rChild, ok := isModuleSupported(ctx, child) if !ok { return } @@ -175,7 +96,7 @@ func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.Single var childId int cInfo, known := singleton.knownCrates[rChild.Name()] if !known { - childId, ok = singleton.addCrate(ctx, rChild, compChild) + childId, ok = singleton.addCrate(ctx, rChild, make(map[string]int)) if !ok { return } @@ -191,41 +112,22 @@ func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.Single }) } -// isModuleSupported returns the RustModule and baseCompiler if the module +// isModuleSupported returns the RustModule if the module // should be considered for inclusion in rust-project.json. -func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Module, *baseCompiler, bool) { +func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Module, bool) { rModule, ok := module.(*Module) if !ok { - return nil, nil, false - } - if rModule.compiler == nil { - return nil, nil, false + return nil, false } - var comp *baseCompiler - switch c := rModule.compiler.(type) { - case *libraryDecorator: - comp = c.baseCompiler - case *binaryDecorator: - comp = c.baseCompiler - case *testDecorator: - comp = c.binaryDecorator.baseCompiler - case *procMacroDecorator: - comp = c.baseCompiler - case *toolchainLibraryDecorator: - comp = c.baseCompiler - default: - return nil, nil, false - } - return rModule, comp, true + return rModule, true } // addCrate adds a crate to singleton.project.Crates ensuring that required // dependencies are also added. It returns the index of the new crate in // singleton.project.Crates -func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (int, bool) { - rootModule, ok := crateSource(ctx, rModule, comp) - if !ok { - ctx.Errorf("Unable to find source for valid module: %v", rModule) +func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module, deps map[string]int) (int, bool) { + rootModule, err := rModule.compiler.checkedCrateRootPath() + if err != nil { return 0, false } @@ -233,28 +135,33 @@ func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContex crate := rustProjectCrate{ DisplayName: rModule.Name(), - RootModule: rootModule, - Edition: comp.edition(), + RootModule: rootModule.String(), + Edition: rModule.compiler.edition(), Deps: make([]rustProjectDep, 0), Cfg: make([]string, 0), Env: make(map[string]string), ProcMacro: procMacro, } - if comp.cargoOutDir().Valid() { - crate.Env["OUT_DIR"] = comp.cargoOutDir().String() + if rModule.compiler.cargoOutDir().Valid() { + crate.Env["OUT_DIR"] = rModule.compiler.cargoOutDir().String() } - for _, feature := range comp.Properties.Features { + for _, feature := range rModule.compiler.features() { crate.Cfg = append(crate.Cfg, "feature=\""+feature+"\"") } - deps := make(map[string]int) singleton.mergeDependencies(ctx, rModule, &crate, deps) - idx := len(singleton.project.Crates) - singleton.knownCrates[rModule.Name()] = crateInfo{Idx: idx, Deps: deps} - singleton.project.Crates = append(singleton.project.Crates, crate) + var idx int + if cInfo, ok := singleton.knownCrates[rModule.Name()]; ok { + idx = cInfo.Idx + singleton.project.Crates[idx] = crate + } else { + idx = len(singleton.project.Crates) + singleton.project.Crates = append(singleton.project.Crates, crate) + } + singleton.knownCrates[rModule.Name()] = crateInfo{Idx: idx, Deps: deps, Device: rModule.Device()} return idx, true } @@ -262,18 +169,23 @@ func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContex // It visits the dependencies of the module depth-first so the dependency ID can be added to the current module. If the // current module is already in singleton.knownCrates, its dependencies are merged. func (singleton *projectGeneratorSingleton) appendCrateAndDependencies(ctx android.SingletonContext, module android.Module) { - rModule, comp, ok := isModuleSupported(ctx, module) + rModule, ok := isModuleSupported(ctx, module) if !ok { return } // If we have seen this crate already; merge any new dependencies. if cInfo, ok := singleton.knownCrates[module.Name()]; ok { + // If we have a new device variant, override the old one + if !cInfo.Device && rModule.Device() { + singleton.addCrate(ctx, rModule, cInfo.Deps) + return + } crate := singleton.project.Crates[cInfo.Idx] singleton.mergeDependencies(ctx, rModule, &crate, cInfo.Deps) singleton.project.Crates[cInfo.Idx] = crate return } - singleton.addCrate(ctx, rModule, comp) + singleton.addCrate(ctx, rModule, make(map[string]int)) } func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) { -- cgit v1.2.3-59-g8ed1b