Thursday, February 10, 2011

Doxygen tips-n-tricks


Doxygen documentation parser written by Dimitri van Heesch (big thanks!) has been a part of my professional tool chest for a good part of the last ten years. Along with Graphvis (layered drawings of directed graphs), a graph visualization toolkit from AT&T and Lucent Bell Labs, it provides a quick and intuitive way of documenting your source code. Doxygen output also helped me tremendously to navigate through a maze and learn quickly the inner workings of every new project I came across in the past.

First, you need to create a configuration file, Doxyfile, either by running doxywizard GUI or from command-line with 'doxygen -g' command.

Adjust Configuration File

First thing you would want to adjust is project name/number, document encoding and output directory.

PROJECT_NAME = Granule
PROJECT_NUMBER = 1.4.0

OUTPUT_DIRECTORY = dox
DOXYFILE_ENCODING = UTF-8
TAB_SIZE = 4
FULL_PATH_NAMES = NO
HIDE_UNDOC_CLASSES = NO
HIDE_IN_BODY_DOCS = YES 
EXTRACT_ALL = YES
RECURSIVE = YES

If it is a "C" project, optimize for "C":

OPTIMIZE_OUTPUT_FOR_C = YES

For C++ project,

BUILTIN_STL_SUPPORT = YES
TEMPLATE_RELATIONS = YES
CLASS_GRAPH = YES
UML_LOOK = YES
GRAPHICAL_HIERARCHY = YES


You need to tell doxygen the file types to parse:

FILE_PATTERNS = *.h *.cpp

One thing I like about doxygen is its ability to shed some light on the function call chain in a program. For every function, it can optionally list all callers as well as call chain.

CALL_GRAPH = YES
CALLER_GRAPH = YES
REFERENCED_BY_RELATION = YES

COLLABORATION_GRAPH = YES
SOURCE_BROWSER = YES
INLINE_SOURCES = YES

ALPHABETICAL_INDEX = YES
GENERATE_TREEVIEW = YES   (side pane) 
SEARCHENGINE = YES

GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER = 
HTML_STYLESHEET = 
HTML_ALIGN_MEMBERS = YES
DISABLE_INDEX = NO

HAS_DOT = YES
DOT_IMAGE_FORMAT = png
DOT_FONTNAME = FreeSans

Cross-Referencing with Tag Files

If your project is an collection of disjointed libraries each within the boundary of its own package, you might want to enable cross-referencing with tagging feature of doxygen.

To better illustrate the concept, I will use my own software as an example. My flashcards program, Granule, internally relies on libassa (a collection of reusable shared code). In my Linux development environment, I have the following code arrangement:

Library

/path/to/libs/libassa/assa/
|
|-/dox/
|    \--html/
|         \--index.html
|--{*}.h
|--{*}.cpp
|--Makefile
\--Doxygen-lib

Application

/path/to/apps/granule/src
|
|--/dox/
|    \--html/
|         \--index.html
|--{*}.h
|--{*}.cpp
|--Makefile
\--Doxygen-app

The two paths are distinctly different. In order for the HTML documentation generated by Doxygen-app include references to the documentation generated by Doxygen-lib, we need
  • configure Doxygen-lib to generate its tag file
  • configure Doxygen-app to include external tag file(s) to resolve external references
With this in mind, let's look at the syntax of both configuration files:

--- Doxygen-lib ---

GENERATE_TAGFILE = dox/html/libassa.tag


--- Doxygen-app --

TAGFILES = /path/to/libs/libassa/assa/dox/html/libassa.tag=/path/to/libs/libassa/assa/dox/html


BTW, the path can be either absolute (as show in the example above) or relative. As you can see for yourself, the syntax of the TAGFILES parameter is a bit awkward by any standards. I would prefer instead an option of an environment variable to resolve the location of tag files which is more suited for a team of collaborative developers.

However, it gets the job done and that is what's important at the end of the day.

Happy coding!

1 comment: