From 977bf2fa8f7269d449571d54a3792005282a7a0b Mon Sep 17 00:00:00 2001 From: Austin Schuh Date: Mon, 10 Aug 2026 00:03:22 -0700 Subject: [PATCH] Fix rust_bindgen's clang include path and dep wiring rust_bindgen rebuilds clang's command line from the cc_toolchain, but only keeps flags from an allowlist, and -idirafter isn't on it. toolchains_llvm passes every sysroot and builtin include directory that way (together with -nostdinc, so clang won't rediscover them on its own), which leaves bindgen parsing headers against a truncated include path. Whatever survives that filter is still a C++ compile's flags being handed to a C parse, so clang warns "argument unused during compilation" for each one, burying the real output. Add -Wno-unused-command-line-argument the same way the rule already adds -Wno-unknown-warning-option; both are clang-only, which is fine since everything after `--` goes to the clang bindgen forcibly uses. Finally, rules_rust now warns that a CcInfo-only target in a rust_library's 'deps' should be in 'link_deps'. Two of the targets the macro generates trip that: the thunks cc_library, and the bindgen target itself when merge_cc_lib_objects_into_rlib is off. Move those. The bindgen target has to stay in 'deps' when that flag is on (the default). There it links cc_lib into the rlib through a BuildInfo carrying -lstatic=/-Lnative= flags, and deliberately withholds cc_lib's libraries from its CcInfo so nothing downstream links them twice. transform_link_deps keeps only CcInfo, so routing it through 'link_deps' drops the objects and the binary fails to link. It also never warned, since BuildInfo already marks it as a Rust target. Signed-off-by: Austin Schuh --- extensions/bindgen/private/bindgen.bzl | 33 +++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/extensions/bindgen/private/bindgen.bzl b/extensions/bindgen/private/bindgen.bzl index 988d356e0e..59c9aa6f8b 100644 --- a/extensions/bindgen/private/bindgen.bzl +++ b/extensions/bindgen/private/bindgen.bzl @@ -80,9 +80,10 @@ def rust_bindgen_library( ): if shared in kwargs: bindgen_kwargs.update({shared: kwargs[shared]}) + merge_cc_lib_objects_into_rlib = True 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") + merge_cc_lib_objects_into_rlib = kwargs.pop("merge_cc_lib_objects_into_rlib") + bindgen_kwargs.update({"merge_cc_lib_objects_into_rlib": merge_cc_lib_objects_into_rlib}) rust_bindgen( name = name + "__bindgen", @@ -102,6 +103,10 @@ def rust_bindgen_library( if "deps" in kwargs: kwargs.pop("deps") + link_deps = kwargs.get("link_deps") or [] + if "link_deps" in kwargs: + kwargs.pop("link_deps") + if wrap_static_fns: native.filegroup( name = name + "__bindgen_c_thunks", @@ -115,10 +120,26 @@ def rust_bindgen_library( deps = [cc_lib], ) + # With `merge_cc_lib_objects_into_rlib` the bindgen target links `cc_lib` + # into the rlib via a `BuildInfo` provider carrying `-lstatic=`/`-Lnative=` + # flags, and deliberately withholds `cc_lib`'s libraries from its `CcInfo` + # so nothing downstream links them twice. `link_deps` keeps only `CcInfo`, + # so routing it there would drop the objects entirely; it has to stay in + # `deps`. Without the flag it provides a plain `CcInfo` and belongs in + # `link_deps`, as does the `cc_library` of static fn thunks. + if merge_cc_lib_objects_into_rlib: + deps = deps + [":" + name + "__bindgen"] + else: + link_deps = link_deps + [":" + name + "__bindgen"] + + if wrap_static_fns: + link_deps = link_deps + [":" + name + "__bindgen_c_thunks_library"] + rust_library( name = name, srcs = [name + "__bindgen.rs"], - deps = deps + [":" + name + "__bindgen"] + ([":" + name + "__bindgen_c_thunks_library"] if wrap_static_fns else []), + deps = deps, + link_deps = link_deps, tags = tags, **kwargs ) @@ -288,6 +309,11 @@ def _rust_bindgen_impl(ctx): # Ignore unknown warning options from the CC toolchain (e.g., GCC-specific flags) args.add("-Wno-unknown-warning-option") + # The CC toolchain's flags are written for its own language mode. bindgen + # parses headers as C, where flags like -nostdinc++ do nothing, so clang + # warns about each one and buries the real output. + args.add("-Wno-unused-command-line-argument") + resource_dir = _get_resource_dir(cc_toolchain) if resource_dir: args.add("-resource-dir=%s" % resource_dir) @@ -321,6 +347,7 @@ def _rust_bindgen_impl(ctx): param_flags_known_to_clang = ( "-I", "-iquote", + "-idirafter", "-isystem", "--sysroot", "--gcc-toolchain",