Skip to content

feat: 全面规范化升级 — CMake 现代化、Doxygen 文档、CI 跨平台、代码质量工具 - #1

Merged
Mr-tooth merged 21 commits into
mainfrom
feature/modernize
Mar 15, 2026
Merged

feat: 全面规范化升级 — CMake 现代化、Doxygen 文档、CI 跨平台、代码质量工具#1
Mr-tooth merged 21 commits into
mainfrom
feature/modernize

Conversation

@Mr-tooth

Copy link
Copy Markdown
Member

📋 概述

将 Heuclid 代码库从个人项目升级为符合国际开源标准的专业 C++ 库。对标 pinocchio + jrl-cmakemodules 的成熟模式。

🔄 主要变更

CMake 现代化

  • 引入 jrl-cmakemodules(三重查找:submodule → system → FetchContent)
  • cmake_minimum_required(VERSION 3.0) 升级到 3.22
  • Header-only INTERFACE 库架构(适配大量模板类)
  • 跨平台支持:移除 GCC/MSVC 硬编码,使用 CMake 标准机制
  • setup_project_finalize() 集成(Doxyfile 自动生成、pkg-config、export)

Eigen3 依赖管理

  • 版本锁定到 3.4.0(不再用 master 分支)
  • FetchContent fallback:无系统 Eigen3 时自动下载
  • IMPORTED INTERFACE target 避免 CMake export 冲突
  • 避免 add_subdirectory(不触发 Eigen3 的 uninstall target 冲突)

Doxygen 文档

  • 全部 20 个头文件添加 @file + 类/方法级 Doxygen 注释
  • jrl-cmakemodules 自动生成 Doxyfile(doc/Doxyfile.extra.in 追加定制)
  • CI 独立 docs job(Ubuntu-only,安装 Doxygen + Graphviz)
  • MathJax 3 支持数学公式渲染

双语 README

  • README.md(英文)+ README_zh.md(中文)
  • Features、Quick Start、Installation、API Reference、Contributing
  • License + CI badges

代码质量工具

  • .clang-format 统一代码风格
  • CONTRIBUTING.md 贡献指南
  • GitHub Actions CI(Ubuntu + macOS + Windows)

Bug 修复

  • Vector3D::operator== 参数类型错误(Vector2DVector3D
  • ConvexHull2D 迭代器非 const 左值引用绑定右值
  • C++14 auto 返回类型 → C++11 显式类型

✅ CI 状态

Platform Build Tests Doxygen
Ubuntu
macOS
Windows

📊 变更统计

  • 31 files changed, 978 insertions(+), 326 deletions(-)
  • 21 commits on feature/modernize

🔗 关联资源

Mr-tooth added 21 commits March 15, 2026 17:16
- Rewrite CMakeLists.txt using jrl-cmakemodules (FetchContent/submodule/system)
- Convert library to INTERFACE (header-only) target
- Set minimum C++ standard to C++11
- Rewrite test CMakeLists.txt with cross-platform GoogleTest via FetchContent
- Replace legacy HeuclidConfig.cmake with modern CMakePackageConfigHelpers
- Fix ConvexHull2D.h iterator binding error (auto& → auto for rvalue iterators)
- Update .gitignore for build/IDE/Doxygen artifacts
- Verified on Linux GCC 13.3: cmake configure + build + all tests pass
- Add @file, @brief, @author doxygen headers to all 20 header files
- Fully document Point2D.h: class, all public methods, operators, params
- Group related methods with @name/@brief doxygen blocks
- All tests still pass (verified)
- Rewrite README.md (English) with badges, features, quick start, structure
- Add README_zh.md (Chinese) matching English README structure
- Add .github/workflows/ci.yml for Linux GCC/Clang, macOS Clang, MSVC
- Add .clang-format (Google-based, 120 col, C++11)
- Add CONTRIBUTING.md with dev setup and PR guidelines
- Vector2D.h: full Doxygen (class, constructors, getters/setters)
- UnitVector2D.h: full Doxygen with lazy normalization explanation
- Vector3D.h: full Doxygen + fix operator== comparing wrong type (Vector2D→Vector3D)
- Point3D.h: add Doxygen class doc, method groups, @param/@return
- ConvexPolygon2D.h, Line2D.h: add @brief class documentation
- HeuclidCoreTool.h: add @brief struct documentation
- Orientation2D.h: add @brief class documentation
- ZeroTestEpsilon.h: add @brief macro documentation
- All tests pass (verified)
- Quaternion.h: enhance class documentation with formula and conventions
- Pose2D.h: add @brief class documentation
- Pose3D.h: add @brief to existing documentation
- All tests pass (verified)
…mpat

- ConvexHull2D.h: replace 5 auto& getters with explicit const ref types
- Add @brief Doxygen documentation to the getters
- All tests pass (verified)
- Add vcpkg install eigen3:x64-windows step for Windows
- Pass CMAKE_TOOLCHAIN_FILE pointing to vcpkg on Windows
- Windows CI was failing because Eigen3 was not installed
- HeuclidGeometryTools.h: add @brief class documentation
- HeuclidPolygonTools.h: replace Javadoc-style with Doxygen @brief
- UnitVector3D.h: replace Javadoc-style with Doxygen @brief class doc
- QuaternionTool.h: add @name group, @param, @brief to all multiply functions
- All tests pass (verified)
- Add @brief to calculateHalfspaceForm, loadRectangleVertex, loadVertex
- All tests pass (verified)
- CMakeLists.txt: replace add_project_dependency with find_package +
  FetchContent fallback for Eigen3 (gitlab.com/libeigen/eigen)
- Simplify CI: remove platform-specific Eigen install steps, CMake
  auto-fetches Eigen when not found locally
- Fixes Windows CI where Eigen3 was not installed correctly via vcpkg
- All tests pass locally (verified)
…makemodules

- Use FetchContent_Populate instead of FetchContent_MakeAvailable for Eigen3
- Create INTERFACE target manually (Eigen is header-only only need headers)
- Avoids 'uninstall' target collision between Eigen and jrl-cmakemodules
- Simplify CI to 3 platforms using default compilers
- All tests pass locally (verified)
- Create heuclid_Eigen3 (not Eigen3::Eigen) for FetchContent case
- Use _HEUCLID_EIGEN_TARGET variable in target_link_libraries
- Eigen dependency only at build time, consumers via find_dependency
- Fixes 'target not in export set' CMake error on CI
…rt error

Root cause: target_link_libraries(heuclid INTERFACE eigen_target) propagates
Eigen into the export set, causing 'target not in any export set' error.

Fix:
- Fetch Eigen master branch (3.4.0 lacks FetchContent CMake support)
- Use target_include_directories with $<BUILD_INTERFACE> for Eigen headers
- Remove target_link_libraries for Eigen (no dependency propagation)
- Consumers get Eigen via find_dependency(Eigen3) in Config.cmake
- CI needs no platform-specific Eigen install steps
Windows CI has no Doxygen installed, but jrl-cmakemodules auto-creates
heuclid-doc target that fails. Set BUILD_DOCUMENTATION=OFF and
INSTALL_DOCUMENTATION=OFF before base.cmake include.
- Move BUILD_DOCUMENTATION option before base.cmake include (jrl-cmakemodules requirement)
- Add explicit -DBUILD_DOCUMENTATION=OFF to build matrix jobs (safety net)
- Add independent 'docs' job: Ubuntu-latest only, installs Doxygen + graphviz, builds heuclid-doc
- Add doc/Doxyfile.in template for Doxygen configuration
- BUILD_DOCUMENTATION defaults to ON (for local dev with Doxygen installed)
…odules integration

ROOT CAUSE: PROJECT_AUTO_RUN_FINALIZE=FALSE but setup_project_finalize()
was never called, so _SETUP_PROJECT_DOCUMENTATION_FINALIZE() never ran
and the Doxyfile was never generated.

Changes:
- Add setup_project_finalize() at end of CMakeLists.txt
- Fix export name: heuclid-targets → heuclidTargets (jrl convention)
- Remove manual Config.cmake install (handled by jrl package-config.cmake)
- Replace doc/Doxyfile.in (wrong format) with doc/Doxyfile.extra.in
- Set DOXYGEN_FILE_PATTERNS='*.h' and DOXYGEN_HTML_OUTPUT='doxygen-html'
- Update CI doc check path to build/doc/doxygen-html

Verified locally:
- cmake configure: ✅ (with proxy for FetchContent)
- heuclid-doc target: ✅ (160 HTML files generated)
- ctest: ✅ (2/2 tests passed)
Changes:
- FetchContent_Populate (deprecated) → FetchContent_MakeAvailable
- Eigen3 master branch → locked to 3.4.0 (reproducible builds)
- Manual get_target_property extract → target_link_libraries(Eigen3::Eigen)
- Remove manual BUILD_INTERFACE include dir hack
- Add add_project_dependency(Eigen3) for generated Config.cmake
- Remove cmake/Config.cmake.in (handled by jrl-cmakemodules)

Verified locally:
- Eigen3 found: 3.4.0 (system)
- Build: ✅
- Tests: 2/2 passed
- Doxygen: ✅
FetchContent_MakeAvailable(eigen3) runs add_subdirectory which creates
an 'uninstall' target that conflicts with jrl-cmakemodules' 'uninstall'.

Fix: set EIGEN_BUILD_UNINSTALL/OFF, EIGEN_BUILD_DOC/OFF,
EIGEN_BUILD_TESTING/OFF before FetchContent_MakeAvailable.
Eigen3 is header-only. Instead of add_subdirectory (which creates
conflicting 'uninstall' target), just populate and create an INTERFACE
library with the include directory.

- FetchContent_Populate to get source dir (no add_subdirectory)
- Create Eigen3_Eigen INTERFACE library manually
- Alias as Eigen3::Eigen for compatibility
- Set Eigen3_FOUND=TRUE so add_project_dependency works

Also fixes the deprecated FetchContent_Populate warning by noting
that MakeAvailable isn't used here intentionally (avoids target conflict).
…tent

add_project_dependency(Eigen3) calls find_package(Eigen3) internally,
which fails on systems without Eigen3 installed (CI Windows/macOS).
Skip it when Eigen3 was fetched (not found via find_package).
… error

Root cause: manually created Eigen3_Eigen (non-imported) caused
CMake export to fail with 'target not in any export set' because
heuclid links to it via target_link_libraries.

Fix: create Eigen3::Eigen as INTERFACE IMPORTED target.
CMake's export mechanism skips imported targets, so no conflict.

This is the same pattern used by find_package(Eigen3) which also
creates an IMPORTED target.
@Mr-tooth
Mr-tooth merged commit 8e1931c into main Mar 15, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant