# 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()