From c564d2d5a46af4c213e424ee5a7ad7ff9cb2ba3a Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Tue, 4 Aug 2020 15:43:37 -0400 Subject: [PATCH] Add support for custom bindgen binaries. In some cases customized logic is required to generate the expected bindgen bindings. This adds support for rust_bindgen modules to define a HostTool module to use instead of bindgen. Bug: 161816141 Test: New Soong tests pass. Test: Local test case shows custom_binary module being used for bindgen generation. Change-Id: Id52aec4f25c38206d7e585d8e662be7836aa1d4b --- rust/bindgen.go | 25 +++++++++++++++++++++---- rust/bindgen_test.go | 26 ++++++++++++++++++++++++++ rust/rust.go | 16 ++++++++++++---- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/rust/bindgen.go b/rust/bindgen.go index 403f4665a..2224a9cca 100644 --- a/rust/bindgen.go +++ b/rust/bindgen.go @@ -41,12 +41,12 @@ var ( bindgen = pctx.AndroidStaticRule("bindgen", blueprint.RuleParams{ Command: "CLANG_PATH=$bindgenClang LIBCLANG_PATH=$bindgenLibClang RUSTFMT=${config.RustBin}/rustfmt " + - "$bindgenCmd $flags $in -o $out -- -MD -MF $out.d $cflags", - CommandDeps: []string{"$bindgenCmd"}, + "$cmd $flags $in -o $out -- -MD -MF $out.d $cflags", + CommandDeps: []string{"$cmd"}, Deps: blueprint.DepsGCC, Depfile: "$out.d", }, - "flags", "cflags") + "cmd", "flags", "cflags") ) func init() { @@ -76,6 +76,12 @@ type BindgenProperties struct { // list of shared libraries that provide headers for this binding. Shared_libs []string `android:"arch_variant"` + // module name of a custom binary/script which should be used instead of the 'bindgen' binary. This custom + // binary must expect arguments in a similar fashion to bindgen, e.g. + // + // "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]" + Custom_bindgen string `android:"path"` + //TODO(b/161141999) Add support for headers from cc_library_header modules. } @@ -130,17 +136,28 @@ func (b *bindgenDecorator) generateSource(ctx android.ModuleContext, deps PathDe outputFile := android.PathForModuleOut(ctx, b.baseSourceProvider.getStem(ctx)+".rs") + var cmd, cmdDesc string + if b.Properties.Custom_bindgen != "" { + cmd = ctx.GetDirectDepWithTag(b.Properties.Custom_bindgen, customBindgenDepTag).(*Module).HostToolPath().String() + cmdDesc = b.Properties.Custom_bindgen + } else { + cmd = "$bindgenCmd" + cmdDesc = "bindgen" + } + ctx.Build(pctx, android.BuildParams{ Rule: bindgen, - Description: "bindgen " + wrapperFile.Path().Rel(), + Description: strings.Join([]string{cmdDesc, wrapperFile.Path().Rel()}, " "), Output: outputFile, Input: wrapperFile.Path(), Implicits: implicits, Args: map[string]string{ + "cmd": cmd, "flags": strings.Join(bindgenFlags, " "), "cflags": strings.Join(cflags, " "), }, }) + b.baseSourceProvider.outputFile = outputFile return outputFile } diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go index c42834843..0b529ca5a 100644 --- a/rust/bindgen_test.go +++ b/rust/bindgen_test.go @@ -55,3 +55,29 @@ func TestRustBindgen(t *testing.T) { t.Errorf("missing static_libs exported includes in rust_bindgen rule: cflags %#v", libbindgen.Args["cflags"]) } } + +func TestRustBindgenCustomBindgen(t *testing.T) { + ctx := testRust(t, ` + rust_bindgen { + name: "libbindgen", + wrapper_src: "src/any.h", + crate_name: "bindgen", + stem: "libbindgen", + source_stem: "bindings", + custom_bindgen: "my_bindgen" + } + rust_binary_host { + name: "my_bindgen", + srcs: ["foo.rs"], + } + `) + + libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a").Output("bindings.rs") + + // The rule description should contain the custom binary name rather than bindgen, so checking the description + // should be sufficient. + if !strings.Contains(libbindgen.Description, "my_bindgen") { + t.Errorf("Custom bindgen binary %s not used for libbindgen: rule description %#v", "my_bindgen", + libbindgen.Description) + } +} diff --git a/rust/rust.go b/rust/rust.go index 01952477e..7ec2d736b 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -722,10 +722,11 @@ type dependencyTag struct { } var ( - rlibDepTag = dependencyTag{name: "rlibTag", library: true} - dylibDepTag = dependencyTag{name: "dylib", library: true} - procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true} - testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"} + customBindgenDepTag = dependencyTag{name: "customBindgenTag"} + rlibDepTag = dependencyTag{name: "rlibTag", library: true} + dylibDepTag = dependencyTag{name: "dylib", library: true} + procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true} + testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"} ) type autoDep struct { @@ -1009,6 +1010,13 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { actx.AddVariationDependencies(commonDepVariations, cc.CrtEndDepTag, deps.CrtEnd) } + if mod.sourceProvider != nil { + if bindgen, ok := mod.sourceProvider.(*bindgenDecorator); ok && + bindgen.Properties.Custom_bindgen != "" { + actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), customBindgenDepTag, + bindgen.Properties.Custom_bindgen) + } + } // proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy. actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...) }