mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-19 02:33:32 +00:00
feat: Add Profile-Guided Optimization (PGO) build support
Implements two-stage PGO build system with CMake integration and automated build scripts for Windows, Linux, and macOS. Supports MSVC, GCC, and Clang compilers. PGO enables runtime profiling-based optimizations for improved emulator performance. Includes helper scripts to streamline the build workflow and resolve platform-specific issues. Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
209
pgo-build.ps1
Normal file
209
pgo-build.ps1
Normal file
@@ -0,0 +1,209 @@
|
||||
# SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# PGO Build Script for Citron (Windows/PowerShell)
|
||||
# This script automates the Profile-Guided Optimization build process
|
||||
|
||||
param(
|
||||
[Parameter(Position=0, Mandatory=$true)]
|
||||
[ValidateSet('generate', 'use', 'clean')]
|
||||
[string]$Stage,
|
||||
|
||||
[Parameter()]
|
||||
[int]$Jobs = 0,
|
||||
|
||||
[Parameter()]
|
||||
[switch]$EnableLTO,
|
||||
|
||||
[Parameter()]
|
||||
[switch]$Help
|
||||
)
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$BuildDir = Join-Path $ScriptDir "build"
|
||||
$PgoProfilesDir = Join-Path $BuildDir "pgo-profiles"
|
||||
$BackupProfilesDir = Join-Path $ScriptDir "pgo-profiles-backup"
|
||||
|
||||
function Show-Usage {
|
||||
Write-Host @"
|
||||
Usage: .\pgo-build.ps1 [STAGE] [OPTIONS]
|
||||
|
||||
STAGE can be:
|
||||
generate - Build with PGO instrumentation (Stage 1)
|
||||
use - Build using PGO profile data (Stage 2)
|
||||
clean - Clean build directory but preserve profiles
|
||||
|
||||
Example:
|
||||
.\pgo-build.ps1 generate # Build instrumented version
|
||||
# Run citron.exe to collect profiles
|
||||
.\pgo-build.ps1 use # Build optimized version
|
||||
|
||||
Options:
|
||||
-Jobs N Number of parallel jobs (default: auto-detect)
|
||||
-EnableLTO Enable Link-Time Optimization
|
||||
-Help Show this help message
|
||||
"@
|
||||
}
|
||||
|
||||
function Write-Header {
|
||||
param([string]$Message)
|
||||
Write-Host "`n=================================================================" -ForegroundColor Cyan
|
||||
Write-Host $Message -ForegroundColor Cyan
|
||||
Write-Host "=================================================================`n" -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function Write-Info {
|
||||
param([string]$Message)
|
||||
Write-Host "[INFO] $Message" -ForegroundColor Green
|
||||
}
|
||||
|
||||
function Write-Warning {
|
||||
param([string]$Message)
|
||||
Write-Host "[WARNING] $Message" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
function Write-Error-Custom {
|
||||
param([string]$Message)
|
||||
Write-Host "[ERROR] $Message" -ForegroundColor Red
|
||||
}
|
||||
|
||||
if ($Help) {
|
||||
Show-Usage
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Auto-detect number of processors
|
||||
if ($Jobs -eq 0) {
|
||||
$Jobs = $env:NUMBER_OF_PROCESSORS
|
||||
if (-not $Jobs) { $Jobs = 4 }
|
||||
}
|
||||
|
||||
$LtoFlag = if ($EnableLTO) { "ON" } else { "OFF" }
|
||||
|
||||
# Clean stage
|
||||
if ($Stage -eq "clean") {
|
||||
Write-Header "Cleaning Build Directory"
|
||||
|
||||
if (Test-Path $PgoProfilesDir) {
|
||||
Write-Info "Backing up PGO profiles..."
|
||||
New-Item -ItemType Directory -Force -Path $BackupProfilesDir | Out-Null
|
||||
Copy-Item -Path "$PgoProfilesDir\*" -Destination $BackupProfilesDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
if (Test-Path $BuildDir) {
|
||||
Write-Info "Removing build directory..."
|
||||
Remove-Item -Path $BuildDir -Recurse -Force
|
||||
}
|
||||
|
||||
if (Test-Path $BackupProfilesDir) {
|
||||
Write-Info "Restoring PGO profiles..."
|
||||
New-Item -ItemType Directory -Force -Path $PgoProfilesDir | Out-Null
|
||||
Move-Item -Path "$BackupProfilesDir\*" -Destination $PgoProfilesDir -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path $BackupProfilesDir -Recurse -Force
|
||||
}
|
||||
|
||||
Write-Info "Clean complete!"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Generate stage
|
||||
if ($Stage -eq "generate") {
|
||||
Write-Header "PGO Stage 1: Generate Profile Data"
|
||||
|
||||
# Create build directory
|
||||
New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null
|
||||
Set-Location $BuildDir
|
||||
|
||||
# Configure
|
||||
Write-Info "Configuring CMake..."
|
||||
cmake .. `
|
||||
-DCITRON_ENABLE_PGO_GENERATE=ON `
|
||||
-DCITRON_ENABLE_LTO=$LtoFlag `
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error-Custom "CMake configuration failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Build
|
||||
Write-Info "Building instrumented Citron (this may take a while)..."
|
||||
cmake --build . --config Release -j $Jobs
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error-Custom "Build failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Header "Build Complete!"
|
||||
Write-Info "Next steps:"
|
||||
Write-Host " 1. Run: .\bin\Release\citron.exe"
|
||||
Write-Host " 2. Play games for 15-30 minutes to collect profile data"
|
||||
Write-Host " 3. Exit citron"
|
||||
Write-Host " 4. Run: .\pgo-build.ps1 use"
|
||||
|
||||
Set-Location $ScriptDir
|
||||
}
|
||||
|
||||
# Use stage
|
||||
if ($Stage -eq "use") {
|
||||
Write-Header "PGO Stage 2: Build Optimized Binary"
|
||||
|
||||
# Check if profile data exists
|
||||
if (-not (Test-Path $PgoProfilesDir) -or -not (Get-ChildItem $PgoProfilesDir -ErrorAction SilentlyContinue)) {
|
||||
Write-Error-Custom "No profile data found in $PgoProfilesDir"
|
||||
Write-Info "Please run the generate stage first and collect profile data"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Backup profiles if build directory exists
|
||||
if (Test-Path $BuildDir) {
|
||||
Write-Info "Backing up PGO profiles..."
|
||||
New-Item -ItemType Directory -Force -Path $BackupProfilesDir | Out-Null
|
||||
Copy-Item -Path "$PgoProfilesDir\*" -Destination $BackupProfilesDir -Recurse -Force
|
||||
Remove-Item -Path $BuildDir -Recurse -Force
|
||||
}
|
||||
|
||||
# Create build directory and restore profiles
|
||||
New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null
|
||||
if (Test-Path $BackupProfilesDir) {
|
||||
New-Item -ItemType Directory -Force -Path $PgoProfilesDir | Out-Null
|
||||
Move-Item -Path "$BackupProfilesDir\*" -Destination $PgoProfilesDir -Force
|
||||
Remove-Item -Path $BackupProfilesDir -Recurse -Force
|
||||
}
|
||||
|
||||
Set-Location $BuildDir
|
||||
|
||||
# Configure
|
||||
Write-Info "Configuring CMake..."
|
||||
cmake .. `
|
||||
-DCITRON_ENABLE_PGO_USE=ON `
|
||||
-DCITRON_ENABLE_LTO=$LtoFlag `
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error-Custom "CMake configuration failed"
|
||||
Set-Location $ScriptDir
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Build
|
||||
Write-Info "Building optimized Citron (this may take a while)..."
|
||||
cmake --build . --config Release -j $Jobs
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error-Custom "Build failed"
|
||||
Set-Location $ScriptDir
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Header "Build Complete!"
|
||||
Write-Info "Your optimized Citron binary is ready!"
|
||||
Write-Info "Location: $BuildDir\bin\Release\citron.exe"
|
||||
Write-Host ""
|
||||
Write-Info "This build is optimized for your specific usage patterns."
|
||||
Write-Info "Enjoy improved performance! 🚀"
|
||||
|
||||
Set-Location $ScriptDir
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user