diff --git a/.github/scripts/run-bazel-ci.sh b/.github/scripts/run-bazel-ci.sh index 0e46b7157..9c95fda15 100755 --- a/.github/scripts/run-bazel-ci.sh +++ b/.github/scripts/run-bazel-ci.sh @@ -5,6 +5,7 @@ set -euo pipefail print_failed_bazel_test_logs=0 use_node_test_env=0 remote_download_toplevel=0 +windows_msvc_host_platform=0 while [[ $# -gt 0 ]]; do case "$1" in @@ -20,6 +21,10 @@ while [[ $# -gt 0 ]]; do remote_download_toplevel=1 shift ;; + --windows-msvc-host-platform) + windows_msvc_host_platform=1 + shift + ;; --) shift break @@ -32,7 +37,7 @@ while [[ $# -gt 0 ]]; do done if [[ $# -eq 0 ]]; then - echo "Usage: $0 [--print-failed-test-logs] [--use-node-test-env] [--remote-download-toplevel] -- -- " >&2 + echo "Usage: $0 [--print-failed-test-logs] [--use-node-test-env] [--remote-download-toplevel] [--windows-msvc-host-platform] -- -- " >&2 exit 1 fi @@ -121,14 +126,35 @@ if [[ ${#bazel_args[@]} -eq 0 || ${#bazel_targets[@]} -eq 0 ]]; then exit 1 fi -if [[ $use_node_test_env -eq 1 && "${RUNNER_OS:-}" != "Windows" ]]; then +if [[ $use_node_test_env -eq 1 ]]; then # Bazel test sandboxes on macOS may resolve an older Homebrew `node` # before the `actions/setup-node` runtime on PATH. node_bin="$(which node)" + if [[ "${RUNNER_OS:-}" == "Windows" ]]; then + node_bin="$(cygpath -w "${node_bin}")" + fi bazel_args+=("--test_env=CODEX_JS_REPL_NODE_PATH=${node_bin}") fi post_config_bazel_args=() +if [[ "${RUNNER_OS:-}" == "Windows" && $windows_msvc_host_platform -eq 1 ]]; then + has_host_platform_override=0 + for arg in "${bazel_args[@]}"; do + if [[ "$arg" == --host_platform=* ]]; then + has_host_platform_override=1 + break + fi + done + + if [[ $has_host_platform_override -eq 0 ]]; then + # Keep Windows Bazel targets on `windows-gnullvm` for cfg coverage, but opt + # specific jobs into an MSVC exec platform when they need helper binaries + # like Rust test wrappers and V8 generators to resolve a compatible host + # toolchain. + post_config_bazel_args+=("--host_platform=//:local_windows_msvc") + fi +fi + if [[ $remote_download_toplevel -eq 1 ]]; then # Override the CI config's remote_download_minimal setting when callers need # the built artifact to exist on disk after the command completes. diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index fa1398c3e..f7f16dd99 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -82,9 +82,16 @@ jobs: -//third_party/v8:all ) + bazel_wrapper_args=( + --print-failed-test-logs + --use-node-test-env + ) + if [[ "${RUNNER_OS}" == "Windows" ]]; then + bazel_wrapper_args+=(--windows-msvc-host-platform) + fi + ./.github/scripts/run-bazel-ci.sh \ - --print-failed-test-logs \ - --use-node-test-env \ + "${bazel_wrapper_args[@]}" \ -- \ test \ --test_tag_filters=-argument-comment-lint \ diff --git a/MODULE.bazel b/MODULE.bazel index 9ef6cbac8..b42936fde 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -72,6 +72,7 @@ single_version_override( patches = [ "//patches:rules_rs_windows_gnullvm_exec.patch", "//patches:rules_rs_delete_git_worktree_pointer.patch", + "//patches:rules_rs_windows_exec_linker.patch", ], version = "0.0.43", ) @@ -85,7 +86,9 @@ rules_rust.patch( "//patches:rules_rust_windows_gnullvm_build_script.patch", "//patches:rules_rust_windows_exec_msvc_build_script_env.patch", "//patches:rules_rust_windows_bootstrap_process_wrapper_linker.patch", + "//patches:rules_rust_windows_build_script_runner_paths.patch", "//patches:rules_rust_windows_msvc_direct_link_args.patch", + "//patches:rules_rust_windows_process_wrapper_skip_temp_outputs.patch", "//patches:rules_rust_windows_exec_bin_target.patch", "//patches:rules_rust_windows_exec_std.patch", "//patches:rules_rust_windows_exec_rustc_dev_rlib.patch", @@ -189,8 +192,18 @@ bazel_dep(name = "zstd", version = "1.5.7") crate.annotation( crate = "zstd-sys", - gen_build_script = "off", - deps = ["@zstd"], + gen_build_script = "on", + patch_args = ["-p1"], + patches = [ + "//patches:zstd-sys_windows_msvc_include_dirs.patch", + ], +) +crate.annotation( + crate = "ring", + patch_args = ["-p1"], + patches = [ + "//patches:ring_windows_msvc_include_dirs.patch", + ], ) crate.annotation( build_script_env = { @@ -218,8 +231,7 @@ bazel_dep(name = "bzip2", version = "1.0.8.bcr.3") crate.annotation( crate = "bzip2-sys", - gen_build_script = "off", - deps = ["@bzip2//:bz2"], + gen_build_script = "on", ) inject_repo(crate, "bzip2") @@ -228,24 +240,19 @@ bazel_dep(name = "zlib", version = "1.3.1.bcr.8") crate.annotation( crate = "libz-sys", - gen_build_script = "off", - deps = ["@zlib"], + gen_build_script = "on", ) inject_repo(crate, "zlib") -bazel_dep(name = "xz", version = "5.4.5.bcr.8") - +# TODO(zbarsky): Enable annotation after fixing windows arm64 builds. crate.annotation( crate = "lzma-sys", - gen_build_script = "off", - deps = ["@xz//:lzma"], + gen_build_script = "on", ) bazel_dep(name = "openssl", version = "3.5.4.bcr.0") -inject_repo(crate, "xz") - crate.annotation( build_script_data = [ "@openssl//:gen_dir", diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 746679af3..1e2123ec4 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -228,8 +228,6 @@ "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", "https://bcr.bazel.build/modules/with_cfg.bzl/0.12.0/MODULE.bazel": "b573395fe63aef4299ba095173e2f62ccfee5ad9bbf7acaa95dba73af9fc2b38", "https://bcr.bazel.build/modules/with_cfg.bzl/0.12.0/source.json": "3f3fbaeafecaf629877ad152a2c9def21f8d330d91aa94c5dc75bbb98c10b8b8", - "https://bcr.bazel.build/modules/xz/5.4.5.bcr.8/MODULE.bazel": "e48a69bd54053c2ec5fffc2a29fb70122afd3e83ab6c07068f63bc6553fa57cc", - "https://bcr.bazel.build/modules/xz/5.4.5.bcr.8/source.json": "bd7e928ccd63505b44f4784f7bbf12cc11f9ff23bf3ca12ff2c91cd74846099e", "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.8/MODULE.bazel": "772c674bb78a0342b8caf32ab5c25085c493ca4ff08398208dcbe4375fe9f776", diff --git a/codex-rs/app-server/BUILD.bazel b/codex-rs/app-server/BUILD.bazel index 5f1ba790d..872f533be 100644 --- a/codex-rs/app-server/BUILD.bazel +++ b/codex-rs/app-server/BUILD.bazel @@ -3,5 +3,6 @@ load("//:defs.bzl", "codex_rust_crate") codex_rust_crate( name = "app-server", crate_name = "codex_app_server", + integration_test_timeout = "long", test_tags = ["no-sandbox"], ) diff --git a/codex-rs/core/BUILD.bazel b/codex-rs/core/BUILD.bazel index 86405cb8a..9141579ab 100644 --- a/codex-rs/core/BUILD.bazel +++ b/codex-rs/core/BUILD.bazel @@ -30,6 +30,7 @@ codex_rust_crate( integration_compile_data_extra = [ "//codex-rs/apply-patch:apply_patch_tool_instructions.md", ], + integration_test_timeout = "long", test_data_extra = [ "config.schema.json", ] + glob([ @@ -46,6 +47,7 @@ codex_rust_crate( "//:AGENTS.md", ], test_tags = ["no-sandbox"], + unit_test_timeout = "long", extra_binaries = [ "//codex-rs/linux-sandbox:codex-linux-sandbox", "//codex-rs/rmcp-client:test_stdio_server", diff --git a/codex-rs/otel/BUILD.bazel b/codex-rs/otel/BUILD.bazel index 1860690be..fdbcf6871 100644 --- a/codex-rs/otel/BUILD.bazel +++ b/codex-rs/otel/BUILD.bazel @@ -3,4 +3,5 @@ load("//:defs.bzl", "codex_rust_crate") codex_rust_crate( name = "otel", crate_name = "codex_otel", + integration_test_args = ["--test-threads=1"], ) diff --git a/codex-rs/tui/BUILD.bazel b/codex-rs/tui/BUILD.bazel index baebe18e9..ef6866293 100644 --- a/codex-rs/tui/BUILD.bazel +++ b/codex-rs/tui/BUILD.bazel @@ -15,7 +15,10 @@ codex_rust_crate( "//codex-rs/collaboration-mode-templates:templates/default.md", "//codex-rs/collaboration-mode-templates:templates/plan.md", ], - test_data_extra = glob(["src/**/snapshots/**"]) + ["//codex-rs/core:model_availability_nux_fixtures"], + test_data_extra = glob([ + "src/**/*.rs", + "src/**/snapshots/**", + ]) + ["//codex-rs/core:model_availability_nux_fixtures"], integration_compile_data_extra = ["src/test_backend.rs"], extra_binaries = [ "//codex-rs/cli:codex", diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index c231a4e4c..4156082cb 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -210,7 +210,14 @@ pub(super) use tokio::sync::mpsc::unbounded_channel; pub(super) use toml::Value as TomlValue; pub(super) fn chatwidget_snapshot_dir() -> PathBuf { - codex_utils_cargo_bin::find_resource!("src/chatwidget/snapshots").expect("snapshot dir") + let snapshot_file = codex_utils_cargo_bin::find_resource!( + "src/chatwidget/snapshots/codex_tui__chatwidget__tests__chatwidget_tall.snap" + ) + .expect("snapshot file"); + snapshot_file + .parent() + .unwrap_or_else(|| panic!("snapshot file has no parent: {}", snapshot_file.display())) + .to_path_buf() } macro_rules! assert_chatwidget_snapshot { diff --git a/codex-rs/tui/tests/manager_dependency_regression.rs b/codex-rs/tui/tests/manager_dependency_regression.rs index 35a05b703..908b054e0 100644 --- a/codex-rs/tui/tests/manager_dependency_regression.rs +++ b/codex-rs/tui/tests/manager_dependency_regression.rs @@ -21,9 +21,12 @@ fn rust_sources_under(dir: &Path) -> Vec { #[test] fn tui_runtime_source_does_not_depend_on_manager_escape_hatches() { - let src_dir = codex_utils_cargo_bin::find_resource!("src") + let src_file = codex_utils_cargo_bin::find_resource!("src/chatwidget.rs") .unwrap_or_else(|err| panic!("failed to resolve src runfile: {err}")); - let sources = rust_sources_under(&src_dir); + let src_dir = src_file + .parent() + .unwrap_or_else(|| panic!("source file has no parent: {}", src_file.display())); + let sources = rust_sources_under(src_dir); let forbidden = [ "AuthManager", "ThreadManager", diff --git a/codex-rs/windows-sandbox-rs/build.rs b/codex-rs/windows-sandbox-rs/build.rs index 768f6e828..3aca5b7e3 100644 --- a/codex-rs/windows-sandbox-rs/build.rs +++ b/codex-rs/windows-sandbox-rs/build.rs @@ -1,4 +1,14 @@ fn main() { + if std::env::var_os("RULES_RUST_BAZEL_BUILD_SCRIPT_RUNNER").is_some() + && matches!(std::env::var("CARGO_CFG_TARGET_ENV").as_deref(), Ok("gnu")) + { + // The Windows Bazel lint/test lane targets `windows-gnullvm`, where + // `winres` can emit a `resource` link directive without a usable + // archive in `OUT_DIR`. Skip embedding the manifest there; Cargo's + // normal MSVC builds still compile it. + return; + } + let mut res = winres::WindowsResource::new(); res.set_manifest_file("codex-windows-sandbox-setup.manifest"); let _ = res.compile(); diff --git a/defs.bzl b/defs.bzl index d23398c8f..a8ffaa77b 100644 --- a/defs.bzl +++ b/defs.bzl @@ -13,15 +13,21 @@ PLATFORMS = [ "windows_arm64", ] -# The Bazel-built windows-gnullvm binaries that pull in V8 need a larger PE -# stack reserve than the default linker setting. Thread the flag through the -# executable and test entry points so the final linked artifacts behave the same -# in normal builds and under `bazel test`. -WINDOWS_GNULLVM_RUSTC_STACK_FLAGS = select({ +# Match Cargo's Windows linker behavior so Bazel-built binaries and tests use +# the same stack reserve on both Windows ABIs and resolve UCRT imports on MSVC. +WINDOWS_RUSTC_LINK_FLAGS = select({ "@rules_rs//rs/experimental/platforms/constraints:windows_gnullvm": [ "-C", "link-arg=-Wl,--stack,8388608", ], + "@rules_rs//rs/experimental/platforms/constraints:windows_msvc": [ + "-C", + "link-arg=/STACK:8388608", + "-C", + "link-arg=/NODEFAULTLIB:libucrt.lib", + "-C", + "link-arg=ucrt.lib", + ], "//conditions:default": [], }) @@ -119,8 +125,11 @@ def codex_rust_crate( rustc_env = {}, deps_extra = [], integration_compile_data_extra = [], + integration_test_args = [], + integration_test_timeout = None, test_data_extra = [], test_tags = [], + unit_test_timeout = None, extra_binaries = []): """Defines a Rust crate with library, binaries, and tests wired for Bazel + Cargo parity. @@ -149,9 +158,14 @@ def codex_rust_crate( deps_extra: Extra normal deps beyond @crates resolution. Typically only needed when features add additional deps. integration_compile_data_extra: Extra compile_data for integration tests. + integration_test_args: Optional args for integration test binaries. + integration_test_timeout: Optional Bazel timeout for integration test + targets generated from `tests/*.rs`. test_data_extra: Extra runtime data for tests. test_tags: Tags applied to unit + integration test targets. Typically used to disable the sandbox, but see https://bazel.build/reference/be/common-definitions#common.tags + unit_test_timeout: Optional Bazel timeout for the unit-test target + generated from `src/**/*.rs`. extra_binaries: Additional binary labels to surface as test data and `CARGO_BIN_EXE_*` environment variables. These are only needed for binaries from a different crate. """ @@ -232,7 +246,7 @@ def codex_rust_crate( # `../codex-rs//...` paths for `file!()`. Strip either # prefix so the workspace-root launcher sees Cargo-like metadata # such as `tui/src/...`. - rustc_flags = rustc_flags_extra + WINDOWS_GNULLVM_RUSTC_STACK_FLAGS + [ + rustc_flags = rustc_flags_extra + WINDOWS_RUSTC_LINK_FLAGS + [ "--remap-path-prefix=../codex-rs=", "--remap-path-prefix=codex-rs=", ], @@ -241,12 +255,17 @@ def codex_rust_crate( tags = test_tags + ["manual"], ) + unit_test_kwargs = {} + if unit_test_timeout: + unit_test_kwargs["timeout"] = unit_test_timeout + workspace_root_test( name = name + "-unit-tests", env = test_env, test_bin = ":" + unit_test_binary, workspace_root_marker = "//codex-rs/utils/cargo-bin:repo_root.marker", tags = test_tags, + **unit_test_kwargs ) maybe_deps += [name] @@ -264,7 +283,7 @@ def codex_rust_crate( crate_root = main, deps = all_crate_deps() + maybe_deps + deps_extra, edition = crate_edition, - rustc_flags = rustc_flags_extra + WINDOWS_GNULLVM_RUSTC_STACK_FLAGS, + rustc_flags = rustc_flags_extra + WINDOWS_RUSTC_LINK_FLAGS, srcs = native.glob(["src/**/*.rs"]), visibility = ["//visibility:public"], ) @@ -274,6 +293,12 @@ def codex_rust_crate( binary = Label(binary_label).name cargo_env["CARGO_BIN_EXE_" + binary] = "$(rlocationpath %s)" % binary_label + integration_test_kwargs = {} + if integration_test_args: + integration_test_kwargs["args"] = integration_test_args + if integration_test_timeout: + integration_test_kwargs["timeout"] = integration_test_timeout + for test in native.glob(["tests/*.rs"], allow_empty = True): test_file_stem = test.removeprefix("tests/").removesuffix(".rs") test_crate_name = test_file_stem.replace("-", "_") @@ -292,7 +317,7 @@ def codex_rust_crate( # Bazel has emitted both `codex-rs//...` and # `../codex-rs//...` paths for `file!()`. Strip either # prefix so Insta records Cargo-like metadata such as `core/tests/...`. - rustc_flags = rustc_flags_extra + WINDOWS_GNULLVM_RUSTC_STACK_FLAGS + [ + rustc_flags = rustc_flags_extra + WINDOWS_RUSTC_LINK_FLAGS + [ "--remap-path-prefix=../codex-rs=", "--remap-path-prefix=codex-rs=", ], @@ -302,4 +327,5 @@ def codex_rust_crate( # execute from the repo root and can misplace integration snapshots. env = cargo_env, tags = test_tags, + **integration_test_kwargs ) diff --git a/patches/BUILD.bazel b/patches/BUILD.bazel index b6e96df52..75d6be358 100644 --- a/patches/BUILD.bazel +++ b/patches/BUILD.bazel @@ -5,15 +5,20 @@ exports_files([ "aws-lc-sys_windows_msvc_memcmp_probe.patch", "llvm_windows_symlink_extract.patch", "rules_rust_windows_bootstrap_process_wrapper_linker.patch", + "rules_rust_windows_build_script_runner_paths.patch", "rules_rust_windows_exec_bin_target.patch", "rules_rust_windows_exec_std.patch", + "rules_rust_windows_process_wrapper_skip_temp_outputs.patch", "rules_rust_repository_set_exec_constraints.patch", "rules_rust_windows_msvc_direct_link_args.patch", "rules_rust_windows_gnullvm_build_script.patch", "rules_rs_windows_gnullvm_exec.patch", + "rules_rs_windows_exec_linker.patch", "rusty_v8_prebuilt_out_dir.patch", + "ring_windows_msvc_include_dirs.patch", "v8_bazel_rules.patch", "v8_module_deps.patch", "v8_source_portability.patch", "windows-link.patch", + "zstd-sys_windows_msvc_include_dirs.patch", ]) diff --git a/patches/aws-lc-sys_windows_msvc_prebuilt_nasm.patch b/patches/aws-lc-sys_windows_msvc_prebuilt_nasm.patch index 37f334b8b..76faca025 100644 --- a/patches/aws-lc-sys_windows_msvc_prebuilt_nasm.patch +++ b/patches/aws-lc-sys_windows_msvc_prebuilt_nasm.patch @@ -1,24 +1,98 @@ -diff --git a/builder/main.rs b/builder/main.rs ---- a/builder/main.rs -+++ b/builder/main.rs -@@ -721,16 +721,29 @@ - fn get_crate_cflags() -> Option { - optional_env_optional_crate_target("TARGET_CFLAGS") - .or(optional_env_optional_crate_target("CFLAGS")) +diff --git a/builder/cc_builder.rs b/builder/cc_builder.rs +index 95cacb0..d5d814b 100644 +--- a/builder/cc_builder.rs ++++ b/builder/cc_builder.rs +@@ -20,9 +20,10 @@ mod win_x86_64; + use crate::nasm_builder::NasmBuilder; + use crate::{ + cargo_env, disable_jitter_entropy, emit_warning, env_name_for_target, env_var_to_bool, +- execute_command, get_crate_cc, get_crate_cflags, get_crate_cxx, is_no_asm, out_dir, +- requested_c_std, set_env_for_target, target, target_arch, target_env, target_os, target_vendor, +- test_clang_cl_command, CStdRequested, EnvGuard, OutputLibType, ++ execute_command, get_crate_cc, get_crate_cflags, get_crate_cxx, ++ is_bazel_windows_msvc_build_script, is_no_asm, out_dir, requested_c_std, set_env_for_target, ++ target, target_arch, target_env, target_os, target_vendor, test_clang_cl_command, ++ CStdRequested, EnvGuard, OutputLibType, + }; + use std::cell::Cell; + use std::collections::HashMap; +@@ -769,6 +770,30 @@ impl CcBuilder { + } + } + ++fn configure_windows_msvc_clang_cl() { ++ let should_use_clang_cl = target_os() == "windows" ++ && target_env() == "msvc" ++ && (target_arch() == "aarch64" || is_bazel_windows_msvc_build_script()); ++ if !should_use_clang_cl { ++ return; ++ } ++ ++ let clang_cl = if test_clang_cl_command() { ++ Some(String::from("clang-cl")) ++ } else { ++ let system_clang_cl = PathBuf::from(r"C:\Program Files\LLVM\bin\clang-cl.exe"); ++ system_clang_cl.is_file().then(|| system_clang_cl.display().to_string()) ++ }; ++ if let Some(clang_cl) = clang_cl { ++ if get_crate_cc().is_none() { ++ set_env_for_target("CC", &clang_cl); ++ } ++ if get_crate_cxx().is_none() { ++ set_env_for_target("CXX", &clang_cl); ++ } ++ } +} + -+fn is_bazel_windows_msvc_build_script() -> bool { + impl crate::Builder for CcBuilder { + fn check_dependencies(&self) -> Result<(), String> { + if OutputLibType::Dynamic == self.output_lib_type { +@@ -784,18 +809,12 @@ impl crate::Builder for CcBuilder { + return Err("cc_builder for libssl not supported".to_string()); + } + ++ configure_windows_msvc_clang_cl(); + Ok(()) + } + + fn build(&self) -> Result<(), String> { +- if target_os() == "windows" +- && target_arch() == "aarch64" +- && target_env() == "msvc" +- && get_crate_cc().is_none() +- && test_clang_cl_command() +- { +- set_env_for_target("CC", "clang-cl"); +- } ++ configure_windows_msvc_clang_cl(); + + println!("cargo:root={}", self.out_dir.display()); + let sources = crate::cc_builder::identify_sources(); + +diff --git a/builder/main.rs b/builder/main.rs +index 51a9bc1..e714ba4 100644 +--- a/builder/main.rs ++++ b/builder/main.rs +@@ -723,14 +723,31 @@ fn get_crate_cflags() -> Option { + .or(optional_env_optional_crate_target("CFLAGS")) + } + ++pub(crate) fn is_bazel_windows_msvc_build_script() -> bool { + if !target().ends_with("windows-msvc") { + return false; + } + ++ if optional_env("RULES_RUST_BAZEL_BUILD_SCRIPT_RUNNER").is_some() { ++ return true; ++ } ++ + let cargo_manifest_dir = cargo_env("CARGO_MANIFEST_DIR"); + let manifest_dir = Path::new(&cargo_manifest_dir); + manifest_dir + .components() + .any(|component| component.as_os_str() == "bazel-out") - } - ++} ++ fn use_prebuilt_nasm() -> bool { + let use_prebuilt_for_bazel_windows_msvc = is_bazel_windows_msvc_build_script(); target_os() == "windows" @@ -32,12 +106,27 @@ diff --git a/builder/main.rs b/builder/main.rs && (Some(true) == allow_prebuilt_nasm() || is_prebuilt_nasm()) } - fn allow_prebuilt_nasm() -> Option { +@@ -817,8 +834,12 @@ fn main() { + initialize(); + prepare_cargo_cfg(); + +- let manifest_dir = current_dir(); +- let manifest_dir = dunce::canonicalize(Path::new(&manifest_dir)).unwrap(); ++ let manifest_dir = if is_bazel_windows_msvc_build_script() { ++ PathBuf::from(cargo_env("CARGO_MANIFEST_DIR")) ++ } else { ++ let manifest_dir = current_dir(); ++ dunce::canonicalize(Path::new(&manifest_dir)).unwrap() ++ }; + let prefix_str = prefix_string(); + let prefix = if is_no_prefix() { + None + diff --git a/builder/nasm_builder.rs b/builder/nasm_builder.rs +index cf1f5c8..f683274 100644 --- a/builder/nasm_builder.rs +++ b/builder/nasm_builder.rs -@@ -57,7 +57,7 @@ - if self.files.is_empty() { +@@ -57,7 +57,7 @@ impl NasmBuilder { return vec![]; } diff --git a/patches/ring_windows_msvc_include_dirs.patch b/patches/ring_windows_msvc_include_dirs.patch new file mode 100644 index 000000000..682252011 --- /dev/null +++ b/patches/ring_windows_msvc_include_dirs.patch @@ -0,0 +1,100 @@ +diff --git a/build.rs b/build.rs +index 9843ad8aa..573075489 100644 +--- a/build.rs ++++ b/build.rs +@@ -346,7 +346,29 @@ fn ring_build_rs_main(c_root_dir: &Path, core_name_and_version: &str) { + // we want to optimize for minimizing the build tools required: No Perl, + // no nasm, etc. + let generated_dir = if !is_git { +- c_root_dir.join(PREGENERATED) ++ let pregenerated_dir = c_root_dir.join(PREGENERATED); ++ if target.os == WINDOWS ++ && target.env == "msvc" ++ && env::var_os("RULES_RUST_BAZEL_BUILD_SCRIPT_RUNNER").is_some() ++ { ++ let mut pending = vec![(pregenerated_dir.clone(), out_dir.clone())]; ++ while let Some((src_dir, dst_dir)) = pending.pop() { ++ fs::create_dir_all(&dst_dir).unwrap(); ++ for entry in fs::read_dir(&src_dir).unwrap() { ++ let entry = entry.unwrap(); ++ let src_path = entry.path(); ++ let dst_path = dst_dir.join(entry.file_name()); ++ if entry.file_type().unwrap().is_dir() { ++ pending.push((src_path, dst_path)); ++ } else { ++ fs::copy(&src_path, &dst_path).unwrap(); ++ } ++ } ++ } ++ out_dir.clone() ++ } else { ++ pregenerated_dir ++ } + } else { + generate_sources_and_preassemble( + &out_dir, +@@ -569,6 +591,15 @@ fn configure_cc(c: &mut cc::Build, target: &Target, c_root_dir: &Path, include_d + + let _ = c.include(c_root_dir.join("include")); + let _ = c.include(include_dir); ++ let _ = c.include(c_root_dir.join("third_party").join("fiat")); ++ if compiler.is_like_msvc() { ++ let _ = c.include(c_root_dir.join("crypto").join("curve25519")); ++ let _ = c.include(c_root_dir.join("crypto").join("limbs")); ++ let _ = c.include(c_root_dir.join("crypto").join("fipsmodule").join("aes")); ++ let _ = c.include(c_root_dir.join("crypto").join("fipsmodule").join("bn")); ++ let _ = c.include(c_root_dir.join("crypto").join("fipsmodule").join("ec")); ++ let _ = c.include(c_root_dir.join("crypto").join("poly1305")); ++ } + for f in cpp_flags(&compiler) { + let _ = c.flag(f); + } +diff --git a/crypto/curve25519/curve25519.c b/crypto/curve25519/curve25519.c +index 99d7d7fbb..2f69ad560 100644 +--- a/crypto/curve25519/curve25519.c ++++ b/crypto/curve25519/curve25519.c +@@ -47,11 +47,11 @@ + #if defined(__GNUC__) + #pragma GCC diagnostic ignored "-Wpedantic" + #endif +-#include "../../third_party/fiat/curve25519_64.h" ++#include "curve25519_64.h" + #elif defined(OPENSSL_64_BIT) +-#include "../../third_party/fiat/curve25519_64_msvc.h" ++#include "curve25519_64_msvc.h" + #else +-#include "../../third_party/fiat/curve25519_32.h" ++#include "curve25519_32.h" + #endif + + +diff --git a/crypto/curve25519/curve25519_64_adx.c b/crypto/curve25519/curve25519_64_adx.c +index 88964a9dd..b660f55f4 100644 +--- a/crypto/curve25519/curve25519_64_adx.c ++++ b/crypto/curve25519/curve25519_64_adx.c +@@ -19,5 +19,5 @@ + #pragma GCC diagnostic ignored "-Wpedantic" + #pragma GCC diagnostic ignored "-Wsign-conversion" + +-#include "../../third_party/fiat/curve25519_64_adx.h" ++#include "curve25519_64_adx.h" + #endif +diff --git a/crypto/fipsmodule/ec/p256.c b/crypto/fipsmodule/ec/p256.c +index 0117916da..4224d1192 100644 +--- a/crypto/fipsmodule/ec/p256.c ++++ b/crypto/fipsmodule/ec/p256.c +@@ -50,11 +50,11 @@ + #if defined(__GNUC__) + #pragma GCC diagnostic ignored "-Wpedantic" + #endif +-#include "../../../third_party/fiat/p256_64.h" ++#include "p256_64.h" + #elif defined(OPENSSL_64_BIT) +-#include "../../../third_party/fiat/p256_64_msvc.h" ++#include "p256_64_msvc.h" + #else +-#include "../../../third_party/fiat/p256_32.h" ++#include "p256_32.h" + #endif + + diff --git a/patches/rules_rs_windows_exec_linker.patch b/patches/rules_rs_windows_exec_linker.patch new file mode 100644 index 000000000..25892de83 --- /dev/null +++ b/patches/rules_rs_windows_exec_linker.patch @@ -0,0 +1,73 @@ +# What: use a working Windows direct linker for `rules_rs` exec toolchains and +# preserve the Windows stdlib link flags the stable wrapper was dropping. +# Scope: Windows-only linker metadata for the generated `rules_rs` toolchains. + +diff --git a/rs/experimental/toolchains/declare_rustc_toolchains.bzl b/rs/experimental/toolchains/declare_rustc_toolchains.bzl +index 67e491c..3f1cff5 100644 +--- a/rs/experimental/toolchains/declare_rustc_toolchains.bzl ++++ b/rs/experimental/toolchains/declare_rustc_toolchains.bzl +@@ -50,6 +50,8 @@ def declare_rustc_toolchains( + rust_toolchain( + name = rust_toolchain_name, + rust_doc = "{}rustdoc".format(rustc_repo_label), ++ linker = "{}rust-lld".format(rustc_repo_label) if exec_triple.system == "windows" else None, ++ linker_type = "direct" if exec_triple.system == "windows" else None, + rust_std = select(rust_std_select), + rustc = "{}rustc".format(rustc_repo_label), + cargo = "{}cargo".format(cargo_repo_label), +@@ -82,7 +84,20 @@ def declare_rustc_toolchains( + stdlib_linkflags = select({ + "@platforms//os:freebsd": ["-lexecinfo", "-lpthread"], + "@platforms//os:macos": ["-lSystem", "-lresolv"], +- # TODO: windows ++ "@rules_rs//rs/experimental/platforms/constraints:windows_gnullvm": [ ++ "advapi32.lib", ++ "ws2_32.lib", ++ "userenv.lib", ++ "Bcrypt.lib", ++ ], ++ "@rules_rs//rs/experimental/platforms/constraints:windows_msvc": [ ++ "advapi32.lib", ++ "ws2_32.lib", ++ "userenv.lib", ++ "Bcrypt.lib", ++ "ucrt.lib", ++ ], ++ # TODO: other platforms + "//conditions:default": [], + }), + default_edition = edition, +diff --git a/rs/private/rustc_repository.bzl b/rs/private/rustc_repository.bzl +index f4f0286..6558bb2 100644 +--- a/rs/private/rustc_repository.bzl ++++ b/rs/private/rustc_repository.bzl +@@ -1,13 +1,28 @@ + load("@rules_rust//rust/platform:triple.bzl", "triple") + load( + "@rules_rust//rust/private:repository_utils.bzl", + "BUILD_for_compiler", + ) + load(":rust_repository_utils.bzl", "download_and_extract", "RUST_REPOSITORY_COMMON_ATTR") + ++_WINDOWS_EXEC_LINKER_BUILD = """ ++filegroup( ++ name = "rust-lld", ++ srcs = ["bin/lld-link.exe"], ++ visibility = ["//visibility:public"], ++) ++""" ++ + def _rustc_repository_impl(rctx): + exec_triple = triple(rctx.attr.triple) + download_and_extract(rctx, "rustc", "rustc", exec_triple) +- rctx.file("BUILD.bazel", BUILD_for_compiler(exec_triple)) ++ build_file = BUILD_for_compiler(exec_triple) ++ if exec_triple.system == "windows": ++ lld_link = rctx.which("lld-link.exe") ++ if lld_link == None: ++ fail("lld-link.exe not found on PATH") ++ rctx.symlink(lld_link, "bin/lld-link.exe") ++ build_file += _WINDOWS_EXEC_LINKER_BUILD ++ rctx.file("BUILD.bazel", build_file) + + return rctx.repo_metadata(reproducible = True) diff --git a/patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch b/patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch index 9a978b8be..842098bb3 100644 --- a/patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch +++ b/patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch @@ -1,23 +1,21 @@ --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl -@@ -472,7 +472,19 @@ +@@ -472,7 +472,17 @@ ) ld_is_direct_driver = False - if not ld or toolchain.linker_preference == "rust": -+ # The bootstrap process wrapper is built without the normal rules_rust -+ # process wrapper. On Windows nightly toolchains that expose rust-lld, the -+ # C++ toolchain path currently resolves to clang++ while still emitting -+ # MSVC-style arguments, so prefer rust-lld for this one bootstrap binary -+ # instead of switching all Rust actions over. -+ use_bootstrap_rust_linker = ( ++ # Windows MSVC Rust targets can inherit a GNU-flavored C++ linker path ++ # (`clang++`) alongside MSVC-style arguments. Prefer the toolchain linker ++ # there so both exec helpers and ordinary MSVC Rust targets link through ++ # the Windows direct linker instead. ++ use_windows_rust_linker = ( + toolchain.target_os.startswith("windows") and -+ toolchain.linker != None and -+ hasattr(ctx.executable, "_bootstrap_process_wrapper") and -+ not ctx.executable._process_wrapper ++ toolchain.target_abi == "msvc" and ++ toolchain.linker != None + ) + -+ if not ld or toolchain.linker_preference == "rust" or use_bootstrap_rust_linker: ++ if not ld or toolchain.linker_preference == "rust" or use_windows_rust_linker: ld = toolchain.linker.path ld_is_direct_driver = toolchain.linker_type == "direct" diff --git a/patches/rules_rust_windows_build_script_runner_paths.patch b/patches/rules_rust_windows_build_script_runner_paths.patch new file mode 100644 index 000000000..ace5959d5 --- /dev/null +++ b/patches/rules_rust_windows_build_script_runner_paths.patch @@ -0,0 +1,171 @@ +--- a/cargo/private/cargo_build_script_runner/bin.rs ++++ b/cargo/private/cargo_build_script_runner/bin.rs +@@ -24,6 +24,85 @@ + use cargo_build_script_runner::cargo_manifest_dir::{remove_symlink, symlink, RunfilesMaker}; + use cargo_build_script_runner::{BuildScriptOutput, CompileAndLinkFlags}; + ++#[cfg(windows)] ++fn normalize_windows_relative_path(path: &str) -> String { ++ path.replace('/', "\\") ++} ++ ++#[cfg(not(windows))] ++fn normalize_windows_relative_path(path: &str) -> String { ++ path.to_owned() ++} ++ ++fn exec_root_join(exec_root: &Path, relative: &str) -> PathBuf { ++ exec_root.join(normalize_windows_relative_path(relative)) ++} ++ ++#[cfg(windows)] ++#[link(name = "Kernel32")] ++unsafe extern "system" { ++ fn GetShortPathNameW( ++ lpszLongPath: *const u16, ++ lpszShortPath: *mut u16, ++ cchBuffer: u32, ++ ) -> u32; ++} ++ ++#[cfg(windows)] ++fn windows_extended_length_path(path: &Path) -> PathBuf { ++ let path = path.as_os_str().to_string_lossy(); ++ if path.starts_with(r"\\?\") { ++ PathBuf::from(path.to_string()) ++ } else if let Some(stripped) = path.strip_prefix(r"\\") { ++ PathBuf::from(format!(r"\\?\UNC\{stripped}")) ++ } else { ++ PathBuf::from(format!(r"\\?\{path}")) ++ } ++} ++ ++#[cfg(windows)] ++fn shorten_windows_path(path: &Path) -> PathBuf { ++ use std::os::windows::ffi::OsStrExt; ++ ++ let long_path = windows_extended_length_path(path); ++ let long_path = long_path ++ .as_os_str() ++ .encode_wide() ++ .chain(Some(0)) ++ .collect::>(); ++ ++ unsafe { ++ let required = GetShortPathNameW(long_path.as_ptr(), std::ptr::null_mut(), 0); ++ if required == 0 { ++ return path.to_owned(); ++ } ++ ++ let mut short_path = vec![0u16; required as usize]; ++ let written = GetShortPathNameW(long_path.as_ptr(), short_path.as_mut_ptr(), required); ++ if written == 0 { ++ path.to_owned() ++ } else { ++ let short_path = PathBuf::from( ++ ::from_wide( ++ &short_path[..written as usize], ++ ), ++ ); ++ PathBuf::from( ++ short_path ++ .as_os_str() ++ .to_string_lossy() ++ .trim_start_matches(r"\\?\") ++ .to_string(), ++ ) ++ } ++ } ++} ++ ++#[cfg(not(windows))] ++fn shorten_windows_path(path: &Path) -> PathBuf { ++ path.to_owned() ++} ++ + fn run_buildrs() -> Result<(), String> { + // We use exec_root.join rather than std::fs::canonicalize, to avoid resolving symlinks, as + // some execution strategies and remote execution environments may use symlinks in ways which +@@ -31,10 +110,11 @@ fn run_buildrs() -> Result<(), String> { + // directory - resolving these may cause tools which inspect $0, or try to resolve files + // relative to themselves, to fail. + let exec_root = env::current_dir().expect("Failed to get current directory"); +- let manifest_dir_env = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR was not set"); +- let rustc_env = env::var("RUSTC").expect("RUSTC was not set"); +- let manifest_dir = exec_root.join(manifest_dir_env); +- let rustc = exec_root.join(&rustc_env); ++ let manifest_dir_env = ++ normalize_windows_relative_path(&env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR was not set")); ++ let rustc_env = normalize_windows_relative_path(&env::var("RUSTC").expect("RUSTC was not set")); ++ let manifest_dir = exec_root_join(&exec_root, &manifest_dir_env); ++ let rustc = shorten_windows_path(&exec_root_join(&exec_root, &rustc_env)); + let Args { + progname, + crate_links, +@@ -55,7 +135,8 @@ fn run_buildrs() -> Result<(), String> { + cargo_manifest_maker.create_runfiles_dir().unwrap() + } + +- let out_dir_abs = exec_root.join(out_dir); ++ let out_dir_abs = shorten_windows_path(&exec_root_join(&exec_root, &out_dir)); + // For some reason Google's RBE does not create the output directory, force create it. + create_dir_all(&out_dir_abs) + .unwrap_or_else(|_| panic!("Failed to make output directory: {:?}", out_dir_abs)); +@@ -89,11 +170,12 @@ fn run_buildrs() -> Result<(), String> { + + let working_directory = resolve_rundir(&rundir, &exec_root, &manifest_dir)?; + +- let mut command = Command::new(exec_root.join(progname)); ++ let mut command = Command::new(exec_root_join(&exec_root, &progname)); + command +- .current_dir(&working_directory) ++ .current_dir(shorten_windows_path(&working_directory)) + .envs(target_env_vars) + .env("OUT_DIR", &out_dir_abs) ++ .env("RULES_RUST_BAZEL_BUILD_SCRIPT_RUNNER", "1") + .env("CARGO_MANIFEST_DIR", manifest_dir) + .env("RUSTC", rustc) + .env("RUST_BACKTRACE", "full"); +@@ -123,7 +205,7 @@ fn run_buildrs() -> Result<(), String> { + + for tool_env_var in &["CC", "CXX", "LD"] { + if let Some(tool_path) = env::var_os(tool_env_var) { +- command.env(tool_env_var, exec_root.join(tool_path)); ++ command.env(tool_env_var, exec_root_join(&exec_root, &tool_path.to_string_lossy())); + } + } + +@@ -139,7 +221,7 @@ fn run_buildrs() -> Result<(), String> { + command.env_remove("AR"); + command.env_remove("ARFLAGS"); + } else { +- command.env("AR", exec_root.join(ar_path)); ++ command.env("AR", exec_root_join(&exec_root, &ar_path.to_string_lossy())); + } + } + +@@ -257,7 +339,8 @@ fn resolve_rundir(rundir: &str, exec_root: &Path, manifest_dir: &Path) -> Result + if rundir.is_empty() { + return Ok(manifest_dir.to_owned()); + } +- let rundir_path = Path::new(rundir); ++ let rundir = normalize_windows_relative_path(rundir); ++ let rundir_path = Path::new(&rundir); + if rundir_path.is_absolute() { + return Err(format!("rundir must be empty (to run in manifest path) or relative path (relative to exec root), but was {:?}", rundir)); + } +diff --git a/cargo/private/cargo_build_script_runner/cargo_manifest_dir.rs b/cargo/private/cargo_build_script_runner/cargo_manifest_dir.rs +--- a/cargo/private/cargo_build_script_runner/cargo_manifest_dir.rs ++++ b/cargo/private/cargo_build_script_runner/cargo_manifest_dir.rs +@@ -282,7 +282,7 @@ + /// been copied into the runfiles directory. + fn drain_runfiles_dir_windows(&self) -> Result<(), String> { + for dest in self.runfiles.values() { +- if !self ++ if self + .filename_suffixes_to_retain + .iter() + .any(|suffix| dest.ends_with(suffix)) + { + continue; + } diff --git a/patches/rules_rust_windows_exec_msvc_build_script_env.patch b/patches/rules_rust_windows_exec_msvc_build_script_env.patch index c78dba43c..14e114f46 100644 --- a/patches/rules_rust_windows_exec_msvc_build_script_env.patch +++ b/patches/rules_rust_windows_exec_msvc_build_script_env.patch @@ -1,62 +1,39 @@ diff --git a/cargo/private/cargo_build_script.bzl b/cargo/private/cargo_build_script.bzl --- a/cargo/private/cargo_build_script.bzl +++ b/cargo/private/cargo_build_script.bzl -@@ -142,40 +142,82 @@ def _strip_stack_protector_for_windows_llvm_mingw(toolchain, args): - def _rewrite_windows_exec_msvc_cc_args(toolchain, args): - """Translate GNU-flavored cc args when exec-side build scripts target Windows MSVC.""" +@@ -144,9 +144,14 @@ def _rewrite_windows_exec_msvc_cc_args(toolchain, args): if toolchain.target_flag_value != toolchain.exec_triple.str or not toolchain.exec_triple.str.endswith("-pc-windows-msvc"): return args - rewritten = [] -- skip_next = False -- for arg in args: -- if skip_next: -- skip_next = False -- continue + rewritten = [ + "-target", + toolchain.target_flag_value, + ] -+ skip_next = False + skip_next = False +- for arg in args: + for index in range(len(args)): + arg = args[index] + -+ if skip_next: -+ skip_next = False -+ continue - - if arg == "-target": -- skip_next = True -+ skip_next = True + if skip_next: + skip_next = False continue - - if arg.startswith("-target=") or arg.startswith("--target="): - continue - +@@ -161,21 +166,58 @@ def _rewrite_windows_exec_msvc_cc_args(toolchain, args): if arg == "-nostdlibinc" or arg.startswith("--sysroot"): continue - if "mingw-w64-" in arg or "mingw_import_libraries_directory" in arg or "mingw_crt_library_search_directory" in arg: + if arg.startswith("-fstack-protector") or arg.startswith("-D_FORTIFY_SOURCE="): - continue - -- if arg.startswith("-fstack-protector"): -- continue -- -- if arg.startswith("-D_FORTIFY_SOURCE="): -- continue ++ continue ++ + if arg == "-isystem" and index + 1 < len(args): + path = args[index + 1] + if "mingw-w64-" in path or "mingw_import_libraries_directory" in path or "mingw_crt_library_search_directory" in path: + skip_next = True + continue - - rewritten.append(arg) - -- return [ -- "-target", -- toolchain.target_flag_value, -- ] + rewritten ++ ++ rewritten.append(arg) ++ + return rewritten + +def _rewrite_windows_exec_msvc_link_args(toolchain, args): @@ -78,8 +55,9 @@ diff --git a/cargo/private/cargo_build_script.bzl b/cargo/private/cargo_build_sc + continue + + if arg.startswith("--sysroot="): -+ continue -+ + continue + +- if arg.startswith("-fstack-protector"): + if arg == "-L" and index + 1 < len(args): + path = args[index + 1] + if "mingw_import_libraries_directory" in path or "mingw_crt_library_search_directory" in path: @@ -87,25 +65,120 @@ diff --git a/cargo/private/cargo_build_script.bzl b/cargo/private/cargo_build_sc + continue + rewritten.extend([arg, path]) + skip_next = True -+ continue -+ + continue + +- if arg.startswith("-D_FORTIFY_SOURCE="): + if arg.startswith("-L") and ( + "mingw_import_libraries_directory" in arg or + "mingw_crt_library_search_directory" in arg + ): -+ continue -+ -+ rewritten.append(arg) -+ + continue + + rewritten.append(arg) + +- return [ +- "-target", +- toolchain.target_flag_value, +- ] + rewritten + return rewritten def get_cc_compile_args_and_env(cc_toolchain, feature_configuration): """Gather cc environment variables from the given `cc_toolchain` -@@ -509,6 +550,7 @@ def _construct_build_script_env( +@@ -508,15 +550,23 @@ def _cargo_build_script_impl(ctx): + cc_toolchain, feature_configuration = find_cc_toolchain(ctx) linker, _, link_args, linker_env = get_linker_and_args(ctx, "bin", toolchain, cc_toolchain, feature_configuration, None) env.update(**linker_env) - env["LD"] = linker -+ link_args = _rewrite_windows_exec_msvc_link_args(toolchain, link_args) - env["LDFLAGS"] = " ".join(_pwd_flags(link_args)) +- env["LD"] = linker +- env["LDFLAGS"] = " ".join(_pwd_flags(link_args)) ++ use_windows_exec_msvc_path_tools = ( ++ toolchain.target_flag_value == toolchain.exec_triple.str and ++ toolchain.exec_triple.str.endswith("-pc-windows-msvc") ++ ) ++ ++ if not use_windows_exec_msvc_path_tools: ++ env["LD"] = linker ++ link_args = _rewrite_windows_exec_msvc_link_args(toolchain, link_args) ++ env["LDFLAGS"] = " ".join(_pwd_flags(link_args)) ++ ++ # Defaults for cxx flags. ++ env["CFLAGS"] = "" ++ env["CXXFLAGS"] = "" - # Defaults for cxx flags. +- # Defaults for cxx flags. + env["ARFLAGS"] = "" +- env["CFLAGS"] = "" +- env["CXXFLAGS"] = "" + fallback_tools = [] +- if not cc_toolchain: ++ if not cc_toolchain and not use_windows_exec_msvc_path_tools: + fallbacks = { + "AR": "_fallback_ar", + "CC": "_fallback_cc", +@@ -542,36 +592,37 @@ def _cargo_build_script_impl(ctx): + + toolchain_tools.append(cc_toolchain.all_files) + +- env["CC"] = cc_common.get_tool_for_action( +- feature_configuration = feature_configuration, +- action_name = ACTION_NAMES.c_compile, +- ) +- env["CXX"] = cc_common.get_tool_for_action( +- feature_configuration = feature_configuration, +- action_name = ACTION_NAMES.cpp_compile, +- ) +- env["AR"] = cc_common.get_tool_for_action( +- feature_configuration = feature_configuration, +- action_name = ACTION_NAMES.cpp_link_static_library, +- ) +- +- # Many C/C++ toolchains are missing an action_config for AR because +- # one was never included in the unix_cc_toolchain_config. +- if not env["AR"]: +- env["AR"] = cc_toolchain.ar_executable +- +- cc_c_args = _strip_stack_protector_for_windows_llvm_mingw(toolchain, cc_c_args) +- cc_cxx_args = _strip_stack_protector_for_windows_llvm_mingw(toolchain, cc_cxx_args) +- cc_c_args = _rewrite_windows_exec_msvc_cc_args(toolchain, cc_c_args) +- cc_cxx_args = _rewrite_windows_exec_msvc_cc_args(toolchain, cc_cxx_args) +- # Populate CFLAGS and CXXFLAGS that cc-rs relies on when building from source, in particular +- # to determine the deployment target when building for apple platforms (`macosx-version-min` +- # for example, itself derived from the `macos_minimum_os` Bazel argument). +- env["CFLAGS"] = " ".join(_pwd_flags(cc_c_args)) +- env["CXXFLAGS"] = " ".join(_pwd_flags(cc_cxx_args)) +- # It may be tempting to forward ARFLAGS, but cc-rs is opinionated enough +- # that doing so is more likely to hurt than help. If you need to change +- # ARFLAGS, make changes to cc-rs. ++ if not use_windows_exec_msvc_path_tools: ++ env["CC"] = cc_common.get_tool_for_action( ++ feature_configuration = feature_configuration, ++ action_name = ACTION_NAMES.c_compile, ++ ) ++ env["CXX"] = cc_common.get_tool_for_action( ++ feature_configuration = feature_configuration, ++ action_name = ACTION_NAMES.cpp_compile, ++ ) ++ env["AR"] = cc_common.get_tool_for_action( ++ feature_configuration = feature_configuration, ++ action_name = ACTION_NAMES.cpp_link_static_library, ++ ) ++ ++ # Many C/C++ toolchains are missing an action_config for AR because ++ # one was never included in the unix_cc_toolchain_config. ++ if not env["AR"]: ++ env["AR"] = cc_toolchain.ar_executable ++ ++ cc_c_args = _strip_stack_protector_for_windows_llvm_mingw(toolchain, cc_c_args) ++ cc_cxx_args = _strip_stack_protector_for_windows_llvm_mingw(toolchain, cc_cxx_args) ++ cc_c_args = _rewrite_windows_exec_msvc_cc_args(toolchain, cc_c_args) ++ cc_cxx_args = _rewrite_windows_exec_msvc_cc_args(toolchain, cc_cxx_args) ++ # Populate CFLAGS and CXXFLAGS that cc-rs relies on when building from source, in particular ++ # to determine the deployment target when building for apple platforms (`macosx-version-min` ++ # for example, itself derived from the `macos_minimum_os` Bazel argument). ++ env["CFLAGS"] = " ".join(_pwd_flags(cc_c_args)) ++ env["CXXFLAGS"] = " ".join(_pwd_flags(cc_cxx_args)) ++ # It may be tempting to forward ARFLAGS, but cc-rs is opinionated enough ++ # that doing so is more likely to hurt than help. If you need to change ++ # ARFLAGS, make changes to cc-rs. + + # Inform build scripts of rustc flags + # https://github.com/rust-lang/cargo/issues/9600 diff --git a/patches/rules_rust_windows_msvc_direct_link_args.patch b/patches/rules_rust_windows_msvc_direct_link_args.patch index 2f04f8ca8..05aef785d 100644 --- a/patches/rules_rust_windows_msvc_direct_link_args.patch +++ b/patches/rules_rust_windows_msvc_direct_link_args.patch @@ -1,6 +1,32 @@ --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl -@@ -2305,7 +2305,7 @@ +@@ -501,11 +501,41 @@ + filtered_args.append(version) + # Keep library search path flags + ++ elif processed_arg == "-L" and i + 1 < len(link_args): ++ path = link_args[i + 1] ++ if ld_is_direct_driver and toolchain.target_os == "windows": ++ skip_next = True ++ continue ++ filtered_args.extend([processed_arg, path]) ++ skip_next = True ++ + elif processed_arg.startswith("-L"): ++ if ld_is_direct_driver and toolchain.target_os == "windows": ++ continue + filtered_args.append(processed_arg) + # Keep sysroot flags (as single or two-part arguments) + + elif processed_arg == "--sysroot" or processed_arg.startswith("--sysroot="): ++ if ld_is_direct_driver and toolchain.target_os == "windows": ++ if processed_arg == "--sysroot" and i + 1 < len(link_args): ++ skip_next = True ++ continue + filtered_args.append(processed_arg) + if processed_arg == "--sysroot" and i + 1 < len(link_args): + # Two-part argument, keep the next arg too +@@ -2305,7 +2335,7 @@ return crate.metadata.dirname return crate.output.dirname @@ -30,11 +56,17 @@ # Windows toolchains can inherit POSIX defaults like -pthread from C deps, # which fails to link with the MinGW/LLD toolchain. Drop them here. -@@ -2558,17 +2563,25 @@ +@@ -2453,14 +2483,21 @@ else: # For all other crate types we want to link C++ runtime library statically # (for example libstdc++.a or libc++.a). + runtime_libs = cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration) ++ if toolchain.target_os == "windows" and use_direct_link_driver: ++ runtime_libs = depset([ ++ runtime_lib ++ for runtime_lib in runtime_libs.to_list() ++ if runtime_lib.basename.endswith(".lib") ++ ]) args.add_all( - cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration), + runtime_libs, @@ -47,18 +79,11 @@ - map_each = get_lib_name, - format_each = "-lstatic=%s", - ) -+ if toolchain.target_os == "windows" and use_direct_link_driver: -+ for runtime_lib in runtime_libs.to_list(): -+ if runtime_lib.basename.endswith(".lib"): -+ args.add(get_lib_name(runtime_lib), format = "-lstatic=%s") -+ else: -+ args.add(runtime_lib.path, format = "--codegen=link-arg=%s") -+ else: -+ args.add_all( -+ runtime_libs, -+ map_each = get_lib_name, -+ format_each = "-lstatic=%s", -+ ) ++ args.add_all( ++ runtime_libs, ++ map_each = get_lib_name, ++ format_each = "-lstatic=%s", ++ ) def _get_dirname(file): """A helper function for `_add_native_link_flags`. diff --git a/patches/rules_rust_windows_process_wrapper_skip_temp_outputs.patch b/patches/rules_rust_windows_process_wrapper_skip_temp_outputs.patch new file mode 100644 index 000000000..454e9d154 --- /dev/null +++ b/patches/rules_rust_windows_process_wrapper_skip_temp_outputs.patch @@ -0,0 +1,15 @@ +--- a/util/process_wrapper/main.rs ++++ b/util/process_wrapper/main.rs +@@ -213,6 +213,12 @@ fn consolidate_dependency_search_paths( + let file_name_lower = file_name + .to_string_lossy() + .to_ascii_lowercase(); ++ if file_name_lower.contains(".tmp") || file_name_lower.ends_with(".rcgu.o") { ++ // MSVC link actions can leave transient `*.exe.tmp*` and ++ // per-codegen-unit `*.rcgu.o` outputs next to the final binary. ++ // Those are not stable linker search-path inputs. ++ continue; ++ } + if !seen.insert(file_name_lower) { + continue; + } diff --git a/patches/zstd-sys_windows_msvc_include_dirs.patch b/patches/zstd-sys_windows_msvc_include_dirs.patch new file mode 100644 index 000000000..c45a360a4 --- /dev/null +++ b/patches/zstd-sys_windows_msvc_include_dirs.patch @@ -0,0 +1,41 @@ +diff --git a/build.rs b/build.rs +index 912a3bf..e078f0e 100644 +--- a/build.rs ++++ b/build.rs +@@ -85,6 +85,7 @@ fn flag_if_supported_with_fallbacks(config: &mut cc::Build, flags: &[&str]) { + } + + fn compile_zstd() { ++ let target = env::var("TARGET").unwrap_or_default(); + let mut config = cc::Build::new(); + + // Search the following directories for C files to add to the compilation. +@@ -164,6 +165,16 @@ fn compile_zstd() { + // Some extra parameters + config.include("zstd/lib/"); + config.include("zstd/lib/common"); ++ if target.contains("msvc") { ++ config.include("zstd/lib/compress"); ++ config.include("zstd/lib/decompress"); ++ #[cfg(feature = "zdict_builder")] ++ config.include("zstd/lib/dictBuilder"); ++ #[cfg(feature = "legacy")] ++ config.include("zstd/lib/legacy"); ++ #[cfg(feature = "seekable")] ++ config.include("zstd/contrib/seekable_format"); ++ } + config.warnings(false); + + config.define("ZSTD_LIB_DEPRECATED", Some("0")); +@@ -210,7 +221,9 @@ fn compile_zstd() { + + // Hide symbols from resulting library, + // so we can be used with another zstd-linking lib. +- // See https://github.com/gyscos/zstd-rs/issues/58 +- config.flag("-fvisibility=hidden"); ++ // See https://github.com/gyscos/zstd-rs/issues/58. ++ if !target.contains("msvc") { ++ config.flag("-fvisibility=hidden"); ++ } + config.define("XXH_PRIVATE_API", Some("")); + config.define("ZSTDLIB_VISIBILITY", Some(""));