From 57cdf93fac8341a93636ba64e292d30c909c7700 Mon Sep 17 00:00:00 2001 From: garrytan Date: Sat, 3 Oct 2026 21:12:47 +0000 Subject: [PATCH] E2: Windows /cso build disables only C5105, and a failed MSVC compile is not reported as a missing toolchain The Windows SDK's winbase.h raises C5105, which /W4 /WX promotes to error C2220, so every MSVC build of the native /cso helper failed, and setup mapped every probe failure to 'install Visual Studio 2022 Build Tools'. Both compile lines add /wd5105 (only that diagnostic), and setup keeps the probe's output: a probe that found MSVC but failed to compile reports windows-msvc-compile with the compiler's first error. Not run on Windows: the mapping test stubs powershell.exe; the ps1 assertion runs everywhere. Co-authored-by: AlinValentin7 --- scripts/build-cso-windows.ps1 | 7 ++- setup | 17 +++++-- test/setup-cso-windows-probe.test.ts | 69 ++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 test/setup-cso-windows-probe.test.ts diff --git a/scripts/build-cso-windows.ps1 b/scripts/build-cso-windows.ps1 index 77522461a..481c39382 100644 --- a/scripts/build-cso-windows.ps1 +++ b/scripts/build-cso-windows.ps1 @@ -64,7 +64,10 @@ try { $output = Join-Path $temporary 'probe.exe' Set-Content -LiteralPath $source -Encoding Ascii -NoNewline -Value 'int main(void) { return 0; }' $object = Join-Path $temporary 'probe.obj' - & $compiler /nologo /std:c11 /W4 /WX /O2 /MT /GS /guard:cf /D_CRT_SECURE_NO_WARNINGS "/Fo$object" "/Fe$output" $source /link /DYNAMICBASE /NXCOMPAT /HIGHENTROPYVA + # /wd5105: the Windows SDK's own winbase.h raises C5105 ("macro expansion + # producing 'defined' has undefined behavior"), which /WX turns into + # error C2220 inside a system header (#3015). Only that diagnostic is off. + & $compiler /nologo /std:c11 /W4 /WX /wd5105 /O2 /MT /GS /guard:cf /D_CRT_SECURE_NO_WARNINGS "/Fo$object" "/Fe$output" $source /link /DYNAMICBASE /NXCOMPAT /HIGHENTROPYVA if ($LASTEXITCODE -ne 0) { throw "Native CSO Windows compiler probe failed ($LASTEXITCODE)." } if (-not (Test-Path -LiteralPath $output -PathType Leaf)) { throw 'Native CSO Windows compiler probe was not produced.' } } else { @@ -78,7 +81,7 @@ try { foreach ($build in $builds) { $object = Join-Path $temporary $build.Object $forcedInclude = if ($build.Binding) { "/FI$binding" } else { @() } - & $compiler /nologo /std:c11 /W4 /WX /O2 /MT /GS /guard:cf /D_CRT_SECURE_NO_WARNINGS $forcedInclude "/Fo$object" "/Fe$($build.Output)" $build.Source /link /DYNAMICBASE /NXCOMPAT /HIGHENTROPYVA + & $compiler /nologo /std:c11 /W4 /WX /wd5105 /O2 /MT /GS /guard:cf /D_CRT_SECURE_NO_WARNINGS $forcedInclude "/Fo$object" "/Fe$($build.Output)" $build.Source /link /DYNAMICBASE /NXCOMPAT /HIGHENTROPYVA if ($LASTEXITCODE -ne 0) { throw "Native CSO Windows helper compilation failed ($LASTEXITCODE)." } if (-not (Test-Path -LiteralPath $build.Output -PathType Leaf)) { throw 'Native CSO Windows output was not produced.' } } diff --git a/setup b/setup index 0e50e67f6..20ac8627e 100755 --- a/setup +++ b/setup @@ -1476,9 +1476,10 @@ _cso_unavailable() { # A successful probe is only a prerequisite check; any later source build failure # still aborts setup and therefore cannot be mistaken for a missing local tool. probe_cso_build_prerequisites() { - local _help _flag _platform _compiler _tmp _ps_script _repo_root _git_path + local _help _flag _platform _compiler _tmp _ps_script _repo_root _git_path _probe_out CSO_BUILD_AVAILABLE=1 CSO_FAIL_REASON="" + CSO_PROBE_DETAIL="" if [ "${GSTACK_SETUP_SKIP_CSO_BUILD:-0}" = "1" ]; then _cso_unavailable "skipped-by-request" return 0 @@ -1505,9 +1506,16 @@ probe_cso_build_prerequisites() { _cso_unavailable "windows-git" return 0 fi - if ! powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass \ - -File "$_ps_script" -RepoRoot "$_repo_root" -GitExePath "$(cygpath -aw "$_git_path")" -CheckOnly >/dev/null 2>&1; then - _cso_unavailable "windows-msvc-toolchain" + # E2 (#3015): a probe that found MSVC but could not compile is not a + # missing toolchain; keep the probe's own first diagnostic for the summary. + if ! _probe_out="$(powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass \ + -File "$_ps_script" -RepoRoot "$_repo_root" -GitExePath "$(cygpath -aw "$_git_path")" -CheckOnly 2>&1)"; then + case "$_probe_out" in + *"compiler probe failed"*|*"compiler probe was not produced"*) + _cso_unavailable "windows-msvc-compile" + CSO_PROBE_DETAIL="$(printf '%s\n' "$_probe_out" | grep -m1 -E 'error [A-Z]*[0-9]+|probe (failed|was not produced)' | tr -d '\r' | head -c 200)" ;; + *) _cso_unavailable "windows-msvc-toolchain" ;; + esac fi return 0 fi @@ -4194,6 +4202,7 @@ if [ "$CSO_BUILD_AVAILABLE" -eq 0 ]; then macos-codesign|macos-native-toolchain) _CSO_PREREQ="install the macOS compiler and codesign command-line tools" ;; windows-shell-toolchain) _CSO_PREREQ="run setup from Git Bash with Windows PowerShell available" ;; windows-msvc-toolchain) _CSO_PREREQ="install Visual Studio 2022 Build Tools with Desktop development with C++" ;; + windows-msvc-compile) _CSO_PREREQ="fix the MSVC compile error its toolchain probe reported (${CSO_PROBE_DETAIL:-see scripts/build-cso-windows.ps1 -CheckOnly}); Visual Studio is already installed" ;; windows-git) _CSO_PREREQ="install Git for Windows and run setup from its Git Bash" ;; unsupported-platform) _CSO_PREREQ="use a supported macOS, Linux, or Windows host" ;; skipped-by-request) _CSO_PREREQ="re-run without GSTACK_SETUP_SKIP_CSO_BUILD=1" ;; diff --git a/test/setup-cso-windows-probe.test.ts b/test/setup-cso-windows-probe.test.ts new file mode 100644 index 000000000..20635bdcb --- /dev/null +++ b/test/setup-cso-windows-probe.test.ts @@ -0,0 +1,69 @@ +import { afterEach, describe, expect, test } from 'bun:test'; +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; +import { runBashScript } from './helpers/bash-script'; + +// E2 (#3015): the Windows /cso build compiles with /W4 /WX, and the Windows +// SDK's winbase.h raises C5105, so every MSVC build failed; and setup reported +// every probe failure as a missing Visual Studio toolchain. The probe and the +// helper builds disable only C5105, and a probe that found MSVC but could not +// compile gets its own reason with the compiler's first diagnostic. Runs the +// real setup function on any OS with powershell.exe/cygpath stubbed. +const ROOT = path.resolve(import.meta.dir, '..'); +const setup = fs.readFileSync(path.join(ROOT, 'setup'), 'utf8'); +const ps1 = fs.readFileSync(path.join(ROOT, 'scripts/build-cso-windows.ps1'), 'utf8'); +const fn = (name: string) => { + const start = setup.indexOf(`\n${name}() {`); + const end = setup.indexOf('\n}\n', start); + if (start < 0 || end < 0) throw new Error(`missing setup function ${name}`); + return setup.slice(start + 1, end + 3); +}; +const summaryStart = setup.indexOf(' case "$CSO_FAIL_REASON" in'); +const summaryCase = setup.slice(summaryStart, setup.indexOf('\n esac\n', summaryStart) + 8); + +const tmps: string[] = []; +afterEach(() => { for (const t of tmps.splice(0)) fs.rmSync(t, { recursive: true, force: true }); }); + +function probe(powershellOutput: string) { + const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-cso-win-')); + tmps.push(tmp); + fs.writeFileSync(path.join(tmp, 'powershell.exe'), `#!/bin/sh\ncat <<'OUT' >&2\n${powershellOutput}\nOUT\nexit 1\n`, { mode: 0o755 }); + fs.writeFileSync(path.join(tmp, 'cygpath'), '#!/bin/sh\nshift; echo "$1"\n', { mode: 0o755 }); + return runBashScript([ + 'IS_WINDOWS=1', `SOURCE_GSTACK_DIR="${ROOT}"`, + 'bun_cmd() { echo "--no-compile-autoload-dotenv --no-compile-autoload-bunfig --no-compile-autoload-tsconfig --no-compile-autoload-package-json"; }', + fn('_cso_unavailable'), fn('probe_cso_build_prerequisites'), + 'probe_cso_build_prerequisites', summaryCase, + 'printf "reason=%s\\nprereq=%s\\n" "$CSO_FAIL_REASON" "$_CSO_PREREQ"', + ].join('\n'), { env: { ...process.env, PATH: `${tmp}:${process.env.PATH}` }, timeout: 30_000 }); +} + +describe('setup: Windows /cso build probe (E2)', () => { + test('both MSVC compile lines disable only C5105 and keep /W4 /WX', () => { + const lines = ps1.split('\n').filter(l => l.includes('& $compiler')); + expect(lines).toHaveLength(2); + for (const line of lines) expect(line).toContain('/W4 /WX /wd5105 '); + }); +}); + +// The stubs are POSIX shell scripts named powershell.exe and cygpath, so the +// reason mapping runs off Windows; the real probe needs MSVC (not verified here). +describe.skipIf(process.platform === 'win32')('setup: Windows /cso probe failure mapping (E2)', () => { + test('a compile failure with MSVC present names the compiler error, not a missing toolchain', () => { + const r = probe([ + "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.19041.0\\um\\winbase.h(9531): error C2220: the following warning is treated as an error", + 'Native CSO Windows compiler probe failed (2).', + ].join('\n')); + expect(r.stdout).toContain('reason=windows-msvc-compile\n'); + expect(r.stdout).toContain('prereq=fix the MSVC compile error its toolchain probe reported ('); + expect(r.stdout).toContain('error C2220: the following warning is treated as an error'); + expect(r.stdout).toContain('Visual Studio is already installed'); + }); + + test('a missing Visual Studio toolchain keeps the install instruction', () => { + const r = probe('CSO Windows build requires Visual Studio 2022 Build Tools with the Desktop development with C++ workload.'); + expect(r.stdout).toContain('reason=windows-msvc-toolchain\n'); + expect(r.stdout).toContain('prereq=install Visual Studio 2022 Build Tools with Desktop development with C++\n'); + }); +});