]> vilimpoc.org git repositories - dotfiles/commitdiff
setup-windows: Msys2 step - MSYS2 with MinGW-w64 GCC, per-user, no elevation master
authorMax Vilimpoc <max@vilimpoc.org>
Sat, 17 Oct 2026 17:13:22 +0000 (19:13 +0200)
committerMax Vilimpoc <max@vilimpoc.org>
Sat, 17 Oct 2026 17:13:22 +0000 (19:13 +0200)
Unpacks the MSYS2 base self-extracting archive into %LOCALAPPDATA%\msys64
(the winget package would run the installer machine-wide into C:\msys64),
updates it, and installs GCC for ucrt64 (x86_64) and mingw32 (i686,
msvcrt - the environment that can still target Windows XP). Same
toolchains as GitHub's windows-latest runner. Nothing goes on the PATH;
projects pick an environment's bin directory by full path. x64-only.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
README.md
setup-windows-steps.ps1
setup-windows.bat

index 67e6a3b38c50f1f35a74545f72f8a59384cccb7f..8c4d631ac8edd4d3e86c95570b374e7a60f3f36b 100644 (file)
--- a/README.md
+++ b/README.md
@@ -145,6 +145,7 @@ missing or out of date.
 | winget packages | `winget install` on a package winget can see is installed upgrades it when a newer version exists and otherwise does nothing — winget's own default. `--force`, which would install regardless, is never used. |
 | `ClaudeCode` | Anthropic's installer always downloads and reinstalls, so `setup-windows-current.ps1` asks first: is `%USERPROFILE%\.local\bin\claude.exe` the latest release — the version the installer's own endpoint names — and the build for this host? Only both skip it. |
 | `NASM` | Its per-user fallback install registers nothing, so winget cannot see it and would rerun the installer every time. `setup-windows-current.ps1` compares that `nasm.exe` with the version winget offers. A machine-wide NASM is left to winget. |
 | winget packages | `winget install` on a package winget can see is installed upgrades it when a newer version exists and otherwise does nothing — winget's own default. `--force`, which would install regardless, is never used. |
 | `ClaudeCode` | Anthropic's installer always downloads and reinstalls, so `setup-windows-current.ps1` asks first: is `%USERPROFILE%\.local\bin\claude.exe` the latest release — the version the installer's own endpoint names — and the build for this host? Only both skip it. |
 | `NASM` | Its per-user fallback install registers nothing, so winget cannot see it and would rerun the installer every time. `setup-windows-current.ps1` compares that `nasm.exe` with the version winget offers. A machine-wide NASM is left to winget. |
+| `Msys2` | The base archive is downloaded only when `%LOCALAPPDATA%\msys64\usr\bin\pacman.exe` is missing. Otherwise `pacman -Syuu` updates what is there, and `pacman -S --needed` leaves the GCC packages alone when they are already installed. |
 | `Rustup` | Needs no help: rustup registers itself under the manifest's product code and rewrites its version when it updates itself, so winget sees what is really there. |
 | `AndroidStudio` | Installed only when it is missing. Studio updates itself in the app, and winget's package is marked never to upgrade it; the check keeps winget from installing over a Studio it cannot match to its package, as on a box where Studio was installed some other way. |
 | `WiX` | Skipped when 5.0.2 is already in the .NET global tool store. |
 | `Rustup` | Needs no help: rustup registers itself under the manifest's product code and rewrites its version when it updates itself, so winget sees what is really there. |
 | `AndroidStudio` | Installed only when it is missing. Studio updates itself in the app, and winget's package is marked never to upgrade it; the check keeps winget from installing over a Studio it cannot match to its package, as on a box where Studio was installed some other way. |
 | `WiX` | Skipped when 5.0.2 is already in the .NET global tool store. |
@@ -390,6 +391,16 @@ missing or out of date.
   emulation on ARM64, which every Windows on Arm has; the audit lists it as
   expected. It stays on ARM64 for the same reason `iperf3` does: it is bound by
   the link to the device, not by the CPU.
   emulation on ARM64, which every Windows on Arm has; the audit lists it as
   expected. It stays on ARM64 for the same reason `iperf3` does: it is bound by
   the link to the device, not by the CPU.
+- **MSYS2 and MinGW-w64 GCC** (`Msys2`) go into `%LOCALAPPDATA%\msys64`, per-user,
+  with no elevation: the MSYS2 base self-extracting archive unpacks wherever it
+  is pointed, whereas the winget package runs the installer machine-wide into
+  `C:\msys64`. Two environments get GCC: `ucrt64` (x86_64, links the UCRT) and
+  `mingw32` (i686, links `msvcrt.dll`, the one that can still target Windows XP).
+  These are the same toolchains GitHub's `windows-latest` runner carries, so a
+  build that works here works there. Nothing is added to the `PATH`: the
+  environments' `bin` directories hold same-named `gcc`, `ld` and `windres`, so a
+  project names the one it wants by full path, e.g.
+  `%LOCALAPPDATA%\msys64\mingw32\bin`.
 - **Android Studio and the Android SDK** are separate steps. Studio
   (`Google.AndroidStudio`) is machine-wide — its installer elevates itself — and
   is installed only when missing, since it updates itself. The SDK is per-user,
 - **Android Studio and the Android SDK** are separate steps. Studio
   (`Google.AndroidStudio`) is machine-wide — its installer elevates itself — and
   is installed only when missing, since it updates itself. The SDK is per-user,
@@ -495,6 +506,7 @@ duplicates it or that exists only as an x64 binary.**
 | `WinMerge.WinMerge` | `setup-windows.bat` | ARM64 ships as a **machine-scope** installer only, so an unelevated `winget` can install nothing but the emulated x64 build |
 | `LLVM.LLVM` | `setup-windows.bat` | second Clang, dropped along with VS's `clang-cl` |
 | `NASM.NASM` | `setup-windows.bat` | x86/x86-64 assembler with no ARM64 target; MSVC's `armasm64.exe` is the native one |
 | `WinMerge.WinMerge` | `setup-windows.bat` | ARM64 ships as a **machine-scope** installer only, so an unelevated `winget` can install nothing but the emulated x64 build |
 | `LLVM.LLVM` | `setup-windows.bat` | second Clang, dropped along with VS's `clang-cl` |
 | `NASM.NASM` | `setup-windows.bat` | x86/x86-64 assembler with no ARM64 target; MSVC's `armasm64.exe` is the native one |
+| MSYS2 (`Msys2`) | `setup-windows.bat` | its base system is x86_64 and would run emulated, and the Windows XP target it is installed for is x64-box work |
 | `Google.AndroidGPUInspector` | `setup-windows.bat` | x64-only, and it profiles Android devices rather than anything compiled here |
 | `OpenCppCoverage` | `setup-windows.bat` | collects coverage by stepping x86/x64 instructions, so it cannot instrument an ARM64 binary at all |
 | VS Clang/LLVM component | `setup-windows-with-uac.ps1` | see below |
 | `Google.AndroidGPUInspector` | `setup-windows.bat` | x64-only, and it profiles Android devices rather than anything compiled here |
 | `OpenCppCoverage` | `setup-windows.bat` | collects coverage by stepping x86/x64 instructions, so it cannot instrument an ARM64 binary at all |
 | VS Clang/LLVM component | `setup-windows-with-uac.ps1` | see below |
index 765bb37ba9538be278215e92179b1c49d4824436..f311b41b0142bc637ebd510695d12fda122f8868 100644 (file)
@@ -119,6 +119,9 @@ function Get-SetupCatalog {
         New-SetupStep PlatformTools       U bat -Package Google.PlatformTools -Text 'Android SDK Platform-Tools: adb, fastboot (an x86 build)'
         New-SetupStep NASM                U bat -Package NASM.NASM `
             -X64Only 'x86/x64-only assembler; MSVC armasm64 is the native one'
         New-SetupStep PlatformTools       U bat -Package Google.PlatformTools -Text 'Android SDK Platform-Tools: adb, fastboot (an x86 build)'
         New-SetupStep NASM                U bat -Package NASM.NASM `
             -X64Only 'x86/x64-only assembler; MSVC armasm64 is the native one'
+        # Not winget: its package runs the machine-wide installer into C:\msys64.
+        New-SetupStep Msys2               U bat -Text 'MSYS2 into %LOCALAPPDATA%\msys64 (no admin), with MinGW-w64 GCC: ucrt64 (x64) and mingw32 (i686, msvcrt, for XP targets)' `
+            -X64Only 'its base system is x86_64 (emulated on Arm), and the XP target it is here for is x64-box work'
         New-SetupStep VirtualBox          U bat -Package Oracle.VirtualBox -Text 'for the Windows 7 test VM' `
             -X64Only 'no ARM64 host build, so no Windows 7 x86 test VM either' `
             -NotInVM 'the test VMs belong on the physical host, not nested in a guest'
         New-SetupStep VirtualBox          U bat -Package Oracle.VirtualBox -Text 'for the Windows 7 test VM' `
             -X64Only 'no ARM64 host build, so no Windows 7 x86 test VM either' `
             -NotInVM 'the test VMs belong on the physical host, not nested in a guest'
index d49edd4b5c52585d9d78e83fb4296b88f1e9171d..eb145ec0433ee6de33202ac53c509c8070fbb5d3 100644 (file)
@@ -376,6 +376,46 @@ call :want NASM || goto :after_nasm
 if not "%ERRORLEVEL%"=="0" call :winget NASM NASM.NASM\r
 :after_nasm\r
 \r
 if not "%ERRORLEVEL%"=="0" call :winget NASM NASM.NASM\r
 :after_nasm\r
 \r
+@rem MSYS2, per-user, for the MinGW-w64 GCC toolchains - the same ones GitHub's\r
+@rem windows-latest runner carries under C:\msys64, so a build that works here\r
+@rem works there. Two environments are installed:\r
+@rem   ucrt64   x86_64, links the UCRT        - the modern target\r
+@rem   mingw32  i686, links msvcrt.dll        - the one that can still target\r
+@rem                                            Windows XP\r
+@rem\r
+@rem Not through winget: the MSYS2.MSYS2 package runs the GUI installer, which\r
+@rem installs machine-wide into C:\msys64 by default. The self-extracting\r
+@rem archive (7-Zip SFX) needs no elevation and unpacks wherever it is pointed,\r
+@rem here %LOCALAPPDATA%\msys64. Nothing is put on the PATH on purpose: the\r
+@rem environments' bin directories carry same-named exes (gcc, ld, windres) and\r
+@rem a project picks one by its full path, e.g. %LOCALAPPDATA%\msys64\mingw32\bin.\r
+@rem\r
+@rem Re-running: the archive is downloaded only when pacman is missing; otherwise\r
+@rem `pacman -Syu` updates what is there and `--needed` leaves installed packages\r
+@rem alone. The first -Syu after a fresh unpack may replace the MSYS2 runtime and\r
+@rem end the shell on purpose, which is why it runs twice.\r
+call :want Msys2 || goto :after_msys2\r
+set "MSYS2_ROOT=%LOCALAPPDATA%\msys64"\r
+if exist "%MSYS2_ROOT%\usr\bin\pacman.exe" goto :msys2_packages\r
+echo [setup-windows] Msys2: downloading the MSYS2 base archive\r
+"%PS64%" -NoProfile -ExecutionPolicy Bypass -Command "$ProgressPreference='SilentlyContinue'; Invoke-WebRequest -Uri 'https://github.com/msys2/msys2-installer/releases/latest/download/msys2-base-x86_64-latest.sfx.exe' -OutFile \"$env:TEMP\msys2-base.sfx.exe\""\r
+if not exist "%TEMP%\msys2-base.sfx.exe" ( echo [setup-windows] Msys2: download failed & goto :after_msys2 )\r
+echo [setup-windows] Msys2: unpacking into %MSYS2_ROOT%\r
+"%TEMP%\msys2-base.sfx.exe" -y -o"%LOCALAPPDATA%" >nul\r
+del /q "%TEMP%\msys2-base.sfx.exe" 2>nul\r
+if not exist "%MSYS2_ROOT%\usr\bin\pacman.exe" ( echo [setup-windows] Msys2: unpack failed & goto :after_msys2 )\r
+@rem First start: creates the home directory and the key ring.\r
+"%MSYS2_ROOT%\usr\bin\bash.exe" -lc "true"\r
+:msys2_packages\r
+echo [setup-windows] Msys2: updating the base system\r
+"%MSYS2_ROOT%\usr\bin\bash.exe" -lc "pacman -Syuu --noconfirm"\r
+"%MSYS2_ROOT%\usr\bin\bash.exe" -lc "pacman -Syuu --noconfirm"\r
+echo [setup-windows] Msys2: MinGW-w64 GCC for ucrt64 and mingw32\r
+"%MSYS2_ROOT%\usr\bin\bash.exe" -lc "pacman -S --noconfirm --needed mingw-w64-ucrt-x86_64-gcc mingw-w64-i686-gcc"\r
+"%MSYS2_ROOT%\mingw32\bin\gcc.exe" --version | findstr /i "gcc" && echo [setup-windows] Msys2: mingw32 gcc ready in %MSYS2_ROOT%\mingw32\bin\r
+"%MSYS2_ROOT%\ucrt64\bin\gcc.exe" --version | findstr /i "gcc" && echo [setup-windows] Msys2: ucrt64 gcc ready in %MSYS2_ROOT%\ucrt64\bin\r
+:after_msys2\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 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