Complete Guide On Using Doxygen To Document C Source Code..!!

As we know Doxygen is a very powerful tool to do documentation, but it’s more geared toward object-oriented languages like C++ and Java. The Doxy wizard, a.k.a. the GUI frontend of Doxygen, has so many options to play with and in this article, I am going to show you how to optimize the settings to wield the full power of Doxygen to document source code written in C.

I have written this article keeping beginners in mind. First, let’s see how Doxygen works, then let’s see how to write Doxygen compatible comments and then proceed to see how to install Doxygen on your computer and how to configure the settings to produce optimized documentation for C code.

If you are already familiar with some sections, feel free to skip them and proceed to the section of interest using the table of contents below.

So let’s begin!

How Doxygen works? Doxygen has some special syntaxes, which you can use in your comments in the code, and when you run this tool, it will parse out the documentation details from comments which follow the special Doxygen syntax.

Doxygen tags and symbols to use in your comments

Doxygen supports several methods for incorporating documentation inside the comments. The 2 simplest methods to include in C source code are

/**

 … comments…

*/

And

/// Comments.

Note the extra asterisk (*) in line 1 of the first option and extra slash symbol(/), i.e. 3 instead of 2 slashes. These syntaxes are used to tell the Doxygen parser that it is documentation and it needs to be extracted.

The above 2 syntaxes must be placed just above an entity so that the Doxygen parser can associate the comments to that particular entity.

What is an entity in Doxygen? An entity can be a global variable, a structure declaration, enum declaration or a function.

Consider the code snippet below

#include <stdio.h>

/// This is a test string
char * hello = "Hello Embedded Inventors!";

/**
 * This is the main function
 * 
*/
int main()
{
    printf("%s \n", hello);
    return 0;
}

Here I have used the 3 slashes syntax to document the global variable and the “/**….*/ syntax to document the function. Putting this code through Doxygen gives me documentation that looks like this.

You may think that these comments look too simple so let’s take a more complex example to see the full power of Doxygen. Have a look at this next code snippet.

/// @file main.c
#include<stdio.h>
 
#define PI       3.1415   ///< Mathematical constant PI.
#define RADIUS_M 7.82     ///< Radius in meters
 
/**
 * Calculates the Area of the circle.
 * Formula: Area = PI*r^2
 * @param[in] radius
 * @param[out] area
 */ 
float calculate_area(float radius)
{
    float area;
    area = PI * radius * radius;
    return area;
}
 
/** 
 * Calculates the Perimeter of the circle.
 * Formula: Perimeter = 2*PI*r
 * @param[in] radius
 * @param[out] perimeter
*/
float calculate_perimeter(float radius)
{
    float perimeter;
    perimeter = 2 * PI * radius;
    return perimeter;
}
 
/**
 * Main entry point of the program.
*/
int main()
{
    float radius, area, perimeter;
    radius = RADIUS_M;
    area = calculate_area(radius);
    perimeter = calculate_perimeter(radius);
    printf("Area = %.2f sq.m \n", area);
    printf("perimeter = %.2f m\n", perimeter);
    return 0;
}

This is a simple program to calculate the area and perimeter using the radius. Now have a look at the documentation produced by this code

It is considered good practice in C to make literal values into macros to enhance the readability and some comments explaining the meaning will make it even better.

The macro documentation looks like the picture above. If you look at the code, you may have noticed that instead of keeping the comments on top of the entity  I have kept it at the right-hand side of the macro definition.

Also instead of “/// “

I have used “///< “

This is another syntax commonly used with Doxygen if we wish to have documentation on the right-hand side of the entity. While writing code in C we often find this need to keep the documentation to the right. This is especially true with macros and structure member documentations.

Next, let’s look at the Function list part of the documentation.

Here as you can see the first line of the comments is placed below the function’s name in the list and it is followed by a “More…”  Link.

If you click on the “more” you will be taken to the detailed description of the function as you can see in the next picture.

Here you can see both the first line and the second line which contains the formula used.

In Doxygen, there are 2 levels of description for an entity

  • Brief description and
  • Detailed description

By tuning the settings of Doxygen (I have explained exactly how to do this in the following sections) you can make Doxygen parser to take the first sentence of the comment to be the brief description and the remaining sentences to be detailed description. Doxygen by default takes this brief description and places it on the list of functions as shown above for easy referencing and it keeps the detailed description for the “More” section of the documentation.

Next, let’s look at the documentation of parameters. Here another special Doxygen syntax is used which is the @ syntax.

Doxygen calls these as structural commands.  There are several of them and the most useful ones for C programmers are the following.

@file The file name must be present in the file header for inclusion into the documentation generation process
@param Parameter documentation for functions
@page Markdown page name
@mainpage Main markdown page for the project
@tableofcontents Generates “table of contents” for the markdown page

The syntax used in the parameter description is the following

@param[in/out] <variable name> <variable description>

Since the variable name radius is obvious to the reader of the code, I did not add the description. Please have a look at my other article When to use and when to avoid comments? for guidelines on commenting.

The syntax used in the parameter description is the following

@param[in/out] <variable name> <variable description>

Since the variable name radius is obvious to the reader of the code, I did not add the description. Please have a look at my other article When to use and when to avoid comments? for guidelines on commenting.

Doxygen pages

Apart from syntaxes and tags mentioned above, Doxygen can also use markdown files to generate HTML webpages as part of your documentation. If you need to provide code snippets, coding standards, architecture information, etc, on your documentation then the best way to do it is via pages or markdown files.

If you don’t understand what markdown files are I recommend you to watch this short youtube video (link) (youtube.com/watch?v=eJojC3lSkwg)

Doxygen classifies our markdown files as 3 hierarchical pages

  • Main page
  • Page and
  • Subpage

And each page can have sections and subsections too.

Main page

Let’s first look at an example of the main page and then we can look at the theory side of things. This is how a project main page should be made in a markdown file.

@mainpage Project title
This is the main page for the project. 
 
1. Describe the project in general and the components/ modules it has
2. Explain each module using data flow and software architecture diagrams
3. Place links for each of the sub module's markdown pages

Once running it through Doxygen the final HTML file will look like this

This is the main page for the project, you can enter the details like requirements, release notes, overall architecture,  etc., in this page. The Doxygen structural command to use is “@mainpage” as shown in the example above. This tag on one of our markdown files will tell the Doxygen parser that a given markdown file is the main page for the project. This is the page shown when you click index.html from the HTML folder generated by Doxygen.

Page

These are the normal pages. These will show in the first level of pages on your left-hand side of the tree view. In a later section of this article, I have shown you how to enable “TreeView”  which I think is better than the default view for C documentation.

The structural command to use for a Doxygen page is @page as shown in the markdown file below

@page module_name
**Author:** Author name
**Date:**  Date
## Module's Role
Explain the module's role in the system in general

After running it through Doxygen the final output will look like this

Subpage

These pages will not be on the first level, rather it will be placed under another page.

The structural command to use for a Doxygen sub-page is @subpage. This @subpage should be used on the module’s page to which the given page is a sub-page to like this.

@page module_name Module Name
@subpage sub_page_name
**Author:** Author name
**Date:**  Date
## Module's Role
Explain the module's role in the system in general

The markdown file for the subpage will look like this

@page sub_page_name Sub module Name
some text here explaining the role of the sub module

As you can see in the above picture, the Doxygen output has added the sub-page “Sub module Name” under the page “Module Name” on the tree-view at the left-hand side and added a link to it on our page.

The sub-page itself is an ordinary page and it looks like as it is shown in the image below.

I generally avoid sections and subsections as it increases the complexity of the documentation process. I like doing them with Markdown formatting options instead (even if that will make it hard to interlink a section with another one). I leave it up to you to decide for yourself if you need them in your particular project or not.

Installation of Doxygen

The installation of Doxygen is as simple as it can get. Just head over to this link and scroll down to the section “Sources and Binaries” and download the version that has support for your particular operating system, be it Linux or Mac or Windows. Then install as you would install any other normal application!



Doxygen Download page

The GUI Interface

Once you have downloaded and installed Doxygen successfully, go ahead and open the GUI Front End of Doxygen, named Doxywizard. The GUI interface on windows looks something like this

As you can see there are 3 tabs named

  • Wizard
  • Expert and
  • Run

Wizard Tab

This tab is made for the beginners of this tool and it has all the basic necessary options to create documentation using Doxygen

The wizard tab has 4 “Topics” or as I like to call it “Sub-Tabs” named

  • Project
  • Mode
  • Output and
  • Diagrams
Wizard->Project

In the above picture, the Project sub-tab is already selected and you get the following 3 options in it

  • Project details: Here you can enter the details such as project heading(Name), sub-heading (Synopsis), project version and project logo
  • Source location: Here you can enter the root directory of your project, in other words the path to your project folder
  • Destination location: Here you can enter the folder in which you want to save the documentation generated by Doxygen.

Be sure to check the Scan recursively button to make Doxygen search all the subfolders too.

If you run Doxygen with the settings above, giving it an empty folder as a source directory, you would get something like this.

As you can see in the above picture, The logo(which I created for this tutorial), the project name, version, and synopsis are shown at the top of the generated HTML.

Keep the Height of the Logo to 100px, to ensure a good fit as Doxygen is not smart enough to resize it for us.

Wizard->Mode

Here you can 2 options

  1. Extraction mode: lets you decide if you want undocumented code to be used for HTML generation or not.
  2. Programming Language: lets you select your programming language, so that Doxygen can use an appropriate template for the documentation generation

I prefer to keep the default for the first option, which is “Documented entities only” as this lets me maintain a less cluttered documentation.  If you select “All entities” then all the functions, global variables, and markdown files, even if they are not documented using the special syntax shown in the first section of this article. But some people prefer to document all entities, as this would point out the functions which are not documented, as an indicator that it needs documentation. I leave it up to you to experiment with both options and decide on one.

Make sure you choose “Optimize for C or PHP output” for the second option as shown above.

Wizard->Output

This tab lets you select the type of output you need. I personally never use Latex so I unchecked that and other than that I have kept the default settings here as shown in the picture below.

Wizard->Diagrams

I have not experimented much with the diagram generation options of Doxygen as most of these are geared towards the object-oriented languages. 

I have tried the call graphs and called by graphs and did not find them very useful.

I personally prefer just the architecture diagrams, which I make myself for my projects so hence I keep the diagrams option to No diagrams as shown below.

Expert Tab

The expert tab contains configuration options that are not available in the “Wizard” tab. Let’s tweak the options in this tab to give us more control over the output, and make it tailored specifically for C source code.

Expert->Project

You don’t need to change much here as all the options that need to be changed have already been while we went through the wizard tab. 2 simple tweaks that can be done in this section is shown in the image below (the red rectangles show the changes made).

The option FULL_PATH_NAMES has been unchecked so that the final output doesn’t include the entire path name like “C:/User/user_name/Desktop?project_directory/sub_directory/file_name“. Instead, we can get the output to start from the root directory of the project itself. In the above case, the output HTML will only show sub_directory/file_name

As we saw above, there are 2 levels of description for any given entity, a brief description, and detailed description. The next option JAVADOC_AUTOBRIEF is checked so that we can separate the brief and detailed description of the entities using a simple period punctuation so that the first sentence is the brief description and all sentences after that are the detailed description part.

/**
 * Calculates the Area of the circle.
 * Formula: Area = PI*r^2
 * @param[in] radius
 * @param[out] area
 */ 
float calculate_area(float radius)
{
    float area;
    area = PI * radius * radius;
    return area;
}

In the code snippet above, the first line “Calculates the Area of the Circle” is the brief description and the “Formula …” is the detailed description.

Expert->Build

In the build tab, you can uncheck the following options

  1. GENERATE_TODOLIST
  2. GENERATE_TESTLIST
  3. GENERATE_BUGLIST
  4. GENERATE_DEPRACEDLIST
  5. SHOW_USED_FILES

The first 4 options mentioned above are pretty self-explanatory. These Todo tests, bugs, and deprecated list don’t belong in the code, rather they should be part of your source code tracking and management tool. 

The last option SHOW_USED_FILES has been unchecked to prevent unnecessary clutter in the documentation. It basically prints a line at the end of pages showing structs the list of files used to generate the documentation. For example, consider the following header file

/// @file main.h
#ifndef MAIN_H_
#define MAIN_H_
/**
 * Stores the calculated parameters of the circle.
 * It stores the area and perimeter of the circle.
*/
struct  circle_params
{
    float area; ///< Area of the circle
    float perimeter; ///< Perimeter of the circle
};
#endif

It has a simple struct definition.

Now adding this file and running it through Doxygen gives an output that looks like this.

Basically we are trying to eliminate this portion of the documentation by unchecking that option. For a simple sample code, it might look okay to have this part, but for a real-word project, the clutter can add up and intrude and actual useful documentation. I suggest you experiment for yourself and find out if you need this portion or not.

Expert->Messages

You don’t need to change anything here. This basically controls the log printed as you run the Doxygen and has nothing to do with the content of the generated HTML.

Expert->Input

This one contains the options to control the files which are being used to generate the documentation. While writing C code, we often find ourselves using libraries from 3rd parties. These libraries usually contain a large number of files and it might add unnecessary clutter to the documentation. If you have folders that you need to exclude from the documentation, then you can add them to the exclude tab as shown below.

Expert->Source Browser

No changes to be made here

Expert->Index

I suggest you disable this ALPHABETICAL_INDEX option or else you will end up with pages like this. I normally remember the modules a particular struct is placed in and not its actual name so I uncheck this option to eliminate documentation like this. You can experiment and figure out for yourself if you need it.

Expert->HTML

Here check DISABLE_INDEX and GENERATE_TREEVIEW options as shown in the image below to get the same user-friendly left-hand side tree-view we have been seeing throughout this article.

Expert->Latex, RTF, Docbook, AutoGen, PerlMod

No changes here.

Expert->Preprocessor

I like unchecking the preprocessing option so that I can see the code as I wrote it and not modified through preprocessing done by Doxygen side so it’s better to uncheck it. Again you can experiment for yourself to see and decide if preprocessing makes better sense to you.

Expert->External

No changes to be made here

Expert->Dot

The diagrams generated by Doxygen are more focussed on object-oriented software and hence you can uncheck the class diagrams. If you want, you can also experiment using “Dot” which is a diagram generator for Doxygen. But I like to keep my diagrams at an architecture level and not at a code level and hence I prefer not to use it.

The Doxyfile

You can download the doxyfile that is generated by following this tutorial through this link and use it on your own projects!

I hope you guys learned something through this post and hope it was useful to you guys.

You can email us or contact us through this link if you have any questions or suggestions.

If you liked the post, feel free to share this post with your friends and colleagues! 

Related Articles

How To Use The Power Of Comments In Your Code The Right Way?

C: Macro Function vs Regular Function vs Inline Functions

Photo of author
Editor
Balaji Gunasekaran
Balaji Gunasekaran is a Senior Software Engineer with a Master of Science degree in Mechatronics and a bachelor’s degree in Electrical and Electronics Engineering. He loves to write about tech and has written more than 300 articles. He has also published the book “Cracking the Embedded Software Engineering Interview”. You can follow him on LinkedIn