cmake_minimum_required(VERSION 3.12) project(enter_the_fog C) set(CMAKE_C_STANDARD 11) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 1. BUILD PROFILES set(BIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/binary") set(CMAKE_C_FLAGS_RELEASE "-O2 -s") set(CMAKE_C_FLAGS_DEBUG "-g -O0") # --- SANITIZER LOGIC --- # Enables ThreadSanitizer only when CMAKE_BUILD_TYPE is Debug set(SANITIZER_FLAGS "") if(CMAKE_BUILD_TYPE STREQUAL "Debug") message(STATUS "Debug build detected: Enabling ThreadSanitizer") set(SANITIZER_FLAGS "-fsanitize=address") endif() # 2. DEPENDENCIES find_package(PkgConfig REQUIRED) pkg_check_modules(RAYLIB REQUIRED raylib) # 3. SOURCE DISCOVERY file(GLOB_RECURSE ALL_C_FILES "${CMAKE_CURRENT_SOURCE_DIR}/source_code/*.c") file(GLOB_RECURSE ALL_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/source_code/*.h") set(PROJECT_INCLUDE_DIRS "") set(EXTERN_INCLUDE_DIRS "") foreach(_header ${ALL_HEADERS}) get_filename_component(_dir ${_header} DIRECTORY) if(_dir MATCHES "/external_code/") list(APPEND EXTERN_INCLUDE_DIRS ${_dir}) else() list(APPEND PROJECT_INCLUDE_DIRS ${_dir}) endif() endforeach() list(REMOVE_DUPLICATES PROJECT_INCLUDE_DIRS) list(REMOVE_DUPLICATES EXTERN_INCLUDE_DIRS) set(TEST_SOURCES "") set(EXTERN_SOURCES "") set(CORE_SOURCES "") foreach(_file ${ALL_C_FILES}) if(_file MATCHES ".*/test_[^/]+\\.c$" OR _file MATCHES ".*/tests/.*") list(APPEND TEST_SOURCES ${_file}) elseif(_file MATCHES ".*/external_code/.*") list(APPEND EXTERN_SOURCES ${_file}) elseif(NOT _file MATCHES ".*/main\\.c$" AND NOT _file MATCHES ".*/test_main\\.c$") list(APPEND CORE_SOURCES ${_file}) endif() endforeach() # 4. TARGETS # --- EXTERN LIB (Third party code) --- add_library(enter_the_fog_extern STATIC ${EXTERN_SOURCES}) target_include_directories(enter_the_fog_extern SYSTEM PUBLIC ${EXTERN_INCLUDE_DIRS}) # --- CORE LIB (Your code) --- add_library(enter_the_fog_core STATIC ${CORE_SOURCES}) target_include_directories(enter_the_fog_core PUBLIC ${PROJECT_INCLUDE_DIRS}) target_link_libraries(enter_the_fog_core PRIVATE enter_the_fog_extern) # Apply Sanitizers to Core target_compile_options(enter_the_fog_core PRIVATE -Wall -Wextra -Wpedantic -Werror -Wconversion -Wsign-conversion -Wunused-variable -Wunused-function -Wmissing-declarations -Wshadow -Wno-implicit-fallthrough -Wredundant-decls -Wfloat-equal -Winline -Wnull-dereference -Waddress -Wno-long-long -Wimplicit-function-declaration ${SANITIZER_FLAGS}) target_link_options(enter_the_fog_core INTERFACE ${SANITIZER_FLAGS}) # --- EXECUTABLES --- # Main Game add_executable(enter_the_fog "${CMAKE_CURRENT_SOURCE_DIR}/source_code/main.c") target_link_libraries(enter_the_fog enter_the_fog_core enter_the_fog_extern ${RAYLIB_LIBRARIES} m) set_target_properties(enter_the_fog PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BIN_DIR}") target_compile_options(enter_the_fog PRIVATE ${SANITIZER_FLAGS}) target_link_options(enter_the_fog PRIVATE ${SANITIZER_FLAGS}) # Test Suite add_executable(test_suite "${CMAKE_CURRENT_SOURCE_DIR}/source_code/test_main.c" ${TEST_SOURCES}) target_link_libraries(test_suite enter_the_fog_core enter_the_fog_extern ${RAYLIB_LIBRARIES} m) set_target_properties(test_suite PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BIN_DIR}") target_compile_options(test_suite PRIVATE ${SANITIZER_FLAGS}) target_link_options(test_suite PRIVATE ${SANITIZER_FLAGS}) # 5. WORKFLOW COMMANDS (LSP Fix Included) set(ROOT_JSON "${CMAKE_CURRENT_SOURCE_DIR}/compile_commands.json") add_custom_target(test COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/../test" COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -B "${CMAKE_BINARY_DIR}/../test" -S "${CMAKE_SOURCE_DIR}" COMMAND ${CMAKE_COMMAND} --build "${CMAKE_BINARY_DIR}/../test" --target test_suite COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/../test/compile_commands.json" "${ROOT_JSON}" COMMAND "${BIN_DIR}/test_suite" COMMENT "Building and running tests with ThreadSanitizer...") add_custom_target(debug COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/../debug" COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -B "${CMAKE_BINARY_DIR}/../debug" -S "${CMAKE_SOURCE_DIR}" COMMAND ${CMAKE_COMMAND} --build "${CMAKE_BINARY_DIR}/../debug" --target enter_the_fog # This specifically copies the JSON from the debug build folder to the root COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/../debug/compile_commands.json" "${ROOT_JSON}" COMMENT "Building debug binary and updating LSP commands...") target_compile_options(enter_the_fog PRIVATE -Wall -Wextra -Wpedantic -Werror -Wconversion -Wsign-conversion -Wunused-variable -Wunused-function -Wmissing-declarations -Wshadow -Wno-implicit-fallthrough -Wredundant-decls -Wfloat-equal -Winline -Wnull-dereference -Waddress -Wno-long-long -Wimplicit-function-declaration ${SANITIZER_FLAGS}) target_compile_options(test_suite PRIVATE -Wall -Wextra -Wpedantic -Werror -Wconversion -Wsign-conversion -Wunused-variable -Wunused-function -Wmissing-declarations -Wshadow -Wno-implicit-fallthrough -Wredundant-decls -Wfloat-equal -Winline -Wnull-dereference -Waddress -Wno-long-long -Wimplicit-function-declaration ${SANITIZER_FLAGS}) # 6. INITIAL LSP SUPPORT # Catch-all for when you run cmake manually from a build folder if(EXISTS "${CMAKE_BINARY_DIR}/compile_commands.json") execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/compile_commands.json" "${ROOT_JSON}") endif()