\r
@rem ---------------------------------------------------------------------------\r
@rem setup-windows.bat - provision a fresh Windows box for native development\r
+@rem\r
+@rem Runs on x64 and on ARM64 (Windows 11 on Arm). See the ARM64 block below for\r
+@rem what changes on Arm silicon.\r
@rem ---------------------------------------------------------------------------\r
\r
+@rem ---------------------------------------------------------------------------\r
+@rem Host architecture\r
+@rem\r
+@rem PROCESSOR_ARCHITECTURE alone is not enough: a 32-bit cmd.exe under emulation\r
+@rem reports x86 and stashes the real one in PROCESSOR_ARCHITEW6432. Check both,\r
+@rem so this is right however the script was launched.\r
+@rem\r
+@rem The value drives two things below, and nothing else - winget resolves the\r
+@rem installer architecture on its own (native first, then whatever the box can\r
+@rem emulate), so the ordinary installs need no help:\r
+@rem - VirtualBox is skipped on ARM64 (see below)\r
+@rem - the summary tells you which tools you got as emulated x64\r
+@rem ---------------------------------------------------------------------------\r
+set "HOST_ARCH=%PROCESSOR_ARCHITECTURE%"\r
+if defined PROCESSOR_ARCHITEW6432 set "HOST_ARCH=%PROCESSOR_ARCHITEW6432%"\r
+set "IS_ARM64=0"\r
+if /i "%HOST_ARCH%"=="ARM64" set "IS_ARM64=1"\r
+echo [setup-windows] Host architecture: %HOST_ARCH%\r
+\r
@rem --- Non-admin (per-user) winget installs ---\r
+@rem\r
+@rem No --architecture anywhere on purpose. winget already picks the best\r
+@rem installer the manifest offers for this machine - arm64, else x64, else x86 -\r
+@rem and pinning it would turn "no native build, use the emulated one" into a\r
+@rem hard failure.\r
+@rem\r
+@rem These all publish real ARM64 installers, so on an ARM64 box every one of\r
+@rem them lands as a native ARM64 binary with no emulation involved.\r
+@rem\r
+@rem The Sysinternals packages are a multi-architecture ZIP rather than an\r
+@rem installer, so the ARM64 build is IN there but is not the default-named exe:\r
+@rem the zip holds procexp.exe (x86), procexp64.exe (x64) and procexp64a.exe\r
+@rem (ARM64). On ARM64, run the *64a.exe variants - plain procexp.exe is the x86\r
+@rem one and will run emulated.\r
winget install Anthropic.ClaudeCode\r
+winget install Brave.Brave\r
winget install Git.Git\r
+winget install Microsoft.DotNet.SDK.10\r
winget install Microsoft.PowerShell Microsoft.Sysinternals.ProcessExplorer Microsoft.Sysinternals.ProcessMonitor Microsoft.Sysinternals.SDelete Microsoft.VisualStudioCode Microsoft.WindowsTerminal\r
winget install Python.Python.3.13\r
winget install WinMerge.WinMerge\r
-winget install WiXToolset.WiXCLI\r
+\r
+@rem --- Build drivers, standalone and native ---\r
+@rem\r
+@rem CMake and Ninja BOTH ship with Visual Studio, so this is not about making\r
+@rem them exist - it is about which binary you get and where it is on the PATH:\r
+@rem\r
+@rem - VS's cmake.exe is already ARM64, but it only lands on the PATH inside a\r
+@rem Developer Command Prompt. The build line further down assumes a plain\r
+@rem `cmake`, so install the standalone one to make that true in any shell.\r
+@rem - VS's bundled ninja.exe is x64 EVEN ON ARM64 (verified on this box), so it\r
+@rem runs under emulation. Ninja is re-invoked for every edge in the build\r
+@rem graph, which makes it the one tool here where emulation is actually paid\r
+@rem over and over, and ninja-winarm64.zip is a native build. Worth having.\r
+@rem\r
+@rem Which ninja wins inside a VS Developer Command Prompt: the native one. VS\r
+@rem adds its copy from Common7\Tools\vsdevcmd\ext\cmake.bat with\r
+@rem set "PATH=%PATH%;...\CMake\bin;...\CMake\Ninja"\r
+@rem which APPENDS, so the VS directories sit at the very end of the composed\r
+@rem PATH, behind every machine and user entry. setup-windows-no-uac.ps1 then\r
+@rem pins the native ninja's directory to the FRONT of the user PATH so the\r
+@rem margin does not depend on two append orders staying as they are.\r
+winget install Kitware.CMake\r
+winget install Ninja-build.Ninja\r
+\r
+@rem --- Second, independent Clang: compiler diversity ---\r
+@rem\r
+@rem The elevated half installs Visual Studio's Clang component (clang-cl, native\r
+@rem ARM64). This is a DIFFERENT LLVM: the upstream release, on its own schedule\r
+@rem and usually several major versions ahead of the one VS bundles, installed to\r
+@rem C:\Program Files\LLVM rather than inside the VS tree. Two Clang majors plus\r
+@rem MSVC over the same sources is the point - it is what catches the bugs a\r
+@rem single toolchain agrees with itself about.\r
+@rem\r
+@rem Native on ARM64: the manifest resolves to LLVM-<ver>-woa64.exe ("Windows on\r
+@rem Arm 64"), not the x64 build.\r
+@rem\r
+@rem PATH ORDER MATTERS if you use it. Should this installer put its bin on the\r
+@rem PATH, a bare `clang-cl` resolves to the upstream one while CMake's\r
+@rem `-T ClangCL` toolset keeps using the VS copy - so the two can be selected\r
+@rem independently, but only if you know which one you are asking for. Prefer\r
+@rem -DCMAKE_CXX_COMPILER with a full path when you care.\r
+winget install LLVM.LLVM\r
+\r
+@rem x64-only manifests: winget falls back to the x64 installer on ARM64 and these\r
+@rem run under Prism emulation. Harmless for what they do here - iperf3 is a\r
+@rem network benchmark bounded by the link, and AGI is an Android-side GPU\r
+@rem profiler whose work happens on the phone. Neither is CPU-bound on this box.\r
+winget install ar51an.iPerf3\r
+winget install Google.AndroidGPUInspector\r
+\r
+@rem NASM assembles x86/x86-64 only - there is no ARM64 target in it and no ARM64\r
+@rem build of it. Installed on ARM64 anyway (as emulated x64) because this box\r
+@rem still cross-compiles x86/x64 binaries, where NASM is the assembler that\r
+@rem builds them. If you only ever target ARM64, nothing here uses it: the ARM64\r
+@rem assembler is armasm64.exe, which ships with MSVC.\r
+winget install NASM.NASM\r
+\r
+@rem VirtualBox has no ARM64 Windows host build, and the x64 one cannot be made to\r
+@rem work by emulation: a hypervisor is kernel-mode, and its x64 driver will not\r
+@rem load on an ARM64 kernel. Installing it on ARM64 gets you a broken product and\r
+@rem a failed driver install, so skip it and say so.\r
+@rem\r
+@rem This is also what makes setup-windows-7-test-env.bat unreachable from an\r
+@rem ARM64 host: it prepares a Windows 7 *x86* guest, and neither VirtualBox nor\r
+@rem Hyper-V on ARM64 can run one.\r
+if "%IS_ARM64%"=="1" (\r
+ echo [setup-windows] Skipping Oracle.VirtualBox: no ARM64 Windows host build ^(x64 hypervisor drivers cannot load on an ARM64 kernel^).\r
+ echo [setup-windows] The Windows 7 x86 test-VM workflow ^(setup-windows-7-test-env.bat^) is therefore unavailable on this box.\r
+) else (\r
+ winget install Oracle.VirtualBox\r
+)\r
\r
@rem OpenCppCoverage: native (PE) line coverage for the C++ binaries. run-coverage-occ.py drives the\r
@rem pytest suite under it to produce an HTML report (the binaries under test build with PDBs,\r
@rem which it reads). The installer elevates via UAC.\r
+@rem\r
+@rem x86/x64 only, and unlike the other emulated tools that is a real limit rather\r
+@rem than a slowdown: it collects coverage by debugging the process under test and\r
+@rem stepping x86/x64 instructions, so it can cover the x86/x64 binaries this box\r
+@rem cross-compiles but NOT an ARM64 one. For ARM64 coverage, build the ARM64\r
+@rem binaries with /fsanitize-coverage or use the x64 build for the coverage run.\r
winget install OpenCppCoverage.OpenCppCoverage\r
+if "%IS_ARM64%"=="1" echo [setup-windows] NOTE: OpenCppCoverage is x86/x64-only - it cannot instrument ARM64 binaries. Run coverage against the x64 build.\r
+\r
+@rem --- WiX 5.0.2, pinned on purpose ---\r
+@rem WiX packages our proprietary software into MSIs, and the version is pinned to keep that\r
+@rem free of a fee. 5.0.2 is the last release distributed under the Microsoft Reciprocal\r
+@rem License alone. From 6.0 onward the package also carries OSMFEULA.txt, an Open Source\r
+@rem Maintenance Fee agreement: a monthly fee owed by anyone who uses the PREBUILT BINARIES\r
+@rem as part of revenue-generating activity and has annual gross revenue >= US$10,000.\r
+@rem\r
+@rem It is a fee for the binaries, not a restriction on what we ship - MS-RL is file-scoped\r
+@rem and never reached the MSIs WiX builds, under any version - but 5.0.2 owes nothing.\r
+@rem The 6.x/7.x SOURCE is still MS-RL too, so self-compiling is another way out; a pin is\r
+@rem the cheaper one. This replaces `winget install WiXToolset.WiXCLI`, which has no version\r
+@rem selector and so installs the latest (7.0.0 today, EULA and all).\r
+@rem\r
+@rem PIN THE MSBUILD SIDE TOO. A .wixproj referencing WixToolset.Sdk without a version\r
+@rem resolves to the latest - 7.x, same EULA - and nothing here constrains it. Pin it in the\r
+@rem project: <Project Sdk="WixToolset.Sdk/5.0.2">.\r
+@rem\r
+@rem dotnet.exe is called by full path: winget put the SDK on the machine PATH a few lines\r
+@rem ago, but this cmd session inherited its environment before that and cannot see it.\r
+@rem install-then-update is for re-runs - install fails once the tool is there, and update\r
+@rem then holds it at exactly 5.0.2 - which keeps this script idempotent like the rest.\r
+@rem\r
+@rem %ProgramFiles%\dotnet is the NATIVE SDK's root on every architecture, ARM64\r
+@rem included - what winget just installed. An x64 SDK installed alongside it on\r
+@rem an ARM64 box goes to %ProgramFiles%\dotnet\x64 instead, so fall back there\r
+@rem for a machine that only ever got the x64 one. Prefer the native root: the\r
+@rem ARM64 SDK runs the wix tool natively, and building an MSI is not something\r
+@rem worth doing through emulation.\r
+set "DOTNET_EXE=%ProgramFiles%\dotnet\dotnet.exe"\r
+if not exist "%DOTNET_EXE%" set "DOTNET_EXE=%ProgramFiles%\dotnet\x64\dotnet.exe"\r
+if not exist "%DOTNET_EXE%" echo [setup-windows] WARNING: dotnet.exe not found; skipping the WiX 5.0.2 pin.\r
+if not exist "%DOTNET_EXE%" goto :after_wix\r
+\r
+"%DOTNET_EXE%" tool install --global wix --version 5.0.2 || "%DOTNET_EXE%" tool update --global wix --version 5.0.2\r
+\r
+@rem Report what the pin actually produced. By full path again, and because the shim lands in\r
+@rem a directory this session's PATH predates: expect "5.0.2+<commit>", not 7.x.\r
+"%USERPROFILE%\.dotnet\tools\wix.exe" --version\r
+\r
+:after_wix\r
\r
@rem ---------------------------------------------------------------------------\r
@rem No package manager needed for the Windows build\r
@rem\r
@rem Just:\r
@rem cd windows && cmake -B build -G "Visual Studio 17 2022" -A x64 && cmake --build build --config Release\r
+@rem\r
+@rem -A selects the TARGET, independently of the host. On an ARM64 box the same\r
+@rem generator cross-compiles all three, and MSVC's ARM64-hosted toolchain is used\r
+@rem for each - nothing is emulated:\r
+@rem -A ARM64 native ARM64 binaries\r
+@rem -A x64 x64 binaries (run here under emulation)\r
+@rem -A Win32 x86 binaries\r
+@rem Use the generator matching the Visual Studio the elevated half installed -\r
+@rem "Visual Studio 17 2022" on x64, "Visual Studio 18 2026" on ARM64 - or just\r
+@rem let CMake pick the newest it finds.\r
@rem ---------------------------------------------------------------------------\r
\r
-@rem --- Elevated installs (VS2022, WDK, system tools) ---\r
+@rem --- Elevated installs (Visual Studio, WDK, system tools) ---\r
@rem The elevated script runs in its own window and logs to setup-windows-uac.log.\r
@rem -PassThru + $p.ExitCode propagates its real exit code back through to ERRORLEVEL.\r
set "UAC_LOG=%~dp0setup-windows-uac.log"\r
@rem py -m pip install "headroom-ai[all]"\r
@rem npm install headroom-ai\r
\r
-py -m pip install Pillow
\ No newline at end of file
+@rem Pillow publishes win_arm64 wheels alongside win_amd64, so `py` - the ARM64\r
+@rem Python winget just installed - gets a native wheel and never falls back to\r
+@rem building from source. Any package WITHOUT an ARM64 wheel does fall back, and\r
+@rem that source build needs the MSVC toolchain the elevated half installs.\r
+py -m pip install Pillow\r
+\r
+if "%IS_ARM64%"=="1" (\r
+ echo.\r
+ echo [setup-windows] ARM64 notes:\r
+ echo [setup-windows] native ARM64: Git, Python, .NET SDK, PowerShell, VS Code, Windows Terminal,\r
+ echo [setup-windows] WinMerge, Brave, Sysinternals ^(the *64a.exe variants^),\r
+ echo [setup-windows] Claude Code, CMake, Ninja, and the SDK/WPT tools.\r
+ echo [setup-windows] compilers : MSVC and clang-cl from Visual Studio 2026, plus upstream\r
+ echo [setup-windows] LLVM - all three native ARM64, two different Clang majors.\r
+ echo [setup-windows] emulated x64: iperf3, NASM, OpenCppCoverage, BinSkim, rsync.exe, AGI.\r
+ echo [setup-windows] unavailable : VirtualBox, the Windows 7 x86 test VM, Intel VTune,\r
+ echo [setup-windows] and the v141 / Windows XP targeting toolset.\r
+)\r