cmake_minimum_required(VERSION 3.26)
project(focal LANGUAGES CXX VERSION 0.0.1)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)   # for clangd / IDE tooling

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()

# The C++ library.  Globbed with CONFIGURE_DEPENDS so new files under src/
# get picked up without editing this file.
file(GLOB_RECURSE FOCAL_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
add_library(focal_core STATIC ${FOCAL_SOURCES})
target_include_directories(focal_core PUBLIC
  "${CMAKE_CURRENT_SOURCE_DIR}/include"
  "${CMAKE_CURRENT_SOURCE_DIR}/third_party")
target_compile_options(focal_core PRIVATE
  $<$<CXX_COMPILER_ID:AppleClang,Clang,GNU>:-Wall -Wextra>)

if(MSVC)
  # windows.h (pulled in by stb under STBI_WINDOWS_UTF8) defines min/max as
  # macros, which breaks std::min and std::max at every call site.  stb also
  # uses fopen/sprintf, which MSVC flags as deprecated.
  target_compile_definitions(focal_core PRIVATE NOMINMAX _CRT_SECURE_NO_WARNINGS)
endif()

# The Python extension module.
# Development.SABIModule is what nanobind links against for STABLE_ABI below;
# without it the STABLE_ABI flag is silently ignored and you get one wheel per
# Python version instead of one per platform.
find_package(Python 3.12 REQUIRED
             COMPONENTS Interpreter Development.Module Development.SABIModule)

execute_process(
  COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
  OUTPUT_VARIABLE NANOBIND_CMAKE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE
  COMMAND_ERROR_IS_FATAL ANY)
list(APPEND CMAKE_PREFIX_PATH "${NANOBIND_CMAKE_DIR}")
find_package(nanobind CONFIG REQUIRED)

file(GLOB_RECURSE FOCAL_BINDINGS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/python/*.cpp")
nanobind_add_module(_focal STABLE_ABI NB_STATIC ${FOCAL_BINDINGS})
target_link_libraries(_focal PRIVATE focal_core)

install(TARGETS _focal LIBRARY DESTINATION focal)
