Gromacs

Doxygen

    Introduction

    This page documents how Doxygen is currently set up in the Gromacs source tree, as well as guidelines for adding new Doxygen comments. Embedded in the guidelines are hints on what needs to be documented to avoid warnings from Doxygen. The guidelines focus on C++ code and other new code added in 5.0, and documentation of existing code after it has been split into smaller modules from gmxlib and mdlib. Parts of the guidelines are still applicable to documenting older code, in particular the guidelines about formatting the Doxygen comments and the use of \internal.

    The guidelines are still in a somewhat drafting phase.

    Documentation Flavors

    The Gromacs source tree is set up to produce three different levels of Doxygen documentation:

    1. Public API documentation (suffix -user), which includes functions and classes exported from the library and intended for use outside the Gromacs library.
    2. Library API documentation (suffix -lib), which additionally includes functions and classes that are designed to be used from other parts of Gromacs.
    3. Full documentation (suffix -full), which includes (nearly) all (documented) functions and classes in the source tree.

    Each subsequent level of documentation includes all the documentation from the levels above it. The suffixes above refer to the suffixes of Doxygen input and output files, see the next section.

    Currently, it is not clear what are the criteria for classifying a function as being part of a public API. Also, if one is documenting existing code, e.g., from mdlib or gmxlib, the module division is not clear and it may be difficult to decide on which level of the documentation something belongs. At a minimum, please keep anything that is not in an installed header out of the public API documentation. If/when the code from mdlib/gmxlib gets reorganized into more logical modules, these things can be more fully thought out.

    Building the Documentation

    Doxygen is set up only for the master branch.

    If you simply want to see up-to-date documentation, you can go to http://jenkins.gromacs.org/job/Doxygen_Nightly_master/javadoc/? to see the documentation for the master branch. Gerrit also runs Doxygen for all changes submitted to master, and the resulting documentation can be viewed from the link posted by Jenkins. The Doxygen build is marked as unstable if it introduces any new doxygen warnings.

    You may need to build the documentation locally if you want to check the results after adding/modifying a significant amount of comments. This is recommended in particular if you don't have much experience with Doxygen. It's a good idea to build with all the different settings (see below) to see that the result is what you want.

    All files related to Doxygen reside in a doxygen/ subdirectory in the source and build trees. In a freshly checked out source tree, this directory contains Doxyfile-full.cmakein, Doxyfile-user.cmakein and Doxyfile-lib.cmakein. When you run cmake, files Doxyfile-full, Doxyfile-user and Doxyfile-lib are generated at the corresponding location in the build tree. There is also Doxyfile-common.cmakein, which is used to produce Doxyfile-common. This file contains settings that are shared between all the input files.

    You can run Doxygen directly with one of the generated files (all output will be produced under the current working directory), or use make doc-full, make doc-lib or make doc-user (or make doc-all to build all versions). The generated documentation will be contained under html-full/, html-lib/ and/or html-user/. Open doxygen/index.html from the build tree or index.html file from one of the subdirectories to start browsing. Log files with all Doxygen warnings are also produced under doxygen/. In order to see whether there were warnings, you need to check the contents of the file (the log file will be empty if there were no warnings).

    Guidelines for Doxygen Markup in Code

    General things:

    • Use the Qt-style comments (/*! */ and //! instead of /** */ and ///, \brief instead of @brief etc.). The only exception is for single-line brief descriptions in C code (see the next bullet). Example:
    /*! \brief
     * Performs a simple operation.
     *
     * \param[in] value  Input value.
     * \returns   Computed value.
     * \throws    std::bad_alloc if out of memory.
     *
     * Detailed description.
     */
    int function(int value);
    
    • If there is only a brief description, it can be specified with //! Brief description. The text must fit on a single line, otherwise it isn't interpreted as a brief description. For C code, use /** Brief description. */, since MSVC does not like // comments in C. In this case, the brief description must not contain periods except at the end.
    • When adding comments, ensure that a short brief description is produced. For one-liners, use //! or /** */, since /*! Comment. */ does not produce a brief description. Also note that \brief makes the whole following paragraph the brief description, so the paragraph should be short.

    General guidelines for controlling in which flavor of documentation the comments should appear (TODO: the use of \inpublicapi and \inlibraryapi in combination with \ingroup module_MODULENAME needs more consideration):

    • For every entity that is part of the public API, add a \inpublicapi command at the end of the documentation block. For entities that are designed to be used outside their module within the library, but that users would not normally use, put a \inlibraryapi command at the end and \libinternal in the beginning. For intra-module entities, put \internal in the beginning. These commands are redefined in the different configuration files to generate a group containing the public API, and to control whether to generate documentation for the intra-library API. There are also conditional sections called libapi and internal for use with \if and \cond. For top-level entities, add a \ingroup module_MODULENAME at the end (see more instructions about documenting modules at the end). Example:
    /*! [\[lib]internal] \brief
     * Brief description.
     *
     * More details.
     *
     * [\in(public|library)api]
     * \ingroup module_MODULENAME
     */
    class SimpleClass
    • If there is a lot of entities in the same file that should all be added, you can use (should go inside all namespace declarations to work properly):
    /*! \addtopublicapi
     * \{
     */
    
    <declarations>
    
    /*!\}*/
    • There is a similar construct \addtolibraryapi, but that should be used with care, as it can easily add unintended functions to be visible in the public API docs. TODO: figure out how it should be used to not to cause that.

    How to document classes and structs:

    • Document all classes and their methods at the point of declaration (typically in the header file). Implementation-specific comments that don't influence how a method is used should go into the source file, just before the method definition, with an \internal tag in the beginning of the comment block.
    • Classes and structs in header files appear always in Doxygen documentation, even if their enclosing file is not documented. So start the documentation blocks of classes that are not part of the public API with \internal or \libinternal. Classes in anonymous namespaces do not currently appear in the documentation.
    • If a whole class is not documented, this does not currently generate any warning. But if a member of a documented class is not documented, a warning is generated. Guidelines for documenting free functions apply to methods of a class as well.
    • For base classes, the API classification (\inpublicapi/\inlibraryapi) should be based on where the class is meant to be subclassed. The visibility (\internal/\libinternal), in contrast, should reflect the API classification of derived classes such that the base class documentation is always generated together with the derived classes.
    • For classes that are meant to be subclassed and have protected members, the protected members should only appear at the documentation level where the class is meant to be subclassed. E.g., if a class is meant to be subclasses only within a module, the protected members should only appear in the documentation generated from Doxyfile-full, but not from Doxyfile-lib or Doxyfile-user. This can be accomplished using \cond with the defined section names internal and libapi (note that you will need to add the \cond command also to the source files to hide the same methods from Doxygen, otherwise you will get warnings). Notice that \cond does not work properly inside //! comments, at least in Doxygen 1.7.3. Example of what works:
    protected:
        /*! \cond internal */
        
        <declarations>
        
        //! \endcond
    

    How to document free functions (also applies to methods of classes, just replace "enclosing file" with "enclosing class" in the instructions):

    • Location of the documentation should follow that for classes.
    • Free functions do not appear in the Doxygen documentation unless their enclosing file is documented. Note, however, that this does not apply to functions that reside within documented namespaces. So if a function is not within a namespace (mostly applicable to C code) and has the same visibility as its enclosing file, it is not necessary to add a \internal/\libinternal tag. Static functions are currently extracted for the full documentation only. Functions in anonymous namespaces are currently excluded from the documentation.
    • If you want to exclude a function from the documentation, you need to put in inside a \cond block such that Doxygen does not see it. Otherwise, a warning for an undocumented function is generated. You need to enclose both the declaration and the definition by \cond.

    How to document files:

    • In each file, add a comment block that describes the contents of the file right after the copyright notice. Mark the block with the \internal or \libinternal tag if it is not part of the public API. Format the comment block like this:
    /*! [\[lib]internal] \file
     * \brief
     * Brief description of the file.
     *
     * More details on the file if needed.
     *
     * \author Author Name <author.name@email.com>
     * [\in(public|library)api]
     * \ingroup module_MODULENAME
     */
    • Following the logic for base classes, the API classification (\inpublicapi/\inlibraryapi) should be based on where the header is meant to be directly included. The visibility (\internal/\libinternal) should reflect the API classification of any headers that indirectly cause the header to be included. Hence, any installed headers (i.e., headers indirectly included by public API headers) should not have a \internal/\libinternal specifier.
    • All source and test files should be documented with \internal in the beginning.
    • When you make significant modifications to a file, you should add an \author line for yourself.

    Documenting modules:

    • For each module, decide on a header file that is the most important one for that module (TODO: It may be better to designate, e.g., module-doc.h for this purpose if there is no self-evident header). In that header, add a documentation block like this (replace NAME with the directory name of the module, and group_utilitymodules with the proper group for the module):
    /*! \defgroup module_NAME Title of the module
     * \ingroup group_utilitymodules
     * \brief
     * Brief description of the module.
     *
     * Detailed description of the purpose and API of the module.
     * Should link to the header files and the most important functions/classes
     * in the module.
     *
     * \author Author Name <author.name@email.com>
     */
    • For all compound entities (in Doxygen terminology: classes, files, namespaces) that belong to the module, add a \ingroup module_NAME to the end of the documentation block. This can't be done for functions, typedefs or enums that are part of the public API, because these can only belong to one group.

    Examples

    For C++ code, there are ample examples of documentation following these guidelines in the source tree. Please see, e.g., src/gromacs/analysisdata/ or src/gromacs/options/ subdirectories. Some comments in src/gromacs/selection/ (in particular, any C-like code) predate the introduction of these guidelines, so those are not the best examples.

    TODO: Add some examples here as well, in particular for constructs other than C++ classes.

    Page last modified 08:48, 29 Jul 2012 by tmurtola