cmake_minimum_required(VERSION 3.16) project(orni VERSION 0.8.1 LANGUAGES CXX) # Info del projecte (font de veritat per a project.h) set(PROJECT_LONG_NAME "Orni Attack") set(PROJECT_COPYRIGHT "© 2026 JailDesigner") if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) endif() set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # --- GENERACIÓ DEL project.h AMB GIT HASH --- # Si GIT_HASH ve passat des de fora (Makefile), l'usem; si no, el resolem amb git. if(NOT DEFINED GIT_HASH OR GIT_HASH STREQUAL "") find_package(Git QUIET) if(GIT_FOUND) execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --short=7 HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) endif() if(NOT DEFINED GIT_HASH OR GIT_HASH STREQUAL "") set(GIT_HASH "unknown") endif() endif() configure_file(${CMAKE_SOURCE_DIR}/source/project.h.in ${CMAKE_BINARY_DIR}/project.h @ONLY) # --- LLISTA DE FONTS (AUTO-DESCOBRIMENT) --- # Cerquem tots els .cpp dins core/ i game/, més main.cpp. Exclou legacy/. file(GLOB_RECURSE CORE_SOURCES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/source/core/*.cpp") file(GLOB_RECURSE GAME_SOURCES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/source/game/*.cpp") file(GLOB_RECURSE EXTERNAL_SOURCES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/source/external/*.cpp") set(APP_SOURCES ${CORE_SOURCES} ${GAME_SOURCES} ${EXTERNAL_SOURCES} source/main.cpp ) list(FILTER APP_SOURCES EXCLUDE REGEX ".*/legacy/.*") list(LENGTH APP_SOURCES APP_SOURCES_COUNT) message(STATUS "Fonts .cpp trobades: ${APP_SOURCES_COUNT}") # --- SDL3 --- find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) add_executable(${PROJECT_NAME} ${APP_SOURCES}) target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_SOURCE_DIR}/source" "${CMAKE_BINARY_DIR}" ) target_link_libraries(${PROJECT_NAME} PRIVATE SDL3::SDL3) # Silencia warnings de codi de tercers (mateixa filosofia que el # .clang-tidy a source/external/). Només afecta aquests TUs concrets; # la resta del codi continua compilant amb -Wall -Wextra -Wpedantic. if(EXTERNAL_SOURCES) set_source_files_properties( ${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-Wno-missing-field-initializers;-Wno-deprecated-declarations;-Wno-tautological-compare" ) endif() target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic) target_compile_options(${PROJECT_NAME} PRIVATE $<$:-O2 -ffunction-sections -fdata-sections> ) target_compile_definitions(${PROJECT_NAME} PRIVATE $<$:_DEBUG> $<$:RELEASE_BUILD> ) if(APPLE AND MACOSX_BUNDLE) target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUNDLE) endif() if(WIN32) target_compile_definitions(${PROJECT_NAME} PRIVATE WINDOWS_BUILD) target_link_libraries(${PROJECT_NAME} PRIVATE mingw32) target_link_options(${PROJECT_NAME} PRIVATE -static-libgcc -static-libstdc++ -static ) elseif(APPLE) target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUILD) target_compile_options(${PROJECT_NAME} PRIVATE -Wno-deprecated) elseif(UNIX AND NOT APPLE) target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD) endif() # --- EINA STANDALONE: pack_resources --- # Executable auxiliar que empaqueta `data/` a `build/resources.pack`. # EXCLUDE_FROM_ALL: només es compila quan algun target en depèn (ho fa # `resource_pack`). Build manual: `cmake --build build --target pack_resources`. add_executable(pack_resources EXCLUDE_FROM_ALL tools/pack_resources/pack_resources.cpp source/core/resources/resource_pack.cpp ) target_include_directories(pack_resources PRIVATE "${CMAKE_SOURCE_DIR}/source" "${CMAKE_BINARY_DIR}" ) target_compile_options(pack_resources PRIVATE -Wall -Wextra -Wpedantic) # --- REGENERACIÓ AUTOMÀTICA DE build/resources.pack --- # A cada build re-empaquetem data/ si algun fitxer dins ha canviat. Evita # debugar amb un pack obsolet. CONFIGURE_DEPENDS força CMake a re-globbar # a la pròxima invocació (recull fitxers nous afegits a data/). file(GLOB_RECURSE DATA_FILES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/data/*") set(RESOURCE_PACK "${CMAKE_BINARY_DIR}/resources.pack") add_custom_command( OUTPUT ${RESOURCE_PACK} COMMAND $ "${CMAKE_SOURCE_DIR}/data" "${RESOURCE_PACK}" DEPENDS pack_resources ${DATA_FILES} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Empaquetant data/ → build/resources.pack" VERBATIM ) add_custom_target(resource_pack ALL DEPENDS ${RESOURCE_PACK}) add_dependencies(${PROJECT_NAME} resource_pack) # --- COMPILACIÓ DE SHADERS GLSL → SPIR-V (headers C++ embedits) --- # Compila els shaders .glsl a SPIR-V i els converteix en headers C++ embedits # (source/core/rendering/gpu/spv/*.h). Aquests headers es commiteen al repo, # així que glslc només és necessari quan canvien els .glsl o falten headers. # # Per a macOS hi ha a més els headers MSL escrits a mà a source/core/rendering/gpu/msl/. set(SHADERS_DIR "${CMAKE_SOURCE_DIR}/shaders") set(HEADERS_DIR "${CMAKE_SOURCE_DIR}/source/core/rendering/gpu/spv") set(ALL_SHADER_HEADERS "${HEADERS_DIR}/line_vert_spv.h" "${HEADERS_DIR}/line_frag_spv.h" "${HEADERS_DIR}/postfx_vert_spv.h" "${HEADERS_DIR}/postfx_frag_spv.h" "${HEADERS_DIR}/bloom_frag_spv.h" ) set(ALL_SHADER_SOURCES "${SHADERS_DIR}/line.vert.glsl" "${SHADERS_DIR}/line.frag.glsl" "${SHADERS_DIR}/postfx.vert.glsl" "${SHADERS_DIR}/postfx.frag.glsl" "${SHADERS_DIR}/bloom.frag.glsl" ) set(ALL_SHADER_HEADERS_PRESENT TRUE) foreach(_spv_header IN LISTS ALL_SHADER_HEADERS) if(NOT EXISTS "${_spv_header}") set(ALL_SHADER_HEADERS_PRESENT FALSE) break() endif() endforeach() find_program(GLSLC_EXE NAMES glslc HINTS ${Vulkan_GLSLC_EXECUTABLE}) if(GLSLC_EXE) add_custom_command( OUTPUT ${ALL_SHADER_HEADERS} COMMAND ${CMAKE_COMMAND} -D GLSLC=${GLSLC_EXE} -D SHADERS_DIR=${SHADERS_DIR} -D HEADERS_DIR=${HEADERS_DIR} -P ${CMAKE_SOURCE_DIR}/tools/shaders/compile_spirv.cmake DEPENDS ${ALL_SHADER_SOURCES} ${CMAKE_SOURCE_DIR}/tools/shaders/compile_spirv.cmake COMMENT "Compilant shaders GLSL → headers SPIR-V embedits" VERBATIM ) add_custom_target(shaders DEPENDS ${ALL_SHADER_HEADERS}) add_dependencies(${PROJECT_NAME} shaders) message(STATUS "Shaders: glslc trobat (${GLSLC_EXE}); headers SPV es regeneraran si canvia el GLSL") elseif(ALL_SHADER_HEADERS_PRESENT) message(STATUS "Shaders: glslc no trobat — s'usaran els headers SPV ja commiteats al repo") else() message(FATAL_ERROR "glslc no trobat i falten headers SPV: instal·la 'shaderc' o 'vulkan-sdk' per generar-los") endif() # --- STATIC ANALYSIS / FORMAT TARGETS --- find_program(CLANG_TIDY_EXE NAMES clang-tidy) find_program(CLANG_FORMAT_EXE NAMES clang-format) find_program(CPPCHECK_EXE NAMES cppcheck) file(GLOB_RECURSE ALL_SOURCE_FILES "${CMAKE_SOURCE_DIR}/source/*.cpp" "${CMAKE_SOURCE_DIR}/source/*.hpp" "${CMAKE_SOURCE_DIR}/source/*.h" ) list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX ".*/external/.*") list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX ".*/legacy/.*") set(CPPCHECK_SOURCES ${ALL_SOURCE_FILES}) list(FILTER CPPCHECK_SOURCES INCLUDE REGEX ".*\\.cpp$") if(CLANG_TIDY_EXE) # En macOS, obtenir la ruta del SDK perquè clang-tidy trobe els headers del sistema. set(CLANG_TIDY_EXTRA_ARGS "") if(APPLE) execute_process( COMMAND xcrun --show-sdk-path OUTPUT_VARIABLE MACOS_SDK_PATH OUTPUT_STRIP_TRAILING_WHITESPACE ) if(MACOS_SDK_PATH) set(CLANG_TIDY_EXTRA_ARGS "--extra-arg=-isysroot${MACOS_SDK_PATH}") message(STATUS "clang-tidy usarà SDK de macOS: ${MACOS_SDK_PATH}") endif() endif() add_custom_target(tidy COMMAND ${CLANG_TIDY_EXE} -p ${CMAKE_BINARY_DIR} ${CLANG_TIDY_EXTRA_ARGS} ${ALL_SOURCE_FILES} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "Running clang-tidy..." ) add_custom_target(tidy-fix COMMAND ${CLANG_TIDY_EXE} -p ${CMAKE_BINARY_DIR} ${CLANG_TIDY_EXTRA_ARGS} --fix ${ALL_SOURCE_FILES} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "Running clang-tidy with fixes..." ) else() message(STATUS "clang-tidy no trobat - targets 'tidy' i 'tidy-fix' no disponibles") endif() if(CLANG_FORMAT_EXE) add_custom_target(format COMMAND ${CLANG_FORMAT_EXE} -i ${ALL_SOURCE_FILES} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "Running clang-format..." ) add_custom_target(format-check COMMAND ${CLANG_FORMAT_EXE} --dry-run --Werror ${ALL_SOURCE_FILES} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "Checking clang-format..." ) else() message(STATUS "clang-format no trobat - targets 'format' i 'format-check' no disponibles") endif() if(CPPCHECK_EXE) add_custom_target(cppcheck COMMAND ${CPPCHECK_EXE} --enable=warning,style,performance,portability --std=c++20 --language=c++ --inline-suppr --suppress=missingIncludeSystem --suppress=toomanyconfigs --suppress=*:*source/external/* --suppress=*:*source/legacy/* --suppress=normalCheckLevelMaxBranches --suppress=useStlAlgorithm -D_DEBUG -DLINUX_BUILD --quiet -I ${CMAKE_SOURCE_DIR}/source ${CPPCHECK_SOURCES} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "Running cppcheck..." ) else() message(STATUS "cppcheck no trobat - target 'cppcheck' no disponible") endif()