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
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 403f466..2224a9c 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -41,12 +41,12 @@
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 @@
// 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 @@
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 c428348..0b529ca 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -55,3 +55,29 @@
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 0195247..7ec2d73 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -722,10 +722,11 @@
}
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 @@
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...)
}