From 3997146eaa41f5a035adcf56e8fef340fb990a4d Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 15:53:45 -0700 Subject: [PATCH] ci: run Windows argument-comment-lint via native Bazel --- .github/actions/setup-bazel-ci/action.yml | 9 +- .../run-argument-comment-lint-bazel.sh | 192 ++++++++++++++++++ .github/scripts/run-bazel-ci.sh | 26 ++- .github/workflows/rust-ci-full.yml | 32 ++- .github/workflows/rust-ci.yml | 32 ++- BUILD.bazel | 9 +- MODULE.bazel | 31 +++ codex-rs/core/src/shell_snapshot_tests.rs | 12 +- codex-rs/linux-sandbox/src/landlock.rs | 32 ++- codex-rs/linux-sandbox/src/proxy_routing.rs | 3 +- patches/BUILD.bazel | 3 + ...rust_repository_set_exec_constraints.patch | 26 +++ ...ows_bootstrap_process_wrapper_linker.patch | 23 +++ ...s_rust_windows_msvc_direct_link_args.patch | 64 ++++++ 14 files changed, 440 insertions(+), 54 deletions(-) create mode 100755 .github/scripts/run-argument-comment-lint-bazel.sh create mode 100644 patches/rules_rust_repository_set_exec_constraints.patch create mode 100644 patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch create mode 100644 patches/rules_rust_windows_msvc_direct_link_args.patch diff --git a/.github/actions/setup-bazel-ci/action.yml b/.github/actions/setup-bazel-ci/action.yml index 34bbd40b19..f7b1ffaa59 100644 --- a/.github/actions/setup-bazel-ci/action.yml +++ b/.github/actions/setup-bazel-ci/action.yml @@ -60,8 +60,15 @@ runs: # Use the shortest available drive to reduce argv/path length issues, # but avoid the drive root because some Windows test launchers mis-handle # MANIFEST paths there. - $bazelOutputUserRoot = if (Test-Path 'D:\') { 'D:\b' } else { 'C:\b' } + $hasDDrive = Test-Path 'D:\' + $bazelOutputUserRoot = if ($hasDDrive) { 'D:\b' } else { 'C:\b' } + $repoContentsCache = Join-Path $env:RUNNER_TEMP "bazel-repo-contents-cache-$env:GITHUB_RUN_ID-$env:GITHUB_JOB" "BAZEL_OUTPUT_USER_ROOT=$bazelOutputUserRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + "BAZEL_REPO_CONTENTS_CACHE=$repoContentsCache" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + if (-not $hasDDrive) { + $repositoryCache = Join-Path $env:USERPROFILE '.cache\bazel-repo-cache' + "BAZEL_REPOSITORY_CACHE=$repositoryCache" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + } - name: Enable Git long paths (Windows) if: runner.os == 'Windows' diff --git a/.github/scripts/run-argument-comment-lint-bazel.sh b/.github/scripts/run-argument-comment-lint-bazel.sh new file mode 100755 index 0000000000..5c832a05dd --- /dev/null +++ b/.github/scripts/run-argument-comment-lint-bazel.sh @@ -0,0 +1,192 @@ +#!/usr/bin/env bash + +set -euo pipefail + +all_manual_rust_test_targets=() +compatible_manual_rust_test_targets=() +incompatible_manual_rust_test_targets=() +cquery_stdout="$(mktemp)" +cquery_stderr="$(mktemp)" +trap 'rm -f "$cquery_stdout" "$cquery_stderr"' EXIT + +ci_config=ci-linux +case "${RUNNER_OS:-}" in + macOS) + ci_config=ci-macos + ;; + Windows) + ci_config=ci-windows + ;; +esac + +bazel_startup_args=() +if [[ -n "${BAZEL_OUTPUT_USER_ROOT:-}" ]]; then + bazel_startup_args+=("--output_user_root=${BAZEL_OUTPUT_USER_ROOT}") +fi + +run_bazel() { + if [[ "${RUNNER_OS:-}" == "Windows" ]]; then + MSYS2_ARG_CONV_EXCL='*' bazel "$@" + return + fi + + bazel "$@" +} + +cquery_args=("$@" "--config=${ci_config}" "--keep_going") +compatibility_cquery_args=("$@" "--config=${ci_config}") +query_args=() +if [[ -n "${BAZEL_REPO_CONTENTS_CACHE:-}" ]]; then + cquery_args+=("--repo_contents_cache=${BAZEL_REPO_CONTENTS_CACHE}") + compatibility_cquery_args+=("--repo_contents_cache=${BAZEL_REPO_CONTENTS_CACHE}") + query_args+=("--repo_contents_cache=${BAZEL_REPO_CONTENTS_CACHE}") +fi +if [[ -n "${BAZEL_REPOSITORY_CACHE:-}" ]]; then + cquery_args+=("--repository_cache=${BAZEL_REPOSITORY_CACHE}") + compatibility_cquery_args+=("--repository_cache=${BAZEL_REPOSITORY_CACHE}") + query_args+=("--repository_cache=${BAZEL_REPOSITORY_CACHE}") +fi +if [[ -n "${BUILDBUDDY_API_KEY:-}" ]]; then + cquery_args+=("--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}") + compatibility_cquery_args+=("--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}") + query_args+=("--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}") +fi + +# The generated unit-test binaries all end in `-unit-tests-bin`. Enumerate +# those labels explicitly so the final Bazel build can subtract them from the +# wildcard target set and then add back only the compatible subset on Windows. +manual_rust_test_query='kind("rust_test rule", filter("-unit-tests-bin$", //codex-rs/...))' +if ! run_bazel "${bazel_startup_args[@]}" \ + --noexperimental_remote_repo_contents_cache \ + cquery \ + "${cquery_args[@]}" \ + --output=label \ + "$manual_rust_test_query" >"$cquery_stdout" 2>"$cquery_stderr"; then + if [[ ! -s "$cquery_stdout" ]]; then + cat "$cquery_stderr" >&2 + exit 1 + fi +fi + +while IFS= read -r label; do + [[ -n "$label" ]] || continue + incompatible_manual_rust_test_targets+=("$label") +done < <( + sed -n 's/^Target \(\/\/[^ ]*\) is incompatible and cannot be built, but was explicitly requested\.$/\1/p' "$cquery_stderr" +) + +is_incompatible_manual_rust_test_target() { + local candidate="$1" + local incompatible_label + for incompatible_label in "${incompatible_manual_rust_test_targets[@]}"; do + if [[ "$candidate" == "$incompatible_label" ]]; then + return 0 + fi + done + return 1 +} + +normalize_bazel_label() { + local label="$1" + if [[ "$label" == /* && "$label" != //* ]]; then + printf '/%s\n' "$label" + return + fi + + printf '%s\n' "$label" +} + +manual_rust_test_target_is_compatible() { + local candidate="$1" + local compatibility_stdout + local compatibility_stderr + compatibility_stdout="$(mktemp)" + compatibility_stderr="$(mktemp)" + if run_bazel "${bazel_startup_args[@]}" \ + --noexperimental_remote_repo_contents_cache \ + cquery \ + "${compatibility_cquery_args[@]}" \ + --output=label \ + "$candidate" >"$compatibility_stdout" 2>"$compatibility_stderr"; then + if grep -Fq "Target ${candidate} is incompatible and cannot be built, but was explicitly requested." "$compatibility_stderr"; then + rm -f "$compatibility_stdout" "$compatibility_stderr" + return 1 + fi + + if [[ ! -s "$compatibility_stdout" ]]; then + cat "$compatibility_stderr" >&2 + rm -f "$compatibility_stdout" "$compatibility_stderr" + exit 1 + fi + + rm -f "$compatibility_stdout" "$compatibility_stderr" + return 0 + fi + + if grep -Fq "Target ${candidate} is incompatible and cannot be built, but was explicitly requested." "$compatibility_stderr"; then + rm -f "$compatibility_stdout" "$compatibility_stderr" + return 1 + fi + + cat "$compatibility_stderr" >&2 + rm -f "$compatibility_stdout" "$compatibility_stderr" + exit 1 +} + +while IFS= read -r label; do + [[ -n "$label" ]] || continue + # cquery emits configured target labels as `//pkg:target (abcdef0)`. Strip + # the configuration hash before passing the label back to `bazel build`. + label="${label%% (*}" + label="$(normalize_bazel_label "$label")" + all_manual_rust_test_targets+=("$label") + if is_incompatible_manual_rust_test_target "$label"; then + continue + fi + if [[ "${RUNNER_OS:-}" == "Windows" ]] && ! manual_rust_test_target_is_compatible "$label"; then + continue + fi + compatible_manual_rust_test_targets+=("$label") +done <"$cquery_stdout" + +for label in "${incompatible_manual_rust_test_targets[@]}"; do + all_manual_rust_test_targets+=("$label") +done + +excluded_manual_rust_test_targets=() +for label in "${all_manual_rust_test_targets[@]}"; do + excluded_manual_rust_test_targets+=("-${label}") +done + +final_build_targets=(//codex-rs/... "${excluded_manual_rust_test_targets[@]}" "${compatible_manual_rust_test_targets[@]}") +if [[ "${RUNNER_OS:-}" == "Windows" ]]; then + base_rule_targets_stdout="$(mktemp)" + base_rule_targets_stderr="$(mktemp)" + base_rule_targets_query='kind(".* rule", //codex-rs/...) except filter("-unit-tests-bin$", //codex-rs/...)' + if ! run_bazel "${bazel_startup_args[@]}" \ + --noexperimental_remote_repo_contents_cache \ + query \ + "${query_args[@]}" \ + "$base_rule_targets_query" >"$base_rule_targets_stdout" 2>"$base_rule_targets_stderr"; then + cat "$base_rule_targets_stderr" >&2 + rm -f "$base_rule_targets_stdout" "$base_rule_targets_stderr" + exit 1 + fi + + final_build_targets=() + while IFS= read -r label; do + [[ -n "$label" ]] || continue + label="$(normalize_bazel_label "$label")" + final_build_targets+=("$label") + done <"$base_rule_targets_stdout" + rm -f "$base_rule_targets_stdout" "$base_rule_targets_stderr" + + final_build_targets+=("${compatible_manual_rust_test_targets[@]}") +fi + +./.github/scripts/run-bazel-ci.sh \ + -- \ + build \ + "$@" \ + -- \ + "${final_build_targets[@]}" diff --git a/.github/scripts/run-bazel-ci.sh b/.github/scripts/run-bazel-ci.sh index cf50135c2e..92abd0df2e 100755 --- a/.github/scripts/run-bazel-ci.sh +++ b/.github/scripts/run-bazel-ci.sh @@ -41,6 +41,15 @@ if [[ -n "${BAZEL_OUTPUT_USER_ROOT:-}" ]]; then bazel_startup_args+=("--output_user_root=${BAZEL_OUTPUT_USER_ROOT}") fi +run_bazel() { + if [[ "${RUNNER_OS:-}" == "Windows" ]]; then + MSYS2_ARG_CONV_EXCL='*' bazel "$@" + return + fi + + bazel "$@" +} + ci_config=ci-linux case "${RUNNER_OS:-}" in macOS) @@ -60,7 +69,7 @@ print_bazel_test_log_tails() { bazel_info_cmd+=("${bazel_startup_args[@]}") fi - testlogs_dir="$("${bazel_info_cmd[@]}" info bazel-testlogs 2>/dev/null || echo bazel-testlogs)" + testlogs_dir="$(run_bazel "${bazel_info_cmd[@]:1}" info bazel-testlogs 2>/dev/null || echo bazel-testlogs)" local failed_targets=() while IFS= read -r target; do @@ -126,6 +135,17 @@ if [[ $remote_download_toplevel -eq 1 ]]; then post_config_bazel_args+=(--remote_download_toplevel) fi +if [[ -n "${BAZEL_REPO_CONTENTS_CACHE:-}" ]]; then + # Windows self-hosted runners can run multiple Bazel jobs concurrently. Give + # each job its own repo contents cache so they do not fight over the shared + # path configured in `ci-windows`. + post_config_bazel_args+=("--repo_contents_cache=${BAZEL_REPO_CONTENTS_CACHE}") +fi + +if [[ -n "${BAZEL_REPOSITORY_CACHE:-}" ]]; then + post_config_bazel_args+=("--repository_cache=${BAZEL_REPOSITORY_CACHE}") +fi + bazel_console_log="$(mktemp)" trap 'rm -f "$bazel_console_log"' EXIT @@ -149,7 +169,7 @@ if [[ -n "${BUILDBUDDY_API_KEY:-}" ]]; then bazel_run_args+=("${post_config_bazel_args[@]}") fi set +e - "${bazel_cmd[@]}" \ + run_bazel "${bazel_cmd[@]:1}" \ --noexperimental_remote_repo_contents_cache \ "${bazel_run_args[@]}" \ -- \ @@ -184,7 +204,7 @@ else bazel_run_args+=("${post_config_bazel_args[@]}") fi set +e - "${bazel_cmd[@]}" \ + run_bazel "${bazel_cmd[@]:1}" \ --noexperimental_remote_repo_contents_cache \ "${bazel_run_args[@]}" \ -- \ diff --git a/.github/workflows/rust-ci-full.yml b/.github/workflows/rust-ci-full.yml index a09c7fd433..b388684dfa 100644 --- a/.github/workflows/rust-ci-full.yml +++ b/.github/workflows/rust-ci-full.yml @@ -99,35 +99,29 @@ jobs: run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev - - name: Install nightly argument-comment-lint toolchain - if: ${{ runner.os == 'Windows' }} - shell: bash - run: | - rustup toolchain install nightly-2025-09-18 \ - --profile minimal \ - --component llvm-tools-preview \ - --component rustc-dev \ - --component rust-src \ - --no-self-update - rustup default nightly-2025-09-18 - name: Run argument comment lint on codex-rs via Bazel if: ${{ runner.os != 'Windows' }} env: BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} shell: bash run: | - ./.github/scripts/run-bazel-ci.sh \ - -- \ - build \ + ./.github/scripts/run-argument-comment-lint-bazel.sh \ --config=argument-comment-lint \ --keep_going \ - --build_metadata=COMMIT_SHA=${GITHUB_SHA} \ - -- \ - //codex-rs/... - - name: Run argument comment lint on codex-rs via packaged wrapper + --build_metadata=COMMIT_SHA=${GITHUB_SHA} + - name: Run argument comment lint on codex-rs via Bazel if: ${{ runner.os == 'Windows' }} + env: + BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} shell: bash - run: python3 ./tools/argument-comment-lint/run-prebuilt-linter.py + run: | + ./.github/scripts/run-argument-comment-lint-bazel.sh \ + --config=argument-comment-lint \ + --host_platform=//:local_windows_msvc \ + --platforms=//:local_windows \ + --extra_execution_platforms=//:local_windows \ + --keep_going \ + --build_metadata=COMMIT_SHA=${GITHUB_SHA} # --- CI to validate on different os/targets -------------------------------- lint_build: diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index a655b3071e..f7aa458fe9 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -159,35 +159,29 @@ jobs: run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev - - name: Install nightly argument-comment-lint toolchain - if: ${{ runner.os == 'Windows' }} - shell: bash - run: | - rustup toolchain install nightly-2025-09-18 \ - --profile minimal \ - --component llvm-tools-preview \ - --component rustc-dev \ - --component rust-src \ - --no-self-update - rustup default nightly-2025-09-18 - name: Run argument comment lint on codex-rs via Bazel if: ${{ runner.os != 'Windows' }} env: BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} shell: bash run: | - ./.github/scripts/run-bazel-ci.sh \ - -- \ - build \ + ./.github/scripts/run-argument-comment-lint-bazel.sh \ --config=argument-comment-lint \ --keep_going \ - --build_metadata=COMMIT_SHA=${GITHUB_SHA} \ - -- \ - //codex-rs/... - - name: Run argument comment lint on codex-rs via packaged wrapper + --build_metadata=COMMIT_SHA=${GITHUB_SHA} + - name: Run argument comment lint on codex-rs via Bazel if: ${{ runner.os == 'Windows' }} + env: + BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} shell: bash - run: python3 ./tools/argument-comment-lint/run-prebuilt-linter.py + run: | + ./.github/scripts/run-argument-comment-lint-bazel.sh \ + --config=argument-comment-lint \ + --host_platform=//:local_windows_msvc \ + --platforms=//:local_windows \ + --extra_execution_platforms=//:local_windows \ + --keep_going \ + --build_metadata=COMMIT_SHA=${GITHUB_SHA} # --- Gatherer job that you mark as the ONLY required status ----------------- results: diff --git a/BUILD.bazel b/BUILD.bazel index 0be4b711e6..3f59ff1160 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -17,12 +17,19 @@ platform( platform( name = "local_windows", constraint_values = [ - # We just need to pick one of the ABIs. Do the same one we target. "@rules_rs//rs/experimental/platforms/constraints:windows_gnullvm", ], parents = ["@platforms//host"], ) +platform( + name = "local_windows_msvc", + constraint_values = [ + "@rules_rs//rs/experimental/platforms/constraints:windows_msvc", + ], + parents = ["@platforms//host"], +) + alias( name = "rbe", actual = "@rbe_platform", diff --git a/MODULE.bazel b/MODULE.bazel index e71f92ca77..f739352120 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -82,6 +82,9 @@ rules_rust = use_extension("@rules_rs//rs/experimental:rules_rust.bzl", "rules_r rules_rust.patch( patches = [ "//patches:rules_rust_windows_gnullvm_build_script.patch", + "//patches:rules_rust_windows_bootstrap_process_wrapper_linker.patch", + "//patches:rules_rust_windows_msvc_direct_link_args.patch", + "//patches:rules_rust_repository_set_exec_constraints.patch", ], strip = 1, ) @@ -96,6 +99,34 @@ nightly_rust.toolchain( dev_components = True, edition = "2024", ) +# Keep Windows exec tools on MSVC so Bazel helper binaries link correctly, but +# lint crate targets as `windows-gnullvm` to preserve the repo's actual cfgs. +nightly_rust.repository_set( + name = "rust_windows_x86_64", + edition = "2024", + exec_triple = "x86_64-pc-windows-msvc", + exec_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:windows", + "@rules_rs//rs/experimental/platforms/constraints:windows_msvc", + ], + target_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:windows", + "@rules_rs//rs/experimental/platforms/constraints:windows_msvc", + ], + target_triple = "x86_64-pc-windows-msvc", + versions = ["nightly/2025-09-18"], +) +nightly_rust.repository_set( + name = "rust_windows_x86_64", + target_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:windows", + "@rules_rs//rs/experimental/platforms/constraints:windows_gnullvm", + ], + target_triple = "x86_64-pc-windows-gnullvm", +) use_repo(nightly_rust, "rust_toolchains") toolchains = use_extension("@rules_rs//rs/experimental/toolchains:module_extension.bzl", "toolchains") diff --git a/codex-rs/core/src/shell_snapshot_tests.rs b/codex-rs/core/src/shell_snapshot_tests.rs index 90288300ff..ff700ff7a6 100644 --- a/codex-rs/core/src/shell_snapshot_tests.rs +++ b/codex-rs/core/src/shell_snapshot_tests.rs @@ -313,9 +313,15 @@ async fn timed_out_snapshot_shell_is_terminated() -> Result<()> { shell_snapshot: crate::shell::empty_shell_snapshot_receiver(), }; - let err = run_script_with_timeout(&shell, &script, Duration::from_secs(1), true, dir.path()) - .await - .expect_err("snapshot shell should time out"); + let err = run_script_with_timeout( + &shell, + &script, + Duration::from_secs(1), + /*use_login_shell*/ true, + dir.path(), + ) + .await + .expect_err("snapshot shell should time out"); assert!( err.to_string().contains("timed out"), "expected timeout error, got {err:?}" diff --git a/codex-rs/linux-sandbox/src/landlock.rs b/codex-rs/linux-sandbox/src/landlock.rs index 307f956a4d..f03801a3d9 100644 --- a/codex-rs/linux-sandbox/src/landlock.rs +++ b/codex-rs/linux-sandbox/src/landlock.rs @@ -274,7 +274,10 @@ mod tests { #[test] fn managed_network_enforces_seccomp_even_for_full_network_policy() { assert_eq!( - should_install_network_seccomp(NetworkSandboxPolicy::Enabled, true), + should_install_network_seccomp( + NetworkSandboxPolicy::Enabled, + /*allow_network_for_proxy*/ true, + ), true ); } @@ -282,7 +285,10 @@ mod tests { #[test] fn full_network_policy_without_managed_network_skips_seccomp() { assert_eq!( - should_install_network_seccomp(NetworkSandboxPolicy::Enabled, false), + should_install_network_seccomp( + NetworkSandboxPolicy::Enabled, + /*allow_network_for_proxy*/ false, + ), false ); } @@ -291,18 +297,22 @@ mod tests { fn restricted_network_policy_always_installs_seccomp() { assert!(should_install_network_seccomp( NetworkSandboxPolicy::Restricted, - false + /*allow_network_for_proxy*/ false, )); assert!(should_install_network_seccomp( NetworkSandboxPolicy::Restricted, - true + /*allow_network_for_proxy*/ true, )); } #[test] fn managed_proxy_routes_use_proxy_routed_seccomp_mode() { assert_eq!( - network_seccomp_mode(NetworkSandboxPolicy::Enabled, true, true), + network_seccomp_mode( + NetworkSandboxPolicy::Enabled, + /*allow_network_for_proxy*/ true, + /*is_proxy_routed*/ true, + ), Some(NetworkSeccompMode::ProxyRouted) ); } @@ -310,7 +320,11 @@ mod tests { #[test] fn restricted_network_without_proxy_routing_uses_restricted_mode() { assert_eq!( - network_seccomp_mode(NetworkSandboxPolicy::Restricted, false, false), + network_seccomp_mode( + NetworkSandboxPolicy::Restricted, + /*allow_network_for_proxy*/ false, + /*proxy_routed_network*/ false, + ), Some(NetworkSeccompMode::Restricted) ); } @@ -318,7 +332,11 @@ mod tests { #[test] fn full_network_without_managed_proxy_skips_network_seccomp_mode() { assert_eq!( - network_seccomp_mode(NetworkSandboxPolicy::Enabled, false, false), + network_seccomp_mode( + NetworkSandboxPolicy::Enabled, + /*allow_network_for_proxy*/ false, + /*proxy_routed_network*/ false, + ), None ); } diff --git a/codex-rs/linux-sandbox/src/proxy_routing.rs b/codex-rs/linux-sandbox/src/proxy_routing.rs index f57472c8a1..07e1893ee3 100644 --- a/codex-rs/linux-sandbox/src/proxy_routing.rs +++ b/codex-rs/linux-sandbox/src/proxy_routing.rs @@ -718,7 +718,8 @@ mod tests { #[test] fn rewrites_proxy_url_to_local_loopback_port() { let rewritten = - rewrite_proxy_env_value("socks5h://127.0.0.1:8081", 43210).expect("rewritten value"); + rewrite_proxy_env_value("socks5h://127.0.0.1:8081", /*local_port*/ 43210) + .expect("rewritten value"); assert_eq!(rewritten, "socks5h://127.0.0.1:43210"); } diff --git a/patches/BUILD.bazel b/patches/BUILD.bazel index 8d4acbbb91..e00ac53b3a 100644 --- a/patches/BUILD.bazel +++ b/patches/BUILD.bazel @@ -2,6 +2,9 @@ exports_files([ "abseil_windows_gnullvm_thread_identity.patch", "aws-lc-sys_memcmp_check.patch", "llvm_windows_symlink_extract.patch", + "rules_rust_windows_bootstrap_process_wrapper_linker.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", "rusty_v8_prebuilt_out_dir.patch", diff --git a/patches/rules_rust_repository_set_exec_constraints.patch b/patches/rules_rust_repository_set_exec_constraints.patch new file mode 100644 index 0000000000..31afae4f7a --- /dev/null +++ b/patches/rules_rust_repository_set_exec_constraints.patch @@ -0,0 +1,26 @@ +# What: let `rules_rust` repository_set entries specify an explicit exec-platform +# constraint set. +# Why: codex needs Windows nightly lint toolchains to run helper binaries on an +# MSVC exec platform while still targeting `windows-gnullvm` crates. + +diff --git a/rust/extensions.bzl b/rust/extensions.bzl +--- a/rust/extensions.bzl ++++ b/rust/extensions.bzl +@@ -52,6 +52,7 @@ def _rust_impl(module_ctx): + "allocator_library": repository_set.allocator_library, + "dev_components": repository_set.dev_components, + "edition": repository_set.edition, ++ "exec_compatible_with": [str(v) for v in repository_set.exec_compatible_with] if repository_set.exec_compatible_with else None, + "exec_triple": repository_set.exec_triple, + "extra_target_triples": {repository_set.target_triple: [str(v) for v in repository_set.target_compatible_with]}, + "name": repository_set.name, +@@ -166,6 +167,9 @@ _COMMON_TAG_KWARGS = { + + _RUST_REPOSITORY_SET_TAG_ATTRS = { ++ "exec_compatible_with": attr.label_list( ++ doc = "Execution platform constraints for this repository_set.", ++ ), + "exec_triple": attr.string( + doc = "Exec triple for this repository_set.", + ), + "name": attr.string( diff --git a/patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch b/patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch new file mode 100644 index 0000000000..9a978b8be6 --- /dev/null +++ b/patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch @@ -0,0 +1,23 @@ +--- a/rust/private/rustc.bzl ++++ b/rust/private/rustc.bzl +@@ -472,7 +472,19 @@ + ) + 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 = ( ++ toolchain.target_os.startswith("windows") and ++ toolchain.linker != None and ++ hasattr(ctx.executable, "_bootstrap_process_wrapper") and ++ not ctx.executable._process_wrapper ++ ) ++ ++ if not ld or toolchain.linker_preference == "rust" or use_bootstrap_rust_linker: + ld = toolchain.linker.path + ld_is_direct_driver = toolchain.linker_type == "direct" + diff --git a/patches/rules_rust_windows_msvc_direct_link_args.patch b/patches/rules_rust_windows_msvc_direct_link_args.patch new file mode 100644 index 0000000000..2f04f8ca89 --- /dev/null +++ b/patches/rules_rust_windows_msvc_direct_link_args.patch @@ -0,0 +1,64 @@ +--- a/rust/private/rustc.bzl ++++ b/rust/private/rustc.bzl +@@ -2305,7 +2305,7 @@ + return crate.metadata.dirname + return crate.output.dirname + +-def _portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, for_windows = False, for_darwin = False, flavor_msvc = False): ++def _portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, for_windows = False, for_darwin = False, flavor_msvc = False, use_direct_driver = False): + artifact = get_preferred_artifact(lib, use_pic) + if ambiguous_libs and artifact.path in ambiguous_libs: + artifact = ambiguous_libs[artifact.path] +@@ -2344,6 +2344,11 @@ + artifact.basename.startswith("test-") or artifact.basename.startswith("std-") + ): + return [] if for_darwin else ["-lstatic=%s" % get_lib_name(artifact)] ++ ++ if for_windows and use_direct_driver and not artifact.basename.endswith(".lib"): ++ return [ ++ "-Clink-arg={}".format(artifact.path), ++ ] + + if flavor_msvc: + return [ +@@ -2381,7 +2386,7 @@ + ]) + elif include_link_flags: + get_lib_name = get_lib_name_for_windows if flavor_msvc else get_lib_name_default +- ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, flavor_msvc = flavor_msvc)) ++ ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, flavor_msvc = flavor_msvc, use_direct_driver = use_direct_driver)) + + # 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 @@ + 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) + args.add_all( +- cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration), ++ runtime_libs, + map_each = _get_dirname, + format_each = "-Lnative=%s", + ) + if include_link_flags: +- args.add_all( +- cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration), +- 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", ++ ) + + def _get_dirname(file): + """A helper function for `_add_native_link_flags`.