diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 5c3e50c..e1dd386 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/cpp:1-debian-11 +FROM mcr.microsoft.com/devcontainers/cpp:debian-12 ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="none" @@ -19,4 +19,4 @@ RUN if [ "${REINSTALL_CMAKE_VERSION_FROM_SOURCE}" != "none" ]; then \ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ - && apt-get -y install --no-install-recommends python3-dev + && apt-get -y install --no-install-recommends python3-dev doxygen graphviz diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml new file mode 100644 index 0000000..f983fc8 --- /dev/null +++ b/.github/workflows/doxygen.yml @@ -0,0 +1,55 @@ +name: Generate Doxygen Documentation + +on: + push: + tags: + - '*' + +jobs: + build-docs: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Doxygen + run: | + sudo apt-get update + sudo apt-get install -y doxygen graphviz + + - name: Install build dependencies + run: | + sudo apt-get install -y cmake build-essential python3-dev + + - name: Configure CMake with documentation enabled + run: | + cmake -S . -B cmake-build \ + -DBUILD_DOCS=ON \ + -DCMAKE_BUILD_TYPE=Release + + - name: Build Doxygen documentation + run: | + cmake --build cmake-build --target docs + + - name: Copy docs for local testing (act only) + if: ${{ env.ACT }} + run: | + mkdir -p /tmp/act-artifacts + cp -r cmake-build/docs/html /tmp/act-artifacts/doxygen-html + + - name: Upload documentation artifacts + uses: actions/upload-artifact@v4 + with: + name: doxygen-html-${{ github.ref_name }} + path: cmake-build/docs/html + retention-days: 7 + + - name: Upload XML documentation artifacts + uses: actions/upload-artifact@v4 + with: + name: doxygen-xml-${{ github.ref_name }} + path: cmake-build/docs/xml + retention-days: 7 diff --git a/CMakeLists.txt b/CMakeLists.txt index 948bd22..07c8276 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,4 +59,41 @@ endif() # add_subdirectory(test) #endif() +# --------------------------------------------- +# Documentation (Doxygen) +# --------------------------------------------- +option(BUILD_DOCS "Enable building API documentation with Doxygen" OFF) +if(BUILD_DOCS) + find_package(Doxygen QUIET) + if(DOXYGEN_FOUND) + set(DOXYGEN_INPUT_DIRS + "${PROJECT_SOURCE_DIR}/src" + "${PROJECT_SOURCE_DIR}/src/include" + "${PROJECT_SOURCE_DIR}/core/src" + "${PROJECT_SOURCE_DIR}/core/src/include" + "${PROJECT_SOURCE_DIR}/docs" + ) + # Doxygen expects space-separated paths, not semicolon-separated lists + string(REPLACE ";" " " DOXYGEN_INPUT_DIRS_STR "${DOXYGEN_INPUT_DIRS}") + + # Configure Doxyfile from template + set(DOXYFILE_IN "${PROJECT_SOURCE_DIR}/docs/Doxyfile.in") + set(DOXYFILE_OUT "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile") + set(PROJECT_VERSION "${PROJECT_VERSION}") + configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) + + add_custom_target(docs + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM + ) + + add_custom_target(doc DEPENDS docs) + message(STATUS "Doxygen found. 'docs' target is available.") + else() + message(WARNING "Doxygen not found. Set BUILD_DOCS=OFF or install Doxygen to build documentation.") + endif() +endif() + diff --git a/docs.bash b/docs.bash new file mode 100755 index 0000000..c5cfc9c --- /dev/null +++ b/docs.bash @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Simple helper to build Doxygen docs via CMake +# Usage: ./docs.bash [build-dir] + +BUILD_DIR=${1:-cmake-build} + +# Check doxygen availability +if ! command -v doxygen >/dev/null 2>&1; then + echo "[ERROR] doxygen が見つかりません。macOS の場合: brew install doxygen" >&2 + exit 1 +fi + +# Configure CMake with docs enabled +cmake -S . -B "${BUILD_DIR}" -DBUILD_DOCS=ON -DCMAKE_BUILD_TYPE=Release + +# Build docs target +cmake --build "${BUILD_DIR}" --target docs -- -j + +OUT_HTML="${BUILD_DIR}/docs/html/index.html" +if [ -f "${OUT_HTML}" ]; then + echo "[INFO] ドキュメントを生成しました: ${OUT_HTML}" + # On macOS, try to open in default browser + if command -v open >/dev/null 2>&1; then + open "${OUT_HTML}" || true + fi +else + echo "[WARN] 期待する出力が見つかりませんでした: ${OUT_HTML}" >&2 +fi diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in new file mode 100644 index 0000000..d80e4e5 --- /dev/null +++ b/docs/Doxyfile.in @@ -0,0 +1,49 @@ +# Doxyfile template configured by CMake +# Generated from docs/Doxyfile.in + +# Project +PROJECT_NAME = "@PROJECT_NAME@" +PROJECT_NUMBER = "@PROJECT_VERSION@" +PROJECT_BRIEF = "hakoniwa-core-cpp-client API documentation" + +# Input +INPUT = @DOXYGEN_INPUT_DIRS_STR@ +RECURSIVE = YES +FILE_PATTERNS = *.h *.hpp *.hh *.hxx *.c *.cc *.cpp *.cxx *.dox *.md +EXCLUDE_PATTERNS = */.git/* */cmake-build/* */build/* */_deps/* */third_party/* + +# Output +OUTPUT_DIRECTORY = "@CMAKE_CURRENT_BINARY_DIR@/docs" +GENERATE_HTML = YES +HTML_OUTPUT = html +GENERATE_LATEX = NO +GENERATE_XML = YES +XML_OUTPUT = xml + +# General +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +MARKDOWN_SUPPORT = YES +USE_MDFILE_AS_MAINPAGE = @PROJECT_SOURCE_DIR@/docs/mainpage.md +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ +EXTRACT_ALL = YES + +# Warnings +WARN_IF_UNDOCUMENTED = NO +WARNINGS = YES +QUIET = YES + +# Diagrams +HAVE_DOT = NO +CALL_GRAPH = NO +CALLER_GRAPH = NO + +# Misc +GENERATE_TREEVIEW = YES +MULTILINE_CPP_IS_BRIEF = YES +TAB_SIZE = 4 +CASE_SENSE_NAMES = NO +ALIASES = diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..d1b89c8 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,66 @@ +# hakoniwa-core-cpp-client: API ドキュメント (Doxygen) + +このプロジェクトの C/C++ API ドキュメントを Doxygen で生成するための手順です。 + +## 必要要件 +- Doxygen (macOS なら `brew install doxygen`) +- CMake 3.20 以上 + +## 生成方法(推奨: CMake ターゲット) + +1. ビルドディレクトリを用意し、CMake 設定時にドキュメント機能を有効化します。 + +```sh +cmake -S . -B cmake-build -DBUILD_DOCS=ON -DCMAKE_BUILD_TYPE=Release +cmake --build cmake-build --target docs +``` + +2. 生成された HTML は以下に出力されます。 + +- `cmake-build/docs/html/index.html` + +## ワンライナー(macOS) + +プロジェクトルートで以下を実行します: + +```sh +./docs.bash +``` + +初回は自動的に CMake 設定と `docs` ターゲットのビルドを行います。 + +## 直接 Doxygen を実行したい場合(上級者向け) + +CMake が生成する `Doxyfile`(`cmake-build/Doxyfile`)を使って、直接実行も可能です。 + +```sh +doxygen cmake-build/Doxyfile +``` + +## act でローカル実行(CI/CD テスト) + +GitHub Actions ワークフローをローカルで実行する場合([act](https://github.com/nektos/act) が必要): + +```sh +# actの設定(初回のみ、Medium イメージを使用) +mkdir -p ~/Library/Application\ Support/act +echo '-P ubuntu-latest=catthehacker/ubuntu:act-latest' > ~/Library/Application\ Support/act/actrc + +# ワークフローを実行して成果物をローカルに保存 +act push \ + --container-architecture linux/amd64 \ + -W .github/workflows/doxygen.yml \ + -s GITHUB_TOKEN="$(gh auth token)" \ + --artifact-server-path ./build/artifacts \ + --job build-docs + +# 生成されたドキュメントを確認 +open ./artifacts/doxygen-html-*/index.html +``` + +### 出力内容 +- **HTML**: `./artifacts/doxygen-html-*/` - ブラウザで閲覧可能なドキュメント +- **XML**: `./artifacts/doxygen-xml-*/` - 他ツールとの連携用(Sphinx、解析ツールなど) + +--- +補足: 出力先や入力ディレクトリは `docs/Doxyfile.in` と `CMakeLists.txt` の設定で調整できます。 \ No newline at end of file diff --git a/docs/api_topics.dox b/docs/api_topics.dox new file mode 100644 index 0000000..5c189fe --- /dev/null +++ b/docs/api_topics.dox @@ -0,0 +1,82 @@ +/*! \file api_topics.dox + \brief API をトピック(グループ)としてまとめるための定義。 +*/ + +/** \defgroup asset_api Asset API + * ハコニワの Asset 向け C API。 + * Asset 登録・開始、PDU 読み書き、シミュレーション時間、スリープ等。 + */ + +/** \addtogroup asset_api + * \{ + * + * \fn int hako_asset_register(const char *asset_name, const char *config_path, hako_asset_callbacks_t *callbacks, hako_time_t delta_usec, HakoAssetModelType model) + * \brief Asset を登録します。 + * \param asset_name Asset 名 + * \param config_path 設定ファイルパス + * \param callbacks コールバック群 + * \param delta_usec シミュレーション刻み [usec] + * \param model モデル種別 + * \return 0 で成功、負でエラー + * + * \fn int hako_asset_start(void) + * \brief 登録済み Asset を開始します。 + * \return 0 で成功、負でエラー + * + * \fn int hako_asset_pdu_read(const char *robo_name, HakoPduChannelIdType lchannel, char *buffer, size_t buffer_len) + * \brief PDU を読み込みます。 + * \param robo_name ロボット名 + * \param lchannel ローカルチャンネルID + * \param buffer 読み出し先バッファ + * \param buffer_len バッファ長 + * \return 0 で成功、負でエラー + * + * \fn int hako_asset_pdu_write(const char *robo_name, HakoPduChannelIdType lchannel, const char *buffer, size_t buffer_len) + * \brief PDU に書き込みます。 + * \param robo_name ロボット名 + * \param lchannel ローカルチャンネルID + * \param buffer 書き込み元バッファ + * \param buffer_len バッファ長 + * \return 0 で成功、負でエラー + * + * \fn hako_time_t hako_asset_simulation_time(void) + * \brief 現在のシミュレーション時刻を返します。 + * \return 現在時刻 [usec] + * + * \fn int hako_asset_usleep(hako_time_t sleep_time_usec) + * \brief 指定時間スリープします。 + * \param sleep_time_usec スリープ時間 [usec] + * \return 0 で成功、負でエラー + * + * \fn int hako_initialize_for_external(void) + * \brief 外部連携の初期化を行います。 + * \return 0 で成功、負でエラー + * + * \fn int hako_asset_pdu_create(const char *robo_name, HakoPduChannelIdType lchannel, size_t pdu_size) + * \brief PDU を作成します。 + * \param robo_name ロボット名 + * \param lchannel ローカルチャンネルID + * \param pdu_size PDU サイズ + * \return 0 で成功、負でエラー + * + * \} + */ + +/** \defgroup conductor_api Conductor API + * シミュレーション進行(Conductor)向け C API。 + */ + +/** \addtogroup conductor_api + * \{ + * + * \fn int hako_conductor_start(hako_time_t delta_usec, hako_time_t max_delay_usec) + * \brief Conductor を開始します。 + * \param delta_usec シミュレーション刻み [usec] + * \param max_delay_usec 遅延許容上限 [usec] + * \return 0 で成功、負でエラー + * + * \fn void hako_conductor_stop(void) + * \brief Conductor を停止します。 + * + * \} + */ diff --git a/docs/mainpage.md b/docs/mainpage.md new file mode 100644 index 0000000..0cdbb8a --- /dev/null +++ b/docs/mainpage.md @@ -0,0 +1,9 @@ +\mainpage hakoniwa-core-cpp-client API ドキュメント + +このサイトは hakoniwa-core-cpp-client の C/C++ API をまとめたものです。主要トピック: + +- \ref asset_api "Asset API" +- \ref conductor_api "Conductor API" +- \ref pdu_types "PDU Data Types" + +各グループから目的の関数を参照してください。 \ No newline at end of file diff --git a/docs/pdu_types.dox b/docs/pdu_types.dox new file mode 100644 index 0000000..9cc5532 --- /dev/null +++ b/docs/pdu_types.dox @@ -0,0 +1,26 @@ +/*! \file pdu_types.dox + \brief 箱庭PDUのデータ型をまとめたトピック定義。 +*/ + +/** \defgroup pdu_types PDU Data Types + * 箱庭(Hakoniwa)におけるPDU関連のデータ型をまとめたトピックです。 + * 代表的には以下の構造体があります。 + * - hako::asset::PduReader + * - hako::asset::PduWriter + * - hako::asset::Robot + */ + +/** \class hako::asset::PduReader + * \ingroup pdu_types + * \brief PDUを読み取る側の設定を表す構造体。 + */ + +/** \class hako::asset::PduWriter + * \ingroup pdu_types + * \brief PDUへ書き込む側の設定を表す構造体。 + */ + +/** \class hako::asset::Robot + * \ingroup pdu_types + * \brief ロボット単位のPDU設定を表す構造体。 + */