Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add opt-out from merging cc_lib object files in bindgen #2959

Merged
merged 2 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions bindgen/private/bindgen.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ def rust_bindgen_library(
):
if shared in kwargs:
bindgen_kwargs.update({shared: kwargs[shared]})
if "merge_cc_lib_objects_into_rlib" in kwargs:
bindgen_kwargs.update({"merge_cc_lib_objects_into_rlib": kwargs["merge_cc_lib_objects_into_rlib"]})
kwargs.pop("merge_cc_lib_objects_into_rlib")

rust_bindgen(
name = name + "__bindgen",
Expand Down Expand Up @@ -334,22 +337,28 @@ def _rust_bindgen_impl(ctx):
toolchain = None,
)

return [
_generate_cc_link_build_info(ctx, cc_lib),
# As in https://github.com/bazelbuild/rules_rust/pull/2361, we want
# to link cc_lib to the direct parent (rlib) using `-lstatic=<cc_lib>`
# rustc flag. Hence, we do not need to provide the whole CcInfo of
# cc_lib because it will cause the downstream binary to link the cc_lib
# again. The CcInfo here only contains the custom link flags (i.e.
# linkopts attribute) specified by users in cc_lib.
CcInfo(
linking_context = cc_common.create_linking_context(
linker_inputs = depset([cc_common.create_linker_input(
owner = ctx.label,
user_link_flags = _get_user_link_flags(cc_lib),
)]),
if ctx.attr.merge_cc_lib_objects_into_rlib:
providers = [
_generate_cc_link_build_info(ctx, cc_lib),
# As in https://github.com/bazelbuild/rules_rust/pull/2361, we want
# to link cc_lib to the direct parent (rlib) using `-lstatic=<cc_lib>`
# rustc flag. Hence, we do not need to provide the whole CcInfo of
# cc_lib because it will cause the downstream binary to link the cc_lib
# again. The CcInfo here only contains the custom link flags (i.e.
# linkopts attribute) specified by users in cc_lib.
CcInfo(
linking_context = cc_common.create_linking_context(
linker_inputs = depset([cc_common.create_linker_input(
owner = ctx.label,
user_link_flags = _get_user_link_flags(cc_lib),
)]),
),
),
),
]
else:
providers = [cc_lib[CcInfo]]

return providers + [
OutputGroupInfo(
bindgen_bindings = depset([output]),
bindgen_c_thunks = depset(([c_output] if wrap_static_fns else [])),
Expand All @@ -376,6 +385,11 @@ rust_bindgen = rule(
allow_single_file = True,
mandatory = True,
),
"merge_cc_lib_objects_into_rlib": attr.bool(
doc = ("When True, objects from `cc_lib` will be copied into the `rlib` archive produced by " +
"the rust_library that depends on this `rust_bindgen` rule (using `BuildInfo` provider)"),
default = 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,
Expand Down
4 changes: 3 additions & 1 deletion docs/src/flatten.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ 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>, <a href="#rust_bindgen-wrap_static_fns">wrap_static_fns</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-merge_cc_lib_objects_into_rlib">merge_cc_lib_objects_into_rlib</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 @@ -344,6 +345,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-merge_cc_lib_objects_into_rlib"></a>merge_cc_lib_objects_into_rlib | When True, objects from `cc_lib` will be copied into the `rlib` archive produced by the rust_library that depends on this `rust_bindgen` rule (using `BuildInfo` provider) | Boolean | optional | `True` |
| <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` |


Expand Down
4 changes: 3 additions & 1 deletion docs/src/rust_bindgen.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ 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>, <a href="#rust_bindgen-wrap_static_fns">wrap_static_fns</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-merge_cc_lib_objects_into_rlib">merge_cc_lib_objects_into_rlib</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 +69,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-merge_cc_lib_objects_into_rlib"></a>merge_cc_lib_objects_into_rlib | When True, objects from `cc_lib` will be copied into the `rlib` archive produced by the rust_library that depends on this `rust_bindgen` rule (using `BuildInfo` provider) | Boolean | optional | `True` |
| <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` |


Expand Down
50 changes: 50 additions & 0 deletions test/bindgen/bindgen_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,60 @@ def _test_cc_linkopt(name):
impl = _test_cc_linkopt_impl,
)

def _test_cc_lib_object_merging_impl(env, target):
env.expect.that_int(len(target.actions)).is_greater_than(2)
env.expect.that_action(target.actions[0]).mnemonic().contains("RustBindgen")
env.expect.that_action(target.actions[1]).mnemonic().contains("FileWrite")
env.expect.that_action(target.actions[1]).content().contains("-lstatic=test_cc_lib_object_merging_cc")
env.expect.that_action(target.actions[2]).mnemonic().contains("FileWrite")
env.expect.that_action(target.actions[2]).content().contains("-Lnative=")

def _test_cc_lib_object_merging_disabled_impl(env, target):
# no FileWrite actions writing arg files registered
env.expect.that_int(len(target.actions)).is_greater_than(0)
env.expect.that_action(target.actions[0]).mnemonic().contains("RustBindgen")

def _test_cc_lib_object_merging(name):
cc_library(name = name + "_cc", hdrs = ["simple.h"], srcs = ["simple.cc"])

rust_bindgen_library(
name = name + "_rust_bindgen",
cc_lib = name + "_cc",
header = "simple.h",
tags = ["manual"],
edition = "2021",
)

analysis_test(
name = name,
target = name + "_rust_bindgen__bindgen",
impl = _test_cc_lib_object_merging_impl,
)

def _test_cc_lib_object_merging_disabled(name):
cc_library(name = name + "_cc", hdrs = ["simple.h"], srcs = ["simple.cc"])

rust_bindgen_library(
name = name + "_rust_bindgen",
cc_lib = name + "_cc",
header = "simple.h",
tags = ["manual"],
merge_cc_lib_objects_into_rlib = False,
edition = "2021",
)

analysis_test(
name = name,
target = name + "_rust_bindgen__bindgen",
impl = _test_cc_lib_object_merging_disabled_impl,
)

def bindgen_test_suite(name):
test_suite(
name = name,
tests = [
_test_cc_linkopt,
_test_cc_lib_object_merging,
_test_cc_lib_object_merging_disabled,
],
)
Loading