I am trying to document a header file which has different "overloads" when parsed by C or C++.
#ifdef __cplusplus
/// myfuncA
void myfuncA();
/// MYMACRO_A
#define MYMACRO_A() \
myfuncA();
#else
/// myfuncB
void myfuncB();
/// MYMACRO_B
#define MYMACRO_B() \
myfuncB();
#endif
I want all four of these functions and macros to be collected and individually documented by Doxygen. This is a sensible use-case in my application; these are C and C++ specific overloads to a core function, and the doc will specify which can be called by which language.
Alas, it is proving impossible to make Doxygen simultaneously document all four of them!
When my Doxyfile includes
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
SKIP_FUNCTION_MACROS = NO
then Doxygen will evaluate ifdef __cplusplus to 0 and document only myfuncB and MYMACRO_B.
Alternatively, when I set
ENABLE_PREPROCESSING = NO
then Doxygen will not document any macros at all, and so document only myfuncA and myfuncB.
MACRO_EXPANSION and EXPAND_ONLY_PREDEF, and exposing the macros to EXPAND_AS_DEFINED and PREDEFINED with no success.ENABLE_PREPROCESSING = YES
PREDEFINED = ifdef __cplusplus=
so that Doxygen would remove the #if branches before beginning parsing and evaluation,
but this horrible hack is too complicated for my application.@def and @fn require Doxygen eventually encounter the real signature.PREDEFINED like PREDEFINED_IN_TURN which re-parses the source code for each set of preprocessor values. Then one could use
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
SKIP_FUNCTION_MACROS = NO
# crucially...
PREDEFINED_IN_TURN = __cplusplus=0 __cplusplus=1
but alas, there is no such key (and seems non-trivial to hack). Of course this would not work with my example code immediately which uses #ifdef over #if.#if/#else branch is explored when a macro like
DOXYGEN is defined. This requires removing all #else clauses:
#if defined(__cplusplus) || defined(DOXYGEN)
...
#endif
#if !defined(__cplusplus) || defined(DOXYGEN)
...
#endif
along with Doxyfile
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
SKIP_FUNCTION_MACROS = NO
# crucially
PREDEFINED = DOXYGEN
Alas this is a major and unacceptable change to the source-code in my application, and introduces bug vulnerability.The only workaround I can think up to display all four functions/macros (without major refactor) is to spoof the macros with function signatures that we hide from the compilers (but not doxygen) using #if 0:
#ifdef __cplusplus
/// myfuncA
void myfuncA();
#define MYMACRO_A() \
myfuncA();
#if 0
/// MYMACRO_A
void MYMACRO_A();
#endif
#else
/// myfuncB
void myfuncB();
#define MYMACRO_B() \
myfuncB();
#if 0
/// MYMACRO_B
void MYMACRO_B();
#endif
#endif
The documentation will now include myfuncA, myfuncB, MYMACRO_A and MYMACRO_B but alas the latter two will be listed as functions rather than as macros.
Is this an unsupported use-case? Otherwise, what is a sensible, reliable method to achieve the documenting of all four entities, where the latter two are correctly reported as macros?
(I am using Doxygen 1.13.2 on MacOS)
One way you could do it is to add something like
PREDEFINED = DOXYGEN
to your .dox file, and then change your header files to be more like this:
#if defined(__cplusplus) || defined(DOXYGEN)
/// myfuncA
void myfuncA();
/// MYMACRO_A
#define MYMACRO_A() myfuncA();
#endif
#if !defined(__cplusplus) || defined(DOXYGEN)
/// myfuncB
void myfuncB();
/// MYMACRO_B
#define MYMACRO_B() myfuncB();
#endif
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With