3 @rem ---------------------------------------------------------------------------
\r
4 @rem setup-windows.bat - provision a fresh Windows box for native development
\r
6 @rem Runs on x64 and on ARM64 (Windows 11 on Arm). See the ARM64 block below for
\r
7 @rem what changes on Arm silicon.
\r
8 @rem ---------------------------------------------------------------------------
\r
10 @rem ---------------------------------------------------------------------------
\r
11 @rem Host architecture
\r
13 @rem PROCESSOR_ARCHITECTURE alone is not enough: a 32-bit cmd.exe under emulation
\r
14 @rem reports x86 and stashes the real one in PROCESSOR_ARCHITEW6432. Check both,
\r
15 @rem so this is right however the script was launched.
\r
17 @rem The value drives two things below, and nothing else - winget resolves the
\r
18 @rem installer architecture on its own (native first, then whatever the box can
\r
19 @rem emulate), so the ordinary installs need no help:
\r
20 @rem - VirtualBox is skipped on ARM64 (see below)
\r
21 @rem - the summary tells you which tools you got as emulated x64
\r
22 @rem ---------------------------------------------------------------------------
\r
23 set "HOST_ARCH=%PROCESSOR_ARCHITECTURE%"
\r
24 if defined PROCESSOR_ARCHITEW6432 set "HOST_ARCH=%PROCESSOR_ARCHITEW6432%"
\r
26 if /i "%HOST_ARCH%"=="ARM64" set "IS_ARM64=1"
\r
27 echo [setup-windows] Host architecture: %HOST_ARCH%
\r
29 @rem ---------------------------------------------------------------------------
\r
30 @rem Can this account elevate? Worked out ONCE, here, because it gates two very
\r
31 @rem different things: the elevated half far below, and a handful of the "per-user"
\r
32 @rem winget installs just after this, which are per-user in name only.
\r
34 @rem ALREADY - already elevated. IsInRole(Administrator) is false for an admin
\r
35 @rem running unelevated under UAC, so this means actually elevated,
\r
36 @rem not merely capable of it.
\r
37 @rem PROMPT - not elevated, UAC on, so elevation can be requested.
\r
38 @rem NOLUA - UAC is off machine-wide (EnableLUA = 0) AND this is not an
\r
39 @rem administrator. Elevation is impossible, not merely declined:
\r
40 @rem Windows has no prompt to offer. Note that with UAC off,
\r
41 @rem `Start-Process -Verb RunAs` does not fail - it is silently
\r
42 @rem ignored, runs the child with the caller's own token, and reports
\r
43 @rem success, which is why this needs detecting rather than trying.
\r
44 @rem ---------------------------------------------------------------------------
\r
46 for /f "usebackq tokens=*" %%A in (`powershell -NoProfile -ExecutionPolicy Bypass -Command "$id=[Security.Principal.WindowsIdentity]::GetCurrent(); if (([Security.Principal.WindowsPrincipal]$id).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { 'ALREADY' } elseif ((Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -ErrorAction SilentlyContinue).EnableLUA -eq 0) { 'NOLUA' } else { 'PROMPT' }"`) do set "ELEV=%%A"
\r
47 echo [setup-windows] Elevation: %ELEV%
\r
48 if "%ELEV%"=="NOLUA" (
\r
49 echo [setup-windows] This account cannot elevate ^(UAC off, not an administrator^). Packages that
\r
50 echo [setup-windows] need a machine-wide install will be SKIPPED rather than left to fail; details
\r
51 echo [setup-windows] at each one, and a summary before the elevated half.
\r
54 @rem --- Non-admin (per-user) winget installs ---
\r
56 @rem No --architecture anywhere on purpose. winget already picks the best
\r
57 @rem installer the manifest offers for this machine - arm64, else x64, else x86 -
\r
58 @rem and pinning it would turn "no native build, use the emulated one" into a
\r
61 @rem These all publish real ARM64 installers, so on an ARM64 box every one of
\r
62 @rem them lands as a native ARM64 binary with no emulation involved.
\r
64 @rem The Sysinternals packages are a multi-architecture ZIP rather than an
\r
65 @rem installer, so the ARM64 build is IN there but is not the default-named exe:
\r
66 @rem the zip holds procexp.exe (x86), procexp64.exe (x64) and procexp64a.exe
\r
67 @rem (ARM64). On ARM64, run the *64a.exe variants - plain procexp.exe is the x86
\r
68 @rem one and will run emulated.
\r
69 winget install Anthropic.ClaudeCode
\r
70 winget install Brave.Brave
\r
71 winget install Git.Git
\r
72 winget install Microsoft.PowerShell Microsoft.Sysinternals.ProcessExplorer Microsoft.Sysinternals.ProcessMonitor Microsoft.Sysinternals.SDelete Microsoft.VisualStudioCode Microsoft.WindowsTerminal
\r
73 winget install Python.Python.3.13
\r
75 @rem WinMerge is the one package here where winget's own preference order picks
\r
76 @rem the WRONG architecture, and it is worth knowing why: upstream publishes the
\r
77 @rem ARM64 build as a MACHINE-scope installer (WinMerge-<ver>-ARM64-Setup.exe) and
\r
78 @rem the x64 build as a PER-USER one (WinMerge-<ver>-x64-PerUser-Setup.exe). Run
\r
79 @rem unelevated, winget's scope preference beats its architecture preference and
\r
80 @rem you silently get the emulated x64 build.
\r
82 @rem So ask for arm64 explicitly, and fall back to the default when that cannot be
\r
83 @rem installed - which is exactly the standard-user case, where the machine-scope
\r
84 @rem installer has nowhere to go. The fallback is the x64 build under emulation:
\r
85 @rem a diff tool is not a hot path, and a working WinMerge beats none. The
\r
86 @rem architecture audit at the end of setup-windows-no-uac.ps1 reports which one
\r
87 @rem you ended up with.
\r
88 if "%IS_ARM64%"=="1" (
\r
89 winget install WinMerge.WinMerge --architecture arm64 || winget install WinMerge.WinMerge
\r
91 winget install WinMerge.WinMerge
\r
94 @rem --- Build drivers, standalone and native ---
\r
96 @rem CMake and Ninja BOTH ship with Visual Studio, so this is not about making
\r
97 @rem them exist - it is about which binary you get and where it is on the PATH:
\r
99 @rem - VS's cmake.exe is already ARM64, but it only lands on the PATH inside a
\r
100 @rem Developer Command Prompt. The build line further down assumes a plain
\r
101 @rem `cmake`, so install the standalone one to make that true in any shell.
\r
102 @rem - VS's bundled ninja.exe is x64 EVEN ON ARM64 (verified on this box), so it
\r
103 @rem runs under emulation. Ninja is re-invoked for every edge in the build
\r
104 @rem graph, which makes it the one tool here where emulation is actually paid
\r
105 @rem over and over, and ninja-winarm64.zip is a native build. Worth having.
\r
107 @rem Which ninja wins inside a VS Developer Command Prompt: the native one. VS
\r
108 @rem adds its copy from Common7\Tools\vsdevcmd\ext\cmake.bat with
\r
109 @rem set "PATH=%PATH%;...\CMake\bin;...\CMake\Ninja"
\r
110 @rem which APPENDS, so the VS directories sit at the very end of the composed
\r
111 @rem PATH, behind every machine and user entry. setup-windows-no-uac.ps1 then
\r
112 @rem pins the native ninja's directory to the FRONT of the user PATH so the
\r
113 @rem margin does not depend on two append orders staying as they are.
\r
115 @rem Ninja here, CMake in the machine-wide group below: Ninja is a portable zip
\r
116 @rem winget unpacks into the user profile, CMake is an MSI that installs for the
\r
117 @rem whole machine.
\r
118 winget install Ninja-build.Ninja
\r
120 @rem --- Second, independent Clang: compiler diversity ---
\r
122 @rem The elevated half installs Visual Studio's Clang component (clang-cl, native
\r
123 @rem ARM64). This is a DIFFERENT LLVM: the upstream release, on its own schedule
\r
124 @rem and usually several major versions ahead of the one VS bundles, installed to
\r
125 @rem C:\Program Files\LLVM rather than inside the VS tree. Two Clang majors plus
\r
126 @rem MSVC over the same sources is the point - it is what catches the bugs a
\r
127 @rem single toolchain agrees with itself about.
\r
129 @rem Native on ARM64: the manifest resolves to LLVM-<ver>-woa64.exe ("Windows on
\r
130 @rem Arm 64"), not the x64 build.
\r
132 @rem PATH ORDER MATTERS if you use it. Should this installer put its bin on the
\r
133 @rem PATH, a bare `clang-cl` resolves to the upstream one while CMake's
\r
134 @rem `-T ClangCL` toolset keeps using the VS copy - so the two can be selected
\r
135 @rem independently, but only if you know which one you are asking for. Prefer
\r
136 @rem -DCMAKE_CXX_COMPILER with a full path when you care.
\r
137 winget install LLVM.LLVM
\r
139 @rem x64-only manifest: winget falls back to the x64 installer on ARM64 and it runs
\r
140 @rem under Prism emulation. Harmless for what it does here - iperf3 is a network
\r
141 @rem benchmark bounded by the link, not by CPU.
\r
142 winget install ar51an.iPerf3
\r
144 @rem NASM assembles x86/x86-64 only - there is no ARM64 target in it and no ARM64
\r
145 @rem build of it. Installed on ARM64 anyway (as emulated x64) because this box
\r
146 @rem still cross-compiles x86/x64 binaries, where NASM is the assembler that
\r
147 @rem builds them. If you only ever target ARM64, nothing here uses it: the ARM64
\r
148 @rem assembler is armasm64.exe, which ships with MSVC.
\r
149 winget install NASM.NASM
\r
151 @rem VirtualBox has no ARM64 Windows host build, and the x64 one cannot be made to
\r
152 @rem work by emulation: a hypervisor is kernel-mode, and its x64 driver will not
\r
153 @rem load on an ARM64 kernel. Installing it on ARM64 gets you a broken product and
\r
154 @rem a failed driver install, so skip it and say so.
\r
156 @rem This is also what makes setup-windows-7-test-env.bat unreachable from an
\r
157 @rem ARM64 host: it prepares a Windows 7 *x86* guest, and neither VirtualBox nor
\r
158 @rem Hyper-V on ARM64 can run one.
\r
159 if "%IS_ARM64%"=="1" (
\r
160 echo [setup-windows] Skipping Oracle.VirtualBox: no ARM64 Windows host build ^(x64 hypervisor drivers cannot load on an ARM64 kernel^).
\r
161 echo [setup-windows] The Windows 7 x86 test-VM workflow ^(setup-windows-7-test-env.bat^) is therefore unavailable on this box.
\r
163 winget install Oracle.VirtualBox
\r
166 @rem ---------------------------------------------------------------------------
\r
167 @rem Machine-wide installers, despite sitting in the "per-user" section
\r
169 @rem These four are not per-user at all. On an account that cannot elevate they
\r
170 @rem fail on every run, with installer exit codes that say nothing useful:
\r
171 @rem Microsoft.DotNet.SDK.10 exit 5 (ERROR_ACCESS_DENIED)
\r
172 @rem Kitware.CMake exit 1603 (generic MSI failure)
\r
173 @rem Google.AndroidGPUInspector exit 1603
\r
174 @rem OpenCppCoverage exit 1 (its installer self-elevates)
\r
176 @rem Grouped and skipped outright where elevation is impossible. Attempting a
\r
177 @rem guaranteed failure four times per run - and paying the download for it -
\r
178 @rem teaches nobody anything, and the four opaque error codes bury the one line
\r
179 @rem that matters. On an account that can elevate they run exactly as before.
\r
181 @rem NOTE none of these is a build-blocker: the .NET SDK is only here for the WiX
\r
182 @rem MSI tooling, CMake also ships inside Visual Studio, AGI profiles Android
\r
183 @rem devices, and OpenCppCoverage cannot instrument ARM64 binaries anyway.
\r
184 @rem ---------------------------------------------------------------------------
\r
185 if "%ELEV%"=="NOLUA" (
\r
187 echo [setup-windows] Skipping the machine-wide installers - this account cannot elevate:
\r
188 echo [setup-windows] Microsoft.DotNet.SDK.10, Kitware.CMake, Google.AndroidGPUInspector, OpenCppCoverage.
\r
189 echo [setup-windows] None blocks a build. Re-run from an administrator account to get them.
\r
191 goto :after_admin_pkgs
\r
194 winget install Microsoft.DotNet.SDK.10
\r
195 winget install Kitware.CMake
\r
196 winget install Google.AndroidGPUInspector
\r
198 @rem OpenCppCoverage: native (PE) line coverage for the C++ binaries. run-coverage-occ.py drives the
\r
199 @rem pytest suite under it to produce an HTML report (the binaries under test build with PDBs,
\r
200 @rem which it reads). The installer elevates via UAC.
\r
202 @rem x86/x64 only, and unlike the other emulated tools that is a real limit rather
\r
203 @rem than a slowdown: it collects coverage by debugging the process under test and
\r
204 @rem stepping x86/x64 instructions, so it can cover the x86/x64 binaries this box
\r
205 @rem cross-compiles but NOT an ARM64 one. For ARM64 coverage, build the ARM64
\r
206 @rem binaries with /fsanitize-coverage or use the x64 build for the coverage run.
\r
207 winget install OpenCppCoverage.OpenCppCoverage
\r
210 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
212 @rem --- WiX 5.0.2, pinned on purpose ---
\r
213 @rem WiX packages our proprietary software into MSIs, and the version is pinned to keep that
\r
214 @rem free of a fee. 5.0.2 is the last release distributed under the Microsoft Reciprocal
\r
215 @rem License alone. From 6.0 onward the package also carries OSMFEULA.txt, an Open Source
\r
216 @rem Maintenance Fee agreement: a monthly fee owed by anyone who uses the PREBUILT BINARIES
\r
217 @rem as part of revenue-generating activity and has annual gross revenue >= US$10,000.
\r
219 @rem It is a fee for the binaries, not a restriction on what we ship - MS-RL is file-scoped
\r
220 @rem and never reached the MSIs WiX builds, under any version - but 5.0.2 owes nothing.
\r
221 @rem The 6.x/7.x SOURCE is still MS-RL too, so self-compiling is another way out; a pin is
\r
222 @rem the cheaper one. This replaces `winget install WiXToolset.WiXCLI`, which has no version
\r
223 @rem selector and so installs the latest (7.0.0 today, EULA and all).
\r
225 @rem PIN THE MSBUILD SIDE TOO. A .wixproj referencing WixToolset.Sdk without a version
\r
226 @rem resolves to the latest - 7.x, same EULA - and nothing here constrains it. Pin it in the
\r
227 @rem project: <Project Sdk="WixToolset.Sdk/5.0.2">.
\r
229 @rem dotnet.exe is called by full path: winget put the SDK on the machine PATH a few lines
\r
230 @rem ago, but this cmd session inherited its environment before that and cannot see it.
\r
231 @rem install-then-update is for re-runs - install fails once the tool is there, and update
\r
232 @rem then holds it at exactly 5.0.2 - which keeps this script idempotent like the rest.
\r
234 @rem %ProgramFiles%\dotnet is the NATIVE SDK's root on every architecture, ARM64
\r
235 @rem included - what winget just installed. An x64 SDK installed alongside it on
\r
236 @rem an ARM64 box goes to %ProgramFiles%\dotnet\x64 instead, so fall back there
\r
237 @rem for a machine that only ever got the x64 one. Prefer the native root: the
\r
238 @rem ARM64 SDK runs the wix tool natively, and building an MSI is not something
\r
239 @rem worth doing through emulation.
\r
240 set "DOTNET_EXE=%ProgramFiles%\dotnet\dotnet.exe"
\r
241 if not exist "%DOTNET_EXE%" set "DOTNET_EXE=%ProgramFiles%\dotnet\x64\dotnet.exe"
\r
242 if not exist "%DOTNET_EXE%" echo [setup-windows] WARNING: dotnet.exe not found; skipping the WiX 5.0.2 pin.
\r
243 if not exist "%DOTNET_EXE%" goto :after_wix
\r
245 "%DOTNET_EXE%" tool install --global wix --version 5.0.2 || "%DOTNET_EXE%" tool update --global wix --version 5.0.2
\r
247 @rem Report what the pin actually produced. By full path again, and because the shim lands in
\r
248 @rem a directory this session's PATH predates: expect "5.0.2+<commit>", not 7.x.
\r
249 "%USERPROFILE%\.dotnet\tools\wix.exe" --version
\r
253 @rem ---------------------------------------------------------------------------
\r
254 @rem No package manager needed for the Windows build
\r
257 @rem cd windows && cmake -B build -G "Visual Studio 17 2022" -A x64 && cmake --build build --config Release
\r
259 @rem -A selects the TARGET, independently of the host. On an ARM64 box the same
\r
260 @rem generator cross-compiles all three, and MSVC's ARM64-hosted toolchain is used
\r
261 @rem for each - nothing is emulated:
\r
262 @rem -A ARM64 native ARM64 binaries
\r
263 @rem -A x64 x64 binaries (run here under emulation)
\r
264 @rem -A Win32 x86 binaries
\r
265 @rem Use the generator matching the Visual Studio the elevated half installed -
\r
266 @rem "Visual Studio 17 2022" on x64, "Visual Studio 18 2026" on ARM64 - or just
\r
267 @rem let CMake pick the newest it finds.
\r
268 @rem ---------------------------------------------------------------------------
\r
270 @rem --- Elevated installs (Visual Studio, WDK, system tools) ---
\r
271 @rem The elevated script runs in its own window and logs to setup-windows-uac.log.
\r
272 @rem -PassThru + $p.ExitCode propagates its real exit code back through to ERRORLEVEL.
\r
273 set "UAC_LOG=%~dp0setup-windows-uac.log"
\r
274 if exist "%UAC_LOG%" del "%UAC_LOG%"
\r
276 @rem %ELEV% was worked out at the top of this script - see the comment there for
\r
277 @rem why `Start-Process -Verb RunAs` cannot be trusted to report this itself.
\r
278 if "%ELEV%"=="NOLUA" goto :elev_impossible
\r
279 if "%ELEV%"=="ALREADY" goto :elev_direct
\r
281 @rem Not elevated, UAC is on: request it. Expect a prompt.
\r
282 echo [setup-windows] Requesting elevation ^(expect a UAC prompt^)...
\r
283 powershell -NoProfile -Command "$p = Start-Process powershell -Verb RunAs -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File','""%~dp0setup-windows-with-uac.ps1""' -Wait -PassThru; exit $p.ExitCode"
\r
284 set "UAC_RC=%ERRORLEVEL%"
\r
288 echo [setup-windows] Already running elevated; running the elevated half directly.
\r
289 powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0setup-windows-with-uac.ps1"
\r
290 set "UAC_RC=%ERRORLEVEL%"
\r
295 echo [setup-windows] SKIPPING the elevated half: this account cannot elevate.
\r
296 echo [setup-windows] UAC is disabled machine-wide ^(EnableLUA = 0^) and you are not an administrator,
\r
297 echo [setup-windows] so Windows offers no way to elevate - there is no prompt to accept. With UAC off,
\r
298 echo [setup-windows] 'Start-Process -Verb RunAs' is silently ignored and reports success, which is why
\r
299 echo [setup-windows] this used to look like a cancelled prompt.
\r
300 echo [setup-windows]
\r
301 echo [setup-windows] Not installed: Visual Studio components ^(including clang-cl^), the WDK,
\r
302 echo [setup-windows] rsync, and the OpenSSH server. Everything per-user above is unaffected.
\r
303 echo [setup-windows]
\r
304 echo [setup-windows] To finish the box, either sign in to an administrator account and re-run this
\r
305 echo [setup-windows] script, or have an administrator run setup-windows-with-uac.ps1 there. Then
\r
306 echo [setup-windows] re-run setup-windows-no-uac.ps1 as yourself, so the per-user PATH and .gitconfig
\r
307 echo [setup-windows] land in YOUR profile rather than the administrator's.
\r
309 set "UAC_RC=SKIPPED"
\r
313 @rem --- Surface the elevated session's output (its window has already closed) ---
\r
315 @rem A missing log is NOT self-explanatory, so do not guess at one cause. The
\r
316 @rem elevated script writes its transcript as almost its first act, so no log
\r
317 @rem means it never got as far as running: either the prompt was declined, or it
\r
318 @rem started unelevated and stopped on its own #Requires line. Which of those it
\r
319 @rem was is already known from %ELEV%, so report that instead of speculating.
\r
320 if "%UAC_RC%"=="SKIPPED" goto :after_uac_log
\r
321 if exist "%UAC_LOG%" (
\r
323 echo ===== elevated setup log ^(%UAC_LOG%^) =====
\r
325 echo ===== end of elevated setup log =====
\r
327 echo [setup-windows] WARNING: no elevated log found at "%UAC_LOG%".
\r
328 if "%ELEV%"=="PROMPT" echo [setup-windows] The elevated window never started - the UAC prompt was most likely declined.
\r
329 if "%ELEV%"=="ALREADY" echo [setup-windows] The elevated half exited before writing its transcript; see its output above.
\r
333 @rem --- Non-elevated PowerShell half ---
\r
334 @rem WinMerge on the user PATH, BinSkim, and the global git config (identity +
\r
335 @rem core.sshCommand -> a Win32-OpenSSH client, so git shares the Windows
\r
336 @rem ssh-agent). EDIT THE GIT IDENTITY at the top of setup-windows-no-uac.ps1
\r
337 @rem before the first run.
\r
339 @rem Deliberately NOT elevated: every step writes per-user state (the HKCU PATH,
\r
340 @rem the .gitconfig under %USERPROFILE%), which the elevated half would write to
\r
341 @rem the administrator profile instead.
\r
343 @rem AFTER the elevated half on purpose: core.sshCommand prefers the ssh.exe that
\r
344 @rem half unpacks beside rsync.exe - a push through the in-box client is capped
\r
345 @rem at ~17MB/s - and it can only prefer it once it is on disk. Run either way,
\r
346 @rem including when the elevated half failed above: nothing here depends on it,
\r
347 @rem and the fallback is the in-box client that Windows already has.
\r
349 @rem Non-fatal: these are conveniences, and the elevated half is the part worth
\r
350 @rem the UAC prompt. A failure warns and provisioning continues.
\r
351 powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0setup-windows-no-uac.ps1"
\r
352 if not "%ERRORLEVEL%"=="0" echo [setup-windows] WARNING: setup-windows-no-uac.ps1 reported a failure ^(see above^); continuing.
\r
354 @rem Skipping the elevated half is a reported, understood outcome on a box where
\r
355 @rem elevation is impossible - not a failure to exit non-zero over. The per-user
\r
356 @rem provisioning above did run, and re-running from an administrator account is
\r
357 @rem the documented next step.
\r
358 if "%UAC_RC%"=="SKIPPED" goto :uac_reported
\r
359 if not "%UAC_RC%"=="0" (
\r
361 echo [setup-windows] ELEVATED SETUP FAILED ^(exit code %UAC_RC%^). See log above.
\r
365 echo [setup-windows] Elevated setup completed successfully.
\r
369 if "%UAC_RC%"=="SKIPPED" echo.
\r
370 if "%UAC_RC%"=="SKIPPED" echo [setup-windows] Per-user setup complete; the elevated half was skipped ^(see above^).
\r
372 @rem Removed: this doesn't work as well as I hoped, maybe try again later
\r
373 @rem -- Install Headroom ---
\r
374 @rem py -m pip install "headroom-ai[all]"
\r
375 @rem npm install headroom-ai
\r
377 @rem Pillow publishes win_arm64 wheels alongside win_amd64, so `py` - the ARM64
\r
378 @rem Python winget just installed - gets a native wheel and never falls back to
\r
379 @rem building from source. Any package WITHOUT an ARM64 wheel does fall back, and
\r
380 @rem that source build needs the MSVC toolchain the elevated half installs.
\r
381 py -m pip install Pillow
\r
383 if "%IS_ARM64%"=="1" (
\r
385 echo [setup-windows] ARM64 notes:
\r
386 echo [setup-windows] native ARM64: Git, Python, .NET SDK, PowerShell, VS Code, Windows Terminal,
\r
387 echo [setup-windows] WinMerge, Brave, Sysinternals ^(the *64a.exe variants^),
\r
388 echo [setup-windows] Claude Code, CMake, Ninja, and the SDK/WPT tools.
\r
389 echo [setup-windows] compilers : MSVC and clang-cl from Visual Studio 2026, plus upstream
\r
390 echo [setup-windows] LLVM - all three native ARM64, two different Clang majors.
\r
391 echo [setup-windows] emulated x64: iperf3, NASM, OpenCppCoverage, BinSkim, rsync.exe, AGI.
\r
392 echo [setup-windows] unavailable : VirtualBox, the Windows 7 x86 test VM, Intel VTune,
\r
393 echo [setup-windows] and the v141 / Windows XP targeting toolset.
\r
395 @rem The list above is what this script PROVIDES on ARM64, not necessarily what
\r
396 @rem landed on this run - so point at the audit, which reports the actual state.
\r
397 if "%ELEV%"=="NOLUA" (
\r
398 echo [setup-windows] NOT on this box: everything needing elevation was skipped, including
\r
399 echo [setup-windows] Visual Studio's clang-cl, the .NET SDK and CMake. The
\r
400 echo [setup-windows] architecture audit above lists what is really installed.
\r