Search code examples
doxygenspecificationsrequirements

How to generate "global documentation" with doxygen


I have a fair understanding of both how to document code and how to write "generic documentation" using @mainpage, @page, @subpage and related tags.

I would need to include requirements/specification documentation for the code.

My problem is to keep this kind of documentation (conceptually distinct from code documentation) close to code implementing functionality (i.e.: at least in the same file, sometimes even near specific classes/functions/methods) but still be able to collect it in an orderly fashion and present it in the @mainpage, outside file/class hierarchy.

What I would ideally need is to be able to place specific @page, @section, @subsection etc. randomly in the various source files and then be able to @include them in a specific order into @mainpage or some other @subpage.

Even better would be to be able to include the same snippet in both class/function full doc (not @brief, of course) and in the "front matter" linked in @mainpage.

Global effect I need to have is to have a "specification document" where I detail what the various parts of the code need to implement and then the "normal class/function/whatever" documentation doxygen id very good at providing.

The catch (i.e.: what I don't know how to do) is I would like to keep "specification" and implementation together in the source, but separate them in documentation, i.e.:

  1. General Description: easy, this goes into @mainpage
  2. Requirements: most likely at top of source file implementing them, how do I link/include in main page?
  3. Specification: either right after Requirements at top of file or somewhere near class/function implementing it; also here I don't know how to link/include in "front matter" AKA: @mainpage.
  4. Normal code documentation: here only thing I don't know is how include in class/function description the same "doc snippet" already used for (2) and (3).

Is this possible?

If so, what's the best practice?

Note: I could get the effect using a separate file for each "doc snippet" and then @includeing it in the right places, but that would defeat the whole purpose that's keep Requirements/Specification/code together while separating them in different sections in the resulting documentation.

Update: following @albert comment I tried the following:

  • in a standard Doxygen comment I added markers:
/**
 * Initialization function.
 *
 * [AM_init]
 * It needs to do a long series of tests to ensure AM can actually work.
 *
 * It should also allocate all dynamic memory needed to avoid runtime failures.
 *
...
 * It will be responsibility of system-level daemon to take appropriate action.
 * [AM_init]
 *
 *
 * @param ip_addr
 * @param port
 * @return
 */
static uint32_t AM_init(const char* ip_addr, uint16_t port) {
...
  • in the "front matter" definition I have (among other things):
/**
@page __init Initialization
@snippet{doc} CommandHandler.c AM_init
*/
  • The function documentation is rendered correctly (i.e.: the markers are removed)
  • OTOH the initialization page is "somewhat incomplete":

Initialization

    It needs to do a long series of tests to ensure AM can actually work.

that's it.

Apparently the tag is found, but only the first line is actually included.

Further Update: Following @albert answer (accepted) I had success, but the following caveats:

  • Included snippet ([AM_init]) must be in a standard comment, not a doxygen one, otherwise snippet ends up included twice.
  • Included snippet must not have leading * (very common in "standard comments".
  • Included comments should have HTML controls (e.g.: <br/> for line termination) because Markdown constructs ("double newline", in the above case) are notrecognized.

In retrospect I think "Note" in Doxygen \snippet['{'option'}'] <file-name> ( block_id ) documentation addresses, more or less all the above, but I find it very cryptic and I would never have understood the implications without my nose being rubbed into them.

The last one is very annoying because I use a lot Lists and Tables and while HTML syntax is much more powerful, it is also much more difficult to write and to read in sources.

Finding a way to lift this limitation would be "very nice".


Solution

  • With the following code and the current doxygen version (1.9.4 (5d15657a55555e6181a7830a5c723af75e7577e2)) but also with the 1.9.1 (ef9b20ac7f8a8621fcfc299f8bd0b80422390f4b) version, I get good result:

    bb.h

    /// \file
    
    /**
    @page __init Initialization
    @snippet{doc} CommandHandler.c AM_init
    */
    

    CommandHandler.c

    /// \file
    
    /**
     * Initialization function.
     */
    
    /* [AM_init]
       It needs to do a long series of tests to ensure AM can actually work.<br>
    
       It should also allocate all dynamic memory needed to avoid runtime failures.<br>
    
       It will be responsibility of system-level daemon to take appropriate action.<br>
       [AM_init]
     */
    /**
     * \snippet{doc} this AM_init
     *
     * @param ip_addr
     * @param port
     * @return
     */
    static uint32_t AM_init(const char* ip_addr, uint16_t port){}
    

    Doxyfile

    EXTRACT_STATIC = YES
    EXAMPLE_PATH = .
    QUIET = YES
    

    Note: OP rightfully mentioned in further update that there are some things to take care of:

    • Included snippet ([AM_init]) must be in a standard comment, not a doxygen one, otherwise snippet ends up included twice.
    • Included snippet must not have leading * (very common in "standard comments".
    • Included comments should have HTML controls (e.g.:
      for line termination) because Markdown constructs ("double newline", in the above case) are not recognized.