devAlice
← Windows

Mantenimiento semanal del entorno de desarrollo en Windows — un comando para MSYS2, winget y toolchains

Un script semanal de PowerShell que actualiza MSYS2 pacman, winget, Scoop, globals de npm, rustup, binarios de cargo, pipx y Flutter.

Un entorno de desarrollo en Windows siempre es un mosaico de dependencias: IDEs de winget, gcc/make/git de MSYS2, CLIs de scoop, globals de npm/pip/cargo. Cada uno tiene un comando de actualización diferente, y olvidarlos acaba rompiendo una compilación de Tauri con algo sin sentido como ld.exe: cannot find -lcrypt32.

Creo que la solución no es recordar más, sino automatizar el recuerdo. Antes intentaba mantener actualizadas las herramientas una a una cuando surgía el problema; ahora, porque el script lo hace todo en orden, el tiempo que antes perdía depurando entornos rotos se invierte en el trabajo real.

Este artículo es el script integrado de PowerShell en 8 pasos que lo previene. Ejecútalo una vez a la semana — listo.

Resumen

  • MSYS2 pacmanwingetScoopnpm -grustupcargo install-updatepipxflutter
  • MSYS2 es el paso 1: es el SO de tu entorno de compilación en Windows. Saltárselo hace que las compilaciones nativas se desmoronen en cadena
  • Cada paso se salta automáticamente si la herramienta no está instalada; un fallo no detiene el resto
  • ~100 líneas de PowerShell, ejecutadas haciendo doble clic en update-system.bat

Por qué MSYS2 es el paso 1

El winget de Windows gestiona apps de usuario (Chrome, Slack…) y artefactos finales de herramientas de desarrollo. Pero el entorno que realmente compila código vive dentro de MSYS2 — gcc, make, autotools, cabeceras de openssl, libsqlite, zlib a través de pacman.

Sáltate un mes y verás:

  • Las compilaciones cruzadas de Rust + Tauri fallan por incompatibilidad de cabeceras OpenSSL
  • Las compilaciones de extensiones C de Python (pip install pillow, etc.) fallan por desfase de versión de freetype
  • Cualquier compilación basada en MinGW falla por incompatibilidad ABI en las librerías dependientes

Por eso pacman -Syuu (doble u — sincronización incluyendo bajadas de versión) es siempre el primer paso.

Requisitos previos

  • Windows 10 1709+ / 11 (winget integrado)
  • Para los 8 pasos completos: MSYS2, pipx, cargo-update, Flutter preinstalados
  • Scoop opcional — se salta automáticamente si no está presente

Preparación única

PowerShell como administrador:

# MSYS2 (~700 MB) — el SO del entorno de compilación
winget install MSYS2.MSYS2
 
# pipx (gestor de paquetes globales de Python)
python -m pip install --user pipx
python -m pipx ensurepath
 
# extensión cargo-update
cargo install cargo-update
 
# Flutter (~1 GB)
winget install Flutter.Flutter
# Si no está en winget: https://docs.flutter.dev/get-started/install/windows

Tras instalar MSYS2, abre el shell de MSYS2 una vez y ejecuta pacman -Syuu para sincronizar los paquetes base.

8 pasos de actualización

#PasoComandoNotas
1MSYS2pacman -SyuuSO del entorno de compilación — #1
2wingetwinget upgrade --allpaquetes del sistema
3Scoopscoop update *solo si está instalado
4npm globalsnpm update -gpaquetes npm globales
5Toolchain de Rustrustup updatecanal stable
6Binarios de Cargocargo install-update -anecesita cargo-update
7pipxpipx upgrade-allherramientas globales de Python
8Flutter SDKflutter upgradeúltimo del canal actual

El script integrado

Guarda dos archivos:

update-system.ps1 (la lógica):

<#
.SYNOPSIS
    Actualización masiva de herramientas del sistema — Windows
.DESCRIPTION
    Refresca el entorno de compilación / gestores de paquetes / toolchains de lenguajes de un golpe.
.NOTES
    Ejecutar: update-system.bat (se recomienda admin)
    Objetivo: 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 (el más importante — SO del entorno de compilación)
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 (opcional)
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. Toolchain de Rust
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. Binarios de Cargo
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 (punto de entrada con doble clic):

@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

Guarda el archivo .ps1 como UTF-8 con BOM. Sin BOM, la salida no ASCII se corrompe en Windows PowerShell 5.1. En VS Code, haz clic en la codificación en la esquina inferior derecha → «Save with Encoding» → «UTF-8 with BOM».

Ejemplo de salida

Haz doble clic en update-system.bat (acepta UAC). La primera ejecución tarda 5–10 min (MSYS2 + winget). Las siguientes, 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)

Automatización — solo un recordatorio con Task Scheduler

La automatización completa no se recomienda. winget ocasionalmente muestra diálogos de EULA, y las actualizaciones de núcleo de MSYS2 requieren un reinicio de shell que rompe las ejecuciones desatendidas. Un recordatorio, no una ejecución automática:

Task Scheduler mediante 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"

Cada viernes a las 10:00, un cuadro de mensaje. Tú decides cuándo ejecutarlo.

Puntos a tener en cuenta

  • Las actualizaciones del núcleo de MSYS2 requieren reinicio del shell + nueva ejecución: Cuando pacman se actualiza a sí mismo o las librerías del núcleo (libcurl, openssl), detiene la transacción y pide una nueva ejecución. Ejecuta update-system.bat una vez más después de que termine la primera.
  • Algunos paquetes de winget necesitan entrada interactiva: La mayoría van en silencioso con --silent, pero las nuevas EULAs bloquean. Instala esos paquetes manualmente.
  • Flutter puede no estar en el repositorio de winget: Cuando Flutter.Flutter no aparece, descarga el zip de docs.flutter.dev y añádelo al PATH.
  • Scoop es opcional: Si usas intencionadamente solo winget o solo scoop, el otro paso se salta limpiamente. Sin riesgo de conflicto.
  • La segunda u en -Syuu: Sincroniza bajadas de versión. MSYS2 a veces baja versiones de paquetes intencionadamente; -Syu solo acumula conflictos.

¿Usuarios de Mac?

La misma idea cubriendo brew + toolchains de lenguajes + Flutter + CocoaPods → Mantenimiento semanal del entorno de desarrollo en Mac.

Resumen

  • En Windows, la actualización de MSYS2 es prioridad #1
  • Actualizar las herramientas una a una → acabarás olvidando alguna
  • Un script integrado → olvídate de todo, solo ejecútalo
  • Automatiza solo como recordatorio, nunca la ejecución en sí
  • Una vez a la semana previene roturas de compilación, vencimiento de certificados y desfase de SDK