Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doxygen inconsistently expands C macros

Context

I am using doxygen for documentation in a project written in C. In that project there is a lot of repeated code. Since I am limited to the use of pure C (no C++ allowed), I am using macros to reduce repetitions in the source files. In the code generated by the macros I am hoping to include functions and type declarations (they follow a pattern and the actual macros are fairly easy to write). I would really want these generated functions and types to appear in the doxygen documentations, since they are vital for the library API. However, I am struggling to make doxygen correctly expand the macros

Problem

Doxygen doesn't always expand the macros. E.g. in the same line of code, the same function-like macro, called twice, is expanded the first time but not the second.

I feel that the best way to explain this problem is by showing a MRE (you can download it from here)

Example Source File

Consider the following file singlefile.h

/** @file singlefile.h
@defgroup singlefile singlefile.h: Single File Example
Test file
@{
*/

#ifndef _SINGLE_FILE_H
#define _SINGLE_FILE_H

#define _CCONCAT(X, Y) X ## Y
#define _CONCAT(X, Y) _CCONCAT(X, Y)
#define CONCAT(X, Y) _CONCAT(X, Y)

#define MY_TYPE_FULL(MY_TYPE) CONCAT(My, MY_TYPE)
#define MY_TYPEDEF_H(MY_TYPE) typedef struct MY_TYPE_FULL(MY_TYPE) MY_TYPE_FULL(MY_TYPE);

MY_TYPEDEF_H(Account)

#endif

/** @} */

Expected output of the macro call MY_TYPEDEF_H(Account) is the following type declaration

typedef struct MyAccount MyAccount;

This works as expected in a C preprcessor (also verified using https://godbolt.org/), but not in doxygen. The output of the doxygen preprcessor is

Preprocessing /home/<username>/Documents/doxygenmacroexpand/src/singlefile.h...
Preprocessor output (size: 296 bytes):
---------
00001 /** @file singlefile.h
00002 @defgroup singlefile singlefile.h: Single File Example
00003 Test file
00004 @{
00005 */
00006 
00007 
00008 
00009 
00010 #define _CCONCAT(X, Y) 
00011 #define _CONCAT(X, Y) 
00012 #define CONCAT(X, Y) 
00013 
00014 #define MY_TYPE_FULL(MY_TYPE) 
00015 #define MY_TYPEDEF_H(MY_TYPE) 
00016 
00017 typedef struct  MyAccount  MY_TYPE_FULL( Account );
00018 
00019 
00020 
00021 /** @} */
00022 
---------
Macros accessible in this file:
---------
_CCONCAT _CONCAT MY_TYPE_FULL MY_TYPEDEF_H CONCAT 
---------

Accordingly, the HTML documentation has the following type declaration

struct MyAccount    MY_TYPE_FULL (Account)

This results in pure garbage documentation for my actual project, in which I have even more layers of macro calls.

What I find quite bizarre is that the same macro is expanded the first time but not the second.

Doxyfile

I used a fresh Doxyfile generated with doxygen 1.8.17. I set the following tags differently than default

INPUT                  = ./src
OUTPUT_DIRECTORY       = ./doc
MACRO_EXPANSION        = YES
OPTIMIZE_OUTPUT_FOR_C  = YES

This is the directory structure (output of tree)

.
├── Doxyfile
└── src
    └── singlefile.h

Question

How do I make doxygen properly expand all macros?

TL;DR. Some macros in the C source file are expanded by the doxygen preprocessor and some are not, even at the same call depth. This leads to partially generated documentation in the simplest cases and to complete garbage in my real project scenario.

Side note: this is my first posted question here on SO. Usually I find answers that allow me to solve my problems, but not his time. Anyway, I am open to feedback if you have any advice on how I should post a question

like image 482
ChromaticIsobar Avatar asked Jul 02 '21 09:07

ChromaticIsobar


1 Answers

The version 1.8.17 is from December 27, 2019 and exhibits the problem shown. With doxygen version 1.8.18 (April 4, 2020) the problem is gone so it is with the current version 1.9.1. In all these cases I do see

00017 typedef struct  MyAccount   MyAccount ;

The advice is to update to version 1.9.1.

like image 178
albert Avatar answered Sep 21 '22 08:09

albert