From fdf9345d5de1c951603e5da3ee8454e9efe2dc28 Mon Sep 17 00:00:00 2001 From: skal Date: Wed, 11 Feb 2026 08:19:05 +0100 Subject: refactor: Modularize CMake build system into 10 specialized modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor monolithic 866-line CMakeLists.txt into 54-line orchestrator + 10 modules: - DemoOptions.cmake - Build option declarations - DemoConfig.cmake - Option implications and platform detection - DemoCommon.cmake - Shared macros (conditional sources, size opts, linking) - DemoDependencies.cmake - External library discovery (WGPU, GLFW) - DemoSourceLists.cmake - Conditional source file lists - DemoLibraries.cmake - Subsystem library targets - DemoTools.cmake - Build tools (asset_packer, compilers) - DemoCodegen.cmake - Code generation (assets, timeline, music) - DemoExecutables.cmake - Main binaries (demo64k, test_demo) - DemoTests.cmake - Test infrastructure (36 tests) - Validation.cmake - Uniform buffer validation Benefits: - 94% reduction in main file size (866 → 54 lines) - Conditional module inclusion (tests only parsed if DEMO_BUILD_TESTS=ON) - Shared macros eliminate 200+ lines of repetition - Clear separation of concerns All 36 tests passing. All build modes verified. Documentation: Created doc/CMAKE_MODULES.md with module architecture. Co-Authored-By: Claude Sonnet 4.5 --- cmake/DemoCommon.cmake | 199 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 cmake/DemoCommon.cmake (limited to 'cmake/DemoCommon.cmake') diff --git a/cmake/DemoCommon.cmake b/cmake/DemoCommon.cmake new file mode 100644 index 0000000..1c63b26 --- /dev/null +++ b/cmake/DemoCommon.cmake @@ -0,0 +1,199 @@ +# CMake Common Utilities +# Shared macros and functions for the demo64k build system + +# ============================================================================= +# demo_set_conditional_sources(VAR HEADLESS_LIST STRIP_LIST NORMAL_LIST) +# ============================================================================= +# Simplifies 3-branch conditional source lists based on build mode +# +# Arguments: +# VAR - Output variable name (e.g., GPU_SOURCES) +# HEADLESS_LIST - Sources for DEMO_HEADLESS mode +# STRIP_LIST - Sources for DEMO_STRIP_EXTERNAL_LIBS mode +# NORMAL_LIST - Sources for normal builds +# +# Usage: +# demo_set_conditional_sources(GPU_SOURCES +# "src/gpu/headless_gpu.cc;src/gpu/effect.cc" +# "src/gpu/stub_gpu.cc" +# "src/gpu/gpu.cc;src/gpu/effect.cc" +# ) +function(demo_set_conditional_sources VAR HEADLESS_LIST STRIP_LIST NORMAL_LIST) + if(DEMO_HEADLESS) + set(${VAR} ${HEADLESS_LIST} PARENT_SCOPE) + elseif(DEMO_STRIP_EXTERNAL_LIBS) + set(${VAR} ${STRIP_LIST} PARENT_SCOPE) + else() + set(${VAR} ${NORMAL_LIST} PARENT_SCOPE) + endif() +endfunction() + +# ============================================================================= +# demo_apply_size_optimizations(TARGET) +# ============================================================================= +# Applies platform-specific size optimization flags to a target +# +# Arguments: +# TARGET - CMake target name +# +# Behavior: +# - Only applies if DEMO_SIZE_OPT is enabled +# - MSVC: /Os /GS- /OPT:REF /OPT:ICF +# - Apple: -Os -Wl,-dead_strip +# - Linux: -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -s +# +# Usage: +# demo_apply_size_optimizations(demo64k) +function(demo_apply_size_optimizations TARGET) + if(DEMO_SIZE_OPT) + if(MSVC) + target_compile_options(${TARGET} PRIVATE /Os /GS-) + target_link_options(${TARGET} PRIVATE /OPT:REF /OPT:ICF /INCREMENTAL:NO) + elseif(APPLE) + target_compile_options(${TARGET} PRIVATE -Os) + target_link_options(${TARGET} PRIVATE -Wl,-dead_strip) + else() + target_compile_options(${TARGET} PRIVATE -Os -ffunction-sections -fdata-sections) + target_link_options(${TARGET} PRIVATE -Wl,--gc-sections -s) + endif() + endif() +endfunction() + +# ============================================================================= +# demo_link_libraries_ordered(TARGET) +# ============================================================================= +# Links subsystem libraries in correct order with platform-specific quirks +# +# Arguments: +# TARGET - CMake target name +# +# Link Order: +# - Circular dependencies on Linux require --start-group/--end-group +# - Apple uses direct linking +# - DEMO_STRIP_EXTERNAL_LIBS mode excludes DEMO_LIBS +# +# Usage: +# demo_link_libraries_ordered(demo64k) +function(demo_link_libraries_ordered TARGET) + if(DEMO_STRIP_EXTERNAL_LIBS) + # Size measurement mode: No external libraries + if(APPLE) + target_link_libraries(${TARGET} PRIVATE 3d gpu audio procedural util) + else() + target_link_libraries(${TARGET} PRIVATE + -Wl,--start-group 3d gpu audio procedural util -Wl,--end-group + pthread m) + endif() + else() + # Normal mode: Link external libraries + if(APPLE) + target_link_libraries(${TARGET} PRIVATE 3d gpu audio procedural util ${DEMO_LIBS}) + else() + target_link_libraries(${TARGET} PRIVATE + -Wl,--start-group 3d gpu audio procedural util -Wl,--end-group + ${DEMO_LIBS}) + endif() + endif() +endfunction() + +# ============================================================================= +# demo_add_test_with_deps(NAME TEST_NAME LABEL SOURCE [SOURCES...] +# [LINK libs...] [DEPENDS targets...] +# [DEFINITIONS defs...] [INCLUDES dirs...]) +# ============================================================================= +# Streamlined test registration with automatic dependency handling +# +# Arguments: +# NAME - Executable target name +# TEST_NAME - CTest test name +# LABEL - Test label for subsystem grouping (audio, gpu, 3d, assets, util) +# SOURCE - First source file (required) +# SOURCES... - Additional source files (parsed until keyword) +# +# Optional Keywords: +# LINK libs... - Libraries to link (parsed until next keyword) +# DEPENDS targets... - Target dependencies (parsed until next keyword) +# DEFINITIONS defs... - Compile definitions (parsed until next keyword) +# INCLUDES dirs... - Include directories (parsed until next keyword) +# +# Usage: +# demo_add_test_with_deps(test_window HammingWindowTest audio +# src/tests/audio/test_window.cc +# ${GEN_DEMO_CC} +# LINK audio util procedural ${DEMO_LIBS} +# DEPENDS generate_demo_assets +# ) +function(demo_add_test_with_deps NAME TEST_NAME LABEL) + set(options "") + set(oneValueArgs "") + set(multiValueArgs LINK DEPENDS DEFINITIONS INCLUDES) + + # Collect sources until we hit a keyword + set(SOURCES "") + set(current_list SOURCES) + set(keyword_mode FALSE) + + foreach(arg ${ARGN}) + if(arg STREQUAL "LINK" OR arg STREQUAL "DEPENDS" OR + arg STREQUAL "DEFINITIONS" OR arg STREQUAL "INCLUDES") + set(current_list ${arg}) + set(keyword_mode TRUE) + else() + list(APPEND ${current_list} ${arg}) + endif() + endforeach() + + # Create test executable + add_executable(${NAME} ${SOURCES}) + add_test(NAME ${TEST_NAME} COMMAND ${NAME}) + set_tests_properties(${TEST_NAME} PROPERTIES LABELS "${LABEL}") + + # Apply optional parameters + if(DEFINED LINK) + target_link_libraries(${NAME} PRIVATE ${LINK}) + endif() + + if(DEFINED DEPENDS) + add_dependencies(${NAME} ${DEPENDS}) + endif() + + if(DEFINED DEFINITIONS) + target_compile_definitions(${NAME} PRIVATE ${DEFINITIONS}) + endif() + + if(DEFINED INCLUDES) + target_include_directories(${NAME} PRIVATE ${INCLUDES}) + endif() +endfunction() + +# ============================================================================= +# add_demo_executable(NAME SOURCES...) +# ============================================================================= +# Creates an executable for the demo +# +# Arguments: +# NAME - Executable target name +# SOURCES - Source files +# +# Note: target_link_libraries must be called manually to ensure correct order +macro(add_demo_executable NAME) + add_executable(${NAME} ${ARGN}) +endmacro() + +# ============================================================================= +# add_demo_test(NAME TEST_NAME LABEL SOURCES...) +# ============================================================================= +# Creates a test executable and registers it with CTest (legacy macro) +# +# Arguments: +# NAME - Executable target name +# TEST_NAME - CTest test name +# LABEL - Test label for subsystem grouping +# SOURCES - Source files +# +# Note: Use demo_add_test_with_deps() for new tests +macro(add_demo_test NAME TEST_NAME LABEL) + add_executable(${NAME} ${ARGN}) + add_test(NAME ${TEST_NAME} COMMAND ${NAME}) + set_tests_properties(${TEST_NAME} PROPERTIES LABELS "${LABEL}") +endmacro() -- cgit v1.2.3