diff --git a/bindgen/private/bindgen.bzl b/bindgen/private/bindgen.bzl index 8606cac9c1..06f0595db2 100644 --- a/bindgen/private/bindgen.bzl +++ b/bindgen/private/bindgen.bzl @@ -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") @@ -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. @@ -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. """ @@ -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 ) @@ -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 ) @@ -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: @@ -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, @@ -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 [])), ), ] @@ -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"), ), diff --git a/docs/flatten.md b/docs/flatten.md index f3d33865af..c828c8df78 100644 --- a/docs/flatten.md +++ b/docs/flatten.md @@ -327,7 +327,7 @@ is available under the key `dsym_folder` in `OutputGroupInfo`. ## rust_bindgen
-rust_bindgen(name, bindgen_flags, cc_lib, clang_flags, header)
+rust_bindgen(name, bindgen_flags, cc_lib, clang_flags, header, wrap_static_fns)
 
Generates a rust source file from a cc_library and a header. @@ -342,6 +342,7 @@ Generates a rust source file from a cc_library and a header. | cc_lib | The cc_library that contains the `.h` file. This is used to find the transitive includes. | Label | required | | | clang_flags | Flags to pass directly to the clang executable. | List of strings | optional | `[]` | | header | The `.h` file to generate bindings for. | Label | required | | +| 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` | @@ -1668,7 +1669,8 @@ list[struct(repo=str, is_dev_dep=bool)]: A list of the repositories ## rust_bindgen_library
-rust_bindgen_library(name, header, cc_lib, bindgen_flags, bindgen_features, clang_flags, kwargs)
+rust_bindgen_library(name, header, cc_lib, bindgen_flags, bindgen_features, clang_flags,
+                     wrap_static_fns, kwargs)
 
Generates a rust source file for `header`, and builds a rust_library. @@ -1687,6 +1689,7 @@ Arguments are the same as `rust_bindgen`, and `kwargs` are passed directly to ru | bindgen_flags | Flags to pass directly to the bindgen executable. See https://rust-lang.github.io/rust-bindgen/ for details. | `None` | | bindgen_features | The `features` attribute for the `rust_bindgen` target. | `None` | | clang_flags | Flags to pass directly to the clang executable. | `None` | +| 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` | | kwargs | Arguments to forward to the underlying `rust_library` rule. | none | diff --git a/docs/rust_bindgen.md b/docs/rust_bindgen.md index aa87c3a2b7..7489a7cbd3 100644 --- a/docs/rust_bindgen.md +++ b/docs/rust_bindgen.md @@ -53,7 +53,7 @@ toolchains following the instructions for [rust_bindgen_toolchain](#rust_bindgen ## rust_bindgen
-rust_bindgen(name, bindgen_flags, cc_lib, clang_flags, header)
+rust_bindgen(name, bindgen_flags, cc_lib, clang_flags, header, wrap_static_fns)
 
Generates a rust source file from a cc_library and a header. @@ -68,6 +68,7 @@ Generates a rust source file from a cc_library and a header. | cc_lib | The cc_library that contains the `.h` file. This is used to find the transitive includes. | Label | required | | | clang_flags | Flags to pass directly to the clang executable. | List of strings | optional | `[]` | | header | The `.h` file to generate bindings for. | Label | required | | +| 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` | @@ -140,7 +141,8 @@ list[struct(repo=str, is_dev_dep=bool)]: A list of the repositories ## rust_bindgen_library
-rust_bindgen_library(name, header, cc_lib, bindgen_flags, bindgen_features, clang_flags, kwargs)
+rust_bindgen_library(name, header, cc_lib, bindgen_flags, bindgen_features, clang_flags,
+                     wrap_static_fns, kwargs)
 
Generates a rust source file for `header`, and builds a rust_library. @@ -159,6 +161,7 @@ Arguments are the same as `rust_bindgen`, and `kwargs` are passed directly to ru | bindgen_flags | Flags to pass directly to the bindgen executable. See https://rust-lang.github.io/rust-bindgen/ for details. | `None` | | bindgen_features | The `features` attribute for the `rust_bindgen` target. | `None` | | clang_flags | Flags to pass directly to the clang executable. | `None` | +| 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` | | kwargs | Arguments to forward to the underlying `rust_library` rule. | none | diff --git a/examples/bindgen/BUILD.bazel b/examples/bindgen/BUILD.bazel index 4387173236..400fd0c0fa 100644 --- a/examples/bindgen/BUILD.bazel +++ b/examples/bindgen/BUILD.bazel @@ -9,6 +9,7 @@ rust_bindgen_library( ], cc_lib = "//bindgen/simple", header = "//bindgen/simple:simple.h", + wrap_static_fns = True, ) rust_binary( diff --git a/examples/bindgen/main.rs b/examples/bindgen/main.rs index 21e4241619..d466824f27 100644 --- a/examples/bindgen/main.rs +++ b/examples/bindgen/main.rs @@ -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(), ); } @@ -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()); } } diff --git a/examples/bindgen/simple/simple.h b/examples/bindgen/simple/simple.h index f689ac06b7..a7ca3f4312 100644 --- a/examples/bindgen/simple/simple.h +++ b/examples/bindgen/simple/simple.h @@ -9,8 +9,10 @@ #include -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