This issue is due to doxygen parsing constraints. I am using doxygen 1.8.11 with Eclox (the eclipse plugin) in Kinetis Design Studio for embedded C development.
Almost all of the doxygen compiling works, except I need to have a few very large static arrays. I didn't want to clutter up the main code, so I used a hack I found on these forums (https://stackoverflow.com/a/4645515/6776259):
static const float Large_Array[2000] = {
#include "Comma_Delimited_Text_File.txt"
};
Unfortunately, that hack is causing the compile of my main.c main_module group to fail. With the following error:
warning: end of file while inside a group
I've tried excluding those constants from my main_module group with something like the following:
/*!
** #addtogroup main_module
** #{
*/
...
... header code ...
...
/*!
** #}
*/
static const float Large_Array[2000] = {
#include "Comma_Delimited_Text_File.txt"
};
/*!
** #addtogroup main_module
** #{
*/
...
More code, definitions, etc.
None of this is generated in the doxygen compile...?
/*!
** #}
*/
This gets rid of the doxygen compiling error, but the compiled doxygen documentation does not include anything after the Large_Array declaration. So it seems the second #addtogroup statement is not working.
Am I missing something simple? Any help is appreciated. Thank you.
If Comma_Delimited_Text_File.txt doesn't have trailing linebreak, then try adding one.
Doxygen gets confused if include file doesn't end with linebreak. This can break the document generation for other files too, even when they don't seem related. Often this results in missing symbols and broken callgraphs.
Related
I'm doing some compile works recently.
After updated openssl1.1.1f to openssl1.1.1h, I met some compile errors for packages using the openssl headers "bio.h" and "evp.h".
That's because openssl1.1.1h add something like this:
/*
* name is cast to lose const, but might be better to route through a
* function so we can do it safely
*/
#ifdef CONST_STRICT
/*
* If you are wondering why this isn't defined, its because CONST_STRICT is
* purely a compile-time kludge to allow const to be checked.
*/
int BIO_read_filename(BIO *b, const char *name);
# else
# define BIO_read_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \
BIO_CLOSE|BIO_FP_READ,(char *)(name))
# endif
If the CONST_STRICT marco is defined, you have to implement the api yourself otherwise you will get an undefined reference error during linkage phase.
I wonder what compile option I have to add to make the CONST_STRICT marco NOT defined?
Thanks in advance!
I miss-understood what the comment in the openssl header file means, thanks to Guillaume Petitjean who corrected me.
The error I got is due to other cause. One of my packages has an older version of openssl in it, and it installed it's header files after it's being built. In that version the api BIO_read_filename was not implemented by marco definition but in a source file. I modified the makefile of the package to not install the older openssl header file and the error are gone.
./theheader.h:349: Error: Syntax error in input(3).
Offending line:
string read_gdbm(GDBM_FILE dbf, string key_str, bool show_err = gbls.verbose);
Any ideas?
Typically, a syntax error in SWIG means that it can't understand the line in question (which can be annoying, because the line numbers don't follow macros such as %defines). So I suggest you check that string (should it be std::string? has it been defined?), GDBM_FILE (has it been defined? should it be in a namespace?) and maybe gbls.verbose (has it been defined?) make sense to SWIG. It may help to run swig with the -E option (be sure to redirect the stdout), find the corresponding line and search backward for each type involved. You may need to add some #includes.
Also check the previous line, to ensure you're not missing a semicolon, or something like that.
As a side note, I've run into the same issue for different reasons: I was trying to use a vector < vector < double >>. Now the ">>" character sequence mustn't be used with templates according to the C++99 standard, hence the swig error message popped up. The solution was to simply add an extra space to separate them.
I hit a similar error. I'll clarify my process, hope it can be helpful.
lib.i:
...
%begin %{
#include "header1.h"
%}
...
%include "header1.h"
header1.h:
19 typedef struct T {
...
23 } PACKED TlvHdr;
The error message just as below
./header1.h:23: Error: Syntax error in input(3).
I check the SWIG doc(http://www.swig.org/Doc1.3/SWIG.html 5.7.1) and found that the syntax error is so common, it's probably caused by a SWIG bug.
The doc recommended when encountering a syntax error to use #ifndef SWIG to omit statements that will make SWIG parser issue an error. So I changed the header1.h file, then the error disappeared.
header1.h:
#ifndef SWIG
19 typedef struct T {
...
23 } PACKED TlvHdr;
#endif
If you can't modify theheader.h file, you can make a new header file that just contains the declarations you need and replace the file from theheader.h to your new header file at %include directive
I had a similar issue and -E helped me understand that a macro definition was hidden inside an #ifndef SWIG block. I suspect that here it does not see the definition of GDBM_FILE, likely because it does not recurse.
I'm using doxygen to comment a pure C project. The documentation for a struct is of the following form:
/** #struct cl_options
* #brief This structure contains all ...
* #var cl_options::input_file
* Member 'input_file' contains ...
* #var cl_options::output_file
* Member 'output_file' contains ...
* #var cl_options::bitrate_mode
* ...
*/
struct cl_options {
FILE* input_file;
FILE* output_file;
....
};
Nevertheless I get warnings:
.../commandline.c:39: Warning: Member input_file (variable) of class cl_options is not documented.
.../commandline.c:40: Warning: Member output_file (variable) of class cl_options is not documented.
and so on. For all the structures within the project.
There is a decleration in the header file commandline.h
struct cl_options;
typedef struct cl_options cl_options;
but the doxygen is in the .c-File.
Now the generated doxygen has a link for the struct in the data structures section but it is not documented. Instead there is a link which says
The documentation for this struct was generated from the following
file: commandline.c
and then there is the documentation I provided in the .c-file. How can I avoid this?
I noticed a lot of warnings myself, while using doxygen, however most of the time the output seemed to be fine with me. You can turn, different warnings on and off. For more information visit the doxygen manual and choose which warnings your want to be enable.
However, you can try to move your #var tags from your .c file to your .h header. Just leave the documentation of functionality from your struct, in your .c.
Also, you might want to take a look at this post, with a similar question.
using-doxygen-with-c-do-you-comment-the-function-prototype-or-the-definition? Or both?
I'm having an issue with compiling code for Arduino if the code is in multiple files. What I have been doing in the past is have a script concatenate the files in another directory and make the project there. I would like to be able to compile directly from my build folder without having to jump through hoops of making sure everything is defined in the right order, etc.
I'm using avrdude to compile from Linux command line, because the Arduino IDE doesn't work very well with my window manager. When I make with multiple files (with appropriate #include statements, I get errors of the following nature, but for all of my methods and variables.
./../lib/motor.ino:3:21: error: redefinition of ‘const long unsigned int MOVE_DELAY’
./../lib/motor.ino:3:21: error: ‘const long unsigned int MOVE_DELAY’ previously defined here
The only other place that MOVE_DELAY is used is inside the void loop() function, and it doesn't redefine it there. The code also compiles fine if concatenate it into one file and run make in that directory, but not if they are in separate files with includes.
I believe your problem is solvable by declaring the objects with the "extern" prefix or external. For example. I often use the SdFat library, in which it is included in both my main sketch and instanced in other libraries.
/**
* \file test.ino
*/
#include <SdFat.h>
#include <foo.h>
SdFat sd;
...
Where I also use the same object in other libraries, such as foo.h.
/**
* \file foo.h
*/
#include <SdFat.h>
extern SdFat sd;
...
If it was not for the prefix of "extern" it would error like yours, as "sd" can not exist twice. Where the extern prefix tells the linker don't make a new instantiation, rather link to the externally instance elsewhere.
I have #define values in headers that I certainly want Doxygen to document but I have others in C files that I treat as static constants and I don't want Doxygen to document them. Something as simple and stupid as
#define NUMBER_OF(a) (sizeof((a))/sizeof((a)[0]))
#define MSTR(e) #e
How can I keep Doxygen from putting those #defines in the documentation it creates? I've tried marking it with #internal but that didn't seem to help.
A somewhat-related question on Doxygen and #define, how can I get:
#define SOME_CONSTANT 1234 /**< An explanation */
to put "SOME_CONSTANT" and "An explanation" but not "1234" in the output?
There is no need to use the \cond and \endcond commands. You can hide the initializer by simply using the \hideinitializer command:
#define SOME_CONSTANT 1234 /**< An explanation #hideinitializer */
Regarding the first question, you may set HIDE_UNDOC_MEMBERS = YES and only the macros having a Doxygen documentation block will be shown in the output.
You can set MAX_INITIALIZER_LINES = 0 in your doxyfile to hide the values of your defines.
You can exclude any part of code from Doxygen parsing with \cond ... \endcond tags.
edit: Some related questions:
How can Doxygen exclude a C++ class?
Exclude some classes from doxygen documentation
You only want to document what is declared in the .h files. I'm assuming you declare all static functions and variables as static in your .c files. All the remaining are declared in .h corresponding files also. These are your "public" members.
What I like to do in this case, and I believe doxygen was more designed to be used this way is:
in your Doxyfile, set EXTRACT_ALL = NO and add the directory where your .h files are to INPUT
add /** \file */ to all your .h files (but not your .c files).
This will index only what is contained in your .h files. You can still add the directory containing your .c files to INPUT at your Doxyfile, and they will be scanned for additional documentation for your "public" members...
It will no doubt still seem noisy and unnatural, but to address your other question, try:
/** An explanation */
#define SOME_CONSTANT /** #cond */ 1234 /** #endcond */
I solved this problem by moving my documentation from the .c file to the .h file. Then run doxygen only on the .h file.
Then the items that I want to document (the 'public' items) are intrinsically what doxygen picks up.
Because I have been previously careful to put 'public' items in the .h file and 'private' items in the .c file this works very well.
This technique came to mind when I noticed that doxygen was pulling in the includes. It struck me that if I were to also move the subset of includes that the calling module would need to use my module, then that list would be documented as well.
This technique has an additional benefit: I can put the documentation in one terminal window and the source in a different terminal window while updating the documentation.
Sometimes you may have a define which you want to document, but want doxygen to treat it differently (or even ignore it completely to avoid parsing errors).
For this you can define the #define in doxygen differently than in your sourcecode.
Example:
Some compilers allow variable linkage to specific segments, i.e.:
const int myvar # "segment_of_myvar_in_memory"=123;
=> doxygen would parse the "segment_of_myvar_in_memory" part as variable name which is not desired.
We could use a define for it:
#define __link_to_segment(name) # name
const int myvar __link_to_segment("segment_of_myvar_in_memory")=123;
If Preprocessing is active, Doxygen interprets our variable now as a function because of the function-like define using brackets..
But if we redefine our define within the Doxyfile, behaviour changes:
PREDEFINED = __link_to_segment(a)=
now the variable is parsed correctly as variable - also all types or keywords in front are correctly shown as keywords.
A nice side effekt:
In case you use 2 different IDEs with your code (one IDE for compiling&debugging, one for editing), you will also discover that some IDEs (i.e. Eclipse) have problems parsing variables with #"segment name". Using the approach above, you can redefine the __link_to_segment(name) there too:
#define __link_to_segment(name)
i.e. Eclipse will then show and parse the variable correctly, whereas the "compiling&debugging" IDE can still link the variable to its segment name.