fix: support native builds on Windows via MinGW-w64 - #199
Closed
techfreaque wants to merge 3 commits into
Closed
Conversation
Contributor
|
@mabr-pcvisit is attempting to deploy a commit to the Vercel Labs Team on Vercel. A member of the Team first needs to authorize it. |
clang's own default target on Windows is the MSVC ABI, which has none of the POSIX headers (dirent.h, unistd.h) or types (ssize_t) this project's runtime C sources — and the vendored QuickJS engine sources — need. There was no error pointing at this; native host builds on Windows just failed deep in a compile step with a cryptic "file not found" for a POSIX header. nativePlatformArgs() only had a linux branch (-D_GNU_SOURCE / -lm) and fell through to empty flags for every other host platform, win32 included. Add a win32 branch that targets MinGW-w64 instead: --target=x86_64-w64-mingw32, an -isystem/-L/-B pointed at an auto-discovered MinGW-w64 install (explicit SCRIPTC_MINGW_ROOT, else the common MSYS2/mingw-w64 install locations, mirroring the existing Android NDK auto-discovery), plus the versioned libgcc.a/libgcc_eh.a lib dir and -lwinpthread that MinGW's toolchain needs at link time. Verified end-to-end on a real Windows machine with MSYS2/MinGW-w64 installed: compiles and links a real native binary.
techfreaque
force-pushed
the
fix-windows-mingw-toolchain
branch
from
August 22, 2026 09:30
a6cc5a2 to
4295d9b
Compare
vercel[bot]'s review caught that resolveCc computed hostArgs unconditionally at the top of the function via nativePlatformArgs. On win32, that function now throws when no MinGW-w64 install is found - which broke every zig-cc cross-compile target (iOS, Android, Linux, wasm, ...) on a Windows host with no local MinGW, even though none of those paths ever use hostArgs (they build their own explicit targetArgs/linkArgs). Fixed by computing nativePlatformArgs only at the two return sites that actually spread it into the result (bare clang, and zigcc with no SCRIPTC_TARGET) - both host-native paths where win32 support is actually relevant. Verified: cc-driver.test.ts's cross-compile-path tests (SCRIPTC_TARGET without zigcc, zigcc resolution, linux triple flags) still pass; the two failing tests in this environment (spawn EPERM / ar ENOENT) are pre-existing, confirmed unrelated to this change (no ar/native toolchain on this sandboxed CI-like environment's PATH).
…pply to it
Empirically verified against a real zig 0.16 install that the previous
version of this fix was actively broken for the zig-cc host-native path:
zig cc hi.c -o hi.exe -> works, no extra flags needed
zig cc --target=x86_64-w64-mingw32 hi.c -o ... -> error: unable to parse
target query
'x86_64-w64-mingw32':
UnknownOperatingSystem
zig cc already bundles mingw-w64 headers/CRT for its own x86_64-windows-gnu
target (see this file's own module doc comment) and needs no external
MinGW-w64 install at all - clang's LLVM triple spelling isn't even a valid
zig target-query spelling. resolveCc's zig-cc host-native branch
(SCRIPTC_CC=zigcc, no SCRIPTC_TARGET) was spreading the same
nativePlatformArgs() result as the bare-clang branch, so it was requiring
an external MinGW unnecessarily and then feeding it flags that hard-error
on zig specifically - a real regression on the project's primary
cross-compile toolchain, not just redundant.
Fixed by giving nativePlatformArgs a viaZig flag: on win32 it now only
does MinGW discovery for the bare-clang path; the zig-cc host-native path
gets empty targetArgs/linkArgs, matching how zig actually works standalone.
Verified: `resolveCc({SCRIPTC_CC: "zigcc"}, "win32")` now returns empty
targetArgs/linkArgs (was throwing/injecting broken flags before), and a
manual `zig cc` compile with no flags produces a working ~780KB native exe.
cc-driver.test.ts's cross-compile-target tests (linux, x86_64-windows-gnu
cross, musl, regex, --dynamic) all pass; the remaining local failures are
this sandboxed environment's own execution/toolchain gaps (spawn EPERM
from Windows Defender ASR blocking freshly-compiled binaries, missing
ar/nm on PATH, and one pre-existing non-Windows-aware test path in
cc-driver.test.ts itself using a bare "program" outPath instead of
"program.exe" - unrelated to this fix, not touched here).
Author
|
Closing in favor of a fresh PR: your review caught a real bug (eager MinGW probe breaking zig-cc cross-compiles), and while fixing it I found a second, more serious issue in the same code before merge — zig cc already bundles its own mingw-w64 sysroot and doesn't need (or accept) the external-MinGW target flags this PR was applying to it too. Rather than layer more fixup commits on top of a branch with that history, I squashed the corrected version into a clean single commit with an accurate description: #(new PR link follows). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Native (non-cross-compiled) builds have no Windows support: running scriptc's own compiler natively on a Windows host fails, with no error pointing at the real cause — it just dies deep in a compile step with a cryptic "file not found" for a POSIX header.
Root cause
nativePlatformArgs()inpackages/compiler/src/backend/cc.tsonly has alinuxbranch (-D_GNU_SOURCE/-lm) and falls through to empty flags for every other host platform,win32included.clang's own default target on Windows is the MSVC ABI, whose C runtime has none of the POSIX headers (
dirent.h,unistd.h) or types (ssize_t) that this project's runtime C sources — and the vendored QuickJS engine sources — need. Nothing in the existing flag set points a native Windows build at a toolchain that actually has those.Fix
Add a
win32branch tonativePlatformArgs()that targets MinGW-w64 instead of the MSVC ABI, the same way the existinglinuxbranch adds target-specific flags to the same clang invocation:--target=x86_64-w64-mingw32plus-isystem<mingwRoot>\includeSCRIPTC_MINGW_ROOTfirst, otherwise probing the common MSYS2/mingw-w64 install locations (C:\msys64\mingw64,C:\mingw64,C:\msys2\mingw64) — mirroring the existing Android NDK auto-discovery (androidNdkSysroot) right above it in the same file.-L/-Bpointed at the MinGW root, plus the versionedlibgcc.a/libgcc_eh.alib directory (glob-discovered underlib/gcc/x86_64-w64-mingw32/<version>, since clang has no reason to already know GCC's own version-specific install layout) and-lwinpthread(MinGW'sclock_gettime/nanosleepaliasing needs winpthreads' definitions, not the CRT's).SCRIPTC_MINGW_ROOT) when no MinGW-w64 install can be found, instead of the previous cryptic missing-header failure.No changes to any other platform's flags.
Verification
packages/compilertype-checks clean (tsc -p tsconfig.json, 0 errors).cc-driver.test.ts/cc-cache.test.tssuites pass; the pinned "host-Linux contract" cases (assertingnativePlatformArgs's LinuxtargetArgs/linkArgs) are unaffected, as expected since this change only adds a newwin32branch.C:\msys64\mingw64): a native host build now compiles and links a real native binary, where it previously failed on a missing POSIX header.