-
Notifications
You must be signed in to change notification settings - Fork 169
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
438 lines (387 loc) · 18.5 KB
/
Copy pathCMakeLists.txt
File metadata and controls
438 lines (387 loc) · 18.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
cmake_minimum_required(VERSION 3.25 FATAL_ERROR)
project(CWR
VERSION 1.0.0
LANGUAGES CXX C
DESCRIPTION "Arma: Cold War Assault - Remastered"
)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# Version tag embedded in release builds (e.g. rc1, release). Kept as a cache
# variable for script compatibility, but the actual binary metadata is generated
# at build time from OFPR_BUILD_VERSION_TAG so raw `cmake --build` with no env
# clears stale tags instead of reusing this sticky cache value.
set(BUILD_VERSION_TAG "" CACHE STRING "Version tag (rc1 / release / ...); empty = git sha")
add_compile_definitions(
$<$<CONFIG:Debug>:_DEBUG> # Standard debug define (Debug only — avoids _ITERATOR_DEBUG_LEVEL mismatch in Release)
)
if(WIN32)
add_compile_definitions(
# Architecture
x86
WIN32
_LIB
_ALLOW_KEYWORD_MACROS # C++ language features
# Minimal Windows.h — exclude rarely-used APIs, prevent min/max macro pollution
WIN32_LEAN_AND_MEAN
NOMINMAX
NOSERVICE
NOMCX
NOIME
)
# Function- and data-level COMDAT so each function lands in its own
# section. Executable targets opt into /OPT:REF /OPT:ICF to dead-strip
# functions no reachable code calls — see apps/tetris/Tetris/CMakeLists.txt.
add_compile_options(/Gy /Gw)
else()
add_compile_definitions(
HAS_CLOCK_GETTIME # Linux: use clock_gettime in potime.cpp
)
# Equivalent of MSVC /Gy /Gw — per-function/per-data sections so the
# linker (--gc-sections) can dead-strip unused symbols.
add_compile_options(-ffunction-sections -fdata-sections)
endif()
# Make __FILE__ repo-root-relative so log/assert lines (Fail(), DoAssert(), LOG_*)
# read "engine/Poseidon/...:NN" instead of an absolute build-machine path. Affects only
# the __FILE__ macro string, not debug info.
#
# GNU-driver clang only. clang-cl silently ignores GCC-style -f flags on its own command
# line (a per-TU -Wunknown-argument warning), and forwarding via /clang: would rewrite
# __FILE__ to a repo-relative string — which breaks the __FILE__-based repo-root resolution
# several test helpers depend on (e.g. RepoPath() walks __FILE__'s parents expecting an
# absolute path). So leave clang-cl's default absolute __FILE__ alone.
if(NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options(-fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=)
endif()
if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options($<$<CONFIG:Release>:/Zi>)
add_link_options($<$<CONFIG:Release>:/DEBUG>)
else()
add_compile_options($<$<CONFIG:Release>:-g>)
endif()
# Global warning suppressions for legacy codebase and intentional patterns
# These are all actually needed - verified 11,624 warnings without them (Dec 2025)
add_compile_options(
# Most critical suppressions (cover 80% of warnings)
-Wno-microsoft-enum-forward-reference # 1,987 instances - Forward enum declarations (MSVC extension)
-Wno-nontrivial-memcall # 4,000+ instances - Intentional memcpy/memmove on bitwise-movable types (ClassIsMovableZeroed)
-Wno-microsoft-extra-qualification # 324 instances - Extra qualifications on members (MSVC quirk)
# Test/development suppressions
-Wno-varargs # Suppress until EvalError enum in va_start (UB but works)
# Other MSVC compatibility
-Wno-microsoft-include # MSVC-specific include behavior
-Wno-microsoft-cast # MSVC-style casts
-Wno-nonportable-include-path # Case mismatches in includes (Windows filesystem)
-Wno-inconsistent-dllimport # DLL import inconsistencies
-Wno-ignored-pragmas # Unrecognized pragmas (MSVC-specific)
"-Wno-#pragma-messages" # #pragma message directives (build config info)
-Wno-pragma-pack # #pragma pack warnings
# Intentional legacy patterns
-Wno-switch # Incomplete switch statements (intentional in AI logic)
-Wno-reorder-ctor # Constructor init order (legacy code, low risk)
-Wno-reorder # Field initialization order (legacy code, low risk)
-Wno-logical-op-parentheses # Operator precedence (intentional boolean logic)
-Wno-writable-strings # String literals to char* (legacy API contracts)
-Wno-vexing-parse # Most vexing parse (legacy declarations)
-Wno-dynamic-class-memaccess # memset on classes (legacy pattern, works)
-Wno-deprecated-non-prototype # Old C-style function declarations
-Wno-parentheses # Parentheses warnings
-Wno-enum-compare # Enum comparisons (intentional)
-Wno-bitwise-op-parentheses # Bitwise operator precedence
-Wno-delete-non-abstract-non-virtual-dtor # Non-virtual dtors (legacy class design)
-Wno-delete-non-virtual-dtor # Delete on non-final classes with virtual functions but non-virtual dtor
-Wno-implicit-const-int-float-conversion # Implicit conversions (legacy code)
-Wno-invalid-offsetof # offsetof on non-standard-layout types
-Wno-non-pod-varargs # Non-POD types in varargs (legacy pattern)
-Wno-pointer-sign # Pointer sign mismatches
-Wno-pointer-bool-conversion # Pointer to bool conversions
-Wno-tautological-compare # Tautological comparisons (defensive checks for invalid enum values)
-Wno-tautological-bitwise-compare # Bitwise comparisons (defensive programming)
-Wno-bitwise-instead-of-logical # Bitwise operators used for side effects
# Debug/unused suppressions (may be used in other configs)
-Wno-unused-function # Static helper functions
-Wno-unused-private-field # Private fields (may be used in debug builds)
-Wno-unused-variable # Unused vars (may be used in debug builds)
-Wno-unused-but-set-variable # Variables set but not used
-Wno-unused-const-variable # Unused constants
-Wno-unused-value # Unused expression values
-Wno-unneeded-internal-declaration # Static declarations not emitted
# Defensive programming patterns
-Wno-null-dereference # Intentional crash triggers in error paths
-Wno-tautological-constant-out-of-range-compare # Range checks
# Other
-Wno-comment # Comment warnings (legacy formatting)
-Wno-deprecated-declarations # Deprecated functions (platform-specific)
-Wno-undefined-bool-conversion # Undefined bool conversions
-Wno-unknown-warning-option # Warning options not recognized by all clang versions
-Wno-format # Format string mismatches (MSVC vs clang differences)
)
enable_testing()
# Backend availability — driven by platform, overridable
option(CWR_HAS_OPENGL "OpenGL 4.5 graphics backend" ON)
option(CWR_HAS_OPENAL "OpenAL audio backend" ON)
# Disable precompiled headers — for include self-containment audits. With PCH off
# the prelude is no longer force-included, so every TU must pull what it uses;
# building this way surfaces files that silently lean on the prelude. Off in CI.
option(POSEIDON_DISABLE_PCH "Disable precompiled headers (include self-containment audit)" OFF)
# libFuzzer harnesses (network decoder). Off by default; the win-x64-clang-fuzz
# preset turns it on. Requires a clang toolchain built with -fsanitize=fuzzer.
option(POSEIDON_BUILD_FUZZERS "Build libFuzzer network harnesses" OFF)
configure_file(
${CMAKE_SOURCE_DIR}/cmake/BuildConfig.h.in
${CMAKE_BINARY_DIR}/generated/BuildConfig.h
)
include_directories(${CMAKE_BINARY_DIR}/generated)
find_package(Catch2 CONFIG REQUIRED)
find_package(enkiTS CONFIG REQUIRED)
# dist/<preset>/{game,viewer,tools} - auto-create on build
get_filename_component(PRESET_NAME "${CMAKE_BINARY_DIR}" NAME)
set(DIST_PRESET_NAME "${PRESET_NAME}")
if(DIST_PRESET_NAME MATCHES "^(win|macos|linux)-([^-]+)(-(.*))?$")
set(_dist_platform "${CMAKE_MATCH_1}")
set(_dist_arch "${CMAKE_MATCH_2}")
set(_dist_suffix "${CMAKE_MATCH_4}")
if(_dist_suffix MATCHES "^clang-(.+)$")
set(_dist_suffix "${CMAKE_MATCH_1}")
elseif(_dist_suffix STREQUAL "clang")
set(_dist_suffix "")
endif()
if(_dist_suffix)
set(DIST_PRESET_NAME "${_dist_arch}-${_dist_platform}-${_dist_suffix}")
else()
set(DIST_PRESET_NAME "${_dist_arch}-${_dist_platform}")
endif()
elseif(DIST_PRESET_NAME MATCHES "^steamrt4-([^-]+)-clang(-(.*))?$")
set(_dist_arch "${CMAKE_MATCH_1}")
set(_dist_suffix "${CMAKE_MATCH_3}")
if(_dist_suffix)
set(DIST_PRESET_NAME "${_dist_arch}-steamrt4-${_dist_suffix}")
else()
set(DIST_PRESET_NAME "${_dist_arch}-steamrt4")
endif()
endif()
set(DIST_DIR "${CMAKE_SOURCE_DIR}/dist/${DIST_PRESET_NAME}")
add_subdirectory(engine/Poseidon)
add_subdirectory(engine/PoseidonGL33)
add_subdirectory(engine/PoseidonOpenAL)
add_subdirectory(engine/PoseidonFormats)
add_subdirectory(tests/unit/engine/Poseidon/Foundation)
add_subdirectory(apps/tools/Evaluator)
add_subdirectory(tests/unit/apps/Evaluator)
add_subdirectory(tests/unit/engine/Poseidon)
add_subdirectory(apps/cwr/GameBase)
add_subdirectory(apps/cwr/Server)
add_subdirectory(tests/unit/apps/Server)
if(POSEIDON_BUILD_FUZZERS)
add_subdirectory(apps/fuzzers/Fuzzer)
endif()
add_subdirectory(apps/cwr/Game)
add_subdirectory(apps/cwr/GameDemo)
add_subdirectory(apps/tools/Tools)
add_subdirectory(apps/tools/TcPbo)
add_subdirectory(apps/tools/TcLister)
add_subdirectory(apps/tools/Studio)
add_subdirectory(tests/unit/apps/Studio)
add_subdirectory(apps/tetris/Tetris)
add_subdirectory(tests/unit/apps/Tetris)
include(${CMAKE_SOURCE_DIR}/cmake/TridentCTest.cmake)
register_trident_integration_ctests()
# ── Precompiled header ───────────────────────────────────────────────────────
# The Poseidon static lib precompiles PoseidonPCH.hpp (see engine/Poseidon).
# Apply the same prelude as a precompiled header to the other substantial,
# prelude-consuming targets so their TUs build against a precompiled blob instead
# of re-parsing the prelude per file. Per-target PRIVATE rather than REUSE_FROM:
# targets carry differing compile definitions (e.g. _WINDOWS) that clang bakes
# into the PCH, so a shared blob would be rejected. Trivial 1-2 TU targets
# (TcPbo, TcLister) and the standalone PoseidonFormats C-API are excluded.
set(POSEIDON_PCH_TARGETS
PoseidonGL33 PoseidonOpenAL GameBase
PoseidonGame PoseidonGameDemo PoseidonServer PoseidonTools
PoseidonStudio PoseidonEvaluator PoseidonTetris
PoseidonTests PoseidonCoreTests PoseidonFoundationTests
PoseidonServerTests PoseidonTetrisTests PoseidonEvaluatorTests
)
if(NOT POSEIDON_DISABLE_PCH)
foreach(pch_target ${POSEIDON_PCH_TARGETS})
if(TARGET ${pch_target})
# Restrict to C++ TUs: some targets (e.g. PoseidonGL33's glad.c) carry C
# sources, and the prelude is C++ (operator new, namespaces).
target_precompile_headers(${pch_target} PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/engine/Poseidon/Foundation/PoseidonPCH.hpp>)
endif()
endforeach()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
foreach(pch_target Poseidon ${POSEIDON_PCH_TARGETS})
if(TARGET ${pch_target})
target_compile_options(${pch_target} PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:-Xclang>
$<$<COMPILE_LANGUAGE:CXX>:-fno-pch-timestamp>)
endif()
endforeach()
endif()
endif()
# Collect sources for static analysis and formatting
set(ANALYSIS_TARGETS
PoseidonFoundationTests
PoseidonCoreTests
PoseidonTests
PoseidonGame
PoseidonServer
PoseidonTools
PoseidonStudio
PoseidonEvaluator
PoseidonEvaluatorTests
PoseidonTetris
PoseidonTetrisTests
TcPbo
TcLister
)
foreach(target ${ANALYSIS_TARGETS})
get_target_property(target_sources ${target} SOURCES)
get_target_property(target_source_dir ${target} SOURCE_DIR)
foreach(source ${target_sources})
# Convert relative paths to absolute
if(NOT IS_ABSOLUTE ${source})
set(source "${target_source_dir}/${source}")
endif()
# Skip PCH files
if(source MATCHES "pch\\.(cpp|hpp)$")
continue()
endif()
# Collect .cpp files for clang-tidy (analyzes headers transitively)
if(source MATCHES "\\.cpp$")
list(APPEND ALL_CPP_SOURCES ${source})
endif()
# Collect .cpp and .hpp files for clang-format
if(source MATCHES "\\.(cpp|hpp)$")
list(APPEND ALL_FORMAT_SOURCES ${source})
endif()
endforeach()
endforeach()
# Add Poseidon sources to formatting
foreach(source ${POSEIDON_MODERN_SOURCES})
# Convert relative paths to absolute
if(NOT IS_ABSOLUTE ${source})
set(source "${CMAKE_SOURCE_DIR}/engine/Poseidon/${source}")
endif()
# Collect .cpp files for clang-tidy
if(source MATCHES "\\.cpp$")
list(APPEND ALL_CPP_SOURCES ${source})
endif()
# Collect .cpp and .hpp files for clang-format
if(source MATCHES "\\.(cpp|hpp)$")
list(APPEND ALL_FORMAT_SOURCES ${source})
endif()
endforeach()
list(REMOVE_DUPLICATES ALL_CPP_SOURCES)
list(REMOVE_DUPLICATES ALL_FORMAT_SOURCES)
# Write source lists to files (avoid Windows command line length limit)
file(WRITE ${CMAKE_BINARY_DIR}/format_sources.txt "")
foreach(source ${ALL_FORMAT_SOURCES})
file(APPEND ${CMAKE_BINARY_DIR}/format_sources.txt "${source}\n")
endforeach()
file(WRITE ${CMAKE_BINARY_DIR}/tidy_sources.txt "")
foreach(source ${ALL_CPP_SOURCES})
file(APPEND ${CMAKE_BINARY_DIR}/tidy_sources.txt "${source}\n")
endforeach()
# clang-format targets
find_program(CLANG_FORMAT_EXE NAMES clang-format REQUIRED)
if(WIN32)
add_custom_target(Format
COMMAND powershell -NoProfile -Command "Get-Content ${CMAKE_BINARY_DIR}/format_sources.txt | ForEach-Object { & '${CLANG_FORMAT_EXE}' --dry-run --Werror $_ }"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Checking C++ formatting (fails if changes needed)"
VERBATIM
)
add_custom_target(FormatFix
COMMAND powershell -NoProfile -Command "Get-Content ${CMAKE_BINARY_DIR}/format_sources.txt | ForEach-Object { & '${CLANG_FORMAT_EXE}' -i $_ }"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Formatting C++ sources with clang-format"
VERBATIM
)
else()
add_custom_target(Format
COMMAND xargs -a ${CMAKE_BINARY_DIR}/format_sources.txt ${CLANG_FORMAT_EXE} --dry-run --Werror
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Checking C++ formatting (fails if changes needed)"
VERBATIM
)
add_custom_target(FormatFix
COMMAND xargs -a ${CMAKE_BINARY_DIR}/format_sources.txt ${CLANG_FORMAT_EXE} -i
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Formatting C++ sources with clang-format"
VERBATIM
)
endif()
# Python lint targets (ruff via uv, optional)
find_program(UV_EXE NAMES uv)
set(BLENDER_ADDON_DIR ${CMAKE_SOURCE_DIR}/apps/tools/BlenderAddon)
set(BLENDER_PYTHON_LINT_PATHS ${BLENDER_ADDON_DIR}/io_import_p3d)
if(EXISTS ${CMAKE_SOURCE_DIR}/tests/BlenderAddon)
list(APPEND BLENDER_PYTHON_LINT_PATHS ${CMAKE_SOURCE_DIR}/tests/BlenderAddon)
endif()
if(UV_EXE AND EXISTS ${BLENDER_ADDON_DIR}/pyproject.toml)
add_custom_target(PythonLint
COMMAND ${UV_EXE} run ruff check ${BLENDER_PYTHON_LINT_PATHS}
COMMAND ${UV_EXE} run ruff format --check ${BLENDER_PYTHON_LINT_PATHS}
WORKING_DIRECTORY ${BLENDER_ADDON_DIR}
COMMENT "Checking Python formatting and lint (ruff)"
VERBATIM
)
add_custom_target(PythonLintFix
COMMAND ${UV_EXE} run ruff format ${BLENDER_PYTHON_LINT_PATHS}
COMMAND ${UV_EXE} run ruff check --fix ${BLENDER_PYTHON_LINT_PATHS}
WORKING_DIRECTORY ${BLENDER_ADDON_DIR}
COMMENT "Formatting Python sources with ruff"
VERBATIM
)
# Combined targets: C++ + Python
add_custom_target(Lint DEPENDS Format PythonLint)
add_custom_target(LintFix DEPENDS FormatFix PythonLintFix)
else()
# No Python tooling — Lint just runs C++ format
add_custom_target(Lint DEPENDS Format)
add_custom_target(LintFix DEPENDS FormatFix)
endif()
# clang-tidy targets
find_program(CLANG_TIDY_EXE NAMES clang-tidy)
if(CLANG_TIDY_EXE)
if(WIN32)
add_custom_target(Tidy
COMMAND powershell -NoProfile -Command "Get-Content ${CMAKE_BINARY_DIR}/tidy_sources.txt | ForEach-Object { & '${CLANG_TIDY_EXE}' -p ${CMAKE_BINARY_DIR} --allow-no-checks $_ }"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy on all sources"
VERBATIM
)
add_custom_target(TidyFix
COMMAND powershell -NoProfile -Command "Get-Content ${CMAKE_BINARY_DIR}/tidy_sources.txt | ForEach-Object { & '${CLANG_TIDY_EXE}' -p ${CMAKE_BINARY_DIR} --allow-no-checks --fix-errors --fix $_ }"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy with automatic fixes (including compilation errors)"
VERBATIM
)
else()
add_custom_target(Tidy
COMMAND xargs -a ${CMAKE_BINARY_DIR}/tidy_sources.txt ${CLANG_TIDY_EXE} -p ${CMAKE_BINARY_DIR} --allow-no-checks
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy on all sources"
VERBATIM
)
add_custom_target(TidyFix
COMMAND xargs -a ${CMAKE_BINARY_DIR}/tidy_sources.txt ${CLANG_TIDY_EXE} -p ${CMAKE_BINARY_DIR} --allow-no-checks --fix-errors --fix
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy with automatic fixes (including compilation errors)"
VERBATIM
)
endif()
endif()
# File size check target (warn > 3000 lines, error > 5000 lines)
add_custom_target(FileSize
COMMAND ${CMAKE_COMMAND} -DSOURCE_LIST=${CMAKE_BINARY_DIR}/format_sources.txt -P ${CMAKE_SOURCE_DIR}/cmake/CheckFileSize.cmake
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Checking source file sizes (warn > 3000, error > 5000)"
VERBATIM
)