mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-19 10:43:33 +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:
9
.gitignore
vendored
9
.gitignore
vendored
@@ -36,3 +36,12 @@ CMakeSettings.json
|
|||||||
# Windows global filetypes
|
# Windows global filetypes
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
|
# PGO (Profile-Guided Optimization) files
|
||||||
|
pgo-profiles-backup/
|
||||||
|
*.pgd
|
||||||
|
*.pgc
|
||||||
|
*.profraw
|
||||||
|
*.profdata
|
||||||
|
*.gcda
|
||||||
|
*.gcno
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modul
|
|||||||
include(DownloadExternals)
|
include(DownloadExternals)
|
||||||
include(CMakeDependentOption)
|
include(CMakeDependentOption)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
include(PGO)
|
||||||
|
|
||||||
# Disable Warnings as Errors for MSVC
|
# Disable Warnings as Errors for MSVC
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
@@ -78,6 +79,10 @@ option(CITRON_CHECK_SUBMODULES "Check if submodules are present" ON)
|
|||||||
|
|
||||||
option(CITRON_ENABLE_LTO "Enable link-time optimization" OFF)
|
option(CITRON_ENABLE_LTO "Enable link-time optimization" OFF)
|
||||||
|
|
||||||
|
option(CITRON_ENABLE_PGO_GENERATE "Build with PGO instrumentation to generate profile data (Stage 1)" OFF)
|
||||||
|
option(CITRON_ENABLE_PGO_USE "Build using PGO profile data for optimization (Stage 2)" OFF)
|
||||||
|
set(CITRON_PGO_PROFILE_DIR "${CMAKE_BINARY_DIR}/pgo-profiles" CACHE PATH "Directory to store PGO profile data")
|
||||||
|
|
||||||
option(CITRON_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" OFF)
|
option(CITRON_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" OFF)
|
||||||
|
|
||||||
option(CITRON_ENABLE_PORTABLE "Allow citron to enable portable mode if a user folder is found in the CWD" ON)
|
option(CITRON_ENABLE_PORTABLE "Allow citron to enable portable mode if a user folder is found in the CWD" ON)
|
||||||
@@ -792,6 +797,22 @@ if(DEFINED HAS_BOOST_PROCESS_DEFINITION)
|
|||||||
target_compile_definitions(core PRIVATE ${HAS_BOOST_PROCESS_DEFINITION})
|
target_compile_definitions(core PRIVATE ${HAS_BOOST_PROCESS_DEFINITION})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Apply PGO configuration to main targets
|
||||||
|
if(CITRON_ENABLE_PGO_GENERATE OR CITRON_ENABLE_PGO_USE)
|
||||||
|
if(TARGET citron)
|
||||||
|
citron_configure_pgo(citron)
|
||||||
|
endif()
|
||||||
|
if(TARGET citron-cmd)
|
||||||
|
citron_configure_pgo(citron-cmd)
|
||||||
|
endif()
|
||||||
|
if(TARGET citron-room)
|
||||||
|
citron_configure_pgo(citron-room)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Print PGO instructions
|
||||||
|
citron_print_pgo_instructions()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Set citron project or citron-cmd project as default StartUp Project in Visual Studio depending on whether QT is enabled or not
|
# Set citron project or citron-cmd project as default StartUp Project in Visual Studio depending on whether QT is enabled or not
|
||||||
if(ENABLE_QT)
|
if(ENABLE_QT)
|
||||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT citron)
|
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT citron)
|
||||||
|
|||||||
274
CMakeModules/PGO.cmake
Normal file
274
CMakeModules/PGO.cmake
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Profile-Guided Optimization (PGO) Support
|
||||||
|
#
|
||||||
|
# This module provides functions to enable Profile-Guided Optimization (PGO) for Citron.
|
||||||
|
# PGO is a two-stage compiler optimization technique:
|
||||||
|
# 1. GENERATE stage: Build with instrumentation to collect profiling data during runtime
|
||||||
|
# 2. USE stage: Rebuild using the collected profiling data to optimize hot paths
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# set(CITRON_ENABLE_PGO_GENERATE ON) # First build: generate profiling data
|
||||||
|
# set(CITRON_ENABLE_PGO_USE ON) # Second build: use profiling data
|
||||||
|
# set(CITRON_PGO_PROFILE_DIR "${CMAKE_BINARY_DIR}/pgo-profiles") # Optional: custom profile directory
|
||||||
|
|
||||||
|
# PGO profile directory - where .pgd/.profraw/.profdata files are stored
|
||||||
|
if(NOT DEFINED CITRON_PGO_PROFILE_DIR)
|
||||||
|
set(CITRON_PGO_PROFILE_DIR "${CMAKE_BINARY_DIR}/pgo-profiles" CACHE PATH "Directory to store PGO profile data")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Create the profile directory if it doesn't exist
|
||||||
|
file(MAKE_DIRECTORY "${CITRON_PGO_PROFILE_DIR}")
|
||||||
|
|
||||||
|
# Function to copy MSVC PGO runtime DLLs
|
||||||
|
function(citron_copy_pgo_runtime_dlls target_name)
|
||||||
|
if(NOT MSVC)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Find the Visual Studio installation directory
|
||||||
|
get_filename_component(MSVC_DIR "${CMAKE_CXX_COMPILER}" DIRECTORY)
|
||||||
|
get_filename_component(MSVC_DIR "${MSVC_DIR}" DIRECTORY)
|
||||||
|
get_filename_component(MSVC_DIR "${MSVC_DIR}" DIRECTORY)
|
||||||
|
|
||||||
|
# Common locations for PGO runtime DLLs
|
||||||
|
set(PGO_DLL_PATHS
|
||||||
|
"${MSVC_DIR}/VC/Redist/MSVC/*/x64/Microsoft.VC*.CRT/pgort140.dll"
|
||||||
|
"${MSVC_DIR}/VC/Redist/MSVC/*/x86/Microsoft.VC*.CRT/pgort140.dll"
|
||||||
|
"${MSVC_DIR}/VC/Tools/MSVC/*/bin/Hostx64/x64/pgort140.dll"
|
||||||
|
"${MSVC_DIR}/VC/Tools/MSVC/*/bin/Hostx64/x86/pgort140.dll"
|
||||||
|
"${MSVC_DIR}/VC/Tools/MSVC/*/bin/Hostx86/x64/pgort140.dll"
|
||||||
|
"${MSVC_DIR}/VC/Tools/MSVC/*/bin/Hostx86/x86/pgort140.dll"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find the PGO runtime DLL
|
||||||
|
set(PGO_DLL_FOUND FALSE)
|
||||||
|
foreach(dll_pattern ${PGO_DLL_PATHS})
|
||||||
|
file(GLOB PGO_DLL_CANDIDATES ${dll_pattern})
|
||||||
|
if(PGO_DLL_CANDIDATES)
|
||||||
|
list(GET PGO_DLL_CANDIDATES 0 PGO_DLL_PATH)
|
||||||
|
set(PGO_DLL_FOUND TRUE)
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(PGO_DLL_FOUND)
|
||||||
|
message(STATUS " [${target_name}] Found PGO runtime DLL: ${PGO_DLL_PATH}")
|
||||||
|
|
||||||
|
# Get the target's output directory
|
||||||
|
get_target_property(TARGET_OUTPUT_DIR ${target_name} RUNTIME_OUTPUT_DIRECTORY)
|
||||||
|
if(NOT TARGET_OUTPUT_DIR)
|
||||||
|
get_target_property(TARGET_OUTPUT_DIR ${target_name} RUNTIME_OUTPUT_DIRECTORY_DEBUG)
|
||||||
|
endif()
|
||||||
|
if(NOT TARGET_OUTPUT_DIR)
|
||||||
|
set(TARGET_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Copy the DLL to the output directory
|
||||||
|
add_custom_command(TARGET ${target_name} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${PGO_DLL_PATH}"
|
||||||
|
"${TARGET_OUTPUT_DIR}/"
|
||||||
|
COMMENT "Copying PGO runtime DLL for ${target_name}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(WARNING "PGO runtime DLL (pgort140.dll) not found. The instrumented build may not run properly.")
|
||||||
|
message(STATUS " Please ensure Visual Studio is properly installed with PGO support.")
|
||||||
|
message(STATUS " You may need to install the 'MSVC v143 - VS 2022 C++ x64/x86 build tools' component.")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Function to configure PGO for a specific target
|
||||||
|
function(citron_configure_pgo target_name)
|
||||||
|
if(NOT TARGET ${target_name})
|
||||||
|
message(WARNING "Target ${target_name} does not exist, skipping PGO configuration")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Only configure PGO if either GENERATE or USE is enabled
|
||||||
|
if(NOT CITRON_ENABLE_PGO_GENERATE AND NOT CITRON_ENABLE_PGO_USE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Ensure both stages are not enabled at the same time
|
||||||
|
if(CITRON_ENABLE_PGO_GENERATE AND CITRON_ENABLE_PGO_USE)
|
||||||
|
message(FATAL_ERROR "Cannot enable both CITRON_ENABLE_PGO_GENERATE and CITRON_ENABLE_PGO_USE simultaneously. Please build twice: first with GENERATE, then with USE.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Configuring PGO for target: ${target_name}")
|
||||||
|
|
||||||
|
# MSVC-specific PGO
|
||||||
|
if(MSVC)
|
||||||
|
if(CITRON_ENABLE_PGO_GENERATE)
|
||||||
|
message(STATUS " [${target_name}] MSVC PGO: GENERATE stage")
|
||||||
|
# Use FASTGENPROFILE for faster profiling with similar accuracy
|
||||||
|
# GENPROFILE provides more detailed profiling but is slower
|
||||||
|
# You can change FASTGENPROFILE to GENPROFILE for more accuracy but slower profiling
|
||||||
|
target_compile_options(${target_name} PRIVATE /GL)
|
||||||
|
target_link_options(${target_name} PRIVATE
|
||||||
|
/LTCG
|
||||||
|
/FASTGENPROFILE
|
||||||
|
/PGD:"${CITRON_PGO_PROFILE_DIR}/${target_name}.pgd"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Copy PGO runtime DLLs to output directory
|
||||||
|
citron_copy_pgo_runtime_dlls(${target_name})
|
||||||
|
elseif(CITRON_ENABLE_PGO_USE)
|
||||||
|
message(STATUS " [${target_name}] MSVC PGO: USE stage")
|
||||||
|
# Check if profile data exists in pgo-profiles directory
|
||||||
|
set(PGD_FILE "${CITRON_PGO_PROFILE_DIR}/${target_name}.pgd")
|
||||||
|
|
||||||
|
# Also check in the output directory (where MSVC creates them during GENERATE)
|
||||||
|
get_target_property(TARGET_OUTPUT_DIR ${target_name} RUNTIME_OUTPUT_DIRECTORY)
|
||||||
|
if(NOT TARGET_OUTPUT_DIR)
|
||||||
|
set(TARGET_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
endif()
|
||||||
|
set(PGD_FILE_OUTPUT "${TARGET_OUTPUT_DIR}/${target_name}.pgd")
|
||||||
|
|
||||||
|
if(EXISTS "${PGD_FILE}")
|
||||||
|
target_compile_options(${target_name} PRIVATE /GL)
|
||||||
|
# Use the profile directory path
|
||||||
|
file(TO_NATIVE_PATH "${PGD_FILE}" PGD_FILE_NATIVE)
|
||||||
|
target_link_options(${target_name} PRIVATE
|
||||||
|
/LTCG
|
||||||
|
"/USEPROFILE:PGD=${PGD_FILE_NATIVE}"
|
||||||
|
)
|
||||||
|
message(STATUS " [${target_name}] Using profile data: ${PGD_FILE}")
|
||||||
|
elseif(EXISTS "${PGD_FILE_OUTPUT}")
|
||||||
|
target_compile_options(${target_name} PRIVATE /GL)
|
||||||
|
# Use the output directory path
|
||||||
|
file(TO_NATIVE_PATH "${PGD_FILE_OUTPUT}" PGD_FILE_NATIVE)
|
||||||
|
target_link_options(${target_name} PRIVATE
|
||||||
|
/LTCG
|
||||||
|
"/USEPROFILE:PGD=${PGD_FILE_NATIVE}"
|
||||||
|
)
|
||||||
|
message(STATUS " [${target_name}] Using profile data: ${PGD_FILE_OUTPUT}")
|
||||||
|
else()
|
||||||
|
message(WARNING "Profile data not found for ${target_name}. Checked:")
|
||||||
|
message(STATUS " - ${PGD_FILE}")
|
||||||
|
message(STATUS " - ${PGD_FILE_OUTPUT}")
|
||||||
|
message(WARNING "PGO USE stage will be skipped.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# GCC-specific PGO
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
if(CITRON_ENABLE_PGO_GENERATE)
|
||||||
|
message(STATUS " [${target_name}] GCC PGO: GENERATE stage")
|
||||||
|
target_compile_options(${target_name} PRIVATE
|
||||||
|
-fprofile-generate="${CITRON_PGO_PROFILE_DIR}"
|
||||||
|
)
|
||||||
|
target_link_options(${target_name} PRIVATE
|
||||||
|
-fprofile-generate="${CITRON_PGO_PROFILE_DIR}"
|
||||||
|
)
|
||||||
|
elseif(CITRON_ENABLE_PGO_USE)
|
||||||
|
message(STATUS " [${target_name}] GCC PGO: USE stage")
|
||||||
|
# Check if profile data exists
|
||||||
|
file(GLOB profile_files "${CITRON_PGO_PROFILE_DIR}/*.gcda")
|
||||||
|
if(profile_files)
|
||||||
|
target_compile_options(${target_name} PRIVATE
|
||||||
|
-fprofile-use="${CITRON_PGO_PROFILE_DIR}"
|
||||||
|
-fprofile-correction # Handle inconsistencies in profile data
|
||||||
|
)
|
||||||
|
target_link_options(${target_name} PRIVATE
|
||||||
|
-fprofile-use="${CITRON_PGO_PROFILE_DIR}"
|
||||||
|
)
|
||||||
|
message(STATUS " [${target_name}] Using profile data from: ${CITRON_PGO_PROFILE_DIR}")
|
||||||
|
else()
|
||||||
|
message(WARNING "No profile data found for ${target_name} in ${CITRON_PGO_PROFILE_DIR}. PGO USE stage will be skipped.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Clang-specific PGO
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
if(CITRON_ENABLE_PGO_GENERATE)
|
||||||
|
message(STATUS " [${target_name}] Clang PGO: GENERATE stage")
|
||||||
|
target_compile_options(${target_name} PRIVATE
|
||||||
|
-fprofile-generate="${CITRON_PGO_PROFILE_DIR}"
|
||||||
|
)
|
||||||
|
target_link_options(${target_name} PRIVATE
|
||||||
|
-fprofile-generate="${CITRON_PGO_PROFILE_DIR}"
|
||||||
|
)
|
||||||
|
elseif(CITRON_ENABLE_PGO_USE)
|
||||||
|
message(STATUS " [${target_name}] Clang PGO: USE stage")
|
||||||
|
|
||||||
|
# For Clang, we need to merge .profraw files into .profdata first
|
||||||
|
set(PROFDATA_FILE "${CITRON_PGO_PROFILE_DIR}/default.profdata")
|
||||||
|
|
||||||
|
# Check if merged profile data exists, if not try to create it
|
||||||
|
if(NOT EXISTS "${PROFDATA_FILE}")
|
||||||
|
file(GLOB profraw_files "${CITRON_PGO_PROFILE_DIR}/*.profraw")
|
||||||
|
if(profraw_files)
|
||||||
|
find_program(LLVM_PROFDATA llvm-profdata)
|
||||||
|
if(LLVM_PROFDATA)
|
||||||
|
message(STATUS " [${target_name}] Merging .profraw files into ${PROFDATA_FILE}")
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${LLVM_PROFDATA} merge -output=${PROFDATA_FILE} ${profraw_files}
|
||||||
|
RESULT_VARIABLE merge_result
|
||||||
|
OUTPUT_QUIET
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
if(NOT merge_result EQUAL 0)
|
||||||
|
message(WARNING "Failed to merge profile data for ${target_name}. PGO USE stage will be skipped.")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(WARNING "llvm-profdata not found. Cannot merge profile data. PGO USE stage will be skipped.")
|
||||||
|
message(STATUS " Please run: llvm-profdata merge -output=${PROFDATA_FILE} ${CITRON_PGO_PROFILE_DIR}/*.profraw")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(WARNING "No .profraw files found in ${CITRON_PGO_PROFILE_DIR}. PGO USE stage will be skipped.")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(EXISTS "${PROFDATA_FILE}")
|
||||||
|
target_compile_options(${target_name} PRIVATE
|
||||||
|
-fprofile-use="${PROFDATA_FILE}"
|
||||||
|
)
|
||||||
|
target_link_options(${target_name} PRIVATE
|
||||||
|
-fprofile-use="${PROFDATA_FILE}"
|
||||||
|
)
|
||||||
|
message(STATUS " [${target_name}] Using profile data: ${PROFDATA_FILE}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(WARNING "PGO is not supported for compiler: ${CMAKE_CXX_COMPILER_ID}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Helper function to print PGO instructions
|
||||||
|
function(citron_print_pgo_instructions)
|
||||||
|
if(CITRON_ENABLE_PGO_GENERATE)
|
||||||
|
message(STATUS "")
|
||||||
|
message(STATUS "=================================================================")
|
||||||
|
message(STATUS "PGO GENERATE Stage")
|
||||||
|
message(STATUS "=================================================================")
|
||||||
|
message(STATUS "Citron has been built with profiling instrumentation.")
|
||||||
|
message(STATUS "")
|
||||||
|
message(STATUS "Next steps:")
|
||||||
|
message(STATUS " 1. Run the built citron executable")
|
||||||
|
message(STATUS " 2. Play games/perform typical operations to generate profile data")
|
||||||
|
message(STATUS " 3. Exit citron")
|
||||||
|
message(STATUS " 4. Profile data will be saved to: ${CITRON_PGO_PROFILE_DIR}")
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
message(STATUS " 5. For Clang: Merge profile data with:")
|
||||||
|
message(STATUS " llvm-profdata merge -output=${CITRON_PGO_PROFILE_DIR}/default.profdata ${CITRON_PGO_PROFILE_DIR}/*.profraw")
|
||||||
|
endif()
|
||||||
|
message(STATUS " 6. Rebuild with: cmake -DCITRON_ENABLE_PGO_GENERATE=OFF -DCITRON_ENABLE_PGO_USE=ON")
|
||||||
|
message(STATUS "=================================================================")
|
||||||
|
message(STATUS "")
|
||||||
|
elseif(CITRON_ENABLE_PGO_USE)
|
||||||
|
message(STATUS "")
|
||||||
|
message(STATUS "=================================================================")
|
||||||
|
message(STATUS "PGO USE Stage")
|
||||||
|
message(STATUS "=================================================================")
|
||||||
|
message(STATUS "Citron is being optimized using profile data from: ${CITRON_PGO_PROFILE_DIR}")
|
||||||
|
message(STATUS "This build will be significantly faster than standard builds.")
|
||||||
|
message(STATUS "=================================================================")
|
||||||
|
message(STATUS "")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
174
fix-pgo-dll.ps1
Normal file
174
fix-pgo-dll.ps1
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Fix PGO DLL Script for Citron (Windows)
|
||||||
|
# This script helps locate and copy the required pgort140.dll for MSVC PGO builds
|
||||||
|
|
||||||
|
param(
|
||||||
|
[Parameter()]
|
||||||
|
[string]$OutputDir = "build\bin\Release",
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[switch]$Help
|
||||||
|
)
|
||||||
|
|
||||||
|
function Show-Usage {
|
||||||
|
Write-Host @"
|
||||||
|
Usage: .\fix-pgo-dll.ps1 [OPTIONS]
|
||||||
|
|
||||||
|
This script helps fix the "pgort140.DLL was not found" error by locating
|
||||||
|
and copying the required PGO runtime DLL to your build output directory.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-OutputDir PATH Target directory to copy DLL (default: build\bin\Release)
|
||||||
|
-Help Show this help message
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.\fix-pgo-dll.ps1
|
||||||
|
.\fix-pgo-dll.ps1 -OutputDir "C:\MyBuild\bin"
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Header "PGO DLL Fixer for Citron"
|
||||||
|
|
||||||
|
# Find Visual Studio installation
|
||||||
|
$VSInstallPath = $null
|
||||||
|
$VSWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||||
|
|
||||||
|
if (Test-Path $VSWhere) {
|
||||||
|
Write-Info "Searching for Visual Studio installations..."
|
||||||
|
$VSInstallPath = & $VSWhere -latest -property installationPath
|
||||||
|
if ($VSInstallPath) {
|
||||||
|
Write-Info "Found Visual Studio at: $VSInstallPath"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Warning "vswhere.exe not found. Trying common installation paths..."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Common Visual Studio installation paths
|
||||||
|
$CommonPaths = @(
|
||||||
|
"${env:ProgramFiles}\Microsoft Visual Studio\2022\Community",
|
||||||
|
"${env:ProgramFiles}\Microsoft Visual Studio\2022\Professional",
|
||||||
|
"${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise",
|
||||||
|
"${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community",
|
||||||
|
"${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Professional",
|
||||||
|
"${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Enterprise"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not $VSInstallPath) {
|
||||||
|
foreach ($path in $CommonPaths) {
|
||||||
|
if (Test-Path $path) {
|
||||||
|
$VSInstallPath = $path
|
||||||
|
Write-Info "Found Visual Studio at: $VSInstallPath"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $VSInstallPath) {
|
||||||
|
Write-Error-Custom "Visual Studio installation not found!"
|
||||||
|
Write-Host "Please ensure Visual Studio 2019 or 2022 is installed with C++ support."
|
||||||
|
Write-Host "You can download it from: https://visualstudio.microsoft.com/downloads/"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Search for pgort140.dll
|
||||||
|
Write-Info "Searching for pgort140.dll..."
|
||||||
|
|
||||||
|
$DllPaths = @(
|
||||||
|
"$VSInstallPath\VC\Redist\MSVC\*\x64\Microsoft.VC*.CRT\pgort140.dll",
|
||||||
|
"$VSInstallPath\VC\Redist\MSVC\*\x86\Microsoft.VC*.CRT\pgort140.dll",
|
||||||
|
"$VSInstallPath\VC\Tools\MSVC\*\bin\Hostx64\x64\pgort140.dll",
|
||||||
|
"$VSInstallPath\VC\Tools\MSVC\*\bin\Hostx64\x86\pgort140.dll",
|
||||||
|
"$VSInstallPath\VC\Tools\MSVC\*\bin\Hostx86\x64\pgort140.dll",
|
||||||
|
"$VSInstallPath\VC\Tools\MSVC\*\bin\Hostx86\x86\pgort140.dll"
|
||||||
|
)
|
||||||
|
|
||||||
|
$FoundDll = $null
|
||||||
|
foreach ($pattern in $DllPaths) {
|
||||||
|
$matches = Get-ChildItem -Path $pattern -ErrorAction SilentlyContinue
|
||||||
|
if ($matches) {
|
||||||
|
$FoundDll = $matches[0].FullName
|
||||||
|
Write-Info "Found pgort140.dll at: $FoundDll"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $FoundDll) {
|
||||||
|
Write-Error-Custom "pgort140.dll not found in Visual Studio installation!"
|
||||||
|
Write-Host "This usually means:"
|
||||||
|
Write-Host "1. Visual Studio was installed without PGO support"
|
||||||
|
Write-Host "2. You need to install the 'MSVC v143 - VS 2022 C++ x64/x86 build tools' component"
|
||||||
|
Write-Host "3. Try repairing your Visual Studio installation"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "To fix this:"
|
||||||
|
Write-Host "1. Open Visual Studio Installer"
|
||||||
|
Write-Host "2. Click 'Modify' on your Visual Studio installation"
|
||||||
|
Write-Host "3. Go to 'Individual components' tab"
|
||||||
|
Write-Host "4. Search for 'PGO' and ensure it's checked"
|
||||||
|
Write-Host "5. Click 'Modify' to install the component"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create output directory if it doesn't exist
|
||||||
|
if (-not (Test-Path $OutputDir)) {
|
||||||
|
Write-Info "Creating output directory: $OutputDir"
|
||||||
|
New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy the DLL
|
||||||
|
try {
|
||||||
|
Write-Info "Copying pgort140.dll to: $OutputDir"
|
||||||
|
Copy-Item -Path $FoundDll -Destination $OutputDir -Force
|
||||||
|
Write-Info "Successfully copied pgort140.dll!"
|
||||||
|
|
||||||
|
# Verify the copy
|
||||||
|
$CopiedDll = Join-Path $OutputDir "pgort140.dll"
|
||||||
|
if (Test-Path $CopiedDll) {
|
||||||
|
Write-Info "Verification: pgort140.dll is now available in $OutputDir"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "You can now run your PGO instrumented Citron build!"
|
||||||
|
} else {
|
||||||
|
Write-Error-Custom "Failed to copy pgort140.dll"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Error-Custom "Error copying pgort140.dll: $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Header "PGO DLL Fix Complete!"
|
||||||
|
Write-Info "The pgort140.dll has been copied to your build output directory."
|
||||||
|
Write-Info "Your PGO instrumented Citron build should now run without the DLL error."
|
||||||
|
Write-Host ""
|
||||||
|
Write-Info "Next steps:"
|
||||||
|
Write-Host "1. Run your PGO instrumented build"
|
||||||
|
Write-Host "2. Play games to collect profile data"
|
||||||
|
Write-Host "3. Rebuild with PGO USE stage for optimization"
|
||||||
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
|
||||||
|
}
|
||||||
|
|
||||||
203
pgo-build.sh
Normal file
203
pgo-build.sh
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# PGO Build Script for Citron (Linux/macOS)
|
||||||
|
# This script automates the Profile-Guided Optimization build process
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
BUILD_DIR="${SCRIPT_DIR}/build"
|
||||||
|
PGO_PROFILES_DIR="${BUILD_DIR}/pgo-profiles"
|
||||||
|
BACKUP_PROFILES_DIR="${SCRIPT_DIR}/pgo-profiles-backup"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
print_header() {
|
||||||
|
echo -e "${BLUE}=================================================================${NC}"
|
||||||
|
echo -e "${BLUE}$1${NC}"
|
||||||
|
echo -e "${BLUE}=================================================================${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_info() {
|
||||||
|
echo -e "${GREEN}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_usage() {
|
||||||
|
echo "Usage: $0 [STAGE]"
|
||||||
|
echo ""
|
||||||
|
echo "STAGE can be:"
|
||||||
|
echo " generate - Build with PGO instrumentation (Stage 1)"
|
||||||
|
echo " use - Build using PGO profile data (Stage 2)"
|
||||||
|
echo " clean - Clean build directory but preserve profiles"
|
||||||
|
echo ""
|
||||||
|
echo "Example:"
|
||||||
|
echo " $0 generate # Build instrumented version"
|
||||||
|
echo " # Run citron to collect profiles"
|
||||||
|
echo " $0 use # Build optimized version"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -j N Number of parallel jobs (default: auto-detect)"
|
||||||
|
echo " -lto Enable Link-Time Optimization"
|
||||||
|
echo " -h Show this help message"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
STAGE=""
|
||||||
|
JOBS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo "4")
|
||||||
|
ENABLE_LTO="OFF"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
generate|use|clean)
|
||||||
|
STAGE="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-j)
|
||||||
|
JOBS="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-lto)
|
||||||
|
ENABLE_LTO="ON"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
show_usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print_error "Unknown option: $1"
|
||||||
|
show_usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$STAGE" ]; then
|
||||||
|
print_error "No stage specified"
|
||||||
|
show_usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean stage
|
||||||
|
if [ "$STAGE" == "clean" ]; then
|
||||||
|
print_header "Cleaning Build Directory"
|
||||||
|
|
||||||
|
if [ -d "$PGO_PROFILES_DIR" ]; then
|
||||||
|
print_info "Backing up PGO profiles..."
|
||||||
|
mkdir -p "$BACKUP_PROFILES_DIR"
|
||||||
|
cp -r "$PGO_PROFILES_DIR"/* "$BACKUP_PROFILES_DIR/" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$BUILD_DIR" ]; then
|
||||||
|
print_info "Removing build directory..."
|
||||||
|
rm -rf "$BUILD_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$BACKUP_PROFILES_DIR" ]; then
|
||||||
|
print_info "Restoring PGO profiles..."
|
||||||
|
mkdir -p "$PGO_PROFILES_DIR"
|
||||||
|
mv "$BACKUP_PROFILES_DIR"/* "$PGO_PROFILES_DIR/" 2>/dev/null || true
|
||||||
|
rm -rf "$BACKUP_PROFILES_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_info "Clean complete!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate stage
|
||||||
|
if [ "$STAGE" == "generate" ]; then
|
||||||
|
print_header "PGO Stage 1: Generate Profile Data"
|
||||||
|
|
||||||
|
# Create build directory
|
||||||
|
mkdir -p "$BUILD_DIR"
|
||||||
|
cd "$BUILD_DIR"
|
||||||
|
|
||||||
|
# Configure
|
||||||
|
print_info "Configuring CMake..."
|
||||||
|
cmake .. \
|
||||||
|
-DCITRON_ENABLE_PGO_GENERATE=ON \
|
||||||
|
-DCITRON_ENABLE_LTO=$ENABLE_LTO \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
|
# Build
|
||||||
|
print_info "Building instrumented Citron (this may take a while)..."
|
||||||
|
cmake --build . -j"$JOBS"
|
||||||
|
|
||||||
|
print_header "Build Complete!"
|
||||||
|
print_info "Next steps:"
|
||||||
|
echo " 1. Run: ./bin/citron"
|
||||||
|
echo " 2. Play games for 15-30 minutes to collect profile data"
|
||||||
|
echo " 3. Exit citron"
|
||||||
|
|
||||||
|
# Clang-specific instructions
|
||||||
|
if [ "$(cmake --system-information | grep CMAKE_CXX_COMPILER_ID | grep -i clang)" ]; then
|
||||||
|
echo " 4. Merge profiles: llvm-profdata merge -output=$PGO_PROFILES_DIR/default.profdata $PGO_PROFILES_DIR/*.profraw"
|
||||||
|
echo " 5. Run: $0 use"
|
||||||
|
else
|
||||||
|
echo " 4. Run: $0 use"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use stage
|
||||||
|
if [ "$STAGE" == "use" ]; then
|
||||||
|
print_header "PGO Stage 2: Build Optimized Binary"
|
||||||
|
|
||||||
|
# Check if profile data exists
|
||||||
|
if [ ! -d "$PGO_PROFILES_DIR" ] || [ -z "$(ls -A $PGO_PROFILES_DIR 2>/dev/null)" ]; then
|
||||||
|
print_error "No profile data found in $PGO_PROFILES_DIR"
|
||||||
|
print_info "Please run the generate stage first and collect profile data"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup profiles if build directory exists
|
||||||
|
if [ -d "$BUILD_DIR" ]; then
|
||||||
|
print_info "Backing up PGO profiles..."
|
||||||
|
mkdir -p "$BACKUP_PROFILES_DIR"
|
||||||
|
cp -r "$PGO_PROFILES_DIR"/* "$BACKUP_PROFILES_DIR/"
|
||||||
|
rm -rf "$BUILD_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create build directory and restore profiles
|
||||||
|
mkdir -p "$BUILD_DIR"
|
||||||
|
if [ -d "$BACKUP_PROFILES_DIR" ]; then
|
||||||
|
mkdir -p "$PGO_PROFILES_DIR"
|
||||||
|
mv "$BACKUP_PROFILES_DIR"/* "$PGO_PROFILES_DIR/"
|
||||||
|
rm -rf "$BACKUP_PROFILES_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$BUILD_DIR"
|
||||||
|
|
||||||
|
# Configure
|
||||||
|
print_info "Configuring CMake..."
|
||||||
|
cmake .. \
|
||||||
|
-DCITRON_ENABLE_PGO_USE=ON \
|
||||||
|
-DCITRON_ENABLE_LTO=$ENABLE_LTO \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
|
# Build
|
||||||
|
print_info "Building optimized Citron (this may take a while)..."
|
||||||
|
cmake --build . -j"$JOBS"
|
||||||
|
|
||||||
|
print_header "Build Complete!"
|
||||||
|
print_info "Your optimized Citron binary is ready!"
|
||||||
|
print_info "Location: $BUILD_DIR/bin/citron"
|
||||||
|
echo ""
|
||||||
|
print_info "This build is optimized for your specific usage patterns."
|
||||||
|
print_info "Enjoy improved performance! 🚀"
|
||||||
|
fi
|
||||||
|
|
||||||
Reference in New Issue
Block a user