diff --git a/.bazelrc b/.bazelrc index 12191bd9c41..f46547818de 100644 --- a/.bazelrc +++ b/.bazelrc @@ -21,7 +21,9 @@ common:windows --@rules_rust//rust/settings:experimental_use_sh_toolchain_for_bo common --incompatible_strict_action_env # Not ideal, but We need to allow dotslash to be found -common --test_env=PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +common:macos --test_env=PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +common:windows --test_env=PATH +#common:windows --test_env=PATH=/mingw64/bin:/usr/bin:/c/Users/runneradmin/bin:/d/a/_temp/install-dotslash/bin:/c/Program\ Files/Git/bin common --test_output=errors common --bes_results_url=https://app.buildbuddy.io/invocation/ @@ -37,7 +39,7 @@ common --grpc_keepalive_time=30s # This limits both in-flight executions and concurrent downloads. Even with high number # of jobs execution will still be limited by CPU cores, so this just pays a bit of # memory in exchange for higher download concurrency. -common --jobs=30 +common --jobs=100 common:remote --extra_execution_platforms=//:rbe common:remote --remote_executor=grpcs://remote.buildbuddy.io diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index 4f97d2de023..020169b5d31 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -36,9 +36,10 @@ jobs: target: aarch64-unknown-linux-musl - os: ubuntu-24.04 target: x86_64-unknown-linux-musl - # TODO: Enable Windows once we fix the toolchain issues there. - #- os: windows-latest - # target: x86_64-pc-windows-gnullvm + + # Windows + - os: windows-latest + target: x86_64-pc-windows-gnullvm runs-on: ${{ matrix.os }} # Configure a human readable name for each job @@ -61,6 +62,14 @@ jobs: shell: pwsh run: Copy-Item (Get-Command dotslash).Source -Destination "$env:LOCALAPPDATA\Microsoft\WindowsApps\dotslash.exe" + - name: Where is git (pwsh) + if: runner.os == 'Windows' + shell: pwsh + run: | + Get-Command git | Format-List * + (Get-Command git).Source + where.exe git + # Install Bazel via Bazelisk - name: Set up Bazel uses: bazelbuild/setup-bazelisk@v3 @@ -95,7 +104,7 @@ jobs: shell: pwsh run: | # Use a very short path to reduce argv/path length issues. - "BAZEL_STARTUP_ARGS=--output_user_root=C:\" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + "BAZEL_STARTUP_ARGS=--output_user_root=D:\" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: bazel test //... env: diff --git a/.github/workflows/ci.bazelrc b/.github/workflows/ci.bazelrc index 5322d2a8d1d..95ad3b5b361 100644 --- a/.github/workflows/ci.bazelrc +++ b/.github/workflows/ci.bazelrc @@ -2,6 +2,15 @@ common --remote_download_minimal common --nobuild_runfile_links common --keep_going +# By default runfiles directories are disabled on Windows but we +# don't read runfiles manifests, so force them on. +common --enable_runfiles + +# Rearrange caches on Windows so they're on the same volume as the checkout. +common:windows --disk_cache=D:/a/.cache/bazel-disk-cache +common:windows --repo_contents_cache=D:/a/.cache/bazel-repo-contents-cache +common:windows --repository_cache=D:/a/.cache/bazel-repo-cache + # We prefer to run the build actions entirely remotely so we can dial up the concurrency. # We have platform-specific tests, so we want to execute the tests on all platforms using the strongest sandboxing available on each platform. diff --git a/MODULE.bazel b/MODULE.bazel index 2547325c9d9..64d7a395363 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -2,13 +2,9 @@ bazel_dep(name = "platforms", version = "1.0.0") bazel_dep(name = "toolchains_llvm_bootstrapped", version = "0.3.1") archive_override( module_name = "toolchains_llvm_bootstrapped", - integrity = "sha256-9ks21bgEqbQWmwUIvqeLA64+Jk6o4ZVjC8KxjVa2Vw8=", - strip_prefix = "toolchains_llvm_bootstrapped-e3775e66a7b6d287c705ca0cd24497ef4a77c503", - urls = ["https://github.com/cerisier/toolchains_llvm_bootstrapped/archive/e3775e66a7b6d287c705ca0cd24497ef4a77c503/master.tar.gz"], - patch_strip = 1, - patches = [ - "//patches:llvm_toolchain_archive_params.patch", - ], + integrity = "sha256-4/2h4tYSUSptxFVI9G50yJxWGOwHSeTeOGBlaLQBV8g=", + strip_prefix = "toolchains_llvm_bootstrapped-d20baf67e04d8e2887e3779022890d1dc5e6b948", + urls = ["https://github.com/cerisier/toolchains_llvm_bootstrapped/archive/d20baf67e04d8e2887e3779022890d1dc5e6b948/master.tar.gz"], ) osx = use_extension("@toolchains_llvm_bootstrapped//toolchain/extension:osx.bzl", "osx") @@ -41,6 +37,7 @@ single_version_override( "//patches:rules_rust.patch", "//patches:rules_rust_windows_gnu.patch", "//patches:rules_rust_musl.patch", + "//patches:rules_rust_direct_deps.patch", ], ) @@ -57,7 +54,7 @@ rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") rust.toolchain( edition = "2024", extra_target_triples = RUST_TRIPLES, - versions = ["1.90.0"], + versions = ["1.92.0"], ) use_repo(rust, "rust_toolchains") diff --git a/patches/llvm_toolchain_archive_params.patch b/patches/llvm_toolchain_archive_params.patch deleted file mode 100644 index bd148829a23..00000000000 --- a/patches/llvm_toolchain_archive_params.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff --git a/toolchain/cc_toolchain.bzl b/toolchain/cc_toolchain.bzl -index 58da8ec..bf1fbdd 100644 ---- a/toolchain/cc_toolchain.bzl -+++ b/toolchain/cc_toolchain.bzl -@@ -26,6 +26,7 @@ def cc_toolchain(name, tool_map): - cc_feature_set( - name = name + "_runtimes_only_known_features", - all_of = [ -+ "//toolchain/features:archive_param_file", - # Always last (contains user_compile_flags and user_link_flags who should apply last). - "@rules_cc//cc/toolchains/args:experimental_replace_legacy_action_config_features", - ], -@@ -45,6 +46,7 @@ def cc_toolchain(name, tool_map): - ], - "@platforms//os:none": [], - }) + [ -+ "//toolchain/features:archive_param_file", - "//toolchain/features/legacy:all_legacy_builtin_features", - # Always last (contains user_compile_flags and user_link_flags who should apply last). - "@rules_cc//cc/toolchains/args:experimental_replace_legacy_action_config_features", -@@ -54,6 +56,7 @@ def cc_toolchain(name, tool_map): - cc_feature_set( - name = name + "_runtimes_only_enabled_features", - all_of = [ -+ "//toolchain/features:archive_param_file", - # Always last (contains user_compile_flags and user_link_flags who should apply last). - "@rules_cc//cc/toolchains/args:experimental_replace_legacy_action_config_features", - ], -diff --git a/toolchain/features/BUILD.bazel b/toolchain/features/BUILD.bazel -index e787484..bccd45b 100644 ---- a/toolchain/features/BUILD.bazel -+++ b/toolchain/features/BUILD.bazel -@@ -17,6 +17,11 @@ cc_feature( - overrides = "@rules_cc//cc/toolchains/features:static_link_cpp_runtimes", - ) - -+cc_feature( -+ name = "archive_param_file", -+ feature_name = "archive_param_file", -+) -+ - cc_args( - name = "opt_link_flags", - actions = [ -@@ -124,6 +129,7 @@ cc_feature( - cc_feature_set( - name = "all_non_legacy_builtin_features", - all_of = [ -+ ":archive_param_file", - ":opt", - ":opt_stub", - ":dbg", diff --git a/patches/rules_rust_direct_deps.patch b/patches/rules_rust_direct_deps.patch new file mode 100644 index 00000000000..3a991085590 --- /dev/null +++ b/patches/rules_rust_direct_deps.patch @@ -0,0 +1,515 @@ +diff -ruN rules_rust_src/rust/platform/triple.bzl rules_rust_mod/rust/platform/triple.bzl +--- rules_rust_src/rust/platform/triple.bzl 2025-12-09 17:08:33 ++++ rules_rust_mod/rust/platform/triple.bzl 2026-01-13 20:19:36 +@@ -156,9 +156,10 @@ + if "win" in repository_ctx.os.name: + _validate_cpu_architecture(arch, supported_architectures["windows"]) + prefix = "{}-pc-windows".format(arch) ++ default_abi = "gnullvm" + return triple("{}-{}".format( + prefix, +- abi.get(prefix, "msvc"), ++ abi.get(prefix, default_abi), + )) + + fail("Unhandled host os: {}", repository_ctx.os.name) +diff -ruN rules_rust_src/rust/platform/triple_mappings.bzl rules_rust_mod/rust/platform/triple_mappings.bzl +--- rules_rust_src/rust/platform/triple_mappings.bzl 2025-12-09 17:08:33 ++++ rules_rust_mod/rust/platform/triple_mappings.bzl 2026-01-13 20:19:41 +@@ -29,6 +29,7 @@ + "i686-pc-windows-msvc": _support(std = True, host_tools = True), + "i686-unknown-linux-gnu": _support(std = True, host_tools = True), + "x86_64-apple-darwin": _support(std = True, host_tools = True), ++ "x86_64-pc-windows-gnullvm": _support(std = True, host_tools = True), + "x86_64-pc-windows-msvc": _support(std = True, host_tools = True), + "x86_64-unknown-linux-gnu": _support(std = True, host_tools = True), + "x86_64-unknown-nixos-gnu": _support(std = True, host_tools = True), # Same as `x86_64-unknown-linux-gnu` but with `@platforms//os:nixos`. +@@ -45,6 +46,7 @@ + "aarch64-apple-ios": _support(std = True, host_tools = False), + "aarch64-apple-ios-sim": _support(std = True, host_tools = False), + "aarch64-linux-android": _support(std = True, host_tools = False), ++ "aarch64-pc-windows-gnullvm": _support(std = True, host_tools = True), + "aarch64-pc-windows-msvc": _support(std = True, host_tools = True), + "aarch64-unknown-fuchsia": _support(std = True, host_tools = False), + "aarch64-unknown-uefi": _support(std = True, host_tools = False), +diff -ruN rules_rust_src/rust/private/clippy.bzl rules_rust_mod/rust/private/clippy.bzl +--- rules_rust_src/rust/private/clippy.bzl 2025-12-09 17:08:33 ++++ rules_rust_mod/rust/private/clippy.bzl 2026-01-13 09:56:14 +@@ -140,7 +140,11 @@ + ctx.rule.attr.lint_config[LintsInfo].clippy_lint_files + \ + ctx.rule.attr.lint_config[LintsInfo].rustc_lint_files + +- compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs = collect_inputs( ++ transitive_crate_dir = ctx.actions.declare_directory(ctx.label.name + "_transitive_crates") ++ transitive_crate_dir_args = ctx.actions.args() ++ transitive_crate_dir_args.add_all([transitive_crate_dir], expand_directories = False, format_each = "-Ldependency=%s") ++ ++ compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs, _proc_macro_outputs = collect_inputs( + ctx, + ctx.rule.file, + ctx.rule.files, +@@ -151,8 +155,10 @@ + feature_configuration, + crate_info, + dep_info, ++ crate_info.proc_macro_deps.to_list(), + build_info, + lint_files, ++ transitive_crate_dir, + ) + + if clippy_diagnostics_file: +@@ -229,7 +235,7 @@ + outputs = outputs + [x for x in [clippy_diagnostics_file] if x], + env = env, + tools = [clippy_executable], +- arguments = args.all, ++ arguments = args.all + [transitive_crate_dir_args], + mnemonic = "Clippy", + progress_message = "Clippy %{label}", + toolchain = "@rules_rust//rust:toolchain_type", +diff -ruN rules_rust_src/rust/private/common.bzl rules_rust_mod/rust/private/common.bzl +--- rules_rust_src/rust/private/common.bzl 2025-12-09 17:08:33 ++++ rules_rust_mod/rust/private/common.bzl 2026-01-13 20:43:07 +@@ -31,9 +31,9 @@ + # + # Note: Code in `.github/workflows/crate_universe.yaml` looks for this line, if + # you remove it or change its format, you will also need to update that code. +-DEFAULT_RUST_VERSION = "1.86.0" ++DEFAULT_RUST_VERSION = "1.92.0" + +-DEFAULT_NIGHTLY_ISO_DATE = "2025-04-03" ++DEFAULT_NIGHTLY_ISO_DATE = "2025-10-03" + + def _create_crate_info(**kwargs): + """A constructor for a `CrateInfo` provider +diff -ruN rules_rust_src/rust/private/rust.bzl rules_rust_mod/rust/private/rust.bzl +--- rules_rust_src/rust/private/rust.bzl 2025-12-09 17:08:33 ++++ rules_rust_mod/rust/private/rust.bzl 2026-01-13 09:56:14 +@@ -935,6 +935,7 @@ + }, + fragments = ["cpp"], + toolchains = [ ++ str(Label("@@bazel_lib+//lib:copy_to_directory_toolchain_type")), + str(Label("//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], +@@ -1033,6 +1034,7 @@ + fragments = ["cpp"], + cfg = _rust_static_library_transition, + toolchains = [ ++ str(Label("@@bazel_lib+//lib:copy_to_directory_toolchain_type")), + str(Label("//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], +@@ -1082,6 +1084,7 @@ + fragments = ["cpp"], + cfg = _rust_shared_library_transition, + toolchains = [ ++ str(Label("@@bazel_lib+//lib:copy_to_directory_toolchain_type")), + str(Label("//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], +@@ -1138,6 +1141,7 @@ + ), + fragments = ["cpp"], + toolchains = [ ++ str(Label("@@bazel_lib+//lib:copy_to_directory_toolchain_type")), + str(Label("//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], +@@ -1222,6 +1226,7 @@ + fragments = ["cpp"], + cfg = _rust_binary_transition, + toolchains = [ ++ str(Label("@@bazel_lib+//lib:copy_to_directory_toolchain_type")), + str(Label("//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], +@@ -1365,6 +1370,7 @@ + executable = True, + fragments = ["cpp"], + toolchains = [ ++ str(Label("@@bazel_lib+//lib:copy_to_directory_toolchain_type")), + str(Label("//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], +@@ -1381,6 +1387,7 @@ + attrs = dict(_common_attrs_for_binary_without_process_wrapper(_common_attrs).items()), + fragments = ["cpp"], + toolchains = [ ++ str(Label("@@bazel_lib+//lib:copy_to_directory_toolchain_type")), + str(Label("//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], +@@ -1421,6 +1428,7 @@ + fragments = ["cpp"], + test = True, + toolchains = [ ++ str(Label("@@bazel_lib+//lib:copy_to_directory_toolchain_type")), + str(Label("//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], +@@ -1458,6 +1466,7 @@ + cfg = _rust_test_transition, + test = True, + toolchains = [ ++ str(Label("@@bazel_lib+//lib:copy_to_directory_toolchain_type")), + str(Label("//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], +diff -ruN rules_rust_src/rust/private/rustc.bzl rules_rust_mod/rust/private/rustc.bzl +--- rules_rust_src/rust/private/rustc.bzl 2025-12-09 17:08:33 ++++ rules_rust_mod/rust/private/rustc.bzl 2026-01-13 20:55:51 +@@ -14,6 +14,7 @@ + + """Functionality for constructing actions that invoke the Rust compiler""" + ++load("@@bazel_lib+//lib:copy_to_directory.bzl", "copy_to_directory_bin_action") + load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") + load( + "@bazel_tools//tools/build_defs/cc:action_names.bzl", +@@ -695,8 +696,10 @@ + feature_configuration, + crate_info, + dep_info, ++ proc_macro_deps, + build_info, + lint_files, ++ transitive_crate_dir, + stamp = False, + force_depend_on_objects = False, + experimental_use_cc_common_link = False, +@@ -714,8 +717,10 @@ + feature_configuration (FeatureConfiguration): Feature configuration to be queried. + crate_info (CrateInfo): The Crate information of the crate to process build scripts for. + dep_info (DepInfo): The target Crate's dependency information. ++ proc_macro_deps (list[DepVariantInfo]): Proc-macro dependencies for the crate. + build_info (BuildInfo): The target Crate's build settings. + lint_files (list): List of files with rustc args for the Crate's lint settings. ++ transitive_crate_dir (File): Directory containing consolidated crate outputs. + stamp (bool, optional): Whether or not workspace status stamping is enabled. For more details see + https://docs.bazel.build/versions/main/user-manual.html#flag--stamp + force_depend_on_objects (bool, optional): Forces dependencies of this rule to be objects rather than +@@ -773,6 +778,19 @@ + if _depend_on_metadata(crate_info, force_depend_on_objects): + transitive_crate_outputs = dep_info.transitive_metadata_outputs + ++ proc_macro_outputs = [] ++ for dep in proc_macro_deps: ++ dep_crate_info = dep.crate_info ++ if dep_crate_info and _is_proc_macro(dep_crate_info): ++ proc_macro_outputs.append(dep_crate_info.output) ++ for dep in dep_info.direct_crates.to_list(): ++ if hasattr(dep, "dep"): ++ dep_crate_info = dep.dep ++ else: ++ dep_crate_info = dep ++ if _is_proc_macro(dep_crate_info) and dep_crate_info.output not in proc_macro_outputs: ++ proc_macro_outputs.append(dep_crate_info.output) ++ + nolinkstamp_compile_direct_inputs = [] + if build_info: + if build_info.rustc_env: +@@ -800,6 +818,8 @@ + else: + runtime_libs = cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration) + ++ proc_macro_outputs_depset = depset(proc_macro_outputs) ++ + nolinkstamp_compile_inputs = depset( + nolinkstamp_compile_direct_inputs + + additional_transitive_inputs, +@@ -808,6 +828,7 @@ + linker_depset, + crate_info.srcs, + transitive_crate_outputs, ++ proc_macro_outputs_depset, + crate_info.compile_data, + dep_info.transitive_proc_macro_data, + toolchain.all_files, +@@ -846,8 +867,27 @@ + # If stamping is enabled include the volatile and stable status info file + stamp_info = [ctx.version_file, ctx.info_file] if stamp else [] + ++ transitive_crate_files = depset( ++ transitive = [ ++ dep_info.transitive_crate_outputs, ++ dep_info.transitive_metadata_outputs, ++ ], ++ ).to_list() + proc_macro_outputs ++ ++ copy_to_directory_bin_action( ++ ctx, ++ name = transitive_crate_dir.basename, ++ dst = transitive_crate_dir, ++ copy_to_directory_bin = ctx.toolchains["@@bazel_lib+//lib:copy_to_directory_toolchain_type"].copy_to_directory_info.bin, ++ files = transitive_crate_files, ++ root_paths = [], ++ replace_prefixes = {"**/": ""}, ++ hardlink = "auto", ++ include_external_repositories = ["**"], ++ ) ++ + compile_inputs = depset( +- linkstamp_outs + stamp_info, ++ [transitive_crate_dir] + linkstamp_outs + stamp_info, + transitive = [ + nolinkstamp_compile_inputs, + ], +@@ -870,7 +910,7 @@ + build_env_files = list(build_env_files) + build_env_files.append(build_env_file) + compile_inputs = depset(build_env_files + lint_files, transitive = [build_script_compile_inputs, compile_inputs]) +- return compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs ++ return compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs, proc_macro_outputs_depset + + def _will_emit_object_file(emit): + for e in emit: +@@ -892,6 +932,7 @@ + feature_configuration, + crate_info, + dep_info, ++ transitive_crate_dir, + linkstamp_outs, + ambiguous_libs, + output_hash, +@@ -923,6 +964,7 @@ + feature_configuration (FeatureConfiguration): Class used to construct command lines from CROSSTOOL features. + crate_info (CrateInfo): The CrateInfo provider of the target crate + dep_info (DepInfo): The DepInfo provider of the target crate ++ transitive_crate_dir (File): Directory containing consolidated crate outputs. + linkstamp_outs (list): Linkstamp outputs of native dependencies + ambiguous_libs (dict): Ambiguous libs, see `_disambiguate_libs` + output_hash (str): The hashed path of the crate root +@@ -1155,7 +1197,13 @@ + use_metadata = _depend_on_metadata(crate_info, force_depend_on_objects) + + # These always need to be added, even if not linking this crate. +- add_crate_link_flags(rustc_flags, dep_info, force_all_deps_direct, use_metadata) ++ add_crate_link_flags( ++ rustc_flags, ++ dep_info, ++ force_all_deps_direct, ++ use_metadata, ++ transitive_crate_dir, ++ ) + + needs_extern_proc_macro_flag = _is_proc_macro(crate_info) and crate_info.edition != "2015" + if needs_extern_proc_macro_flag: +@@ -1359,7 +1407,11 @@ + rust_flags = rust_flags + ctx.attr.lint_config[LintsInfo].rustc_lint_flags + lint_files = lint_files + ctx.attr.lint_config[LintsInfo].rustc_lint_files + +- compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs = collect_inputs( ++ transitive_crate_dir = ctx.actions.declare_directory(attr.name + "_transitive_crates") ++ transitive_crate_dir_args = ctx.actions.args() ++ transitive_crate_dir_args.add_all([transitive_crate_dir], expand_directories = False, format_each = "-Ldependency=%s") ++ ++ compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs, proc_macro_outputs = collect_inputs( + ctx = ctx, + file = ctx.file, + files = ctx.files, +@@ -1369,8 +1421,10 @@ + feature_configuration = feature_configuration, + crate_info = crate_info, + dep_info = dep_info, ++ proc_macro_deps = proc_macro_deps, + build_info = build_info, + lint_files = lint_files, ++ transitive_crate_dir = transitive_crate_dir, + stamp = stamp, + experimental_use_cc_common_link = experimental_use_cc_common_link, + ) +@@ -1410,6 +1464,7 @@ + feature_configuration = feature_configuration, + crate_info = crate_info, + dep_info = dep_info, ++ transitive_crate_dir = transitive_crate_dir, + linkstamp_outs = linkstamp_outs, + ambiguous_libs = ambiguous_libs, + output_hash = output_hash, +@@ -1437,6 +1492,7 @@ + feature_configuration = feature_configuration, + crate_info = crate_info, + dep_info = dep_info, ++ transitive_crate_dir = transitive_crate_dir, + linkstamp_outs = linkstamp_outs, + ambiguous_libs = ambiguous_libs, + output_hash = output_hash, +@@ -1509,7 +1565,8 @@ + inputs = compile_inputs, + outputs = action_outputs, + env = env, +- arguments = args.all, ++ arguments = args.all + [transitive_crate_dir_args], ++ tools = proc_macro_outputs.to_list(), + mnemonic = "Rustc", + progress_message = "Compiling Rust {} {}{} ({} file{})".format( + crate_info.type, +@@ -1527,7 +1584,8 @@ + inputs = compile_inputs, + outputs = [build_metadata] + [x for x in [rustc_rmeta_output] if x], + env = env, +- arguments = args_metadata.all, ++ arguments = args_metadata.all + [transitive_crate_dir_args], ++ tools = proc_macro_outputs.to_list(), + mnemonic = "RustcMetadata", + progress_message = "Compiling Rust metadata {} {}{} ({} file{})".format( + crate_info.type, +@@ -1547,7 +1605,8 @@ + inputs = compile_inputs, + outputs = action_outputs, + env = env, +- arguments = [args.rustc_path, args.rustc_flags], ++ arguments = [args.rustc_path, args.rustc_flags, transitive_crate_dir_args], ++ tools = proc_macro_outputs.to_list(), + mnemonic = "Rustc", + progress_message = "Compiling Rust (without process_wrapper) {} {}{} ({} file{})".format( + crate_info.type, +@@ -2119,7 +2178,7 @@ + dirs[f.dirname] = None + return dirs.keys() + +-def add_crate_link_flags(args, dep_info, force_all_deps_direct = False, use_metadata = False): ++def add_crate_link_flags(args, dep_info, force_all_deps_direct = False, use_metadata = False, transitive_crate_dir = None): + """Adds link flags to an Args object reference + + Args: +@@ -2137,6 +2196,11 @@ + ], + ) if force_all_deps_direct else dep_info.direct_crates + ++ if transitive_crate_dir: ++ for crate in direct_crates.to_list(): ++ _add_crate_link_flag_in_dir(args, crate, transitive_crate_dir, use_metadata) ++ return ++ + crate_to_link_flags = _crate_to_link_flag_metadata if use_metadata else _crate_to_link_flag + args.add_all(direct_crates, uniquify = True, map_each = crate_to_link_flags) + +@@ -2146,6 +2210,34 @@ + uniquify = True, + format_each = "-Ldependency=%s", + ) ++ ++def _add_crate_link_flag_in_dir(args, crate, transitive_crate_dir, use_metadata): ++ """A helper macro used by `add_crate_link_flags` for adding crate link flags to a Arg object ++ ++ Args: ++ crate (CrateInfo|AliasableDepInfo): A CrateInfo or an AliasableDepInfo provider ++ transitive_crate_dir (File): Directory containing consolidated crate outputs. ++ use_metadata (bool): Whether to prefer metadata files when available. ++ ++ Returns: ++ list: Link flags for the given provider ++ """ ++ if hasattr(crate, "dep"): ++ name = crate.name ++ crate_info = crate.dep ++ else: ++ name = crate.name ++ crate_info = crate ++ ++ if _is_proc_macro(crate_info): ++ args.add("--extern={}={}/{}".format(name, transitive_crate_dir.path, crate_info.output.basename)) ++ return ++ ++ lib_or_meta = crate_info.metadata if use_metadata else crate_info.output ++ if use_metadata and (not crate_info.metadata or not crate_info.metadata_supports_pipelining): ++ lib_or_meta = crate_info.output ++ ++ args.add("--extern={}={}/{}".format(name, transitive_crate_dir.path, lib_or_meta.basename)) + + def _crate_to_link_flag_metadata(crate): + """A helper macro used by `add_crate_link_flags` for adding crate link flags to a Arg object +diff -ruN rules_rust_src/rust/private/rustdoc.bzl rules_rust_mod/rust/private/rustdoc.bzl +--- rules_rust_src/rust/private/rustdoc.bzl 2025-12-09 17:08:33 ++++ rules_rust_mod/rust/private/rustdoc.bzl 2026-01-13 09:56:14 +@@ -103,7 +103,11 @@ + aliases = crate_info.aliases, + ) + +- compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs = collect_inputs( ++ transitive_crate_dir = ctx.actions.declare_directory(ctx.label.name + "_transitive_crates") ++ transitive_crate_dir_args = ctx.actions.args() ++ transitive_crate_dir_args.add_all([transitive_crate_dir], expand_directories = False, format_each = "-Ldependency=%s") ++ ++ compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs, _proc_macro_outputs = collect_inputs( + ctx = ctx, + file = ctx.file, + files = ctx.files, +@@ -113,8 +117,10 @@ + feature_configuration = feature_configuration, + crate_info = crate_info, + dep_info = dep_info, ++ proc_macro_deps = crate_info.proc_macro_deps.to_list(), + build_info = build_info, + lint_files = lint_files, ++ transitive_crate_dir = transitive_crate_dir, + # If this is a rustdoc test, we need to depend on rlibs rather than .rmeta. + force_depend_on_objects = is_test, + include_link_flags = False, +@@ -167,7 +173,7 @@ + executable = ctx.executable._process_wrapper, + inputs = all_inputs, + env = env, +- arguments = args.all, ++ arguments = args.all + [transitive_crate_dir_args], + tools = [toolchain.rust_doc], + ) + +diff -ruN rules_rust_src/rust/private/unpretty.bzl rules_rust_mod/rust/private/unpretty.bzl +--- rules_rust_src/rust/private/unpretty.bzl 2025-12-09 17:08:33 ++++ rules_rust_mod/rust/private/unpretty.bzl 2026-01-13 09:56:14 +@@ -147,7 +147,11 @@ + ) + lint_files = [] + +- compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs = collect_inputs( ++ transitive_crate_dir = ctx.actions.declare_directory(ctx.label.name + "_transitive_crates") ++ transitive_crate_dir_args = ctx.actions.args() ++ transitive_crate_dir_args.add_all([transitive_crate_dir], expand_directories = False, format_each = "-Ldependency=%s") ++ ++ compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs, _proc_macro_outputs = collect_inputs( + ctx, + ctx.rule.file, + ctx.rule.files, +@@ -158,8 +162,10 @@ + feature_configuration, + crate_info, + dep_info, ++ crate_info.proc_macro_deps.to_list(), + build_info, + lint_files, ++ transitive_crate_dir, + ) + + output_groups = {} +@@ -217,7 +223,7 @@ + inputs = compile_inputs, + outputs = [unpretty_out], + env = env, +- arguments = args.all, ++ arguments = args.all + [transitive_crate_dir_args], + mnemonic = mnemonic, + toolchain = "@rules_rust//rust:toolchain_type", + ) +diff -ruN rules_rust_src/rust/repositories.bzl rules_rust_mod/rust/repositories.bzl +--- rules_rust_src/rust/repositories.bzl 2025-12-09 17:08:33 ++++ rules_rust_mod/rust/repositories.bzl 2026-01-13 20:19:46 +@@ -43,12 +43,12 @@ + # Note: Code in `.github/workflows/crate_universe.yaml` looks for this line, if you remove it or change its format, you will also need to update that code. + DEFAULT_TOOLCHAIN_TRIPLES = { + "aarch64-apple-darwin": "rust_macos_aarch64", +- "aarch64-pc-windows-msvc": "rust_windows_aarch64", ++ "aarch64-pc-windows-gnullvm": "rust_windows_aarch64", + "aarch64-unknown-linux-gnu": "rust_linux_aarch64", + "powerpc64le-unknown-linux-gnu": "rust_linux_powerpc64le", + "s390x-unknown-linux-gnu": "rust_linux_s390x", + "x86_64-apple-darwin": "rust_macos_x86_64", +- "x86_64-pc-windows-msvc": "rust_windows_x86_64", ++ "x86_64-pc-windows-gnullvm": "rust_windows_x86_64", + "x86_64-unknown-freebsd": "rust_freebsd_x86_64", + "x86_64-unknown-linux-gnu": "rust_linux_x86_64", + }