学惯用doxygen生成源码文档
副标题#e#
维护用C/C++ 开拓的遗留系统并添加新特性是一项艰巨的任务。这涉及几方面的问题 :领略现有的类条理布局和全局变量,差异的用户界说范例,以及函数挪用图阐明等等。 本文在 C/C++ 项目标上下文中通过示例接头 doxygen 的几个特性。可是,doxygen 很是 机动,也可用于用Python、Java、PHP 和其他语言开拓的软件项目。本文的主要目标是帮 助您从 C/C++ 源代码提取出信息,但也扼要描写了如何用doxygen 界说的标志生成代码 文档。
安装 doxygen
有两种得到 doxygen 的要领。可以下载预编译的可 执行文件,也可以从 SVN 存储库下载源代码并本身编译。清单 1 演示的是后一种要领。
清单 1. 安装和构建 doxygen 源代码
bash-2.05$ svn co https://doxygen.svn.sourceforge.net/svnroot/doxygen/trunk doxygen-svn
bash-2.05$ cd doxygen-svn
bash-2.05$ ./configure –prefix=/home/user1/bin
bash-2.05$ make
bash-2.05$ make install
留意,设置剧本把编译的源代码存储在 /home/user1/bin 中(进 行编译后,会在 PATH 变量中添加这个目次),因为并非每个 UNIX® 用户都有写 /usr 文件夹的权限。别的,需要用svn 实用措施下载源代码。
利用doxygen生成 文档
利用doxygen生成源代码的文档需要执行三个步调。
生成设置文件
在 shell 提示上,输入呼吁 doxygen -g 。这个呼吁在当前目次中生成一个可编 辑的设置文件 Doxyfile。可以改变这个文件名,在这种环境下,应该挪用doxygen -g <user-specified file name>,见 清单 2。
清单 2.生成默认的设置文件
bash-2.05b$ doxygen -g
Configuration file 'Doxyfile' created.
Now edit the configuration file and enter
doxygen Doxyfile
to generate the documentation for your project
bash-2.05b$ ls Doxyfile
Doxyfile
编辑设置文件
设置文件回收 <TAGNAME> = <VALUE> 这样的布局,与 Make 文件名目相似。下面是最重要 的标志:
<OUTPUT_DIRECTORY>:必需在这里提供一个目次名,譬喻 /home/user1/documentation,这个目次是安排生成的文档文件的位置。假如提供一个不 存在的目次名,doxygen 会以这个名称建设具有适当用户权限的目次。
<INPUT>:这个标志建设一个以空格脱离的所有目次的列表,这个列表包括 需要生成文档的C/C++ 源代码文件和头文件。譬喻,请思量以下代码片断:INPUT = /home/user1/project/kernel /home/user1/project/memory
在这里, doxygen 会从这两个目次读取 C/C++ 源代码。假如项目只有一个源代码根目次,个中有 多个子目次,那么只需指定根目次并把 <RECURSIVE> 标志配置为 Yes。
<FILE_PATTERNS>:在默认环境下,doxygen 会搜索具有典范 C/C++ 扩展 名的文件,好比 .c、.cc、.cpp、.h 和 .hpp。假如 <FILE_PATTERNS> 标志没有 相关联的值,doxygen 就会这样做。假如源代码文件回收差异的定名约定,就应该相应地 更新这个标志。譬喻,假如项目利用.c86 作为 C 文件扩展名,就应该在 <FILE_PATTERNS> 标志中添加这个扩展名。
<RECURSIVE>:假如源代 码条理布局是嵌套的,并且需要为所有条理上的C/C++ 文件生成文档,就把这个标志配置 为 Yes。譬喻,请思量源代码根目次条理布局 /home/user1/project/kernel,个中有 /home/user1/project/kernel/vmm 和 /home/user1/project/kernel/asm 等子目次。如 果这个标志配置为 Yes,doxygen 就会递归地搜索整个条理布局并提取信息。
<EXTRACT_ALL>:这个标志汇报 doxygen,纵然各个类或函数没有文档,也 要提取信息。必需把这个标志配置为 Yes。
<EXTRACT_PRIVATE>:把这个标 记配置为 Yes。不然,文档不包括类的私有数据成员。
<EXTRACT_STATIC> :把这个标志配置为 Yes。不然,文档不包括文件的静态成员(函数和变量)。
#p#副标题#e#
清单 3 给出一个 Doxyfile 示例。
清单 3. 包括用户提供的标志值的doxyfile 示例
OUTPUT_DIRECTORY = /home/user1/docs
EXTRACT_ALL = yes
EXTRACT_PRIVATE = yes
EXTRACT_STATIC = yes
INPUT = /home/user1/project/kernel
#Do not add anything here unless you need to. Doxygen already covers all
#common formats like .c/.cc/.cxx/.c++/.cpp/.inl/.h/.hpp
FILE_PATTERNS =
RECURSIVE = yes
运行 doxygen
在 shell 提示下输入 doxygen Doxyfile(可能 已为设置文件选择的其他文件名)运行 doxygen。在最终生成 Hypertext Markup Language(HTML)和 Latex 名目(默认)的文档之前,doxygen 会显示几个动静。在生 成文档期间,在 <OUTPUT_DIRECTORY> 标志指定的文件夹中,会建设两个子文件夹 html 和 latex。清单 4 是一个 doxygen 运行日志示例。
清单 4. doxygen 的日 志输出
#p#分页标题#e#
Searching for include files...
Searching for example files...
Searching for images...
Searching for dot files...
Searching for files to exclude
Reading input files...
Reading and parsing tag files
Preprocessing /home/user1/project/kernel/kernel.h
…
Read 12489207 bytes
Parsing input...
Parsing file /project/user1/project/kernel/epico.cxx
…
Freeing input...
Building group list...
..
Generating docs for compound MemoryManager::ProcessSpec
…
Generating docs for namespace std
Generating group index...
Generating example index...
Generating file member index...
Generating namespace member index...
Generating page index...
Generating graph info page...
Generating search index...
Generating style sheet...
文档输格外式
除了 HTML 之外,doxygen 还可以生成几种输格外式的文档。可以让 doxygen生 成以下名目标文档:
UNIX 手册页:把 <GENERATE_MAN> 标志配置为 Yes。 在默认环境下,会在 <OUTPUT_DIRECTORY> 指定的目次中建设 man 子文件夹,生 成的文档放在这个文件夹中。必需把这个文件夹添加到 MANPATH 情况变量中。
Rich Text Format(RTF):把 <GENERATE_RTF> 标志配置为 Yes。把 <RTF_OUTPUT> 标志配置为但愿安排 .rtf 文件的目次;在默认环境下,文档放在 OUTPUT_DIRECTORY 中的rtf 子文件夹中。要想支持跨文档欣赏,应该把 <RTF_HYPERLINKS> 标志配置为 Yes。假如配置这个标志,生成的.rtf 文件会包括 跨文档链接。
Latex:在默认环境下,doxygen生成 Latex 和 HTML 名目标文档。 在默认的Doxyfile 中,<GENERATE_LATEX> 标志配置为 Yes。别的, <LATEX_OUTPUT> 标志配置为 Latex,这意味着会在 OUTPUT_DIRECTORY 中建设 latex 子文件夹并在个中生成 Latex 文件。
Microsoft® Compiled HTML Help(CHM)名目:把 <GENERATE_HTMLHELP> 标志配置为 Yes。因为在 UNIX 平台 上不支持这种名目,doxygen 只在生存 HTML 文件的文件夹中生成一个 index.hhp 文件 。您必需通过 HTML 辅佐编译器把这个文件转换为 .chm 文件。
Extensible Markup Language(XML)名目:把 <GENERATE_XML> 标志配置为 Yes。(留意, doxygen 开拓团队还在开拓 XML 输出)。
清单 5 提供的Doxyfile 示例让 doxygen生成所有名目标文档。
清单 5.生成多种名目标文档的 Doxyfile
#for HTML
GENERATE_HTML = YES
HTML_FILE_EXTENSION = .htm
#for CHM files
GENERATE_HTMLHELP = YES
#for Latex output
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
#for RTF
GENERATE_RTF = YES
RTF_OUTPUT = rtf
RTF_HYPERLINKS = YES
#for MAN pages
GENERATE_MAN = YES
MAN_OUTPUT = man
#for XML
GENERATE_XML = YES
doxygen 中的非凡标志
doxygen 包括几个非凡标志。
C/C++ 代码的预处理惩罚
为了提取信息,doxygen 必需对 C/C++ 代码举办预处理惩罚。可是,在默认环境下,它只进 行部门预处理惩罚 —— 计较条件编译语句(#if…#endif),可是不执行 宏展开。请思量 清单 6 中的代码。
清单 6. 利用宏的C++ 代码示例
#include <cstring>
#include <rope>
#define USE_ROPE
#ifdef USE_ROPE
#define STRING std::rope
#else
#define STRING std::string
#endif
static STRING name;
通过源代码中界说的<USE_ROPE>,doxygen生成的文档如下:
Defines
#define USE_ROPE
#define STRING std::rope
Variables
static STRING name
在这里可以看 到 doxygen 执行了条件编译,可是没有对 STRING 执行宏展开。Doxyfile 中的 <ENABLE_PREPROCESSING> 标志在默认环境下配置为 Yes。为了执行宏展开,还应 该把 <MACRO_EXPANSION> 标志配置为 Yes。这会使 doxygen 发生以下输出:
Defines
#define USE_ROPE
#define STRING std::string
Variables
static std::rope name
假如把 <ENABLE_PREPROCESSING> 标志配置为 No,前面源代码的doxygen 输出就是:
Variables
static STRING name
留意,文档此刻没有界说,并且不行能推导出 STRING 的范例。因此,老是应该把 <ENABLE_PREPROCESSING> 标志配置为 Yes。
在文档中,大概但愿只展开特 定的宏。为此,除了把 <ENABLE_PREPROCESSING> 和 <MACRO_EXPANSION> 标志配置为 Yes 之外,还必需把 <EXPAND_ONLY_PREDEF> 标志配置为 Yes(这个 标志在默认环境下配置为 No),并在 <PREDEFINED> 或 <EXPAND_AS_DEFINED> 标志中提供宏的细节。请思量 清单 7 中的代码,这里只希 望展开宏 CONTAINER。
清单 7. 包括多个宏的C++ 源代码
#p#分页标题#e#
#ifdef USE_ROPE
#define STRING std::rope
#else
#define STRING std::string
#endif
#if ALLOW_RANDOM_ACCESS == 1
#define CONTAINER std::vector
#else
#define CONTAINER std::list
#endif
static STRING name;
static CONTAINER gList;
清 单 8 给出设置文件。
清单 8. 答允有选择地展开宏的 Doxyfile
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
EXPAND_AS_DEFINED = CONTAINER
…
下面的doxygen 输出只展开了 CONTAINER:
Defines
#define STRING std::string
#define CONTAINER std::list
Variables
static STRING name
static std::list gList
留意,只有 CONTAINER 宏被展开了。在 <MACRO_EXPANSION> 和 <EXPAND_ONLY_PREDEF> 都配置为 Yes 的环境下,<EXPAND_AS_DEFINED> 标志只选择展开等号操纵符右边列出的宏。
对付预处理惩罚进程,要留意的最后一个 标志是<PREDEFINED>。就像用-D 开关向 C++ 编译器通报预处理惩罚器界说一样,利用 这个标志界说宏。请思量 清单 9 中的Doxyfile。
清单 9. 界说了宏展开标志的 Doxyfile
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
EXPAND_AS_DEFINED =
PREDEFINED = USE_ROPE= \
ALLOW_RANDOM_ACCESS=1
下面是doxygen生成的输出:
Defines
#define USE_CROPE
#define STRING std::rope
#define CONTAINER std::vector
Variables
static std::rope name
static std::vector gList
在利用<PREDEFINED> 标志时,宏应该界说为 <macro name>=<value> 形式。假如不提供值,好比简朴的#define,那么只利用 <macro name>=<spaces> 即可。多个宏界说以空格或反斜杠(\)脱离。
从文档生成进程中解除特定文件或目次
在 Doxyfile 中的 <EXCLUDE> 标志中,添加不该该为其生成文档的文件或目次(以空格脱离)。因此 ,假如提供了源代码条理布局的根,并要跳过某些子目次,这将很是有用。譬喻,假如层 次布局的根是src_root,但愿在文档生成进程中跳过 examples/ 和 test/memoryleaks 文件夹,Doxyfile 应该像 清单 10 这样。
清单 10. 利用EXCLUDE 标志的 Doxyfile
INPUT = /home/user1/src_root
EXCLUDE = /home/user1/src_root/examples /home/user1/src_root/test/memoryleaks
…
生成图形和图表
在默认环境下,Doxyfile 把 <CLASS_DIAGRAMS> 标志配置为 Yes。这个标志用来生成类条理布局图。要想生成 更好的视图,可以从 Graphviz 下载站点 下载 dot 东西。Doxyfile 中的以下标志用来 生成图表:
<CLASS_DIAGRAMS>:在 Doxyfile 中这个标志默认配置为 Yes 。假如这个标志配置为 No,就不生成担任条理布局图。
<HAVE_DOT>:假如 这个标志配置为 Yes,doxygen 就利用dot 东西生成更强大的图形,好比辅佐领略类成员 及其数据布局的协作图。留意,假如这个标志配置为 Yes,<CLASS_DIAGRAMS> 标 记就无效了。
<CLASS_GRAPH>:假如 <HAVE_DOT> 标志和这个标志同 时配置为 Yes,就利用dot生成担任条理布局图,并且其外观比只利用 <CLASS_DIAGRAMS> 时更富厚。
<COLLABORATION_GRAPH>:假如 <HAVE_DOT> 标志和这个标志同时配置为 Yes,doxygen 会生成协作图(尚有担任 图),显示各个类成员(即包括)及其担任条理布局。
清单 11 提供一个利用一 些数据布局的示例。留意,在设置文件中 <HAVE_DOT>、<CLASS_GRAPH> 和 <COLLABORATION_GRAPH> 标志都配置为 Yes。
清单 11. C++ 类和布局示例
struct D {
int d;
};
class A {
int a;
};
class B : public A {
int b;
};
class C : public B {
int c;
D d;
};
图 1 给出 doxygen 的输出。
图 1. 利用dot 东西生成的类担任图和协作图
代码 文档样式
到今朝为止,我们都是利用doxygen 从原本没有文档的代码中提取信息 。可是,doxygen 也勉励利用文档样式和语法,这有助于生成更具体的文档。本节接头 doxygen 勉励在 C/C++ 代码中利用的一些常用标志。更多信息拜见 参考资料。
每个代码元素有两种描写:简短的和具体的。简短描写凡是是单行的。函数和类要领尚有 第三种描写体内描写(in-body description),这种描写把在函数体中找到的所有注释 块会合在一起。较量常用的一些 doxygen 标志和注释样式如下:
简短描写:利用 单行的C++ 注释,或利用<\brief> 标志。
具体描写:利用JavaDoc 式的注 释 /** … test … */(留意开头的两个星号 [*])或 Qt 式的注释 /*! … text … */。
体内描写:类、布局、连系体和名称空间等 C++ 元素都有本身的标志,好比 <\class>、<\struct>、<\union> 和 <\namespace>。
#p#分页标题#e#
为了为全局函数、变量和列举范例生成文档,必需先对对应的文件利用 <\file> 标志。清单 12 给出的示例包括用于四种元素的标志:函数标志(<\fn>)、函数参数标志(<\param>)、变量名标志(<\var>)、用于 #define 的标志(<\def>)以及用来暗示与一个代码片断相关的问题的标志(<\warning>)。
清单 12. 典范的doxygen 标志及其利用要领
/*! \file globaldecls.h
\brief Place to look for global variables, enums, functions
and macro definitions
*/
/** \var const int fileSize
\brief Default size of the file on disk
*/
const int fileSize = 1048576;
/** \def SHIFT(value, length)
\brief Left shift value by length in bits
*/
#define SHIFT(value, length) ((value) << (length))
/** \fn bool check_for_io_errors(FILE* fp)
\brief Checks if a file is corrupted or not
\param fp Pointer to an already opened file
\warning Not thread safe!
*/
bool check_for_io_errors(FILE* fp);
下面是生成的文档:
Defines
#define SHIFT (value, length) ((value) << (length))
Left shift value by length in bits.
Functions
bool check_for_io_errors (FILE *fp)
Checks if a file is corrupted or not.
Variables
const int fileSize = 1048576;
Function Documentation
bool check_for_io_errors (FILE* fp)
Checks if a file is corrupted or not.
Parameters
fp: Pointer to an already opened file
Warning
Not thread safe!
竣事语
本文接头如何用 doxygen 从遗留的C/C++ 代码提取出大量相关信息。假如用doxygen 标志生成代码文档, doxygen 会以容易阅读的名目生成输出。只要以适当的方法利用,doxygen 就可以辅佐任 何开拓人员维护和打点遗留系统。