Doxygen で internal な実装群を隠す
隠すやり方がいくつかあるんだけど、 どう隠したいかで使うべきコマンドが違うみたい…。
遭遇したケース
通常、 source file local な class やメソッドに対する Doxygen コメントとかは
Doxygen の設定の EXTRACT_〜
を適切にすれば出力されないはず。
私が今回遭遇したケースは
- constexpr function なのでヘッダーに実装を書いてる
- Google C++ Style Guide に則るとヘッダーファイルでは無名名前空間が使えないので
impl
という名前空間に入れてる - 勢い余ってせっかく書いた doxygen コメントは残しておきたいが、内部実装なので API リファレンスとしての Doxygen の output からは除外したい
- そういった実装が複数連続してる存在してるのでまとめて隠したい
この場合は @cond
, @endcond
を使うとできる。
Doxygen における条件による出力の出し分け方
いくつか方法がある。以下網羅できてるかは知らない。
#ifndef
を使う方法
- 隠したいところを Doxygen 解釈時以外には絶対に定義されないマクロの
#ifndef
で括る
#ifndef DOXYGEN_SHOW_CLASS_FOO /// This class provides so FOO features. class Foo { }; #endif // !defined(DOXYGEN_SHOW_CLASS_FOO)
ENABLE_PREPROCESSING = YES
にする- 出力したいときは
PREDEFINED = DOXYGEN_SHOW_CLASS_FOO
にする
これは @cond
が実装される前に使われてた方法らしい。
- C / C++ として何か作用したいわけではないのに、 C / C++ としてのソースが汚れる
- ソースコードの読み手が慎重になる必要がある
- プリプロセッサマクロを解釈するようなツール群が期待しない動作になる or 期待動作のために追加設定が必要になる、かも
- エディタのコードハイライティング
- lint など静的解析ツール
- ...
あたりが欠点かなぁ…。
@cond
を使う方法
これは上で書いたので簡単に言うと #ifndef
とかの代わりに Doxygen コマンドを使う、と。
/// @cond DOXYGEN_SHOW_CLASS_FOO /// This class provides so FOO features. class Foo { }; /// This class provides so BAR features. class Bar { }; /// @endcond
- 出力したいときは
ENABLED_SECTIONS=DOXYGEN_SHOW_CLASS_FOO
のようにする
これは使いやすいよね。コードハイライティングがおかしくなったりもしないだろうし。
ちなみに常時出力しないのでよければ @cond
のうしろ(「セクションラベル」と呼ぶらしい)は省略できるらしい。
/// @cond /// This class provides so FOO features. class Foo { }; /// This class provides so BAR features. class Bar { }; /// @endcond
まぁ、どういう意図で @cond
で括っているかの表明にもなるから、私だったら省略しないルールにすると思う。
@if
を使う方法
これが紛らわしい。
@cond
がざっくりまとめて出力・非出力を切り替える目的に使えるのに対して、
@if
はコメントブロック内で一部の出力条件を変える目的に使う。
この「コメントブロック内〜」が重要なんだけど私は最初読み飛ばしちゃってて混乱した。
要はクラスなり関数なりの説明のまとまりの中で一部を出力する条件を記述するのに使えるってことらしい。
今回のように目的が「コードを読んだ人には見せるけど Doxygen 出力からは隠す」だと
/// This class provides so FOO features. /// /// @if CLASS_FOO_SECRET /// This is not doxygen-documented secret, Ha ha. /// @endif class Foo { };
みたいなことになる。
ENABLED_SECTIONS=CLASS_FOO_SECRET
としてやれば括ってあるところも出力される。
ただ、コメントブロックをまたげないので、
今回のように複数関数をまとめて出力する・しないを切り替えたいような用途には使えない。
これだけだと私にはあんまりありがたみが感じられなかったんだが、
/// This class provides so FOO features. /// /// @if english /// Details by English. /// @elseif japanese /// 日本語での詳細記述。 /// @endif class Foo { };
こんな感じで言語を切り替えるのに使ってるのは、
そういえば以前に見たような記憶がかすかにある…。
ENABLED_SECTIONS
と出力先を切り替えながら出力すると
複数言語分のドキュメントが生成できる、と。