From e487e66f64d9ba74dc67ba5bc4741597edaf471d Mon Sep 17 00:00:00 2001 From: portersky Date: Sun, 4 Oct 2026 22:48:25 +0200 Subject: [PATCH] feat: C++ CMake template --- .editorconfig | 30 ++++++++ .gitignore | 1 + CMakeLists.txt | 23 ++++++ deps/Coverage.cmake | 56 ++++++++++++++ deps/Emscripten.cmake | 50 +++++++++++++ deps/FindCMock.cmake | 92 +++++++++++++++++++++++ deps/FindGTest.cmake | 84 +++++++++++++++++++++ deps/FindUnity.cmake | 67 +++++++++++++++++ deps/FindVulkan.cmake | 104 ++++++++++++++++++++++++++ deps/Findasio.cmake | 70 ++++++++++++++++++ deps/Findctre.cmake | 79 ++++++++++++++++++++ deps/Findearcut.cmake | 57 +++++++++++++++ deps/Findfmt.cmake | 68 +++++++++++++++++ deps/Findglad.cmake | 59 +++++++++++++++ deps/Findglfw3.cmake | 72 ++++++++++++++++++ deps/Findglm.cmake | 66 +++++++++++++++++ deps/Findhttplib.cmake | 93 ++++++++++++++++++++++++ deps/Findimgui.cmake | 59 +++++++++++++++ deps/Findimnodes.cmake | 47 ++++++++++++ deps/Findimplot.cmake | 52 +++++++++++++ deps/Findimplot3d.cmake | 52 +++++++++++++ deps/Findkfr.cmake | 105 +++++++++++++++++++++++++++ deps/Findminiaudio.cmake | 63 ++++++++++++++++ deps/Findmvt.cmake | 62 ++++++++++++++++ deps/Findprotozero.cmake | 57 +++++++++++++++ deps/Findsokol.cmake | 56 ++++++++++++++ deps/Findspdlog.cmake | 76 +++++++++++++++++++ deps/Findsqlite3.cmake | 46 ++++++++++++ deps/Findstb.cmake | 49 +++++++++++++ deps/Findtinyobjloader.cmake | 70 ++++++++++++++++++ deps/Findtoml11.cmake | 75 +++++++++++++++++++ deps/Findutf8cpp.cmake | 75 +++++++++++++++++++ deps/Findzlib.cmake | 53 ++++++++++++++ deps/Flags.cmake | 137 +++++++++++++++++++++++++++++++++++ deps/IDE.cmake | 82 +++++++++++++++++++++ deps/Platform.cmake | 64 ++++++++++++++++ deps/Sanitizers.cmake | 28 +++++++ hello.cpp | 6 ++ 38 files changed, 2385 insertions(+) create mode 100644 .editorconfig create mode 100644 CMakeLists.txt create mode 100644 deps/Coverage.cmake create mode 100644 deps/Emscripten.cmake create mode 100644 deps/FindCMock.cmake create mode 100644 deps/FindGTest.cmake create mode 100644 deps/FindUnity.cmake create mode 100644 deps/FindVulkan.cmake create mode 100644 deps/Findasio.cmake create mode 100644 deps/Findctre.cmake create mode 100644 deps/Findearcut.cmake create mode 100644 deps/Findfmt.cmake create mode 100644 deps/Findglad.cmake create mode 100644 deps/Findglfw3.cmake create mode 100644 deps/Findglm.cmake create mode 100644 deps/Findhttplib.cmake create mode 100644 deps/Findimgui.cmake create mode 100644 deps/Findimnodes.cmake create mode 100644 deps/Findimplot.cmake create mode 100644 deps/Findimplot3d.cmake create mode 100644 deps/Findkfr.cmake create mode 100644 deps/Findminiaudio.cmake create mode 100644 deps/Findmvt.cmake create mode 100644 deps/Findprotozero.cmake create mode 100644 deps/Findsokol.cmake create mode 100644 deps/Findspdlog.cmake create mode 100644 deps/Findsqlite3.cmake create mode 100644 deps/Findstb.cmake create mode 100644 deps/Findtinyobjloader.cmake create mode 100644 deps/Findtoml11.cmake create mode 100644 deps/Findutf8cpp.cmake create mode 100644 deps/Findzlib.cmake create mode 100644 deps/Flags.cmake create mode 100644 deps/IDE.cmake create mode 100644 deps/Platform.cmake create mode 100644 deps/Sanitizers.cmake create mode 100644 hello.cpp diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e5d3e2e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,30 @@ +[*] +end_of_line = LF +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{ts,js,tsx,jsx,lua,sh,html}] +charset = utf-8 +indent_style = space +indent_size = 2 + +[*.{go,bb}] +indent_style = tab + +[Makefile] +indent_style = tab + +[*.{yml,json}] +indent_style = space +indent_size = 2 + +[.clang-tidy] +indent_style = space +indent_size = 2 + +[CMakeLists.txt] +indent_style = space +indent_size = 2 diff --git a/.gitignore b/.gitignore index 074653a..ad76eab 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ out/ *.o *.obj *.exe +.cache # OS / editor .DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5401239 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.21) +project(cppcourse VERSION 0.0.0) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Add the deps directory to the module path +# Required for find_package injection +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/deps") + +# Platform and compiler detection +include(Platform) +include(Flags) + +# Dependencies +find_package(fmt REQUIRED) + +# Main executable +add_executable(hello "hello.cpp") +target_include_directories(hello PRIVATE ".") +target_compile_features(hello PRIVATE cxx_std_23) +target_compile_options(hello PRIVATE ${BASE_OPTIONS}) +target_compile_definitions(hello PRIVATE ${BASE_DEFINITIONS}) +target_link_libraries(hello PRIVATE fmt::fmt) diff --git a/deps/Coverage.cmake b/deps/Coverage.cmake new file mode 100644 index 0000000..01159ef --- /dev/null +++ b/deps/Coverage.cmake @@ -0,0 +1,56 @@ +# ============================================================================== +# Coverage +# ============================================================================== +# gcov-based coverage via --coverage, reported by gcovr. +# Works with GCC and Clang on Linux and macOS out of the box. +# Windows requires GCC (e.g. MinGW via scoop install gcc) or a Clang build +# that includes compiler-rt (clang_rt.profile). +# +# Requires: gcovr on PATH (install via: uv tool install gcovr) +# Usage: cmake -DENABLE_COVERAGE=ON ... then ninja coverage +# Report: build/coverage/index.html +# ============================================================================== + +option(ENABLE_COVERAGE "Build with coverage instrumentation" OFF) + +if (ENABLE_COVERAGE) + if (NOT CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + message(FATAL_ERROR "ENABLE_COVERAGE requires GCC or Clang") + endif() + + find_program(GCOVR_EXE gcovr REQUIRED) + + if (CMAKE_C_COMPILER_ID MATCHES "Clang") + # gcovr needs a single-token gcov executable. Wrap llvm-cov gcov in a + # script placed in the build dir (guaranteed no spaces in path). + # AppleClang ships llvm-cov inside Xcode, reached only via xcrun. + if (WIN32) + find_program(LLVM_COV_EXE llvm-cov REQUIRED) + set(GCOV_EXECUTABLE "${CMAKE_BINARY_DIR}/llvm-gcov.bat") + file(WRITE "${GCOV_EXECUTABLE}" "@echo off\r\n\"${LLVM_COV_EXE}\" gcov %*\r\n") + elseif (CMAKE_C_COMPILER_ID STREQUAL "AppleClang") + find_program(XCRUN_EXE xcrun REQUIRED) + set(GCOV_EXECUTABLE "${CMAKE_BINARY_DIR}/llvm-gcov.sh") + file(WRITE "${GCOV_EXECUTABLE}" "#!/bin/sh\nexec xcrun llvm-cov gcov \"$@\"\n") + file(CHMOD "${GCOV_EXECUTABLE}" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE) + else() + find_program(LLVM_COV_EXE llvm-cov REQUIRED) + set(GCOV_EXECUTABLE "${CMAKE_BINARY_DIR}/llvm-gcov.sh") + file(WRITE "${GCOV_EXECUTABLE}" "#!/bin/sh\nexec \"${LLVM_COV_EXE}\" gcov \"$@\"\n") + file(CHMOD "${GCOV_EXECUTABLE}" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE) + endif() + message(STATUS "Coverage: enabled (gcovr: ${GCOVR_EXE}, gcov: llvm-cov gcov)") + else() + set(GCOV_EXECUTABLE "gcov") + message(STATUS "Coverage: enabled (gcovr: ${GCOVR_EXE})") + endif() + + add_compile_options(--coverage -O0 -g) + add_link_options(--coverage) +endif() diff --git a/deps/Emscripten.cmake b/deps/Emscripten.cmake new file mode 100644 index 0000000..37cc7eb --- /dev/null +++ b/deps/Emscripten.cmake @@ -0,0 +1,50 @@ +# ============================================================================== +# Emscripten Configuration +# ============================================================================== +# Emscripten-specific compile definitions, options, and link flags. +# Mirrors the build steps from hellotext (dev/CMakeLists.txt). +# +# Variables set: +# EMSCRIPTEN_DEFINITIONS - Preprocessor definitions for Emscripten +# EMSCRIPTEN_COMPILE_OPTS - Compile flags for Emscripten +# EMSCRIPTEN_LINK_OPTS - Link flags for Emscripten +# +# Requires: Platform.cmake (IS_EMSCRIPTEN) +# ============================================================================== + +# ------------------------------------------------------------------------------ +# Compile Definitions +# ------------------------------------------------------------------------------ +set(EMSCRIPTEN_DEFINITIONS + "GL_GLEXT_PROTOTYPES=1" + "GL3_PROTOTYPES=1" + "EGL_EGLEXT_PROTOTYPES=1" + "ASIO_DISABLE_THREADS" +) + +# ------------------------------------------------------------------------------ +# Compile Options +# ------------------------------------------------------------------------------ +set(EMSCRIPTEN_COMPILE_OPTS + "-pthread" + "-fexceptions" +) + +# ------------------------------------------------------------------------------ +# Link Options +# ------------------------------------------------------------------------------ +set(EMSCRIPTEN_LINK_OPTS + "-sLEGACY_GL_EMULATION=0" + "-sUSE_WEBGL2=1" + "-sFULL_ES3=1" + "-fexceptions" + "-sALLOW_MEMORY_GROWTH" + "-sFETCH" +) + +# ------------------------------------------------------------------------------ +# Apply Flags +# ------------------------------------------------------------------------------ +add_compile_definitions(${EMSCRIPTEN_DEFINITIONS}) +add_compile_options(${EMSCRIPTEN_COMPILE_OPTS}) +add_link_options(${EMSCRIPTEN_LINK_OPTS}) diff --git a/deps/FindCMock.cmake b/deps/FindCMock.cmake new file mode 100644 index 0000000..6988bb7 --- /dev/null +++ b/deps/FindCMock.cmake @@ -0,0 +1,92 @@ +# ============================================================================== +# Find CMock +# ============================================================================== +# This module fetches the CMock mocking framework (depends on Unity). +# +# Targets provided: +# CMock::CMock - The CMock library target +# +# Variables set: +# CMock_FOUND - TRUE if CMock is available +# CMock_LIBRARIES - The CMock library target (CMock::CMock) +# CMock_INCLUDE_DIR - Include directories for CMock +# CMock_VERSION - Version of CMock (if available) +# +# Generator variables (set when Ruby is found): +# CMOCK_SCRIPT - Path to lib/cmock.rb +# RUBY_EXECUTABLE - Path to ruby interpreter +# ============================================================================== + +if (DEFINED _FINDCMOCK_INCLUDED) + return() +endif() +set(_FINDCMOCK_INCLUDED TRUE) + +find_package(Unity REQUIRED) + +if (DEFINED CMock_FIND_VERSION AND NOT CMock_FIND_VERSION STREQUAL "") + set(CMOCK_VERSION "${CMock_FIND_VERSION}") +else() + set(CMOCK_VERSION "2.6.0") +endif() + +message(STATUS "Fetching CMock ${CMOCK_VERSION}") + +include(FetchContent) + +FetchContent_Declare( + cmock + URL https://github.com/ThrowTheSwitch/CMock/archive/refs/tags/v${CMOCK_VERSION}.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +# CMock uses Meson — bypass its build system and compile src/cmock.c directly. +# FetchContent_MakeAvailable cannot be used here (no CMakeLists.txt in CMock), +# so we call FetchContent_Populate directly and opt into the old policy. +cmake_policy(PUSH) +cmake_policy(SET CMP0169 OLD) +FetchContent_GetProperties(cmock) +if (NOT cmock_POPULATED) + FetchContent_Populate(cmock) +endif() +cmake_policy(POP) + +# The Ruby generator expects vendor/unity/auto/type_sanitizer.rb — populate +# it from the Unity source we already have rather than needing a git submodule +set(_cmock_vendor_auto "${cmock_SOURCE_DIR}/vendor/unity/auto") +if (NOT EXISTS "${_cmock_vendor_auto}/type_sanitizer.rb") + file(MAKE_DIRECTORY "${_cmock_vendor_auto}") + file(COPY "${unity_SOURCE_DIR}/auto/" DESTINATION "${_cmock_vendor_auto}") +endif() + +if (NOT TARGET cmock) + add_library(cmock STATIC "${cmock_SOURCE_DIR}/src/cmock.c") + target_include_directories(cmock PUBLIC + "${cmock_SOURCE_DIR}/src" + "${unity_SOURCE_DIR}/src" + ) + target_link_libraries(cmock PUBLIC unity) +endif() + +if (NOT TARGET CMock::CMock) + add_library(CMock::CMock ALIAS cmock) +endif() + +set(CMock_FOUND TRUE) +set(CMock_LIBRARIES CMock::CMock) +set(CMock_VERSION "${CMOCK_VERSION}") +set(CMock_INCLUDE_DIR "${cmock_SOURCE_DIR}/src") +set(CMOCK_SCRIPT "${cmock_SOURCE_DIR}/lib/cmock.rb" CACHE FILEPATH "Path to CMock Ruby generator") + +if (CMock_INCLUDE_DIR AND TARGET cmock) + set_target_properties(cmock PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${CMock_INCLUDE_DIR}" + ) +endif() + +find_program(RUBY_EXECUTABLE ruby) +if (NOT RUBY_EXECUTABLE) + message(WARNING "Ruby not found — CMock code generation unavailable") +endif() + +set(CMOCK_LICENSE_FILE "${cmock_SOURCE_DIR}/LICENSE.txt" CACHE FILEPATH "Path to CMock license file") diff --git a/deps/FindGTest.cmake b/deps/FindGTest.cmake new file mode 100644 index 0000000..7a02c91 --- /dev/null +++ b/deps/FindGTest.cmake @@ -0,0 +1,84 @@ +# ============================================================================== +# Find GTest +# ============================================================================== +# This module fetches the Google Test framework. +# +# Targets provided: +# GTest::gtest - The gtest library target +# GTest::gtest_main - The gtest_main library target +# +# Variables set: +# GTEST_FOUND - TRUE if GTest is available +# GTEST_LIBRARIES - The gtest library targets (gtest gtest_main) +# GTEST_INCLUDE_DIRS - Include directories for GTest +# GTEST_VERSION - Version of GTest +# ============================================================================== + +if(DEFINED _FINDGTEST_INCLUDED) + return() +endif() +set(_FINDGTEST_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 1.17.0 +if (DEFINED gtest_FIND_VERSION AND NOT gtest_FIND_VERSION STREQUAL "") + set(GTEST_VERSION "${gtest_FIND_VERSION}") +else() + set(GTEST_VERSION "1.17.0") +endif() + +message(STATUS "Fetching GoogleTest ${GTEST_VERSION}") +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(GTEST_FETCH_METHOD "GIT") +else() + set(GTEST_FETCH_METHOD "ZIP") +endif() + +if (GTEST_FETCH_METHOD STREQUAL "GIT") + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v${GTEST_VERSION} + ) +else() + FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/refs/tags/v${GTEST_VERSION}.zip + ) +endif() + +FetchContent_MakeAvailable(googletest) + +message(STATUS "{GoogleTest} version: ${GTEST_VERSION}") + +# Provide in-tree aliases to the raw library targets +if(TARGET gtest AND NOT TARGET GTest::gtest) + add_library(GTest::gtest ALIAS gtest) +endif() +if(TARGET gtest_main AND NOT TARGET GTest::gtest_main) + add_library(GTest::gtest_main ALIAS gtest_main) +endif() + +set(GTEST_INCLUDE_DIRS ${googletest_SOURCE_DIR}/googletest/include) +set(GTEST_LIBRARIES gtest gtest_main) +set(GTEST_FOUND TRUE) + +# Mark GTest includes as SYSTEM to suppress warnings from its headers +if (GTEST_INCLUDE_DIRS AND TARGET gtest) + set_target_properties(gtest PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIRS}" + ) +endif() +if (GTEST_INCLUDE_DIRS AND TARGET gtest_main) + set_target_properties(gtest_main PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIRS}" + ) +endif() + +mark_as_advanced( + GTest_INCLUDE_DIRS + GTest_LIBRARY + GTest_MAIN_LIBRARY +) diff --git a/deps/FindUnity.cmake b/deps/FindUnity.cmake new file mode 100644 index 0000000..6d3edb5 --- /dev/null +++ b/deps/FindUnity.cmake @@ -0,0 +1,67 @@ +# ============================================================================== +# Find Unity +# ============================================================================== +# This module fetches the Unity unit testing framework. +# +# Targets provided: +# Unity::Unity - The Unity library target +# +# Variables set: +# Unity_FOUND - TRUE if Unity is available +# Unity_LIBRARIES - The Unity library target (Unity::Unity) +# Unity_INCLUDE_DIR - Include directories for Unity +# Unity_VERSION - Version of Unity (if available) +# ============================================================================== + +if (DEFINED _FINDUNITY_INCLUDED) + return() +endif() +set(_FINDUNITY_INCLUDED TRUE) + +if (DEFINED Unity_FIND_VERSION AND NOT Unity_FIND_VERSION STREQUAL "") + set(UNITY_VERSION "${Unity_FIND_VERSION}") +else() + set(UNITY_VERSION "2.6.1") +endif() + +message(STATUS "Fetching Unity ${UNITY_VERSION}") + +include(FetchContent) + +FetchContent_Declare( + unity + URL https://github.com/ThrowTheSwitch/Unity/archive/refs/tags/v${UNITY_VERSION}.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +FetchContent_MakeAvailable(unity) + +# Unity sets INTERFACE_SYSTEM_INCLUDE_DIRECTORIES to a path inside the build +# tree, which CMake rejects on newer versions. The path stays in +# INTERFACE_INCLUDE_DIRECTORIES so headers are still found. +if (TARGET unity) + set_target_properties(unity PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "") +endif() + +if (NOT TARGET Unity::Unity) + if (TARGET unity) + add_library(Unity::Unity ALIAS unity) + else() + message(FATAL_ERROR "Could not fetch Unity; no target unity or Unity::Unity available") + endif() +endif() + +set(Unity_FOUND TRUE) +set(Unity_LIBRARIES Unity::Unity) +set(Unity_VERSION "${UNITY_VERSION}") +set(Unity_INCLUDE_DIR "${unity_SOURCE_DIR}/src") + + +if (TARGET unity) + target_compile_definitions(unity PUBLIC + UNITY_OUTPUT_COLOR + UNITY_INCLUDE_PRINT_FORMATTED + ) +endif() + +set(UNITY_LICENSE_FILE "${unity_SOURCE_DIR}/LICENSE.txt" CACHE FILEPATH "Path to Unity license file") diff --git a/deps/FindVulkan.cmake b/deps/FindVulkan.cmake new file mode 100644 index 0000000..b6f05b0 --- /dev/null +++ b/deps/FindVulkan.cmake @@ -0,0 +1,104 @@ +# ============================================================================== +# Find Vulkan +# ============================================================================== +# This module finds a locally installed Vulkan SDK. +# +# Targets provided: +# vulkan::vulkan - The Vulkan library target +# +# Variables set: +# Vulkan_FOUND - TRUE if Vulkan is available +# Vulkan_LIBRARIES - The Vulkan library target (Vulkan::Vulkan) +# Vulkan_INCLUDE_DIR - Include directory for Vulkan headers +# Vulkan_VERSION - Version of the found Vulkan SDK +# ============================================================================== + +if (DEFINED _FINDVULKAN_INCLUDED) + return() +endif() +set(_FINDVULKAN_INCLUDED TRUE) + +# detect_vulkan_sdk( ) +# +# Detects the Vulkan SDK root and sets the include path, lib path, and version. +# Search order: +# 1. VULKAN_SDK environment variable (all platforms) +# 2. C:/VulkanSDK/ (Windows fallback) +# 3. /usr (Linux system packages) +# +# Parameters: +# - OUT_INC Name of the variable to set with the SDK include path +# - OUT_LIB Name of the variable to set with the SDK lib path +# - OUT_VER Name of the variable to set with the SDK version string +function(detect_vulkan_sdk OUT_INC OUT_LIB OUT_VER) + # 1. VULKAN_SDK env var (set by the LunarG installer on all platforms) + if (DEFINED ENV{VULKAN_SDK}) + set(_ROOT "$ENV{VULKAN_SDK}") + # The env var already points inside the versioned dir on all platforms + # e.g. C:/VulkanSDK/1.4.335.0 or ~/VulkanSDK/1.4.xxx/x86_64 + set(${OUT_VER} "env" PARENT_SCOPE) + set(${OUT_INC} "${_ROOT}/Include" PARENT_SCOPE) # Windows + set(${OUT_LIB} "${_ROOT}/Lib" PARENT_SCOPE) # Windows + # On Linux/macOS the SDK uses lowercase paths + if (NOT WIN32) + set(${OUT_INC} "${_ROOT}/include" PARENT_SCOPE) + set(${OUT_LIB} "${_ROOT}/lib" PARENT_SCOPE) + endif() + return() + endif() + + # 2. Windows: scan C:/VulkanSDK for latest version directory + if (WIN32) + set(_ROOT "C:/VulkanSDK") + file(GLOB _VERSIONS RELATIVE "${_ROOT}" "${_ROOT}/*") + list(SORT _VERSIONS ORDER DESCENDING) + list(GET _VERSIONS 0 _VERSION) + set(${OUT_VER} "${_VERSION}" PARENT_SCOPE) + set(${OUT_INC} "${_ROOT}/${_VERSION}/Include" PARENT_SCOPE) + set(${OUT_LIB} "${_ROOT}/${_VERSION}/Lib" PARENT_SCOPE) + return() + endif() + + # 3. Linux/macOS: fall back to system paths + set(${OUT_VER} "system" PARENT_SCOPE) + set(${OUT_INC} "/usr/include" PARENT_SCOPE) + set(${OUT_LIB} "/usr/lib" PARENT_SCOPE) +endfunction() + +detect_vulkan_sdk(_Vulkan_INC _Vulkan_LIB Vulkan_VERSION) +message(STATUS "Vulkan SDK: ${Vulkan_VERSION}") + +# Library name differs by platform +if (WIN32) + set(_Vulkan_LIB_NAME "vulkan-1") +else() + set(_Vulkan_LIB_NAME "vulkan") +endif() + +find_library(_Vulkan_LIBRARY ${_Vulkan_LIB_NAME} HINTS "${_Vulkan_LIB}") + +if (NOT _Vulkan_LIBRARY) + if (Vulkan_FIND_REQUIRED) + message(FATAL_ERROR "Could not find ${_Vulkan_LIB_NAME} in ${_Vulkan_LIB}") + else() + message(STATUS " [ ] Vulkan (${_Vulkan_LIB_NAME})") + return() + endif() +endif() + +message(STATUS " [x] Vulkan (${_Vulkan_LIBRARY})") + +if (NOT TARGET vulkan::vulkan) + add_library(vulkan::vulkan UNKNOWN IMPORTED) + set_target_properties(vulkan::vulkan PROPERTIES + IMPORTED_LOCATION "${_Vulkan_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${_Vulkan_INC}" + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_Vulkan_INC}" + ) +endif() + +set(Vulkan_FOUND TRUE) +set(Vulkan_LIBRARIES Vulkan::Vulkan) +set(Vulkan_INCLUDE_DIR "${_Vulkan_INC}") + +unset(_Vulkan_LIBRARY CACHE) diff --git a/deps/Findasio.cmake b/deps/Findasio.cmake new file mode 100644 index 0000000..f0e4bbb --- /dev/null +++ b/deps/Findasio.cmake @@ -0,0 +1,70 @@ +# ============================================================================== +# Find asio +# ============================================================================== +# This module fetches the asio networking library. +# +# Targets provided: +# asio::asio - The asio library target +# +# Variables set: +# asio_FOUND - TRUE if asio is available +# asio_LIBRARIES - The asio library target (asio::asio) +# asio_INCLUDE_DIR - Include directories for asio +# asio_VERSION - Version of asio (if available) +# ============================================================================== + +if (DEFINED _FINDASIO_INCLUDED) + return() +endif() +set(_FINDASIO_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 1.32.0 +if (DEFINED asio_FIND_VERSION AND NOT asio_FIND_VERSION STREQUAL "") + set(ASIO_VERSION "${asio_FIND_VERSION}") +else() + set(ASIO_VERSION "1.30.2") +endif() + +message(STATUS "Fetching asio ${ASIO_VERSION}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(ASIO_FETCH_METHOD "GIT") +else() + message(FATAL_ERROR "Fetch method ZIP not supported") +endif() + +if (ASIO_FETCH_METHOD STREQUAL "GIT") + FetchContent_Declare( + asio + GIT_REPOSITORY https://github.com/mononerv/asio.git + GIT_TAG ${ASIO_VERSION} + ) +endif() + +FetchContent_MakeAvailable(asio) + +if (NOT TARGET asio::asio) + if (TARGET asio) + add_library(asio::asio ALIAS asio) + else() + message(FATAL_ERROR "Could not fetch asio; no target asio or asio::asio available") + endif() +endif() + +set(asio_FOUND TRUE) +set(asio_LIBRARIES asio::asio) +set(asio_VERSION "${ASIO_VERSION}") +get_target_property(_asio_inc asio::asio INTERFACE_INCLUDE_DIRECTORIES) +set(asio_INCLUDE_DIR "${_asio_inc}") + +# Mark asio includes as SYSTEM to suppress warnings from its headers +if (_asio_inc AND TARGET asio) + set_target_properties(asio PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_asio_inc}" + ) +endif() + +set(ASIO_LICENSE_FILE "${asio_SOURCE_DIR}/LICENSE_1_0.txt" CACHE FILEPATH "Path to Asio license file") diff --git a/deps/Findctre.cmake b/deps/Findctre.cmake new file mode 100644 index 0000000..aa70359 --- /dev/null +++ b/deps/Findctre.cmake @@ -0,0 +1,79 @@ +# ============================================================================== +# Find ctre +# ============================================================================== +# This module fetches the CTRE (Compile Time Regular Expressions) library. +# +# Targets provided: +# ctre::ctre - The ctre library target +# +# Variables set: +# ctre_FOUND - TRUE if ctre is available +# ctre_LIBRARIES - The ctre library target (ctre::ctre) +# ctre_INCLUDE_DIR - Include directories for ctre +# ctre_VERSION - Version of ctre (if available) +# ============================================================================== + +if (DEFINED _FINDCTRE_INCLUDED) + return() +endif() +set(_FINDCTRE_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 3.10.0 +if (DEFINED ctre_FIND_VERSION AND NOT ctre_FIND_VERSION STREQUAL "") + set(CTRE_VERSION "${ctre_FIND_VERSION}") +else() + set(CTRE_VERSION "3.10.0") +endif() + +message(STATUS "Fetching ctre ${CTRE_VERSION}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(CTRE_FETCH_METHOD "GIT") +else() + message(FATAL_ERROR "Fetch with zip not supported.") +endif() + +if (CTRE_FETCH_METHOD STREQUAL "GIT") + # Turn off BUILD_TESTING globally to prevent CTest from being included in CTRE + set(BUILD_TESTING OFF CACHE BOOL "Disable testing globally" FORCE) + # Set the CTRE_BUILD_TESTS option before including the CTRE library + set(CTRE_BUILD_TESTS OFF CACHE BOOL "Build ctre Tests" FORCE) + set(CTRE_BUILD_PACKAGE OFF CACHE BOOL "Build ctre Package" FORCE) + + FetchContent_Declare( + ctre + GIT_REPOSITORY https://github.com/hanickadot/compile-time-regular-expressions.git + GIT_TAG v${CTRE_VERSION} + ) +endif() + +FetchContent_MakeAvailable(ctre) + +# Turn BUILD_TESTING back on after including CTRE +set(BUILD_TESTING ON CACHE BOOL "Enable testing globally" FORCE) + +if (NOT TARGET ctre::ctre) + if (TARGET ctre) + add_library(ctre::ctre ALIAS ctre) + else() + message(FATAL_ERROR "Could not fetch ctre; no target ctre or ctre::ctre available") + endif() +endif() + +set(ctre_FOUND TRUE) +set(ctre_LIBRARIES ctre::ctre) +set(ctre_VERSION "${CTRE_VERSION}") +get_target_property(_ctre_inc ctre::ctre INTERFACE_INCLUDE_DIRECTORIES) +set(ctre_INCLUDE_DIR "${_ctre_inc}") + +# Mark ctre includes as SYSTEM to suppress warnings from its headers +if (_ctre_inc AND TARGET ctre) + set_target_properties(ctre PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_ctre_inc}" + ) +endif() + +set(CTRE_LICENSE_FILE "${ctre_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to CTRE license file") diff --git a/deps/Findearcut.cmake b/deps/Findearcut.cmake new file mode 100644 index 0000000..9539860 --- /dev/null +++ b/deps/Findearcut.cmake @@ -0,0 +1,57 @@ +# ============================================================================== +# Find earcut +# ============================================================================== +# This module fetches the earcut.hpp polygon triangulation library. +# +# Targets provided: +# earcut::earcut - The earcut library target +# +# Variables set: +# earcut_FOUND - TRUE if earcut is available +# earcut_LIBRARIES - The earcut library target (earcut::earcut) +# earcut_INCLUDE_DIR - Include directories for earcut +# earcut_VERSION - Version of earcut (if available) +# ============================================================================== + +if (DEFINED _FINDEARCUT_INCLUDED) + return() +endif() +set(_FINDEARCUT_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to v2.2.4 +if (DEFINED earcut_FIND_VERSION AND NOT earcut_FIND_VERSION STREQUAL "") + set(EARCUT_VERSION "${earcut_FIND_VERSION}") +else() + set(EARCUT_VERSION "2.2.4") +endif() + +message(STATUS "Fetching earcut ${EARCUT_VERSION}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (NOT GIT_EXECUTABLE) + message(FATAL_ERROR "Fetch with zip not supported.") +endif() + +FetchContent_Declare( + earcut + GIT_REPOSITORY https://github.com/mapbox/earcut.hpp.git + GIT_TAG v${EARCUT_VERSION} + SOURCE_SUBDIR _unused # no CMakeLists.txt here; skips add_subdirectory +) + +# SOURCE_SUBDIR points to a non-existent directory so FetchContent_MakeAvailable +# skips add_subdirectory; we only need the headers under include/. +FetchContent_MakeAvailable(earcut) + +add_library(earcut INTERFACE) +target_include_directories(earcut SYSTEM INTERFACE "${earcut_SOURCE_DIR}/include") +add_library(earcut::earcut ALIAS earcut) + +set(earcut_FOUND TRUE) +set(earcut_LIBRARIES earcut::earcut) +set(earcut_VERSION "${EARCUT_VERSION}") +set(earcut_INCLUDE_DIR "${earcut_SOURCE_DIR}/include") + +set(EARCUT_LICENSE_FILE "${earcut_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to earcut license file") diff --git a/deps/Findfmt.cmake b/deps/Findfmt.cmake new file mode 100644 index 0000000..83aeaa0 --- /dev/null +++ b/deps/Findfmt.cmake @@ -0,0 +1,68 @@ +# ============================================================================== +# Find fmt +# ============================================================================== +# This module fetches the fmt formatting library. +# +# Targets provided: +# fmt::fmt - The fmt library target +# +# Variables set: +# fmt_FOUND - TRUE if fmt is available +# fmt_LIBRARIES - The fmt library target (fmt::fmt) +# fmt_INCLUDE_DIR - Include directories for fmt +# fmt_VERSION - Version of fmt (if available) +# ============================================================================== + +if (DEFINED _FINDFMT_INCLUDED) + return() +endif() +set(_FINDFMT_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 12.1.0 +if (DEFINED fmt_FIND_VERSION AND NOT fmt_FIND_VERSION STREQUAL "") + set(FMT_VERSION "${fmt_FIND_VERSION}") +else() + set(FMT_VERSION "12.1.0") +endif() + +message(STATUS "Fetching fmt ${FMT_VERSION}") + +include(FetchContent) + +FetchContent_Declare( + fmt + URL https://github.com/fmtlib/fmt/releases/download/${FMT_VERSION}/fmt-${FMT_VERSION}.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +FetchContent_MakeAvailable(fmt) + +if (NOT TARGET fmt::fmt) + if (TARGET fmt) + add_library(fmt::fmt ALIAS fmt) + else() + message(FATAL_ERROR "Could not fetch fmt; no target fmt or fmt::fmt available") + endif() +endif() + +set(fmt_FOUND TRUE) +set(fmt_LIBRARIES fmt::fmt) +set(fmt_VERSION "${FMT_VERSION}") +get_target_property(_fmt_inc fmt::fmt INTERFACE_INCLUDE_DIRECTORIES) +set(fmt_INCLUDE_DIR "${_fmt_inc}") + +# Mark fmt includes as SYSTEM to suppress warnings from its headers +if (_fmt_inc AND TARGET fmt) + set_target_properties(fmt PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_fmt_inc}" + ) +endif() + +# Suppress warnings from fmt's own compiled sources (third-party code) +if (TARGET fmt) + target_compile_options(fmt PRIVATE + $<$,$,$>:-Wno-unused-result> + ) +endif() + +set(FMT_LICENSE_FILE "${fmt_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to fmt license file") diff --git a/deps/Findglad.cmake b/deps/Findglad.cmake new file mode 100644 index 0000000..43624a9 --- /dev/null +++ b/deps/Findglad.cmake @@ -0,0 +1,59 @@ +# ============================================================================== +# Find glad +# ============================================================================== +# This module fetches the glad OpenGL loader library. +# +# Targets provided: +# glad::glad - The glad library target +# +# Variables set: +# glad_FOUND - TRUE if glad is available +# glad_LIBRARIES - The glad library target (glad::glad) +# glad_INCLUDE_DIR - Include directories for glad +# glad_VERSION - Version of glad (commit hash or tag) +# ============================================================================== + +if (DEFINED _FINDGLAD_INCLUDED) + return() +endif() +set(_FINDGLAD_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to commit hash +if (DEFINED glad_FIND_VERSION AND NOT glad_FIND_VERSION STREQUAL "") + set(GLAD_VERSION "${glad_FIND_VERSION}") +else() + set(GLAD_VERSION "f4759d7c5143c0a23391ab05caaf43052cefdd65") +endif() + +message(STATUS "Fetching glad ${GLAD_VERSION}") + +include(FetchContent) + +FetchContent_Declare( + glad + URL https://github.com/mononerv/glad/archive/${GLAD_VERSION}.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +FetchContent_MakeAvailable(glad) + +if (NOT TARGET glad::glad) + if (TARGET glad) + add_library(glad::glad ALIAS glad) + else() + message(FATAL_ERROR "Could not fetch glad; no target glad or glad::glad available") + endif() +endif() + +set(glad_FOUND TRUE) +set(glad_LIBRARIES glad::glad) +set(glad_VERSION "${GLAD_VERSION}") +get_target_property(_glad_inc glad::glad INTERFACE_INCLUDE_DIRECTORIES) +set(glad_INCLUDE_DIR "${_glad_inc}") + +# Mark glad includes as SYSTEM to suppress warnings from its headers +if (_glad_inc AND TARGET glad) + set_target_properties(glad PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_glad_inc}" + ) +endif() diff --git a/deps/Findglfw3.cmake b/deps/Findglfw3.cmake new file mode 100644 index 0000000..9479fcd --- /dev/null +++ b/deps/Findglfw3.cmake @@ -0,0 +1,72 @@ +# ============================================================================== +# Find GLFW +# ============================================================================== +# This module fetches the GLFW library for window/input handling. +# +# Targets provided: +# glfw::glfw - The GLFW library target +# glfw - The GLFW library target (non-namespaced) +# +# Variables set: +# GLFW_FOUND - TRUE if GLFW is available +# GLFW_LIBRARIES - The GLFW library target (glfw::glfw) +# GLFW_INCLUDE_DIR - Include directories for GLFW +# GLFW_VERSION - Version of GLFW (if available) +# ============================================================================== + +if (DEFINED _FINDGLFW_INCLUDED) + return() +endif() +set(_FINDGLFW_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 3.4 +if (DEFINED GLFW_FIND_VERSION AND NOT GLFW_FIND_VERSION STREQUAL "") + set(GLFW_VERSION "${GLFW_FIND_VERSION}") +else() + set(GLFW_VERSION "3.4") +endif() + +message(STATUS "Fetching GLFW ${GLFW_VERSION}") + +include(FetchContent) + +# Disable GLFW extras to keep builds lightweight. +set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) +set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) +# Environment issue where a cross-compilation script +# set(GLFW_BUILD_WAYLAND OFF CACHE BOOL "" FORCE) + +FetchContent_Declare( + glfw + URL https://github.com/glfw/glfw/archive/refs/tags/${GLFW_VERSION}.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +set(_glfw_suppress_prev ${CMAKE_SUPPRESS_DEVELOPER_WARNINGS}) +set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS TRUE CACHE INTERNAL "") +FetchContent_MakeAvailable(glfw) +set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS ${_glfw_suppress_prev} CACHE INTERNAL "") + +if (NOT TARGET glfw::glfw) + if (TARGET glfw) + add_library(glfw::glfw ALIAS glfw) + else() + message(FATAL_ERROR "Could not fetch GLFW; no target glfw or glfw::glfw available") + endif() +endif() + +set(GLFW_FOUND TRUE) +set(GLFW_LIBRARIES glfw::glfw) +get_target_property(_glfw_inc glfw::glfw INTERFACE_INCLUDE_DIRECTORIES) +set(GLFW_INCLUDE_DIR "${_glfw_inc}") + +# Mark GLFW includes as SYSTEM to suppress warnings from its headers +if (_glfw_inc AND TARGET glfw) + set_target_properties(glfw PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_glfw_inc}" + ) +endif() + +set(GLFW_LICENSE_FILE "${glfw_SOURCE_DIR}/LICENSE.md" CACHE FILEPATH "Path to GLFW license file") diff --git a/deps/Findglm.cmake b/deps/Findglm.cmake new file mode 100644 index 0000000..cf5ab62 --- /dev/null +++ b/deps/Findglm.cmake @@ -0,0 +1,66 @@ +# ============================================================================== +# Find glm +# ============================================================================== +# This module fetches the GLM (OpenGL Mathematics) library. +# +# Targets provided: +# glm::glm - The glm library target +# +# Variables set: +# glm_FOUND - TRUE if glm is available +# glm_LIBRARIES - The glm library target (glm::glm) +# glm_INCLUDE_DIR - Include directories for glm +# glm_VERSION - Version of glm (if available) +# ============================================================================== + +if (DEFINED _FINDGLM_INCLUDED) + return() +endif() +set(_FINDGLM_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 1.0.1 +if (DEFINED glm_FIND_VERSION AND NOT glm_FIND_VERSION STREQUAL "") + set(GLM_VERSION "${glm_FIND_VERSION}") +else() + set(GLM_VERSION "1.0.1") +endif() + +message(STATUS "Fetching glm ${GLM_VERSION}") + +include(FetchContent) + +set(_glm_warn_deprecated "${CMAKE_WARN_DEPRECATED}") +set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Suppress deprecated warnings while fetching glm" FORCE) + +FetchContent_Declare( + glm + URL https://github.com/g-truc/glm/archive/refs/tags/${GLM_VERSION}.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +FetchContent_MakeAvailable(glm) + +set(CMAKE_WARN_DEPRECATED "${_glm_warn_deprecated}" CACHE BOOL "Restore deprecation warnings" FORCE) + +if (NOT TARGET glm::glm) + if (TARGET glm) + add_library(glm::glm ALIAS glm) + else() + message(FATAL_ERROR "Could not fetch glm; no target glm or glm::glm available") + endif() +endif() + +set(glm_FOUND TRUE) +set(glm_LIBRARIES glm::glm) +set(glm_VERSION "${GLM_VERSION}") +get_target_property(_glm_inc glm::glm INTERFACE_INCLUDE_DIRECTORIES) +set(glm_INCLUDE_DIR "${_glm_inc}") + +# Mark glm includes as SYSTEM to suppress warnings from its headers +if (_glm_inc AND TARGET glm) + set_target_properties(glm PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_glm_inc}" + ) +endif() + +set(GLM_LICENSE_FILE "${glm_SOURCE_DIR}/copying.txt" CACHE FILEPATH "Path to GLM license file") diff --git a/deps/Findhttplib.cmake b/deps/Findhttplib.cmake new file mode 100644 index 0000000..3d62c6e --- /dev/null +++ b/deps/Findhttplib.cmake @@ -0,0 +1,93 @@ +# ============================================================================== +# Find httplib +# ============================================================================== +# This module fetches the cpp-httplib HTTP library. +# +# Targets provided: +# httplib::httplib - The httplib library target +# +# Variables set: +# httplib_FOUND - TRUE if httplib is available +# httplib_LIBRARIES - The httplib library target (httplib::httplib) +# httplib_INCLUDE_DIR - Include directories for httplib +# httplib_VERSION - Version of httplib +# ============================================================================== + +if (DEFINED _FINDHTTPLIB_INCLUDED) + return() +endif() +set(_FINDHTTPLIB_INCLUDED TRUE) + +message(STATUS "Fetching httplib") + +include(FetchContent) + +# Choose fetch method depending on git availability +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(HTTPLIB_FETCH_METHOD "GIT") +else() + set(HTTPLIB_FETCH_METHOD "ZIP") +endif() + +# Disable optional compression dependencies +set(HTTPLIB_USE_ZSTD_IF_AVAILABLE OFF CACHE BOOL "" FORCE) +set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF CACHE BOOL "" FORCE) + +if (HTTPLIB_FETCH_METHOD STREQUAL "GIT") + FetchContent_Declare( + httplib + GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git + GIT_TAG v0.28.0 + ) +else() + # GitHub release ZIP for v0.28.0 + FetchContent_Declare( + httplib + URL https://github.com/yhirose/cpp-httplib/archive/refs/tags/v0.28.0.zip + ) +endif() + +FetchContent_MakeAvailable(httplib) + +set(httplib_FOUND TRUE) +set(httplib_VERSION "0.28.0") + +# Ensure we have a usable target +if (NOT TARGET httplib::httplib) + if (TARGET httplib) + add_library(httplib::httplib ALIAS httplib) + else() + # As a last resort, create a header-only INTERFACE target around httplib.h + message(STATUS "No 'httplib' or 'httplib::httplib' target exists. Creating a header-only target manually.") + + add_library(httplib INTERFACE) + add_library(httplib::httplib ALIAS httplib) + + # Try to infer the include directory (where httplib.h lives) + if (DEFINED httplib_SOURCE_DIR) + target_include_directories(httplib INTERFACE "${httplib_SOURCE_DIR}") + elseif (DEFINED HTTPLIB_SOURCE_DIR) + target_include_directories(httplib INTERFACE "${HTTPLIB_SOURCE_DIR}") + endif() + endif() +endif() + +set(httplib_FOUND TRUE) +set(httplib_LIBRARIES httplib::httplib) + +get_target_property(_httplib_inc httplib::httplib INTERFACE_INCLUDE_DIRECTORIES) +if (_httplib_inc) + set(httplib_INCLUDE_DIR "${_httplib_inc}") +endif() + +# Mark httplib includes as SYSTEM to suppress warnings from its headers +if (_httplib_inc AND TARGET httplib) + set_target_properties(httplib PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_httplib_inc}" + ) +endif() + +set(HTTPLIB_LICENSE_FILE "${httplib_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to httplib license file") + +message(STATUS "httplib version: ${httplib_VERSION}") diff --git a/deps/Findimgui.cmake b/deps/Findimgui.cmake new file mode 100644 index 0000000..4e42967 --- /dev/null +++ b/deps/Findimgui.cmake @@ -0,0 +1,59 @@ +# ============================================================================== +# Find imgui +# ============================================================================== +# Builds Dear ImGui from the bundled sources in deps/imgui/. +# +# Targets provided: +# imgui::imgui - The Dear ImGui library target +# +# Variables set: +# imgui_FOUND - TRUE if imgui is available +# imgui_LIBRARIES - The imgui library target (imgui::imgui) +# imgui_INCLUDE_DIR - Include directories for imgui +# +# Configuration (set before find_package): +# IMGUI_BACKEND_PLATFORM - Platform backend (default: glfw) +# IMGUI_BACKEND_RENDERER - Renderer backend (default: opengl3) +# IMGUI_BUILD_DEMO - Include demo sources (default: ON) +# ============================================================================== + +if (DEFINED _FINDIMGUI_INCLUDED) + return() +endif() +set(_FINDIMGUI_INCLUDED TRUE) + +set(IMGUI_BACKEND_PLATFORM "glfw" CACHE STRING "Dear ImGui platform backend") +set(IMGUI_BACKEND_RENDERER "opengl3" CACHE STRING "Dear ImGui renderer backend") +option(IMGUI_BUILD_DEMO "Include Dear ImGui demo window sources" ON) + +set(_imgui_source_dir "${CMAKE_CURRENT_LIST_DIR}/imgui") + +if (NOT EXISTS "${_imgui_source_dir}/imgui.cpp") + message(FATAL_ERROR "imgui sources not found at '${_imgui_source_dir}'") +endif() + +# On Emscripten, GLFW is provided by compiler flags (-sUSE_GLFW=3), not a CMake target. +# Create a stub interface target so imgui's CMakeLists skips find_package(glfw3). +if (IS_EMSCRIPTEN AND NOT TARGET glfw) + add_library(glfw INTERFACE) +endif() + +add_subdirectory("${_imgui_source_dir}" "${CMAKE_BINARY_DIR}/_deps/imgui-build" EXCLUDE_FROM_ALL) + +if (NOT TARGET imgui::imgui) + message(FATAL_ERROR "imgui: target imgui::imgui was not created") +endif() + +set(imgui_FOUND TRUE) +set(imgui_LIBRARIES imgui::imgui) +get_target_property(_imgui_inc imgui INTERFACE_INCLUDE_DIRECTORIES) +set(imgui_INCLUDE_DIR "${_imgui_inc}") + +# Mark imgui includes as SYSTEM to suppress warnings from its headers +if (_imgui_inc AND TARGET imgui) + set_target_properties(imgui PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_imgui_inc}" + ) +endif() + +set(IMGUI_LICENSE_FILE "${_imgui_source_dir}/LICENSE.txt" CACHE FILEPATH "Path to Dear ImGui license file") diff --git a/deps/Findimnodes.cmake b/deps/Findimnodes.cmake new file mode 100644 index 0000000..7b68d3e --- /dev/null +++ b/deps/Findimnodes.cmake @@ -0,0 +1,47 @@ +# ============================================================================== +# Find imnodes +# ============================================================================== +# Builds imnodes from the bundled sources in deps/imnodes/. +# +# Targets provided: +# imnodes::imnodes - The imnodes library target +# +# Variables set: +# imnodes_FOUND - TRUE if imnodes is available +# imnodes_LIBRARIES - The imnodes library target (imnodes::imnodes) +# imnodes_INCLUDE_DIR - Include directories for imnodes +# ============================================================================== + +if (DEFINED _FINDIMNODES_INCLUDED) + return() +endif() +set(_FINDIMNODES_INCLUDED TRUE) + +set(_imnodes_source_dir "${CMAKE_CURRENT_LIST_DIR}/imnodes") + +if (NOT EXISTS "${_imnodes_source_dir}/imnodes.cpp") + message(FATAL_ERROR "imnodes sources not found at '${_imnodes_source_dir}'") +endif() + +if (NOT TARGET imgui::imgui) + message(FATAL_ERROR "imnodes requires imgui::imgui to be available before find_package(imnodes)") +endif() + +add_subdirectory("${_imnodes_source_dir}" "${CMAKE_BINARY_DIR}/_deps/imnodes-build" EXCLUDE_FROM_ALL) + +if (NOT TARGET imnodes::imnodes) + message(FATAL_ERROR "imnodes: target imnodes::imnodes was not created") +endif() + +set(imnodes_FOUND TRUE) +set(imnodes_LIBRARIES imnodes::imnodes) +get_target_property(_imnodes_inc imnodes INTERFACE_INCLUDE_DIRECTORIES) +set(imnodes_INCLUDE_DIR "${_imnodes_inc}") + +if (_imnodes_inc AND TARGET imnodes) + set_target_properties(imnodes PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_imnodes_inc}" + ) +endif() + +set(IMNODES_LICENSE_FILE "${_imnodes_source_dir}/LICENSE.md" CACHE FILEPATH "Path to imnodes license file") diff --git a/deps/Findimplot.cmake b/deps/Findimplot.cmake new file mode 100644 index 0000000..a68a7c2 --- /dev/null +++ b/deps/Findimplot.cmake @@ -0,0 +1,52 @@ +# ============================================================================== +# Find implot +# ============================================================================== +# Builds ImPlot from the bundled sources in deps/implot/. +# +# Targets provided: +# implot::implot - The ImPlot library target +# +# Variables set: +# implot_FOUND - TRUE if implot is available +# implot_LIBRARIES - The implot library target (implot::implot) +# implot_INCLUDE_DIR - Include directories for implot +# +# Configuration (set before find_package): +# IMPLOT_BUILD_DEMO - Include demo sources (default: ON) +# ============================================================================== + +if (DEFINED _FINDIMPLOT_INCLUDED) + return() +endif() +set(_FINDIMPLOT_INCLUDED TRUE) + +option(IMPLOT_BUILD_DEMO "Include ImPlot demo sources" ON) + +set(_implot_source_dir "${CMAKE_CURRENT_LIST_DIR}/implot") + +if (NOT EXISTS "${_implot_source_dir}/implot.cpp") + message(FATAL_ERROR "implot sources not found at '${_implot_source_dir}'") +endif() + +if (NOT TARGET imgui::imgui) + message(FATAL_ERROR "implot requires imgui::imgui to be available before find_package(implot)") +endif() + +add_subdirectory("${_implot_source_dir}" "${CMAKE_BINARY_DIR}/_deps/implot-build" EXCLUDE_FROM_ALL) + +if (NOT TARGET implot::implot) + message(FATAL_ERROR "implot: target implot::implot was not created") +endif() + +set(implot_FOUND TRUE) +set(implot_LIBRARIES implot::implot) +get_target_property(_implot_inc implot INTERFACE_INCLUDE_DIRECTORIES) +set(implot_INCLUDE_DIR "${_implot_inc}") + +if (_implot_inc AND TARGET implot) + set_target_properties(implot PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_implot_inc}" + ) +endif() + +set(IMPLOT_LICENSE_FILE "${_implot_source_dir}/LICENSE" CACHE FILEPATH "Path to ImPlot license file") diff --git a/deps/Findimplot3d.cmake b/deps/Findimplot3d.cmake new file mode 100644 index 0000000..6146959 --- /dev/null +++ b/deps/Findimplot3d.cmake @@ -0,0 +1,52 @@ +# ============================================================================== +# Find implot3d +# ============================================================================== +# Builds ImPlot3D from the bundled sources in deps/implo3d/. +# +# Targets provided: +# implot3d::implot3d - The ImPlot3D library target +# +# Variables set: +# implot3d_FOUND - TRUE if implot3d is available +# implot3d_LIBRARIES - The implot3d library target (implot3d::implot3d) +# implot3d_INCLUDE_DIR - Include directories for implot3d +# +# Configuration (set before find_package): +# IMPLOT3D_BUILD_DEMO - Include demo sources (default: ON) +# ============================================================================== + +if (DEFINED _FINDIMPLOT3D_INCLUDED) + return() +endif() +set(_FINDIMPLOT3D_INCLUDED TRUE) + +option(IMPLOT3D_BUILD_DEMO "Include ImPlot3D demo sources" ON) + +set(_implot3d_source_dir "${CMAKE_CURRENT_LIST_DIR}/implo3d") + +if (NOT EXISTS "${_implot3d_source_dir}/implot3d.cpp") + message(FATAL_ERROR "implot3d sources not found at '${_implot3d_source_dir}'") +endif() + +if (NOT TARGET imgui::imgui) + message(FATAL_ERROR "implot3d requires imgui::imgui to be available before find_package(implot3d)") +endif() + +add_subdirectory("${_implot3d_source_dir}" "${CMAKE_BINARY_DIR}/_deps/implot3d-build" EXCLUDE_FROM_ALL) + +if (NOT TARGET implot3d::implot3d) + message(FATAL_ERROR "implot3d: target implot3d::implot3d was not created") +endif() + +set(implot3d_FOUND TRUE) +set(implot3d_LIBRARIES implot3d::implot3d) +get_target_property(_implot3d_inc implot3d INTERFACE_INCLUDE_DIRECTORIES) +set(implot3d_INCLUDE_DIR "${_implot3d_inc}") + +if (_implot3d_inc AND TARGET implot3d) + set_target_properties(implot3d PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_implot3d_inc}" + ) +endif() + +set(IMPLOT3D_LICENSE_FILE "${_implot3d_source_dir}/LICENSE" CACHE FILEPATH "Path to ImPlot3D license file") diff --git a/deps/Findkfr.cmake b/deps/Findkfr.cmake new file mode 100644 index 0000000..22cb39a --- /dev/null +++ b/deps/Findkfr.cmake @@ -0,0 +1,105 @@ +# ============================================================================== +# Find kfr +# ============================================================================== +# This module fetches the KFR DSP library. +# +# Targets provided: +# kfr::kfr - The kfr library target +# +# Variables set: +# kfr_FOUND - TRUE if kfr is available +# kfr_LIBRARIES - The kfr library target (kfr::kfr) +# kfr_INCLUDE_DIR - Include directories for kfr +# kfr_VERSION - Version of kfr (if available) +# ============================================================================== + +if (DEFINED _FINDKFR_INCLUDED) + return() +endif() +set(_FINDKFR_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 7.0.1 +if (DEFINED kfr_FIND_VERSION AND NOT kfr_FIND_VERSION STREQUAL "") + set(KFR_VERSION "${kfr_FIND_VERSION}") +else() + set(KFR_VERSION "7.0.1") +endif() + +message(STATUS "Fetching kfr ${KFR_VERSION}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(KFR_FETCH_METHOD "GIT") +else() + set(KFR_FETCH_METHOD "ZIP") +endif() + +# Disable tests, examples, and other unnecessary components +set(ENABLE_TESTS OFF CACHE BOOL "" FORCE) +set(ENABLE_EXAMPLES OFF CACHE BOOL "" FORCE) +set(KFR_ENABLE_ASMTEST OFF CACHE BOOL "" FORCE) +set(KFR_ENABLE_CAPI_BUILD OFF CACHE BOOL "" FORCE) +set(KFR_INSTALL_HEADERS OFF CACHE BOOL "" FORCE) +set(KFR_INSTALL_LIBRARIES OFF CACHE BOOL "" FORCE) + +# Create dummy uninstall target to prevent KFR from creating one +if (NOT TARGET uninstall) + add_custom_target(uninstall) +endif() + +if (KFR_FETCH_METHOD STREQUAL "GIT") + FetchContent_Declare( + kfr + GIT_REPOSITORY https://github.com/kfrlib/kfr.git + GIT_TAG ${KFR_VERSION} + ) +else() + FetchContent_Declare( + kfr + URL https://github.com/kfrlib/kfr/archive/refs/tags/${KFR_VERSION}.zip + ) +endif() + +FetchContent_MakeAvailable(kfr) + +# Fix KFR's redundant standard library linking +# KFR explicitly links stdc++/pthread/m, but these are already linked by the compiler +# On Windows with Clang: these Unix libraries don't exist +# On macOS: stdc++ becomes c++ which duplicates the automatic libc++ linking +if (TARGET kfr) + get_target_property(_kfr_link_libs kfr INTERFACE_LINK_LIBRARIES) + if (_kfr_link_libs) + list(REMOVE_ITEM _kfr_link_libs "stdc++" "c++" "pthread" "m") + set_target_properties(kfr PROPERTIES INTERFACE_LINK_LIBRARIES "${_kfr_link_libs}") + endif() +endif() + +# Remove KFR's uninstall target +if (TARGET uninstall) + set_target_properties(uninstall PROPERTIES EXCLUDE_FROM_ALL TRUE) +endif() + +if (NOT TARGET kfr::kfr) + if (TARGET kfr) + add_library(kfr::kfr ALIAS kfr) + else() + message(FATAL_ERROR "Could not fetch kfr; no target kfr or kfr::kfr available") + endif() +endif() + +set(kfr_FOUND TRUE) +set(kfr_LIBRARIES kfr::kfr) +set(kfr_VERSION "${KFR_VERSION}") +get_target_property(_kfr_inc kfr::kfr INTERFACE_INCLUDE_DIRECTORIES) +set(kfr_INCLUDE_DIR "${_kfr_inc}") + +# Mark kfr includes as SYSTEM to suppress warnings from its headers +if (_kfr_inc AND TARGET kfr) + set_target_properties(kfr PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_kfr_inc}" + ) +endif() + +set(KFR_LICENSE_FILE "${kfr_SOURCE_DIR}/LICENSE.txt" CACHE FILEPATH "Path to KFR license file") diff --git a/deps/Findminiaudio.cmake b/deps/Findminiaudio.cmake new file mode 100644 index 0000000..3d16cef --- /dev/null +++ b/deps/Findminiaudio.cmake @@ -0,0 +1,63 @@ +# ============================================================================== +# Find miniaudio +# ============================================================================== +# This module fetches the miniaudio audio playback and capture library. +# +# Targets provided: +# miniaudio::miniaudio - The miniaudio library target +# +# Variables set: +# miniaudio_FOUND - TRUE if miniaudio is available +# miniaudio_LIBRARIES - The miniaudio library target (miniaudio::miniaudio) +# miniaudio_INCLUDE_DIR - Include directories for miniaudio +# miniaudio_VERSION - Version of miniaudio +# ============================================================================== + +if (DEFINED _FINDMINIAUDIO_INCLUDED) + return() +endif() +set(_FINDMINIAUDIO_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 0.11.21 +if (DEFINED miniaudio_FIND_VERSION AND NOT miniaudio_FIND_VERSION STREQUAL "") + set(MINIAUDIO_VERSION "${miniaudio_FIND_VERSION}") +else() + set(MINIAUDIO_VERSION "0.11.21") +endif() + +message(STATUS "Fetching miniaudio ${MINIAUDIO_VERSION}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(MINIAUDIO_FETCH_METHOD "GIT") +else() + message(FATAL_ERROR "Fetch with zip not supported.") +endif() + +if (MINIAUDIO_FETCH_METHOD STREQUAL "GIT") + FetchContent_Declare( + miniaudio + GIT_REPOSITORY https://github.com/mackron/miniaudio.git + GIT_TAG ${MINIAUDIO_VERSION} + ) +endif() + +FetchContent_MakeAvailable(miniaudio) + +if (NOT TARGET miniaudio) + add_library(miniaudio INTERFACE) + target_include_directories(miniaudio SYSTEM INTERFACE "${miniaudio_SOURCE_DIR}") +endif() + +if (NOT TARGET miniaudio::miniaudio) + add_library(miniaudio::miniaudio ALIAS miniaudio) +endif() + +set(miniaudio_FOUND TRUE) +set(miniaudio_LIBRARIES miniaudio::miniaudio) +set(miniaudio_VERSION "${MINIAUDIO_VERSION}") +set(miniaudio_INCLUDE_DIR "${miniaudio_SOURCE_DIR}") + +set(MINIAUDIO_LICENSE_FILE "${miniaudio_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to miniaudio license file") diff --git a/deps/Findmvt.cmake b/deps/Findmvt.cmake new file mode 100644 index 0000000..531d9bb --- /dev/null +++ b/deps/Findmvt.cmake @@ -0,0 +1,62 @@ +# ============================================================================== +# Findmvt.cmake +# ============================================================================== +# This module provides the Mapbox Vector Tile Specification (v2.1) for use +# with protozero. The .proto file is downloaded as a reference; actual decoding +# is done manually via protozero (no code generation step required). +# +# Targets provided: +# mvt::mvt - Interface target (pulls in protozero) +# +# Variables set: +# mvt_FOUND - TRUE if mvt is available +# mvt_LIBRARIES - The library target (mvt::mvt) +# mvt_PROTO_FILE - Path to the downloaded vector_tile.proto +# ============================================================================== + +if (DEFINED _FINDMVT_INCLUDED) + return() +endif() +set(_FINDMVT_INCLUDED TRUE) + +# ------------------------------------------------------------------------------ +# Protozero (the actual parsing library) +# ------------------------------------------------------------------------------ +find_package(protozero REQUIRED) + +# ------------------------------------------------------------------------------ +# Download .proto file (reference only — no code generation) +# ------------------------------------------------------------------------------ +set(_MVT_PROTO_DIR "${CMAKE_CURRENT_BINARY_DIR}/mvt_proto") +set(_MVT_PROTO_FILE "${_MVT_PROTO_DIR}/vector_tile.proto") + +file(MAKE_DIRECTORY "${_MVT_PROTO_DIR}") + +if (NOT EXISTS "${_MVT_PROTO_FILE}") + message(STATUS "Downloading vector_tile.proto") + file(DOWNLOAD + "https://raw.githubusercontent.com/mapbox/vector-tile-spec/refs/heads/master/2.1/vector_tile.proto" + "${_MVT_PROTO_FILE}" + STATUS _download_status + ) + list(GET _download_status 0 _download_code) + if (NOT _download_code EQUAL 0) + list(GET _download_status 1 _download_error) + message(FATAL_ERROR "Failed to download vector_tile.proto: ${_download_error}") + endif() +endif() + +message(STATUS "MVT proto: ${_MVT_PROTO_FILE}") + +# ------------------------------------------------------------------------------ +# Interface target +# ------------------------------------------------------------------------------ +if (NOT TARGET mvt::mvt) + add_library(mvt INTERFACE) + target_link_libraries(mvt INTERFACE protozero::protozero) + add_library(mvt::mvt ALIAS mvt) +endif() + +set(mvt_FOUND TRUE) +set(mvt_LIBRARIES mvt::mvt) +set(mvt_PROTO_FILE "${_MVT_PROTO_FILE}" CACHE FILEPATH "Path to vector_tile.proto") diff --git a/deps/Findprotozero.cmake b/deps/Findprotozero.cmake new file mode 100644 index 0000000..bc5b417 --- /dev/null +++ b/deps/Findprotozero.cmake @@ -0,0 +1,57 @@ +# ============================================================================== +# Findprotozero.cmake +# ============================================================================== +# This module fetches the protozero header-only protobuf reader library. +# +# Targets provided: +# protozero::protozero - The protozero interface target +# +# Variables set: +# protozero_FOUND - TRUE if protozero is available +# protozero_LIBRARIES - The library target (protozero::protozero) +# protozero_INCLUDE_DIR - Include directory for protozero headers +# protozero_VERSION - Version of protozero +# ============================================================================== + +if (DEFINED _FINDPROTOZERO_INCLUDED) + return() +endif() +set(_FINDPROTOZERO_INCLUDED TRUE) + +if (DEFINED protozero_FIND_VERSION AND NOT protozero_FIND_VERSION STREQUAL "") + set(PROTOZERO_VERSION "${protozero_FIND_VERSION}") +else() + set(PROTOZERO_VERSION "1.8.1") +endif() + +message(STATUS "Fetching protozero ${PROTOZERO_VERSION}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (NOT GIT_EXECUTABLE) + message(FATAL_ERROR "Fetch with zip not supported.") +endif() + +FetchContent_Declare( + protozero + GIT_REPOSITORY https://github.com/mapbox/protozero.git + GIT_TAG v${PROTOZERO_VERSION} + SOURCE_SUBDIR _unused # no CMakeLists.txt here; skips add_subdirectory +) + +# SOURCE_SUBDIR points to a non-existent directory so FetchContent_MakeAvailable +# skips add_subdirectory (protozero's tests/tools/docs are never configured). +FetchContent_MakeAvailable(protozero) + +add_library(protozero INTERFACE) +target_include_directories(protozero SYSTEM INTERFACE "${protozero_SOURCE_DIR}/include") +add_library(protozero::protozero ALIAS protozero) + +set(protozero_FOUND TRUE) +set(protozero_LIBRARIES protozero::protozero) +set(protozero_VERSION "${PROTOZERO_VERSION}") +get_target_property(_protozero_inc protozero::protozero INTERFACE_INCLUDE_DIRECTORIES) +set(protozero_INCLUDE_DIR "${_protozero_inc}") + +set(PROTOZERO_LICENSE_FILE "${protozero_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to protozero license file") diff --git a/deps/Findsokol.cmake b/deps/Findsokol.cmake new file mode 100644 index 0000000..40c08ff --- /dev/null +++ b/deps/Findsokol.cmake @@ -0,0 +1,56 @@ +# ============================================================================== +# Findsokol.cmake +# ============================================================================== +# This module fetches the sokol single-header C libraries. +# https://github.com/floooh/sokol +# +# Targets provided: +# sokol::sokol - Interface target (headers at repo root) +# +# Variables set: +# sokol_FOUND - TRUE if sokol is available +# sokol_LIBRARIES - The library target (sokol::sokol) +# sokol_INCLUDE_DIR - Include directory (repo root) +# ============================================================================== + +if (DEFINED _FINDSOKOL_INCLUDED) + return() +endif() +set(_FINDSOKOL_INCLUDED TRUE) + +if (DEFINED sokol_FIND_VERSION AND NOT sokol_FIND_VERSION STREQUAL "") + set(SOKOL_TAG "${sokol_FIND_VERSION}") +else() + set(SOKOL_TAG "HEAD") +endif() + +message(STATUS "Fetching sokol @ ${SOKOL_TAG}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (NOT GIT_EXECUTABLE) + message(FATAL_ERROR "Fetch with zip not supported.") +endif() + +FetchContent_Declare( + sokol + GIT_REPOSITORY https://github.com/floooh/sokol.git + GIT_TAG ${SOKOL_TAG} + GIT_SHALLOW TRUE + SOURCE_SUBDIR _unused # no CMakeLists.txt here; skips add_subdirectory +) + +# SOURCE_SUBDIR points to a non-existent directory so FetchContent_MakeAvailable +# skips add_subdirectory; sokol is single-header files, we only need the root dir. +FetchContent_MakeAvailable(sokol) + +add_library(sokol INTERFACE) +target_include_directories(sokol SYSTEM INTERFACE "${sokol_SOURCE_DIR}") +add_library(sokol::sokol ALIAS sokol) + +set(sokol_FOUND TRUE) +set(sokol_LIBRARIES sokol::sokol) +set(sokol_INCLUDE_DIR "${sokol_SOURCE_DIR}") + +set(SOKOL_LICENSE_FILE "${sokol_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to sokol license file") diff --git a/deps/Findspdlog.cmake b/deps/Findspdlog.cmake new file mode 100644 index 0000000..6ad431e --- /dev/null +++ b/deps/Findspdlog.cmake @@ -0,0 +1,76 @@ +# ============================================================================== +# Find spdlog +# ============================================================================== +# This module fetches the spdlog logging library. +# +# Targets provided: +# spdlog::spdlog - The spdlog library target +# +# Variables set: +# spdlog_FOUND - TRUE if spdlog is available +# spdlog_LIBRARIES - The spdlog library target (spdlog::spdlog) +# spdlog_INCLUDE_DIR - Include directories for spdlog +# spdlog_VERSION - Version of spdlog (if available) +# ============================================================================== + +if (DEFINED _FINDSPDLOG_INCLUDED) + return() +endif() +set(_FINDSPDLOG_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to v1.17.0 +# spdlog tags are prefixed with 'v', so prepend it if not already present +if (DEFINED spdlog_FIND_VERSION AND NOT spdlog_FIND_VERSION STREQUAL "") + set(SPDLOG_VERSION "v${spdlog_FIND_VERSION}") +else() + set(SPDLOG_VERSION "v1.17.0") +endif() + +message(STATUS "Fetching spdlog ${SPDLOG_VERSION}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(SPDLOG_FETCH_METHOD "GIT") +else() + set(SPDLOG_FETCH_METHOD "ZIP") +endif() + +if (SPDLOG_FETCH_METHOD STREQUAL "GIT") + FetchContent_Declare( + spdlog + GIT_REPOSITORY https://github.com/gabime/spdlog.git + GIT_TAG ${SPDLOG_VERSION} + ) +else() + FetchContent_Declare( + spdlog + URL https://github.com/gabime/spdlog/archive/refs/tags/${SPDLOG_VERSION}.zip + ) +endif() + +FetchContent_MakeAvailable(spdlog) + +if (NOT TARGET spdlog::spdlog) + if (TARGET spdlog) + add_library(spdlog::spdlog ALIAS spdlog) + else() + message(FATAL_ERROR "Could not fetch spdlog; no target spdlog or spdlog::spdlog available") + endif() +endif() + +set(spdlog_FOUND TRUE) +set(spdlog_LIBRARIES spdlog::spdlog) +set(spdlog_VERSION "${SPDLOG_VERSION}") +get_target_property(_spdlog_inc spdlog::spdlog INTERFACE_INCLUDE_DIRECTORIES) +set(spdlog_INCLUDE_DIR "${_spdlog_inc}") + +# Mark spdlog includes as SYSTEM to suppress warnings from its headers +if (_spdlog_inc AND TARGET spdlog) + set_target_properties(spdlog PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_spdlog_inc}" + ) +endif() + +set(SPDLOG_LICENSE_FILE "${spdlog_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to spdlog license file") diff --git a/deps/Findsqlite3.cmake b/deps/Findsqlite3.cmake new file mode 100644 index 0000000..1564673 --- /dev/null +++ b/deps/Findsqlite3.cmake @@ -0,0 +1,46 @@ +# ============================================================================== +# Findsqlite3.cmake +# ============================================================================== +# This module fetches and builds the SQLite amalgamation as a static library. +# +# Targets provided: +# sqlite3::sqlite3 - The SQLite static library target +# +# Variables set: +# sqlite3_FOUND - TRUE if sqlite3 is available +# sqlite3_LIBRARIES - The sqlite3 library target (sqlite3::sqlite3) +# sqlite3_INCLUDE_DIR - Include directory for sqlite3.h +# sqlite3_VERSION - Version of sqlite3 +# ============================================================================== + +if (DEFINED _FINDSQLITE3_INCLUDED) + return() +endif() +set(_FINDSQLITE3_INCLUDED TRUE) + +set(SQLITE3_VERSION "3.52.0") + +message(STATUS "Fetching sqlite3 ${SQLITE3_VERSION}") + +include(FetchContent) + +FetchContent_Declare( + sqlite3_amalgamation + URL https://sqlite.org/2026/sqlite-amalgamation-3520000.zip + URL_HASH SHA3_256=3fab435106250ea1cdfd5f9fa1657ad832fd431df1d817d48af66ba166e0d16e + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +FetchContent_MakeAvailable(sqlite3_amalgamation) + +if (NOT TARGET sqlite3::sqlite3) + add_library(sqlite3 STATIC ${sqlite3_amalgamation_SOURCE_DIR}/sqlite3.c) + target_include_directories(sqlite3 PUBLIC ${sqlite3_amalgamation_SOURCE_DIR}) + target_link_libraries(sqlite3 PRIVATE ${CMAKE_DL_LIBS}) + add_library(sqlite3::sqlite3 ALIAS sqlite3) +endif() + +set(sqlite3_FOUND TRUE) +set(sqlite3_LIBRARIES sqlite3::sqlite3) +set(sqlite3_VERSION "${SQLITE3_VERSION}") +set(sqlite3_INCLUDE_DIR "${sqlite3_amalgamation_SOURCE_DIR}") diff --git a/deps/Findstb.cmake b/deps/Findstb.cmake new file mode 100644 index 0000000..4390619 --- /dev/null +++ b/deps/Findstb.cmake @@ -0,0 +1,49 @@ +# ============================================================================== +# Find stb +# ============================================================================== +# This module fetches the stb single-file public domain libraries +# (stb_image_write.h for PNG writing, etc.). +# +# Targets provided: +# stb::stb - Interface library (add #define STB_IMAGE_WRITE_IMPLEMENTATION +# in exactly one .cpp before including "stb_image_write.h") +# +# Variables set: +# stb_FOUND - TRUE if stb is available +# stb_INCLUDE_DIR - Include directories for stb +# stb_VERSION - Version of stb (commit) +# ============================================================================== + +if (DEFINED _FINDSTB_INCLUDED) + return() +endif() +set(_FINDSTB_INCLUDED TRUE) + +# Pin to a recent stable commit +set(STB_VERSION "master") + +message(STATUS "Fetching stb ${STB_VERSION}") + +include(FetchContent) + +FetchContent_Declare( + stb + URL https://github.com/nothings/stb/archive/refs/heads/master.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +FetchContent_MakeAvailable(stb) + +add_library(stb INTERFACE) +target_include_directories(stb INTERFACE "${stb_SOURCE_DIR}") + +add_library(stb::stb ALIAS stb) + +set(stb_FOUND TRUE) +set(stb_INCLUDE_DIR "${stb_SOURCE_DIR}") +set(stb_VERSION "${STB_VERSION}") + +# Mark as SYSTEM includes +set_target_properties(stb PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${stb_SOURCE_DIR}" +) diff --git a/deps/Findtinyobjloader.cmake b/deps/Findtinyobjloader.cmake new file mode 100644 index 0000000..29a1d4e --- /dev/null +++ b/deps/Findtinyobjloader.cmake @@ -0,0 +1,70 @@ +# ============================================================================== +# Find tinyobjloader +# ============================================================================== +# This module fetches the tinyobjloader library. +# +# Targets provided: +# tinyobjloader::tinyobjloader - The tinyobjloader library target +# +# Variables set: +# tinyobjloader_FOUND - TRUE if tinyobjloader is available +# tinyobjloader_LIBRARIES - The tinyobjloader library target +# tinyobjloader_INCLUDE_DIR - Include directories for tinyobjloader +# tinyobjloader_VERSION - Version of tinyobjloader (if available) +# ============================================================================== + +if (DEFINED _FINDTINYOBJLOADER_INCLUDED) + return() +endif() +set(_FINDTINYOBJLOADER_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to v2.0.0rc13 +if (DEFINED tinyobjloader_FIND_VERSION AND NOT tinyobjloader_FIND_VERSION STREQUAL "") + set(TINYOBJLOADER_VERSION "${tinyobjloader_FIND_VERSION}") +else() + set(TINYOBJLOADER_VERSION "v2.0.0rc13") +endif() + +message(STATUS "Fetching tinyobjloader ${TINYOBJLOADER_VERSION} via FetchContent...") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(TINYOBJLOADER_FETCH_METHOD "GIT") +else() + message(FATAL_ERROR "Fetch with zip not supported.") +endif() + +if (TINYOBJLOADER_FETCH_METHOD STREQUAL "GIT") + FetchContent_Declare( + tinyobjloader + GIT_REPOSITORY https://github.com/tinyobjloader/tinyobjloader.git + GIT_TAG ${TINYOBJLOADER_VERSION} + ) +endif() + +FetchContent_MakeAvailable(tinyobjloader) + +if (NOT TARGET tinyobjloader::tinyobjloader) + if (TARGET tinyobjloader) + add_library(tinyobjloader::tinyobjloader ALIAS tinyobjloader) + else() + message(FATAL_ERROR "Could not fetch tinyobjloader; no target tinyobjloader or tinyobjloader::tinyobjloader available") + endif() +endif() + +set(tinyobjloader_FOUND TRUE) +set(tinyobjloader_LIBRARIES tinyobjloader::tinyobjloader) +set(tinyobjloader_VERSION "${TINYOBJLOADER_VERSION}") +get_target_property(_tol_inc tinyobjloader::tinyobjloader INTERFACE_INCLUDE_DIRECTORIES) +set(tinyobjloader_INCLUDE_DIR "${_tol_inc}") + +# Mark tinyobjloader includes as SYSTEM to suppress warnings from its headers +if (_tol_inc AND TARGET tinyobjloader) + set_target_properties(tinyobjloader PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_tol_inc}" + ) +endif() + +set(TINYOBJLOADER_LICENSE_FILE "${tinyobjloader_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to tinyobjloader license file") diff --git a/deps/Findtoml11.cmake b/deps/Findtoml11.cmake new file mode 100644 index 0000000..9c7374d --- /dev/null +++ b/deps/Findtoml11.cmake @@ -0,0 +1,75 @@ +# ============================================================================== +# Find toml11 +# ============================================================================== +# This module fetches the toml11 TOML parser library. +# +# Targets provided: +# toml11::toml11 - The toml11 library target +# +# Variables set: +# toml11_FOUND - TRUE if toml11 is available +# toml11_LIBRARIES - The toml11 library target (toml11::toml11) +# toml11_INCLUDE_DIR - Include directories for toml11 +# toml11_VERSION - Version of toml11 (if available) +# ============================================================================== + +if (DEFINED _FINDTOML11_INCLUDED) + return() +endif() +set(_FINDTOML11_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 4.4.0 +if (DEFINED toml11_FIND_VERSION AND NOT toml11_FIND_VERSION STREQUAL "") + set(TOML11_VERSION "${toml11_FIND_VERSION}") +else() + set(TOML11_VERSION "4.4.0") +endif() + +message(STATUS "Fetching toml11 ${TOML11_VERSION}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(TOML11_FETCH_METHOD "GIT") +else() + set(TOML11_FETCH_METHOD "ZIP") +endif() + +if (TOML11_FETCH_METHOD STREQUAL "GIT") + FetchContent_Declare( + toml11 + GIT_REPOSITORY https://github.com/ToruNiina/toml11.git + GIT_TAG v${TOML11_VERSION} + ) +else() + FetchContent_Declare( + toml11 + URL https://github.com/ToruNiina/toml11/archive/refs/tags/v${TOML11_VERSION}.zip + ) +endif() + +FetchContent_MakeAvailable(toml11) + +if (NOT TARGET toml11::toml11) + if (TARGET toml11) + add_library(toml11::toml11 ALIAS toml11) + else() + message(FATAL_ERROR "Could not fetch toml11; no target toml11 or toml11::toml11 available") + endif() +endif() + +set(toml11_FOUND TRUE) +set(toml11_LIBRARIES toml11::toml11) +set(toml11_VERSION "${TOML11_VERSION}") +get_target_property(_toml11_inc toml11::toml11 INTERFACE_INCLUDE_DIRECTORIES) +set(toml11_INCLUDE_DIR "${_toml11_inc}") + +# Mark toml11 includes as SYSTEM to suppress warnings from its headers +if (_toml11_inc AND TARGET toml11) + set_target_properties(toml11 PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_toml11_inc}" + ) +endif() + +set(TOML11_LICENSE_FILE "${toml11_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to toml11 license file") diff --git a/deps/Findutf8cpp.cmake b/deps/Findutf8cpp.cmake new file mode 100644 index 0000000..77de3c3 --- /dev/null +++ b/deps/Findutf8cpp.cmake @@ -0,0 +1,75 @@ +# ============================================================================== +# Find utf8cpp +# ============================================================================== +# This module fetches the UTF-8 with C++ library. +# +# Targets provided: +# utf8cpp::utf8cpp - The utf8cpp library target +# +# Variables set: +# utf8cpp_FOUND - TRUE if utf8cpp is available +# utf8cpp_LIBRARIES - The utf8cpp library target (utf8cpp::utf8cpp) +# utf8cpp_INCLUDE_DIR - Include directories for utf8cpp +# utf8cpp_VERSION - Version of utf8cpp +# ============================================================================== + +if (DEFINED _FINDUTF8CPP_INCLUDED) + return() +endif() +set(_FINDUTF8CPP_INCLUDED TRUE) + +# Use the version passed to find_package(), or default to 4.0.6 +if (DEFINED utf8cpp_FIND_VERSION AND NOT utf8cpp_FIND_VERSION STREQUAL "") + set(UTF8CPP_VERSION "${utf8cpp_FIND_VERSION}") +else() + set(UTF8CPP_VERSION "4.0.6") +endif() + +message(STATUS "Fetching utf8cpp ${UTF8CPP_VERSION}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (GIT_EXECUTABLE) + set(UTF8CPP_FETCH_METHOD "GIT") +else() + set(UTF8CPP_FETCH_METHOD "ZIP") +endif() + +if (UTF8CPP_FETCH_METHOD STREQUAL "GIT") + FetchContent_Declare( + utf8cpp + GIT_REPOSITORY https://github.com/nemtrif/utfcpp.git + GIT_TAG v${UTF8CPP_VERSION} + ) +else() + FetchContent_Declare( + utf8cpp + URL https://github.com/nemtrif/utfcpp/archive/refs/tags/v${UTF8CPP_VERSION}.zip + ) +endif() + +FetchContent_MakeAvailable(utf8cpp) + +if (NOT TARGET utf8cpp::utf8cpp) + if (TARGET utf8cpp) + add_library(utf8cpp::utf8cpp ALIAS utf8cpp) + else() + message(FATAL_ERROR "Could not fetch utf8cpp; no target utf8cpp or utf8cpp::utf8cpp available") + endif() +endif() + +set(utf8cpp_FOUND TRUE) +set(utf8cpp_LIBRARIES utf8cpp::utf8cpp) +set(utf8cpp_VERSION "${UTF8CPP_VERSION}") +get_target_property(_utf8cpp_inc utf8cpp::utf8cpp INTERFACE_INCLUDE_DIRECTORIES) +set(utf8cpp_INCLUDE_DIR "${_utf8cpp_inc}") + +# Mark utf8cpp includes as SYSTEM to suppress warnings from its headers +if (_utf8cpp_inc AND TARGET utf8cpp) + set_target_properties(utf8cpp PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_utf8cpp_inc}" + ) +endif() + +set(UTF8CPP_LICENSE_FILE "${utf8cpp_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to utf8cpp license file") diff --git a/deps/Findzlib.cmake b/deps/Findzlib.cmake new file mode 100644 index 0000000..ba471d4 --- /dev/null +++ b/deps/Findzlib.cmake @@ -0,0 +1,53 @@ +# ============================================================================== +# Findzlib.cmake +# ============================================================================== +# This module fetches and builds the zlib compression library. +# https://github.com/madler/zlib +# +# Targets provided: +# ZLIB::ZLIBSTATIC - Static library target +# +# Variables set: +# zlib_FOUND - TRUE if zlib is available +# zlib_LIBRARIES - The library target (ZLIB::ZLIBSTATIC) +# zlib_INCLUDE_DIR - Include directories for zlib +# ============================================================================== + +if (DEFINED _FINDZLIB_INCLUDED) + return() +endif() +set(_FINDZLIB_INCLUDED TRUE) + +if (DEFINED zlib_FIND_VERSION AND NOT zlib_FIND_VERSION STREQUAL "") + set(ZLIB_TAG "v${zlib_FIND_VERSION}") +else() + set(ZLIB_TAG "v1.3.2") +endif() + +message(STATUS "Fetching zlib @ ${ZLIB_TAG}") + +include(FetchContent) + +find_program(GIT_EXECUTABLE git) +if (NOT GIT_EXECUTABLE) + message(FATAL_ERROR "Fetch with zip not supported.") +endif() + +FetchContent_Declare( + zlib + GIT_REPOSITORY https://github.com/madler/zlib.git + GIT_TAG ${ZLIB_TAG} + GIT_SHALLOW TRUE + EXCLUDE_FROM_ALL +) + +set(ZLIB_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) + +FetchContent_MakeAvailable(zlib) + +# zlib's CMakeLists provides ZLIB::ZLIBSTATIC for the static build +set(zlib_FOUND TRUE) +set(zlib_LIBRARIES ZLIB::ZLIBSTATIC) +set(zlib_INCLUDE_DIR "${zlib_SOURCE_DIR};${zlib_BINARY_DIR}") + +set(ZLIB_LICENSE_FILE "${zlib_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to zlib license file") diff --git a/deps/Flags.cmake b/deps/Flags.cmake new file mode 100644 index 0000000..07a754f --- /dev/null +++ b/deps/Flags.cmake @@ -0,0 +1,137 @@ +# ============================================================================== +# Compiler and Linker Flags +# ============================================================================== +# This module sets platform-specific and compiler-specific flags, libraries, +# and definitions used throughout the build system. +# +# Variables set: +# BASE_LIBRARIES - Libraries to link based on target platform +# BASE_DEFINITIONS - Preprocessor definitions based on target platform +# +# This module also configures global compile and link options for: +# - Emscripten (WebAssembly) builds +# - Clang/GCC warning flags +# - MSVC warning flags and settings +# +# Requires: Platform.cmake must be included first (for IS_* variables) +# ============================================================================== + +# ------------------------------------------------------------------------------ +# Platform-Specific Link Libraries +# ------------------------------------------------------------------------------ +# These libraries are required for OpenGL and windowing on each platform. + +# detect_windows_sdk() +# +# Detects the latest installed Windows 10 SDK and sets out_var to its um/x64 lib path. +# +# Parameters: +# - OUT_VAR Name of the variable to set with the SDK lib path +function(detect_windows_sdk OUT_VAR) + set(_ROOT "C:/Program Files (x86)/Windows Kits/10/Lib") + file(GLOB _VERSIONS RELATIVE "${_ROOT}" "${_ROOT}/10.*") + list(SORT _VERSIONS ORDER DESCENDING) + list(GET _VERSIONS 0 _VERSION) + message(STATUS "Windows SDK: ${_VERSION}") + set(${OUT_VAR} "${_ROOT}/${_VERSION}/um/x64" PARENT_SCOPE) +endfunction() + +# find_and_link( ) +# +# Searches for a library and, if found, appends it to the output list. +# +# Parameters: +# - OUT_VAR Name of the list variable to append the library to +# - LIB_NAME The library filename to search for (e.g. "d3d12.lib") +# - DISPLAY_NAME Human-readable name for status messages (e.g. "Direct3D 12") +function(find_and_link OUT_VAR LIB_NAME DISPLAY_NAME) + find_library(_FOUND_LIB ${LIB_NAME} HINTS "${_WINSDK_LIB_PATH}") + if (_FOUND_LIB) + message(STATUS " [x] ${DISPLAY_NAME} (${LIB_NAME})") + list(APPEND ${OUT_VAR} "${LIB_NAME}") + set(${OUT_VAR} "${${OUT_VAR}}" PARENT_SCOPE) + else() + message(STATUS " [ ] ${DISPLAY_NAME} (${LIB_NAME})") + endif() + unset(_FOUND_LIB CACHE) +endfunction() + +# find_and_link_framework( ) +# +# Searches for an Apple framework and, if found, appends -framework to the output list. +# +# Parameters: +# - OUT_VAR Name of the list variable to append the flag to +# - FRAMEWORK_NAME The framework name to search for (e.g. "Cocoa") +# - DISPLAY_NAME Human-readable name for status messages +function(find_and_link_framework OUT_VAR FRAMEWORK_NAME DISPLAY_NAME) + find_library(_FOUND_LIB ${FRAMEWORK_NAME}) + if (_FOUND_LIB) + message(STATUS " [x] ${DISPLAY_NAME} (-framework ${FRAMEWORK_NAME})") + list(APPEND ${OUT_VAR} "-framework ${FRAMEWORK_NAME}") + set(${OUT_VAR} "${${OUT_VAR}}" PARENT_SCOPE) + else() + message(STATUS " [ ] ${DISPLAY_NAME} (-framework ${FRAMEWORK_NAME})") + endif() + unset(_FOUND_LIB CACHE) +endfunction() + +set(BASE_LIBRARIES "") +if (IS_MACOS) + # TODO: Support macOS + message(STATUS "macOS link libraries:") + find_and_link_framework(BASE_LIBRARIES "Cocoa" "Cocoa") + find_and_link_framework(BASE_LIBRARIES "IOKit" "IOKit") + find_and_link_framework(BASE_LIBRARIES "CoreVideo" "Core Video") + find_and_link_framework(BASE_LIBRARIES "OpenGL" "OpenGL") +elseif (IS_LINUX) # Linux, BSD, Solaris, Minix + message(STATUS "Linux link libraries:") + find_and_link(BASE_LIBRARIES "dl" "Dynamic Linking") + find_and_link(BASE_LIBRARIES "m" "Math") + find_and_link(BASE_LIBRARIES "GL" "OpenGL") + find_and_link(BASE_LIBRARIES "X11" "X11") +elseif (IS_WINDOWS) + detect_windows_sdk(_WINSDK_LIB_PATH) + message(STATUS "Windows link libraries:") + find_and_link(BASE_LIBRARIES "OpenGL32.lib" "OpenGL") + find_and_link(BASE_LIBRARIES "winmm.lib" "WinMM") + find_and_link(BASE_LIBRARIES "dwmapi.lib" "DWM API") +elseif(IS_EMSCRIPTEN) + include(Emscripten) +endif() + +# ------------------------------------------------------------------------------ +# Platform-Specific Definitions +# ------------------------------------------------------------------------------ +set(BASE_DEFINITIONS + "ASIO_STANDALONE" +) +if (IS_WINDOWS) + set(BASE_DEFINITIONS + ${BASE_DEFINITIONS} + # See _WIN32_WINNT version constants + # https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt + "_WIN32_WINNT=0x0A00" + ) +endif() + +# ------------------------------------------------------------------------------ +# Compiler Warning Flags +# ------------------------------------------------------------------------------ +# These are stored in BASE_OPTIONS and applied per-target via +# target_compile_options() to avoid polluting external dependencies. +set(BASE_OPTIONS "") +if (IS_CLANG_OR_GCC) + set(BASE_OPTIONS + "-Wall" # Enable all common warnings + "-Wextra" # Enable extra warnings + "-Werror" # Treat warnings as errors + ) +elseif (IS_MSVC) + set(BASE_OPTIONS + "/W4" # Warning level 4 (high) + "/WX" # Treat warnings as errors + "/utf-8" # Set source and execution character set to UTF-8 + "/Zc:__cplusplus" # Report correct C++ standard version in __cplusplus + ) +endif() diff --git a/deps/IDE.cmake b/deps/IDE.cmake new file mode 100644 index 0000000..a342224 --- /dev/null +++ b/deps/IDE.cmake @@ -0,0 +1,82 @@ +# ============================================================================== +# IDE Integration +# ============================================================================== +# This module configures IDE-specific settings for better project organization. +# Currently supports Visual Studio and Xcode by grouping dependency targets +# into folders for cleaner navigation in the IDE's solution/project explorer. +# +# Folder structure created: +# deps/ - Third-party libraries (fmt, glad, imgui, sqlite3, etc.) +# deps/GLFW/ - GLFW library and related targets +# deps/gtest/ - Google Test targets +# deps/tinyobj/ - tinyobjloader and its uninstall target +# ============================================================================== + +# ------------------------------------------------------------------------------ +# Visual Studio and Xcode Folder Organization +# ------------------------------------------------------------------------------ +# Group dependency targets into logical folders for easier navigation. +# This only affects IDE project generation and has no effect on the build. +# Helper function to set folder property if target exists +function(set_target_folder target folder) + if (TARGET ${target}) + set_target_properties(${target} PROPERTIES FOLDER ${folder}) + endif() +endfunction() + +if (CMAKE_GENERATOR MATCHES "Visual Studio" OR CMAKE_GENERATOR MATCHES "Xcode") + # General deps + # Networking / async + set_target_folder(asio deps) + + # Text / parsing + set_target_folder(ctre deps) + set_target_folder(fmt deps) + set_target_folder(utf8cpp deps) + + # Math / geometry + set_target_folder(earcut deps) + set_target_folder(glm deps) + + # Graphics / windowing + set_target_folder(glad deps) + set_target_folder(imgui deps) + set_target_folder(imgui_backend deps) + set_target_folder(implot deps) + set_target_folder(sokol deps) + set_target_folder(stb deps) + + # Audio + set_target_folder(miniaudio deps) + + # Map / geo + set_target_folder(protozero deps) + set_target_folder(mvt deps) + + # Data / storage + set_target_folder(sqlite3 deps) + set_target_folder(zlib deps) + set_target_folder(zlibstatic deps) + + # Logging + set_target_folder(spdlog deps) + + # 3D assets + set_target_folder(tinyobjloader deps/tinyobj) + + # GLFW + set_target_folder(glfw deps/GLFW) + set_target_folder(update_mappings deps/GLFW) + + # GTest + set_target_folder(gtest deps/gtest) + set_target_folder(gtest_main deps/gtest) + set_target_folder(gmock deps/gtest) + set_target_folder(gmock_main deps/gtest) + + # Hide uninstall target + if (TARGET uninstall) + set_target_properties(uninstall PROPERTIES FOLDER deps/tinyobj) + set_target_properties(uninstall PROPERTIES EXCLUDE_FROM_ALL TRUE) + endif() +endif() diff --git a/deps/Platform.cmake b/deps/Platform.cmake new file mode 100644 index 0000000..6326538 --- /dev/null +++ b/deps/Platform.cmake @@ -0,0 +1,64 @@ +# ============================================================================== +# Platform Detection +# ============================================================================== +# This module detects the current platform and compiler, setting IS_* variables +# that can be used throughout the build system for conditional logic. +# +# Compiler flags set: +# IS_CLANG_OR_GCC - TRUE if using Clang or GCC compiler +# IS_MSVC - TRUE if using Microsoft Visual C++ compiler +# +# Platform flags set: +# IS_WINDOWS - TRUE if building for Windows +# IS_LINUX - TRUE if building for Linux +# IS_MACOS - TRUE if building for macOS +# IS_IOS - TRUE if building for iOS +# IS_ANDROID - TRUE if building for Android +# IS_EMSCRIPTEN - TRUE if building for WebAssembly via Emscripten +# ============================================================================== + +# ------------------------------------------------------------------------------ +# Compiler Detection +# ------------------------------------------------------------------------------ +set(IS_CLANG_OR_GCC FALSE) +set(IS_MSVC FALSE) + +if(MSVC) + set(IS_MSVC TRUE) +elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") + set(IS_CLANG_OR_GCC TRUE) +endif() + +# ------------------------------------------------------------------------------ +# Platform Detection +# ------------------------------------------------------------------------------ +set(IS_WINDOWS FALSE) +set(IS_LINUX FALSE) +set(IS_MACOS FALSE) +set(IS_IOS FALSE) +set(IS_ANDROID FALSE) +set(IS_EMSCRIPTEN FALSE) + +if(EMSCRIPTEN) + message(STATUS "Platform: Emscripten") + set(IS_EMSCRIPTEN TRUE) +elseif(ANDROID) + message(STATUS "Platform: Android") + set(IS_ANDROID TRUE) +elseif(APPLE) + if(IOS) + message(STATUS "Platform: iOS") + set(IS_IOS TRUE) + else() + message(STATUS "Platform: macOS") + set(IS_MACOS TRUE) + endif() +elseif(WIN32) + message(STATUS "Platform: Windows") + set(IS_WINDOWS TRUE) +elseif(UNIX) + message(STATUS "Platform: Linux") + set(IS_LINUX TRUE) +else() + message(FATAL_ERROR "Unknown platform!") +endif() diff --git a/deps/Sanitizers.cmake b/deps/Sanitizers.cmake new file mode 100644 index 0000000..d793dcd --- /dev/null +++ b/deps/Sanitizers.cmake @@ -0,0 +1,28 @@ +# ============================================================================== +# Sanitizers +# ============================================================================== +# AddressSanitizer (ASan) support. +# Works with GCC/Clang on Linux and macOS, Clang on Windows (requires +# compiler-rt with sanitizers), and MSVC on Windows (/fsanitize=address). +# +# Usage: cmake -DENABLE_ASAN=ON ... +# ============================================================================== + +option(ENABLE_ASAN "Build with AddressSanitizer" OFF) + +if (ENABLE_ASAN) + if (ENABLE_COVERAGE) + message(FATAL_ERROR "ENABLE_ASAN and ENABLE_COVERAGE cannot be used together") + endif() + + if (MSVC) + add_compile_options(/fsanitize=address) + message(STATUS "ASan: enabled (MSVC)") + elseif (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + add_compile_options(-fsanitize=address -fno-omit-frame-pointer) + add_link_options(-fsanitize=address) + message(STATUS "ASan: enabled (${CMAKE_C_COMPILER_ID})") + else() + message(FATAL_ERROR "ENABLE_ASAN: unsupported compiler ${CMAKE_C_COMPILER_ID}") + endif() +endif() diff --git a/hello.cpp b/hello.cpp new file mode 100644 index 0000000..04c3d51 --- /dev/null +++ b/hello.cpp @@ -0,0 +1,6 @@ +#include "fmt/std.h" + +auto main([[maybe_unused]]int argc, [[maybe_unused]]char const* argv[]) -> int { + fmt::println("Hello, World!"); + return 0; +}