こんにちは、今回はcatkin経由でdoxgenを叩いてドキュメント生成ができるようにしたのでその方法について備忘録を残しておこうと思います。
実際に作業を行ったリポジトリはこちらです。
作業結果はこんな感じで出来上がります。
まずは今回使ったツールの紹介から
使用ツール
catkin
現行のROSで主に使用されているビルドシステム、CMakeをベースにしているためCMakeのモジュールを作れば結構そのままいろいろできたりする。
doxygen
OpenCVのドキュメントとかでよく見るページを自動生成してくれる賢い子
HTML形式いがいにもlatexの形式とかいろんな形式で出力してくれるが今回はとりあえずHTMLを出力した。
下準備
過去にdoxygenとCMakeを組み合わせてドキュメントを生成するTipsはあったのでそれをベースに改良してみた。
参考記事その1:https://qiita.com/tmichi/items/9105bc271ee7fd7277fb
参考記事その2:https://qiita.com/yoyomion/items/16d152421ef4f7bfc8ac
今回はROSノードごとにドキュメントをビルドしたかったのでその2の方法をベースにした。
今回のディレクトリ構成は以下のようになっています。
robotx_packages
┣ Doxygen
┃ ┣ images ━ .jpg,.jpeg,*.png
┃ ┣ Doxyfile.in
┃ ┣ doxygen-script.cmake
┃ ┗ doxygen.cmake
┃
┗ ros_packages ━ CMakeLists.txt
Doxyfile.inは参考記事その2のものをそのまま使っています。
かなり長いのでコピペされたい方はこちらからどうぞ。
doxygen-script.cmakeは参考記事その2と同じで以下のようになっています。
configure_file(
"${DOXYGEN_TEMPLATE}"
"${DOXY_DOCUMENTATION_OUTPUT_PATH}/${DOXY_PROJECT_NAME}/Doxyfile"
@ONLY)
doxygen.cmakeはほぼ参考記事その2と同じですがDoxygen/images内部の画像を転送できるようにした、.hな拡張子のファイルだけでなく.hhを探せるようにしたので一部異なっています。
find_package(Doxygen)
# WITH_DOCUMENT オプションを追加、ONにするとドキュメントがビルドされるようになる。
option(WITH_DOCUMENT OFF)
# add_document関数を追加、targetにビルドターゲットを入れるとDoxygenによりドキュメントがビルドされる。
function(add_document target)
if(${DOXYGEN_FOUND})
#各種パスの設定
set(doxydir ${PROJECT_SOURCE_DIR}/../Doxygen)
set(outputdir ${PROJECT_BINARY_DIR}/DoxyDoc)
set(image_source_dir ${PROJECT_SOURCE_DIR}/../Doxygen/images)
set(image_dir ${PROJECT_BINARY_DIR}/DoxyDoc//${target}/html/images)
message("build document for ${target}")
#*.jpg,*.jpeg,*.pngの拡張子のファイルを探索しimage_dirに転送
# すべてのドキュメントごとにimage_dirが存在するので
#
#/**
# * @mainpage gazebo plugin for twist sensor simulation
# * @image html images/vmrc.jpg
# * @author Masaya Kataoka
# * @date 2018-06-09
# */
#
# のような書き方をすると画像をドキュメントに入れられます。
file(GLOB images_png ${image_source_dir}/*.png)
file(GLOB images_jpg ${image_source_dir}/*.jpg)
file(GLOB images_jpeg ${image_source_dir}/*.jpeg)
message("images : ${images_png} ${images_jpg} ${images_jpeg}")
foreach (img ${images_png})
file(COPY ${img} DESTINATION ${image_dir})
set(image_spaces "${image_spaces} ${img}")
message("transport images : ${img}")
endforeach ()
foreach (img ${images_jpg})
file(COPY ${img} DESTINATION ${image_dir})
set(image_spaces "${image_spaces} ${img}")
message("transport images : ${img}")
endforeach ()
foreach (img ${images_jpeg})
file(COPY ${img} DESTINATION ${image_dir})
set(image_spaces "${image_spaces} ${img}")
message("transport images : ${img}")
endforeach ()
#ソースファイル一覧を取得
get_property(sourcefiles
TARGET ${target}
PROPERTY SOURCES)
foreach (source ${sourcefiles})
set(source_spaces "${source_spaces} ${PROJECT_SOURCE_DIR}/${source}")
endforeach ()
get_property(includedirs
TARGET ${target}
PROPERTY INCLUDE_DIRECTORIES)
#ヘッダファイル一覧を取得
file(GLOB headers ${includedirs}/*.h)
foreach (h ${headers})
set(header_spaces "${header_spaces} ${h}")
endforeach ()
file(GLOB headers_hh ${includedirs}/*.hh)
foreach (h ${headers_hh})
set(header_spaces "${header_spaces} ${h}")
endforeach ()
foreach (dir ${includedirs})
set(dir_spaces "${dir_spaces} ${dir}")
endforeach ()
get_property(definitions
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
PROPERTY COMPILE_DEFINITIONS)
foreach (def ${definitions})
set(predef_spaces "${predef_spaces} ${def}")
endforeach ()
message("found source codes : ${source_spaces}")
message("output directory : ${outputdir}")
message("doxygen directory : ${doxydir}")
message("include directory : ${includedirs}")
#出力ディレクトリを作成
file(MAKE_DIRECTORY ${outputdir})
add_custom_command(
OUTPUT ${outputdir}/${target}/Doxyfile
COMMAND ${CMAKE_COMMAND}
-D "DOXYGEN_TEMPLATE=${doxydir}/Doxyfile.in"
-D "DOXY_PROJECT_INPUT=${source_spaces} ${header_spaces}"
-D "DOXY_PROJECT_INCLUDE_DIR=${dir_spaces}"
-D "DOXY_PROJECT_PREDEFINED=${predef_spaces}"
-D "DOXY_PROJECT_STRIP_FROM_PATH=${PROJECT_SOURCE_DIR}"
-D "DOXY_DOCUMENTATION_OUTPUT_PATH=${outputdir}"
-D "DOXY_PROJECT_NAME=${target}"
-P "${doxydir}/doxygen-script.cmake"
DEPENDS ${doxydir}/Doxyfile.in
${outputdir}
WORKING_DIRECTORY
${outputdir}
COMMENT "Generating Doxyfile for ${target}")
#Doxyfileからドキュメントを生成
add_custom_command(
OUTPUT ${outputdir}/${target}/index.html
COMMAND ${DOXYGEN_EXECUTABLE}
DEPENDS ${outputdir}/${target}/Doxyfile
WORKING_DIRECTORY
${outputdir}/${target}
COMMENT "Creating HTML documentation for ${target}")
#WITH_DOCUMENT オプションがONならばデフォルトでドキュメントをビルドする設定に
if(WITH_DOCUMENT)
add_custom_target("doxygen-${PROJECT_NAME}-${target}" ALL
DEPENDS ${outputdir}/${target}/index.html)
else()
add_custom_target("doxygen-${PROJECT_NAME}-${target}"
DEPENDS ${outputdir}/${target}/index.html)
endif()
else()
message("doxygen not found")
endif()
endfunction()
CMakeLists.txtの設定
以下の例のようにadd_document関数にターゲットを引き渡す。
# usv_twist_sensor_plugin
add_library(usv_twist_sensor_plugin
src/usv_twist_sensor_plugin.cc
)
target_link_libraries(usv_twist_sensor_plugin
${catkin_LIBRARIES}
${GAZEBO_LIBRARIES}
${Eigen_LIBRARIES}
)
add_document(usv_twist_sensor_plugin)
ビルド
catkin_make -DWITH_DOCUMENT=ON
以上のやり方でドキュメント作成の自動化が実現できました。