The Linux Page

Doxygen does not generate documentation for my C functions (or any global function)

As I write programs, mainly in C++, I document them using the Doxygen tool. This is a very powerful parser that is capable of finding functions, variables, macros, and many other things in the source code and attach the corresponding documentation to those functions, variables, macros, etc.

This is extremly practical when creating large projects or libraries that you want to share with others.

One problem though, by default it seems like global functions (and thus C functions) and variables do not make it to the documentation, when C++ classes work fine.

Here are two potential issues in that regard:

EXTRACT_ALL

The EXTRACT_ALL flag is set to NO. This is the default and it is expected to remain set to NO. By setting the flag to YES you already get many more definitions in your output but still not everything.

However, setting this to YES has some side effects that are often unwanted. Especially, it does prevent Doxygen from emitting warnings about undocumented parts of your code. It makes it much harder to make sure you are documentation complete. Therefore I suggest you instead use the following trick.

@file

Files are considered private by default. This means files that do not have the @file declaration (or \file) are ignored and not included in your Doxygen output, except for members of C++ classes.

Yes! It is that simple. Edit your C/C++ files, go anywhere you want, and add @file in a comment, probably with a @brief description too:

@file
@brief This file is marvelous.

Note that the @file accepts the name of the file as a parameter, but since it defaults to the expected name of the file you're documenting, it is not required.

Although it is possible to define all your files in one single documentation file. Obviously, in that case the filename is required.

One other reason is when you generate a file from another. To place the documentation in the generated file, but reference the source, using the source filename is useful:

@file source.file
@brief blah blah blah...

This way you'll finally get everything as Doxygen will not skip the documentation you wrote for your C files and any C++ global funtion, variable, etc. It is also not a bad idea to indicate what a file is about and instead of putting that info in a standalone comment at the top or bottom, using the @file makes it readily available to your docs as well!

Note that the \enum <name> also used to work. In 1.9.x, it is not possible to define the enumeration documentation in anywhere other than just before the enum declaration, in your header:

/** \brief This enum is fantastic
 *
 * Some more details here...
 */
enum fantastic_t { A, B, C };

I tried many things talked about on stackoverflow, but nothing worked other than what is shown above. I think this is sad. It should still be working. It used to work in older versions. Note that even setting the EXTRACT_ALL to true does not help with this one. If not declared as shown above, it's not making it to the documentation. Period.

No name namespace

When you create a set of private declarations, variables, functions, classes, etc. in an unnamed namespace, you actually get a form of special namespace which Doxygen still has a hard time with.

The C++ compiler often show you errors with something like this:

n1::<no-name-namespace>::n2::varname

where the <no-name-namespace> is your unnamed namespace in that one file.

The Doxygen parser is not currently doing that. Their issue (I think) is that they can't add a namespace because if the search mechanism they are using to find the various variables, classes, etc. found in the unnamed namespace.

In any event, to fix this issue, I've used a Doxygen Trick:

  1. Make sure you have a DOXYGEN predefined and expand the no_name macro
PREDEFINED             = DOXYGEN=1
EXPAND_AS_DEFINED      = no_name
  1. In my projects, I create a doxygen.h header file with:
#ifdef DOXYGEN
#define no_name doxygen
#else
#define no_name
#endif
  1. In each file with an unnamed namespace
namespace no_name
{
... private definitions ...
}

What this means is: if we are running Doxygen, use the name "doxygen" for all those unnamed namespaces, otherwise use nothing (i.e. then it's really an unamed namespace).

Of course, this is wrong as far as C++ is concerned since that would mean that the declarations in those paragraphs would be visible in the entire software. That's exactly what helps Doxygen. Now, of course, if you have definition using the same names in separate files, Doxygen is likely to make mistakes and choose the first definition it found instead of the one in the same file. However, 99% of the time, this is a lot better than not having proper support for unnamed namespaces in your documentation.

LaTeX

I ran in some issues with the latest version of Doxygen when trying to get my LaTeX expressions to work. There were several issues:

The New Way (no $ or $$)

Somehow the support for $<exr>$ and $$<display express>$$ vanished. Maybe there is a flag that is false by default. However, reading the Doxygen documentation, it seems that these were removed and only the \f are supported.

There are two \f$ to start and stop an inline equation and also \f[ and \f] to display a large equation as a paragraph of its own. Up to here, that was not too complicated to find. Once I converted my documentation, it just failed generating the documentation altogether. Hmm...

Equation Too Large

Two of my equations did not fit the width of the page. In most likelihood, you should break such equations in multiple equations (simplify!) In my case, though, I could do two things:

Solution 1. Use \small

In one case, I could simply add the \small command at the top and the whole thing shrank sufficiently to fit in the page. That was easy!

Solution 2. Use \begin{aligned} and \end{aligned}

I had another case where the equation was just too wide. That is, even using \small (or even \tiny) did not help sufficiently. More of the equation fit, but there was still too much to the right side. Unfortunate... Well, maybe not. I instead decided to break the equation on multiple lines. This is done with the align feature and the & character.

This means encapsulating the whole equation inside the begin/end aligned (notice the past tense) and then adding an & before the = and each + (I had three 4x4 matrices). To force having a newline added, I used the \\ character sequence before a newline and the next matrix and the & before the + operator. Simplified, it looks like this:

\f[
\begin{aligned}
M & = A
  \\
  & + B
  \\
  & + C
\end{aligned}
\f]

Important Note: I put the \\ on its own line because on the same line as the \end{bmatrix} it doesn't work.

Here is the resulting PNG image:

\frac instead of \over

I've learned that although \over generally works, it's more complicated to use properly so it is most of the time safer touse \frac.

lhs \over rhs

becomes:

\frac{lhs}{rhs}

I actually ran in a problem with \over where the closing parenthesis would appear before the right hand side (rhs) in newer versions.

Re: Doxygen does not generate documentation for my C ...

Thank you! Very helpful

Re: Doxygen does not generate documentation for my C ...

This really helped, thanks!

Re: Doxygen does not generate documentation for my C ...

Yes... Really difficult to find such a trick! I noticed just yesterday that a C++ library would not make it at all until I had at least one @file, then most everything started happening. Very strange!

Re: Doxygen does not generate documentation for my C ...

Thank you!! I can't believe they didn't add this in the Doxygen tutorial.