This commit closes the structural-tests work on PR #18. Every gate in `run-all.sh --fast` now passes end-to-end on the canonical dev machine. New gates ───────── 1. shellcheck (scripts/quality/shellcheck.sh) * Scans every `scripts/**/*.sh` at severity=warning+ * 16 scripts inspected; cleanup pass took the tree from 7 findings (SC2164 + SC2034) to 0 findings. 2. cppcheck (scripts/quality/cppcheck.sh) * Complementary static analyser to clang-tidy; different heuristics, fewer false-positives on heavy CGAL/Eigen templates. * Default severity warning+, --strict adds style, --all = everything. * Suppresses 4 noise classes (missingIncludeSystem, etc.) explicitly. 3. .editorconfig * Cross-IDE fallback for editors that don't honour clang-format. * Covers Markdown (preserve trailing whitespace), Python, YAML, JSON, shell, Makefile (tabs) — the file types clang-format doesn't cover. 4. CONFORMALLAB_WARNINGS_AS_ERRORS CMake option * Off by default → regular builds don't break on new GCC warnings. * `-DCONFORMALLAB_WARNINGS_AS_ERRORS=ON` adds `-Werror`, intended for CI promotion-track and sanitizer runs. Dependency audit (doc/architecture/dependencies.md) ──────────────────────────────────────────────────── New single-source-of-truth document listing: * what the library requires (Eigen + CGAL + Boost — all header-only) * what tests require (auto-fetched GTest, no system install) * what each quality tool is for, install command per OS, and behaviour when missing (each gate exits 2 = SKIP, run-all recognises this and continues) * a verification recipe that strips PATH down and shows the library still configures + builds + tests cleanly with zero quality tools installed. run-all.sh enhanced ─────────────────── * Recognises "tool not in PATH" → SKIP (not FAIL). * Summary now reports `passed / skipped / failed` separately. Bug fixes uncovered by the sweep ──────────────────────────────── * sanitizers.sh: gtest_discover_tests ran the ASan-instrumented binary at build time and aborted → added `-DCMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE=PRE_TEST` to defer discovery to ctest invocation. Now 23/23 sanitizer-instrumented tests pass. * clang-tidy.sh on macOS: brew-installed clang-tidy couldn't find Apple SDK system headers (<cmath>, <complex>, …) → added `--extra-arg=-isysroot $(xcrun --show-sdk-path)` on Darwin. * clang-tidy.sh: needed `-DWITH_CGAL_TESTS=ON` in compile_commands generation so CGAL include paths are part of at least one compile entry. Now resolves CGAL/Surface_mesh.h etc. * clang-tidy.sh: viewer-only headers (`viewer_utils.h`, `mesh_utils.hpp`) excluded — they need `WITH_VIEWER=ON` + system GLFW/libigl that the lint build doesn't drag in. * `.codespellrc`: extended ignore list (recognise, signalled, modelled, travelled, …) for British-English consistency across own writing. Final state — local quality block on this commit, this branch: ✅ License headers (66/66 carry MIT SPDX) ✅ CGAL conventions (0/6 violations on 6 CGAL headers) ✅ clang-format drift (0 drift) ✅ cmake-format/-lint (0 drift, 0 lint findings) ✅ codespell (0 typos in scope) ✅ shellcheck (0 findings across 16 .sh files) ✅ cppcheck (warning+ severity clean) ✅ Markdown links (122/122 resolve) ✅ Sanitizers (ASan+UBSan) (23/23 fast tests pass) ✅ clang-tidy (35 headers inspected, 0 findings) Library standalone-ness verified: env -i PATH=... cmake -S code -B /tmp/build-standalone cmake --build /tmp/build-standalone --target conformallab_tests ctest -E '^cgal\.' → all green Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
183 lines
8.4 KiB
CMake
183 lines
8.4 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
||
|
||
set(PROJECT_NAME "conformallab_core")
|
||
project(${PROJECT_NAME} LANGUAGES C CXX)
|
||
|
||
message(STATUS "Configuring ${PROJECT_NAME}...")
|
||
|
||
# ── Build modes ────────────────────────────────────────────────────────────────
|
||
#
|
||
# Default (CI fast / pure-math tests):
|
||
# cmake -S code -B build
|
||
# Only Eigen + GTest required. 36 non-CGAL tests.
|
||
#
|
||
# -DWITH_CGAL_TESTS=ON CGAL test suite only — no viewer, no CLI app.
|
||
# cmake -S code -B build -DWITH_CGAL_TESTS=ON
|
||
# Requires: system Boost headers (apt install libboost-dev).
|
||
# Builds: conformallab_cgal_tests (158 tests).
|
||
# Does NOT require wayland-scanner, GLFW, libigl or a display.
|
||
# Use this in headless CI.
|
||
#
|
||
# -DWITH_CGAL=ON Full build: CLI app + viewer + examples + CGAL tests.
|
||
# cmake -S code -B build -DWITH_CGAL=ON
|
||
# Requires: Boost + Wayland/X11 dev headers (wayland-scanner, libx11-dev …).
|
||
# Automatically enables WITH_VIEWER.
|
||
# Use this for local development with the interactive viewer.
|
||
#
|
||
# -DWITH_VIEWER=ON Viewer library only (libigl / GLFW / GLAD).
|
||
#
|
||
# ──────────────────────────────────────────────────────────────────────────────
|
||
option(WITH_CGAL_TESTS "Build CGAL test suite without viewer/CLI (headless CI)" OFF)
|
||
option(WITH_CGAL "Build conformallab_core CLI app + viewer + CGAL tests" OFF)
|
||
option(WITH_VIEWER "Build viewer library (libigl / GLFW / GLAD)" OFF)
|
||
|
||
# WITH_CGAL_TESTS is a strict subset of WITH_CGAL — no viewer, no CLI.
|
||
# WITH_CGAL (full build) implies WITH_VIEWER.
|
||
if(WITH_CGAL AND NOT WITH_VIEWER)
|
||
message(STATUS "WITH_CGAL implies WITH_VIEWER – enabling automatically.")
|
||
set(WITH_VIEWER ON CACHE BOOL "" FORCE)
|
||
endif()
|
||
|
||
# Propagate Boost requirement for both CGAL modes.
|
||
if(WITH_CGAL OR WITH_CGAL_TESTS)
|
||
find_package(Boost REQUIRED)
|
||
endif()
|
||
|
||
# ── Standard settings ──────────────────────────────────────────────────────────
|
||
set(CMAKE_CXX_STANDARD 17)
|
||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||
|
||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||
|
||
if(NOT CMAKE_BUILD_TYPE)
|
||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
|
||
endif()
|
||
|
||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
||
# ─── Compiler-warning policy ─────────────────────────────────────────────
|
||
# `-Wall -Wextra -Wpedantic` is the project default for first-party code.
|
||
# Vendored deps under code/deps/ get a separate, looser policy (handled
|
||
# via per-target SYSTEM include marking when they are pulled in).
|
||
#
|
||
# `CONFORMALLAB_WARNINGS_AS_ERRORS=ON` flips on `-Werror` — used in CI's
|
||
# promotion-track and by `scripts/quality/sanitizers.sh` to make sure no
|
||
# new warning class slips in unannounced. Off by default so regular
|
||
# builds on slightly older toolchains aren't broken by a new GCC's
|
||
# added warning.
|
||
option(CONFORMALLAB_WARNINGS_AS_ERRORS
|
||
"Treat compiler warnings as errors (-Werror)." OFF)
|
||
|
||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||
|
||
if(CONFORMALLAB_WARNINGS_AS_ERRORS)
|
||
add_compile_options(-Werror)
|
||
message(STATUS "Warnings-as-errors mode active (-Werror).")
|
||
endif()
|
||
|
||
# AddressSanitizer only in Debug (gtest_discover_tests runs the binary at
|
||
# configure time and hangs with ASan enabled).
|
||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT BUILD_TESTING)
|
||
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
|
||
add_link_options(-fsanitize=address)
|
||
endif()
|
||
endif()
|
||
|
||
# ── GTest (always – tests are always built) ────────────────────────────────────
|
||
include(FetchContent)
|
||
include(CTest)
|
||
enable_testing()
|
||
|
||
FetchContent_Declare(
|
||
googletest
|
||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||
GIT_TAG v1.14.0
|
||
)
|
||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||
set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
|
||
set(BUILD_GMOCK OFF CACHE BOOL "" FORCE)
|
||
FetchContent_MakeAvailable(googletest)
|
||
|
||
# ── External deps (lazy tarball extraction) ────────────────────────────────────
|
||
add_subdirectory(deps)
|
||
|
||
# ── Viewer library (optional) ──────────────────────────────────────────────────
|
||
if(WITH_VIEWER)
|
||
add_subdirectory(deps/glfw-3.4)
|
||
|
||
add_library(glad STATIC
|
||
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-glad/src/glad.c)
|
||
target_include_directories(glad PUBLIC
|
||
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-glad/include)
|
||
|
||
add_library(viewer STATIC src/viewer/simple_viewer.cpp)
|
||
target_include_directories(viewer PUBLIC
|
||
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-2.6.0/include
|
||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-glad/include
|
||
${CMAKE_CURRENT_SOURCE_DIR}/deps/eigen-3.4.0/)
|
||
target_link_libraries(viewer PUBLIC glad glfw)
|
||
endif()
|
||
|
||
# ── Core CLI app (optional, requires CGAL + Viewer) ───────────────────────────
|
||
if(WITH_CGAL)
|
||
add_executable(${PROJECT_NAME} src/apps/v0/conformallab_cli.cpp)
|
||
target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE
|
||
${CMAKE_CURRENT_SOURCE_DIR}/deps/single_includes
|
||
${CMAKE_CURRENT_SOURCE_DIR}/deps/eigen-3.4.0/
|
||
${CMAKE_CURRENT_SOURCE_DIR}/deps/CGAL-6.1.1/include
|
||
${CMAKE_CURRENT_SOURCE_DIR}/deps/libigl-2.6.0/include
|
||
${Boost_INCLUDE_DIRS})
|
||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||
CGAL_DISABLE_GMP CGAL_DISABLE_MPFR)
|
||
target_link_libraries(${PROJECT_NAME} PRIVATE viewer)
|
||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
|
||
endif()
|
||
|
||
# ── Example programs (require WITH_CGAL; viewer example also needs WITH_VIEWER) ─
|
||
if(WITH_CGAL)
|
||
add_subdirectory(examples)
|
||
endif()
|
||
|
||
# ── Tests (always) ────────────────────────────────────────────────────────────
|
||
add_subdirectory(tests)
|
||
|
||
# ── Install target (header-only library) ──────────────────────────────────────
|
||
# Installs all public headers to <prefix>/include/conformallab/
|
||
# Usage from another CMake project:
|
||
# cmake --install build --prefix /usr/local
|
||
# target_include_directories(myapp PRIVATE /usr/local/include/conformallab)
|
||
include(GNUInstallDirs)
|
||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
|
||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/conformallab
|
||
FILES_MATCHING PATTERN "*.hpp"
|
||
PATTERN "* 2.*" EXCLUDE) # exclude macOS Finder duplicates
|
||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE
|
||
${CMAKE_CURRENT_SOURCE_DIR}/../CITATION.cff
|
||
DESTINATION ${CMAKE_INSTALL_DATADIR}/conformallab)
|
||
|
||
# ── Doxygen documentation target (Phase 7.5) ──────────────────────────────────
|
||
# Generates HTML API documentation into doc/doxygen/html/.
|
||
# Usage:
|
||
# cmake --build build --target doc
|
||
# open doc/doxygen/html/index.html
|
||
#
|
||
# Optional dependency: install Doxygen via `brew install doxygen` (macOS) or
|
||
# `apt install doxygen graphviz` (Linux). The target is silently disabled
|
||
# if Doxygen is not found.
|
||
find_package(Doxygen QUIET)
|
||
if(DOXYGEN_FOUND)
|
||
set(DOXYGEN_PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||
add_custom_target(doc
|
||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_PROJECT_ROOT}/Doxyfile
|
||
WORKING_DIRECTORY ${DOXYGEN_PROJECT_ROOT}
|
||
COMMENT "Generating API documentation with Doxygen"
|
||
VERBATIM)
|
||
message(STATUS "Doxygen found: target 'doc' available (cmake --build build --target doc)")
|
||
else()
|
||
message(STATUS "Doxygen not found — 'doc' target unavailable (install: brew/apt install doxygen)")
|
||
endif()
|