【Doxygen】为项目生成一个炫酷的说明文档
1 Doxygen简介
Doxygen 是一个能从带注释的源码中自动生成说明文档的标准工具,它支持众多流行的编程语言,包括 C/C++
、C#
、PHP
、Java
、Python
、IDL
等
Doxygen能够从以下三个方面进行工作:
- 从一组源文件中生成 HTML 格式的在线文档和 LaTeX 格式的离线文档,此外还提供了 RTF(富文本编辑器,例如MS-Word)、PostScript、超链接 PDF、压缩 HTML 和 Unix 等格式输出。
- 从源码中提取代码结构,通过依赖关系图、继承图和协作图自动生成各种元素之间的关系图。
- 为用户制作用户手册和网站
Doxygen 可以在 Mac OS、Linux 和 Windows 下工作,还可以在大多数其他 Unix 上运行。
2 安装 Doxygen
这里只介绍开发常用的安装方式,Ubuntu下可以直接从 apt 源进行安装
sudo apt-get install graphviz
sudo apt-get install doxygen
# 带 gui 的 doxygen
sudo apt-get install doxygen-gui
3 基本使用方式
3.1 从命令行生成
3.1.1 创建配置文件
doxygen -g <config-file>
# 或(不含注释)
doxygen -s -g <config-file>
<config-file>为生成配置文件的名称,如果不输入则默认为Doxyfile,若已存在名为 <config-file>的文件,则会将原先的 <config-file>重命名为 <config-file>.bak。
3.1.2 修改配置文件
这里列举出常用的配置选项,关于完整的配置选项说明,可以参考 doxygen 官网提供的Config-Docs
3.1.2.1 项目配置
-
DOXYFILE_ENCODING
指定用于配置文件中所有字符的编码,默认为 UTF-8。
-
PROJECT_NAME
项目名称,默认为 My Project
3.1.2.2 输入配置
-
INPUT
标记用于指定包含记录的源文件的文件和/或目录。
-
INPUT_ENCODING
标记可用于指定 doxygen 解析的源文件的字符编码。
-
RECURSIVE
指定是否也应搜索子目录以查找输入文件。
3.1.2.3 输出配置
-
OUTPUT_DIRECTORY
标记用于指定将生成的文档写入的(相对或绝对)路径。如果输入了相对路径,则该路径将相对于 doxygen 的启动位置。如果留空,将使用当前目录。
-
OUTPUT_LANGUAGE
标记用于指定编写 doxygen 生成的所有文档的语言。
3.1.2.4 构建配置
-
EXTRACT_ALL
如果设置为
YES
,则 doxygen 将假定文档中的所有实体都已记录,即使没有可用的文档也是如此。私有类成员和静态文件成员将被隐藏,除非EXTRACT_PRIVATE分别EXTRACT_STATIC标记设置为YES
. -
EXTRACT_PRIVATE
如果设置为
YES
,则类的所有私有成员都将包含在文档中。 -
EXTRACT_STATIC
如果设置为
YES
,则文件的所有静态成员都将包含在文档中。 -
EXTRACT_LOCAL_CLASSES
如果设置为
YES
,则在源文件中本地定义的类(和结构)将包含在文档中。如果设置为NO
,则仅包括头文件中定义的类。
3.1.2.5 绘图配置
-
HAVE_DOT
是否使用 Graphviz1 图形可视化工具包
-
CALL_GRAPH
为每个全局函数或类方法生成一个调用依赖图,启用此选项将显着增加运行时间。
-
CALLER_GRAPH
为每个全局函数或类方法生成调用者依赖图,启用此选项将显着增加运行时间。
3.1.3 使配置生效
最终让配置再次生效:
doxygen Doxyfile # 选择你自己的文件,默认是 Doxyfile
3.2 从 GUI 生成
在终端输入
doxywizard
# 修改配置文件
doxywizard Doxyfile
出现以下 GUI 界面,并在相应位置进行修改
3.2.1 向导模式配置
3.2.2 专业模式配置
最终,点击 Run doxygen 即可生成一份说明文档
3.3 查看文档
在生成的 html
中寻找 index.html
文件,打开。
当前页面为空白的主页,并且根据源码生成了两个可供查看的选项:Classes、Files
4 配合 CMake 进行配置
以上操作如果每发布一般代码,都需要手动配置一次,那将显得及其复杂,若能做到根据是否安装 Doxygen 来自动处理安装过程,将会特别方便。
为此,我参考了 OpenCV 中 doc/CMakeLists.txt
的源码,对利用 CMake 配置 Doxygen 做了一些总结。
4.1 FindDoxygen
查看本地路径 /usr/local/share/cmake-x.xx/Modules
可以发现一个 FindDoxygen.cmake
文件,里面对于 Doxygen 做了很多函数和预设变量的定义。
我们可以使用 find_package
来查找Doxygen,使用 doxygen_add_docs
函数来生成简易的 Doxyfile。2可参考以下代码:
find_package(Doxygen)
if (DOXYGEN_FOUND)
doxygen_add_docs(abc ${CMAKE_CURRENT_SOURCE_DIR}/modules
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generate man page")
endif()
WORKING_DIRECTORY
为工作路径COMMENT
将作为add_custom_target()
的命令进行传递
可以使用已经生成的 Doxyfile.abc
进行最终说明文档的生成,但仍然不够炫酷。
不过也可以在 build
文件夹下找到一个 Doxyfile.abc
和一个 CMakeDoxyfile.in
文件,其中 CMakeDoxyfile.in
文件可用于实时加载 CMake 变量,生成最终的 Doxyfile
文件,这正是下文要介绍的内容。
4.2 使用 configure_file 编写配置文件
4.2.1 configure_file 基本语法
具体的语法可参考作者的这一篇文章,这里展示在 OpenCV 中是如何使用的
# writing file
configure_file("${OPENCV_DOCS_DOXYGEN_LAYOUT}" DoxygenLayout.xml @ONLY)
configure_file("${OPENCV_DOCS_DOXYFILE_IN}" ${doxyfile} @ONLY)
configure_file(root.markdown.in ${rootfile} @ONLY)
先不考虑第一个 configure_file
的功能,第二个 configure_file
作用就是将 Doxyfile.in
生成一个 Doxyfile
文件,用于 Doxygen 的配置,第三个 configure_file
是为了生成 main page。这些 *.in 文件的内容与原始的文件基本一致,只不过所有的值均设置成了 CMake 变量,以更加灵活的载入。
4.2.2 编写 Doxyfile.in
这里给出了一个模板,其代码在附件1中,其中有个风格配置的一行代码:
HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/stylesheet.css
这里使用到的 stylesheet.css
文件,文件内容可参考 OpenCV 下的 doc/stylesheet.css
。没有安装 opencv 的小伙伴可参考附件2,需手动创建文件,并编辑代码。
4.2.3 编写 root.markdown.in
这一步是为了生成一个 markdown 文件,用来作为说明文档的 main page,一般主页面可以提供给读者一系列的模块、类的说明。
OpenCV 中是自动查找所有模块,并使用 cmake 的字符串操作,组合起来,其代码如下,可供参考
OpenCV modules {#mainpage}
==============
- @ref intro
- @ref tutorial_root
- @ref tutorial_py_root
@CMAKE_DOXYGEN_TUTORIAL_JS_ROOT@
@CMAKE_DOXYGEN_TUTORIAL_CONTRIB_ROOT@
- @ref faq
- @ref citelist
@CMAKE_DOXYGEN_MAIN_REFERENCE@
@CMAKE_DOXYGEN_EXTRA_REFERENCE@
当然也可以自己手写一个 root.markdown.in
文件,可能对于初学者来说更加友好,缺点就是如果模块、类等内容发生了改变,可能需要自己手动修改 root.markdown.in
文件。
4.3 配置生成信息
4.3.1 获取与 Doxyfile 相关的 CMake 变量
可参考以下 OpenCV 中的代码来设置 cmake 变量
# set export variables
### 解释:设置 Doxyfile 里的 INPUT 项
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_INPUT_LIST "${rootfile} ; ${faqfile}")
### 解释:其中 ${rootfile} 用在了 Doxyfile 中的 USE_MDFILE_AS_MAINPAGE 项
### 解释:设置 Doxygen 里的 INPUT 项
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_IMAGE_PATH "${doxygen_image_path}")
### 解释:设置 Doxygen 里的 EXCLUDE 项
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_EXCLUDE_LIST "${CMAKE_DOXYGEN_EXCLUDE_LIST}")
string(REPLACE ";" " " CMAKE_DOXYGEN_ENABLED_SECTIONS "${CMAKE_DOXYGEN_ENABLED_SECTIONS}")
# TODO: remove paths_doc from EXAMPLE_PATH after face module tutorials/samples moved to separate folders
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_EXAMPLE_PATH "${example_path} ; ${paths_doc} ; ${paths_sample}")
string(REPLACE ";" " \\\n" CMAKE_DOXYGEN_INCLUDE_ROOTS "${paths_include}")
### 解释:设置 Doxyfile 里的 LAYOUT_FILE 项
set(CMAKE_DOXYGEN_LAYOUT "${CMAKE_CURRENT_BINARY_DIR}/DoxygenLayout.xml")
### 解释:设置 Doxyfile 里的 OUTPUT_DIRECTORY 项
set(CMAKE_DOXYGEN_OUTPUT_PATH "doxygen")
### 解释:设置 root.markdown.in 内的参数
set(CMAKE_DOXYGEN_MAIN_REFERENCE "${refs_main}")
set(CMAKE_DOXYGEN_EXTRA_REFERENCE "${refs_extra}")
set(CMAKE_EXTRA_BIB_FILES "${bibfile} ${paths_bib}")
4.3.2 生成文档
在命令行中输入:
mkdir build
cd build
cmake ..
可以看到出现的 Doxyfile 文件,可以直接输入
doxygen Doxyfile
来生成对应的 html/index.html
。
也可采用以下方法,即在 CMakeLists.txt
中添加可被 make 的目标
add_custom_target(doxygen)
# execute 'make doxygen' to create *.html
add_custom_command(
TARGET doxygen
POST_BUILD
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
意思就是,如果在命令行中输入make doxygen
,则可以会自动执行文档的生成过程,即运行 doxygen Doxyfile
。
4.4 效果展示
左边为 OpenCV 的文档,右边为作者仿照 OpenCV 设计的文档,可以看出,基本一致
附件
附件1
Doxyfile.in
模板文件
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME =
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = @CMAKE_DOXYGEN_OUTPUT_PATH@
CREATE_SUBDIRS = YES
OUTPUT_LANGUAGE = Chinese
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = YES
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
JAVADOC_BANNER = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
ALIASES =
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 5
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = YES
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_PRIV_VIRTUAL = YES
EXTRACT_PACKAGE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = YES
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE = @CMAKE_DOXYGEN_LAYOUT@
CITE_BIB_FILES =
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
INPUT = @CMAKE_DOXYGEN_INPUT_LIST@
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.idl \
*.ddl \
*.odl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.cs \
*.d \
*.php \
*.php4 \
*.php5 \
*.phtml \
*.inc \
*.m \
*.markdown \
*.md \
*.mm \
*.dox \
*.doc \
*.txt \
*.py \
*.pyw \
*.f90 \
*.f95 \
*.f03 \
*.f08 \
*.f \
*.for \
*.tcl \
*.vhd \
*.vhdl \
*.ucf \
*.qsf \
*.ice
RECURSIVE = YES
EXCLUDE = @CMAKE_DOXYGEN_EXCLUDE_LIST@
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE = @rootfile@
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
CLANG_ASSISTED_PARSING = NO
CLANG_OPTIONS =
CLANG_DATABASE_PATH =
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
GENERATE_HTML = YES
HTML_OUTPUT = @CMAKE_DOXYGEN_OUTPUT_PATH@/html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/stylesheet.css
HTML_EXTRA_FILES = @CMAKE_DOXYGEN_HTML_FILES@
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = YES
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 14
FORMULA_TRANSPARENT = YES
FORMULA_MACROFILE =
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME =
MAKEINDEX_CMD_NAME = makeindex
LATEX_MAKEINDEX_CMD = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
XML_NS_MEMB_FILE_SCOPE = NO
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
CLASS_DIAGRAMS = YES
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = YES
CALLER_GRAPH = YES
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = svg
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
附件2
stylesheet.css
文件
/* The standard CSS for doxygen 1.8.6 */
body, table, div, p, dl {
font: 400 14px/22px Helvetica, 'Segoe UI', Arial, freesans, sans-serif;
word-wrap: break-word;
}
code {
font-size: 85%;
font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;
white-space: pre-wrap;
padding: 1px 5px;
background-color: rgb(223, 229, 241);
vertical-align: baseline;
}
body {
background-image: url(bodybg.png);
margin: 0 auto;
}
div.fragment {
padding: 3px;
padding-bottom: 0px;
}
div.line {
padding-bottom: 3px;
font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;
}
div.contents {
width: 980px;
margin: 0 auto;
padding: 15px 15px;
border: 1px solid rgb(10, 80, 122);
background-color: #fff;
}
span.arrow {
height: 13px;
}
div.image img{
max-width: 900px;
}
#projectlogo
{
text-align: center;
vertical-align: middle;
border-collapse: separate;
padding-left: 0.5em;
}