feat: add OpenGL abstraction layer with RAII resources

- Replace window class with cbt::opengl::context
- Add buffer resource (VBO, EBO, UBO, SSBO) with move semantics
- Add texture resource with format/type enums and filtering
- Add descriptor_set for Vulkan-style resource binding
- All resources use RAII with proper cleanup
This commit is contained in:
2026-05-05 21:58:34 +02:00
parent f18e5e4adc
commit 90d013695d
36 changed files with 2139 additions and 55 deletions
+84
View File
@@ -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
)
+104
View File
@@ -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(<out_inc> <out_lib> <out_ver>)
#
# 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/<latest> (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)
+79
View File
@@ -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")
+57
View File
@@ -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")
+75
View File
@@ -0,0 +1,75 @@
# ==============================================================================
# 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)
find_program(GIT_EXECUTABLE git)
if (GIT_EXECUTABLE)
set(GLM_FETCH_METHOD "GIT")
else()
message(FATAL_ERROR "Fetch with zip not supported.")
endif()
set(_glm_warn_deprecated "${CMAKE_WARN_DEPRECATED}")
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Suppress deprecated warnings while fetching glm" FORCE)
if (GLM_FETCH_METHOD STREQUAL "GIT")
FetchContent_Declare(
glm
GIT_REPOSITORY https://github.com/g-truc/glm.git
GIT_TAG ${GLM_VERSION}
)
endif()
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")
+93
View File
@@ -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}")
+59
View File
@@ -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")
+47
View File
@@ -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")
+52
View File
@@ -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")
+52
View File
@@ -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")
+105
View File
@@ -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")
+63
View File
@@ -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")
+62
View File
@@ -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")
+57
View File
@@ -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")
+56
View File
@@ -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")
+76
View File
@@ -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")
+46
View File
@@ -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}")
+75
View File
@@ -0,0 +1,75 @@
# ==============================================================================
# Find stb
# ==============================================================================
# This module fetches the stb single-file public domain libraries.
#
# Targets provided:
# stb::stb - The stb library target
#
# Variables set:
# stb_FOUND - TRUE if stb is available
# stb_LIBRARIES - The stb library target (stb::stb)
# stb_INCLUDE_DIR - Include directories for stb
# stb_VERSION - Version of stb (commit-based)
#
# Usage notes:
# stb headers are header-only but require an implementation macro to be
# defined in exactly ONE translation unit (.cpp file) before including the
# header, e.g.:
#
# #define STB_IMAGE_IMPLEMENTATION
# #include <stb_image.h>
#
# Each stb header has its own implementation macro. Do NOT define the macro
# in header files or in more than one translation unit or you will get
# duplicate symbol linker errors.
# ==============================================================================
if (DEFINED _FINDSTB_INCLUDED)
return()
endif()
set(_FINDSTB_INCLUDED TRUE)
# Use the version passed to find_package(), or default to 2.30
if (DEFINED stb_FIND_VERSION AND NOT stb_FIND_VERSION STREQUAL "")
set(STB_VERSION "${stb_FIND_VERSION}")
else()
set(STB_VERSION "2fb8c5a3deb2110c89669f8d6f36e5833b556b44")
endif()
message(STATUS "Fetching stb ${STB_VERSION}")
include(FetchContent)
find_program(GIT_EXECUTABLE git)
if (GIT_EXECUTABLE)
set(STB_FETCH_METHOD "GIT")
else()
message(FATAL_ERROR "Fetch with zip not supported.")
endif()
if (STB_FETCH_METHOD STREQUAL "GIT")
FetchContent_Declare(
stb
GIT_REPOSITORY https://github.com/nothings/stb.git
GIT_TAG ${STB_VERSION}
)
endif()
FetchContent_MakeAvailable(stb)
if (NOT TARGET stb)
add_library(stb INTERFACE)
target_include_directories(stb SYSTEM INTERFACE "${stb_SOURCE_DIR}")
endif()
if (NOT TARGET stb::stb)
add_library(stb::stb ALIAS stb)
endif()
set(stb_FOUND TRUE)
set(stb_LIBRARIES stb::stb)
set(stb_VERSION "${STB_VERSION}")
set(stb_INCLUDE_DIR "${stb_SOURCE_DIR}")
set(STB_LICENSE_FILE "${stb_SOURCE_DIR}/LICENSE" CACHE FILEPATH "Path to stb license file")
+70
View File
@@ -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")
+75
View File
@@ -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")
+53
View File
@@ -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")
+162
View File
@@ -0,0 +1,162 @@
# ==============================================================================
# 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(<out_var>)
#
# 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(<OUT_VAR> <LIB_NAME> <DISPLAY_NAME>)
#
# 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(<OUT_VAR> <FRAMEWORK_NAME> <DISPLAY_NAME>)
#
# Searches for an Apple framework and, if found, appends -framework <name> 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(FATAL_ERROR "macOS not supported!")
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)
# add_compile_definitions("ImDrawIdx=unsigned int")
add_compile_options(
"-fexceptions"
)
add_link_options(
# "-pthread"
"-fexceptions"
# "-sUSE_PTHREADS=1"
# "-sALLOW_MEMORY_GROWTH=1"
# "-sINITIAL_MEMORY=67108864"
"-sFETCH=1"
# Graphics
"-sUSE_GLFW=3"
# "--use-port=emdawnwebgpu"
"-sUSE_WEBGL2=1"
"-sFULL_ES3=1"
# "-sSTACK_SIZE=1048576"
# Safari Pointer Lock API polyfill
"--pre-js=${CMAKE_SOURCE_DIR}/res/pre.js"
)
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"
)
elseif (IS_EMSCRIPTEN)
set(BASE_DEFINITIONS
${BASE_DEFINITIONS}
"ASIO_DISABLE_THREADS"
)
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()
+82
View File
@@ -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()
+64
View File
@@ -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()