dragonmoonlight/scripts/build-installer-win.ps1

183 lines
6 KiB
PowerShell

param(
[string]$Version = "",
[string]$BuildDir = "build\win",
[string]$StagingDir = "dist\win",
[string]$WintunVersion = "0.14.1",
[switch]$Sign,
[string]$SignCert = ""
)
$ErrorActionPreference = "Stop"
# Color output functions
function Write-Info { Write-Host $args -ForegroundColor Cyan }
function Write-Success { Write-Host $args -ForegroundColor Green }
function Write-Error { Write-Host $args -ForegroundColor Red }
try {
Write-Info "=== DragonMoonlight Windows Installer Build ==="
# Determine version
if ([string]::IsNullOrEmpty($Version)) {
Write-Info "Version not provided, attempting git describe..."
try {
$Version = git describe --tags --abbrev=0 2>$null
if ([string]::IsNullOrEmpty($Version)) {
$Version = "0.1.0"
}
} catch {
$Version = "0.1.0"
}
}
Write-Success "Building DragonMoonlight version: $Version"
# Check prerequisites
Write-Info "Checking prerequisites..."
$prerequisites = @("cmake", "cargo", "iscc", "windeployqt")
foreach ($tool in $prerequisites) {
try {
if ($tool -eq "iscc") {
$result = Get-Command "iscc.exe" -ErrorAction Stop
} elseif ($tool -eq "windeployqt") {
$result = Get-Command "windeployqt.exe" -ErrorAction Stop
} else {
$result = Get-Command $tool -ErrorAction Stop
}
Write-Success "$tool found"
} catch {
Write-Error "$tool not found. Please install it before proceeding."
throw "Missing prerequisite: $tool"
}
}
# Build boringtun
Write-Info "Building boringtun..."
& pwsh scripts\build-boringtun-win.ps1
if ($LASTEXITCODE -ne 0) {
throw "boringtun build failed"
}
Write-Success "boringtun built successfully"
# CMake configure
Write-Info "Running CMake configure..."
cmake -B $BuildDir -A x64 -DCMAKE_BUILD_TYPE=Release
if ($LASTEXITCODE -ne 0) {
throw "CMake configure failed"
}
Write-Success "CMake configure completed"
# CMake build
Write-Info "Building with CMake..."
cmake --build $BuildDir --config Release
if ($LASTEXITCODE -ne 0) {
throw "CMake build failed"
}
Write-Success "CMake build completed"
# Create staging directory and copy executable
Write-Info "Staging release files..."
if (-not (Test-Path $StagingDir)) {
New-Item -ItemType Directory -Path $StagingDir -Force | Out-Null
}
$exePath = Join-Path $BuildDir "Release\DragonMoonlight.exe"
if (-not (Test-Path $exePath)) {
throw "DragonMoonlight.exe not found at $exePath"
}
Copy-Item -Path $exePath -Destination $StagingDir -Force
Write-Success "Copied DragonMoonlight.exe to $StagingDir"
# Run windeployqt
Write-Info "Running windeployqt..."
$stagedExe = Join-Path $StagingDir "DragonMoonlight.exe"
windeployqt --release --qmldir app $stagedExe
if ($LASTEXITCODE -ne 0) {
throw "windeployqt failed"
}
Write-Success "windeployqt completed"
# Download wintun.dll
Write-Info "Downloading Wintun..."
$wintunUrl = "https://www.wintun.net/builds/wintun-$WintunVersion.zip"
$tempDir = Join-Path $env:TEMP "wintun_build"
if (-not (Test-Path $tempDir)) {
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
}
$wintunZip = Join-Path $tempDir "wintun-$WintunVersion.zip"
try {
Write-Info "Downloading from $wintunUrl..."
Invoke-WebRequest -Uri $wintunUrl -OutFile $wintunZip -UseBasicParsing
Write-Info "Extracting wintun.dll..."
Expand-Archive -Path $wintunZip -DestinationPath $tempDir -Force
$wintunDll = Join-Path $tempDir "wintun\bin\amd64\wintun.dll"
if (-not (Test-Path $wintunDll)) {
throw "wintun.dll not found in extracted archive"
}
# Verify wintun.dll size sanity check (x64 is ~50-80 KB)
$actualSize = (Get-Item $wintunDll).Length
if ($actualSize -lt 30000 -or $actualSize -gt 200000) {
throw "wintun.dll size check failed ($actualSize bytes) — download may be corrupt or tampered"
}
Write-Info "wintun.dll verified ($actualSize bytes)"
Copy-Item -Path $wintunDll -Destination $StagingDir -Force
Write-Success "Wintun.dll extracted and copied to $StagingDir"
} finally {
if (Test-Path $wintunZip) {
Remove-Item -Path $wintunZip -Force
}
}
# Run Inno Setup
Write-Info "Building installer with Inno Setup..."
$issArgs = @("/DMyAppVersion=$Version", "scripts\DragonMoonlight.iss")
if ($Sign -or -not [string]::IsNullOrEmpty($SignCert)) {
$cert = $SignCert
if ([string]::IsNullOrEmpty($cert) -and -not [string]::IsNullOrEmpty($env:SIGNTOOL_CERT)) {
$cert = $env:SIGNTOOL_CERT
}
if (-not [string]::IsNullOrEmpty($cert)) {
Write-Info "Code signing enabled with certificate: $cert"
$env:SIGNTOOL_CERT = $cert
}
}
iscc @issArgs
if ($LASTEXITCODE -ne 0) {
throw "Inno Setup build failed"
}
Write-Success "Inno Setup build completed"
# Report results
$outputExe = Join-Path "dist" "DragonMoonlight-$Version-Setup.exe"
if (Test-Path $outputExe) {
Write-Success "Installer created: $outputExe"
$sha256 = (Get-FileHash -Path $outputExe -Algorithm SHA256).Hash
Write-Success "SHA256: $sha256"
Write-Info "Installer build successful!"
} else {
throw "Installer file not found at expected location: $outputExe"
}
}
catch {
Write-Error "Build failed: $_"
exit 1
}
finally {
# Clean up temporary files
$tempDir = Join-Path $env:TEMP "wintun_build"
if (Test-Path $tempDir) {
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}
}