wiki:GCI/Documentation/DoxygenCleanup

Version 2 (modified by Gedare Bloom, on Nov 17, 2015 at 7:37:33 PM) (diff)

Import more from GCI/Projects

Doxygen

Table of Contents

    Doxygen

    Add Doxygen File Headers

    Given a first pass of which files we would like to improve Doxygen in, there are at least 55 tasks in this category assuming 10 files per GCI task.

    Tasks related to improved RTEMS "Doxygenation"; you should also read through Doxygen Recommendations.

    Special thanks to Gedare Bloom, Jennifer Averett, and Sebastian Huber for instructions on writing and checking Doxygen comments. The RTEMS source base has been in a long process to use Doxygen. But since Doxygen is newer than RTEMS, there are still lots of files which don't have the bare minimum of even a proper Doxygen file header comment block. These tasks consist of editing a set of files to provide a proper Doxygen style file header comment block to RTEMS source files, and merging any comments that precede any method declaration in the .c file into the Doxygen comment block preceding the method's prototype in the approriate .h file.

    Check out the Doxygen Recommendations for BSPs page for a detailed guide useful in completing these tasks.

    This task is a little tricky: there are two desired header formats:

    1. The top of the file has an @file, @ingroup, and @brief
    2. The middle of the file has an @ingroup and @brief

    The format of the @brief is different for the top of the file and the end of the file.

    Directions

    1. locate the .h file for a .c file
    2. Add the headers
    3. Check your work
    4. Continue to check your work until you're ready to submit
    5. Format the patch
    6. Submit your work
    Locating the .h file for a .c File

    Identifying the group a function is in is one of the key points of having Doxygen headers. To identify which group a function is in, locate the .h file where the function is, and use the group defined in the @defgroup tag. For example, for cpukis/score/src/watchdoginsert.c, the @ingroup would be based on this line from cpukit/score/include/rtems/score/watchdog.h:

    Identifying the Group
    /* @file                                                cpukit/example/include/example.h
     * @defgroup ScoreWatchdog Watchdog Handler
    

    The tag above defines the handle ScoreWatchdog and says it has the printable name Watchdog Handler. Thus cpukit/score/src/watchdog.c would use

    cpukit/example.c

    /* @file only used for the first header in a file

    • @ingroup ScoreWatchdog
    Locating the File

    To locate the .h file where the @defgroup (for the @ingroup) is, you can use grep as follows:

    cd rtems/cpukit/DIRECTORY
    grep -r rtems\_random\_function include
    

    DIRECTORY should be replaced with the appropriate subdirectory based on the file being edited. For the first tasks of this type, this will be score, rtems, sapi, or posix.

    Notes
    • If you locate the prototype for the method in the RTEMS source, then merge the comments in the .c file into the appropriate .h file. Please put the the comments from the .c file to the .h file Doxygen comment block above the function.
    • If you do not find the function in a .h, do NOT remove the comments above the function in the .c file. Edit any existing comments to turn them into proper Doxygen comments. Some functions in the cpukit/posix/src or cpukit/libcsupport directories are prototyped by the C library, so you may not find their prototypes.
    • Examples: The methods in cpukit/rtems/include/rtems/rtems/event.h provide a good example of how RTEMS uses Doxygen. When in doubt, there is online documentation for Doxygen at http://www.doxygen.org and you can always ask questions via the Google Code In site or in #rtems on IRC freenode.
    Add the Headers

    Once the @ingroup is found, the next step is to add the headers. For each file, there are two types of headers. The first header has an @file, an @ingroup and a Table of Contents @brief. The other headers DO NOT have an @file, but DO have an @ingroup and a Topic Sentence @brief. Please see the examples.

    First Header in a File

    Desired Format (at the top of the file):

    line 1                                                cpukit/example/example.c
    /**
     * @file
     *
     * @ingroup GROUP_FROM_dot_h_FILE
     * @brief Brief Description for Table of Contents
     */
    
    /*
     * COPYRIGHT
     * 
     * The copyright should exist in every file already, but the header will have 
     * to be edited and the copyright remain below and in a separate comment block.
     */
    

    Advice on first header in file @brief contents: The @brief text for classes and files is what will show up in a Table of Contents. The key is short, English suitable for Table of Contents. For a file with a single method, it might be the method's name in English. For example: The file with the _Chain_Initialize() method should use something like "Initialize a Chain" for the @brief text. In many cases, the .h file with this method prototyped will have an @brief which is suitable for use. In other words, you can use the @brief text from the .h file description of the same method. See above for instructions on locating the appropriate .h file. Some guidelines:

    • The first header's @brief text for classes and files will show up in Table of Contents. Use capitalization like section or chapter headings
    • Do not end the first header's @brief with a period
    Other Comments in a File

    Desired Format (in the middle of the file):

        ...                                              cpukit/example/example.c
        rtems_random_call();
        return 55;
    }
    line 10+
    /**
     * @ingroup GROUP_FROM_dot_h_FILE
     * @brief Topic sentence describing a function, if it goes over 79
     * characters, please put on the next line.
     */
    
    • Other header's @brief text for classes and files will show up in Function Descriptions. Use a topic sentence structure.
    • End the other header's @brief with a period
    Notes

    Make sure there are no tab characters embedded in the changes. RTEMS does not embed the tab character. Check your editor setting and look for one that inserts spaces and not tab characters. The tab default size is 2.

    Checking Your Work (How to Run Doxygen)

    One way to quickly become a quality coder is to make sure your code does what it's supposed to. This code is used to generate cross-references needed for certifying RTEMS in safety critical applications, as well as, telling our users (such as embedded software developers working for car manufacturers and aerospace corporations) what each function does. There are several ways to see what html is produced by the Doxygen comments written.

    Advice: please just use ONE method.

    Method 1 Calling Doxygen Directly
    1. Install doxygen
    2. Get the Doxyfile
      1. Copy the File:Doxyfile.diff? to a directory outside of the RTEMS directory.
      2. Rename Doxyfile.diff to Doxyfile.tar.gz
      3. Extract it outside the RTEMS directory
      4. Open the Doxyfile in a text editor and edit line 577 to point it at the directory you want to generate documentation for, as well as lines 28 and 41 to rename the resulting folder
    3. call doxygen from the rtems directory ~/rtems> doxygen ../Doxyfile ~/rtems> firefox cpukit_doxy/html/index.html
    4. Click on Modules
    5. Click on your module
    6. ctrl+f Function Documentation

    Once you're done looking, delete the cpukit_doxy

    ~/rtems> rm -rf cpukit_doxy
    
    Method 2 Using the do_doxygen script

    UPDATED: There is a newer do_doxygen script available at https://github.com/joelsherrill/gci_tasks/blob/master/2013/doxygen_c_header_tasks/validate/do_doxygen. Your environment needs to have the root directory of rtems set in the variable r so that $r prints the path to rtems, and the script takes as argument a relative directory from there to generate the doxygen, for example to generate the doxygen for all of libbsp you would do:

    export r=~/rtems
    ./do_doxygen c/src/lib/libbsp
    

    And it should just work.

    Outdated: There is a shell script do_doxygen in the same ftp directory as the list of files to edit http://rtems.org/ftp/pub/rtems/people/joel/Doxygen_Tasks/. It assumes the directory layout in the RTEMS Virtual Machine?. There is another shell script in that directory named build_doxygen which takes command line arguments.

    Format the Patch (How to Run Doxygen)

    Please submit a patch generated by git.

    Please select a suitable name by replacing "gci-doxygen-task2.diff" with something that relates to your task. You can add an extra '-2' to the name, for example "gci-doxygen-task2-2.diff" if you need to submit more than one diff as a result of reviews.

    You can do this with a git command similar to:

    $ git diff > gci-doxygen-task2.diff
    

    Directions for RTEMS Mentors

    Task Count: Across 4 directories, a search indicates there are ~800 files with this problem. If students are given a set of 10 files, then there are ~80 of these tasks. This task can be expanded to include other directories.

    What to Submit: The student will be editing the comments in RTEMS source code and submitting a patch. Git instructions for RTEMS are at http://wiki.rtems.org/wiki/index.php/RTEMS_GIT_Repository#GIT_Access_for_users, and http://wiki.rtems.org/wiki/index.php/Git_Users. If there is a need for simpler instructions geared to GCI, a mentor will create them.

    Mentor Guidelines: The student will submit a patch which will likely need to be directly emailed to a mentor for review. This is necessary because the rtems-devel mailing list only accepts email from subscribers and students are not expected to subscribe. The mentor will review the patch for correctness. When correct, if the mentor doesn't have git write permission, they should post the patch to rtems-devel. If the mentor does have write permission, they are free to commit it. In either case, we need the student's name and email to give credit in the commit message.

    Cleanup Doxygen

    The cleanup tasks consist of changes to make Doxygen use consistent with the Doxygen Recommendations. The submission consists of a patch ("diff"), and the student's name and email address for the commit message.

    Students will submit a patch generated by git. You can do this with a git command similar to:

    $ git diff > gci-doxygen-taskXYZ.diff
    

    Use sentences for function @brief

    Convert function @brief from "Table of Contents" to "Topic sentence" style. The descriptive text of a function's @brief is used to start a paragraph, so it should be a simple, concise sentence describing the function that begins with an active, present tense verb. See Doxygen Recommendations#Declaring functions? for an example. When the description begins with a noun, rewrite the description so that the action of the function comes first. Eliminate any redundant wording such as "Function that does..." or "This function...".

    Use @param to document function parameters

    Replace @a with @param. See Doxygen Recommendations#Declaring functions? for an example. If you cannot determine whether a parameter is "in", "out", or "in,out" then ask for assistance.

    Use @retval to document function return values

    Replace @return with @retval statements. See Doxygen Recommendations#Declaring functions? for an example. If you cannot determine the possible return values for a particular function then ask for assistance.

    Hierarchy formatting and correctness

    There are multiple levels of groupings that RTEMS functions fall into. We want to represent this in Doxygen. To determine the subsystem (higher level grouping) that a group falls into. This task is designed to put the RTEMS Modules into a logical hierarchy.

    1. Add missing @defgroup
    2. Nest subgroups
      1. Find the @defgroup / @addtogroup
      2. Add an @ingroup indicating the "subsystem" for the @defgroup
    3. Put all @{ for @defgroup, @name statements in the same comment block as the defgroup/name statement. See Doxygen Recommendations#Using .40defgroup for group definitions? for an example.
    4. Ensure all @{ have matching @}. See Doxygen Recommendations#Ending the file? for how this should be done at the end of a header file for the primary defgroup. If you cannot determine where to place the terminator for a @defgroup or @name then ask for assistance.

    Add missing @defgroup

    Identify what @ingroup do not have a @defgroup, and add @defgroup for the missing ones. This task comprises searching for @ingroup labels and matching them with a @defgroup. A little bit of scripting should help, for example:

    $> cd rtems/cpukit
    $> grep ingroup score/include/rtems/score/thread.h
     *  @ingroup Score
    $> grep -R defgroup * | grep "Score"
    ...
    score/include/rtems/score/object.h: * @defgroup Score SuperCore
    ...
    

    Would be a way to find the group definition for the Score group. If you get no results for the defgroup query, then probably the group has not been defined. If you get too many results, you can do additional filtering, for example:

    $> grep -R defgroup * | grep "Score "
    score/include/rtems/score/object.h: * @defgroup Score SuperCore
    

    grep

    -R means recursively look into every file

    • means every folder | means pipe the output through

    grep "Score" means filter for "Score"

    Use the knowledge there is a space after the group's name for the group's description to filter the results to exactly the defgroup you want to find.=== = Nest Subgroups ====

    look at the subfolder in cpukit that contains the file.

    • cpukit/rtems -> Classic API
    • cpukit/posix -> POSIX API
    • cpukit/score -> SuperCore
    • cpukit/libfs -> (1) Filesystems (2) filesystem X
    • cpukit/libcsupport -> Subsystem (Higher Level Grouping) = Libc Support, keep the lower level grouping as determined from file.

    Using Doxygen Subgroups

    Doxygen is used to put groups into subsystems by using @defgroup or @addtogroup. The difference between @defgroup and @addtogroup is that @defgroup forces each call to be unique, while @addtogroup merges multiple groups with the same name together. For expediency and robustness of the Doxygen system for RTEMS, @addtogroup may be preferable.

    To use Doxygen subgrouping add the following to the comments Example: Malloc is a subgroup of Libc Support

    /

    • @defgroup Malloc malloc.h the file with the @defgroup
    • @ingroup Libc Support this is what we want to add
    • @brief Brief In Table of Contents Style* *Style depends on where the */ comment is in the file

    Doxygen Grouping Example

    Mentor Guidelines

    The student will submit a patch that should be reviewed for correctness. When correct, if the mentor doesn't have git write permission, they should post the patch to rtems-devel. If the mentor does have write permission, they are free to commit it. In either case, we need the student's name and email to give credit in the commit message.

    Structuring Doxygen in libbsp

    The existing doxygen in the libbsp directory has been added in ad hoc and without any real structure. This makes navigating through the resulting documentation very difficult, and virtually impossible if the libbsp doxygen is ever to be compiled with the cpukit doxygen. Tasks in this of this type would work towards refactoring the existing doxygen within the libbsp directory to conform to a structure that more closely resembles the structure and heirarchy of the libbsp directory itself. The end goal is to have a single "Board Support Packages" module, with submodules for each cpu architecture and each specific board support package.

    These tasks will involve renaming and reordering old @defgroup declarations, as well as adding in new @defgroup and @ingroup declarations to conform the structure of doxygen to be more like how libbsp is ordered.

    Check out the Doxygen Recommendations for BSPs for more specifics on the implementation of the structure outline that follows.

    Outline of Structure

    The structure of the doxygen in libbsp should match the structure of libbsp itself as closely as possible. Let's start by looking carefully at how libbsp is structured.

    The libbsp directory itself is very well ordered. Considered at the root, the first level contains directories of each cpu architecture RTEMS currently supports, along with a folder containing files and headers shared between all architectures.

    $ cd c/src/lib/libbsp
    $ ls
    arm   bsp.am  lm32  m68k             mips   no_cpu         README  sparc
    avr   h8300   m32c  Makefile.am      moxie  powerpc        sh      sparc64
    bfin  i386    m32r  MERGE.PROCEDURE  nios2  preinstall.am  shared  v850
    

    If we cd into a specific architecture, we see that a similar structure is employed. libbsp/arm/ contains directories for each Board Support Package for boards with an ARM cpu, along with a folder for files and .h's shared by all BSPs of that architecture.

    $ cd arm
    $ ls
    acinclude.m4  edb7312    gumstix   Makefile.am    realview-pbx-a9  stm32f4
    configure.ac  gba        lm3s69xx  nds            rtl22xx          xilinx-zynq
    csb336        gdbarmsim  lpc24xx   preinstall.am  shared
    csb337        gp32       lpc32xx   raspberrypi    smdk2410
    

    Finally, if we cd into a specific BSP, we see the files and .h's that compose the package for that particular board.

    $ cd raspberrypi
    $ ls
    bsp_specs  configure.ac  include  make         misc           README
    clock      console       irq      Makefile.am  preinstall.am  startup
    

    The goal is for someone to be able to search through the doxygen is a very similar way. The way to accomplish this would be to have a single libbsp parent module that would contain a submodule for each cpu architechture, which in turn would contain submodules for each BSP. Modules for shared and generic functions would be defined at each level, whenever appropriate. Rememember, our goal is for the structure of doxygen modules and submodules to match the structure of libbsp as closely as possible.

    The overarching parent module that all other modules should belong to is bsp_kit, whose @defgroup is found in /shared/include/bootcard.h Consider this to be the "root directory" for libbsp doxygen purposes.

    c/src/lib/libbsp/shared/include/bootcard.h: @defgroup bsp_kit Board Support Package
    

    The first thing that should be @ingroup to this bsp_kit module (I will use module and group interchangably) should be submodules for each architechture. This group should have the "@defgroup *bsp_architechture*" placed in one of shared header files that is sufficiently generic. The specific location of this @defgroup does not matter, you can place the @defgroup in a file and not add the file to the group (even though you should add it, unless it belongs in a more specific submodule). For example, the @defgroup for the arm architecture is found in arm/shared/include/start.h

    c/src/lib/libbsp/arm/shared/include/start.h:
    
    ...
    /**
     * @defgroup bsp_arm ARM
     *
     * @ingroup bsp_kit
     *
     * @brief ARM Board Support Packages.
     */
    

    Once all the architectures have their own respective @defgroup defining a module, a final module should defined and added to bsp_kit to house the doxygen for files that are shared by all the architectures. This "Shared" module should be defined in any header in the shared directory, and doxygen for generic implementations should be added to it, or more specific submodules within.

    Now we can move on to the next level, and look at the board support packages themselves. The modules for each specific BSP should be contained within the module for their respective architecture. For example, the raspberrypi module should be "@ingroup bsp_arm", because the raspberry pi board is of the arm architecture. This @defgroup can be found within raspberrypi/include/bsp.h

    c/src/lib/libbsp/arm/raspberrypi/include/bsp.h:
    
    ...
    /**
     * @defgroup arm_raspberrypi Raspberry Pi Support
     *
     * @ingroup bsp_arm
     *
     * @brief Raspberry Pi support package
     */
    

    Again, once modules are in place for all BSP's, a module should be defined to house the doxygen documenting the files shared across all BSPs.

    Finally, we have reached a group we can really work with, the specific group of the BSP, in this case arm_raspberrypi. You can work with this module the same way you would for using doxygen in general, and can follow the standard doxygen instructions given here and elsewhere. @defgroup new headers in .h files (remembering @ingroup any new headers you define into the BSP group), move protoypes and function comments to the .h and include @briefs, @ingroup relevant .c files, etc etc. These directions can be found in the section Add Doxygen File Headers, and other doxygen reccomendations can be found here

    Notes, tips, tricks

    • Most BSP's will contain groups that are similar. This is because each board has to implement some form of interrupt support, memory management, and other features. If you're ever not sure what you should name a group, or whether something should be its own group, or what group a .c should be a part of, just take a look at how another board with finished doxygen handles those files.
    • If you're ever working on adding doxygen for a specific board support package and you find a group of .c files that logically belong together but find no common .h file included in all of them, check to see if there is a shared .h in the cpu architecture module that would provide a good group to include these files in. Often times some or all of these .c files are implementations or hooks of a more generic prototype found in one of the cpu headers. A good example of this is the start up code in the raspberrypi bsp having a "@ingroup arm_start" tag, which is defined in arm/shared/include/start.h.
    • Look at how groups are named. If you haven't put this together already, group names should always have the form *parent-group*_*submodule*. Some examples of this would be "bsp_arm", "arm_start", and "arm_raspberrypi". The only exception to this rule is the all inclusive bsp-kit. This convention makes it a lot easier to tell what module the group belongs to, and gives a good idea of the structure without actually having to generate the documentation. In the case of arm_start, you aren't just working on any old start module, your working on the start submodule of arm.