mirror of
https://github.com/jessicanataliagta/PSPRecomp
synced 2026-09-26 08:41:08 -04:00
98d6b05477
mais otimizaçoes
132 lines
5.6 KiB
CMake
132 lines
5.6 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
project(PSPRecomp VERSION 0.1.0 LANGUAGES CXX)
|
|
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
option(PSPRECOMP_BUILD_TESTS "Build reusable PSPRecomp tests" ON)
|
|
option(PSPRECOMP_BUILD_PROFILE_TESTS "Build tests supplied by the selected profile" ON)
|
|
set(PSPRECOMP_PROFILE "" CACHE STRING "Profile to build from profiles/<name>; empty builds only the framework")
|
|
|
|
set(PSPRECOMP_GENERATED_OPT_LEVEL "2" CACHE STRING
|
|
"Optimization level for generated AOT units (0, 1, 2 or 3)")
|
|
set_property(CACHE PSPRECOMP_GENERATED_OPT_LEVEL PROPERTY STRINGS 0 1 2 3)
|
|
if(NOT PSPRECOMP_GENERATED_OPT_LEVEL MATCHES "^[0-3]$")
|
|
message(FATAL_ERROR "PSPRECOMP_GENERATED_OPT_LEVEL must be 0, 1, 2 or 3")
|
|
endif()
|
|
|
|
option(PSPRECOMP_LTO "Enable link-time/whole-program optimization" OFF)
|
|
option(PSPRECOMP_NATIVE_AVX2 "Use AVX2 code generation for optimized MSVC builds" OFF)
|
|
option(PSPRECOMP_HOST_AVX "Use AVX for host-side scalar floor/ceil hot paths on MSVC" ON)
|
|
option(PSPRECOMP_AOT_ASSUME_NO_WRITE_WATCH
|
|
"Remove per-store write-watch branch from production AOT fast memory" OFF)
|
|
option(PSPRECOMP_AOT_PRODUCTION_FASTPATHS
|
|
"Compile out AOT chain diagnostic/counter branches for production builds" OFF)
|
|
set(PSPRECOMP_MSVC_CGTHREADS "0" CACHE STRING
|
|
"MSVC LTCG code-generation threads (0 = compiler default)")
|
|
if(NOT PSPRECOMP_MSVC_CGTHREADS MATCHES "^[0-9]+$")
|
|
message(FATAL_ERROR "PSPRECOMP_MSVC_CGTHREADS must be a non-negative integer")
|
|
endif()
|
|
|
|
# Bare /MP lets cl.exe spawn one front-end per logical core, and MSBuild /m
|
|
# multiplies that by the number of projects it builds in parallel. On the VCS
|
|
# profile each generated AOT unit costs well over a gigabyte at /Ox /Ob3, so the
|
|
# unbounded product exhausts physical memory. Cap the per-cl.exe degree here and
|
|
# let the build scripts pick a memory-aware value.
|
|
set(PSPRECOMP_MSVC_MP_JOBS "0" CACHE STRING
|
|
"Max cl.exe front-ends (0 = logical-core default, 1 = disable /MP)")
|
|
if(NOT PSPRECOMP_MSVC_MP_JOBS MATCHES "^[0-9]+$")
|
|
message(FATAL_ERROR "PSPRECOMP_MSVC_MP_JOBS must be a non-negative integer")
|
|
endif()
|
|
if(PSPRECOMP_MSVC_MP_JOBS STREQUAL "0")
|
|
set(PSPRECOMP_MSVC_MP_FLAG "/MP")
|
|
elseif(PSPRECOMP_MSVC_MP_JOBS STREQUAL "1")
|
|
# Omitting /MP is materially different from /MP1: the latter still creates
|
|
# and communicates with a child compiler process and can fail with D8040.
|
|
set(PSPRECOMP_MSVC_MP_FLAG "")
|
|
else()
|
|
set(PSPRECOMP_MSVC_MP_FLAG "/MP${PSPRECOMP_MSVC_MP_JOBS}")
|
|
endif()
|
|
|
|
if(PSPRECOMP_AOT_ASSUME_NO_WRITE_WATCH)
|
|
add_compile_definitions(PSPRECOMP_AOT_ASSUME_NO_WRITE_WATCH=1)
|
|
endif()
|
|
if(PSPRECOMP_AOT_PRODUCTION_FASTPATHS)
|
|
add_compile_definitions(PSPRECOMP_AOT_PRODUCTION_FASTPATHS=1)
|
|
endif()
|
|
if(MSVC AND PSPRECOMP_NATIVE_AVX2)
|
|
add_compile_options($<$<CONFIG:Release>:/arch:AVX2>
|
|
$<$<CONFIG:RelWithDebInfo>:/arch:AVX2>)
|
|
endif()
|
|
|
|
if(PSPRECOMP_LTO)
|
|
include(CheckIPOSupported)
|
|
check_ipo_supported(RESULT PSPRECOMP_LTO_SUPPORTED OUTPUT PSPRECOMP_LTO_REASON)
|
|
if(PSPRECOMP_LTO_SUPPORTED)
|
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
|
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON)
|
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL ON)
|
|
else()
|
|
message(WARNING "Whole-program optimization unavailable: ${PSPRECOMP_LTO_REASON}")
|
|
endif()
|
|
endif()
|
|
|
|
add_library(psprecomp_core STATIC
|
|
src/decoder.cpp
|
|
src/deflate.cpp
|
|
src/elf32.cpp
|
|
src/guest_memory.cpp
|
|
src/nid_registry.cpp
|
|
src/program_analysis.cpp
|
|
src/runtime.cpp
|
|
src/sha256.cpp
|
|
)
|
|
target_include_directories(psprecomp_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
target_compile_definitions(psprecomp_core PRIVATE
|
|
$<$<CXX_COMPILER_ID:MSVC>:_CRT_SECURE_NO_WARNINGS>)
|
|
if(MSVC)
|
|
target_compile_options(psprecomp_core PRIVATE /W4 /permissive- /EHsc ${PSPRECOMP_MSVC_MP_FLAG}
|
|
$<$<CONFIG:Release>:/Ob3> $<$<CONFIG:RelWithDebInfo>:/Ob3>)
|
|
else()
|
|
target_compile_options(psprecomp_core PRIVATE -Wall -Wextra -Wpedantic -Wconversion -Wshadow)
|
|
endif()
|
|
|
|
add_executable(psp_analyze tools/analyzer_main.cpp)
|
|
target_link_libraries(psp_analyze PRIVATE psprecomp_core)
|
|
|
|
add_executable(psp_recomp tools/codegen_main.cpp)
|
|
target_link_libraries(psp_recomp PRIVATE psprecomp_core)
|
|
|
|
add_executable(dump_function tools/dump_function.cpp)
|
|
target_link_libraries(dump_function PRIVATE psprecomp_core)
|
|
|
|
function(psprecomp_enable_host_avx target)
|
|
# /arch:AVX appears after the directory-wide /arch:AVX2 option in MSVC's
|
|
# command line and therefore silently downgrades the whole target. AVX2
|
|
# already includes the AVX scalar instructions this compatibility switch
|
|
# was introduced for, so do not emit the weaker override in an AVX2 build.
|
|
if(PSPRECOMP_HOST_AVX AND MSVC AND NOT PSPRECOMP_NATIVE_AVX2)
|
|
target_compile_options(${target} PRIVATE /arch:AVX)
|
|
endif()
|
|
endfunction()
|
|
|
|
if(PSPRECOMP_BUILD_TESTS)
|
|
enable_testing()
|
|
add_executable(psprecomp_tests tests/test_main.cpp)
|
|
target_link_libraries(psprecomp_tests PRIVATE psprecomp_core)
|
|
add_dependencies(psprecomp_tests psp_recomp)
|
|
target_compile_definitions(psprecomp_tests PRIVATE
|
|
PSPRECOMP_CODEGEN_PATH="$<TARGET_FILE:psp_recomp>")
|
|
add_test(NAME psprecomp_tests COMMAND psprecomp_tests)
|
|
endif()
|
|
|
|
if(NOT PSPRECOMP_PROFILE STREQUAL "")
|
|
set(PSPRECOMP_PROFILE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/profiles/${PSPRECOMP_PROFILE}")
|
|
if(NOT EXISTS "${PSPRECOMP_PROFILE_DIR}/CMakeLists.txt")
|
|
message(FATAL_ERROR "Unknown PSPRecomp profile: ${PSPRECOMP_PROFILE}")
|
|
endif()
|
|
add_subdirectory("${PSPRECOMP_PROFILE_DIR}" "profiles/${PSPRECOMP_PROFILE}")
|
|
endif()
|