缘起
在搜索dot和Graphviz时,看到doxygen,了解doxygen利用dot来绘制方法的关系图。后来,在fish(friend interactive shell)的帮助文档时,看到文档是由doxygen生成的。很好奇,doxygen居然可以生成html文档,就做了一下资料收集,整理出这么个文档出来。
正文
1. Doxygen简介
Doxygen是一种开源跨平台的,以类似JavaDoc风格描述的文档系统,完全支持C、C++、Java、Objective-C和IDL语言,部分支持PHP、C#。注释的语法与Qt-Doc、KDoc和JavaDoc兼容。其可以提供三个方面的帮助:
1.它可以从一组带有文档(即注释)的源文件中生成在线文档(HTML格式),或者离线参考手册(LATEX格式)。同时还支持生成RTF(MS-Word)、Postscript、PDF、压缩的HTML和UNIX man手册。文档是从源文件注释中直接提取的,从而十分容易保持文档和源码的一致。
2.doxygen可配置,用以从没有标注文档的源文件中提取代码结构。这对于要在大量源文件中快速地找到所需的东西来说是非常有用的。通过包含依赖图(include dependency graphs)、继承图(inheritance diagram)和协作图(collaboration diagram)等手段(它们都是自动生成的),可以使不同成分之间的关系可视化。
3.还可以“滥用”doxygen,创建普通文档。”
一个好的程序员在写程序时,都会在适当的地方加上合适的批注。如果以符合某种格式的方式撰写批注,就能使用工具程序依据程序结构及批注产生出漂亮的文档。
2. 支持语言和格式
支持的语言:C/C++,Java,Objective-C,Python,IDL (Corba, Microsoft及KDE-DCOP类型),Fortran,VHDL(一种硬件描述语言),PHP,C#
备注:Ruby的问档工具为Rdoc
输出格式: HTML,XML,LaTeX(间接支持PDF),RTF (MS-Word),PostScript,Unix Man Page
3. 安装
Ubuntu/debian:sudo apt-get install doxygen
官方下载二进制包(Linux,windows,Mac os各种平台在官方网站都有的下)或源码编译(./configure-->make-->make install)。源码编译可能比较麻烦,存在一些前置条件:graphviz,flex,python,make以及g++之类的工具。不过我编译的时候,没有出现问题,那些前置条件恰好都满足,遇到不满足的,apt-get install就行了。
4. 简单使用
Doxygen使用可以分为两个部分:1.特定格式的注释的撰写(主要工作) 2.利用Doxygen工具来生成文档
下面首先介绍Doxygen支持的注释格式,然后介绍如何使用doxygen来生成文档。
4.1. 编写注释
一般而言,要为每个类、以及该类的重要成员函数增加短注释和长注释。短注释应给出类或函数的基本信息的简要描述。而较长的注释给出更长和更完整的描述。类的短注释和长注释,以及成员函数的简短描述,将放在头文件中。成员函数的长注释将出现在成员函数的实现出现的地方。
4.1.1. 注释风格
使用doxygen的第一步是在代码中插入doxygen风格的注释。代码附加的注释块通常由一行或多行组成,其中包含一个概要说明和详细说明,可以使用多种不同风格的doxygen注释:
1)JavaDoc类型的多行注释
/**
* ... text ...
*/
2)Qt风格的多行注释:
/*!
...text...
*/
3)单行注释:
//! ... one line of text ...
/// ... one line of text ...
http://www.slac.stanford.edu/exp/glast/ground/software/doxygen_examples/v1/class_CsICluster.html提供一个可参照的样例HTML文档。
4.1.2. 常用注释格式
通常的选择上面的一、两种注释风格,遇到头文件中各种类型定义,关键变量、宏的定义,在其前或者后使用@brief定义其简要说明,空一行后继续写其详细的注释即可。
函数是需要注释说明的部分。除了定义其简要说明以及详细注释,还可以使用param命令对其各个参数进行注释,使用return命令对返回值进行注释。函数的参数格式如下:
格式1:
/**
<A short one line description>
<Longer description>
<May span multiple lines or paragraphs as needed>
@param Description of method's or function's input parameter
@param ...
@return Description of the return value
*/
格式2:
/**
* <A short one line description>
*
* <Longer description>
* <May span multiple lines or paragraphs as needed>
*
* @param Description of method's or function's input parameter
* @param ...
* @return Description of the return value
*/
格式3:
/// <A short one line description>
///
/// <Longer description>
/// <May span multiple lines or paragraphs as needed>
///
/// @param Description of method's or function's input parameter
/// @param ...
/// @return Description of the return value
C++中常使用的格式:
/**
* @file
* @author John Doe <jdoe@example.com>
* @version 1.0
*
* @section LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details at
* http://www.gnu.org/copyleft/gpl.html
*
* @section DESCRIPTION
*
* The time class represents a moment of time.
*/
class Time {
public:
/**
* Constructor that sets the time to a given value.
*
* @param timemillis Number of milliseconds
* passed since Jan 1, 1970.
*/
Time (int timemillis) {
// the code
}
/**
* Get the current time.
*
* @return A time object set to the current time.
*/
static Time now () {
// the code
}
};
进行设计时,通常有模块的概念,一个模块可能有多个类或者函数组成,完成某个特定功能的代码的集合。为了这个概念进行注释,doxygen提供了group命令,生成的模块的注释会单独放在一个模块的页面中。使用下面的格式定义一个group。
group中的代码可以有自己的注释。单纯定义一个模块,去除{ 和}命令即可。任何其他代码项(比如类、函数、甚至文件)如果要加入到某个模块,可以在其doxygen注释中使用ingroup命令即可。Group之间使用ingroup命令,可以组成树状关系。
将多个代码项一起添加到某个模块中可以使用addtogroup命令,格式和defgroup相似。对于某几个功能类似的代码项(比如类、函数、变量)等,如果希望一起添加注释,而又不想提升到模块的概念,可以通过下面的方式:
//@{
code...
//@}
4.1.3. 常用注释命令
doxygen通过注释命令识别注释中需要特殊处理的注释,比如函数的参数、返回值进行突出显示。上面也提到了一些注释命令(如:brief、param、return、以及group相关的命令),命令都以'\'或'@'开始,二者无区别,下面对其他一些常用的注释命令进行解释说明:
@exception <exception-object> {exception description} 对一个异常对象进行注释。
@warning {warning message } 一些需要注意的事情
@todo { things to be done } 对将要做的事情进行注释
@see {comment with reference to other items } 一段包含其他部分引用的注释,中间包含对其他代码项的名称,自动产生对其的引用链接。
@relates <name> 通常用做把非成员函数的注释文档包含在类的说明文档中。
@since {text} 通常用来说明从什么版本、时间写此部分代码。
@deprecated
@pre { description of the precondition } 用来说明代码项的前提条件。
@post { description of the postcondition } 用来说明代码项之后的使用条件。
@code 在注释中开始说明一段代码,直到@endcode命令。
@endcode 注释中代码段的结束。
在doxygen中有一些特殊命令用来增强所生成的文档。
\author 说明作者
\mainpage 指定用以填充主页面的注释的内容。
\section 指定章节信息。
\image 在你的文档中插入图像,可以用在任何注释中。其语法如下所示:
\image html mypicture.gif
注意:doxygen通过IMAGE_PATH的变量在指定的目录中查找图像文件,且并非所有格式都支持所有的图像类型。
到此为止,常用的doxygen的注释格式讨论完毕,可以按照一定的格式撰写doxygen识别的注释,不过注释中应该写些什么,如何撰写有效的注释?
4.1.4. 注释的书写
注释应该怎么写,写多还是写少。过多的注释甚至会干扰对代码的阅读,过少又不足以解释清楚。写注释的一个总的原则就是注释应该尽量用来表明作者的意图,从解决问题的层次上进行注释,而是重复性介绍一些显然易见的东西。
写注释的过程是首先使用注释勾勒出代码的主要框架,然后根据注释撰写相应的代码。对各种主要的数据结构、输出的函数、多个函数公用的变量进行详细地注释。对代码中控制结构,单一目的的语句集进行注释。下面是一些写注释时需要注意的要点:
- l 避免对单独语句进行注释;
- l 通过注释解释为什么这么做、或者要做什么,使代码的读者可以只阅读注释理解代码;
- l 对读者可能会有疑问的地方进行注释;
- l 对数据定义进行注释,而不是对其使用过程进行注释;
- l 对于难于理解的代码,进行改写,而不要试图通过注释加以说明;
- l 对关键的控制结构进行注释;
- l 对数据和函数的边界、使用前提等进行注释;
4.2. 生成文档
Doxygen的生成文档的步骤非常简单:
1)使用doxygen生成一个配置文件的模板:
doxygen [-s] -g [configName]
如果configName是'-'那么doxygen将会把结果写到标准输出。
2)使用doxygen更新旧的配置文件:
doxygen [-s] -u [configName]
3)根据已经存在的配置文件,使用doxygen生成文档:
doxygen [configName]
如果configName是'-'那么doxygen将会从标准输入读取配置信息。
4)使用doxygen生成RTF,HTML,或者Latex风格的模板文件:
RTF格式:doxygen -w rtf styleSheetFile
HTML格式:doxygen -w html headerFile footerFile styleSheetFile [configFile]
LaTex格式:doxygen -w latex headerFile styleSheetFile [configFile]
5)使用doxygen生成rtf扩展文件??
RTF格式:doxygen -e rtf extensionsFile
如果指定了-s那么配置文件中的注释将会被忽略。如果配置名被忽略了,那么'Doxy-file'将被做为默认的文件使用。
安装doxygen-doc会获得如何使用doxygen的更多信息(即$sudo apt-get install doxygen-doc)。可以查看/usr/share/doc/doxygen。
使用Doxyfile时需要设置一些参数。这里三个有趣的参数,其他的请参考doxygen的配置文件。
● INPUT:此参数指定doxygen在其中搜索源码的目录。
● FILE_PATTERNS:此参数指定doxygen所要解析的文件的类型。
● IMAGE_PATH:此参数指定doxygen在哪里查找使用/image命令包含的图像。
设置完参数就可以运行doxygen。假定配置文件为Doxyfile,执行
doxygen Doxyfile
doxygen将解析你指定的所有文件。缺省地,HTML输出将被放在叫作html/的目录中(这也可在Doxyfile中改变)。
4.2.1. Doxygen的配置文件
Doxygen在生成文档时存在很多可配置的选项,doxygen -g可以生成缺省的配置文件。doxygen配置文件的格式为unix下配置文件的格式:
l 注释'#'开始;
l tag = value[,value2...];
l 对于多值的情况可以使用 tag += value [,value2...]。
对doxygen的配置文件的修改分为两类:一种就是输出选项,控制如何解释源代码、如何输出;一种就是项目或程序相关的信息,比如项目名称、源代码目录、输出文档目录等。对于第一种配置,通常所有项目可以共用相同的配置,而第二种配置是每个项目或程序必须设置的。下面选择重要的,有可能需要修改的选项进行解释说明,其他选项在配置文件都有详细解释。
TAG | 缺省值 | 含义 |
PROJECT_NAME |
| 项目名称 |
PROJECT_NUMBER |
| 可以理解为版本信息 |
OUTPUT_DIRECTORY |
| 输出文件到的目录,相对目录(doxygen运行目录)或者绝对目录 |
INPUT |
| 代码文件或者代码所在目录,使用空格分割 |
FILE_PATTERNS | *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h*.hh *.hxx *.hpp *.h++ *.idl *.odl | 指定INPUT的目录中特定文件,如:*.cpp *.c *.h |
RECURSIVE | NO | 是否递归INPUT中目录的子目录 |
EXCLUDE |
| 在INPUT目录中需要忽略的子目录 |
EXCLUDE_PATTERNS |
| 明确指定的在INPUT目录中需要忽略的文件,如:FromOut*.cpp |
OUTPUT_LANGUAGE |
| English 生成文档的语言,当前支持2、30种语言,国内用户可以设置为Chinese |
DOXYFILE_ENCODING | UTF-8 | 文件编码格式 |
EXTRACT_ALL | NO | 为NO,只解释有doxygen格式注释的代码;为YES,解析所有代码,即使没有注释。类的私有成员和所有的静态项由EXTRACT_PRIVATE和 EXTRACT_STATIC控制 |
EXTRACT_PRIVATE | NO | 是否解析类的私有成员 |
EXTRACT_STATIC | NO | 是否解析静态项 |
EXTRACT_LOCAL_CLASSES | YES | 是否解析源文件(cpp文件)中定义的类 |
SOURCE_BROWSER | NO | 如果为YES,源代码文件会被包含在文档中 |
INLINE_SOURCES | NO | 如果为YES,函数和类的实现代码被包含在文档中 |
ALPHABETICAL_INDEX | NO | 生成一个字母序的列表,有很多类、结构等项时建议设为YES |
GENERATE_HTML | YES | 是否生成HTML格式文档 |
GENERATE_HTMLHELP | NO | 是否生成压缩HTML格式文档(.chm) |
GENERATE_LATEX | YES | 是否生成latex格式的文档 |
GENERATE_RTF | NO | 是否生成RTF格式的文档 |
GENERATE_MAN | NO | 是否生成man格式文档 |
GENERATE_XML | NO | 是否生成XML格式文档 |
4.3. 使用实例
下面使用一个简单的例子来测试Doxygen,程序的结构是
./src/main.cpp
./src/subModule/myClass.h
./src/subModule/myClass.h
./src/main.cpp
./lib/say.h
./lib/say.cpp
可下载测试文件的链接为: test.zip
使用命令doxygen -g test 生成名为test的doxygen配置文件,对其中的配置项作出如下修改:
#给出所有文档的输出目录
OUTPUT_DIRECTORY = doc
#设置使用的语言
OUTPUT_LANGUAGE = Chinese
#生成chm格式的压缩html文档
GENERATE_HTMLHELP = YES
#生成latex文档
GENERATE_LATEX = YES
#指定doxygen分析的输入文件(目录)
INPUT = src lib
#指定分析的文件的类型(扩展名)
INCLUDE_FILE_PATTERNS = *.cpp *.h
#递归查找INPUT中的文件
RECURSIVE = YES
#处理完一个函数的文档之后,对函数调用的函数也列出相关的链接。
REFERENCES_RELATION = YES
截图显示:
Html结果展示:
5. 进一步阅读
Doxygen使用总结:http://blog.chinaunix.net/uid-9525959-id-2001574.html
Doxygen中文手册(1.63):http://wenku.baidu.com/view/3b33690f33687e21af45a9c0.html
Doxygen官方主页:http://www.stack.nl/~dimitri/doxygen/
开发主页(Github)https://github.com/doxygen/doxygen
总结
Doxygen还是比较的强大的工具,花了很长时间来学习和了解这个工具。此外,自己下载源代码编译还是很有用处的,可以自己编译文档之类的,如果编译成功确实不错,但是失败的时候,也挺令人沮丧的。
有时候,觉得自己写的相关的主题的东西网上很泛滥,何必再增加重复信息。本着记录探索的过程的方式,我还是写了关于这个主题的博客,也有介绍自己的动机,并且还自认为自己写的不错(请原谅我的自恋)。
最近,写博客的方式是先在WPS(Linux版)中编写,然后复制到csdn的博客中。本地doc的文档的排版要比博客上的排版好,这里提供一个pdf版下载链接:关于Doxygen。
参考文献
1. Doxygen使用:http://blog.youkuaiyun.com/yuantao/article/details/402207
2. Doxygen使用总结:http://blog.chinaunix.net/uid-9525959-id-2001574.html
3. Doxygen中文手册(1.63):http://wenku.baidu.com/view/3b33690f33687e21af45a9c0.html
4. doxygen使用详解:http://wenku.baidu.com/view/3ad26a4279563c1ec5da71b7.html