feat(napi): build a native binary for Windows on ARM - #82
Merged
Conversation
aarch64-pc-windows-msvc was the one platform in the loader with no binary behind it: index.js has always had a `win32-arm64-msvc` branch, so every Windows-on-ARM install walked it, found nothing, and fell back to the TypeScript ingest path. Graceful, but it is the slow path, and it is the same population that just hit the unshipped parse worker. Cross-compiled from windows-latest, mirroring how aarch64-linux is built on ubuntu-latest, then require()-loaded on windows-11-arm — GitHub's hosted ARM Windows runner, free for public repos — so the binary is verified on real hardware rather than shipped on faith. That keeps the invariant napi-build.yml states for itself: every published binary is loaded on a matching host before publish. Also registers the platform package and its release-please version entry, matching the other five. Those packages are not published today (the main package fat-bundles every binary) but are kept version-synced. Includes a temporary pull_request-triggered probe workflow to prove the cross-compile works on the runner image, since rusqlite's bundled SQLite needs an MSVC toolset targeting ARM64 and that cannot be checked locally. It is removed in the next commit. Claude-Session: https://claude.ai/code/session_01LQt9EvHYXCd2U4ZJMfMm4E
It existed to answer one question that could not be settled locally: whether windows-latest can cross-compile aarch64-pc-windows-msvc, including rusqlite's bundled SQLite, which needs an MSVC toolset targeting ARM64 rather than just the Rust std for that target. Both halves passed on the previous commit: Compiling rusqlite v0.31.0 Finished `release` profile [optimized] target(s) in 1m 35s spaghetti.win32-arm64-msvc.node 4544512 bytes Loaded OK on win32 arm64 - nativeVersion = 0.5.21 The cross-compile is 3m33s on windows-latest and the load check is 1m10s on windows-11-arm, so the equivalent legs now in napi-build.yml cost the release about the same as the existing windows-x64 pair. Claude-Session: https://claude.ai/code/session_01LQt9EvHYXCd2U4ZJMfMm4E
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.
Why
aarch64-pc-windows-msvcwas the one platform in the loader with no binary behind it.index.jshas always had awin32-arm64-msvcbranch, so every Windows-on-ARM install walked it, found nothing, and fell back to the TypeScript ingest path.Graceful, but it's the slow path — and it's the same population that just hit the unshipped parse worker in #81, which compounded into sequential TypeScript parsing.
What
aarch64-pc-windows-msvcadded tonapi.targetswindows-latest, mirroring howaarch64-linuxis built onubuntu-latestwindows-11-arm, GitHub's hosted ARM Windows runner (free for public repos), so the binary isrequire()-loaded on real hardware rather than shipped on faith — keeping the invariant napi-build.yml states for itselfThe loader needs no change: napi generates branches for every known platform regardless of which targets are built, so
win32-arm64-msvcwas already wired.Verification
rusqlite'sbundledfeature compiles SQLite from C, so this needs an MSVC toolset targeting ARM64 — not just Rust std for the target. That can't be checked locally (my box has no ARM64cl.exe; the build fails withfailed to find tool "cl.exe"), so this PR carries a temporary probe workflow that cross-compiles and then loads the result on real ARM64 hardware.napi-build.ymlcouldn't be used for this: it'sworkflow_dispatch-only and its publish job has no condition, so dispatching it to test a build would also attempt an npm publish. Andrelease.ymldispatches it with no inputs, so adding apublishinput would silently stop releases from publishing.The probe is deleted before merge — it exists to produce evidence, not to ship.
🤖 Generated with Claude Code
https://claude.ai/code/session_01LQt9EvHYXCd2U4ZJMfMm4E