cmake_minimum_required(VERSION 3.30) # --- C++26 modules + `import std;` (clang + libc++) ------------------------- # CMake gates `import std` behind an experimental value documented in # Help/dev/experimental.rst for the CMake version in use. set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") # Path to the standard-library module description. A cross toolchain overrides # this before the compiler is probed; this default targets the Linux LLVM # package. if(NOT CMAKE_CXX_STDLIB_MODULES_JSON) set(CMAKE_CXX_STDLIB_MODULES_JSON "/usr/lib/llvm-21/lib/libc++.modules.json") endif() # libc++ must be selected before the compiler is probed: CMake builds its # internal standard-library module target during `project()`, and that target # only sees `CMAKE_CXX_FLAGS` (not later `add_compile_options`). The standard # and extension settings must also be in place before `project()` so the # internal `std.pcm` is built with the same configuration as our modules. set(CMAKE_CXX_FLAGS_INIT "-stdlib=libc++") set(CMAKE_EXE_LINKER_FLAGS_INIT "-stdlib=libc++") set(CMAKE_SHARED_LINKER_FLAGS_INIT "-stdlib=libc++") set(CMAKE_CXX_STANDARD 26) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_SCAN_FOR_MODULES ON) project(OpenRA3 VERSION 0.1.0 LANGUAGES CXX) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) endif() set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") option(OPENRA3_WERROR "Treat warnings as errors" OFF) function(openra3_target_defaults target) target_compile_options(${target} PRIVATE -Wall -Wextra) set_property(TARGET ${target} PROPERTY CXX_MODULE_STD ON) if(OPENRA3_WERROR) target_compile_options(${target} PRIVATE -Werror) endif() endfunction() # --- SDL3: pkg-config on Linux, or an explicit MinGW root for Windows -------- add_library(openra3_sdl3 INTERFACE) set(OPENRA3_HAS_SDL3 OFF) if(OPENRA3_SDL3_ROOT) target_include_directories(openra3_sdl3 INTERFACE "${OPENRA3_SDL3_ROOT}/x86_64-w64-mingw32/include") target_link_libraries(openra3_sdl3 INTERFACE "${OPENRA3_SDL3_ROOT}/x86_64-w64-mingw32/lib/libSDL3.dll.a") set(OPENRA3_HAS_SDL3 ON) else() find_package(PkgConfig QUIET) if(PkgConfig_FOUND) pkg_check_modules(SDL3 QUIET IMPORTED_TARGET sdl3) endif() if(SDL3_FOUND) target_link_libraries(openra3_sdl3 INTERFACE PkgConfig::SDL3) set(OPENRA3_HAS_SDL3 ON) endif() endif() if(OPENRA3_HAS_SDL3) message(STATUS "OpenRA3: SDL3 found - windowed viewer enabled") else() message(STATUS "OpenRA3: SDL3 not found - offscreen BMP output only") endif() # --- engine core ------------------------------------------------------------- add_library(ra3_core STATIC) target_sources(ra3_core PUBLIC FILE_SET CXX_MODULES FILES src/core/ra3.core.cppm) openra3_target_defaults(ra3_core) # --- game logic -------------------------------------------------------------- add_library(ra3_logic STATIC) target_sources(ra3_logic PUBLIC FILE_SET CXX_MODULES FILES src/logic/ra3.logic.cppm) target_link_libraries(ra3_logic PUBLIC ra3_core) openra3_target_defaults(ra3_logic) # --- client ------------------------------------------------------------------ add_library(ra3_client STATIC) target_sources(ra3_client PUBLIC FILE_SET CXX_MODULES FILES src/client/ra3.client.cppm) target_link_libraries(ra3_client PUBLIC ra3_core ra3_logic) openra3_target_defaults(ra3_client) # --- RA3 game definitions ---------------------------------------------------- add_library(ra3_game STATIC) target_sources(ra3_game PUBLIC FILE_SET CXX_MODULES FILES src/game/ra3.game.cppm) target_link_libraries(ra3_game PUBLIC ra3_core ra3_logic) openra3_target_defaults(ra3_game) # --- filesystem: BIG4 + RefPack --------------------------------------------- add_library(ra3_fs STATIC) target_sources(ra3_fs PUBLIC FILE_SET CXX_MODULES FILES src/fs/ra3.fs.cppm) target_link_libraries(ra3_fs PUBLIC ra3_core) openra3_target_defaults(ra3_fs) # --- map discovery/loading --------------------------------------------------- add_library(ra3_map STATIC) target_sources(ra3_map PUBLIC FILE_SET CXX_MODULES FILES src/map/ra3.map.cppm) target_link_libraries(ra3_map PUBLIC ra3_core ra3_fs) openra3_target_defaults(ra3_map) # --- minimal skirmish simulation -------------------------------------------- add_library(ra3_skirmish STATIC) target_sources(ra3_skirmish PUBLIC FILE_SET CXX_MODULES FILES src/skirmish/ra3.skirmish.cppm) target_link_libraries(ra3_skirmish PUBLIC ra3_core ra3_logic ra3_game ra3_map) openra3_target_defaults(ra3_skirmish) # --- software renderer ------------------------------------------------------- add_library(ra3_render STATIC) target_sources(ra3_render PUBLIC FILE_SET CXX_MODULES FILES src/render/ra3.render.cppm) target_link_libraries(ra3_render PUBLIC ra3_core) openra3_target_defaults(ra3_render) # --- windowed viewer (SDL3 or null) ----------------------------------------- add_library(ra3_ui STATIC) if(OPENRA3_HAS_SDL3) target_sources(ra3_ui PUBLIC FILE_SET CXX_MODULES FILES src/ui/ra3.ui.sdl.cppm) target_link_libraries(ra3_ui PUBLIC ra3_core ra3_render openra3_sdl3) else() target_sources(ra3_ui PUBLIC FILE_SET CXX_MODULES FILES src/ui/ra3.ui.null.cppm) target_link_libraries(ra3_ui PUBLIC ra3_core ra3_render) endif() openra3_target_defaults(ra3_ui) # --- umbrella ----------------------------------------------------------------- add_library(ra3 STATIC) target_sources(ra3 PUBLIC FILE_SET CXX_MODULES FILES src/ra3.cppm) target_link_libraries(ra3 PUBLIC ra3_core ra3_logic ra3_client ra3_game ra3_fs ra3_map ra3_skirmish ra3_render ra3_ui) openra3_target_defaults(ra3) # --- executable --------------------------------------------------------------- add_executable(openra3 apps/openra3/main.cpp) target_link_libraries(openra3 PRIVATE ra3) openra3_target_defaults(openra3) if(WIN32 AND OPENRA3_SDL3_ROOT) add_custom_command(TARGET openra3 POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OPENRA3_SDL3_ROOT}/x86_64-w64-mingw32/bin/SDL3.dll" "$") endif() # --- tests -------------------------------------------------------------------- enable_testing() add_executable(ra3_tests tests/ra3_tests.cpp) target_link_libraries(ra3_tests PRIVATE ra3) openra3_target_defaults(ra3_tests) add_test(NAME ra3_tests COMMAND ra3_tests)