Files
codex/patches/rusty_v8_prebuilt_out_dir.patch
Michael Bolin 343d1af3da bazel: enable the full Windows gnullvm CI path (#15952)
## Why

This PR is the current, consolidated follow-up to the earlier Windows
Bazel attempt in #11229. The goal is no longer just to get a tiny
Windows smoke job limping along: it is to make the ordinary Bazel CI
path usable on `windows-latest` for `x86_64-pc-windows-gnullvm`, with
the same broad `//...` test shape that macOS and Linux already use.

The earlier smoke-list version of this work was useful as a foothold,
but it was not a good long-term landing point. Windows Bazel kept
surfacing real issues outside that allowlist:

- GitHub's Windows runner exposed runfiles-manifest bugs such as
`FINDSTR: Cannot open D:MANIFEST`, which broke Bazel test launchers even
when the manifest file existed.
- `rules_rs`, `rules_rust`, LLVM extraction, and Abseil still needed
`windows-gnullvm`-specific fixes for our hermetic toolchain.
- the V8 path needed more work than just turning the Windows matrix
entry back on: `rusty_v8` does not ship Windows GNU artifacts in the
same shape we need, and Bazel's in-tree V8 build needed a set of Windows
GNU portability fixes.

Windows performance pressure also pushed this toward a full solution
instead of a permanent smoke suite. During this investigation we hit
targets such as `//codex-rs/shell-command:shell-command-unit-tests` that
were much more expensive on Windows because they repeatedly spawn real
PowerShell parsers (see #16057 for one concrete example of that
pressure). That made it much more valuable to get the real Windows Bazel
path working than to keep iterating on a narrowly curated subset.

The net result is that this PR now aims for the same CI contract on
Windows that we already expect elsewhere: keep standalone
`//third_party/v8:all` out of the ordinary Bazel lane, but allow V8
consumers under `//codex-rs/...` to build and test transitively through
`//...`.

## What Changed

### CI and workflow wiring

- re-enable the `windows-latest` / `x86_64-pc-windows-gnullvm` Bazel
matrix entry in `.github/workflows/bazel.yml`
- move the Windows Bazel output root to `D:\b` and enable `git config
--global core.longpaths true` in
`.github/actions/setup-bazel-ci/action.yml`
- keep the ordinary Bazel target set on Windows aligned with macOS and
Linux by running `//...` while excluding only standalone
`//third_party/v8:all` targets from the normal lane

### Toolchain and module support for `windows-gnullvm`

- patch `rules_rs` so `windows-gnullvm` is modeled as a distinct Windows
exec/toolchain platform instead of collapsing into the generic Windows
shape
- patch `rules_rust` build-script environment handling so llvm-mingw
build-script probes do not inherit unsupported `-fstack-protector*`
flags
- patch the LLVM module archive so it extracts cleanly on Windows and
provides the MinGW libraries this toolchain needs
- patch Abseil so its thread-local identity path matches the hermetic
`windows-gnullvm` toolchain instead of taking an incompatible MinGW
pthread path
- keep both MSVC and GNU Windows targets in the generated Cargo metadata
because the current V8 release-asset story still uses MSVC-shaped names
in some places while the Bazel build targets the GNU ABI

### Windows test-launch and binary-behavior fixes

- update `workspace_root_test_launcher.bat.tpl` to read the runfiles
manifest directly instead of shelling out to `findstr`, which was the
source of the `D:MANIFEST` failures on the GitHub Windows runner
- thread a larger Windows GNU stack reserve through `defs.bzl` so
Bazel-built binaries that pull in V8 behave correctly both under normal
builds and under `bazel test`
- remove the no-longer-needed Windows bootstrap sh-toolchain override
from `.bazelrc`

### V8 / `rusty_v8` Windows GNU support

- export and apply the new Windows GNU patch set from
`patches/BUILD.bazel` / `MODULE.bazel`
- patch the V8 module/rules/source layers so the in-tree V8 build can
produce Windows GNU archives under Bazel
- teach `third_party/v8/BUILD.bazel` to build Windows GNU static
archives in-tree instead of aliasing them to the MSVC prebuilts
- reuse the Linux release binding for the experimental Windows GNU path
where `rusty_v8` does not currently publish a Windows GNU binding
artifact

## Testing

- the primary end-to-end validation for this work is the `Bazel`
workflow plus `v8-canary`, since the hard parts are Windows-specific and
depend on real GitHub runner behavior
- before consolidation back onto this PR, the same net change passed the
full Bazel matrix in [run
23675590471](https://github.com/openai/codex/actions/runs/23675590471)
and passed `v8-canary` in [run
23675590453](https://github.com/openai/codex/actions/runs/23675590453)
- those successful runs included the `windows-latest` /
`x86_64-pc-windows-gnullvm` Bazel job with the ordinary `//...` path,
not the earlier Windows smoke allowlist

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/15952).
* #16067
* __->__ #15952
2026-03-27 20:37:03 -07:00

75 lines
2.3 KiB
Diff

# What: make `rusty_v8` accept Bazel-provided archives and bindings for the
# windows-gnullvm experiment.
# Scope: `rusty_v8` build.rs only; no V8 source or Bazel rule changes.
--- a/build.rs
+++ b/build.rs
@@ -543,10 +543,15 @@
}
fn static_lib_name(suffix: &str) -> String {
- let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
- if target_os == "windows" {
+ let target = env::var("TARGET").unwrap();
+ let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
+ if target.contains("windows-gnullvm") {
+ // rustc looks for GNU-style archive names when bundling `-lstatic` on the
+ // gnullvm targets, even though the prebuilt release is a COFF `.lib`.
+ format!("librusty_v8{suffix}.a")
+ } else if target_os == "windows" {
format!("rusty_v8{suffix}.lib")
} else {
format!("librusty_v8{suffix}.a")
}
}
@@ -577,7 +577,23 @@
path
}
+fn out_dir_abs() -> PathBuf {
+ let cwd = env::current_dir().unwrap();
+
+ // target/debug/build/rusty_v8-d9e5a424d4f96994/out/
+ let out_dir = env::var_os("OUT_DIR").expect(
+ "The 'OUT_DIR' environment is not set (it should be something like \
+ 'target/debug/rusty_v8-{hash}').",
+ );
+
+ cwd.join(out_dir)
+}
+
fn static_lib_dir() -> PathBuf {
+ if env::var_os("RUSTY_V8_ARCHIVE").is_some() {
+ return out_dir_abs().join("gn_out").join("obj");
+ }
+
build_dir().join("gn_out").join("obj")
}
@@ -794,22 +810,23 @@
}
fn print_link_flags() {
+ let target = env::var("TARGET").unwrap();
println!("cargo:rustc-link-lib=static=rusty_v8");
let should_dyn_link_libcxx = env::var("CARGO_FEATURE_USE_CUSTOM_LIBCXX")
.is_err()
+ || (target.contains("apple") && env::var("RUSTY_V8_ARCHIVE").is_ok())
|| env::var("GN_ARGS").is_ok_and(|gn_args| {
gn_args
.split_whitespace()
.any(|ba| ba == "use_custom_libcxx=false")
});
if should_dyn_link_libcxx {
// Based on https://github.com/alexcrichton/cc-rs/blob/fba7feded71ee4f63cfe885673ead6d7b4f2f454/src/lib.rs#L2462
if let Ok(stdlib) = env::var("CXXSTDLIB") {
if !stdlib.is_empty() {
println!("cargo:rustc-link-lib=dylib={stdlib}");
}
} else {
- let target = env::var("TARGET").unwrap();
if target.contains("msvc") {
// nothing to link to
} else if target.contains("apple")