diff --git a/MODULE.bazel b/MODULE.bazel index c50471017a..6269216734 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -175,8 +175,11 @@ register_toolchains( "//proto/prost:default_prost_toolchain", ) +bindgen = use_extension("//bindgen:extension.bzl", "bindgen") +use_repo(bindgen, "bindgen_toolchains") + register_toolchains( - "//bindgen:default_bindgen_toolchain", + "@bindgen_toolchains//:default_bindgen_toolchain", ) rust_host_tools = use_extension("//rust:extensions.bzl", "rust_host_tools") diff --git a/bindgen/3rdparty/patches/llvm-project.workspace_root.patch b/bindgen/3rdparty/patches/llvm-project.workspace_root.patch new file mode 100644 index 0000000000..46f77112f5 --- /dev/null +++ b/bindgen/3rdparty/patches/llvm-project.workspace_root.patch @@ -0,0 +1,68 @@ +diff --git b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel +--- b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel ++++ a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel +@@ -1,8 +1,9 @@ + # This file is licensed under the Apache License v2.0 with LLVM Exceptions. + # See https://llvm.org/LICENSE.txt for license information. + # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + ++load("//:workspace_root.bzl", "workspace_root") + load("//llvm:tblgen.bzl", "gentbl") + load("//llvm:binary_alias.bzl", "binary_alias") + load("//llvm:cc_plugin_library.bzl", "cc_plugin_library") + load("//llvm:config.bzl", "llvm_stdcxx_copts") +@@ -684,8 +685,10 @@ gentbl( + td_srcs = [ + "include/clang/Basic/ASTNode.td", + "include/clang/Basic/TypeNodes.td", + ], + ) ++ ++workspace_root(name = "workspace_root") + + cc_library( + name = "ast", +@@ -711,8 +714,8 @@ cc_library( + # least bad approach. Using `includes` is *specifically* problematic for + # this library because it contains files that collide easily with system + # headers such as `CXXABI.h`. +- "-I$(GENDIR)/external/llvm-project/clang/lib/AST", +- "-I$(GENDIR)/external/llvm-project/clang/lib/AST/Interp", ++ "-I$(GENDIR)/$(WORKSPACE_ROOT)/clang/lib/AST", ++ "-I$(GENDIR)/$(WORKSPACE_ROOT)/clang/lib/AST/Interp", + ] + llvm_stdcxx_copts, + textual_hdrs = [ + "include/clang/AST/AttrImpl.inc", +@@ -730,8 +733,11 @@ cc_library + "include/clang/AST/StmtDataCollectors.inc", + "include/clang/AST/StmtNodes.inc", + ] + glob([ + "include/clang/AST/*.def", + ], allow_empty = True), ++ toolchains = [ ++ ":workspace_root", ++ ], + deps = [ + ":ast_attr_gen", + ":ast_comment_command_info_gen", + +--- /dev/null ++++ a/utils/bazel/llvm-project-overlay/workspace_root.bzl +@@ -0,0 +1,17 @@ ++def _workspace_root_impl(ctx): ++ """Dynamically determine the workspace root from the current context. ++ ++ The path is made available as a `WORKSPACE_ROOT` environmment variable and ++ may for instance be consumed in the `toolchains` attributes for `cc_library` ++ and `genrule` targets. ++ """ ++ return [ ++ platform_common.TemplateVariableInfo({ ++ "WORKSPACE_ROOT": ctx.label.workspace_root, ++ }), ++ ] ++ ++workspace_root = rule( ++ implementation = _workspace_root_impl, ++ attrs = {}, ++) diff --git a/bindgen/BUILD.bazel b/bindgen/BUILD.bazel index 0ee90783ba..69ead2c8fd 100644 --- a/bindgen/BUILD.bazel +++ b/bindgen/BUILD.bazel @@ -1,5 +1,4 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("//bindgen:defs.bzl", "rust_bindgen_toolchain") package(default_visibility = ["//visibility:public"]) @@ -11,21 +10,18 @@ bzl_library( name = "bzl_lib", srcs = glob(["**/*.bzl"]), deps = [ - "//bindgen/3rdparty:bzl_lib", - "//bindgen/private:bzl_lib", - "//rust:bzl_lib", + "@rules_rust//bindgen/3rdparty:bzl_lib", + "@rules_rust//bindgen/private:bzl_lib", + "@rules_rust//rust:bzl_lib", ], ) -rust_bindgen_toolchain( +alias( name = "default_bindgen_toolchain_impl", - bindgen = "//bindgen/3rdparty:bindgen", - clang = "@llvm-project//clang:clang", - libclang = "@llvm-project//clang:libclang", + actual = "//bindgen/toolchain:default_bindgen_toolchain_impl", ) -toolchain( +alias( name = "default_bindgen_toolchain", - toolchain = "default_bindgen_toolchain_impl", - toolchain_type = "//bindgen:toolchain_type", + actual = "//bindgen/toolchain:default_bindgen_toolchain", ) diff --git a/bindgen/extension.bzl b/bindgen/extension.bzl new file mode 100644 index 0000000000..b02c749b77 --- /dev/null +++ b/bindgen/extension.bzl @@ -0,0 +1,47 @@ +"""Module extension for accessing a bindgen toolchain""" + +load(":repositories.bzl", "rust_bindgen_dependencies") +load(":transitive_repositories.bzl", "rust_bindgen_transitive_dependencies") + +def _bindgen_impl(_): + rust_bindgen_transitive_dependencies(repo_mapping = None) + rust_bindgen_dependencies() + bindgen_toolchains( + name = "bindgen_toolchains", + build_file = "//bindgen/toolchain:BUILD.bazel", + ) + +bindgen = module_extension(implementation = _bindgen_impl) + +def _bindgen_toolchains_impl(rctx): + if (rctx.attr.build_file == None) == (rctx.attr.build_file_content == "_UNSET"): + fail("exactly one of `build_file` or `build_file_content` must be specified") + + if rctx.attr.build_file != None: + rctx.file("BUILD.bazel", rctx.read(rctx.attr.build_file)) + else: + rctx.file("BUILD.bazel", rctx.attr.build_file_content) + +bindgen_toolchains = repository_rule( + implementation = _bindgen_toolchains_impl, + attrs = { + "build_file": attr.label( + doc = + "A file to use as a BUILD file for this repo." + + "
Exactly one of build_file
or build_file_content
" +
+ "must be specified.",
+ ),
+ "build_file_content": attr.string(
+ doc =
+ "The content of a BUILD file to be created for this repo." +
+ "
Exactly one of build_file
or build_file_content
" +
+ "must be specified.",
+ default = "_UNSET",
+ ),
+ },
+ doc =
+ "Creates a local repository containing a provided BUILD file to be used for defining " +
+ "bindgen toolchains." +
+ "
This rule is a replacement for the local_repository
rule available " +
+ "in later supported versions of Bazel.",
+)
diff --git a/bindgen/repositories.bzl b/bindgen/repositories.bzl
index 25e8c8a6bc..8da059bc1d 100644
--- a/bindgen/repositories.bzl
+++ b/bindgen/repositories.bzl
@@ -40,6 +40,7 @@ def rust_bindgen_dependencies():
patches = [
Label("//bindgen/3rdparty/patches:llvm-project.cxx17.patch"),
Label("//bindgen/3rdparty/patches:llvm-project.incompatible_disallow_empty_glob.patch"),
+ Label("//bindgen/3rdparty/patches:llvm-project.workspace_root.patch"),
],
)
diff --git a/bindgen/toolchain/BUILD.bazel b/bindgen/toolchain/BUILD.bazel
new file mode 100644
index 0000000000..21af90e50d
--- /dev/null
+++ b/bindgen/toolchain/BUILD.bazel
@@ -0,0 +1,16 @@
+load("@rules_rust//bindgen:defs.bzl", "rust_bindgen_toolchain")
+
+package(default_visibility = ["//visibility:public"])
+
+rust_bindgen_toolchain(
+ name = "default_bindgen_toolchain_impl",
+ bindgen = "@rules_rust//bindgen/3rdparty:bindgen",
+ clang = "@llvm-project//clang:clang",
+ libclang = "@llvm-project//clang:libclang",
+)
+
+toolchain(
+ name = "default_bindgen_toolchain",
+ toolchain = "default_bindgen_toolchain_impl",
+ toolchain_type = "@rules_rust//bindgen:toolchain_type",
+)
diff --git a/bindgen/transitive_repositories.bzl b/bindgen/transitive_repositories.bzl
index 66c80ee5fc..f39c3ac89e 100644
--- a/bindgen/transitive_repositories.bzl
+++ b/bindgen/transitive_repositories.bzl
@@ -2,18 +2,35 @@
load("@llvm-raw//utils/bazel:configure.bzl", "llvm_configure", "llvm_disable_optional_support_deps")
+DEFAULT_REPO_MAPPING = {
+ "@llvm_zlib": "@zlib",
+}
+LLVM_TARGETS = ["AArch64", "X86"]
+
# buildifier: disable=unnamed-macro
-def rust_bindgen_transitive_dependencies():
- """Declare transitive dependencies needed for bindgen."""
+def rust_bindgen_transitive_dependencies(repo_mapping = DEFAULT_REPO_MAPPING):
+ """Declare transitive dependencies needed for bindgen.
+
+ Args:
+ repo_mapping: Mapping for renaming repositories created by this function.
+ The repository names created by this function are undocumented and subject
+ to change in the future.
+ """
- llvm_configure(
- name = "llvm-project",
- repo_mapping = {"@llvm_zlib": "@zlib"},
- targets = [
- "AArch64",
- "X86",
- ],
- )
+ # Bzlmod does not support the `repo_mapping` parameter *at all*, so we have
+ # to only specify it when requested.
+ if repo_mapping == None:
+ llvm_configure(
+ name = "llvm-project",
+ targets = LLVM_TARGETS,
+ )
+ else:
+ llvm_repo_name = repo_mapping.get("llvm-project", "llvm-project")
+ llvm_configure(
+ name = llvm_repo_name,
+ repo_mapping = repo_mapping,
+ targets = LLVM_TARGETS,
+ )
# Disables optional dependencies for Support like zlib and terminfo. You may
# instead want to configure them using the macros in the corresponding bzl