cloudflare / cloudflare/workerd

Windows: --nowindows_enable_symlinks workaround for TypeScript builds causes test targets to fail to build

Open
#6,510 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
8.7k
Forks
739
Avg merge
2d 20h
Merged PRs (30d)
174

Description

## Summary

The TypeScript pre-build workaround (`--nowindows_enable_symlinks`) used in CI for Windows creates a configuration mismatch that prevents test targets from reusing the cached TS artifacts. When the remote cache is cold or when building locally, ~870 test targets fail to build because they transitively depend on pyodide TypeScript code that only compiles under the `--nowindows_enable_symlinks` configuration.

Applying `--nowindows_enable_symlinks` globally is not an option -- it causes "redefinition" errors in C++ compilation (kj/common.h headers get duplicated via `_virtual_includes` instead of symlinked).

## Background

CI has this workaround in `_bazel.yml`:

```yaml
- name: Bazel build (Windows workaround)
if: runner.os == 'Windows'
# HACK: Work around Bazel Windows bug
run: |
bazel --nowindows_enable_symlinks build ... //src/pyodide:pyodide_static@tsproject
```

The subsequent `bazel build //...` and `bazel test //...` run **without** `--nowindows_enable_symlinks`. This works when the remote cache has TS artifacts from a prior Linux CI run (TS output is platform-independent), but fails when:

1. The remote cache is cold for these targets
2. A developer builds locally on Windows (no remote cache)

## Reproduction

On any Windows machine with the workerd build environment:

```sh
# TS build fails with symlinks enabled:
bazel build --config=windows //src/pyodide:pyodide_static@tsproject

# C++ build fails with symlinks disabled:
bazel --nowindows_enable_symlinks build --config=windows //src/workerd/server:workerd
# -> "redefinition of default argument" in kj/common.h

# Two-step workaround works, but test targets can't reuse the TS artifacts
# because the configuration hashes differ:
bazel --nowindows_enable_symlinks build --config=windows //src/pyodide:pyodide_static@tsproject
bazel test --config=windows //...
# -> ~870 test targets fail to build
```

## Evidence

- Local Windows Server 2025 VM: 109/111 tests pass, but 872 targets fail to build due to the pyodide TS dependency chain
- The same 872 targets build fine on Linux

## Impact

- Windows developers cannot run the full test suite locally
- CI Windows tests are fragile -- they depend on remote cache hits from Linux CI for TS artifacts
- The `--nowindows_enable_symlinks` flag creates two incompatible Bazel configurations that can't share artifacts

## Questions

- What is the root cause of the pyodide TypeScript compilation failure when symlinks are enabled on Windows? Is this a `rules_ts` / `rules_js` bug, or a Bazel bug?
- Is there a way to make the TS build work with symlinks enabled on Windows, eliminating the need for the workaround entirely?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.