Include more cc_toolchain flags in RustBindgen actions (#2358)
This change parses `cc_toolchain` flags for `c++-compile` actions for
use in bindgen. This change aims to allow the action to gain toolchain
specific include paths as well as a more accurate `--sysroot`.
diff --git a/bindgen/private/BUILD.bazel b/bindgen/private/BUILD.bazel
index 97c4669..e8f1c33 100644
--- a/bindgen/private/BUILD.bazel
+++ b/bindgen/private/BUILD.bazel
@@ -2,6 +2,8 @@
bzl_library(
name = "bzl_lib",
- srcs = glob(["**/*.bzl"]),
+ srcs = glob(["**/*.bzl"]) + [
+ "@rules_cc//cc:bzl_srcs",
+ ],
visibility = ["//bindgen:__pkg__"],
)
diff --git a/bindgen/private/bindgen.bzl b/bindgen/private/bindgen.bzl
index aba0469..03bb05b 100644
--- a/bindgen/private/bindgen.bzl
+++ b/bindgen/private/bindgen.bzl
@@ -14,6 +14,11 @@
"""Rust Bindgen rules"""
+load(
+ "@bazel_tools//tools/build_defs/cc:action_names.bzl",
+ "CPP_COMPILE_ACTION_NAME",
+)
+load("@rules_cc//cc:defs.bzl", "CcInfo")
load("//rust:defs.bzl", "rust_library")
# buildifier: disable=bzl-visibility
@@ -69,7 +74,7 @@
cc_lib = cc_lib,
bindgen_flags = bindgen_flags or [],
clang_flags = clang_flags or [],
- tags = tags,
+ tags = ["manual"],
)
rust_library(
@@ -81,8 +86,6 @@
)
def _rust_bindgen_impl(ctx):
- toolchain = ctx.toolchains[Label("//bindgen:toolchain_type")]
-
# nb. We can't grab the cc_library`s direct headers, so a header must be provided.
cc_lib = ctx.attr.cc_lib
header = ctx.file.header
@@ -101,9 +104,6 @@
# libclang should only have 1 output file
libclang_dir = _get_libs_for_static_executable(libclang).to_list()[0].dirname
- include_directories = cc_lib[CcInfo].compilation_context.includes.to_list()
- quote_include_directories = cc_lib[CcInfo].compilation_context.quote_includes.to_list()
- system_include_directories = cc_lib[CcInfo].compilation_context.system_includes.to_list()
env = {
"CLANG_PATH": clang_bin.path,
@@ -129,26 +129,52 @@
# Configure Clang Arguments
args.add("--")
- args.add_all(include_directories, before_each = "-I")
- args.add_all(quote_include_directories, before_each = "-iquote")
- args.add_all(system_include_directories, before_each = "-isystem")
- args.add_all(ctx.attr.clang_flags)
- cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
+ cc_toolchain, feature_configuration = find_cc_toolchain(ctx = ctx)
+ compile_variables = cc_common.create_compile_variables(
+ cc_toolchain = cc_toolchain,
+ feature_configuration = feature_configuration,
+ include_directories = cc_lib[CcInfo].compilation_context.includes,
+ quote_include_directories = cc_lib[CcInfo].compilation_context.quote_includes,
+ system_include_directories = cc_lib[CcInfo].compilation_context.system_includes,
+ user_compile_flags = ctx.attr.clang_flags,
+ )
+ compile_flags = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = CPP_COMPILE_ACTION_NAME,
+ variables = compile_variables,
+ )
+
+ # Bindgen forcibly uses clang.
+ # It's possible that the selected cc_toolchain isn't clang, and may specify flags which clang doesn't recognise.
+ # Ideally we could depend on a more specific toolchain, requesting one which is specifically clang via some constraint.
+ # Unfortunately, we can't currently rely on this, so instead we filter only to flags we know clang supports.
+ # We can add extra flags here as needed.
+ flags_known_to_clang = ("-I", "-iquote", "-isystem", "--sysroot")
+ open_arg = False
+ for arg in compile_flags:
+ if open_arg:
+ args.add(arg)
+ open_arg = False
+ continue
+
+ # The cc_toolchain merged these flags into its returned flags - don't strip these out.
+ if arg in ctx.attr.clang_flags:
+ args.add(arg)
+ continue
+
+ if not arg.startswith(flags_known_to_clang):
+ continue
+
+ args.add(arg)
+
+ if arg in flags_known_to_clang:
+ open_arg = True
+ continue
+
_, _, linker_env = get_linker_and_args(ctx, ctx.attr, "bin", cc_toolchain, feature_configuration, None)
env.update(**linker_env)
- # Allow sysroots configured by the toolchain to be added to Clang arguments.
- if "no-rust-bindgen-cc-sysroot" not in ctx.features:
- if cc_toolchain.sysroot:
- tools = depset(transitive = [tools, cc_toolchain.all_files])
- sysroot_args = ["--sysroot", cc_toolchain.sysroot]
- for arg in ctx.attr.clang_flags:
- if arg.startswith("--sysroot"):
- sysroot_args = []
- break
- args.add_all(sysroot_args)
-
# Set the dynamic linker search path so that clang uses the libstdcxx from the toolchain.
# DYLD_LIBRARY_PATH is LD_LIBRARY_PATH on macOS.
if libstdcxx:
@@ -184,6 +210,7 @@
"cc_lib": attr.label(
doc = "The cc_library that contains the `.h` file. This is used to find the transitive includes.",
providers = [CcInfo],
+ mandatory = True,
),
"clang_flags": attr.string_list(
doc = "Flags to pass directly to the clang executable.",
@@ -191,6 +218,7 @@
"header": attr.label(
doc = "The `.h` file to generate bindings for.",
allow_single_file = True,
+ mandatory = True,
),
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
diff --git a/docs/flatten.md b/docs/flatten.md
index 04c0d60..52a38d9 100644
--- a/docs/flatten.md
+++ b/docs/flatten.md
@@ -371,9 +371,9 @@
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="rust_bindgen-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="rust_bindgen-bindgen_flags"></a>bindgen_flags | Flags to pass directly to the bindgen executable. See https://rust-lang.github.io/rust-bindgen/ for details. | List of strings | optional | <code>[]</code> |
-| <a id="rust_bindgen-cc_lib"></a>cc_lib | The cc_library that contains the <code>.h</code> file. This is used to find the transitive includes. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
+| <a id="rust_bindgen-cc_lib"></a>cc_lib | The cc_library that contains the <code>.h</code> 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 | <code>[]</code> |
-| <a id="rust_bindgen-header"></a>header | The <code>.h</code> file to generate bindings for. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
+| <a id="rust_bindgen-header"></a>header | The <code>.h</code> file to generate bindings for. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
<a id="rust_bindgen_toolchain"></a>
diff --git a/docs/rust_bindgen.md b/docs/rust_bindgen.md
index 1a496cd..a8bc022 100644
--- a/docs/rust_bindgen.md
+++ b/docs/rust_bindgen.md
@@ -65,9 +65,9 @@
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="rust_bindgen-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="rust_bindgen-bindgen_flags"></a>bindgen_flags | Flags to pass directly to the bindgen executable. See https://rust-lang.github.io/rust-bindgen/ for details. | List of strings | optional | <code>[]</code> |
-| <a id="rust_bindgen-cc_lib"></a>cc_lib | The cc_library that contains the <code>.h</code> file. This is used to find the transitive includes. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
+| <a id="rust_bindgen-cc_lib"></a>cc_lib | The cc_library that contains the <code>.h</code> 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 | <code>[]</code> |
-| <a id="rust_bindgen-header"></a>header | The <code>.h</code> file to generate bindings for. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
+| <a id="rust_bindgen-header"></a>header | The <code>.h</code> file to generate bindings for. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
<a id="rust_bindgen_toolchain"></a>
diff --git a/examples/bindgen/simple.h b/examples/bindgen/simple.h
index 072f9ea..96798ec 100644
--- a/examples/bindgen/simple.h
+++ b/examples/bindgen/simple.h
@@ -1,3 +1,5 @@
+#pragma once
+
#include <stdint.h>
const int64_t SIMPLE_VALUE = 42;