Doxygen の使用

このセクションでは、Doxygenが|Gromacs|ソースツリーにどのように設定されるか、および新しいDoxygenコメントを追加するためのガイドラインについて説明しています。例も含まれており、Doxygenの警告を回避するためのヒントやテクニックも紹介しています。これらのガイドラインは、新しいモジュール構造に従うC++コードやその他の新しいコードに焦点を当てています。一部のガイドラインは、古いコード(たとえば、gmxlib/``または``mdlib/``内のコード)を文書化する場合にも適用できます。特に、Doxygenコメントのフォーマットとinternal``の使用に関するガイドラインについては、参照してください:ドキュメントの構成

迅速に始めるには、まず2つのセクションを読むだけで、ドキュメント全体の構造を理解し、最後に記載されている例を確認すれば十分です。残りのセクションは、なぜこれらの例がそのような形になっているのか、そしてより複雑な状況を理解するための詳細を提供します。これらのセクションは、特定の問題に対する解決策を調べるための参照として使用することを目的としており、一度読むだけではなく、繰り返し参照するのに適しています。個別のDoxygenコマンドを理解または見つけるには、まずDoxygenのドキュメント(http://www.doxygen.nl/manual/)を参照してください。

ドキュメントの種類

GROMACS のソースツリーは、複数の異なるレベルのDoxygenドキュメントを生成するように構成されています。

  1. パブリックなAPIドキュメント(サフィックス -user)、これはライブラリからエクスポートされ、|Gromacs|ライブラリの外で利用することを意図した関数とクラスを記述したものです。

  2. ライブラリAPIドキュメント(サフィックス -lib を含む)、これには、|Gromacs|の他の部分から使用するように設計された関数やクラス、および主に開発者向けのガイダンスが含まれています。

  3. 完全なドキュメント(拡張子 -full)、これはソースツリー内の(ほとんど)すべての(ドキュメント化された)関数とクラスを含みます。

  4. 最も詳細なドキュメント("-dev" というサフィックスを使用)で、Doxygenが抽出できるすべての情報に加え、追加の内部リンクも含まれます。

各次のドキュメントレベルには、上位のすべてのドキュメントが含まれています。 上記の接尾辞は、Doxygenの入力および出力ファイルの接尾辞、および出力ディレクトリの名前を指します。 すべてのバージョンが構築された後、ドキュメントの表紙には、他のバージョンへのリンクが含まれており、詳細な違いが説明されています。

一般的なガイドラインとして、ユーザーが|Gromacs|の変更されていないバージョンにリンクする場合にアクセスできる内容を除いた、公開APIのドキュメントは、インストールされているヘッダーの内容を主に記述し、それらを使用するための必要な概要を提供するものでなければなりません。さらに、公開APIのドキュメントに対する要件は高くなっています。理想的には、読者はドキュメントに基づいてAPIをすぐに使用できるようになるべきであり、実装の詳細を確認する必要はありません。

同様に、ライブラリのAPIドキュメントには、|Gromacs|の他のモジュールが呼び出すべきでない、または呼び出すべきではない機能を含めるべきではありません。特に、ソースファイル内でローカルに宣言されたものは、必ずしも完全なドキュメントで利用可能である必要があります。また、ある機能がドキュメント化されている場合、かつそれがライブラリのAPIの一部ではない場合、その関数をそのモジュール外から呼び出す必要はありません。

ドキュメントの作成

最新のドキュメントを参照したい場合は、対応するブランチの最新のスケジュールされたパイプラインの「webpage」ジョブから成果物をダウンロードできます(https://gitlab.com/gromacs/gromacs/-/pipelines?page=1&scope=all&source=schedule)。また、CIは、GitLabにプッシュされたすべての変更に対してDoxygenを実行し、その結果として生成されたドキュメントは、対応する「webpage」ジョブの成果物で見つけることができます。DoxygenジョブがDoxygenの警告を発生させる場合は失敗します。

もし、コメントを大幅に追加/修正した後、結果を確認したい場合は、ドキュメントをローカルでビルドする必要がある場合があります。特に、Doxygenの使用経験が少ない場合は、推奨されます。さまざまな設定でビルドし、結果がご希望のものになっているか、警告が出ないかを確認することをお勧めします。ローカルでの作業では、通常、「GMX_COMPACT_DOXYGEN=ON」というCMakeオプションを設定することが推奨されます。これにより、ドキュメントから一部の大きな生成グラフが削除され、プロセスが大幅に高速化されます。また、「fast」なバージョンの「make」ターゲットも存在し、これらは「lib」レベル以下の追加の図をスキップします。

Doxygenに関連するすべてのファイルは、ソースとビルドツリーの両方にある docs/doxygen/ ディレクトリに存在します。 新しくチェックアウトしたソースツリーでは、このディレクトリにはさまざまな Doxyfile-*.cmakein ファイルが含まれています。 CMakeを実行すると、対応するファイル Doxyfile-userDoxyfile-libDoxyfile-fullDoxyfile-dev がビルドツリーの対応する場所に生成されます。 また、 Doxyfile-common.cmakein も存在し、これを使用して Doxyfile-common を生成します。 このファイルには、すべての入力ファイル間で共有される設定が含まれています。 Doxyfile-compact は、 GMX_COMPACT_DOXYGEN=ON のための追加設定を提供します。

Doxygen を生成されたファイル (すべての出力は現在の作業ディレクトリに生成されます) のいずれかを使用して直接実行できます。または、doxygen-userdoxygen-libdoxygen-fulldoxygen-dev のいずれかのターゲットをビルドできます。これらのターゲットは、Doxygen を静かなモードで実行し、エラーが発生した場合にのみ警告を表示し、出力はビルドツリー内の docs/html/doxygen/ に配置します。これにより、Doxygen のビルドが、より広範な webpage ターゲットと連携できます。doxygen-all ターゲットは、より少ない入力で 3 つのターゲットをすべてビルドします。

生成されたドキュメントは、html-user/html-lib/html-full/、および/または html-dev/ のいずれかのサブディレクトリにある index.xhtml ファイルを開いて閲覧を開始できます(GROMACS 開発者の方は、html-lib/ が適切な開始点です)。すべての Doxygen の警告を含むログファイルも、docs/doxygen/doxygen-*.log として生成されるため、実行後に確認できます。

現在のドキュメントを構築するには、Doxygen 1.8.5 が必要です。他のバージョンでも動作する可能性がありますが、警告が発生する可能性もあります。また、ドキュメント内の一部のグラフには、graphvizmscgen が必要であり、数式には latex が必要です。これらのツールは、ほとんどのパッケージマネージャーから入手できる可能性があります。これらのツールを使用せずにドキュメントを構築することも可能ですが、エラーが発生し、関連する図がドキュメントから削除されます。

一般的な Doxygen マークアップのガイドライン

Doxygenは、ソースコードのドキュメント作成のための、いくつかの異なるスタイルを提供します。Doxygenが異なる種類のコメントをどのように扱うかには、微妙な違いがあり、これはDoxygenの設定にも依存します。コメントのスタイルを変更するだけで、コメントの意味を変えることができます。このような問題を回避し、すべてのスタイルを管理する必要がないようにするため、ソースツリー全体で単一のスタイルを使用することが推奨されます。スタイルに関する扱いについては、|Gromacs|はデフォルトのDoxygen設定を使用していますが、例外として、``JAVADOC_AUTOBRIEF``を``ON``に設定することで、Cコードでのより便利な1行の短い説明を可能にしています。

現在、|Gromacs|で使用されているほとんどのコメントはQtスタイルのコメント(/*!`と//!`の代わりに`/**///brief`の代わりに`@brief`などを使用)であるため、新しいドキュメントにもこれらのスタイルを使用する必要があります。ただし、Cコードの短いコメントについては、例外があります。

同様に、既存のコメントでは、CおよびC++コードの両方でマルチラインコメントに``/*!``を使用しており、C++の場合は複数の``//!``を使用する代わりに、統一的なスタイルを使用しています。これは、コードが長期間にわたって両方の言語の混合になるため、両方で同様のスタイルを使用することがより適切であるためです。また、ファイルが徐々にCからC++に移行する場合、異なるスタイルに関する問題のためにコメントを書き換える必要は通常ありません。最後に、マルチラインの``//!``コメントは、Doxygenの設定によって異なる動作をする可能性があるため、そのような曖昧さを避けることが推奨されます。

コメントを追加する際は、常に短い説明文が生成されるようにしてください。これはさまざまなリストで使用され、メソッドの目的を簡潔に説明するために使用されます。基本的なガイドラインは、すべてのコメントブロックを \brief (他のDoxygenコマンドの後に) で開始することです。1行のコメントでは \brief を使用したくない場合は、//! を使用できますが、説明は1行に収める必要があります。そうしないと、これは短いコメントとして解釈されません。特に、/*!\brief がない場合、短い説明文は生成されません。また、\brief は、その後の段落全体を短い説明としてマークするため、意図した短い説明文の後に空の行を挿入する必要があります。

Cコードでは、// コメントの使用は避けるべきです。なぜなら、一部のコンパイラではこの形式のコメントを認識しないからです。Cコードで、1行のコードに対する brief の記述を避ける場合は、/**//! の代わりに使うことを推奨します。この場合、短い説明には、末尾以外では未エスケープされたピリオドを含めないようにしてください。そのため、C++コードでは //! を使用する方が適切です。

ドキュメントコメントを、宣言を含むヘッダーファイルに記述します(そのようなヘッダーが存在する場合)。メソッドの使用方法に影響を与えない、実装固有のコメントは、メソッド定義の直前に、コメントブロックの先頭に \internal タグを使用してソースファイルに記述できます。関数内のDoxygen形式のコメントは、通常使用できません。

場合によっては、Doxygenが特定のヘッダーやソースファイルの一部を見えないようにする必要があります。一般的には、これを避けるべきですが、公開APIドキュメントに表示したくない関数を削除したり、Doxygenが理解できないコードから警告を回避したりする必要がある場合があります。そのような場合は、\cond``とendcond``を使用することをお勧めします。``cond``がうまくいかない場合は、``#ifndef DOXYGEN``を使用することもできます。ヘッダー内のクラスメソッドを除外する場合は、ソースコードからも除外する必要があります。

GROMACS 特有の仕様

上記のDoxygenコメントのスタイルに関する一般的なガイドラインは上記に示されています。このセクションでは、Doxygenドキュメントで現在使用されている|Gromacs|固有の構文、および|Gromacs|がDoxygenグループを使用してドキュメントを整理する方法について説明します。

一部の整合性チェックは、カスタムスクリプトを使用して自動的に実行されます。詳細は、スクリプトによるソースツリーのチェック を参照してください。

ドキュメントの表示制御

特定の関数がどのレベルのドキュメントに表示されるかを制御するために、3つの異なるメカニズムが使用されます。

  • グローバルなDoxygen設定。これは主に、ソースファイルに限定された宣言のみを完全なドキュメントに含めるために使用されます。詳細は、``Doxyfile-*.cmakein``ファイルから確認できます。また、個々のコード構成についても、一部は以下に記載されています。

  • 標準のDoxygenコマンド \internal は、ドキュメントを完全にドキュメントにのみ抽出するようにマークします(INTERNAL_DOCS は完全にドキュメントに対してのみ ON に設定されます)。これは、すべてのドキュメントを除外するために、コメントブロックの最初のコマンドとして使用する必要があります。 \internal\endinternal を使用して個々の段落を除外することも可能ですが、\if internal を使用することをお勧めします(下記を参照)。さらに、GROMACS-固有のカスタムDoxygenコマンド \libinternal も提供されており、これは、公開APIドキュメントからドキュメントを除外するために、同じ方法で使用する必要があります。このコマンドは、ドキュメントレベルに応じて、\internal に展開するか、何もしない動作になります。

  • Doxygen のコマンド \if\cond を、セクション名 libapiinternal と組み合わせて使用​​すると、それぞれライブラリ API のドキュメントのみ、および完全なドキュメントのみを含めることができます。 libapi は完全なドキュメントにも定義されています。 これらの定義は、Doxygen の設定ファイルにある ENABLED_SECTIONS を使用して行います。

個々のコード構成に関するセクションに、これらの明示的なコマンドを使用する必要がある場所の例が以下に示されています。

モジュールをDoxygenグループとして扱う

ソースコードの構造 に記載されているように、 src/gromacs/ の下にある各サブディレクトリは、*モジュール*を表し、つまり、ある程度まとまったルーチンのコレクションです。Doxygenは、モジュール内のルーチンのリストを自動的に生成できません。代わりに、ドキュメント化されている関数やクラスを含む、さまざまなアルファベット順のインデックスを抽出します。ドキュメントの読みやすさを向上させるために、モジュールのルーチンは、1つの場所に表示される必要があります。

GROMACS は、Doxygen グループを使用してこれを実現します。各ドキュメント化されたモジュールには、モジュールのための \defgroup 定義が含まれており、関連するすべてのクラスと関数を \ingroup\addtogroup を使用してこのグループに追加する必要があります。グループページは、モジュールに関する概要ドキュメントを記述するための自然な場所を提供し、生成されたドキュメントの「モジュール」タブから直接アクセスできます。

\addtogroup を使用する際のいくつかの注意点:

  • \addtogroup は、直接含まれる要素のみをグループに追加します。 名前空間の宣言を含めると、グループには名前空間のみが追加され、名前空間の内容は追加されません。 そのため、\addtogroup は、実際にグループに追加するメンバーの最も内側のスコープ内に配置する必要があります。

  • もしモジュールを公開APIドキュメントに含めない場合は、その定義(defgroup)に \libinternal をプレフィックスとして付加する必要があります。この場合、モジュールに関連するすべての \addtogroup コマンドにも同様にプレフィックスを付加する必要があります。そうしないと、公開APIドキュメントにグループが作成されますが、\defgroup の定義からの内容は含まれません。これにより、通常では含まれない内容も公開APIドキュメントに表示される可能性があります。

公開APIとライブラリAPIグループ

さらに、モジュールグループに加えて、固定グループ「group_publicapi」と「group_libraryapi」も提供しています。これらのグループには、|Gromacs|固有のカスタムコマンド「inpublicapi」と「inlibraryapi」を使用して、クラスとファイルを追加できます。生成されたグループドキュメントページはあまり役に立ちませんが、注釈付きのクラスとファイルは、名前の下でAPI定義を表示するため、この情報へのアクセスが容易になります。これらのコマンドは、ファイルレベルのコメントにも使用され、モジュール間の依存関係の自動検証にも役立ちます(詳細は後述)。

注意: 生成されたドキュメントに個別のページを持たない関数、列挙型、その他のエンティティは、1つのグループにのみ属する必要があります。この場合、APIグループよりもモジュールグループを使用することをお勧めします。

特定のコード構造のドキュメント作成

このセクションでは、特定のコード構造を文書化するための技術的な詳細と、役立つドキュメントを作成するためのヒントやテクニックについて説明しています。 特定の情報をどこに文書化するか迷っている場合は、ドキュメントの構成 のドキュメント構造セクションを参照してください。 ドキュメントの主な内容は、Doxygen ページとモジュールドキュメントの概要に焦点を当てることです。 経験豊富な開発者は、個々の関数を比較的簡単に読み解くことができますが、ドキュメントは全体像を把握するのに役立ちます。

ドキュメントページ

ホームページからのナビゲーションでアクセスできるページは、Markdown形式で記述されており、docs/doxygen/ フォルダに格納されています。 各ページは、別のページの子ページとして階層構造に配置する必要があります。 つまり、\subpage を使用して一度参照する必要があります。 mainpage.md が階層構造のルートです。

「user/」と「lib/」という2つのサブディレクトリが存在し、これらのディレクトリにページを追加することで、ページのドキュメントレベルが決定されます。「lib/」にページを追加する場合は、ページへの参照が、公開されているAPIドキュメントから存在しないように注意してください。「if libapi」を使用することで、通常は公開されているコンテンツに参照を追加できます。一般的には、ページは十分に高いレベルに配置し、有用な概要情報を提供する必要があります。これにより、ライブラリAPIドキュメントから除外する必要がなくなります。

モジュール

各モジュールについて、そのモジュールにとって最も重要なヘッダーファイルを決定します(自明のヘッダーがない場合は、例えば module-doc.h などのヘッダーファイルを、この目的のために指定することをお勧めします。ただし、現在、どのモジュールにも適用されていません)。このヘッダーには、モジュールの \defgroup 定義を含める必要があります。グループの名前は、module_name の形式で指定し、name は、モジュールをホストするサブディレクトリの名前です。

このモジュールは、適切なグループに追加する必要があります(定義は docs/doxygen/misc.cpp を参照)。 \ingroup を使用して、「モジュール」タブのドキュメントを整理します。

モジュールの内容について知っている、または関与している連絡先を \author コマンドを使用してリストアップしてください。これにより、質問がある場合に連絡先を得ることができます。著者は、可能な限り、貢献の順序でリストアップしてください。

クラス/構造体

クラスと構造体は、ヘッダーファイルに定義されている場合、Doxygenドキュメントに常に表示されます。ただし、そのファイルがドキュメント化されていなくてもです。したがって、パブリックAPIの一部ではないクラスのドキュメントブロックは、\internal``またはlibinternal``で開始してください。ソースファイルまたは名前のない名前空間でローカルに宣言されたクラスは、完全なドキュメントのみに表示されます。

もしクラス全体がドキュメントされていない場合、現在では警告は発生しません。クラスは単にドキュメントから除外されます。ただし、ドキュメントされているクラスのメンバーがドキュメントされていない場合、警告が生成されます。フリー関数をドキュメントするためのガイドラインは、クラスのメソッドにも適用されます。

基本クラスの場合、APIの分類(\inpublicapi``またはinlibraryapi``)は、クラスがどのサブクラスで利用されることを想定しているかによって決定します。一方、可視性(\internal``またはlibinternal``)は、派生クラスのAPI分類を反映するように設定し、基本クラスのドキュメントが常に派生クラスと一緒に生成されるようにします。

継承されることを意図したクラスで、保護されたメンバーがある場合、その保護されたメンバーは、クラスが継承されることを意図したドキュメントレベルにのみ表示されるべきです。たとえば、クラスが特定のモジュール内でのみ継承されることを意図している場合、その保護されたメンバーは、完全なドキュメントにのみ表示されるべきです。これは、\cond を使用して実現できます(ただし、Doxygenから同じメソッドを非表示にするために、ソースファイルにも \cond コマンドを追加する必要があります。そうしないと、混乱を招く警告が表示されます)。

メソッド/関数/列挙型/マクロ

これらの項目は、それらが囲まれた範囲がドキュメント化されている場合にのみ、ドキュメントに表示されます。 クラスのメンバーの場合、範囲はクラス自体です。 それ以外の場合は、存在する場合は名前空間、またはファイルです。 \addtogroup は、グループが外部の範囲よりも高い可視性を持つ場合、範囲を定義することもできます。 したがって、関数が名前空間内 (主に C コードの場合) でなく、囲まれたファイルと同じ可視性を持つ場合、\internal または \libinternal を追加する必要はありません。

静的関数は、現在、すべてのドキュメント形式で抽出されており、ヘッダーが static inline 関数(例えば、数学コードで使用される)を宣言できるようにしています。匿名名前空間内の関数は、フルドキュメントにのみ抽出されます。上記のルールと合わせて、ソースファイル内であっても、ドキュメント化された名前空間内に static 関数を配置することは避けるべきです。そうしないと、意図せず公開APIドキュメントに表示される可能性があります。

もし、ドキュメントから特定の項目を除外したい場合は、その項目を \cond ブロック内に配置することで、Doxygenがその項目を認識しないようにする必要があります。そうしないと、ドキュメントされていない関数の警告が生成されます。 \cond ブロックで、宣言と定義の両方を囲む必要があります。

ファイル

各ドキュメント化されたファイルは、必ず(著作権表示のすぐ後に)ドキュメントブロックから始まらなければなりません。正確なフォーマットについては、例を参照してください。注意すべき点:

  • 「file」の後にファイル名を明示的に指定しないでください。デフォルトでは、ファイル内のファイルコメントは、そのファイル自体に適用されます。明示的なファイル名を指定すると、さらに1つの情報が古くなる可能性があります。

  • \brief\file と同じ行には表示できませんが、次の行に表示する必要があります。

  • \internal または \libinternal は、ヘッダーがどこで利用可能かを示すために使用します。 一般的なガイドラインとして、インストールされたすべてのヘッダーは、公開APIドキュメントに表示されるべきであり、これらのコマンドは含まれていません。 もしそうでなければ、公開API関数が含まれていないことを示すために使用します。 ライブラリAPIで何かを宣言しているヘッダーは \libinternal でマークし、残りのヘッダーは \internal でマークします。

  • すべてのソースファイル、およびほとんどのテストファイルは、\internal``でドキュメント化する必要があります。これは、これらのファイルが公開またはライブラリAPIには何も提供していないためであり、意図せずファイルの内容をドキュメントに抽出することを防ぎます。他のモジュールからのテストで使用される共有テストファイルは、libinternal``でマークする必要があります。

  • \inpublicapi または \inlibraryapi を使用して、ヘッダーファイルを直接インクルードすることを指定します。

  • モジュールと同様に、1人以上の担当者名を \author で指定する必要があります。ファイルに大幅な修正や追加を行った場合は、ご自身の名前を \author に追加することを検討してください。

ディレクトリ

ディレクトリのドキュメントには、通常、モジュールとの非常に類似性があるため、モジュール自体が十分に文書化されていることから、役立つ情報がほとんど含まれていません。ただし、「Files」ページで生成されたソースツリーの概要を示すために、短い説明は依然として役立ちます。ディレクトリの説明としては、通常、モジュールへの参照で十分です。現在、すべてのディレクトリは docs/doxygen/directories.cpp に文書化されています。

基本 C++

以下は、C++クラスとその包含ヘッダーファイルのドキュメントの例です。 コード内のコメントと実際のドキュメントは、使用されているDoxygen構文を説明しています。

/*! \libinternal \file
 * \brief
 * Declares gmx::MyClass.
 *
 * More details.  The documentation is still extracted for the class even if
 * this whole comment block is missing.
 *
 * \author Example Author <example@author.com>
 * \inlibraryapi
 * \ingroup module_mymodule
 */

namespace gmx
{

/*! \libinternal
 * \brief
 * Brief description for the class.
 *
 * More details.  The \libinternal tag is required for classes, since they are
 * extracted into the documentation even in the absence of documentation for
 * the enclosing scope.
 * The \libinternal tag is on a separate line because of a bug in Doxygen
 * 1.8.5 (only affects \internal, but for clarity it is also worked around
 * here).
 *
 * \inlibraryapi
 * \ingroup module_mymodule
 */
class MyClass
{
    public:
        // Trivial constructors or destructors do not require documentation.
        // But if a constructor takes parameters, it should be documented like
        // methods below.
        MyClass();
        ~MyClass();

        /*! \brief
         * Brief description for the method.
         *
         * \param[in] param1  Description of the first parameter.
         * \param[in] param2  Description of the second parameter.
         * \returns   Description of the return value.
         * \throws    std::bad_alloc if out of memory.
         *
         * More details describing the method.  It is not an error to put this
         * above the parameter block, but most existing code has it here.
         */
        int myMethod(int param1, const char *param2) const;

        //! Brief description for the accessor.
        int simpleAccessor() const { return var_; }
        /*! \brief
         * Alternative, more verbose way of specifying a brief description.
         */
        int anotherAccessor() const;
        /*! \brief
         * Brief description for another accessor that is so long that it does
         * not conveniently fit on a single line cannot be specified with //!.
         */
        int secondAccessor() const;

    private:
        // Private members (whether methods or variables) are currently ignored
        // by Doxygen, so they don't need to be documented.  Documentation
        // doesn't hurt, though.
        int var_;
};

} // namespace gmx

基本 C

以下は、Cヘッダーファイルをドキュメント化する別の例です(C++スタイルのコメントをすべて避ける)。また、フリー関数を含み、\addtogroup``を使用して、繰り返しingroup``タグを使用せずに複数の関数をモジュールグループに追加する方法も示しています。:

/*! \file
 * \brief
 * Declares a collection of functions for performing a certain task.
 *
 * More details can go here.
 *
 * \author Example Author <example@author.com>
 * \inpublicapi
 * \ingroup module_mymodule
 */

/*! \addtogroup module_mymodule */
/*! \{ */

/*! \brief
 * Brief description for the data structure.
 *
 * More details.
 *
 * \inpublicapi
 */
typedef struct {
    /** Brief description for member. */
    int  member;
    int  second; /**< Brief description for the second member. */
    /*! \brief
     * Brief description for the third member.
     *
     * Details.
     */
    int  third;
} gmx_mystruct_t;

/*! \brief
 * Performs a simple operation.
 *
 * \param[in] value  Input value.
 * \returns   Computed value.
 *
 * Detailed description.
 * \inpublicapi cannot be used here, because Doxygen only allows a single
 * group for functions, and module_mymodule is the preferred group.
 */
int gmx_function(int value);

/* Any . in the brief description, except at the end, should be escaped as \. */
/** Brief description for this function. */
int gmx_simple_function();

/*! \} */

スコープと可視性に関するルール

Doxygenがドキュメントを期待する場所と、``internal``のようなコマンドが必要となる状況は複雑になることがあります。以下に、いくつかの注意点を示します。:

/*! \libinternal \file
 * \brief
 * ...
 *
 * The examples below assume that the file is documented like this:
 * with an \libinternal definition at the beginning, with an intent to not
 * expose anything from the file in the public API.  Things work similarly for
 * the full documentation if you replace \libinternal with \internal
 * everywhere in the example.
 *
 * \ingroup module_example
 */


/*! \brief
 * Brief description for a free function.
 *
 * A free function is not extracted into the documentation unless the enclosing
 * scope (in this case, the file) is.  So a \libinternal is not necessary.
 */
void gmx_function();

// Assume that the module_example group is defined in the public API.

//! \addtogroup module_example
//! \{

//! \cond libapi
/*! \brief
 * Brief description for a free function within \addtogroup.
 *
 * In this case, the enclosing scope is actually the module_example group,
 * which is documented, so the function needs to be explicitly excluded.
 * \\libinternal does not work, since it would produce warnings about an
 * undocumented function, so the whole declaration is hidden from Doxygen.
 */
void gmx_function();
//! \endcond

//! \}

// For modules that are only declared in the library API, \addtogroup
// cannot be used without an enclosing \cond.  Otherwise, it will create
// a dummy module with the identifier as the name...

//! \cond libapi
//! \addtogroup module_libmodule
//! \{

/*! \brief
 * Brief description.
 *
 * No \libinternal is necessary here because of the enclosing \cond.
 */
void gmx_function();

//! \}
//! \endcond

// An alternative to the above is use this, if the enclosing scope is only
// documented in the library API:

//! \libinternal \addtogroup module_libmodule
//! \{

//! Brief description.
void gmx_function()

//! \}

/*! \libinternal \brief
 * Brief description for a struct.
 *
 * Documented structs and classes from headers are always extracted into the
 * documentation, so \libinternal is necessary to exclude it.
 * Currently, undocumented structs/classes do not produce warnings, so \cond
 * is not necessary.
 */
struct t_example
{
    int  member1; //!< Each non-private member should be documented.
    bool member2; //!< Otherwise, Doxygen will produce warnings.
};

// This namespace is documented in the public API.
namespace gmx
{

//! \cond libapi
/*! \brief
 * Brief description for a free function within a documented namespace.
 *
 * In this case, the enclosing scope is the documented namespace,
 * so a \cond is necessary to avoid warnings.
 */
void gmx_function();
//! \endcond

/*! \brief
 * Class meant for subclassing only within the module, but the subclasses will
 * be public.
 *
 * This base class still provides public methods that are visible through the
 * subclasses, so it should appear in the public documentation.
 * But it is not marked with \inpublicapi.
 */
class BaseClass
{
    public:
        /*! \brief
         * A public method.
         *
         * This method also appears in the documentation of each subclass in
         * the public and library API docs.
         */
        void method();

    protected:
        // The \cond is necessary to exlude this documentation from the public
        // API, since the public API does not support subclassing.
        //! \cond internal
        //! A method that only subclasses inside the module see.
        void methodForSubclassToCall();

        //! A method that needs to be implemented by subclasses.
        virtual void virtualMethodToImplement() = 0;
        //! \endcond
};

} // namespace gmx

モジュールに関するドキュメント

新しいモジュールをドキュメント化する際には、モジュールの中心ヘッダーに、以下のようなコメントを記述し、生成されたドキュメントの「モジュール」タブからモジュールにアクセスできるようにします。:

/*! \defgroup module_example "Example module (example)"
 * \ingroup group_utilitymodules
 * \brief
 * Brief description for the module.
 *
 * Detailed description of the module.  Can link to a separate Doxygen page for
 * overview, and/or describe the most important headers and/or classes in the
 * module as part of this documentation.
 *
 * For modules not exposed publicly, \libinternal can be added at the
 * beginning (before \defgroup).
 *
 * \author Author Name <author.name@email.com>
 */

// In other code, use \addtogroup module_example and \ingroup module_example to
// add content (classes, functions, etc.) onto the module page.

よくある間違い

最も一般的な間違い、特にCコードの場合、それはファイルの説明を記述することを忘れてしまうことです。これにより、Doxygenはファイルのほとんどのコメントを無視するため、コメントの内容も検証できず、生成されたドキュメントがどのように見えるかを実際に確認することもできません。

以下の例は、正しくドキュメントを生成しない一般的な間違い(および、まれな間違い)や、Doxygenの「機能」/バグを示しています。これらの内容は、混乱を招く可能性があります。

  • 構造体自体はドキュメントされていません。宣言内の他のコメントは無視されます。

    struct t_struct {
    
        // The comment tries to document both members at once, but it only
        // applies to the first.  The second produces warnings about missing
        // documentation (if the enclosing struct was documented).
    
        //! Angle parameters.
        double alpha, beta;
    };
    
  • これにより、短いドキュメントは生成されません。明示的な \brief を使用するか、//! (C++) または /** */ (C) を使用する必要があります。

    /*! Brief comment. */
    int gmx_function();
    
  • これにより、ドキュメントは生成されません。なぜなら、「!」という記号が先頭にないからです。

    /* \brief
     * Brief description.
     *
     * More details.
     */
    int gmx_function();
    
  • これにより、全体の段落を短い説明に含めます。短い説明の方が適しており、空行で他のテキストから区切るのが望ましいです。:

    /*! \brief
     * Brief description. The description continues with all kinds of details about
     * what the function does and how it should be called.
     */
    int gmx_function();
    
  • これはDoxygenのバグである可能性がありますが、これにより短い説明は生成されません。

    /** \internal Brief description. */
    int gmx_function();
    
  • もし、以下の最初の宣言がヘッダーに、そして2番目の宣言がソースファイルに現れる場合、Doxygenはそれらを正しく関連付けられず、後者のために欠落したドキュメントについて警告します。解決策は、コンパイラが不要であっても、ソースファイルにも明示的に名前空間プレフィックスを追加することです。

    // Header file
    //! Example function with a namespace-qualified parameter type.
    int gmx_function(const gmx::SomeClass &param);
    
    // Source file
    using gmx::SomeClass;
    
    int gmx_function(const SomeClass &param);
    
  • これにより、名前空間を指定されたモジュールに配置し、名前空間の内容ではなく、名前空間自体を配置します。 \addtogroup は最も内側のスコープ内に配置する必要があります。:

    //! \addtogroup module_example
    //! \{
    
    namespace gmx
    {
    
    //! Function intended to be part of module_example.
    int gmx_function();
    
    }
    

既存のコード

さらに多くの例は、ソースツリー内の既存のコードを参照することで見つけることができます。特に、src/gromacs/analysisdata/ および src/gromacs/options/ サブディレクトリにある新しい C++ コードには、これらのガイドラインに従って記述された大量のコードが含まれています。src/gromacs/selection/ (特に C 互換のコード) にある一部のコメントは、これらのガイドラインの導入以前に記述されているため、最適な例ではありません。