Doxygen Cheatsheet

This is my personal Doxygen cheatsheet: Its initial (and primary) purpose is to be a compact help on this topic for myself.

It’s not meant as a general introduction or comprehensive reference for this tool, but it is meant to be a small knowledge base or collection of basics & “gotchas”, often-used commands, snippets, tips, and instructions on how to do certain tasks.


First steps

  1. Download and install Doxygen.

  2. Create a configuration file: doxygen -g [<ConfigFilename>]
    The filename is optional; if omitted, the default name Doxyfile will be used.
    The configuration file can be customized, see below.

  3. Generate the documentation: doxygen [<ConfigFilename>]
    The filename is optional; if omitted, the default name Doxyfile will be used.
    Assumes that the source code has been prepared, see below.


Configuration

I use a customized input file (Doxyfile.in), that file relies on a CMake build process to replace some variables/placeholders (which is automatically done in my standard setup).

Details in the manual.

Build quiet/silent

If you don’t want all the “noise” on the command line output:

QUIET = YES

Input

Doxygen needs to know, which files and directories it should investigate:

INPUT             = <repo>/ReadMe.md <repo>/src/ ...
RECURSIVE         = YES
GENERATE_TREEVIEW = YES

Related:

The EXCLUDE tag can be used to specify files and/or directories that should be excluded from the INPUT source files.

Or better:

If the value of the INPUT tag contains directories, you can use the EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude certain files from those directories.


Documenting the Source Code

First off, I actually use this mainly as a broad guideline/orientation on how to write and structure comments in the source code itself, for myself; the fact that Doxygen can “additionally” generate nice looking documentation in multiple other output formats is currently just a nice bonus 😄

By the way: My comment style has been heavily inspired by Powershell’s comment-based help over the last couple of years. It doesn’t fit C++ or Doxygen 100%, but it’s a good orientation mark for me.

Tip: Since Doxygen 1.8.0 Markdown can be used as a plain text formatting syntax in the source code comments as well as in custom pages (see below); its by default enabled in the Doxyfile.

Tip: Use \n to force a new line in the generated HTML output.

Special comment block (before)

A special comment block marks the comment therein for Doxygen.

There are multiple ways to denote blocks and commands; I prefer the “Qt style”, using the exclamation mark (!) and at sign (@):

/*!
    Text for doxygen...
*/

//!
//! At least two lines are required for this version to work!
//!

Important: If you have very simple source code file (where Doxygen can’t detect things automatically), there needs to be at least one special comment block (see below) with a @file command in it. Otherwise, Doxygen won’t pick up this file at all and global stuff in it (like functions, variables, etc.) won’t show up in the generated pages!

/*!
    @file
    
    @authors Name 1, Name 2
    
    @copyright © 2025 Name (address@example.net)
    
    @license SPDX-License-Identifier: ...-... (see LICENSE.txt).
*/

Within a special comment block, a Doxygen section is marked (tagged) with either @sectionname or \sectionname commands (I prefer the @ symbol).

A few things also work automatically, without these tags (e.g. a brief line or details), if the configuration fits; see the Doxygen docu for more – but I usually prefer to make it distinctively clear (with a command/tag), what the section/paragraph is about.

Normally a section is valid until a blank line or the start of another section is encountered; but there are also exceptions to the first rule (blank line); the @details section for example can consist of multiple paragraphs (that are separated by a blank line, see below).

Same-line comments (after members)

Same-line Doxygen comments (also known as “documentation after members”) can also be used.
As usual, multiple ways/styles are possible; applying the Qt-Style (!<) is just one way.

int a; //!< This comment is for this line item.
int b; /*!< Another documentation after a member. */

These “same-line” blocks can only be used to document members and parameters; they cannot be used to document files, classes, unions, structs, groups, namespaces, macros or enums!

Commands

The essentials

This is a small excerpt that includes a lot of the standard keywords and structure that I would use to comment a function (template), for example:

/*!
    @brief (or @short)
    A short abstract/summary (one line) of the content/functionality of this item (file, function or class, etc.)
    
    @details
    A more extensive description.
    
    Can consist of multiple paragraphs.
    
    @authors Names of the authors (on a single line!)
    
    @author Name 1 (Multiple entries will be combined
    @author Name 2  as separate lines under one heading)
    
    @param         P      Describes the parameter named "P".
    @tparam        T      Describes a template parameter named "T".
    
    @param [in]    PI
    Describes an input parameter with the name "PI".
    
    @param [out]   PO
    Describes an output parameter with the name "PO".
    
    @param[in,out] PIO
    Describes an input/output parameter with the name "PIO".
    
    A note on lengthy parameter description:
    Tested and failed; found https://developer.lsst.io/cpp/api-docs.html#cpp-doxygen-parameters>:
    > Doxygen will not properly parse parameter descriptions that have multiple paragraphs.
    > If your function's input requires a lengthy explanation, put the explanation in the Notes
    > and refer to it from the parameter descriptions.
    
    @return (or @returns or @result)
    The description of what will be returned (by a function)/what will be the result (of a function).
    
    @retval <return value>
    The description of the returned value.
    
    @throws (or @throw or @exception) <exception-object>
    A text that desecribes the thrown exception more...
*/

Other, often used commands and tags

Special parapgraphs

Command Description
@attention manual
@warning manual
@bug manual
@fixme A custom alias in my Doxyfile
@deprecated manual
@important manual
@note manual
@remark manual
@todo manual

Authorship, dates, versions

Command Description
@version
@date
@copyright
@license Custom aliases in my Doxyfile, based on this GitHub Gist
Examples for the license command/alias:
/*!
    @license Licensed under the Xyz License (see LICENSE.txt).
        
    @license{The Xyz License}
    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted.
        
    @licenseblock
    Licensed under the Xyz License.
        
    ... block with multiple paragraphs...
    @endlicenseblock
        
    @licenseblock{The Xyz License}
    Permission is hereby granted, free of charge, to any person obtaining a copy

    ... block with multiple paragraphs...
    @endlicenseblock
*/

Other

Command Description
@test Text describing a test case.
@see A “see also” note; cross-references to classes, functions, methods, variables, files or URL…

More:

Command Description
@struct to document a structure.
@union to document an union.
@enum to document an enumeration type.
@fn to document a function.
@var to document a variable or typedef or enum value.
@def to document a pre-processor definition.
@typedef to document a type definition.
@file to document a file.
@namespace to document a namespace (e.g. @namespace NiftyOddity::Toolkit::CLI::Utilities)
Note on @namespace:
Doxygen 1.9.3 makes a difference between C++17 nested namespaces “with spaces/without spaces” and build two different hierarchies (with the same display name) – weird stuff:
/*!
    @namespace NiftyOddity::Toolkit::CastConvert
    ...
    
    @namespace NiftyOddity :: Toolkit :: CastConvert
    ...
*/
namespace NiftyOddity::Toolkit::CastConvert { /*...*/ }
namespace NiftyOddity :: Toolkit :: CastConvert { /*...*/ }

Common features of all the above:

Mark a (small) code snippet:

/*!
    @code
        // Some short code excerpt:
        int a = func(3,0,5);
    @endcode
*/

For internal use only

/*!
    @internal
        Some internal comment that should not appear in the generated (public) documentation
        ... unless INTERNAL_DOCS is set to YES in the Doxyfile! (The default is NO)
    @endinternal
*/

Including an example

/*!
    @example <filename>
*/

But this works a bit different then what I first assumed:

Lists

Tip: Better not use asterisks (*) for lists, they may get removed (see the entry in the manual)

/*!
    Unordered & nested:
    - item 1
      - item 1.a
    - item 2

    Ordered (& multiline):
    1. item 1\n
       Continued...
    2. item 2

    Checklist:
    - [ ] Unchecked
    - [x] Checked
*/

Tables

Tables can be included in either in HTML format (verbose/distracting) or in the simpler Markdown syntax:

/*!
    Column 1 Header  | Column 2 Header
    ---------------- | -------------
    Cell Content     | Cell Content
    Cell Content     | Cell Content
*/

Don’t repeat yourself, use @copy*

If in doubt that Doxygen will use the correct item, be specific:
Full namespace, no return value, no parameters, parantheses without space!
Example: @copydoc NamespaceOrClass1::NamespaceOrClass2::function_name()

Example
If in the Doxyfile, two input directories have been set up, then Doxygen knows where to look stuff up:
  • C:\devel\git\TheNiftyOddityToolkit\
  • C:\devel\git\TheNiftyOddityToolkit\src\
@copybrief KeyboardLED.h             --> A file with that name only exists once (for Doxygen).
@copybrief KeyboardLED/KeyboardLED.h --> Specifycing a (relative/partial) path also works.
                       |
                       +--> Means file C:\devel\git\TheNiftyOddityToolkit\src\KeyboardLED\KeyboardLED.h

Pages

Additional Documentation (that is not directly related to one specific class, file or member) can also be included as custom pages.

Supported file extensions for these are .dox, .txt or .md.
Weirdly though, Doxygen will treat *.dox or *.txt files as C/C++ source code, but *.md files as Markdown.

By default Doxygen won’t know about these files; use INPUT (see above) to point it.

If you specify the src directory there and enable recursion, then other *.md files in its subdirectories (e.g. a directory-specific ReadMe.me) will also be picked up by Doxygen (but the name in the filelist/filetree will not be like the Markdown heading!).

Main page (index page)

This command in a special comment block marks it as custom content for the main/index page:

/*!
    @mainpage The Title
    ...
*/

But instead of this, I usually specify in my Doxyfile the repository’s top-level ReadMe markdown file as its main page (note that *_REPO_ROOT_DIR is a custom variable in my CMakeLists.txt):

USE_MDFILE_AS_MAINPAGE = ${${CMAKE_PROJECT_NAME}_REPO_ROOT_DIR}/ReadMe.md

Custom Pages

/*!
    @page page1 A documentation page
    
    Leading text.
    
    @tableofcontents
    
    @section sec An example section
    
    This page contains the subsections @ref subsection1 and @ref subsection2.
    For more info see page @ref page2.
    
    @subsection subsection1 The first subsection
    
    Text.
    
    @subsection subsection2 The second subsection
    
    More text.
    
    @subsubsection subsection2 A subsection to a subsection
    
    Text for the sub-subsection.
*/

/*!
    @page page2 Another page
  
    Even more info.
*/

Customization (output format, layout & style)

Disclaimer: Doxygen can output, directly or indirectly, several formats; at the moment, I’m only interested in the generated HTML output!

The default layout and colors of generated Doxygen documentation looks a bit, hmmm, “functional” or “expedient”: It’s not bad, but the look and feel can seem a bit dull and dated…

But fear not, there are ways the change (customize) the layout and style: https://www.doxygen.nl/manual/customize.html

–> TODO


Further reading