fix(natives): make Windows-host builds and addon loading work end to end

Runtime: the loader's AVX2 probe used [System.Runtime.Intrinsics.X86.Avx2]
via powershell.exe, which only exists on .NET Core — stock Windows PowerShell
5.1 raised TypeNotFound, so every Windows host silently loaded the baseline
addon and paid ~270ms for the spawn on the startup path. Ask the kernel via
bun:ffi (IsProcessorFeaturePresent(PF_AVX2_INSTRUCTIONS_AVAILABLE), ~0.5ms)
and fall back to pwsh-then-powershell for Node embeds. scripts/host-detect.ts
shared the same broken probe for build-time variant selection.

Build: `bun run build:native` on a win32 host died deep inside the bazel msvc
repo rules (linux/mac exec hosts only, by design). The `host` pseudo-target
now delegates to the local napi build against real VS Build Tools, and other
targets fail fast with guidance. build-bindings.ts resolves the @napi-rs/cli
JS entry from its manifest (the node_modules/.bin shim is a PE launcher Bun
cannot parse) and auto-appends VS Build Tools' bundled CMake/Ninja to PATH
via vswhere so a vcvars prompt is no longer required. Cap maudio at
opt-level=1 to dodge a rustc ICE codegenning MaybeUninit<ma_fence> for
x86_64-pc-windows-msvc under the pinned nightly (Bazel's older pin is
unaffected).

Compile: Bun.Glob.scan yields backslash paths on Windows; the legacy Pi
virtual module used them verbatim for export keys and generated identifiers,
producing invalid JavaScript in compiled-binary builds.

Tests: strip ConPTY negotiation escapes in the pty argv test; ignore the
bazel-oh-my-pi convenience symlink.
This commit is contained in:
zero
2026-08-07 16:50:52 +08:00
parent ab78d3091e
commit 82436b0e93
10 changed files with 201 additions and 27 deletions
@@ -151,7 +151,10 @@ export async function collectBundledPiEntries(): Promise<BundledPiEntry[]> {
const glob = new Bun.Glob(`**/*${pattern.sourceSuffix}`);
const matches: string[] = [];
for await (const match of glob.scan({ cwd: sourceDir, onlyFiles: true })) {
matches.push(match);
// Bun.Glob yields host separators; the export keys and generated
// identifiers below are `/`-shaped. Same normalization as
// `generate-docs-index.ts`.
matches.push(match.split(path.sep).join("/"));
}
matches.sort();
for (const match of matches) {