diff --git a/rust/binary.go b/rust/binary.go index 9fc52cdb8..48f51dbdf 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -107,7 +107,7 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path fileName := binary.getStem(ctx) + ctx.toolchain().ExecutableSuffix() srcPath, paths := srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs) - deps.SrcDeps = paths + deps.SrcDeps = append(deps.SrcDeps, paths...) outputFile := android.PathForModuleOut(ctx, fileName) binary.unstrippedOutputFile = outputFile diff --git a/rust/builder.go b/rust/builder.go index 7f94bb514..d1d10122b 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -28,7 +28,7 @@ var ( _ = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc") rustc = pctx.AndroidStaticRule("rustc", blueprint.RuleParams{ - Command: "$rustcCmd " + + Command: "$envVars $rustcCmd " + "-C linker=${config.RustLinker} " + "-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " + "--emit link -o $out --emit dep-info=$out.d $in ${libFlags} $rustcFlags", @@ -37,7 +37,7 @@ var ( Deps: blueprint.DepsGCC, Depfile: "$out.d", }, - "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd") + "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars") _ = pctx.SourcePathVariable("clippyCmd", "${config.RustBin}/clippy-driver") clippyDriver = pctx.AndroidStaticRule("clippy", @@ -58,6 +58,14 @@ var ( Rspfile: "$out.rsp", RspfileContent: "$in", }) + + cp = pctx.AndroidStaticRule("cp", + blueprint.RuleParams{ + Command: "cp `cat $outDir.rsp` $outDir", + Rspfile: "${outDir}.rsp", + RspfileContent: "$in", + }, + "outDir") ) type buildOutput struct { @@ -116,6 +124,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl var inputs android.Paths var implicits android.Paths + var envVars []string var output buildOutput var libFlags, rustcFlags, linkFlags []string var implicitOutputs android.WritablePaths @@ -166,7 +175,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...) implicits = append(implicits, deps.StaticLibs...) implicits = append(implicits, deps.SharedLibs...) - implicits = append(implicits, deps.SrcDeps...) + if deps.CrtBegin.Valid() { implicits = append(implicits, deps.CrtBegin.Path(), deps.CrtEnd.Path()) } @@ -209,6 +218,31 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl implicits = append(implicits, clippyFile) } + if len(deps.SrcDeps) > 0 { + moduleGenDir := android.PathForModuleOut(ctx, "out/") + var outputs android.WritablePaths + + for _, genSrc := range deps.SrcDeps { + if android.SuffixInList(outputs.Strings(), "out/"+genSrc.Base()) { + ctx.PropertyErrorf("srcs", + "multiple source providers generate the same filename output: "+genSrc.Base()) + } + outputs = append(outputs, android.PathForModuleOut(ctx, "out/"+genSrc.Base())) + } + + ctx.Build(pctx, android.BuildParams{ + Rule: cp, + Description: "cp " + moduleGenDir.Rel(), + Outputs: outputs, + Inputs: deps.SrcDeps, + Args: map[string]string{ + "outDir": moduleGenDir.String(), + }, + }) + implicits = append(implicits, outputs.Paths()...) + envVars = append(envVars, "OUT_DIR=$$PWD/"+moduleGenDir.String()) + } + ctx.Build(pctx, android.BuildParams{ Rule: rustc, Description: "rustc " + main.Rel(), @@ -222,6 +256,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl "libFlags": strings.Join(libFlags, " "), "crtBegin": deps.CrtBegin.String(), "crtEnd": deps.CrtEnd.String(), + "envVars": strings.Join(envVars, " "), }, }) diff --git a/rust/compiler.go b/rust/compiler.go index c20179bd0..ab3d2f44a 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -46,6 +46,8 @@ type installLocation int const ( InstallInSystem installLocation = 0 InstallInData = iota + + incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\"" ) type BaseCompilerProperties struct { @@ -253,6 +255,7 @@ func (compiler *baseCompiler) relativeInstallPath() string { return String(compiler.Properties.Relative_install_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) { // The srcs can contain strings with prefix ":". // They are dependent modules of this module, with android.SourceDepTag. @@ -266,11 +269,11 @@ func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, andr } } if numSrcs != 1 { - ctx.PropertyErrorf("srcs", "srcs can only contain one path for a rust file") + ctx.PropertyErrorf("srcs", incorrectSourcesError) } if srcIndex != 0 { ctx.PropertyErrorf("srcs", "main source file must be the first in srcs") } paths := android.PathsForModuleSrc(ctx, srcs) - return paths[srcIndex], paths + return paths[srcIndex], paths[1:] } diff --git a/rust/compiler_test.go b/rust/compiler_test.go index 58ca52a0c..b85319643 100644 --- a/rust/compiler_test.go +++ b/rust/compiler_test.go @@ -43,7 +43,7 @@ func TestFeaturesToFlags(t *testing.T) { // Test that we reject multiple source files. func TestEnforceSingleSourceFile(t *testing.T) { - singleSrcError := "srcs can only contain one path for a rust file" + singleSrcError := "srcs can only contain one path for a rust file and source providers prefixed by \":\"" // Test libraries testRustError(t, singleSrcError, ` diff --git a/rust/library.go b/rust/library.go index d718eb897..acca25627 100644 --- a/rust/library.go +++ b/rust/library.go @@ -369,7 +369,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa var outputFile android.WritablePath srcPath, paths := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs) - deps.SrcDeps = paths + deps.SrcDeps = append(deps.SrcDeps, paths...) flags.RustFlags = append(flags.RustFlags, deps.depFlags...) diff --git a/rust/prebuilt.go b/rust/prebuilt.go index 3b4f40a55..3d081c113 100644 --- a/rust/prebuilt.go +++ b/rust/prebuilt.go @@ -96,7 +96,9 @@ func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags prebuilt.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...) srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs()) - deps.SrcDeps = paths + if len(paths) > 0 { + ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)") + } prebuilt.unstrippedOutputFile = srcPath diff --git a/rust/proc_macro.go b/rust/proc_macro.go index 49dbd8dc2..2752dc3aa 100644 --- a/rust/proc_macro.go +++ b/rust/proc_macro.go @@ -66,7 +66,7 @@ func (procMacro *procMacroDecorator) compile(ctx ModuleContext, flags Flags, dep outputFile := android.PathForModuleOut(ctx, fileName) srcPath, paths := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs) - deps.SrcDeps = paths + deps.SrcDeps = append(deps.SrcDeps, paths...) procMacro.unstrippedOutputFile = outputFile diff --git a/rust/rust.go b/rust/rust.go index 51eaf6838..28f8e1a62 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -62,9 +62,10 @@ type BaseProperties struct { AndroidMkProcMacroLibs []string AndroidMkSharedLibs []string AndroidMkStaticLibs []string - SubName string `blueprint:"mutated"` - PreventInstall bool - HideFromMake bool + + SubName string `blueprint:"mutated"` + PreventInstall bool + HideFromMake bool } type Module struct { @@ -87,6 +88,22 @@ type Module struct { subName string } +func (mod *Module) OutputFiles(tag string) (android.Paths, error) { + switch tag { + case "": + if mod.sourceProvider != nil { + return mod.sourceProvider.Srcs(), nil + } else { + if mod.outputFile.Valid() { + return android.Paths{mod.outputFile.Path()}, nil + } + return android.Paths{}, nil + } + default: + return nil, fmt.Errorf("unsupported module reference tag %q", tag) + } +} + var _ android.ImageInterface = (*Module)(nil) func (mod *Module) ImageMutatorBegin(ctx android.BaseModuleContext) {} @@ -860,7 +877,6 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // Dedup exported flags from dependencies depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs) depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags) - depPaths.SrcDeps = android.FirstUniquePaths(depPaths.SrcDeps) return depPaths } @@ -977,3 +993,5 @@ var Bool = proptools.Bool var BoolDefault = proptools.BoolDefault var String = proptools.String var StringPtr = proptools.StringPtr + +var _ android.OutputFileProducer = (*Module)(nil) diff --git a/rust/rust_test.go b/rust/rust_test.go index e80392589..89dfb67e1 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -182,7 +182,7 @@ func TestDepsTracking(t *testing.T) { } rust_library_host_rlib { name: "librlib", - srcs: ["foo.rs", ":my_generator"], + srcs: ["foo.rs"], crate_name: "rlib", } rust_proc_macro { @@ -190,38 +190,17 @@ func TestDepsTracking(t *testing.T) { srcs: ["foo.rs"], crate_name: "pm", } - genrule { - name: "my_generator", - tools: ["any_rust_binary"], - cmd: "$(location) -o $(out) $(in)", - srcs: ["src/any.h"], - out: ["src/any.rs"], - } rust_binary_host { - name: "fizz-buzz-dep", + name: "fizz-buzz", dylibs: ["libdylib"], rlibs: ["librlib"], proc_macros: ["libpm"], static_libs: ["libstatic"], shared_libs: ["libshared"], - srcs: [ - "foo.rs", - ":my_generator", - ], + srcs: ["foo.rs"], } `) - module := ctx.ModuleForTests("fizz-buzz-dep", "linux_glibc_x86_64").Module().(*Module) - rlibmodule := ctx.ModuleForTests("librlib", "linux_glibc_x86_64_rlib").Module().(*Module) - - srcs := module.compiler.(*binaryDecorator).baseCompiler.Properties.Srcs - if len(srcs) != 2 || !android.InList(":my_generator", srcs) { - t.Errorf("missing module dependency in fizz-buzz)") - } - - srcs = rlibmodule.compiler.(*libraryDecorator).baseCompiler.Properties.Srcs - if len(srcs) != 2 || !android.InList(":my_generator", srcs) { - t.Errorf("missing module dependency in rlib") - } + module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module) // Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up. if !android.InList("libdylib", module.Properties.AndroidMkDylibs) { @@ -245,6 +224,73 @@ func TestDepsTracking(t *testing.T) { } } +func TestSourceProviderDeps(t *testing.T) { + ctx := testRust(t, ` + rust_binary { + name: "fizz-buzz-dep", + srcs: [ + "foo.rs", + ":my_generator", + ":libbindings", + ], + } + rust_proc_macro { + name: "libprocmacro", + srcs: [ + "foo.rs", + ":my_generator", + ":libbindings", + ], + crate_name: "procmacro", + } + rust_library { + name: "libfoo", + srcs: [ + "foo.rs", + ":my_generator", + ":libbindings"], + crate_name: "foo", + } + genrule { + name: "my_generator", + tools: ["any_rust_binary"], + cmd: "$(location) -o $(out) $(in)", + srcs: ["src/any.h"], + out: ["src/any.rs"], + } + rust_bindgen { + name: "libbindings", + stem: "bindings", + host_supported: true, + wrapper_src: "src/any.h", + } + `) + + libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib").Rule("rustc") + if !android.SuffixInList(libfoo.Implicits.Strings(), "/out/bindings.rs") { + t.Errorf("rust_bindgen generated source not included as implicit input for libfoo; Implicits %#v", libfoo.Implicits.Strings()) + } + if !android.SuffixInList(libfoo.Implicits.Strings(), "/out/any.rs") { + t.Errorf("genrule generated source not included as implicit input for libfoo; Implicits %#v", libfoo.Implicits.Strings()) + } + + fizzBuzz := ctx.ModuleForTests("fizz-buzz-dep", "android_arm64_armv8-a").Rule("rustc") + if !android.SuffixInList(fizzBuzz.Implicits.Strings(), "/out/bindings.rs") { + t.Errorf("rust_bindgen generated source not included as implicit input for fizz-buzz-dep; Implicits %#v", libfoo.Implicits.Strings()) + } + if !android.SuffixInList(fizzBuzz.Implicits.Strings(), "/out/any.rs") { + t.Errorf("genrule generated source not included as implicit input for fizz-buzz-dep; Implicits %#v", libfoo.Implicits.Strings()) + } + + libprocmacro := ctx.ModuleForTests("libprocmacro", "linux_glibc_x86_64").Rule("rustc") + if !android.SuffixInList(libprocmacro.Implicits.Strings(), "/out/bindings.rs") { + t.Errorf("rust_bindgen generated source not included as implicit input for libprocmacro; Implicits %#v", libfoo.Implicits.Strings()) + } + if !android.SuffixInList(libprocmacro.Implicits.Strings(), "/out/any.rs") { + t.Errorf("genrule generated source not included as implicit input for libprocmacro; Implicits %#v", libfoo.Implicits.Strings()) + } +} + // Test to make sure proc_macros use host variants when building device modules. func TestProcMacroDeviceDeps(t *testing.T) { ctx := testRust(t, `