Doxygen conditional compilation does not produce documentation - doxygen

I'm a relative beginner with doxygen, and am documenting a C program
Part of the code is:
\#include "options.h"
// options.h contains
\#define VAL0 0 // Possible values for PARAM
\#define VAL1 1
\#define PARAM VAL0
// Here's the conditional compilation
\#if (PARAM == VAL0)
// code chunk, which doesn't get compiled by Doxygen
\#endif
The code compiles with GCC as expected, but I get no Doxygen documentation
OK, Doxygen doesn't expand macros, so I tried:
\#define SYMEQ(A, B) (A == B) ? 1 : 0
\#if SYMEQ(PARAM, VAL0)
// code chunk
\#endif
Set the Doxygen:
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
No Predefined macros
EXPAND_AS_DEFINED = SYMEQ
No doxygen output from the conditional part, just up to it
I also tried EXPAND_AS_DEFINED SYMEQ(A, B)
Also no luck
I found a few examples with simple names, then #ifdef NAME \code #endif, but none with macro functions

I just had the problem #ifdef CONDITION \code not compiled by doxygen\ #endif and fixed it by brute force, i.e, appending the conditions to the setting PREDEFINED=CONDITION1 CONDITION2 ... manually.
I tried the header file solution -- generate a file with conditions and include it by setting SEARCH_INCLUDES, INCLUDE_PATH and INCLUDE_FILE_PATTERNS -- but it did not work. From the doxygen manual, I think it requires to explicitly #include "the condition file" in the source files, which means to modify the source code, so I give up.
SEARCH_INCLUDES:
If the SEARCH_INCLUDES tag is set to YES (the default) the includes files in the INCLUDE_PATH (see below) will be searched if a #include is found.

MACRO_EXPANSION and EXPAND_ONLY_PREDEF only control whether a macro will be expanded in your code, not how it will be evaluated in conditional preprocessor blocks. For example, if you had code like:
#define RET_TYPE int
/**
* Some function
*/
RET_TYPE func(void);
With MACRO_EXPANSION=NO, this will be documented by doxygen as RET_TYPE func(void), the macro isn't expanded. With MACRO_EXPANSION=YES, this will be documented as int func(void), the macro is expanded and the resulting signature is documented.
To control conditional code, you'll want to focus on the ENABLE_PREPROCESSING. If this option is set to NO, conditional code will be ignored, and all code within the condition will be documented. If it is set to YES, the conditional code will be evaluated, and only blocks for which the condition matches will be documented. In this case, you'll need to make sure that all of the values being evaluated are defined correctly, this can be accomplished by allowing doxygen to evaluate include files (see SEARCH_INCLUDES, INCLUDE_PATH and INCLUDE_FILE_PATTERNS options), or by predefining the macros to have a particular value (see PREDEFINED).

Related

Document macro without expansion

In my C project which I'm documenting using doxygen 1.9.1, I've got several documented macros such as
/**
* #brief Does a thing.
*/
#define DO_THING() someFunc(1, 2, 3)
When I generate the documentation, DO_THING is listed but it shows the expansion (i.e., someFunc(1, 2, 3)). Is there any way to have doxygen hide the expansion? I'd like my macros to be opaque to my users. That is, I'd like them to only know, "There's a macro called DO_THING() and it does a thing."
Doxygen has the possibility to set the maximum number of initializer lines by means of the setting: MAX_INITIALIZER_LINES
MAX_INITIALIZER_LINES
The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the initial value of a variable or macro / define can have for it to appear in the documentation. If the initializer consists of more lines than specified here it will be hidden. Use a value of 0 to hide initializers completely. The appearance of the value of individual variables and macros / defines can be controlled using \showinitializer or \hideinitializer command in the documentation regardless of this setting.
and has the command \hideinitializer
\hideinitializer
By default the value of a define and the initializer of a variable are displayed unless they are longer than 30 lines. By putting this command in a comment block of a define or variable, the initializer is always hidden. The maximum number of initialization lines can be changed by means of the configuration parameter MAX_INITIALIZER_LINES, the default value is 30.
So you can solve your problem by either setting
MAX_INITIALIZER_LINES to `0 though this is valid for all initialized values
for the relevant parts the \hideinitializer

Include both #ifdef and #else code in doxygen output

If have code in the following format:
#ifdef MY_DEFINE
///some doxy comment
#else
///other doxy comment
#endif
MY_DEFINE is defined at compile time. My issue is that when doxy processes the code above, only "other doxy comment" is handled. Defining MY_DEFINE in the doxyfile makes it so "some doxy comment" is handled. I need both doxy comments to make it into the doxygen output.
Is there a simple catch all configuration I can add to the doxyfile?
The doxygen generation needs to be run on different machines, so something not needing additional installation is preferred. There are other #define statements which need to be handled by doxygen, so setting ENABLE_PREPROCESSING to NO is not enough.
Thanks!
You can set ENABLE_PREPROCESSING=YES, then add a predefined symbol PREDEFINED=DOXYGEN
Then you can:
#if defined(MY_DEFINE) || defined(DOXYGEN)
/// if defined
#endif
#if !defined(MY_DEFINE) || defined(DOXYGEN)
/// if not defined
#endif
The drawback is that you cannot use #else. Also Doxygen gets confused if the same symbol is defined to be two different things on different preprocessor settings.
If you disable ENABLE_PREPROCESSING you cannot document #define's in your headers.

Concatenating an expanded macro and a word using the Fortran preprocessor

I'm trying to concatenate a word in the source code with the expansion of a preprocessor macro. Basically I have foo somewhere in the code, and with a #define EXPANSION bar I want to obtain foobar. However, I'm struggling to find a way to do this, which works with all compilers. For the moment I would be happy if it works with gfortran and ifort.
According to its documentation, the gfortran preprocessor is a C preprocessor running in "traditional mode", which does not have the ## token paste operator. However, the same effect can be obtained with an empty C-style /**/ comment. The ifort preprocessor seems to behave more like the normal C preprocessor, so normal token pasting does the trick in ifort. Unfortunately the empty /**/ comment does not work in ifort, as the comment is replaced by a single space instead.
Here is a little example:
#define EXPANSION bar
#define CAT(x,y) PASTE(x,y)
#define PASTE(x,y) x ## y
foo/**/EXPANSION
CAT(foo,EXPANSION)
For which gfortran produces:
foobar
foo ## bar
While ifort gives me:
foo bar
foobar
Of course I could choose the right way by checking the predefined macros for both compilers:
#ifdef __GFORTRAN__
foo/**/EXPANSION
#else
CAT(foo,EXPANSION)
#endif
This works for both of them, but it's rather ugly to have the preprocessor conditional for every expansion. I would much rather avoid this and have some macro magic only once in the beginning.
I have seen this answer to another question, which would probably allow me to work around this issue, but I would rather find a solution that does not invoke the preprocessor separately.
I'm not too familiar with the C preprocessor. Maybe there is a simple way to do what I want. Any ideas?
EDIT: I've already tried something like this:
#define EXPANSION bar
#define CAT(x,y) PASTE(x,y)
#ifdef __GFORTRAN__
#define PASTE(x,y) x/**/y
#else
#define PASTE(x,y) x ## y
#endif
CAT(foo,EXPANSION)
Unfortunately this does not work in gfortran where it produces fooEXPANSION. I'm not entirely sure how this works, but apparently the expansion of the CAT macro prevents the expansion of EXPANSION in the same line. I suspect that this is a feature of the "traditional" C preprocessor ...
I have done some research and it seems that basically most Fortran compilers (i.e. Intel and PGI) use a relatively normal C-preprocessor with a token pasting operator. We only need a special treatment for gfortran, which uses a C preprocessor in traditional mode without a token pasting operator.
Thanks to an entry on c-faq.com I found this definition of a CAT macro that works with all compilers I tested so far:
#ifdef __GFORTRAN__
#define PASTE(a) a
#define CAT(a,b) PASTE(a)b
#else
#define PASTE(a) a ## b
#define CAT(a,b) PASTE(a,b)
#endif
Another solution (that still uses the /**/ trick) was posted by Jonathan Leffler in this answer to a related question.

Systemverilog: scope of text substitution macro

I read that text substitution macros have global scope in 'verilog'. How does SystemVerilog work? I want to use 2 different definitions of the same text macro in 2 different SystemVerilog files - is that OK to do?
In SystemVerilog, macro definitions are limited to the compilation-unit scope but what that is depends on the tool configuration. From the specification:
The exact mechanism for defining which files constitute a compilation
unit is tool-specific. However, compliant tools shall provide use
models that allow both of the following cases:
a) All files on a given compilation command line make a single
compilation unit (in which case the declarations within those files
are accessible following normal visibility rules throughout the
entire set of files).
b) Each file is a separate compilation unit (in which case the
declarations in each compilation-unit scope are accessible only
within its corresponding file).
Therefore if you use multiple-file compilation units (-mfcu for Modelsim), there will be collisions since the macro namespace will have global scope. However the specification explicitly allows redefinitions so you may not get an error(or warning) in this case, unless your tool supports it.
The text macro name space is global within the compilation unit.
Because text macro names are introduced and used with a leading ‘
character, they remain unambiguous with any other name space. The text
macro names are defined in the linear order of appearance in the set
of input files that make up the compilation unit. Subsequent
definitions of the same name override the previous definitions for the
balance of the input files.
Depending on how you are using macros, you may want to consider using parameters instead. Parameters are essentially constants that are more limited in scope than preprocessor directives. They can also be used to selectively instance code using generate constructs.
You can get the SV specification here for free.
If the desired macro have simuliar structure/format, then you can use macro with arguments. See IEEE1800-2012 Section 22.5.1.
`define myMacro(arg1,arg2) \
prefix_``arg1 = arg2``_postfix
If the desired macro definition is exclusively in its respected file and unique, then you can do the following. All other files will not have an `mymacro that can be called. `undef is from Verilog, IEEE1364-1995 Section 16.3.2, and has been in included into SystemVerilog. You can read more about `undef in the latest revision; IEEE1800-2012 Section 22.5.2.
file1.sv:
`define mymacro abcd
/* SystemVerilog code */
`undef mymacro
file2.sv:
`define mymacro wxyz
/* SystemVerilog code */
`undef mymacro

Is there a way to replace an already defined preprocessor identifier?

I have a library that has several options defined as this:
#define shouldShowToolbar YES
#define shouldAlignToLeft YES
etc..
and I'm looking for a way to actually replace those from outside (without modifying the library, because the future updates will break it). Is it possible, or am I doomed to change the library source code (which I do have) every time an update comes out.
There is #undef
#include "library_header.h" /* Which defines the macro. */
#undef shouldShowToolbar /* You undef it. */
#define shouldShowToolbar NO /* If you want, you can redefine it. */
http://gcc.gnu.org/onlinedocs/cpp/Undefining-and-Redefining-Macros.html
If you don't want a particular macro to take effect for a section of code and you know that macro name too, you can use
#undef shouldShowToolbar
/* Your code */
#define shouldShowToolbar
This wont totally undef the macro, cos you never know which part of your code might actually want it
These are values that are hardcoded at compile time. If you compile the library with your project then you should be able to redefine them in a file that compiles later in the compile list, I think there is a special keyword for it. Otherwise it is like saying I want to replace YES in the library.
As far as i know, preprocessor directives executes before compilation. So after that, there's no chance to change something.