Skip to content
Draft
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
47 changes: 26 additions & 21 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -93,25 +93,25 @@ git_override(
remote = "https://github.com/bazelbuild/rules_pkg.git",
)

# Temporary until rules_rust > 0.69.0 ships with Windows GNU ABI support (PR #3940).
# The CI runner uses MinGW as its cc_toolchain; rules_rust 0.69.0 defaults to
# x86_64-pc-windows-msvc whose linker flags are incompatible with MinGW's g++.
# Pinned past the 0.69.0 release to pick up the Windows-GNU ABI support from
# bazelbuild/rules_rust#3940 (lib name resolution, stdlib link flags, PDB
# emission split by abi). Required because our Windows cc_toolchain is MinGW
# (@winlibs_mingw64), and the 0.69.0 stable release still hard-codes MSVC
# behavior for `target_os == "windows"`.
git_override(
module_name = "rules_rust",
commit = "82506df3f31240f97194b2e9453022125eaa07f4", # main as of April 21, 2026
commit = "f31db8b6f124dd5eebdd0ed8de4daf20d4d9685f", # main as of April 27, 2026 (includes #3940 + #3990)
patch_strip = 1,
patches = [
# Stops rustc_compile_action from leaking default_shell_env into
# CrateInfo.rustc_env, which otherwise clobbers cc_toolchain link_env
# for rust_test(crate = ...). Upstream issue pending.
"//bazel/patches:rules_rust-crateinfo-env-leak.patch",
# Derives `-Cdlltool=<linker-dir>/dlltool.exe` automatically
"//bazel/patches:rules_rust-derive-dlltool-from-linker.patch",
],
remote = "https://github.com/bazelbuild/rules_rust.git",
)

git_override(
module_name = "rules_rust_prost",
commit = "82506df3f31240f97194b2e9453022125eaa07f4",
commit = "f31db8b6f124dd5eebdd0ed8de4daf20d4d9685f",
remote = "https://github.com/bazelbuild/rules_rust.git",
strip_prefix = "extensions/prost",
)
Expand Down Expand Up @@ -282,11 +282,26 @@ llvm.toolchain(
llvm_version = "19.1.7", # https://github.com/bazel-contrib/toolchains_llvm/blob/master/toolchain/internal/llvm_distributions.bzl
)

# Hermetic MinGW-w64 toolchain sourced from a pinned WinLibs distribution.
# Variant: GCC 14.2.0 + MinGW-w64 12.0.0, POSIX threads, MSVCRT runtime,
# no LLVM bundle. URL, sha256 and gcc_version must move together when bumping.
winlibs_mingw_repository = use_repo_rule(
"//bazel/toolchains/mingw:winlibs.bzl",
"winlibs_mingw_repository",
)

winlibs_mingw_repository(
name = "winlibs_mingw64",
gcc_version = "14.2.0",
sha256 = "ff475e985a98c5f3785129baf7460db14fee27708bce35f2833db5009507f1b9",
url = "https://github.com/brechtsanders/winlibs_mingw/releases/download/14.2.0posix-19.1.7-12.0.0-msvcrt-r3/winlibs-x86_64-posix-seh-gcc-14.2.0-mingw-w64msvcrt-12.0.0-r3.zip",
)

# TODO{agent-build}: Find a way to register platform-specific toolchains dynamically
register_toolchains(
"@gcc_toolchain_x86_64//:cc_toolchain",
"@gcc_toolchain_aarch64//:cc_toolchain",
"//bazel/toolchains/mingw:mingw_cc_toolchain",
"@winlibs_mingw64//:mingw_cc_toolchain",
"@llvm_toolchain//:all", # last to avoid taking precedence over GCC toolchains
)

Expand Down Expand Up @@ -334,21 +349,11 @@ rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")

# Register a GNU-ABI Rust toolchain for Windows so that rustc generates
# GNU-style linker flags (-lkernel32, -o, etc.) compatible with the MinGW
# cc_toolchain used on the Windows CI runner. Processed before the default
# toolchains, so Bazel's toolchain resolution picks it over the auto-registered
# x86_64-pc-windows-msvc toolchain.
# cc_toolchain used on the Windows CI runner.
rust.repository_set(
name = "rust_windows_gnu_x86_64",
edition = "2024",
exec_triple = "x86_64-pc-windows-gnu",
extra_exec_rustc_flags = [
"-Clinker=C:/tools/msys64/mingw64/bin/gcc.exe",
"-Cdlltool=C:/tools/msys64/mingw64/bin/dlltool.exe",
],
extra_rustc_flags = [
"-Clinker=C:/tools/msys64/mingw64/bin/gcc.exe",
"-Cdlltool=C:/tools/msys64/mingw64/bin/dlltool.exe",
],
target_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:x86_64",
Expand Down
34 changes: 0 additions & 34 deletions bazel/patches/rules_rust-crateinfo-env-leak.patch

This file was deleted.

35 changes: 35 additions & 0 deletions bazel/patches/rules_rust-derive-dlltool-from-linker.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
index c8f6ecc9..c7319735 100644
--- a/rust/private/rustc.bzl
+++ b/rust/private/rustc.bzl
@@ -1158,6 +1158,30 @@ def construct_arguments(
# If linker_type is not explicitly set, infer from which linker is actually being used
ld_is_direct_driver = False

+ # rustc on Windows-GNU shells out to dlltool to synthesize import
+ # libraries -- both for #[link(... kind = "raw-dylib")] declarations
+ # in *any* crate (rlib included; windows-sys 0.61+ is the common case)
+ # and for the *.dll.a companion that cdylib crates emit alongside
+ # their .dll. cc_toolchain has no action / tool slot for dlltool
+ # because gcc-as-linker invokes it internally -- but rustc drives the
+ # linker directly, so it needs an explicit pointer.
+ #
+ # Inject the derived path here, *outside* the link-emit gate below, so
+ # rlib compiles also see it. Every MinGW distribution (winlibs, MSYS2
+ # mingw64, llvm-mingw) ships dlltool.exe next to the linker, so reuse
+ # the cc_toolchain's CPP_LINK_EXECUTABLE_ACTION_NAME tool path and
+ # swap the basename. User-supplied `-Cdlltool=` via extra_rustc_flags
+ # is appended later and still wins because rustc honors the last
+ # `-C<key>=` for a given key.
+ if cc_toolchain and toolchain.target_os == "windows" and toolchain.target_abi != "msvc":
+ dlltool_linker = cc_common.get_tool_for_action(
+ feature_configuration = feature_configuration,
+ action_name = CPP_LINK_EXECUTABLE_ACTION_NAME,
+ )
+ dlltool_sep = max(dlltool_linker.rfind("/"), dlltool_linker.rfind("\\"))
+ if dlltool_sep >= 0:
+ rustc_flags.add(dlltool_linker[:dlltool_sep] + "/dlltool.exe", format = "--codegen=dlltool=%s")
+
# Link!
if ("link" in emit and crate_info.type not in ["rlib", "lib"]) or add_flags_for_binary:
# Rust's built-in linker can handle linking wasm files. We don't want to attempt to use the cc
7 changes: 3 additions & 4 deletions bazel/rules/ebpf/cgo_godefs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,9 @@ def _cgo_godefs_impl(ctx):
package_name = ctx.label.package.split("/")[-1]
genpost_args = "$ROOT/{test} {pkg}".format(test = test_path_no_ext, pkg = package_name)

# TODO(ABLD-410): uses the system clang rather than a hermetic toolchain.
# On Windows, Go defaults to gcc (MinGW) — no CC override needed, matching
# the old ninja behavior.
cc_prefix = "CC=clang " if platform == "linux" else ""
# TODO(ABLD-410): Linux still shells out to the system clang.
# Windows points cgo at the hermetic MinGW gcc from the cc_toolchain.
cc_prefix = "CC=clang " if platform == "linux" else "CC=$ROOT/{} ".format(go.cgo_tools.c_compiler_path)

cmd = (
"set -euo pipefail && ROOT=$PWD && cd {src_dir} && " +
Expand Down
13 changes: 9 additions & 4 deletions bazel/rules/windows_resources.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ load("@rules_cc//cc:action_names.bzl", "C_COMPILE_ACTION_NAME")
load("@rules_cc//cc:defs.bzl", "cc_common")
load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_ATTRS", "find_cc_toolchain", "use_cc_toolchain")
load("//bazel/rules:version_info.bzl", "agent_version_defines")
load("//bazel/toolchains/mingw:paths.bzl", "MINGW_PATH")

_WINDRES = "@winlibs_mingw64//:windres"
_WINDMC = "@winlibs_mingw64//:windmc"

def _cc_env(ctx):
"""Returns (env, cc_toolchain) from the resolved CC toolchain."""
Expand Down Expand Up @@ -48,7 +50,7 @@ def _win_messagetable_impl(ctx):
windmc_args.add(src)

ctx.actions.run(
executable = MINGW_PATH + "/bin/windmc",
executable = ctx.executable._windmc,
arguments = [windmc_args],
inputs = [src],
outputs = [rc_out, h_out, bin_out],
Expand All @@ -67,7 +69,7 @@ def _win_messagetable_impl(ctx):
windres_args.add("-o", syso_out)

ctx.actions.run(
executable = MINGW_PATH + "/bin/windres",
executable = ctx.executable._windres,
arguments = [windres_args],
env = env,
inputs = depset([rc_out, bin_out], transitive = [cc_toolchain.all_files]),
Expand All @@ -83,6 +85,8 @@ _win_messagetable = rule(
doc = "Compiles a .mc message file into a .syso resource and .h header via windmc + windres.",
attrs = {
"src": attr.label(mandatory = True, allow_single_file = [".mc"]),
"_windmc": attr.label(default = _WINDMC, executable = True, cfg = "exec", allow_single_file = True),
"_windres": attr.label(default = _WINDRES, executable = True, cfg = "exec", allow_single_file = True),
} | CC_TOOLCHAIN_ATTRS,
toolchains = use_cc_toolchain(),
fragments = ["cpp"],
Expand Down Expand Up @@ -129,7 +133,7 @@ def _win_resource_impl(ctx):
windres_args.add("-o", syso_out)

ctx.actions.run(
executable = MINGW_PATH + "/bin/windres",
executable = ctx.executable._windres,
arguments = [windres_args],
env = env,
inputs = depset([src] + ctx.files.deps, transitive = [cc_toolchain.all_files]),
Expand All @@ -147,6 +151,7 @@ _win_resource = rule(
"src": attr.label(mandatory = True, allow_single_file = [".rc"]),
"deps": attr.label_list(allow_files = True),
"defines": attr.string_dict(),
"_windres": attr.label(default = _WINDRES, executable = True, cfg = "exec", allow_single_file = True),
} | CC_TOOLCHAIN_ATTRS,
toolchains = use_cc_toolchain(),
fragments = ["cpp"],
Expand Down
53 changes: 3 additions & 50 deletions bazel/toolchains/mingw/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,50 +1,3 @@
load("@rules_cc//cc:defs.bzl", "cc_toolchain")
load("//bazel/toolchains/mingw:paths.bzl", "MINGW_PATH", "MSYS2_PATH")
load("//bazel/toolchains/mingw:toolchain.bzl", "mingw_cc_toolchain_config")

mingw_cc_toolchain_config(
name = "mingw-cc-toolchain-config",
GCC_VERSION = "14.2.0",
MINGW_PATH = MINGW_PATH,
MSYS2_PATH = MSYS2_PATH,
)

filegroup(
name = "toolchain_files",
)

# Define our cc_toolchain
# (https://bazel.build/reference/be/c-cpp#cc_toolchain).
# The cc_toolchain rule is pre-defined by the C++ rule owners. It uses these
# parameters to construct a ToolchainInfo provider, as required by Bazel's
# platform/toolchain APIs.
cc_toolchain(
name = "mingw_cc_toolchain_definition",
all_files = ":toolchain_files",
compiler_files = ":toolchain_files",
dwp_files = ":toolchain_files",
linker_files = ":toolchain_files",
objcopy_files = ":toolchain_files",
strip_files = ":toolchain_files",
toolchain_config = ":mingw-cc-toolchain-config",
)

# Bazel's platform/toolchain APIs require this wrapper around the actual
# toolchain defined above. It serves two purposes: declare which
# constraint_values it supports (which can be matched to appropriate platforms)
# and tell Bazel what language this toolchain is for.
#
# So when you're building a cc_binary, Bazel has all the info it needs to give
# that cc_binary the right toolchain: it knows cc_binary requires a "C++-type
# toolchain" (this is encoded in the cc_binary rule definition) and needs to
# use a toolchain that matches whatever you set --platforms to at the command
# line.
toolchain(
name = "mingw_cc_toolchain",
target_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:x86_64",
],
toolchain = ":mingw_cc_toolchain_definition",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
# MinGW cc_toolchain lives in @winlibs_mingw64//: (see winlibs.BUILD.bazel).
# This file exists only to mark the package; the toolchain config rule is
# loaded from //bazel/toolchains/mingw:toolchain.bzl by the WinLibs repo.
4 changes: 0 additions & 4 deletions bazel/toolchains/mingw/paths.bzl

This file was deleted.

Loading
Loading