v0.2.0: clang + import std; isolated Windows cross-build (llvm-mingw + SDL3)

This commit is contained in:
EnderTheCoder
2026-09-12 02:04:25 +08:00
parent b35372da52
commit 1d12e4e099
23 changed files with 393 additions and 267 deletions
+80 -67
View File
@@ -1,10 +1,31 @@
cmake_minimum_required(VERSION 3.28)
cmake_minimum_required(VERSION 3.30)
project(OpenRA3 VERSION 0.0.1 LANGUAGES CXX)
# --- 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)
@@ -15,121 +36,113 @@ 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 -Wpedantic)
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()
# --- engine core: fundamental types, math, strings, random, message stream ---
# --- 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
)
target_sources(ra3_core PUBLIC FILE_SET CXX_MODULES FILES src/core/ra3.core.cppm)
openra3_target_defaults(ra3_core)
# --- game logic: objects, players, teams, spatial partition, game loop ---
# --- game logic --------------------------------------------------------------
add_library(ra3_logic STATIC)
target_sources(ra3_logic
PUBLIC FILE_SET CXX_MODULES FILES
src/logic/ra3.logic.cppm
)
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: headless display/input abstraction and the client facade ---
# --- client ------------------------------------------------------------------
add_library(ra3_client STATIC)
target_sources(ra3_client
PUBLIC FILE_SET CXX_MODULES FILES
src/client/ra3.client.cppm
)
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: factions, player templates, science, special powers ---
# --- RA3 game definitions ----------------------------------------------------
add_library(ra3_game STATIC)
target_sources(ra3_game
PUBLIC FILE_SET CXX_MODULES FILES
src/game/ra3.game.cppm
)
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 archives, RefPack codec, local install locator ---
# --- filesystem: BIG4 + RefPack ---------------------------------------------
add_library(ra3_fs STATIC)
target_sources(ra3_fs
PUBLIC FILE_SET CXX_MODULES FILES
src/fs/ra3.fs.cppm
)
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 (real .big data, user's local install) ---
# --- map discovery/loading ---------------------------------------------------
add_library(ra3_map STATIC)
target_sources(ra3_map
PUBLIC FILE_SET CXX_MODULES FILES
src/map/ra3.map.cppm
)
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 headless skirmish simulation ---
# --- minimal skirmish simulation --------------------------------------------
add_library(ra3_skirmish STATIC)
target_sources(ra3_skirmish
PUBLIC FILE_SET CXX_MODULES FILES
src/skirmish/ra3.skirmish.cppm
)
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: framebuffer, TGA decode, BMP encode, map compositing ---
# --- software renderer -------------------------------------------------------
add_library(ra3_render STATIC)
target_sources(ra3_render
PUBLIC FILE_SET CXX_MODULES FILES
src/render/ra3.render.cppm
)
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 when available, otherwise a null backend ---
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
pkg_check_modules(SDL3 QUIET IMPORTED_TARGET sdl3)
endif()
# --- windowed viewer (SDL3 or null) -----------------------------------------
add_library(ra3_ui STATIC)
if(SDL3_FOUND)
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 PkgConfig::SDL3)
message(STATUS "OpenRA3: SDL3 ${SDL3_VERSION} found - windowed viewer enabled")
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_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)
message(STATUS "OpenRA3: SDL3 not found - offscreen BMP output only")
endif()
openra3_target_defaults(ra3_ui)
# --- umbrella module re-exporting the whole SDK ---
# --- umbrella -----------------------------------------------------------------
add_library(ra3 STATIC)
target_sources(ra3
PUBLIC FILE_SET CXX_MODULES FILES
src/ra3.cppm
)
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)
# --- the headless game executable ---
# --- executable ---------------------------------------------------------------
add_executable(openra3 apps/openra3/main.cpp)
target_link_libraries(openra3 PRIVATE ra3)
openra3_target_defaults(openra3)
# --- unit tests ---
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"
"$<TARGET_FILE_DIR:openra3>")
endif()
# --- tests --------------------------------------------------------------------
enable_testing()
add_executable(ra3_tests tests/ra3_tests.cpp)
target_link_libraries(ra3_tests PRIVATE ra3)