#requires -Version 5.1 [CmdletBinding()] param( [switch]$OneFile, [switch]$SkipInstaller ) $ErrorActionPreference = "Stop" $Root = Split-Path -Parent $MyInvocation.MyCommand.Path Set-Location $Root function Get-Python { $candidates = @( @{ Command = "py"; Arguments = @("-3.11") }, @{ Command = "py"; Arguments = @("-3") }, @{ Command = "python"; Arguments = @() }, @{ Command = "python3"; Arguments = @() } ) foreach ($candidate in $candidates) { try { $exe = $candidate.Command $exeArgs = @($candidate.Arguments) $probe = & $exe @exeArgs -c "import sys; print('{0}.{1}'.format(sys.version_info[0], sys.version_info[1]))" 2>$null if ($LASTEXITCODE -eq 0 -and (($probe | Out-String).Trim() -eq "3.11")) { return $candidate } } catch { } } throw "Python 3.11 x64 is required. Install it from python.org and retry." } $version = "1.0.0" $venv = Join-Path $Root ".venv-build" $python = Get-Python if (-not (Test-Path $venv)) { Write-Host "Creating build environment..." $pythonExe = $python.Command $pythonArgs = @($python.Arguments) & $pythonExe @pythonArgs -m venv $venv } $py = Join-Path $venv "Scripts\python.exe" if (-not (Test-Path $py)) { throw "The build virtual environment could not be created." } & $py -m pip install --upgrade pip & $py -m pip install -r (Join-Path $Root "requirements-dev.txt") if ($LASTEXITCODE -ne 0) { throw "Dependency installation failed." } if ($OneFile) { $env:BOLTCLAM_ONEFILE = "1" } else { Remove-Item Env:BOLTCLAM_ONEFILE -ErrorAction SilentlyContinue } Write-Host "Building BoltClam $version..." & $py -m PyInstaller --noconfirm --clean (Join-Path $Root "BoltClam.spec") if ($LASTEXITCODE -ne 0) { throw "PyInstaller failed." } $dist = Join-Path $Root "dist" $artifacts = @() if ($OneFile) { $exe = Join-Path $dist "BoltClam.exe" if (-not (Test-Path $exe)) { throw "Expected $exe was not produced." } $artifacts += $exe } else { $folder = Join-Path $dist "BoltClam" $exe = Join-Path $folder "BoltClam.exe" if (-not (Test-Path $exe)) { throw "Expected $exe was not produced." } $zip = Join-Path $dist "BoltClam-$version-windows-x64.zip" if (Test-Path $zip) { Remove-Item $zip -Force } Compress-Archive -Path (Join-Path $folder "*") -DestinationPath $zip -CompressionLevel Optimal $artifacts += $zip if (-not $SkipInstaller) { $isccCandidates = @( "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe", "$env:ProgramFiles\Inno Setup 6\ISCC.exe" ) $iscc = $isccCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1 if ($iscc) { Write-Host "Building installer with $iscc..." & $iscc "/DMyAppVersion=$version" (Join-Path $Root "installer\BoltClam.iss") if ($LASTEXITCODE -ne 0) { throw "Inno Setup failed." } $setup = Join-Path $dist "BoltClam-$version-Setup.exe" if (Test-Path $setup) { $artifacts += $setup } } else { Write-Warning "Inno Setup 6 was not found; skipping the installer." } } } $checksumPath = Join-Path $dist "SHA256SUMS.txt" $lines = foreach ($artifact in $artifacts) { $hash = (Get-FileHash -Algorithm SHA256 $artifact).Hash.ToLowerInvariant() "$hash $(Split-Path -Leaf $artifact)" } $lines | Set-Content -Encoding ASCII $checksumPath Write-Host "" Write-Host "Built:" $artifacts | ForEach-Object { Write-Host " $_" } Write-Host "Checksums: $checksumPath"