# ============================================================================= # setup-runner.ps1 - Windows Runner Setup fuer RustDesk CI Pipeline # ============================================================================= # Installiert alle Abhaengigkeiten inkl. GitLab Runner auf einem frischen # Windows Server 2022 Core. Anschliessend ist der Runner betriebsbereit. # # Das Skript ist idempotent: Bereits korrekt installierte Komponenten werden # uebersprungen. Nur fehlende oder veraltete Tools werden (neu) installiert. # # Nutzung (als Administrator): # powershell -ExecutionPolicy Bypass -File setup-runner.ps1 # # Exit-Code 0 = Alles installiert und verifiziert # Exit-Code 1 = Fehler (Komponentenname in der Ausgabe) # ============================================================================= #Requires -RunAsAdministrator $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" # --------------------------------------------------------------------------- # Konfiguration # --------------------------------------------------------------------------- $RustVersion = "1.75" $RustToolchain = "1.75.0-x86_64-pc-windows-msvc" $FlutterVersion = "3.24.5" $FlutterRoot = "C:\flutter" $LlvmVersion = "15.0.6" $LlvmHome = "C:\Program Files\LLVM" $GitVersion = "2.47.1" $VcpkgCommit = "120deac3062162151622ca4860575a33844ba10b" $VcpkgRoot = "C:\vcpkg" $VcpkgTriplet = "x64-windows-static" $RustDeskVersion = "1.4.7" # RustDesk Tag fuer vcpkg.json + overlay-ports Download $PythonVersion = "3.11" $PythonDir = "C:\Python311" $NsisVersion = "3.10" $NsisDir = "C:\Program Files (x86)\NSIS" $ImageMagickVersion = "7.1.2" $ImageMagickRelease = "7.1.2-25" $ImageMagickDir = "C:\ImageMagick" $GitLabRunnerDir = "C:\GitLab-Runner" $TempDir = "C:\setup-temp" # --------------------------------------------------------------------------- # Hilfsfunktionen # --------------------------------------------------------------------------- function Step([string]$msg) { Write-Host "`n=== $msg ===" -ForegroundColor Cyan } function OK([string]$msg) { Write-Host " [OK] $msg" -ForegroundColor Green } function Skip([string]$msg) { Write-Host " [SKIP] $msg" -ForegroundColor DarkGray } function Fail([string]$component, [string]$msg) { Write-Host " [FAIL] ${component}: $msg" -ForegroundColor Red exit 1 } function Download([string]$url, [string]$out, [string]$component) { Write-Host " Download: $url" if (Test-Path $out) { Remove-Item -Force $out -ErrorAction SilentlyContinue Start-Sleep -Seconds 1 } & curl.exe -L -s -o $out $url if ($LASTEXITCODE -ne 0) { Fail $component "Download fehlgeschlagen (curl exit code $LASTEXITCODE)" } if (-not (Test-Path $out)) { Fail $component "Datei wurde nicht gespeichert: $out" } $size = (Get-Item $out).Length if ($size -eq 0) { Fail $component "Download leer (0 bytes): $out" } Write-Host " OK: $out ($([math]::Round($size/1MB, 1)) MB)" } function AddPath([string]$dir) { $p = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::Machine) if ($p -notlike "*$dir*") { [System.Environment]::SetEnvironmentVariable("Path", "$p;$dir", [System.EnvironmentVariableTarget]::Machine) } if ($env:Path -notlike "*$dir*") { $env:Path = "$env:Path;$dir" } } function SetEnv([string]$name, [string]$value) { [System.Environment]::SetEnvironmentVariable($name, $value, [System.EnvironmentVariableTarget]::Machine) [System.Environment]::SetEnvironmentVariable($name, $value, [System.EnvironmentVariableTarget]::Process) } # Prueft ob ein Befehl verfuegbar ist und das Versionsmuster matched function Test-InstalledVersion([string]$cmd, [string]$cmdArgs, [string]$pattern) { try { $executable = Get-Command $cmd -ErrorAction SilentlyContinue if (-not $executable) { return $false } $out = & $cmd $cmdArgs.Split(' ') 2>&1 | Out-String return ($out -match $pattern) } catch { return $false } } # --------------------------------------------------------------------------- # Vorbereitung # --------------------------------------------------------------------------- # TLS 1.2 erzwingen (ohne das blockieren manche CDNs auf Server Core) [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # Temp-Verzeichnis anlegen (nur wenn noetig) if (-not (Test-Path $TempDir)) { New-Item -ItemType Directory -Path $TempDir -Force | Out-Null } # --------------------------------------------------------------------------- # 1. Visual Studio Build Tools 2022 # --------------------------------------------------------------------------- Step "Visual Studio Build Tools 2022" $vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" $vsInstalled = $false if (Test-Path $vsWhere) { $vsPath = & $vsWhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath 2>&1 if ($vsPath) { $vsInstalled = $true } } if ($vsInstalled) { Skip "VS Build Tools 2022 (MSVC v143) bereits installiert" } else { # Vorherige Prozesse beenden die Dateien sperren koennten Stop-Process -Name "vs_buildtools" -Force -ErrorAction SilentlyContinue Stop-Process -Name "vs_installer" -Force -ErrorAction SilentlyContinue Stop-Process -Name "vs_setup_bootstrapper" -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 $vsExe = "$TempDir\vs_buildtools.exe" Download "https://aka.ms/vs/17/release/vs_buildtools.exe" $vsExe "VS Build Tools" $p = Start-Process $vsExe -ArgumentList @( "--quiet","--wait","--norestart", "--add","Microsoft.VisualStudio.Workload.VCTools", "--add","Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "--add","Microsoft.VisualStudio.Component.Windows11SDK.22621", "--includeRecommended" ) -Wait -PassThru -NoNewWindow if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) { Fail "VS Build Tools" "Exit-Code $($p.ExitCode)" } OK "VS Build Tools 2022 installiert" } # --------------------------------------------------------------------------- # 2. Rust 1.75 # --------------------------------------------------------------------------- Step "Rust $RustVersion" # Rust systemweit installieren (nicht im User-Profil, da der Runner als Dienst laeuft) $CargoHome = "C:\cargo" $RustupHome = "C:\rustup" SetEnv "CARGO_HOME" $CargoHome SetEnv "RUSTUP_HOME" $RustupHome if (Test-InstalledVersion "rustc" "--version" "rustc 1\.75") { Skip "Rust $RustVersion bereits installiert" } else { $rustup = "$TempDir\rustup-init.exe" Download "https://win.rustup.rs/x86_64" $rustup "Rust" # CARGO_HOME und RUSTUP_HOME muessen vor der Installation gesetzt sein $env:CARGO_HOME = $CargoHome $env:RUSTUP_HOME = $RustupHome $p = Start-Process $rustup -ArgumentList @("-y","--default-toolchain",$RustToolchain,"--default-host","x86_64-pc-windows-msvc") -Wait -PassThru -NoNewWindow if ($p.ExitCode -ne 0) { Fail "Rust" "rustup-init Exit-Code $($p.ExitCode)" } AddPath "$CargoHome\bin" $env:Path = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::Machine) + ";" + [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::User) OK "Rust $RustVersion (x86_64-pc-windows-msvc) installiert" } # --------------------------------------------------------------------------- # 3. Flutter 3.24.5 # --------------------------------------------------------------------------- Step "Flutter $FlutterVersion" # Flutter-Version direkt aus der version-Datei pruefen (flutter --version ist unzuverlaessig) $flutterInstalled = $false $flutterVersionFile = "$FlutterRoot\version" if ((Test-Path "$FlutterRoot\bin\flutter.bat") -and (Test-Path $flutterVersionFile)) { $installedFlutter = (Get-Content $flutterVersionFile -ErrorAction SilentlyContinue).Trim() if ($installedFlutter -eq $FlutterVersion) { $flutterInstalled = $true } } if ($flutterInstalled) { Skip "Flutter $FlutterVersion bereits installiert" } else { if (Test-Path $FlutterRoot) { Remove-Item -Recurse -Force $FlutterRoot } $flutterZip = "$TempDir\flutter.zip" Download "https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_${FlutterVersion}-stable.zip" $flutterZip "Flutter" # ZIP-Integritaet pruefen (muss ein gueltiges ZIP sein, nicht eine HTML-Fehlerseite) $zipSize = (Get-Item $flutterZip).Length if ($zipSize -lt 10MB) { Fail "Flutter" "Download zu klein ($([math]::Round($zipSize/1MB, 1)) MB) - wahrscheinlich fehlgeschlagen" } Write-Host " Entpacke Flutter SDK ($([math]::Round($zipSize/1MB, 0)) MB)..." # Expand-Archive kann bei grossen ZIPs auf Server Core fehlschlagen. # Nutze tar.exe (in Windows Server 2022 enthalten) als zuverlaessigere Alternative. & tar.exe -xf $flutterZip -C "C:\" if ($LASTEXITCODE -ne 0) { # Fallback auf Expand-Archive Write-Host " tar fehlgeschlagen, versuche Expand-Archive..." Expand-Archive -Path $flutterZip -DestinationPath "C:\" -Force } if (-not (Test-Path "$FlutterRoot\bin\flutter.bat")) { # Debug: Zeige was tatsaechlich entpackt wurde $extracted = Get-ChildItem "C:\" -Directory | Where-Object { $_.Name -like "flutter*" } | Select-Object -ExpandProperty Name Fail "Flutter" "flutter.bat nicht gefunden nach Entpacken. Gefundene Verzeichnisse: $($extracted -join ', ')" } SetEnv "FLUTTER_ROOT" $FlutterRoot AddPath "$FlutterRoot\bin" & "$FlutterRoot\bin\flutter.bat" --disable-analytics 2>&1 | Out-Null & "$FlutterRoot\bin\flutter.bat" precache --windows 2>&1 | Out-Null OK "Flutter $FlutterVersion installiert" } # --------------------------------------------------------------------------- # 4. LLVM 15.0.6 # --------------------------------------------------------------------------- Step "LLVM $LlvmVersion" if (Test-InstalledVersion "clang" "--version" $([regex]::Escape($LlvmVersion))) { Skip "LLVM $LlvmVersion bereits installiert" } else { $llvmExe = "$TempDir\llvm-installer.exe" Download "https://github.com/llvm/llvm-project/releases/download/llvmorg-$LlvmVersion/LLVM-$LlvmVersion-win64.exe" $llvmExe "LLVM" $p = Start-Process $llvmExe -ArgumentList @("/S","/D=$LlvmHome") -Wait -PassThru -NoNewWindow if ($p.ExitCode -ne 0) { Fail "LLVM" "Exit-Code $($p.ExitCode)" } SetEnv "LLVM_HOME" $LlvmHome AddPath "$LlvmHome\bin" OK "LLVM $LlvmVersion installiert" } # --------------------------------------------------------------------------- # 5. Git # --------------------------------------------------------------------------- Step "Git $GitVersion" $gitInstalled = $false if (Get-Command git -ErrorAction SilentlyContinue) { $gitOut = git --version 2>&1 | Out-String if ($gitOut -match [regex]::Escape($GitVersion)) { $gitInstalled = $true } } if ($gitInstalled) { Skip "Git $GitVersion bereits installiert" } else { $gitExe = "$TempDir\git-installer.exe" Download "https://github.com/git-for-windows/git/releases/download/v${GitVersion}.windows.1/Git-${GitVersion}-64-bit.exe" $gitExe "Git" $p = Start-Process $gitExe -ArgumentList @("/VERYSILENT","/NORESTART","/NOCANCEL","/SP-","/CLOSEAPPLICATIONS","/RESTARTAPPLICATIONS","/COMPONENTS=ext,ext\shellhere,ext\guihere,assoc,assoc_sh") -Wait -PassThru -NoNewWindow if ($p.ExitCode -ne 0) { Fail "Git" "Exit-Code $($p.ExitCode)" } AddPath "C:\Program Files\Git\cmd" $env:Path = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::Machine) + ";" + [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::User) OK "Git $GitVersion installiert" } # --------------------------------------------------------------------------- # 6. vcpkg + Pakete (Manifest-Modus wie rdgen) # --------------------------------------------------------------------------- Step "vcpkg (Commit $VcpkgCommit) + RustDesk Dependencies" Write-Host " RustDesk Version fuer vcpkg.json: $RustDeskVersion" # Pruefen ob vcpkg auf dem richtigen Commit steht $vcpkgNeedsSetup = $false if (-not (Test-Path "$VcpkgRoot\vcpkg.exe")) { $vcpkgNeedsSetup = $true } else { $env:GIT_REDIRECT_STDERR = '2>&1' Push-Location $VcpkgRoot try { $currentCommit = git rev-parse HEAD 2>&1 | Out-String $currentCommit = $currentCommit.Trim() if ($currentCommit -ne $VcpkgCommit) { $vcpkgNeedsSetup = $true } } catch { $vcpkgNeedsSetup = $true } finally { Pop-Location } } # Pruefen ob die Pakete installiert sind (mehrere kritische Libs als Indikator) $vcpkgLibDir = Join-Path $VcpkgRoot "installed\$VcpkgTriplet\lib" $vcpkgPackagesOk = (Test-Path (Join-Path $vcpkgLibDir "swresample.lib")) -and (Test-Path (Join-Path $vcpkgLibDir "opus.lib")) -and (Test-Path (Join-Path $vcpkgLibDir "vpx.lib")) -and (Test-Path (Join-Path $vcpkgLibDir "avcodec.lib")) -and (Test-Path (Join-Path $vcpkgLibDir "avutil.lib")) -and (Test-Path (Join-Path $vcpkgLibDir "aom.lib")) if (-not $vcpkgNeedsSetup -and $vcpkgPackagesOk) { Write-Host " vcpkg Commit und Pakete OK — fuehre trotzdem Manifest-Update durch..." } # vcpkg klonen/aktualisieren (nur wenn noetig) if ($vcpkgNeedsSetup) { if (Test-Path $VcpkgRoot) { Remove-Item -Recurse -Force $VcpkgRoot } $env:GIT_REDIRECT_STDERR = '2>&1' git clone https://github.com/microsoft/vcpkg.git $VcpkgRoot if ($LASTEXITCODE -ne 0) { Fail "vcpkg" "git clone fehlgeschlagen" } Push-Location $VcpkgRoot try { git checkout $VcpkgCommit if ($LASTEXITCODE -ne 0) { Fail "vcpkg" "git checkout fehlgeschlagen" } & .\bootstrap-vcpkg.bat -disableMetrics 2>&1 | Out-Null if ($LASTEXITCODE -ne 0) { Fail "vcpkg" "Bootstrap fehlgeschlagen" } } finally { Pop-Location } SetEnv "VCPKG_ROOT" $VcpkgRoot AddPath $VcpkgRoot } # vcpkg.json von RustDesk laden und im Manifest-Modus installieren (wie rdgen) # rdgen laeuft: vcpkg install --triplet x64-windows-static --x-install-root="$VCPKG_ROOT/installed" # aus dem Quellverzeichnis mit vcpkg.json — das installiert ALLE Dependencies inkl. FFmpeg/swresample # # Wichtig: vcpkg.json referenziert overlay-ports in ./res/vcpkg/ (custom port definitions). # Wir brauchen daher vcpkg.json UND res/vcpkg/ aus dem RustDesk Repo. $manifestDir = "$TempDir\vcpkg-manifest" if (-not (Test-Path $TempDir)) { New-Item -ItemType Directory -Path $TempDir -Force | Out-Null } if (Test-Path $manifestDir) { Remove-Item -Recurse -Force $manifestDir } # Shallow clone des RustDesk Repos (--depth 1 = nur letzter Commit, ca. 50 MB) Write-Host " Klone RustDesk Repo (shallow, Tag $RustDeskVersion)..." $gitRef = if ($RustDeskVersion -eq "master") { "master" } else { $RustDeskVersion } git clone --depth 1 --branch $gitRef "https://github.com/rustdesk/rustdesk.git" $manifestDir 2>&1 | Out-Null if ($LASTEXITCODE -ne 0) { Fail "vcpkg" "git clone von rustdesk fehlgeschlagen (Branch/Tag: $gitRef)" } # Pruefen ob vcpkg.json vorhanden ist $vcpkgJsonLocal = Join-Path $manifestDir "vcpkg.json" if (-not (Test-Path $vcpkgJsonLocal)) { Fail "vcpkg" "vcpkg.json nicht gefunden nach clone" } # Pruefen ob overlay-ports vorhanden sind $overlayDir = Join-Path $manifestDir "res\vcpkg" if (-not (Test-Path $overlayDir)) { Write-Host " WARNUNG: res/vcpkg (overlay-ports) nicht gefunden — versuche ohne Overlays" -ForegroundColor Yellow # vcpkg.json anpassen: overlay-ports Eintrag entfernen $jsonContent = Get-Content $vcpkgJsonLocal -Raw $jsonContent = $jsonContent -replace '"overlay-ports"\s*:\s*\[[^\]]*\]\s*,?', '' Set-Content -Path $vcpkgJsonLocal -Value $jsonContent } else { Write-Host " overlay-ports gefunden: $overlayDir" } # FFmpeg im vcpkg.json braucht explizit das Feature "swresample" fuer hwcodec. # RustDesk's vcpkg.json listet nur amf/nvcodec/qsv — swresample fehlt. # Die RustDesk overlay-ports in res/vcpkg/ffmpeg entfernen swresample aus den # Default-Features. Wir installieren es daher explizit nach dem Manifest-Install. Write-Host " vcpkg.json und overlay-ports geladen. Starte Manifest-Installation..." Write-Host " (Dies kann 30-60 Minuten dauern bei Erstinstallation)" # Schritt A: Pakete per Manifest installieren (aom, opus, libvpx, libyuv, mfx-dispatch) # Das Manifest installiert auch ffmpeg via overlay-port — OHNE swresample. Write-Host " Installiere Pakete per Manifest..." Push-Location $manifestDir try { $vcpkgOutput = cmd /c "`"$VcpkgRoot\vcpkg.exe`" install --triplet $VcpkgTriplet --x-install-root=`"$VcpkgRoot\installed`" 2>&1" | Out-String $vcpkgExit = $LASTEXITCODE Write-Host $vcpkgOutput if ($vcpkgExit -ne 0) { Fail "vcpkg" "Manifest-Installation fehlgeschlagen (Exit-Code $vcpkgExit)" } } finally { Pop-Location } # Aufraeumen des temporaeren Manifest-Verzeichnisses # WICHTIG: Muss VOR dem ffmpeg-reinstall passieren, damit der overlay-port # nicht mehr im Dateisystem liegt und vcpkg den stock-port verwendet. Remove-Item -Recurse -Force $manifestDir -ErrorAction SilentlyContinue # Schritt B: ffmpeg mit swresample nachinstallieren (stock port). # Das Manifest hat ffmpeg:x64-windows-static via overlay-port installiert # (mit --disable-swresample). Jetzt wo der overlay-port Ordner geloescht ist, # koennen wir ffmpeg mit dem stock-port reinstallieren der swresample enthaelt. Write-Host " Reinstalliere ffmpeg:$VcpkgTriplet mit swresample (stock port)..." $ffmpegOutput = cmd /c "`"$VcpkgRoot\vcpkg.exe`" remove `"ffmpeg:$VcpkgTriplet`" --x-install-root=`"$VcpkgRoot\installed`" 2>&1" | Out-String Write-Host " Remove: $ffmpegOutput" $ffmpegOutput = cmd /c "`"$VcpkgRoot\vcpkg.exe`" install `"ffmpeg[swresample,avcodec,avformat]:$VcpkgTriplet`" --x-install-root=`"$VcpkgRoot\installed`" 2>&1" | Out-String $ffmpegExit = $LASTEXITCODE Write-Host $ffmpegOutput if ($ffmpegExit -ne 0) { Fail "vcpkg" "ffmpeg (stock mit swresample) Installation fehlgeschlagen (Exit-Code $ffmpegExit)" } # vcpkg im Manifest-Modus kann auch in vcpkg_installed/ im CWD installieren. # Pruefen wo die Libs tatsaechlich gelandet sind. $vcpkgLibDir = Join-Path $VcpkgRoot "installed\$VcpkgTriplet\lib" $swresampleLib = Join-Path $vcpkgLibDir "swresample.lib" if (-not (Test-Path $swresampleLib)) { # Suche in alternativen Pfaden Write-Host " swresample.lib nicht in $vcpkgLibDir — suche..." -ForegroundColor Yellow $found = Get-ChildItem -Path $VcpkgRoot -Recurse -Filter "swresample.lib" -ErrorAction SilentlyContinue | Select-Object -First 1 if ($found) { Write-Host " Gefunden: $($found.FullName)" -ForegroundColor Yellow # Aktualisiere vcpkgLibDir $vcpkgLibDir = $found.DirectoryName } } # Verifizieren dass die kritischen Libs vorhanden sind $swresampleLib = Join-Path $vcpkgLibDir "swresample.lib" if (-not (Test-Path $swresampleLib)) { Fail "vcpkg" "swresample.lib nicht gefunden nach Installation — FFmpeg wurde nicht korrekt gebaut" } OK "vcpkg + RustDesk Dependencies (Manifest-Modus, $VcpkgTriplet) installiert" # --------------------------------------------------------------------------- # 7. Python 3.11 # --------------------------------------------------------------------------- Step "Python $PythonVersion" if (Test-InstalledVersion "python" "--version" "Python $([regex]::Escape($PythonVersion))") { Skip "Python $PythonVersion bereits installiert" } else { $pyExe = "$TempDir\python-installer.exe" Download "https://www.python.org/ftp/python/3.11.9/python-3.11.9-amd64.exe" $pyExe "Python" $p = Start-Process $pyExe -ArgumentList @("/quiet","InstallAllUsers=1","TargetDir=$PythonDir","PrependPath=1","Include_test=0") -Wait -PassThru -NoNewWindow if ($p.ExitCode -ne 0) { Fail "Python" "Exit-Code $($p.ExitCode)" } AddPath $PythonDir AddPath "$PythonDir\Scripts" OK "Python $PythonVersion installiert" } # --------------------------------------------------------------------------- # 8. NSIS # --------------------------------------------------------------------------- Step "NSIS $NsisVersion" $nsisInstalled = $false if (Test-Path "$NsisDir\makensis.exe") { $nsisOut = & "$NsisDir\makensis.exe" /VERSION 2>&1 | Out-String if ($nsisOut -match "v3\.") { $nsisInstalled = $true } } if ($nsisInstalled) { Skip "NSIS $NsisVersion bereits installiert" } else { $nsisExe = "$TempDir\nsis-setup.exe" Download "https://sourceforge.net/projects/nsis/files/NSIS%203/3.10/nsis-3.10-setup.exe/download" $nsisExe "NSIS" $p = Start-Process $nsisExe -ArgumentList "/S" -Wait -PassThru -NoNewWindow if ($p.ExitCode -ne 0) { Fail "NSIS" "Exit-Code $($p.ExitCode)" } AddPath $NsisDir OK "NSIS $NsisVersion installiert" } # --------------------------------------------------------------------------- # 9. ImageMagick # --------------------------------------------------------------------------- Step "ImageMagick $ImageMagickRelease" if (Test-InstalledVersion "magick" "--version" "ImageMagick $([regex]::Escape($ImageMagickVersion))") { Skip "ImageMagick $ImageMagickVersion bereits installiert" } else { if (Test-Path $ImageMagickDir) { Remove-Item -Recurse -Force $ImageMagickDir } $imExe = "$TempDir\imagemagick-setup.exe" Download "https://github.com/ImageMagick/ImageMagick/releases/download/$ImageMagickRelease/ImageMagick-${ImageMagickRelease}-Q16-HDRI-x64-dll.exe" $imExe "ImageMagick" $p = Start-Process $imExe -ArgumentList @("/VERYSILENT","/NORESTART","/DIR=$ImageMagickDir") -Wait -PassThru -NoNewWindow if ($p.ExitCode -ne 0) { Fail "ImageMagick" "Exit-Code $($p.ExitCode)" } AddPath $ImageMagickDir OK "ImageMagick $ImageMagickRelease installiert" } # --------------------------------------------------------------------------- # 10. GitLab Runner # --------------------------------------------------------------------------- Step "GitLab Runner" $runnerExe = "$GitLabRunnerDir\gitlab-runner.exe" $runnerInstalled = $false if (Test-Path $runnerExe) { $runnerOut = cmd /c "`"$runnerExe`" --version 2>&1" | Out-String if ($runnerOut -match "Version:\s+\d+") { $runnerInstalled = $true } } if ($runnerInstalled) { Skip "GitLab Runner bereits installiert" } else { if (-not (Test-Path $GitLabRunnerDir)) { New-Item -ItemType Directory -Path $GitLabRunnerDir -Force | Out-Null } Download "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-amd64.exe" $runnerExe "GitLab Runner" # Als Windows-Dienst installieren (stderr-Output ignorieren, da gitlab-runner # Info-Meldungen wie "Runtime platform" auf stderr schreibt) $installOutput = cmd /c "`"$runnerExe`" install 2>&1" # Fehler nur bei tatsaechlichem Fehlschlag pruefen if ($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne $null) { Write-Host " WARNUNG: gitlab-runner install Exit-Code $LASTEXITCODE (evtl. bereits registriert)" -ForegroundColor Yellow } AddPath $GitLabRunnerDir OK "GitLab Runner installiert (Dienst registriert)" Write-Host " HINWEIS: Runner muss noch mit 'gitlab-runner register' konfiguriert werden:" -ForegroundColor Yellow Write-Host " gitlab-runner register --non-interactive --url --token --executor shell --shell powershell --tag-list windows-runner" -ForegroundColor Yellow Write-Host "" Write-Host " WICHTIG: --shell powershell verwenden (NICHT pwsh), da PowerShell Core nicht installiert ist." -ForegroundColor Yellow } # --------------------------------------------------------------------------- # Aufraeumen # --------------------------------------------------------------------------- Step "Aufraeumen" if (Test-Path $TempDir) { Remove-Item -Recurse -Force $TempDir -ErrorAction SilentlyContinue OK "Temporaere Dateien entfernt" } else { Skip "Kein Temp-Verzeichnis vorhanden" } # --------------------------------------------------------------------------- # PATH fuer aktuelle Session neu laden # --------------------------------------------------------------------------- $env:Path = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::Machine) + ";" + [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::User) # --------------------------------------------------------------------------- # Verifikation # --------------------------------------------------------------------------- Step "Verifikation" $failed = @() function Verify([string]$name, [string]$cmd, [string]$pattern) { try { $out = Invoke-Expression $cmd 2>&1 | Out-String if ($out -match $pattern) { OK "$name" } else { Write-Host " [FAIL] $name - Pattern '$pattern' nicht gefunden in: $out" -ForegroundColor Red; $script:failed += $name } } catch { Write-Host " [FAIL] $name - $($_.Exception.Message)" -ForegroundColor Red $script:failed += $name } } Verify "Rust" "rustc --version" "rustc 1\.75" Verify "Cargo" "cargo --version" "cargo 1\.75" Verify "Flutter" "flutter --version" "Flutter 3\.24\.5" Verify "Clang" "clang --version" "15\.0\.6" Verify "vcpkg" "vcpkg version" "vcpkg" Verify "Python" "python --version" "Python 3\.11" Verify "NSIS" "makensis /VERSION" "v3\." Verify "ImageMagick" "magick --version" "ImageMagick 7\." Verify "GitLab Runner" "gitlab-runner --version" "Version:\s+\d+" Verify "Git" "git --version" "git version" # vcpkg-Pakete (kritische Libs pruefen) $vcpkgLibDir = Join-Path $VcpkgRoot "installed\$VcpkgTriplet\lib" $criticalLibs = @( @{N="opus"; F="opus.lib"}, @{N="libvpx"; F="vpx.lib"}, @{N="libyuv"; F="yuv.lib"}, @{N="swresample"; F="swresample.lib"}, @{N="avcodec"; F="avcodec.lib"}, @{N="avutil"; F="avutil.lib"} ) foreach ($lib in $criticalLibs) { $libPath = Join-Path $vcpkgLibDir $lib.F if (Test-Path $libPath) { OK "vcpkg: $($lib.N)" } else { Write-Host " [FAIL] vcpkg: $($lib.N) ($($lib.F) nicht gefunden)" -ForegroundColor Red; $failed += "vcpkg:$($lib.N)" } } # Umgebungsvariablen foreach ($v in @(@{N="VCPKG_ROOT";V=$VcpkgRoot},@{N="FLUTTER_ROOT";V=$FlutterRoot},@{N="LLVM_HOME";V=$LlvmHome})) { $val = [System.Environment]::GetEnvironmentVariable($v.N, [System.EnvironmentVariableTarget]::Machine) if ($val -eq $v.V) { OK "Env: $($v.N)" } else { Write-Host " [FAIL] $($v.N) = '$val' (erwartet: '$($v.V)')" -ForegroundColor Red; $failed += $v.N } } # VS Build Tools $vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" if ((Test-Path $vsWhere) -and (& $vsWhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath 2>&1)) { OK "VS Build Tools (MSVC v143)" } else { Write-Host " [FAIL] VS Build Tools - MSVC v143 nicht gefunden" -ForegroundColor Red $failed += "VS Build Tools" } # --------------------------------------------------------------------------- # Ergebnis # --------------------------------------------------------------------------- Write-Host "" if ($failed.Count -gt 0) { Write-Host "SETUP FEHLGESCHLAGEN - Fehlende Komponenten:" -ForegroundColor Red $failed | ForEach-Object { Write-Host " - $_" -ForegroundColor Red } exit 1 } else { Write-Host "SETUP ABGESCHLOSSEN - Alle Komponenten installiert und verifiziert." -ForegroundColor Green Write-Host "" Write-Host "Naechster Schritt: GitLab Runner registrieren:" -ForegroundColor Yellow Write-Host ' gitlab-runner register --non-interactive --url \' Write-Host ' --token --executor shell --shell powershell \' Write-Host ' --tag-list "windows-runner" --description "Windows Build Runner"' Write-Host "" Write-Host " WICHTIG: --shell powershell (NICHT pwsh) verwenden!" -ForegroundColor Yellow Write-Host "" Write-Host "Dann starten mit: gitlab-runner start" -ForegroundColor Yellow Write-Host "" Write-Host "HINWEIS: Neustart empfohlen, damit alle PATH-Aenderungen wirksam werden." -ForegroundColor Yellow exit 0 }