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
.
Attempted solutions
- I have tried every combination of
MACRO_EXPANSION
andEXPAND_ONLY_PREDEF
, and exposing the macros toEXPAND_AS_DEFINED
andPREDEFINED
with no success. - I tried setting
so that Doxygen would remove theENABLE_PREPROCESSING = YES PREDEFINED = ifdef __cplusplus=
#if
branches before beginning parsing and evaluation, but this horrible hack is too complicated for my application. - I have tried foregoing Doxygen parsing the macros, and instead trying to document them completely fictitiously as "orphaned" functions - but it doesn't seem to work! Use of
@def
and@fn
require Doxygen eventually encounter the real signature. - One could imagine a variant of
PREDEFINED
likePREDEFINED_IN_TURN
which re-parses the source code for each set of preprocessor values. Then one could use
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 usesENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES SKIP_FUNCTION_MACROS = NO # crucially... PREDEFINED_IN_TURN = __cplusplus=0 __cplusplus=1
#ifdef
over#if
. - a functioning but invasive solution is to refactor the code such
that every
#if/#else
branch is explored when a macro likeDOXYGEN
is defined. This requires removing all#else
clauses:
along with Doxyfile#if defined(__cplusplus) || defined(DOXYGEN) ... #endif #if !defined(__cplusplus) || defined(DOXYGEN) ... #endif
Alas this is a major and unacceptable change to the source-code in my application, and introduces bug vulnerability.ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES SKIP_FUNCTION_MACROS = NO # crucially PREDEFINED = DOXYGEN
Unsatisfying solution
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)
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
.
Attempted solutions
- I have tried every combination of
MACRO_EXPANSION
andEXPAND_ONLY_PREDEF
, and exposing the macros toEXPAND_AS_DEFINED
andPREDEFINED
with no success. - I tried setting
so that Doxygen would remove theENABLE_PREPROCESSING = YES PREDEFINED = ifdef __cplusplus=
#if
branches before beginning parsing and evaluation, but this horrible hack is too complicated for my application. - I have tried foregoing Doxygen parsing the macros, and instead trying to document them completely fictitiously as "orphaned" functions - but it doesn't seem to work! Use of
@def
and@fn
require Doxygen eventually encounter the real signature. - One could imagine a variant of
PREDEFINED
likePREDEFINED_IN_TURN
which re-parses the source code for each set of preprocessor values. Then one could use
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 usesENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES SKIP_FUNCTION_MACROS = NO # crucially... PREDEFINED_IN_TURN = __cplusplus=0 __cplusplus=1
#ifdef
over#if
. - a functioning but invasive solution is to refactor the code such
that every
#if/#else
branch is explored when a macro likeDOXYGEN
is defined. This requires removing all#else
clauses:
along with Doxyfile#if defined(__cplusplus) || defined(DOXYGEN) ... #endif #if !defined(__cplusplus) || defined(DOXYGEN) ... #endif
Alas this is a major and unacceptable change to the source-code in my application, and introduces bug vulnerability.ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES SKIP_FUNCTION_MACROS = NO # crucially PREDEFINED = DOXYGEN
Unsatisfying solution
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)
1 Answer
Reset to default 4One 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