cmake_minimum_required(VERSION 3.21) project(CoopAllTheThings VERSION 0.0.1 DESCRIPTION "Steam Remote Play Together for any XInput game" LANGUAGES CXX) if(NOT WIN32) message(FATAL_ERROR "CoopAllTheThings targets Windows only.") endif() set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # Emit compile_commands.json so clangd resolves includes/flags. Ignored by the # Visual Studio generator, so configure the Ninja build (build-clangd/) for this; # .clangd points clangd at that compilation database. set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Single output dir keeps the donor-launch / inject workflow simple: host exe and # hook dll land next to each other under /bin (already in .gitignore). set(COOP_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/bin/$") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${COOP_OUTPUT_DIR}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${COOP_OUTPUT_DIR}") if(MSVC) add_compile_options(/W4 /permissive- /Zc:__cplusplus /utf-8 /MP) add_compile_definitions(UNICODE _UNICODE WIN32_LEAN_AND_MEAN NOMINMAX) endif() # --- x86 sub-build (internal, re-entrant) ---------------------------------- # When the ExternalProject below reconfigures this same tree with -A Win32 and # -DCOOP_X86_HELPER_BUILD=ON, build ONLY the 32-bit hook DLL + injector helper # (staged alongside the x64 binaries) and stop -- no host, tests, or imgui, and # crucially no recursive ExternalProject. option(COOP_X86_HELPER_BUILD "Internal: x86 sub-build (hook DLL + injector helper only)" OFF) if(COOP_X86_HELPER_BUILD) add_subdirectory(common) set(SAFETYHOOK_BUILD_TEST OFF CACHE BOOL "" FORCE) set(SAFETYHOOK_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) set(SAFETYHOOK_BUILD_DOCS OFF CACHE BOOL "" FORCE) add_subdirectory(third_party/safetyhook) add_subdirectory(hook) add_subdirectory(tools/inject_helper) return() endif() add_subdirectory(third_party) add_subdirectory(common) add_subdirectory(host) # The injected hook DLL pulls in SafetyHook, which fetches Zydis via FetchContent # at configure time (allowed for transitive deps). option(COOP_BUILD_HOOK "Build the injected game-side hook DLL" ON) if(COOP_BUILD_HOOK) # SafetyHook's own tests/examples/docs are noise for us. set(SAFETYHOOK_BUILD_TEST OFF CACHE BOOL "" FORCE) set(SAFETYHOOK_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) set(SAFETYHOOK_BUILD_DOCS OFF CACHE BOOL "" FORCE) add_subdirectory(third_party/safetyhook) add_subdirectory(hook) enable_testing() add_subdirectory(tools/audio_tone) # coop_tone: audio source for the loopback test add_subdirectory(tools/audio_probe) # coop_audio_probe: inject + diagnose the render-hook add_subdirectory(tests) endif() # --- x86 helper artifacts for 32-bit (WOW64) games ------------------------- # A 64-bit process can't cleanly inject a 32-bit one, so build the x86 hook DLL # (coop_hook_x86.dll) + a 32-bit injector helper (coop_inject_x86.exe) via a # nested Win32 configure of this same tree, staged next to the x64 binaries. Only # the multi-config Visual Studio generator is supported here (the Ninja # build-clangd/ tree is just for compile_commands and skips this). option(COOP_BUILD_X86_HELPER "Build the x86 hook DLL + injector helper for 32-bit games" ON) if(COOP_BUILD_HOOK AND COOP_BUILD_X86_HELPER AND CMAKE_GENERATOR MATCHES "Visual Studio") include(ExternalProject) ExternalProject_Add(coop_x86 SOURCE_DIR "${CMAKE_SOURCE_DIR}" BINARY_DIR "${CMAKE_BINARY_DIR}/x86" CMAKE_GENERATOR "${CMAKE_GENERATOR}" CMAKE_GENERATOR_PLATFORM "Win32" CMAKE_ARGS "-DCOOP_X86_HELPER_BUILD=ON" BUILD_COMMAND "${CMAKE_COMMAND}" --build --config $ INSTALL_COMMAND "" BUILD_ALWAYS ON USES_TERMINAL_CONFIGURE ON USES_TERMINAL_BUILD ON) endif()