Skip to content

Commit

Permalink
Add support for --wrap-extern-fns to bindgen rules (#2743)
Browse files Browse the repository at this point in the history
  • Loading branch information
hlopko authored Jul 16, 2024
1 parent c177ccc commit 6c2bd67
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 10 deletions.
40 changes: 37 additions & 3 deletions bindgen/private/bindgen.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ load(
"@bazel_tools//tools/build_defs/cc:action_names.bzl",
"CPP_COMPILE_ACTION_NAME",
)
load("@rules_cc//cc:defs.bzl", "CcInfo")
load("@rules_cc//cc:defs.bzl", "CcInfo", "cc_library")
load("//rust:defs.bzl", "rust_library")
load("//rust:rust_common.bzl", "BuildInfo")

Expand Down Expand Up @@ -48,6 +48,7 @@ def rust_bindgen_library(
bindgen_flags = None,
bindgen_features = None,
clang_flags = None,
wrap_static_fns = False,
**kwargs):
"""Generates a rust source file for `header`, and builds a rust_library.
Expand All @@ -60,6 +61,7 @@ def rust_bindgen_library(
bindgen_flags (list, optional): Flags to pass directly to the bindgen executable. See https://rust-lang.github.io/rust-bindgen/ for details.
bindgen_features (list, optional): The `features` attribute for the `rust_bindgen` target.
clang_flags (list, optional): Flags to pass directly to the clang executable.
wrap_static_fns (bool): Whether to create a separate .c file for static fns. Requires nightly toolchain, and a header that actually needs this feature (otherwise bindgen won't generate the file and Bazel complains",
**kwargs: Arguments to forward to the underlying `rust_library` rule.
"""

Expand All @@ -85,6 +87,7 @@ def rust_bindgen_library(
features = bindgen_features,
clang_flags = clang_flags or [],
tags = sub_tags,
wrap_static_fns = wrap_static_fns,
**bindgen_kwargs
)

Expand All @@ -94,10 +97,23 @@ def rust_bindgen_library(
if "deps" in kwargs:
kwargs.pop("deps")

if wrap_static_fns:
native.filegroup(
name = name + "__bindgen_c_thunks",
srcs = [":" + name + "__bindgen"],
output_group = "bindgen_c_thunks",
)

cc_library(
name = name + "__bindgen_c_thunks_library",
srcs = [":" + name + "__bindgen_c_thunks"],
deps = [cc_lib],
)

rust_library(
name = name,
srcs = [name + "__bindgen.rs"],
deps = deps + [name + "__bindgen"],
deps = deps + [":" + name + "__bindgen"] + ([":" + name + "__bindgen_c_thunks_library"] if wrap_static_fns else []),
tags = tags,
**kwargs
)
Expand Down Expand Up @@ -203,6 +219,19 @@ def _rust_bindgen_impl(ctx):
args.add(header)
args.add("--output", output)

wrap_static_fns = getattr(ctx.attr, "wrap_static_fns", False)

c_output = None
if wrap_static_fns:
if "--wrap-static-fns" in ctx.attr.bindgen_flags:
fail("Do not pass `--wrap-static-fns` to `bindgen_flags, it's added automatically." +
"The generated C file is accesible in the `bindgen_c_thunks` output group.")
c_output = ctx.actions.declare_file(ctx.label.name + ".bindgen_c_thunks.c")
args.add("--experimental")
args.add("--wrap-static-fns")
args.add("--wrap-static-fns-path")
args.add(c_output.path)

# Vanilla usage of bindgen produces formatted output, here we do the same if we have `rustfmt` in our toolchain.
rustfmt_toolchain = ctx.toolchains[Label("//rust/rustfmt:toolchain_type")]
if toolchain.default_rustfmt:
Expand Down Expand Up @@ -279,7 +308,7 @@ def _rust_bindgen_impl(ctx):
_get_libs_for_static_executable(libstdcxx),
] if libstdcxx else []),
),
outputs = [output],
outputs = [output] + ([c_output] if wrap_static_fns else []),
mnemonic = "RustBindgen",
progress_message = "Generating bindings for {}..".format(header.path),
env = env,
Expand All @@ -305,6 +334,7 @@ def _rust_bindgen_impl(ctx):
),
OutputGroupInfo(
bindgen_bindings = depset([output]),
bindgen_c_thunks = depset(([c_output] if wrap_static_fns else [])),
),
]

Expand All @@ -328,6 +358,10 @@ rust_bindgen = rule(
allow_single_file = True,
mandatory = True,
),
"wrap_static_fns": attr.bool(
doc = "Whether to create a separate .c file for static fns. Requires nightly toolchain, and a header that actually needs this feature (otherwise bindgen won't generate the file and Bazel complains).",
default = False,
),
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
Expand Down
7 changes: 5 additions & 2 deletions docs/flatten.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ is available under the key `dsym_folder` in `OutputGroupInfo`.
## rust_bindgen

<pre>
rust_bindgen(<a href="#rust_bindgen-name">name</a>, <a href="#rust_bindgen-bindgen_flags">bindgen_flags</a>, <a href="#rust_bindgen-cc_lib">cc_lib</a>, <a href="#rust_bindgen-clang_flags">clang_flags</a>, <a href="#rust_bindgen-header">header</a>)
rust_bindgen(<a href="#rust_bindgen-name">name</a>, <a href="#rust_bindgen-bindgen_flags">bindgen_flags</a>, <a href="#rust_bindgen-cc_lib">cc_lib</a>, <a href="#rust_bindgen-clang_flags">clang_flags</a>, <a href="#rust_bindgen-header">header</a>, <a href="#rust_bindgen-wrap_static_fns">wrap_static_fns</a>)
</pre>

Generates a rust source file from a cc_library and a header.
Expand All @@ -342,6 +342,7 @@ Generates a rust source file from a cc_library and a header.
| <a id="rust_bindgen-cc_lib"></a>cc_lib | The cc_library that contains the `.h` file. This is used to find the transitive includes. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="rust_bindgen-clang_flags"></a>clang_flags | Flags to pass directly to the clang executable. | List of strings | optional | `[]` |
| <a id="rust_bindgen-header"></a>header | The `.h` file to generate bindings for. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="rust_bindgen-wrap_static_fns"></a>wrap_static_fns | Whether to create a separate .c file for static fns. Requires nightly toolchain, and a header that actually needs this feature (otherwise bindgen won't generate the file and Bazel complains). | Boolean | optional | `False` |


<a id="rust_bindgen_toolchain"></a>
Expand Down Expand Up @@ -1668,7 +1669,8 @@ list[struct(repo=str, is_dev_dep=bool)]: A list of the repositories
## rust_bindgen_library

<pre>
rust_bindgen_library(<a href="#rust_bindgen_library-name">name</a>, <a href="#rust_bindgen_library-header">header</a>, <a href="#rust_bindgen_library-cc_lib">cc_lib</a>, <a href="#rust_bindgen_library-bindgen_flags">bindgen_flags</a>, <a href="#rust_bindgen_library-bindgen_features">bindgen_features</a>, <a href="#rust_bindgen_library-clang_flags">clang_flags</a>, <a href="#rust_bindgen_library-kwargs">kwargs</a>)
rust_bindgen_library(<a href="#rust_bindgen_library-name">name</a>, <a href="#rust_bindgen_library-header">header</a>, <a href="#rust_bindgen_library-cc_lib">cc_lib</a>, <a href="#rust_bindgen_library-bindgen_flags">bindgen_flags</a>, <a href="#rust_bindgen_library-bindgen_features">bindgen_features</a>, <a href="#rust_bindgen_library-clang_flags">clang_flags</a>,
<a href="#rust_bindgen_library-wrap_static_fns">wrap_static_fns</a>, <a href="#rust_bindgen_library-kwargs">kwargs</a>)
</pre>

Generates a rust source file for `header`, and builds a rust_library.
Expand All @@ -1687,6 +1689,7 @@ Arguments are the same as `rust_bindgen`, and `kwargs` are passed directly to ru
| <a id="rust_bindgen_library-bindgen_flags"></a>bindgen_flags | Flags to pass directly to the bindgen executable. See https://rust-lang.github.io/rust-bindgen/ for details. | `None` |
| <a id="rust_bindgen_library-bindgen_features"></a>bindgen_features | The `features` attribute for the `rust_bindgen` target. | `None` |
| <a id="rust_bindgen_library-clang_flags"></a>clang_flags | Flags to pass directly to the clang executable. | `None` |
| <a id="rust_bindgen_library-wrap_static_fns"></a>wrap_static_fns | Whether to create a separate .c file for static fns. Requires nightly toolchain, and a header that actually needs this feature (otherwise bindgen won't generate the file and Bazel complains", | `False` |
| <a id="rust_bindgen_library-kwargs"></a>kwargs | Arguments to forward to the underlying `rust_library` rule. | none |


Expand Down
7 changes: 5 additions & 2 deletions docs/rust_bindgen.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ toolchains following the instructions for [rust_bindgen_toolchain](#rust_bindgen
## rust_bindgen

<pre>
rust_bindgen(<a href="#rust_bindgen-name">name</a>, <a href="#rust_bindgen-bindgen_flags">bindgen_flags</a>, <a href="#rust_bindgen-cc_lib">cc_lib</a>, <a href="#rust_bindgen-clang_flags">clang_flags</a>, <a href="#rust_bindgen-header">header</a>)
rust_bindgen(<a href="#rust_bindgen-name">name</a>, <a href="#rust_bindgen-bindgen_flags">bindgen_flags</a>, <a href="#rust_bindgen-cc_lib">cc_lib</a>, <a href="#rust_bindgen-clang_flags">clang_flags</a>, <a href="#rust_bindgen-header">header</a>, <a href="#rust_bindgen-wrap_static_fns">wrap_static_fns</a>)
</pre>

Generates a rust source file from a cc_library and a header.
Expand All @@ -68,6 +68,7 @@ Generates a rust source file from a cc_library and a header.
| <a id="rust_bindgen-cc_lib"></a>cc_lib | The cc_library that contains the `.h` file. This is used to find the transitive includes. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="rust_bindgen-clang_flags"></a>clang_flags | Flags to pass directly to the clang executable. | List of strings | optional | `[]` |
| <a id="rust_bindgen-header"></a>header | The `.h` file to generate bindings for. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="rust_bindgen-wrap_static_fns"></a>wrap_static_fns | Whether to create a separate .c file for static fns. Requires nightly toolchain, and a header that actually needs this feature (otherwise bindgen won't generate the file and Bazel complains). | Boolean | optional | `False` |


<a id="rust_bindgen_toolchain"></a>
Expand Down Expand Up @@ -140,7 +141,8 @@ list[struct(repo=str, is_dev_dep=bool)]: A list of the repositories
## rust_bindgen_library

<pre>
rust_bindgen_library(<a href="#rust_bindgen_library-name">name</a>, <a href="#rust_bindgen_library-header">header</a>, <a href="#rust_bindgen_library-cc_lib">cc_lib</a>, <a href="#rust_bindgen_library-bindgen_flags">bindgen_flags</a>, <a href="#rust_bindgen_library-bindgen_features">bindgen_features</a>, <a href="#rust_bindgen_library-clang_flags">clang_flags</a>, <a href="#rust_bindgen_library-kwargs">kwargs</a>)
rust_bindgen_library(<a href="#rust_bindgen_library-name">name</a>, <a href="#rust_bindgen_library-header">header</a>, <a href="#rust_bindgen_library-cc_lib">cc_lib</a>, <a href="#rust_bindgen_library-bindgen_flags">bindgen_flags</a>, <a href="#rust_bindgen_library-bindgen_features">bindgen_features</a>, <a href="#rust_bindgen_library-clang_flags">clang_flags</a>,
<a href="#rust_bindgen_library-wrap_static_fns">wrap_static_fns</a>, <a href="#rust_bindgen_library-kwargs">kwargs</a>)
</pre>

Generates a rust source file for `header`, and builds a rust_library.
Expand All @@ -159,6 +161,7 @@ Arguments are the same as `rust_bindgen`, and `kwargs` are passed directly to ru
| <a id="rust_bindgen_library-bindgen_flags"></a>bindgen_flags | Flags to pass directly to the bindgen executable. See https://rust-lang.github.io/rust-bindgen/ for details. | `None` |
| <a id="rust_bindgen_library-bindgen_features"></a>bindgen_features | The `features` attribute for the `rust_bindgen` target. | `None` |
| <a id="rust_bindgen_library-clang_flags"></a>clang_flags | Flags to pass directly to the clang executable. | `None` |
| <a id="rust_bindgen_library-wrap_static_fns"></a>wrap_static_fns | Whether to create a separate .c file for static fns. Requires nightly toolchain, and a header that actually needs this feature (otherwise bindgen won't generate the file and Bazel complains", | `False` |
| <a id="rust_bindgen_library-kwargs"></a>kwargs | Arguments to forward to the underlying `rust_library` rule. | none |


Expand Down
1 change: 1 addition & 0 deletions examples/bindgen/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ rust_bindgen_library(
],
cc_lib = "//bindgen/simple",
header = "//bindgen/simple:simple.h",
wrap_static_fns = True,
)

rust_binary(
Expand Down
10 changes: 8 additions & 2 deletions examples/bindgen/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ fn simple_function() -> i64 {
unsafe { simple_bindgen::simple_function() }
}

fn simple_static_function() -> i64 {
unsafe { simple_bindgen::simple_static_function() }
}

fn main() {
println!(
"The values are {} and {}!",
"The values are {}, {}, and {}!",
simple_bindgen::SIMPLE_VALUE,
simple_function()
simple_function(),
simple_static_function(),
);
}

Expand All @@ -18,5 +23,6 @@ mod test {
fn do_the_test() {
assert_eq!(42, simple_bindgen::SIMPLE_VALUE);
assert_eq!(1337, super::simple_function());
assert_eq!(84, super::simple_static_function());
}
}
4 changes: 3 additions & 1 deletion examples/bindgen/simple/simple.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@

#include <stdint.h>

EXTERN_C const int64_t SIMPLE_VALUE = 42;
static const int64_t SIMPLE_VALUE = 42;

EXTERN_C const int64_t simple_function();

static inline int64_t simple_static_function() { return 84; }

#endif

0 comments on commit 6c2bd67

Please sign in to comment.