devAlice
← Windows

Wöchentliche Windows-Dev-Umgebungspflege — ein Befehl für MSYS2 · winget · Toolchains

Ein wöchentliches PowerShell-Skript, das MSYS2 pacman, winget, Scoop, npm-Globals, rustup, Cargo-Binaries, pipx und Flutter aktualisiert.

Eine Windows-Dev-Umgebung ist immer ein Flickenteppich aus Abhängigkeiten — IDEs von winget, gcc/make/git von MSYS2, CLIs von scoop, Globals von npm/pip/cargo. Jedes hat einen anderen Update-Befehl, und sie zu vergessen bricht schließlich einen Tauri-Build mit etwas Unsinnigem wie ld.exe: cannot find -lcrypt32.

Ich denke, was das Problem hier besonders ist, ist nicht die Anzahl der Tools, sondern dass die Fehler durch veraltete Abhängigkeiten oft erst Wochen nach dem Überspringen des Updates auftreten — weil der Zusammenhang zwischen „pacman nicht aktualisiert" und „Rust-Build schlägt fehl" nicht offensichtlich ist, vielmehr als direktes Feedback wahrgenommen wird. Früher habe ich Updates ad hoc durchgeführt; heute ist das wöchentliche Skript mein Standard, da es die kognitive Last beseitigt, sich an verschiedene Update-Befehle für verschiedene Tools zu erinnern.

Dieser Artikel ist das 8-Schritte-integrierte PowerShell-Skript, das das verhindert. Einmal pro Woche ausführen — fertig.

TL;DR

  • MSYS2 pacmanwingetScoopnpm -grustupcargo install-updatepipxflutter
  • MSYS2 ist Schritt 1: Es ist das Betriebssystem der Build-Umgebung unter Windows. Es zu überspringen lässt native Builds wie Dominosteine fallen
  • Jeder Schritt überspringt automatisch, wenn das Tool nicht installiert ist; ein Fehler stoppt den Rest nicht
  • ~100 Zeilen PowerShell, ausgeführt per Doppelklick auf update-system.bat

Warum MSYS2 Schritt 1 ist

Windows' winget kümmert sich um Benutzer-Apps (Chrome, Slack…) und endgültige Dev-Tool-Artefakte. Aber die Umgebung, die tatsächlich Code kompiliert, lebt in MSYS2 — gcc, make, autotools, openssl-Header, libsqlite, zlib via pacman.

Einen Monat überspringen und man sieht:

  • Rust + Tauri-Cross-Compiles brechen wegen OpenSSL-Header-Mismatch
  • Python-C-Erweiterungs-Builds (pip install pillow usw.) scheitern an Freetype-Versions-Skew
  • Jeder MinGW-basierte Build bricht wegen ABI-Mismatch in abhängigen Bibliotheken

Deshalb ist pacman -Syuu (doppeltes u — sync inklusive Downgrades) immer der erste Schritt.

Voraussetzungen

  • Windows 10 1709+ / 11 (winget eingebaut)
  • Für die vollen 8 Schritte: MSYS2, pipx, cargo-update, Flutter vorinstalliert
  • Scoop optional — AUTO-SKIP wenn nicht vorhanden

Einmalige Vorbereitung

Administrator-PowerShell:

# MSYS2 (~700 MB) — das Betriebssystem der Build-Umgebung
winget install MSYS2.MSYS2
 
# pipx (Python-Globalpaketverwaltung)
python -m pip install --user pipx
python -m pipx ensurepath
 
# cargo-update-Erweiterung
cargo install cargo-update
 
# Flutter (~1 GB)
winget install Flutter.Flutter
# Falls nicht in winget: https://docs.flutter.dev/get-started/install/windows

Nach der MSYS2-Installation einmal die MSYS2-Shell öffnen und pacman -Syuu ausführen, um Basispakete zu synchronisieren.

8 Update-Schritte

#SchrittBefehlHinweise
1MSYS2pacman -SyuuBetriebssystem der Build-Umgebung — #1
2wingetwinget upgrade --allSystempakete
3Scoopscoop update *Nur wenn installiert
4npm-Globalsnpm update -gGlobale npm-Pakete
5Rust-Toolchainrustup updateStable-Kanal
6Cargo-Binariescargo install-update -aBenötigt cargo-update
7pipxpipx upgrade-allPython-Globaltools
8Flutter SDKflutter upgradeNeuestes des aktuellen Kanals

Das integrierte Skript

Zwei Dateien speichern:

update-system.ps1 (die Logik):

<#
.SYNOPSIS
    Massen-System-Tool-Update — Windows
.DESCRIPTION
    Build-Umgebung / Paketmanager / Sprach-Toolchains in einem Schritt aktualisieren.
.NOTES
    Ausführen: update-system.bat (Admin empfohlen)
    Ziel: Windows 10/11
#>
 
$ErrorActionPreference = "Continue"
$script:Total = 8
$script:Step  = 0
 
function Step-Header {
    param([string]$Message)
    $script:Step++
    Write-Host ""
    Write-Host ("[{0}/{1}] {2}" -f $script:Step, $script:Total, $Message) -ForegroundColor Cyan
}
 
function Has-Command {
    param([string]$Cmd)
    $null = Get-Command $Cmd -ErrorAction SilentlyContinue
    return $?
}
 
function Write-OK   { param([string]$m) Write-Host "  OK   $m" -ForegroundColor Green }
function Write-Skip { param([string]$m) Write-Host "  SKIP $m" -ForegroundColor DarkGray }
function Write-Warn { param([string]$m) Write-Host "  WARN $m" -ForegroundColor Yellow }
function Write-Fail { param([string]$m) Write-Host "  FAIL $m" -ForegroundColor Red }
 
Write-Host "━━━ System update (Windows) ━━━" -ForegroundColor Cyan
 
# 1. MSYS2 (am wichtigsten — Betriebssystem der Build-Umgebung)
Step-Header "MSYS2 (pacman -Syuu) — critical"
$msys2Candidates = @(
    "C:\msys64\usr\bin\bash.exe",
    "D:\msys64\usr\bin\bash.exe",
    "C:\tools\msys64\usr\bin\bash.exe"
)
$msys2Bash = $msys2Candidates | Where-Object { Test-Path $_ } | Select-Object -First 1
if ($msys2Bash) {
    Write-Host "  → using: $msys2Bash" -ForegroundColor DarkGray
    & $msys2Bash -lc "pacman -Syuu --noconfirm"
    if ($LASTEXITCODE -eq 0) {
        Write-OK "pacman -Syuu done (rerun once if core packages updated)"
    } else {
        Write-Fail "pacman -Syuu (after core updates, restart shell + rerun)"
    }
} else {
    Write-Skip "MSYS2 not installed (checked: C:\msys64, D:\msys64, C:\tools\msys64)"
}
 
# 2. winget
Step-Header "winget (system packages)"
if (Has-Command winget) {
    winget upgrade --all --silent --accept-package-agreements --accept-source-agreements
    if ($LASTEXITCODE -eq 0) { Write-OK "winget upgrade --all" }
    else { Write-Fail "winget upgrade --all (some packages may need admin/interactive)" }
} else {
    Write-Skip "winget not installed"
}
 
# 3. Scoop (optional)
Step-Header "Scoop (if installed)"
if (Has-Command scoop) {
    scoop update
    scoop update *
    Write-OK "scoop update / update *"
} else {
    Write-Skip "scoop not installed"
}
 
# 4. npm globals
Step-Header "npm globals"
if (Has-Command npm) {
    npm update -g
    if ($LASTEXITCODE -eq 0) { Write-OK "npm update -g" } else { Write-Fail "npm update -g" }
} else {
    Write-Skip "npm not installed"
}
 
# 5. Rust toolchain
Step-Header "Rust toolchain (rustup)"
if (Has-Command rustup) {
    rustup update
    if ($LASTEXITCODE -eq 0) { Write-OK "rustup update" } else { Write-Fail "rustup update" }
} else {
    Write-Skip "rustup not installed"
}
 
# 6. Cargo binaries
Step-Header "Cargo binaries (cargo install-update -a)"
if (Has-Command cargo) {
    cargo install-update --version 2>$null | Out-Null
    if ($LASTEXITCODE -eq 0) {
        cargo install-update -a
        if ($LASTEXITCODE -eq 0) { Write-OK "cargo install-update -a" }
        else { Write-Fail "cargo install-update -a" }
    } else {
        Write-Warn "cargo-update missing (install: cargo install cargo-update)"
    }
} else {
    Write-Skip "cargo not installed"
}
 
# 7. pipx
Step-Header "pipx (Python global tools)"
if (Has-Command pipx) {
    pipx upgrade-all
    if ($LASTEXITCODE -eq 0) { Write-OK "pipx upgrade-all" } else { Write-Fail "pipx upgrade-all" }
} else {
    Write-Skip "pipx not installed"
}
 
# 8. Flutter SDK
Step-Header "Flutter SDK (flutter upgrade)"
if (Has-Command flutter) {
    flutter upgrade
    if ($LASTEXITCODE -eq 0) { Write-OK "flutter upgrade" } else { Write-Fail "flutter upgrade" }
} else {
    Write-Skip "flutter not installed"
}
 
Write-Host ""
Write-Host "━━━ Done ━━━" -ForegroundColor Cyan
Write-Host "Checks: winget upgrade  /  npm outdated -g  /  pacman -Qu (MSYS2)" -ForegroundColor DarkGray

update-system.bat (Doppelklick-Einstiegspunkt):

@echo off
title System Update
 
echo ============================================
echo   System Update (Windows)
echo   MSYS2 + winget + npm + rustup + cargo + pipx
echo ============================================
echo.
 
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0update-system.ps1" %*
 
if %errorlevel% neq 0 (
    echo.
    echo [ERROR] Update failed. Check log above.
) else (
    echo.
    echo [DONE] System update complete.
)
 
pause

Die .ps1-Datei als UTF-8 mit BOM speichern. Ohne BOM wird Nicht-ASCII-Ausgabe durch Windows PowerShell 5.1 verstümmelt. In VS Code unten rechts auf die Codierung klicken → „Mit Codierung speichern" → „UTF-8 mit BOM".

Beispielausgabe

update-system.bat doppelklicken (UAC akzeptieren). Erster Durchlauf 5–10 Min. (MSYS2 + winget). Folgeläufe 1–3 Min.

━━━ System update (Windows) ━━━

[1/8] MSYS2 (pacman -Syuu) — critical
  → using: C:\msys64\usr\bin\bash.exe
:: Synchronizing package databases...
:: Starting core system upgrade...
...
  OK pacman -Syuu done (rerun once if core packages updated)

[2/8] winget (system packages)
  Microsoft.VisualStudioCode 1.99.2 → 1.100.0
  GitHub.cli 2.65.0 → 2.66.1
  ...
  OK winget upgrade --all

[3/8] Scoop (if installed)
  SKIP scoop not installed

[4/8] npm globals
  OK npm update -g

...

━━━ Done ━━━
Checks: winget upgrade  /  npm outdated -g  /  pacman -Qu (MSYS2)

Automatisierung — nur eine Erinnerung via Task Scheduler

Vollständige Automatisierung wird nicht empfohlen. winget öffnet gelegentlich EULA-Dialoge, und MSYS2-Kern-Updates benötigen einen Shell-Neustart, der unbeaufsichtigte Läufe unterbricht. Eine Erinnerung, kein Auto-Run:

Task Scheduler via PowerShell:

$action = New-ScheduledTaskAction -Execute "powershell.exe" `
    -Argument '-NoProfile -Command "[System.Reflection.Assembly]::LoadWithPartialName(\"System.Windows.Forms\"); [System.Windows.Forms.MessageBox]::Show(\"Weekly update-system reminder\", \"Dev Maintenance\")"'
 
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Friday -At 10:00am
 
Register-ScheduledTask -TaskName "Dev Update Reminder" `
    -Action $action -Trigger $trigger `
    -Description "Weekly reminder to run update-system"

Jeden Freitag um 10:00 Uhr ein Meldungsfenster. Man entscheidet, wann man ausführt.

Fallstricke

  • MSYS2-Kern-Updates erfordern Shell-Neustart + erneuten Durchlauf: Wenn pacman sich selbst oder Kern-Bibliotheken (libcurl, openssl) aktualisiert, stoppt es die Transaktion und bittet um einen erneuten Durchlauf. update-system.bat nach dem ersten Durchlauf noch einmal ausführen.
  • Einige winget-Pakete benötigen interaktive Eingabe: Die meisten laufen still mit --silent, aber neue EULAs blockieren. Diese Pakete manuell installieren.
  • Flutter ist möglicherweise nicht im winget-Repo: Wenn Flutter.Flutter nicht aufgeführt ist, das ZIP von docs.flutter.dev herunterladen und zu PATH hinzufügen.
  • Scoop ist optional: Wenn man absichtlich nur winget oder nur scoop verwendet, überspringt der andere Schritt sauber. Kein Konfliktrisiko.
  • Das zweite u in -Syuu: Synchronisiert Downgrades. MSYS2 downgradet manchmal Pakete absichtlich; -Syu allein häuft Konflikte an.

Mac-Benutzer?

Dieselbe Idee für brew + Sprach-Toolchains + Flutter + CocoaPods → Wöchentliche Mac-Dev-Umgebungspflege.

Zusammenfassung

  • Unter Windows hat MSYS2-Update Priorität #1
  • Tools einzeln nacheinander aktualisieren → man vergisst es
  • Ein integriertes Skript → man kann alles vergessen, einfach ausführen
  • Nur als Erinnerung automatisieren, nie den Lauf selbst
  • Einmal wöchentlich verhindert Build-Brüche, Zertifikatsabläufe und SDK-Drift