文档与文档系统一个项目,它需要的维护的东西可以分为两个部分:代码与文档!除非一个非常小的项目,否则的话不做文档是非常危险的事。做项目是为了什么?这是一个关键的问题,当然做项目不是为了代码,也不是为了文档,做项目是为了项目可以取得的效果。这句话讲得有一点冒险,我担心有许多人想给我一个石子,可是真理往往就是如此直白无奇。微软做Windows,它不是为了做Windows,而为了赚钱或者可能有一部分人做出一个操作系统,它会帮助人们完成许多事。试想一下,如果现在的人工智能已经相当先进了,人机交互可以像人与人交互一样,Windows还存在吗?所以总结一句:项目的目的是达到项目预期的目标。 上面的说法好像与本文的标题没有关系了,其实不然,要达到项目的目标,我们就必须通过某种手段达到。代码和文档是手段!代码与文档哪个更重要这个问题本身就是荒诞的,我想问你左手和右手哪个更重要?要是你是左撇子,可能会说左手更重要;可要是你是一个右撇子呢?代码可能离我们目标更直接一些,因为程序最终都以某种形式的代码来体现的,但是没有文档是没有办法完成代码的。 本文不说代码,本文说的文档。文档大致分为两种:设计文档和解释文档。前面那个词大家经常听到,后面这个词是我自己发明的。设计文档指导代码的写作,而解释文档解释代码为什么是如此;前者用于写代码,后者用于读代码!写代码的原因大家都明白,读代码原因可能还有疑惑,读是为了更好地写,也是为了更好的设计。 需要维护大量文档的时候,文档工作就变成一个系统工作,此时它需要的不仅仅是人的热情,同时它更需要一个机制来作为保证,如此产生了文件系统──用于维护大量文档的机制或方法。设计文档与解释文档存在区别,设计文档是由无到有的过程,解释文档则与一个解释对象关联。前者关心的核心问题是如何设计一个可用的作品,后者关心的是解释哪个对象,所以任务是不同的两个任务,相应的文档系统就不一样。本文要介绍的就是解释文档的维护系统──Doxygen,强大的源代码解释性文档维护系统。 Doxygen概述Doxygen把自己定义为“Source code documentation generator tool”(源代码文档生成工具)。所以Doxygen只是一个工具,它帮助我维护解释文档,并同时提供一种维护的机制,在这种机制下,工作会变得简单且有保证。Doxygen可以与C++、C、Java、Objective-C、Python、Fortran、PHP, C#等多种语言的源代码一起工作,并且用户可以自定义新语言的支持。Doxygen为做下面的事而设计:
Doxygen是高度可移植的,它可以运行在Linux、Windows、Mac OS以及大多数UNIX系统上。它在GPL协议下发布源代码,用户可以在GPL的许可下使用或复制Doxygen的代码。 Doxygen为我们编写与维护代码提供了一个机制,这个机制就是:代码即文档,通过结构化注释来感到编写与维护文档的效果,代码的结构就是文档的结构,代码的注释就是文档的内容。 Doxygen有3个工具的集合,其中doxygen是工具集的核心,此外还存在一个名为doxytag的工具,用于合并已有的文档,剩下的一个就是前面的两个工具的GUI前端doxywizard。请尝试查看手册页来清楚地了解这些程序。下面的图片工具集的工作流程,图片来自doxygen.org 快速使用Doxygen注意:本文不准备介绍doxywizard这个GUI工作,因为它非常简单,在线帮助也非常全面。当然是英文的。 假设你现在已经有一个项目,要使用Doxygen,最简单的尝试只需要3步,当然这只是最简单的尝试,现实中可以要考虑更多的东西。
要使用Doxygen生成文档就这么简单,为什么现在不是试试呢。然而细心的读者可能已经注意到了,此时我们没有对代码进行格式化注释,所以生成的文档只是生成代码的结构──等等,如果你没有告诉Doxygen生成代码的结构,默认它只生成文档化之后的代码文档,所以你第一次运行的结果可能只是生产了空文档,看上去是文档,结果里面没有任何内容。 Doxygen工程设置在本文的快速指南里,我们已经看到一个项目的文档工作需要一个设置文件,这个设置文件称为“Doxygen工程设置”文件,因为文档是当作一个工程来管理和实施。默认的情况下,这个工程设置文件存在于我们运行doxygen -g的目录里,除非我们手工指定。这个文件非常大,可见Doxygen支持的设置非常多,同时设置文件里存在对每一个设置选项详细的说明,从功用到可用值,非常详尽。所以它本身就是一个非常合适的学习资料。许多时候我们不需要设置太多选项就可以让Doxygen像我们想要的方式运行。在这里我们会讲述一些重要的选项。 每个选项有一个名字,接着会一个等于号(=),之后就是相应的选项值,如果同一个名字出现多次,那么最后一次的设置将重写之前的设置,也就是最后一次设置才是有效。总之这里规则完全等同于一个典型的UNIX风格的设置语法。
备注:Doxygen产生的默认设置文件中含有大量注释,应该抽点时间看看,如果你想对Doxygen有更多定制的话,当然对于大多数人说可能就这个需要了,因为Doxygen默认值可以应付大多数情况。 注释源代码Doxygen不是为了某一种源代码准备的,所以Doxygen支持多种风格的源代码注释,此外就算是一种源代码也可能存在多种风格的注释,这是因为已经存在其它注释风格,Doxygen并不想让自己变得很学习和使用。在众多的注释风格中,我们应该如何选择使用呢?其实问题不在于使用哪种风格的注释,问题选择之后要统一而一致的使用同一种风格的注释。正如C++源代码标识符命名一样,无论哪种风格的命名都没有优势或劣势,只有习惯的差异,所以选择一种吧,然后就一直使用这一种。 基于上面的讨论,本文不会去讨论所有可能的风格,事实上Doxygen支持自定义风格的注释,这是Doxygen可扩展的表现。本文只讨论本人使用的风格,当然在我看来,它们似乎更合适,但记住无论哪种风格都一样的,不一样是人。上面的参考文件也给出了作者习惯的风格,我也受到他影响。 现在有一个问题,如何表述我所以使用的风格呢?其实最好的方法就是代码,所以本文下面将给出一个比较全面的示例代码,并在恰当的时候给出说明或解释。 /** * @file doxygen.cpp * @author 刘广保 easyeagel@gmx.com http://www. * * @brief 这是一个使用Doxygen工具的示例 * * @details 大家注意到没有,如上面的\@file等等实际上是Doxygen支持的命令 \n * 命令是用来帮助Doxygen对相应的信息定位的工具, \n * 上面3个命令意义大家一看就明白了。\n * Doxygen存在大量命令,官方手册有命令:<a href="http://www./~dimitri/doxygen/commands.html">列表</a> */ /** * @brief 一个示例类 */ class Example { public: /** * @brief 打印内部保存的值 * @return 自身的引用 */ Example& print() { std::cout << _num << std::endl; return *this; } /** * @brief 设置内部的值 * @param num 需要设置的值 * @return 自身的引用 */ Example& set(int num) { _num=num; return *this; } private: int _num; } 注意:应该去官方文档中看看有哪些命令是可用的,这样就可以把注释做得更好了。 来自互动百科:http://www.hudong.com/wiki/Doxygen Doxygen是一种开源跨平台的,以类似JavaDoc风格描述的文档系统,完全支持C、C++、Java、Objective-C和IDL语言,部分支持PHP、C#。注释的语法与Qt-Doc、KDoc和JavaDoc兼容。Doxgen可以从一套归档源文件开始,生成HTML格式的在线类浏览器,或离线的LATEX、RTF参考手册。 Doxygen - Doxygen简介Doxygen 是一个程序的文件产生工具,可将程序中的特定批注转换成为说明文件。通常我们在写程序时,或多或少都会写上批注,但是对于其它人而言,要直接探索程序里的批注,与打捞铁达尼号同样的辛苦。大部分有用的批注都是属于针对函式,类别等等的说明。所以,如果能依据程序本身的结构,将批注经过处理重新整理成为一个纯粹的参考手册,对于后面利用您的程序代码的人而言将会减少许多的负担。不过,反过来说,整理文件的工作对于您来说,就是沉重的负担。 一个好的程序设计师,在写程序时,都会在适当的地方加上合适的批注。如果,能够在撰写批注时,稍微符合某种格式,接着就可以透过一个工具程序依据程序结构及您的批注产生出漂亮的文件。这将令许多工作繁重的程序设计师有时间多喝几杯咖啡。
Doxygen 就是这样的一个工具。在您写批注时,稍微按照一些它所制订的规则。接着,他就可以帮您产生出漂亮的文件了。因此,Doxygen 的使用可分为两大部分。首先是特定格式的批注撰写,第二便是利用Doxygen的工具来产生文件。
目前Doxygen可处理的程序语言包含: * C/C++ * Java * IDL (Corba, Microsoft及KDE-DCOP类型)
而可产生出来的文件格式有: * HTML * XML * LaTeX * RTF * Unix Man Page 而其中还可衍生出不少其它格式。如有了LaTeX 文件后,就可以透过一些工具产生出PS或是PDF档案。 在多国语言的支持方面,Doxygen 目前可支持的约有2,30种。自Doxygen 1.2.16开始支持繁体中文(这正是小弟做的好事)。所以在目前一些Open Source 的程序文档管理器中,Doxygen 算是相当完整的一套。在程序语言处理上面,Doxygen也算是少数在Borland C++ Builder 的语法下还能够正常运作的工具之一(若非如此,小弟也不会推荐它)。 本文的目的是希望在经过仔细阅读本文之后能够给大家一个概略性的了解。以便可以很容易的上手使用Doxygen。至于Doxygen本身的详细使用,各位可以参考随着Doxygen 所附的文件。实际上,Doxygen自己的使用手册就是使用Doxygen 产生的。您可以看到他实际上能够产生远比Reference Book更复杂的文件。 Doxygen 的安装可说十分的简单,本文仅介绍binary档案的安装,若您有兴趣从source code重新compile起来,请自行查阅参考手册。 首先,请您先至doxygen 的网站上面抓取最新版本的doxygen 回来。目前,只要您是Linux, Solaris, Mac OS X, HP-UX, 甚至是UnixWare,都有compile好的binary版本可以抓取。如果是Windows 95/98/ME/NT/2000/XP,甚至还有Setup的版本可以抓取。所以安装过程可说十分简单。只要给予正确的安装目录,相信一般在安装上是不会遇到什么问题的。 另外,如果您是Linux或是Windows,可以另外抓取Doxygen Wizard的程序。这是一个辅助工具,可以很快的帮您建立一个Doxygen 的组态档案。透过这个组态档案,您就可以很快的将文件产生出来。另外,若没有使用Doxygen Wizard,还是可以使用一般的文字编辑器将这个组态档制作出来。 若安装成功,您应该可以看到doxygen 这个执行文件出现在您的系统中。若是Windows 平台,则可看到在程序集中有Doxygen 这个Folder出现。 设定Project的doxygen组态 Doxygen 产生文件可以分为三个步骤。一是为Project 建立组态档,二是在程序代码中加上符合Doxygen所定义批注格式。三是使用Doxygen来产生批注。 因此,第一步就是为您的Project 制作Doxygen 的组态档案。这个所谓的组态档案,格式其实与很简单。就是一些Key 与值的设定。每个设定为一行。若第一行开头为"#" 表示该行为批注。Doxygen 会忽略它。每个设定行的格式有两种,分别如下: TAG = value [value, ...] 及 TAG += value [value, ...] 第一种形式是最常见的,也就是要设定一个TAG (也就是一个Key ),他的值为右边所定义的部分。原则上每个值都是单一的英文字,如果您要定义的值有空格符包含在内,可使用双引号将它括住。如果要定义的值超过一个以上,可使用逗号","予以分隔开来。 如果您要定义的TAG 是属于表列型态的,也就是他会有很多的值分别以逗号隔开。在Doxygen 组态档中允许您在不同的地方重复定义。只是后面的定义应使用上面所说的第二种形式。此种形式会将前后两个定义的值合并在一起。 知道这个基本格式后,剩下就是根据各个TAG 的意义来进行设定。关于TAG 的定义很多,此处我们仅针对必要用到的TAG 进行说明,剩下的部分请自行翻阅使用说明。 由于Doxygen 的TAG 还算不少,为了方便使用,Doxygen 自身提供了一个方便的选项,可以帮您建立一份空白的Doxygen档案(Doxygen 是Doxygen 预设的组态档名)。 > doxygen Doxygen
透过这个命令,您可以得到一个Doxygen 档案,接下来就可使用一般的文字编辑器来进行编辑。 下面将针对几个必要的TAG 进行说明: PROJECT_NAME Project 的名字,以一个单字为主,多个单字请使用双引号括住。 PROJECT_VERSION Project的版本号码。 OUTPUT_DIRECTORY 输出路径。产生的文件会放在这个路径之下。如果没有填这个路径,将会以目前所在路径来作为输出路径。 OUTPUT_LANGUAGE 输出语言。预设为English。1.2.16 版后,您可以使用Chinese-Traditional 来输出中文繁体的格式。 INPUT 指定加载或找寻要处理的程序代码档案路径。这边是一个表列式的型态。并且可指定档案及路径。举例来说若您有a.c, b.c, c.c 三个档案。您可使用INPUT = a.c, b.c, c.c 的方式。若您给定一个目录,该目录下面所有档案都会被处理。 FILE_PATTERNS 如果您的INPUT Tag 中指定了目录。您可以透过这个Tag来要求Doxygen在处理时,只针对特定的档案进行动作。例如:您希望对目录下的扩展名为.c, .cpp及.h的档案作处理。您可设定FILE_PATTERNS = *.c, *.cpp, *.h。 RECURSIVE 这是一个布尔值的Tag,只接受YES或NO。当设定为YES时,INPUT所指定目录的所有子目录都会被处理。 EXCLUDE 如果您有某几个特定档案或是目录,不希望经过Doxygen处理。您可在这个Tag中指定。 EXCLUDE_PATTERNS 类似于FILE_PATTERNS的用法,只是这个Tag是供EXCLUDE所使用。 SOURCE_BROWSER 如果设定为YES,则Doxygen会产生出源文件的列表,以供查阅。 INLINE_SOURCES 如果设定为YES ,则程序代码也会被嵌入于说明文件中。 ALPHABETICAL_INDEX 如果设定为YES,则一个依照字母排序的列表会加入在产生的文件中。 GENERATE_HTML 若设定为YES ,就会产生HTML版本的说明文件。HTML文件是Doxygen预设产生的格式之一。 HTML_OUTPUT HTML文件的输出目录。这是一个相对路径,所以实际的路径为OUTPUT_DIRECTORY加上HTML_OUTPUT。这个设定预设为html。 HTML_FILE_EXTENSION HTML文件的扩展名。预设为.html。 HTML_HEADER 要使用在每一页HTML文件中的Header。如果没有指定,Doxygen会使用自己预设的Header。 HTML_FOOTER 要使用在每一页HTML文件中的Footer。如果没有指定,Doxygen会使用自己预设的Footer。 HTML_STYLESHEET 您可给定一个CSS 的设定,让HTML的输出结果更完美。 GENERATE_HTMLHELP 如设定为YES,Doxygen会产生一个索引文件。这个索引文件在您需要制作windows 上的HTML格式的HELP档案时会用的上。 GENERATE_TREEVIEW 若设定为YES,Doxygen会帮您产生一个树状结构,在画面左侧。这个树状结构是以JavaScript所写成。所以需要新版的Browser才能正确显示。 TREEVIEW_WIDTH 用来设定树状结构在画面上的宽度。 GENERATE_LATEX 设定为YES 时,会产生LaTeX 的文件。不过您的系统必需要有安装LaTeX 的相关工具。 LATEX_OUTPUT LaTeX文件的输出目录,与HTML_OUTPUT用法相同,一样是指在OUTPUT_DIRECTORY之下的路径。预设为latex。 LATEX_CMD_NAME LaTeX程序的命令名称及档案所在。预设为latex。 GENERATE_RTF 若设定为YES ,则会产生RTF 格式的说明档。 RTF_OUTPUT 与HTML_OUTPUT 用法相同,用来指定RTF 输出档案路径。预设为rtf。 GENERATE_MAN 若设定为YES ,则会产生Unix Man Page 格式的说明文件。 MAN_OUTPUT 与HTML_OUTPUT 用法相同,用来指定Man Page的输出目录。预设为man。 GENERATE_XML 若设定为YES ,则会产生XML 格式的说明文件。 ENABLE_PREPROCESSING 若设定为YES ,则Doxygen 会启动C 的前置处理器来处理原始档。 PREDEFINED 可以让您自行定义一些宏。类似于gcc 中的-D选项。
若上面这些基本的Tag 都设定正确,接下来就是将您的Source Code批注修改成为正确的格式。若您觉得用一般文字编辑器来编辑组态档 很麻烦,建议您可以使用Doxygen Wizard这个工具程序。他可以很快的建构出您所需要的Doxygen档案。 并非所有程序代码中的批注都会被Doxygen 所处理。您必需依照正确的格式撰写。原则上,Doxygen 仅处理与程序结构相关的批注,如 Function,Class ,档案的批注等。对于Function内部的批注则不做处理。Doxygen可处理下面几种类型的批注。 JavaDoc类型: /** * ... 批注 ... */
Qt类型: /*! * ... 批注 ... */
单行型式的批注: /// ... 批注 ... 或 //! ... 批注 ...
要使用哪种型态完全看自己的喜好。以笔者自己来说,大范围的注解我会使用JavaDoc 型的。单行的批注则使用"///" 的类型。
此外,由于Doxygen 对于批注是视为在解释后面的程序代码。也就是说,任何一个批注都是在说明其后的程序代码。如果要批注前面的程 式码则需用下面格式的批注符号。 /*!< ... 批注 ... */ /**< ... 批注 ... */ //!< ... 批注 ... ///< ... 批注 ...
上面这个方式并不适用于任何地方,只能用在class 的member或是function的参数上。 举例来说,若我们有下面这样的class。 class MyClass { public: int member1 ; int member2: void member_function(); }; 加上批注后,就变成这样: /** * 我的自订类别说明 ... */ class MyClass { public: int member1 ; ///< 第一个member说明 ... int member2: ///< 第二个member说明 ... int member_function(int a, int b); }; /** * 自订类别的member_funtion说明 ... * * @param a 参数a的说明 * @param b 参数b的说明 * * @return 传回a+b。 */ int MyClass::member_function( int a, int b ) { return a+b ; } 当您使用Doxygen 产生说明文件时,Doxygen 会帮您parsing 您的程式码。并且依据程序结构建立对应的文件。然后再将您的批注,依据其位置套入于正确的地方。您可能已经注意到,除了一般文字说明外,还有一些其它特别的指令,像是@param及@return 等。这正是Doxygen 另外一个重要的部分,因为一个类别或是函式其实都有固定几个要说明的部分。为了让Doxygen 能够判断,所有我们就必需使用 这些指令,来告诉Doxygen 后面的批注是在说明什么东西。Doxygen在处理时,就会帮您把这些部分做特别的处理或是排版。甚至是制作 参考连结。
首先,我们先说明在Doxygen 中对于类别或是函数批注的一个特定格式。 /** * class或function的简易说明... * * class或function的详细说明... * ... */ 上面这个例子要说的是,在Doxygen 处理一个class 或是function注解时,会先判断第一行为简易说明。这个简易说明将一直到空一行的 出现。或是遇到第一个"." 为止。之后的批注将会被视为详细说明。两者的差异在于Doxygen 在某些地方只会显示简易说明,而不显示详 细说明。如:class 或function的列表。
另一种比较清楚的方式是指定@brief的指令。这将会明确的告诉Doxygen,何者是简易说明。例如: /** * @brief class或function的简易说明... * * class或function的详细说明... * ... */ 除了这个class 及function外,Doxygen 也可针对档案做说明,条件是该批注需置于档案的前面。主要也是利用一些指令,通常这部分注 解都会放在档案的开始地方。如: /*! \file myfile.h \brief 档案简易说明 详细说明. \author 作者信息 */
如您所见,档案批注约略格式如上,请别被"\" 所搞混。其实,"\"与"@" 都是一样的,都是告诉Doxygen 后面是一个指令。两种在 Doxygen 都可使用。笔者自己比较偏好使用"@"。 接着我们来针对一些常用的指令做说明: @file 档案的批注说明。 @author 作者的信息 @brief 用于class 或function的批注中,后面为class 或function的简易说明。 @param 格式为 @param arg_name 参数说明
主要用于函式说明中,后面接参数的名字,然后再接关于该参数的说明。 @return 后面接函数传回值的说明。用于function的批注中。说明该函数的传回值。 @retval 格式为 @retval value 传回值说明
主要用于函式说明中,说明特定传回值的意义。所以后面要先接一个传回值。然后在放该传回值的说明。
Doxygen 所支持的指令很多,有些甚至是关于输出排版的控制。您可从Doxygen的使用说明中找到详尽的说明。 下面我们准备一组example.h 及example.cpp 来说明Doxygen 批注的使用方式: example.h: /** * @file 本范例的include档案。 * * 这个档案只定义example这个class。 * * @author garylee@localhost */
#define EXAMPLE_OK 0 ///< 定义EXAMPLE_OK的宏为0。
/** * @brief Example class的简易说明 * * 本范例说明Example class。 * 这是一个极为简单的范例。 * */ class Example { private: int var1 ; ///< 这是一个private的变数 public: int var2 ; ///< 这是一个public的变数成员。 int var3 ; ///< 这是另一个public的变数成员。 void ExFunc1(void); int ExFunc2(int a, char b); char *ExFunc3(char *c) ; };
example.cpp:
/** * @file 本范例的程序代码档案。 * * 这个档案用来定义example这个class的 * member function。 * * @author garylee@localhost */
/** * @brief ExFunc1的简易说明 * * ExFunc1没有任何参数及传回值。 */ void Example::ExFunc1(void) { // empty funcion. }
/** * @brief ExFunc2的简易说明 * * ExFunc3()传回两个参数相加的值。 * * @param a 用来相加的参数。 * @param b 用来相加的参数。 * @return 传回两个参数相加的结果。 */ int ExFunc2(int a, char b) { return (a+b); }
/** * @brief ExFunc3的简易说明 * * ExFunc3()只传回参数输入的指标。 * * @param c 传进的字符指针。 * @retval NULL 空字符串。 * @retval !NULL 非空字符串。 */ char * ExFunc2(char * c) { return c; }
上面这两个档案很简单的说明了Doxygen 批注的使用方式。您可依照此要领在你自己的程序代码中加上对应的批注。其实,无论您有无使用Doxygen ,都不妨依照他的格式将批注写入,一方面是依照他的格式,并不会干扰您程序的运作。另一方面,Doxygen 所定义的都是基本程序批注应当要有的东西。撰写清楚的批注是好的程序设计师应当的工作。
当您前面所有的步骤都正确无误执行后,只需要执行下面的命令就可建立出您要的文件了:
> doxygen Doxygen
如果有错误产生,请检查您的Doxygen 组态档设定是否有误,目录的存取权限是否足够。如果输出的结果不正确,请检查您的批注是否符合格式。批注的位置是否正确。举例来说,您不可在说明class 的批注与class 本身插入其它的程序代码或宣告。否则Doxygen 就无法将批注与该class对应起来。
如果您使用Doxygen Wizard,可直接使用上面的Run 的按钮或选单项目来制作说明文件。如果是产生HTML文件,在HTML_OUTPUT 所指定的目录中的index.html将是您说明文件的首页。
在中文繁体方面,目前我仅成功制作出HTML与RTF 格式的说明文件。其它格式的过程比较复杂,需要搭配其它工具, |
|