176 lines
7.3 KiB
PowerShell
176 lines
7.3 KiB
PowerShell
param(
|
|
[string]$Config = "Release",
|
|
[switch]$Clean,
|
|
[switch]$Test,
|
|
[switch]$Package
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$root = $PSScriptRoot
|
|
$build = Join-Path $root "build"
|
|
|
|
if ($Clean -and (Test-Path $build)) { Remove-Item -Recurse -Force $build }
|
|
|
|
if (-not (Get-Command cl.exe -ErrorAction SilentlyContinue)) {
|
|
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
|
if (-not (Test-Path $vswhere)) { throw "vswhere.exe not found - install Visual Studio with the C++ workload" }
|
|
$vsPath = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
|
|
if (-not $vsPath) { throw "no Visual Studio install with the C++ toolset" }
|
|
|
|
$vcvars = Join-Path $vsPath "VC\Auxiliary\Build\vcvars64.bat"
|
|
if (-not (Test-Path $vcvars)) { throw "vcvars64.bat not found under $vsPath" }
|
|
|
|
cmd /c "`"$vcvars`" && set" | ForEach-Object {
|
|
if ($_ -match '^([^=]+)=(.*)$') { Set-Item -Path "env:$($matches[1])" -Value $matches[2] }
|
|
}
|
|
if (-not (Get-Command cl.exe -ErrorAction SilentlyContinue)) { throw "vcvars64 did not put cl.exe on PATH" }
|
|
}
|
|
|
|
$tools = Join-Path $root ".tools"
|
|
|
|
function Get-File($url, $out, $sha) {
|
|
Write-Host "downloading $url"
|
|
$ProgressPreference = "SilentlyContinue"
|
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $out
|
|
if (-not $sha) { return }
|
|
$stream = [IO.File]::OpenRead($out)
|
|
try { $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($stream)) -replace "-", "" }
|
|
finally { $stream.Dispose() }
|
|
if ($hash -ne $sha) {
|
|
Remove-Item -Force $out
|
|
throw "$url does not match its checksum"
|
|
}
|
|
}
|
|
|
|
function Expand-Zip($zip, $dir) {
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
if (Test-Path $dir) { Remove-Item -Recurse -Force $dir }
|
|
[IO.Compression.ZipFile]::ExtractToDirectory($zip, $dir)
|
|
Remove-Item -Force $zip
|
|
}
|
|
|
|
function Find-Python {
|
|
$ErrorActionPreference = "Continue"
|
|
foreach ($candidate in @("py -3", "python")) {
|
|
$exe, $prefix = $candidate -split " ", 2
|
|
if (-not (Get-Command $exe -ErrorAction SilentlyContinue)) { continue }
|
|
$prefix = @($prefix | Where-Object { $_ })
|
|
$found = & $exe @prefix -c "import sys; print(sys.executable if sys.version_info >= (3, 8) else '')" 2>$null
|
|
if ($LASTEXITCODE -eq 0 -and $found) { return "$found".Trim() }
|
|
}
|
|
return $null
|
|
}
|
|
|
|
function Get-Python {
|
|
$portable = Join-Path $tools "python\python.exe"
|
|
if (Test-Path $portable) { return $portable }
|
|
$found = Find-Python
|
|
if ($found) { return $found }
|
|
|
|
Write-Host "Python not found, setting up a portable copy in .tools" -ForegroundColor Yellow
|
|
$dir = Join-Path $tools "python"
|
|
New-Item -ItemType Directory -Force -Path $dir | Out-Null
|
|
$zip = Join-Path $tools "python.zip"
|
|
Get-File "https://www.python.org/ftp/python/3.12.10/python-3.12.10-embed-amd64.zip" $zip "4ACBED6DD1C744B0376E3B1CF57CE906F9DC9E95E68824584C8099A63025A3C3"
|
|
Expand-Zip $zip $dir
|
|
Get-ChildItem $dir -Filter "python*._pth" | ForEach-Object { Add-Content -LiteralPath $_.FullName "import site" }
|
|
$getPip = Join-Path $tools "get-pip.py"
|
|
Get-File "https://bootstrap.pypa.io/get-pip.py" $getPip $null
|
|
$ErrorActionPreference = "Continue"
|
|
& $portable $getPip -q --no-warn-script-location --disable-pip-version-check
|
|
if ($LASTEXITCODE -ne 0) { throw "could not set up pip for the portable Python" }
|
|
Remove-Item -Force $getPip
|
|
return $portable
|
|
}
|
|
|
|
function Initialize-Protobuf($python) {
|
|
$ErrorActionPreference = "Continue"
|
|
& $python -c "import google.protobuf" 2>$null
|
|
if ($LASTEXITCODE -eq 0) { return }
|
|
Write-Host "installing the protobuf Python package" -ForegroundColor Yellow
|
|
& $python -m pip install -q --disable-pip-version-check --no-warn-script-location protobuf
|
|
if ($LASTEXITCODE -ne 0) { & $python -m pip install -q --disable-pip-version-check --no-warn-script-location --user protobuf }
|
|
if ($LASTEXITCODE -ne 0) { throw "could not install the protobuf Python package" }
|
|
}
|
|
|
|
function Get-Protoc {
|
|
$command = Get-Command protoc -ErrorAction SilentlyContinue
|
|
if ($command) { return $command.Source }
|
|
$portable = Join-Path $tools "protoc\bin\protoc.exe"
|
|
if (-not (Test-Path $portable)) {
|
|
Write-Host "protoc not found, downloading it into .tools" -ForegroundColor Yellow
|
|
New-Item -ItemType Directory -Force -Path $tools | Out-Null
|
|
$zip = Join-Path $tools "protoc.zip"
|
|
Get-File "https://github.com/protocolbuffers/protobuf/releases/download/v33.0/protoc-33.0-win64.zip" $zip "3742CD49C8B6BD78B6760540367EB0FF62FA70A1032E15DAFE131BFAF296986A"
|
|
Expand-Zip $zip (Join-Path $tools "protoc")
|
|
}
|
|
return $portable
|
|
}
|
|
|
|
function Initialize-Dotnet {
|
|
$env:DOTNET_NOLOGO = "1"
|
|
$env:DOTNET_GENERATE_ASPNET_CERTIFICATE = "false"
|
|
if (Get-Command dotnet -ErrorAction SilentlyContinue) { return }
|
|
$dir = Join-Path $tools "dotnet"
|
|
if (-not (Test-Path (Join-Path $dir "dotnet.exe"))) {
|
|
Write-Host ".NET SDK not found, installing it into .tools" -ForegroundColor Yellow
|
|
New-Item -ItemType Directory -Force -Path $tools | Out-Null
|
|
$script = Join-Path $tools "dotnet-install.ps1"
|
|
Get-File "https://dot.net/v1/dotnet-install.ps1" $script $null
|
|
& powershell -NoProfile -ExecutionPolicy Bypass -File $script -Channel LTS -InstallDir $dir -NoPath
|
|
Remove-Item -Force $script
|
|
if (-not (Test-Path (Join-Path $dir "dotnet.exe"))) { throw "could not install the .NET SDK" }
|
|
}
|
|
$env:DOTNET_ROOT = $dir
|
|
$env:PATH = "$dir;$env:PATH"
|
|
}
|
|
|
|
$python = Get-Python
|
|
Initialize-Protobuf $python
|
|
$protoc = Get-Protoc
|
|
|
|
New-Item -ItemType Directory -Force -Path $build | Out-Null
|
|
cmake -S "$root" -B "$build" -G Ninja "-DCMAKE_BUILD_TYPE=$Config" "-DPython3_EXECUTABLE=$python" "-DPROTOC_EXECUTABLE=$protoc"
|
|
if ($LASTEXITCODE -ne 0) { throw "cmake configure failed" }
|
|
|
|
cmake --build $build --parallel
|
|
if ($LASTEXITCODE -ne 0) { throw "build failed" }
|
|
|
|
$launcher = $true
|
|
try {
|
|
Initialize-Dotnet
|
|
} catch {
|
|
if ($Package) { throw }
|
|
Write-Host "$($_.Exception.Message), skipping the launcher" -ForegroundColor Yellow
|
|
$launcher = $false
|
|
}
|
|
if ($launcher) {
|
|
& cmd /c "`"$(Join-Path $root 'gui\build.bat')`""
|
|
if ($LASTEXITCODE -ne 0) { throw "launcher build failed" }
|
|
}
|
|
|
|
if ($Test) {
|
|
& (Join-Path $build "bin\capysr_tests.exe")
|
|
if ($LASTEXITCODE -ne 0) { throw "tests failed" }
|
|
}
|
|
|
|
if ($Package) {
|
|
$dist = Join-Path $build "dist\CapySR-win64"
|
|
if (Test-Path $dist) { Remove-Item -Recurse -Force $dist }
|
|
New-Item -ItemType Directory -Force -Path (Join-Path $dist "data") | Out-Null
|
|
Copy-Item (Join-Path $build "bin\capysr.exe") $dist
|
|
Copy-Item (Join-Path $build "bin\CapyLauncher.exe") $dist
|
|
foreach ($dir in "config", "resources", "launcher") {
|
|
Copy-Item -Recurse (Join-Path $root $dir) (Join-Path $dist $dir)
|
|
}
|
|
Copy-Item (Join-Path $root "data\freesr-data.json") (Join-Path $dist "data")
|
|
$zip = "$dist.zip"
|
|
if (Test-Path $zip) { Remove-Item -Force $zip }
|
|
Compress-Archive -Path "$dist\*" -DestinationPath $zip
|
|
Write-Host "packaged $zip"
|
|
}
|
|
|
|
Write-Host "built $build\bin\capysr.exe" -ForegroundColor Green
|
|
if ($launcher) { Write-Host "built $build\bin\CapyLauncher.exe" -ForegroundColor Green }
|