# cmgraph — C++20 core + pybind11 extension module.
# Layout and commands: PLAN.md §7–§8.
cmake_minimum_required(VERSION 3.22)
# The project() VERSION below is a DEV FALLBACK only (used by standalone CMake/ctest
# builds). The single source of truth for the package version is pyproject.toml; under a
# `pip install`/sdist build scikit-build-core injects it as SKBUILD_PROJECT_VERSION, which
# takes precedence when defining CMGRAPH_VERSION for the module (see below). Keep this
# number in sync with pyproject.toml so a standalone dev build reports the same version.
project(cmgraph VERSION 0.0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# C++ unit tests must NOT build during `pip install .` — dev-only, opt-in via ctest.
option(CMGRAPH_BUILD_TESTS "Build C++ unit tests and register them with ctest" OFF)

find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)

# T14 deterministic parallel cell-map build uses std::thread (STL only). Some Linux
# toolchains require -pthread to link/run threaded code; prefer the pthread flag and link
# the imported Threads::Threads target on every C++ target that compiles the core headers.
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

# Standalone configure (outside scikit-build-core): locate pybind11's CMake config
# through the active Python interpreter, so the PLAN.md §8 command works as written.
if(NOT DEFINED pybind11_DIR)
  execute_process(
    COMMAND "${Python_EXECUTABLE}" -m pybind11 --cmakedir
    OUTPUT_VARIABLE _cmgraph_pybind11_cmakedir
    OUTPUT_STRIP_TRAILING_WHITESPACE
    ERROR_QUIET)
  if(_cmgraph_pybind11_cmakedir)
    set(pybind11_DIR "${_cmgraph_pybind11_cmakedir}")
  endif()
endif()
find_package(pybind11 CONFIG REQUIRED)

# The compiled core: cmgraph._core (the full T2–T9 pipeline surface).
pybind11_add_module(_core src/bindings.cpp)
target_include_directories(_core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(_core PRIVATE Threads::Threads)

# MSVC portability: the template-heavy homology/index-map translation unit can exceed the
# COFF object-file section limit (C1128) — /bigobj lifts it; and std::getenv
# (CMGRAPH_NUM_THREADS) trips the C4996 deprecation warning (build has no /WX, so it is
# warning-only) — silence it. No-ops on GCC/Clang.
if(MSVC)
  target_compile_options(_core PRIVATE /bigobj)
  target_compile_definitions(_core PRIVATE _CRT_SECURE_NO_WARNINGS)
endif()

# Single-source the runtime __version__ from pyproject.toml. scikit-build-core resolves
# the pyproject version and passes it as SKBUILD_PROJECT_VERSION at configure time; a
# standalone CMake build falls back to the project() VERSION (the dev placeholder above).
# bindings.cpp reads the CMGRAPH_VERSION macro — there is no hardcoded version in C++.
if(DEFINED SKBUILD_PROJECT_VERSION)
  set(_cmgraph_version "${SKBUILD_PROJECT_VERSION}")
else()
  set(_cmgraph_version "${PROJECT_VERSION}")
endif()
target_compile_definitions(_core PRIVATE "CMGRAPH_VERSION=\"${_cmgraph_version}\"")

install(TARGETS _core DESTINATION cmgraph)

if(CMGRAPH_BUILD_TESTS)
  enable_testing()
  add_subdirectory(tests/cpp)
  # Geometry/topology isolation rule (PLAN.md §3, design 01 §2.8) — mechanical
  # include-graph lint, wired into ctest so CI fails on any violating edge.
  add_test(
    NAME isolation_lint
    COMMAND "${Python_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/check_isolation.py"
    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
