diff --git a/BUILD.bazel b/BUILD.bazel index a82126e6f1..dfd46bd8ca 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,4 +1,5 @@ load("@apple_support//xcode:xcode_config.bzl", "xcode_config") +load("//:windows_platform_test.bzl", "windows_platform_declarations_test") xcode_config(name = "disable_xcode") @@ -17,6 +18,7 @@ platform( platform( name = "local_windows", constraint_values = [ + "@llvm//constraints/windows_abi:gnullvm", "@rules_rs//rs/experimental/platforms/constraints:windows_gnullvm", ], parents = ["@platforms//host"], @@ -25,14 +27,19 @@ platform( platform( name = "local_windows_msvc", constraint_values = [ + "@llvm//constraints/windows_abi:msvc", "@rules_rs//rs/experimental/platforms/constraints:windows_msvc", ], parents = ["@platforms//host"], ) +# The hermetic LLVM Windows toolchain is llvm-mingw and therefore gnullvm. +# MSVC targets intentionally resolve only on Windows hosts with an installed +# MSVC toolchain and Windows SDK. platform( name = "windows_x86_64_gnullvm", constraint_values = [ + "@llvm//constraints/windows_abi:gnullvm", "@platforms//cpu:x86_64", "@platforms//os:windows", "@rules_rs//rs/experimental/platforms/constraints:windows_gnullvm", @@ -42,6 +49,7 @@ platform( platform( name = "windows_x86_64_msvc", constraint_values = [ + "@llvm//constraints/windows_abi:msvc", "@platforms//cpu:x86_64", "@platforms//os:windows", "@rules_rs//rs/experimental/platforms/constraints:windows_msvc", @@ -64,6 +72,17 @@ toolchain( toolchain_type = "@bazel_tools//tools/test:default_test_toolchain_type", ) +windows_platform_declarations_test( + name = "windows_platform_declarations_test", + data = [ + "BUILD.bazel", + "MODULE.bazel", + "//patches:llvm_windows_gnullvm_abi.patch", + ], + script = "windows_platform_test.sh", + target_compatible_with = ["@platforms//os:linux"], +) + alias( name = "rbe", actual = "@rbe_platform", diff --git a/MODULE.bazel b/MODULE.bazel index c4ef9500a7..f123c30f33 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -11,6 +11,7 @@ single_version_override( patch_strip = 1, patches = [ "//patches:llvm_rusty_v8_custom_libcxx.patch", + "//patches:llvm_windows_gnullvm_abi.patch", "//patches:llvm_windows_symlink_extract.patch", ], ) diff --git a/patches/BUILD.bazel b/patches/BUILD.bazel index 72d6990790..b8e839ce18 100644 --- a/patches/BUILD.bazel +++ b/patches/BUILD.bazel @@ -5,6 +5,7 @@ exports_files([ "aws-lc-sys_windows_msvc_memcmp_probe.patch", "bzip2_windows_stack_args.patch", "llvm_rusty_v8_custom_libcxx.patch", + "llvm_windows_gnullvm_abi.patch", "llvm_windows_symlink_extract.patch", "rules_rust_windows_bootstrap_process_wrapper_linker.patch", "rules_rust_windows_build_script_runner_paths.patch", diff --git a/patches/llvm_windows_gnullvm_abi.patch b/patches/llvm_windows_gnullvm_abi.patch new file mode 100644 index 0000000000..8395b19195 --- /dev/null +++ b/patches/llvm_windows_gnullvm_abi.patch @@ -0,0 +1,55 @@ +# What: mark hermetic LLVM's Windows targets as gnullvm-only. +# Why: the toolchain uses *-w64-windows-gnu triples and MinGW runtimes; it does +# not contain the licensed MSVC linker libraries or Windows SDK. + +diff --git a/constraints/windows_abi/BUILD.bazel b/constraints/windows_abi/BUILD.bazel +new file mode 100644 +index 0000000..42aa1aa +--- /dev/null ++++ b/constraints/windows_abi/BUILD.bazel +@@ -0,0 +1,15 @@ ++package(default_visibility = ["//visibility:public"]) ++ ++constraint_setting( ++ name = "windows_abi", ++) ++ ++constraint_value( ++ name = "gnullvm", ++ constraint_setting = ":windows_abi", ++) ++ ++constraint_value( ++ name = "msvc", ++ constraint_setting = ":windows_abi", ++) +diff --git a/toolchain/bootstrap/declare_toolchains.bzl b/toolchain/bootstrap/declare_toolchains.bzl +index 906ba7e..608ec56 100644 +--- a/toolchain/bootstrap/declare_toolchains.bzl ++++ b/toolchain/bootstrap/declare_toolchains.bzl +@@ -260,7 +260,9 @@ def declare_toolchains( + target_compatible_with = [ + "@platforms//cpu:{}".format(target_cpu), + "@platforms//os:{}".format(target_os), +- ], ++ ] + ([ ++ "@llvm//constraints/windows_abi:gnullvm", ++ ] if target_os == "windows" else []), + target_settings = [ + "@llvm//toolchain:bootstrapped_toolchain", + ], +diff --git a/toolchain/declare_toolchains.bzl b/toolchain/declare_toolchains.bzl +index 9870bdd..5d06829 100644 +--- a/toolchain/declare_toolchains.bzl ++++ b/toolchain/declare_toolchains.bzl +@@ -34,7 +34,9 @@ def declare_toolchains(*, execs = SUPPORTED_EXECS, targets = SUPPORTED_TARGETS): + target_compatible_with = [ + "@platforms//cpu:{}".format(target_cpu), + "@platforms//os:{}".format(target_os), +- ], ++ ] + ([ ++ "@llvm//constraints/windows_abi:gnullvm", ++ ] if target_os == "windows" else []), + target_settings = [ + "@llvm//toolchain:prebuilt_toolchain", + ], diff --git a/windows_platform_test.bzl b/windows_platform_test.bzl new file mode 100644 index 0000000000..e8679a62fd --- /dev/null +++ b/windows_platform_test.bzl @@ -0,0 +1,27 @@ +def _windows_platform_declarations_test_impl(ctx): + executable = ctx.actions.declare_file(ctx.label.name + ".sh") + ctx.actions.symlink( + output = executable, + target_file = ctx.executable.script, + is_executable = True, + ) + return [ + DefaultInfo( + executable = executable, + runfiles = ctx.runfiles(files = ctx.files.data), + ), + ] + +windows_platform_declarations_test = rule( + implementation = _windows_platform_declarations_test_impl, + attrs = { + "data": attr.label_list(allow_files = True), + "script": attr.label( + allow_single_file = True, + cfg = "target", + executable = True, + mandatory = True, + ), + }, + test = True, +) diff --git a/windows_platform_test.sh b/windows_platform_test.sh new file mode 100755 index 0000000000..585bd96954 --- /dev/null +++ b/windows_platform_test.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +set -euo pipefail + +workspace="${TEST_SRCDIR}/${TEST_WORKSPACE}" +build_file="${workspace}/BUILD.bazel" +module_file="${workspace}/MODULE.bazel" +llvm_patch="${workspace}/patches/llvm_windows_gnullvm_abi.patch" + +require_line() { + local file="$1" + local line="$2" + if ! grep -Fqx -- "$line" "$file"; then + echo "missing '$line' in $file" >&2 + exit 1 + fi +} + +require_platform_constraint() { + local platform="$1" + local constraint="$2" + local block + block="$(sed -n "/name = \"${platform}\"/,/^)/p" "$build_file")" + if ! grep -Fq -- "\"${constraint}\"," <<<"$block"; then + echo "platform '$platform' is missing constraint '$constraint'" >&2 + exit 1 + fi +} + +require_count() { + local expected="$1" + local file="$2" + local line="$3" + local actual + actual="$(grep -Fxc -- "$line" "$file" || true)" + if [[ "$actual" != "$expected" ]]; then + echo "expected $expected copies of '$line' in $file, found $actual" >&2 + exit 1 + fi +} + +require_platform_constraint local_windows "@llvm//constraints/windows_abi:gnullvm" +require_platform_constraint local_windows_msvc "@llvm//constraints/windows_abi:msvc" +require_platform_constraint windows_x86_64_gnullvm "@llvm//constraints/windows_abi:gnullvm" +require_platform_constraint windows_x86_64_msvc "@llvm//constraints/windows_abi:msvc" +require_line "$module_file" ' "//patches:llvm_windows_gnullvm_abi.patch",' +require_count 2 "$llvm_patch" '+ "@llvm//constraints/windows_abi:gnullvm",'