A crash course in inline source code documentation with Doxygen


So I'm sure a number of you out there were a bit skeptical as to whether or not I'd be able to churn out two Doxygen newsletter articles in a row (I sure didn't think I'd manage :). Well, just to spite all of us non-believers, here I am with a shiny new tutorial on documenting your source code with Doxygen. The things I'm going to cover here are just the basic meat-and-potatoes parts of Doxygen that I use on a day to day basis; for anything else, please consult the online Doxygen manual; it's really quite handy :).

Doxygen comments come in two flavors: JavaDoc style or Qt style. Each comment represents a description for some entity in your code (meaning a class, or a function, or a variable, etc.), and there are two types of descriptions: brief and detailed. Each description is optional, but an item may have no more than one of each type of description. Here's what they all look like:

Listing 1:
/// JavaDoc style, brief

/** JavaDoc style, detailed

//! Qt style, brief

/*! Qt style, detailed

Note that unless you set 'JAVADOC_AUTOBRIEF = NO' in your config files (which I always do :), the JavaDoc versions will try to perform some funky magic behind your back and treat the first sentence in a JavaDoc comment up to the first period as the brief description; if you think this is a good thing, just leave your config files alone :)

At any rate, when Doxygen parses through your files, it applies the descriptions in your Doxygen comments to the immediately preceding declaration or definition in the source file. Thus, to document a BagOfPopcorn class with both a brief and a detailed description, one could do something like the following:

Listing 2:
//! A class that simulates a bag of popcorn.
/*! The BagOfPopcorn class should not be confused with the
BucketOfPopcorn class.
class BagOfPopcorn : public PopcornContainer {

"A class that simulates a bag of popcorn." would be applied as the brief description for class BagOfPopcorn, and "The BagOfPopcorn class should not be confused with the BucketOfPopcorn class." would be applied as the detailed description. Depending upon how you configure Doxygen, brief descriptions are generally displayed in pieces of the documentation that list a number of entities to choose from (such as the "Compound List" page or the initial overview of a class' members on the specific class' page), and detailed descriptions are used separately from or combined with the brief description to form the main chunk of documentation for a given entitiy (for the Storage Kit documentation presented last time, detailed description are combined with the brief descriptions).

Now suppose you didn't want to include the Doxygen comments with the given declaration or definition. For example, we've tended to include all Storage Kit documentation in our source files, leaving the headers clean and easy to browse; if there were no other way to document a given entity, we'd be forced to include documentation about a specific class in the header for that class, as the source file contains no documentable declaration or definition for the class as a whole. Fortunately, one can place a Doxygen comment pretty much anywhere and reference it to a specific entity in the following manner:

Listing 3:
/*! \class BagOfPopcorn
\brief A class that simulates a bag of popcorn.

The BagOfPopcorn class should not be confused with the
BucketOfPopcorn class.

Placing this comment somewhere in BagOfPopcorn's source file would have the same effect as placing Listing 2 in the header. The "\class" bit is a Doxygen command that tells Doxygen to apply the comment to the specified class, in this case, class BagOfPopcorn. Similar commands are available for other documentable entities:

  • \namespace documents a namespace.
  • \file documents a file.
  • \struct documents a struct.
  • \enum documents an enumeration type.
  • \fn documents a function.
  • \var documents a variable, or a typedef, or an enum value.
  • \def documents a #define macro.

There are a few others as well, but I've never needed them. Note that the \file command is the only way to document a file. Further, certain things like global functions will only show up in the generated documentation if the file they live in is documented as well.

Another command introduced in Listing 3 is the \brief command. You can use the \brief command inside of a detailed description in lieu of a separate brief comment. The nice thing about the \brief command is that it can span multiple lines, whereas the specific brief comments are restricted to one line; a line of whitespace designates the end of the brief description.

Another useful thing to know is how to document function parameters and return values. The \param command documents a single parameter (thus you use it once for each parameter), and the eturn command documents the return value. So, for example, you could do something like the following (note that the \c command forces the next word into a monospaced font):

Listing 4:
/*! \brief Recites the poem in the given language at the given tempo.

\param language The language in which the poem should be recited.
\param tempo The speed at which the poem should recited.
- \c B_OK: success
- \c B_BAD_POEM: returned if your poem sucks (note that the poem
will not have been recited)
- other error code: failure
Poem::Recite(Language language, Tempo tempo)

You may have noticed the bulleted list looking bit in Listing 4. This part is fun :). Probably my favorite part of Doxygen is making bulleted lists, which, besides making you look way more organized than you really are, is unbelievably easy to do. I'm not even going to bother explaining it, just check out another example:


Listing 5:
/*! \class CardboardBox
\brief A class that simulates a cardboard box.

- Things cardboard boxes are good for
-# Being worn as a helmet
-# Being thrown at strangers
-# Being used as a fort
-# Being used to store popcorn while it is consumed
- Things cardboard boxes are not good for
-# Being used as pillows
-# Being used to transport water

You ought to be able to figure out what it'll generate just by looking at it, but in case you're curious or skeptical, I've prepared a package with a header/source file pair and a ready-to-go Doxygen config file. It contains all the examples given here, plus a few others I haven't mentioned, and I'd highly encourage you to check it out and play with it if you're at all interested. You'll just need to install Doxygen as instructed last time, unzip the example archive, and run 'doxygen example.cfg' from the doxygen-example/ directory. Doxygen should generate output in html, LaTeX, RTF, Man page format, and XML. For those who are curious where the config file came from, I simply ran 'doxygen -g example.cfg' to generate a generic config file, loaded it up into an editor, and filled in the blanks; there are a lot of useful comments in there to help you along.

Hopefully, that should be enough to get you started. If you find yourself wondering what else you can do with Doxygen (there's actually quite a bit more), be sure to browse through the online manual. And keep in mind that HTML tags can be used anywhere in your documentation; Doxygen will automatically convert them to appropriate markup for other output formats if necessary. Have fun!