qdoc
概述1
- Qdoc是开发者用于在软件工程中生成文档的一个工具。
- 它根据qdocconf文件的指示, 从工程的源文件中提取qdoc类型注释,并以html页面或者DITA XML2文档的形式格式化到文件中。
- Qdoc在.cpp和.qdoc文件中查找注释,而不会在.h文件中查找。一条qdoc注释往往以一个前置声明符号(!)开始
Qdoc把以.qdocconf结尾的参数理解为QDoc configure file,configure file是使用者用以告诉qdoc何处存放源代码文件、头文件以及.qdoc文件,同时它也指定了以何种格式(HTML、DITA XML....)输出结果,以及输出文件的位置, 以及其它信息。
qdoc的目的文件是qhp文件,得到qhp文件后, 使用以下命令对qhp文件打包
%qtbin%\qhelpgenerator.exe %localpath%\testdoc.qhp
然后就可以把它上传到 assistant程序, 或者使用QtHelp打开。
使用qdoc 命令生成文档
这种方法适用于构建不依赖其他项目(有依赖项的处理方式见下文)的单独项目, 当用户写好注释相关文件时, 以以下方式编写 qdocconf文件。
在qdocconf中写入最小信息集
- 作为兼容, 必须添加
include(compat.qdocconf)
- 文档的输出路径
outputdir = html
- 指定和cpp源文件相对应的头文件路径。
headerdirs = .
- 指定包含了 qdoc 文件和 .cpp 文件的路径
sourcedirs = .
- 指定包含了示例源代码的路径
exampledirs = .
- 指定使用到的图片路径
imagedirs = ./images
- 指定qhp输出文件的内容
qhp.projects = testdoc 工程名称
qhp.testdoc.file = testdoc.qhp 输出名称
qhp.testdoc.namespace = com.gsp.1.0 命名空间
qhp.testdoc.virtualFolder = testdoc 依赖项引用它时,使用的名称
qhp.testdoc.indexTitle = glodon doc 索引名
qhp.testdoc.indexRoot =
- 作为兼容, 必须添加
使用qdoc命令输出文档,
`%qtbin%\qdoc %localpath%\testdoc.qdocconf -outputdir %localpath%\doc`
一些额外的重要信息
描述工程基本信息:
project = testdoc Project
description = Sample QDoc project
qhp文件的描述信息:
qhp.Qt.extraFiles = classic.css images/qt-logo.png
qhp.Qt.filterAttributes = qt 4.4.0 qtrefdoc
qhp.Qt.customFilters.Qt.name = Qt 4.4.0
qhp.Qt.customFilters.Qt.filterAttributes = qt 4.4.0
qhp.Qt.subprojects = classes overviews examples 主页面三个section
qhp.Qt.subprojects.classes.title = Classes
qhp.Qt.subprojects.classes.indexTitle = Qt's Classes
qhp.Qt.subprojects.classes.selectors = class
qhp.Qt.subprojects.overviews.title = Overviews
qhp.Qt.subprojects.overviews.indexTitle = All Overviews and HOWTOs
qhp.Qt.subprojects.overviews.selectors = fake:page,group,module
qhp.Qt.subprojects.examples.title = Tutorials and Examples
qhp.Qt.subprojects.examples.indexTitle = Qt Examples
qhp.Qt.subprojects.examples.selectors = fake:example
standard mode 和 single mode
qdoc生成文档有两种方式: standard mode 和 single mode。single mode是比较新的技术,它的准确度和速度都远远大于standard mode。 当然,一般的工程因为文档数量不多,其实两者直观上差别不大。
为什么standard mode比较慢
目前,Qt5 building system并没有使用single mode生成qdoc文档,而是使用了standard mode。当下在转换Qt4文档以识别Qt5模块化这方面,Standard mode是最简单的方法了。在Qt4中,QDoc运行一次,遍历所有的Qt4源代码文件,生成html格式的qdoc文档。在生成qdoc文档的同时,qt4 QDoc还生成了一个索引文件(index file)。这个文件用于在生成依赖于Qt的其它类库、软件产品的html文档时,序列化QDoc的操作,还可以用于把其它类库、软件产品的qdoc文档链接到qt4文档中。
在Qt5中,Qt被模块化,之后,越来越多的模块被加入到Qt5中,在5.5.时,已经有40多个独立模块了。这些模块都有着自己的文档,而不同模块的文档又存在着相互的链接和依赖。
Standard mode中,QDoc为每个模块运行了两次。第一次QDoc在某个指定的模块中运行,遍历所有的源代码文件,并根据获得的一些信息生成索引文件。这个阶段被称为“准备阶段”(prepare phase),因为它生成了索引文件,为下一步的进行做准备。第二次运行依旧遍历所有源代码文件,然后生成qdoc文档,这个阶段被称作“生成阶段”(generate mode),因为它生成了该模块的qdoc文档。
某个模块的qdoc文档可能会包含一个或者多个其它模块的html链接,例如,大部分模块的qdoc文档都有指向QtCore的链接。当一个qdoc文档包含指向其它模块的链接时,认为这个模块依赖于后者。因此当QDoc在该模块下执行生成阶段时,它必须加载所依赖模块的索引文件,以创建这些链接。
由此可知,当Qt5 Building System在生成Qt文档时,它先在每个模块中运行一次QDoc生成索引文件(准备阶段),然后又在每个模块中运行一次QDoc生成qdoc文档(生成阶段);在第二个阶段,QDoc使用那些相互依赖(链接)的索引文件生成qdoc文档,并把相互之间的链接包含进去。每一次执行QDoc,都会遍历一次源代码文件,在生成阶段还会为依赖关系遍历索引文件。两次QDoc的执行期间没有缓存信息。
- 为什么single mode比较快
顾名思义,single mode执行一次QDoc就能生成所有的qdoc文档。其实这个QDoc过程仍然会在每个模块中执行一个“准备阶段”(prepare phase),一个“生成阶段”(generate phase),但是有所不同。它从读取master qdocconf文件开始,然后读取master qdocconf里面的qdocconf文件列表,并为每个文件所在的模块执行“准备阶段”,QDoc会遍历这个模块的所有源代码文件,以生成一个语法树,然后是这个模块的索引文件——尽管这个索引文件不会在第二个阶段中被读取。这里和standard mode不同的是,QDoc会在生成索引文件以后保留语法树;所以当所有模块的准备阶段结束后,QDoc仍保留着它建立的语法树。
接着QDoc执行生成阶段,但是这里QDoc已经不用再遍历模块下的所有源代码文件,也不用再读取索引文件,因为内存中保留着该模块的语法树。
这样,QDoc仅遍历一次源代码文件,并且不用读取索引文件,这也是single mode比standard mode快得多的原因。当前的趋势是Qt Building System中会最终使用single mode。
QDoc工作过程
QDoc从读取由命令行传入的qdocconf文件开始,它把从该文件中读取到的变量保存起来,并在以后使用。例如它使用的一个较早传入的变量 outputformats,它告诉QDoc使用哪个输出生成器。默认是HTML,所以如果你不设置outputformats,QDoc会生成html文档。这通常能够满足用户的要求,但是有时候,用户会需要DITA XML类型的输出,这时需要赋值 DITAXML。
然后QDoc读取headers或者headerdirs变量,并遍历工程里的所有头文件。QDoc不会读取头文件里的注释,而是使用头文件生成一个 master tree,它包含了所有应该在文档中被包括的节点。
接下来,QDoc读取sourcedirs和sources目录,遍历所有的cpp文件和qdoc文件,并读取文件里的qdoc注释。注意qdoc注释是以!开头的(在注释内部)
使用 qdoc 生成文档
对于standard模式,文档的生成分为两个步骤: prepare 和 generate。
%qtbin%\qdoc -prepare %localpath%/testq.qdocconf -outputdir %localpath%\doc
%qtbin%\qdoc -generate %localpath%/testq.qdocconf -outputdir %localpath%\doc
也可以使用一个命令完成, 但在本质上, 还是两个步骤:
%qtbin%\qdoc %localpath%/testq.qdocconf -outputdir %localpath%\doc
对于single-exec模式,文档的生成一步完成。 但是在之前, 你需要建立一个master.qdocconf文件,并且在里面把所有的qdocconf文件的绝对路径列出来:
%qtbin%\qdoc -single-exec %localpath%/master.qdocconf -outputdir %localpath%\doc
注意多了一个 -single-exec
选项。
进阶技能
- qdocconf语法
------------------------------------------------ 处理依赖
qdocconf 文件中,如下处理indexes = D:/qt551/Docs/Qt-5.5/qtcore/qtcore.index D:/qt551/Docs/Qt-5.5/qtwidgets/qtwidgets.index D:/qt551/Docs/Qt-5.5/qtnetwork/qtnetwork.index D:/qt551/Docs/Qt-5.5/qmake/qmake.index
depends += qtcore qtnetwork qtwidgets qmake
qdoc 文件中, 引用如下:
\l {page title}
\l {contentspage}
理论知识
Qdoc注释通过一些命令, 对文档进行组织。
QDoc能识别以下3种类型的命令
- 主题(topic command)
主题命令确定了文档的元素,例如C++类(class),函数(function),类型(type),或者和所有元素无关的一段文字。
- 上下文(context command)
上下文命令向QDoc说明了qdoc文件中某个元素和另外的元素怎么样联系,例如前后页链接,同一主题的页组,或者其它链接库,上下文命令还能够获取元素的那些在源代码文件中无法获取到的信息,例如,该元素是否线程安全,是否是一个重载或者覆写函数,是否已被废除,属于哪个module等
- 标记(Makeup command)
标记命令告诉QDoc文档中的文字和图片如何渲染,以及文档的大纲结构。
主题(topic command)
一个主题命令向QDoc指明源代码中哪一个语法元素要被归档,还有一些主题命令允许您创建没有绑定到任何源代码语法元素的文档页面。当QDoc遍历QDoc注释时,它试图通过首先寻找到一个主题命令来把源代码元素连接到这个注释上。如果没有主题命令, QDoc会连接紧跟在该注释之后的源代码元素。如果不满足上述条件,并且注释中没有其它元素来说明这段注释与源代码无关, 那么该段注释就会被丢弃。
相关的语法元素的名字通常是主题命令唯一的参数字段, 这里要使用完整的名称。有时可以有第二个参数。例如 \page。
\fn 也是一个特例, 它需要加上完整的函数信息, 因此它可能会有多个字段, 但是是一个参数。
主题命令可以出现在注释中的任何位置,但必须独立一行。把主题命令放在第一行是一种很好的做法。如果参数字段跨越几行,确保每一行(除了最后一个)使用一个反斜杠结束。此外,QDoc计数括号,这意味着如果它遇到一个“(“,它会把”)”之前的所有内容作为其参数。
几个主题命令(详见qdoc)
- \class 会生成一个以参数名的小写为文件名的独立html页面
- \externalpage 给一个url定义别名,这样在其它地方可以使用 \l 去引用
- Miscellaneous: 提供一些作用于文档生成和渲染的一些命令。
- \group 用于生成一个列举了所有类的独立的页面,这些类有 \ingroup 元素。
- Relating Things:
- \headerfile 用于生成一个包含了一个头文件中的全局函数、类型、宏等的页面
- \relates 用于把一个全局的元素包含到一个头文件或者类中。 例如, 声明了 \class QChar , 再声明 \relates AElem, 就会在QChar 页面中看到AElem
- \overload 说明函数是重载函数, 参数是重载的函数
- \reimp 用于说明一个函数覆写了虚函数。
注意事项
- 一个module对应一个qhp文件。