# ReXGlue SDK - Xbox 360 Recompilation Toolkit # Modern C++23 cross-platform SDK for recompiling Xbox 360 executables cmake_minimum_required(VERSION 3.25) project(ReXGlue VERSION 0.8.0 LANGUAGES C CXX DESCRIPTION "Xbox 360 Recompilation SDK" ) # Floor only: bump MAJOR.MINOR for API changes. Patch is derived from git tags # in cmake/rex_version.cmake. See docs/RELEASING.md. #========================================================== # Build Options #========================================================== option(REXGLUE_BUILD_TESTS "Build PPC instruction and unit tests" OFF) option(REXGLUE_ENABLE_SANITIZERS "Enable UndefinedBehaviorSanitizer" OFF) option(REXGLUE_ENABLE_FIDELITYFX "Enable optional AMD FidelityFX integration (experimental)" OFF) option(REXGLUE_ENABLE_TRACY "Enable Tracy profiler integration" ON) option(REXGLUE_ENABLE_PERF_COUNTERS "Enable lightweight perf counter registry and overlay" ON) # Propagate profiling defines globally (compiled out in Release) if(REXGLUE_ENABLE_TRACY) add_compile_definitions($<$>:REXGLUE_ENABLE_PROFILING>) endif() if(REXGLUE_ENABLE_PERF_COUNTERS) add_compile_definitions(REXGLUE_ENABLE_PERF_COUNTERS) endif() # Graphics backend selection # D3D12: Windows only, ON by default. # Vulkan: Cross-platform, ON by default everywhere. Windows builds both # backends by default; the active one is chosen at runtime (gpu_backend cvar). if(WIN32) option(REXGLUE_USE_D3D12 "Enable D3D12 graphics backend" ON) option(REXGLUE_USE_VULKAN "Enable Vulkan graphics backend" ON) else() set(REXGLUE_USE_D3D12 OFF) option(REXGLUE_USE_VULKAN "Enable Vulkan graphics backend" ON) endif() if(NOT REXGLUE_USE_D3D12 AND NOT REXGLUE_USE_VULKAN) message(FATAL_ERROR "At least one graphics backend must be enabled (REXGLUE_USE_D3D12 or REXGLUE_USE_VULKAN)") endif() if (REXGLUE_ENABLE_FIDELITYFX AND NOT (REXGLUE_USE_VULKAN OR REXGLUE_USE_D3D12)) message(FATAL_ERROR "REXGLUE_ENABLE_FIDELITYFX requires at least one graphics backend") endif() # Root of the SDK source tree set(REXGLUE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}") # SDK install support include(GNUInstallDirs) include(CMakePackageConfigHelpers) if(APPLE) # Keep app bundles and command-line launches able to find dylibs staged # beside the executable. list(APPEND CMAKE_INSTALL_RPATH "@loader_path" "@loader_path/../${CMAKE_INSTALL_LIBDIR}" ) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) elseif(UNIX AND NOT APPLE) # Keep installed binaries self-contained by resolving shared libs relative # to the install prefix (for example, bin -> ../lib). set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) list(APPEND CMAKE_INSTALL_RPATH "$ORIGIN" "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}" ) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) endif() # Enforce Clang18 compiler if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") message(FATAL_ERROR "ReXGlue requires Clang compiler. Please set CMAKE_CXX_COMPILER to clang++") endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "18.0") message(FATAL_ERROR "ReXGlue requires Clang 18 or newer (found ${CMAKE_CXX_COMPILER_VERSION})") endif() # Enforce x64 architecture if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8) message(FATAL_ERROR "ReXGlue only supports 64-bit architectures (x86_64 or ARM64)") endif() # Set C++23 standard set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_DEBUG_POSTFIX d) set(CMAKE_RELWITHDEBINFO_POSTFIX rd) set(REX_TARGET_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}") if(APPLE AND CMAKE_OSX_ARCHITECTURES) list(LENGTH CMAKE_OSX_ARCHITECTURES REX_OSX_ARCH_COUNT) if(REX_OSX_ARCH_COUNT EQUAL 1) set(REX_TARGET_PROCESSOR "${CMAKE_OSX_ARCHITECTURES}") endif() endif() if(UNIX AND NOT APPLE) # Use appropriate code model based on architecture if(REX_TARGET_PROCESSOR MATCHES "AMD64|x86_64") # Large code model on x86_64 for linking with very large recompiled executables (35MB+) add_compile_options(-mcmodel=large) else() # Small code model for other architectures (ARM64, etc.) add_compile_options(-mcmodel=small) endif() endif() if(NOT WIN32) # Position-independent code for all targets set(CMAKE_POSITION_INDEPENDENT_CODE ON) endif() # Global compile options add_compile_options( -fno-strict-aliasing -ffp-model=strict $<$:-g> $<$:-O0> $<$:-O3> $<$:-DNDEBUG> -fno-char8_t ) # Platform detection (supports AMD64 and ARM64) if(WIN32) if(REX_TARGET_PROCESSOR MATCHES "AMD64|x86_64") set(REX_PLATFORM "win-amd64") elseif(REX_TARGET_PROCESSOR MATCHES "aarch64|ARM64") set(REX_PLATFORM "win-arm64") else() message(FATAL_ERROR "Unsupported Windows architecture: ${REX_TARGET_PROCESSOR}") endif() add_compile_definitions(REX_PLATFORM_WINDOWS=1) elseif(APPLE) if(REX_TARGET_PROCESSOR MATCHES "aarch64|arm64|ARM64") set(REX_PLATFORM "macos-arm64") else() message(FATAL_ERROR "Unsupported macOS architecture: ${REX_TARGET_PROCESSOR}. macOS builds are ARM64-only.") endif() add_compile_definitions(REX_PLATFORM_MAC=1) elseif(UNIX AND NOT APPLE) if(REX_TARGET_PROCESSOR MATCHES "AMD64|x86_64") set(REX_PLATFORM "linux-amd64") elseif(REX_TARGET_PROCESSOR MATCHES "aarch64|ARM64") set(REX_PLATFORM "linux-arm64") else() set(REX_PLATFORM "linux-${REX_TARGET_PROCESSOR}") endif() add_compile_definitions(REX_PLATFORM_LINUX=1) else() message(FATAL_ERROR "Unsupported platform. ReXGlue supports Windows, Linux and macOS only.") endif() # Build config as compile definition (multi-config generators don't know config at configure time) add_compile_definitions(REXGLUE_BUILD_CONFIG="$") include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/rex_version.cmake) rex_resolve_version(REXGLUE_FULL_VERSION FLOOR_MAJOR ${PROJECT_VERSION_MAJOR} FLOOR_MINOR ${PROJECT_VERSION_MINOR} SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) # Strip the -id trailer (if any) for the numeric-only version. string(REGEX REPLACE "-.*$" "" REXGLUE_NUMERIC_VERSION "${REXGLUE_FULL_VERSION}") # Parse up to 4 numeric components for consumers that want integer access. string(REGEX MATCH "^([0-9]+)\\.([0-9]+)(\\.([0-9]+))?(\\.([0-9]+))?" _ "${REXGLUE_NUMERIC_VERSION}") set(REXGLUE_DERIVED_MAJOR "${CMAKE_MATCH_1}") set(REXGLUE_DERIVED_MINOR "${CMAKE_MATCH_2}") if(CMAKE_MATCH_4) set(REXGLUE_DERIVED_PATCH "${CMAKE_MATCH_4}") else() set(REXGLUE_DERIVED_PATCH "0") endif() if(CMAKE_MATCH_6) set(REXGLUE_DERIVED_TWEAK "${CMAKE_MATCH_6}") else() set(REXGLUE_DERIVED_TWEAK "0") endif() # Generate version header -- must run after REX_PLATFORM is set # Timestamp is set at configure time -- intentionally not updated on every rebuild string(TIMESTAMP REXGLUE_BUILD_TIMESTAMP "%Y%m%d_%H%M") configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/include/rex/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/rex/version.h @ONLY ) # Output directories (multi-config appends // automatically) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${REXGLUE_ROOT}/out/${REX_PLATFORM}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${REXGLUE_ROOT}/out/${REX_PLATFORM}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${REXGLUE_ROOT}/out/${REX_PLATFORM}") # Sanitizer support for debugging memory corruption and undefined behavior if(REXGLUE_ENABLE_SANITIZERS) message(STATUS "Enabling UndefinedBehaviorSanitizer (UBSan only - ASan conflicts with custom memory mapping)") # Note: ASan doesn't work well with the custom mmap at 0x100000000, so we only use UBSan add_compile_options(-fsanitize=undefined -fno-omit-frame-pointer -g) add_link_options(-fsanitize=undefined) endif() if(REXGLUE_BUILD_TESTS) list(APPEND CMAKE_MODULE_PATH "${REXGLUE_ROOT}/cmake") list(APPEND CMAKE_MODULE_PATH "${REXGLUE_ROOT}/thirdparty/catch2/extras") endif() # Third-party dependencies (vendored sources only) add_subdirectory(thirdparty) # Enable warnings after thirdparty add_compile_options( -Wall -Wextra ) include_directories(${REXGLUE_ROOT}/include) add_subdirectory(src/core) add_subdirectory(src/filesystem) add_subdirectory(src/ui) add_subdirectory(src/input) add_subdirectory(src/audio) add_subdirectory(src/graphics) add_subdirectory(src/system) add_subdirectory(src/kernel) add_subdirectory(src/codegen) add_subdirectory(src/rexglue) # Add tests subdirectory if tests are enabled if(REXGLUE_BUILD_TESTS) enable_testing() add_subdirectory(tests) endif() # Print configuration summary message(STATUS "===========================================") message(STATUS "ReXGlue Configuration Summary:") message(STATUS " Version: ${REXGLUE_FULL_VERSION}") message(STATUS " Platform: ${REX_PLATFORM}") message(STATUS " Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") message(STATUS " Configurations: ${CMAKE_CONFIGURATION_TYPES}") message(STATUS " Output Dir: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") message(STATUS " C++ Standard: C++${CMAKE_CXX_STANDARD}") message(STATUS " Graphics: D3D12=${REXGLUE_USE_D3D12} Vulkan=${REXGLUE_USE_VULKAN}") message(STATUS " FidelityFX: ${REXGLUE_ENABLE_FIDELITYFX}") message(STATUS " Tracy: ${REXGLUE_ENABLE_TRACY}") message(STATUS " Perf Counters: ${REXGLUE_ENABLE_PERF_COUNTERS}") message(STATUS "===========================================") # SDK install/export rules (skipped when consumed as a subdirectory) if(PROJECT_IS_TOP_LEVEL) include(cmake/rexglue_devenv.cmake) include(cmake/rexglue_install.cmake) else() # When consumed via add_subdirectory(), provide the same interface as find_package(). # This sets REXGLUE_SHARE_DIR and makes rexglue_configure_target() available. set(REXGLUE_SHARE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/ui" PARENT_SCOPE) set(REXGLUE_SHARE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/ui") include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/rexglue_helpers.cmake) endif()