Doxygen is a system that lets you place special kinds of comments next to and within the code you want to document. The doxygen program scans the source code for these comments and uses them, together with information it parses from the programming language statements and declarations, to create documents.

We have Doxygen version 1.5.8 under /usr/local/bin at SLAC.

Doxygen can make documents in several formats: HTML, PDF, RTF, XML, etc. The XML output might be used to create Framemaker files. It seems that several projects have done so using custom scripts. Direct Framemaker support is on the Doxygen wish list.

I've fully documented the packages "dataStructure", "io" and "string" in the "tool" project and I've made quick fixes in the other packages in the project. Once you've updated or checked out tool you can make the documents manually:

cd tool
mkdir -p ../build/tool/doc/interface  ../build/tool/doc/internals
doxygen interface.doxy
doxygen internals.doxy

Making the PDF file requires an extra step since Doxygen writes only LaTeX input with a Makefile to run pdflatex:

cd ../build/tool/doc/interface/latex
make -i pdf

The resulting document is always called refman.pdf. You need to use -i with make because sometimes the LaTeX message about bad cross-references doesn't go away even though the document is OK.

I envisage two versions of code docs per project, one documenting just the public interface and the other all the internals as well. Both documents are prepared from the same source code files but using different Doxgen options. In the source code you can use the @internal command inside any Doxygen comment. The documentation that follows is considered to be internal until the end of the comment or an @endinternal command. When in the project directory the command

    doxygen interface.doxy

will generate the interface document(s). Use internals.doxy to make
the full document.

The interface.doxy file generally generates documentation for the following:

  • The main page and related material.
  • Named namespaces.
  • Non-member functions, typedefs, variables, enums and classes.
  • Public and protected class members.
    *Friend functions.

but the following are excluded:

  • Private class members.
  • Static variables and functions.
  • Nameless namespaces and their contents.
  • Material specifically marked as internal.
  • Friend classes and structs.

Both documents are made by scanning the entire source code tree including all the platform-specific directories such as rtems/, ppc405/, etc. I expect that the bulk of our code will be generic so that generating documents for each platform would be mostly redundant. However, this brings us up against a weakness of Doxygen: it deals poorly with multiple definitions of the same class or struct. We organize our code by including a file with the same name for all platforms but getting the file from a directory that is specific to the platform. That makes it hard to avoid the problem in Doxygen. We can work around it by putting platform-specific declarations inside platform-specific namespaces, but employing using-declarations to hoist the symbols up into the generic namespace, like so:

foo/bar/src/ppc405/Baz.hh:
namespace foo {
  namespace bar {
    namespace ppc405 {
      class Baz {...};
    }
    using ppc405::Baz;
  }
}

foo/bar/src/i386/Baz.hh:
namespace foo {
  namespace bar {
    namespace i386 {
      class Baz {...};
    }
    using i386::Baz;
  }
}

Now the two declarations will be recognized as separate by Doxygen yet when compiling for either CPU the appropriate declaration will be available in namespace foo::bar:

    foo::bar::Baz frobozz;

    using foo::bar::Baz;
    Baz zork;

I've configured Doxygen to scan .hh, .h, .cc and .doc files. (For JJ's code in the "conversion" package I had to add .h. to accomodate his file naming scheme.) The .doc files contain C++ comments giving namespace documentation as well as extra material such as design principles, examples, etc.

.hh and .cc files contain @file commands, .doc files don't.

Platform-specific documentation appears only in platform-specific directories, never in directories containing generic code.

A project has a file named project.doc in its top-level source directory. Here will go a general description of the project (use the @mainpage command to put the description on the main documentation page).

Documentation should be provided for the following source code elements just before their declarations (as opposed to their definitions):

  • Functions.
  • Typedefs.
  • Variables.
  • Named enums.
  • The members of an enum whether or not the enum itself has a name.
  • Classes, structs and named unions.
  • Class, struct or union members in any of the above categories.

Macros can be documented just before their definitions.

As any given namespace may be declared in many different places, namespace documentation should be placed in a .doc file. Don't try to enumerate all the members of the namespace; let Doxygen do that. Namespaces that are part of the interface of a project should be documented in the project.doc file.

If a file, namespace, class, struct or union is undocumented then its members will be undocumented as well, even if you give them Doxygen comments of their own. Enums are a special case since you can document the enumerators of an undocumented nameless enum and still have them show up.

All function arguments should be documented at least to the extent of marking them out or in,out if they are not used strictly for input. A function's return value should be documented if it isn't already described in the general function description. Likewise for exceptions thrown by the function.

Each .cc or .hh file should include a @file command with no filename given; Doxygen will insert the name of the file. That will prevent name clashes in the documentation when a file with the same name is in several different directories, .e.g., generic and platform-specific. See make/boilerplate/legal.hh and legal.cc.

The doc-comment for a file must contain @file or Doxygen will apply it to the first C++ entity declared or defined in the file, which for our code is usually the project namespace.

The internals.doxy file generates documentation for everything that interface.doxy does, plus private class members, static declarations, nameless namespaces and their contents plus material marked as internal.

If you want to have each package within a project to have its own "module" with its own page (HTML) or section (PDF), and assuming that each package has its own namespace, you can do it by assigning each namespace to its own Doxygen module using a package.doc file with code like this:

/**
  @defgroup foo Foo stuff
  @brief Blah, blah, ...

  @namespace foo
  @brief Package namespace.
  @ingroup foo-package
*/
  • No labels