使用Sphinx写项目文档

Posted by Hsz on November 27, 2020

使用sphinx写项目文档

Sphinx是一个开源的python文档生成器,这里有一个中文的使用手册,它采用reStructuredText作为默认的源文件格式,也可以配置使用markdown作为源文件,可以输出为html文件或者pdf文件(需要latex)等多种格式.

由于它自带解析python docstring的功能,因此非常适合用于给python项目做接口文档.通过其他第三方插件的支持,sphinx也可以为javascript,c/c++,golang自动生成接口文档.

本文会结合例子介绍,会按以下顺序演示在不同的场景下使用sphinx写文档

  1. 基本设置,使用markdown写文档
  2. 多语言支持
  3. 借助工具自动生成对应编程语言的api文档
    1. python
    2. C/C++

安装与设置

Sphinx需要python作为运行环境,安装只要pip install sphinx就可以.

sphinx项目的基本构建过程是:

  1. 使用快速构建工具构建文档项目

  2. 修改conf.py做全局设置

  3. 编写文档源文件

  4. 编译文档源文件构造为目标输出格式

构建文档项目

Sphinx提供了两个快速构建工具用于构造一个文档项目.

  1. sphinx-quickstart用于从0开始构造一个文档项目.
  2. sphinx-apidoc用于在已有python模块的情况下快速构建一个文档项目

介于本文并不是专门针对python项目的,这部分我们介绍第一种快速构建工具.sphinx-apidoc则会在[为Python项目创建api文档]部分介绍.

使用sphinx-quickstart创建文档项目.会一步一步提示你填写好项目的基本信息,如果懒得进入交互填写,可以用如下命令

sphinx-quickstart --no-sep -v <项目版本> -r <项目发行版本> -p <项目名> -a <作者名>  -l <使用的语言> [ --ext-todo --ext-mathjax --ext-viewcode [文档源文件所在目录]]

使用sphinx-quickstart创建文档项目有以下几点需要注意

  • 如果项目版本项目发行版本一致,则只有项目版本,否则形式为<项目版本>rc<项目发行版本>
  • --no-sep -v <项目版本> -r 0.0.0 -p <项目发行版本> -a <作者名> -l <使用的语言>这几个中只要有一个没填就需要进交互去填写
  • 使用的语言只支持如下:

    缩写 语言
    ar 阿拉伯语
    bg 保加利亚语
    bn 孟加拉
    ca 加泰罗尼亚语
    cak 喀克其奎语
    cs 捷克语
    cy 威尔士语
    da 丹麦语
    de 德语
    el 希腊语
    en 英语
    eo 世界语
    es 西班牙语
    et 爱沙尼亚语
    eu 巴斯克语
    fa 伊朗语
    fi 芬兰语
    fr 法语
    he 希伯来语
    hi 印地语
    hi_IN 印度印地语
    hr 克罗地亚语
    hu 匈牙利语
    id 印度尼西亚语
    it 意大利语
    ja 日语
    ko 韩语
    lt 立陶宛语
    lv 拉脱维亚语
    mk 马其顿语
    nb_NO 书面挪威语
    ne 尼泊尔语
    nl 荷兰语
    pl 波兰语
    pt 葡萄牙语
    pt_BR 巴西葡萄牙语
    pt_PT 欧洲葡萄牙语
    ro 罗马尼亚语
    ru 俄语
    si 僧伽罗语
    sk 斯洛伐克语
    sl 斯洛文尼亚语
    sq 阿尔巴尼亚语
    sr 塞尔维亚语
    sr@latin 塞尔维亚语(拉丁文)
    sr_RS 塞尔维亚语(西里尔文)
    sv 瑞典语
    ta 泰米尔语
    te 泰卢固语
    tr 土耳其语
    uk_UA 乌克兰语
    ur 乌尔都语
    vi 越南语
    zh_CN 简体中文
    zh_TW 繁体中文
  • 文档源文件所在目录可以缺省,缺省就是在执行目录生成.建议在项目的document目录下创建.
  • --ext-todo --ext-mathjax --ext-viewcode是推荐的通用插件,建议都安上.
    • todo 一个TODO list插件
    • mathjax 可以显示latex写成的公式
    • viewcode 可以查看到项目的源码

一路按照提示选择,创建好后目录结构大约是这样:

|-_build # 用于存放编译好的文档结果
|-_static # 用于存放模板的静态资源文件
|-_templates # 用于存放模板文件
|-conf.py # 文档项目的配置项
|-index.rst # 首页源文件
|-Makefile # 非windows平台用于编译文档项目的makefile文件
|-make.bat # windows平台用于编译文档项目的makefile文件

修改conf.py

conf.py是sphinx文档项目的配置文件,它就是一个python脚本,使用上面的方式创建出来的conf.py大致如下:

project = 'sample'
copyright = '2020, hsz'
author = 'hsz'

# 确定项目版本
version = '0.0.0'
release = '0.0.0'

# 使用的插件
extensions = [
    'sphinx.ext.todo',
    'sphinx.ext.mathjax',
    'sphinx.ext.viewcode',
]

# 指定模板所在文件夹位置
templates_path = ['_templates']

# 文档语言
language = 'en'

# 不进行编译的文件/文件夹
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

# 设置不同后缀的文件使用不同解析器(这个需要后加)
source_suffix = {
    '.rst': 'restructuredtext'
}



# 指定编译成html时使用的主题
html_theme = 'alabaster'

# 指定编译成html时使用的静态文件所在位置
html_static_path = ['_static']


# todo插件的设置
todo_include_todos = True

我们可以直接在conf.py中通过python代码进行设置,设置的基本模式是:

如果上面已经有了但需要修改,就直接修改

  • 修改主题

      html_theme = "alabaster"
    

    自带的主题可以在这里查找.

    个人比较推荐的自带主题是alabaster,其设置可以参考下面

      html_theme = "sphinx_rtd_theme"
      html_sidebars = {
          '**': [
              'about.html',
              'navigation.html',
              'relations.html',
              'searchbox.html',
              'donate.html',
          ]
      }
    

    都不喜欢的话可以去这里查找第三方主题,第三方主题需要先安装.

    个人比较推荐的第三方主题是sphinx_rtd_theme,其设置为

      import sphinx_rtd_theme
      extensions.append('sphinx_rtd_theme')
      html_theme = "sphinx_rtd_theme"
      html_theme_options = {
          'logo_only': True,
          'navigation_depth': 5,
      }
    

如果是原本支持功能,就直接设置对应的参数,比较常用的设置包括:

  • 设置latex的编译配置:

      latex_engine = 'xelatex'
      latex_elements = {
          'fontpkg': r'''
      \setmainfont{DejaVu Serif}
      \setsansfont{DejaVu Sans}
      \setmonofont{DejaVu Sans Mono}
      ''',
          'preamble': r'''
      \usepackage[titles]{tocloft}
      \cftsetpnumwidth {1.25cm}\cftsetrmarg{1.5cm}
      \setlength{\cftchapnumwidth}{0.75cm}
      \setlength{\cftsecindent}{\cftchapnumwidth}
      \setlength{\cftsecnumwidth}{1.25cm}
      ''',
          'fncychap': r'\usepackage[Bjornstrup]{fncychap}',
          'printindex': r'\footnotesize\raggedright\printindex',
      }
      latex_show_urls = 'footnote'
    

如果是通过插件支持的功能,则需要先在``中添加插件,然后写入插件的配置.比如

  • 配置对markdown的支持(需要先安装依赖pip install --upgrade recommonmark)

      from recommonmark.transform import AutoStructify
      from recommonmark.parser import CommonMarkParser
      # 使用插件支持markdowm
      # 使用插件支持markdowm
      extensions.append('recommonmark')
    
      # 针对`.md`为后缀的文件做markdown渲染
      source_suffix[".md"] = 'markdown'
    
      # 设置markdown渲染器的自定义项
    
      def setup(app):
          github_doc_root = 'https://localhost:5000'
          app.add_config_value('recommonmark_config', {
              #'url_resolver': lambda url: github_doc_root + url, # 如果不是本地调试,可以将自己项目的url根目录写上
              "enable_auto_toc_tree": True,
              "auto_toc_tree_section": "目录",
              'auto_toc_maxdepth': 2, # 设置toc_tree深度
              "enable_math": True, # 支持```math,注意目前inline_math会有问题因此不建议使用.
              'enable_eval_rst': True, # 支持嵌入rst
          }, True)
    

使用markdown编写文档

我们的第一个例子是纯粹使用sphinx渲染markdown.这个例子中我们的入口是index.md,它有个目录项会将page1.mdpage2.md引入文件.

编译源文档

编译源文档可以有两种方法:

使用make命令

make <目标文件类型>命令可以在_build目录下简单快捷地构建文档.最常用的就是make html.我们可以看下make的源码:

# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS    ?=
SPHINXBUILD   ?= sphinx-build
SOURCEDIR     = .
BUILDDIR      = _build

# Put it first so that "make" without argument is like "make help".
help:
    @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
    @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

可以看出它实际就是执行sphinx-build命令,我们如果追求简单可以直接修改其中的参数固化每次的编译行为,比如修改BUILDDIR../docs这样方便直接给Github Page使用

使用sphinx-build [options] sourcedir builddir [filenames]来构建.

上面就可以看出sphinx-buildmake的底层,用它可以更灵活的构建.其中sourcedir是源文件目录,builddir是生成文件目录, filenames用于指定要编译的文件,一般不需要写 默认情况下sphinx-build只会编译有变化的文件

脚本 sphinx-build的可选参数有:

  • -b 生成器名字

    生成器,决定了生成文档的类型,是最重要的选项.通用的生成器有:

    • html 生成HTML文档. 默认的生成器.
    • dirhtml 生成HTML文档,但是每个文档都有单一的目录,在用浏览器访问时有漂亮的URLs(没有后缀.html)
    • singlehtml 所有内容生成单一的HTML
    • htmlhelp,qthelp,devhelp,epub 生成HTML文档,建立文档集时包含这些类型之一的额外信息.
    • latex 生成LaTeX源,可使用指定的latex编译器将其编译成PDF文档.默认使用的是xelatex
    • man 生成UNIX系统的groff格式手册.
    • texinfo 生成Texinfo文件,可以使用makeinfo产生Info文件.
    • text 生成纯文本文件.
    • gettext 生成gettext-style分类信息(.pot 文件).
    • linkcheck 检查所有外部链接的可信度.查看Available builders,列出了Sphinx支持的所有生成器及其可添加的扩展.
  • -a 给出时重写全部文档,默认则仅重新生成有新的源文件或源文件被修改的文档.(不适用于所有生成器)

  • -E 不使用保存的environment(环境,缓存了所有的参考索引),而是完全重建.默认仅读取和解析最近新添加及改动的源文件.

  • -t <tag> 定义标签<tag>.与only指令相关,标签是一个目录集合,仅处理标签目录中的内容.

  • -d <path>目前Sphinx生成输出前会读取和解析所有的源文件,解析过的源文件被缓存成”doctree pickles”.通常,这些文件被放在生成目录的 .doctrees文件夹中;这个选项可以选择不同的缓存目录(doctrees可以被所有的生存器共享).

  • -c <path> 不使用源目录下的conf.py而是使用指定的配置文件.注意在配置文件中提及的路径都是相对配置文件所在目录的相对路径,因此路径必须一致.

  • -C 不查找配置文件,仅使用选项-D的配置.

  • -D setting=<value> 覆盖conf.py里的配置值.value是一个字符串或字典.例如:-D latex_elements.docclass=scrartcl.布尔值使用01代替.

  • -A name=<value> 模板里的name变量使用value值代替.

  • -n 采用nit-picky模式.该模式下所有错误都会产生警告信息.

  • -N 不产生彩色输出.(在Windows下,彩色输出一直是不可用的)

  • -q 不产生标准输出,仅使用标准错误输出输出警告和错误信息.

  • -Q 不产生标准输出,也不产生警告信息,仅使用标准错误输出输出错误信息.

  • <-w file> 除标准错误输出外,将警告(错误)输出到指定文件.

  • -W将警告视为错误.产生第一个警告就停止文档生成活动,sphinx-build 在状态1退出.

  • -P 发生未绑定的异常时运行Python调试器pdb.(仅在调试时使用)

多语言支持

上面的例子中我们已经使用language = 'zh_CN'设定了文档使用的语言.但如果一个项目希望国际化,不可避免的会需要多语言支持,Sphinx自然也有对应的方案.

本部分的例子在分支sphinx-example-locale

要支持多语言我们会用到sphinx-intl:

  • pip install sphinx-intl.

  • config.py中添加设置

locale_dirs = ['locale/']   #
gettext_compact = False     # optional.
  • 将文档内容转化为pot文件,放入document/_build/gettext文件夹下

      sphinx-build -b gettext document document/_build/gettext
    
  • 使用sphinx-intl工具将pot文件都转化成po文件用于翻译

      sphinx-intl update -p document/_build/gettext -d document/locale -l 语言1 -l 语言2 ...
    

    这一步的-d document/locale和上面配置的locale_dirs对应

  • 翻译

    上一步以后我们可以在文档源文件文件夹下获得一个locale文件夹.其结构如下:

      locale\
            |- en\
                 |- index.po
                 |- xxx.po
                 |-...
            |- fr\
                 |- index.po
                 |- xxx.po
                 |...
            |- ....
    
    

    一种语言会对应一个文件夹,其中的文件和源文件是一一对应的关系.每个.po文件类似如下:

      # SOME DESCRIPTIVE TITLE.
      # Copyright (C) 2020, hsz
      # This file is distributed under the same license as the sample package.
      # FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
      #
      #, fuzzy
      msgid ""
      msgstr ""
      "Project-Id-Version: sample 0.0.0\n"
      "Report-Msgid-Bugs-To: \n"
      "POT-Creation-Date: 2020-11-20 14:21+0800\n"
      "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
      "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
      "Language-Team: LANGUAGE <LL@li.org>\n"
      "MIME-Version: 1.0\n"
      "Content-Type: text/plain; charset=utf-8\n"
      "Content-Transfer-Encoding: 8bit\n"
      "Generated-By: Babel 2.9.0\n"
    
      #: ../../index.md:5
      msgid "Page1"
      msgstr ""
    
      #: ../../index.md:5
      msgid "Page2"
      msgstr ""
    
      #: ../../index.md:1
      msgid "Welcome to sample's documentation!"
      msgstr ""
    
      #: ../../index.md:3
      msgid "Example"
      msgstr ""
    
      #: ../../index.md:5
      msgid "目录"
      msgstr "Index"
    

    其中#为注释,msgid为源文件中的内容,msgstr为待翻译内容.这一步的任务就是把msgstr都填完.

  • 编译

    还是使用sphinx-build,只是需要加上-D language='<语言>'并且注意目标文件夹,建议将目标文件夹放在主文件夹下的子文件夹下.

      sphinx-build -D language='fr' -b html document docs/fr
    

单一静态站的多语言支持

上面就是多语言支持的完整步骤了,不过要注意,不同语言的静态页面本质上都是不相关独立静态网站,要将他们联系起来我们要借助sphinx的扩展能力.

sphinx支持使用jinja2语法做扩展,我们可以在_template文件夹下写一个versions.html(注意由于css使用的是sphinx_rtd_theme提供的.因此这个方法只能在这个主题中使用)

\{\% if READTHEDOCS or display_lower_left \%\}
\{\# Add rst-badge after rst-versions for small badge style. \#}
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
  <span class="rst-current-version" data-toggle="rst-current-version">
    <span class="fa fa-book"> Read the Docs</span>
    v: \{\{ current_version \}\}
    <span class="fa fa-caret-down"></span>
  </span>
  <div class="rst-other-versions">
    \{\% if languages|length >= 1 \%\}
    <dl>
      <dt>\{\{ _('Languages') \}\}</dt>
      \{\% for slug, url in languages \%\}
      \{\% if slug == current_language \%\} <strong> \{\% endif \%\}
        <dd><a href="\{\{ url \}\}">\{\{ slug \}\}</a></dd>
        \{\% if slug == current_language \%\} </strong> \{\% endif \%\}
      \{\% endfor \%\}
    </dl>
    \{\% endif \%\}
  </div>
</div>
{\{\% endif \%\}

这个模板可以看出,我们会用到变量display_lower_left,version,current_language,和languages,因此我们需要在config.py中配置这4个变量

...

# 多语言支持
try:
    html_context
except:
    html_context = dict()
html_context["current_version"] = version
html_context['display_lower_left'] = True

# 从环境变量`CURRENT_LANGUAGE`获取当前语言,默认为zh_CN
current_language = os.environ.get('CURRENT_LANGUAGE') if os.environ.get('CURRENT_LANGUAGE') else 'zh_CN'
html_context['current_language'] = current_language

if current_language == 'zh_CN':
    # # POPULATE LINKS TO OTHER LANGUAGES
    html_context['languages'] = [('zh_CN', 'index.html')]

    languages = [lang.name for lang in Path(__file__).parent.joinpath("locale").iterdir() if lang.is_dir()]
    for lang in languages:
        html_context['languages'].append((lang, f'{lang}/index.html'))
else:
    # # POPULATE LINKS TO OTHER LANGUAGES
    html_context['languages'] = [('zh_CN', '../index.html')]

    languages = [lang.name for lang in Path(__file__).parent.joinpath("locale").iterdir() if lang.is_dir()]
    for lang in languages:
        html_context['languages'].append((lang, f'../{lang}/index.html'))

html_context是在使用模板时变量的保存位置,它是一个字典结构,我们把需要设置的值都放入其中即可.需要注意的是languages中的元素是一个展示和路径组成的元组,在编译不同语言的静态页面时,路径往往是不同的(主要是主语言和locale中的语言会有不同),为了解决这个问题,我们要在外部借助环境变量CURRENT_LANGUAGE在外部告知编译时的程序.因此编译程序为:

  • linux/macos

      export CURRENT_LANGUAGE=fr && sphinx-build -D language='fr' -b html document docs/fr
    
  • windows

      $env:CURRENT_LANGUAGE="fr"; sphinx-build -D language='fr' -b html document docs/fr
    

利用这种方式我们还可以扩展出其他用法,比如将历史版本也带上什么的,不过这就要借助CI/CD工具了.具体可以参考这个项目.

借助工具自动生成对应编程语言的api文档

sphinx在设计之初主要目的就是给python做项目文档,因此内置了插件sphinx.ext.autodoc来自动从python项目的源码中获取docstring生成api文档.这也是它能流行的主要原因.

在它越来越流行的同时,用户开始希望它可以将这一特性扩展至其他编程语言.这一功能目前并没有官方实现,但比较接近的有几个第三方项目,比较可惜的是目前并没有相对成熟的方案

  • autoapi

    这个项目由readthedocs这个项目组在维护,目前支持对Python的配置化部署.也提供了Javascript,Go,C#的支持,但还在alpha版本,基本不可用因此建议只将它用在python项目中.这个项目有意构造为一个专注于python并为其他语言的支持提供扩展接口的底层库.我觉得是个蛮好的思路.

    这个项目使用pip install sphinx-autoapi安装.

  • sphinx-js 这个项目由mozilla在维护.它和上面用法类似,支持JavascriptTypescript.但很遗憾比较手动挡,而且不支持markdown.因此本文不做介绍

  • exhale

    这个项目本质上是对doxygen构造的文档的自动化嫁接(借助breathe).

接下来的部分我们会介绍上面几种编程语言的自动化api编译.

本部分的例子演示的是单一语言环境下的api文档自动生成.

自动生成Python项目的API

本部分的例子在标签sphinx-example-python下.

在安装好sphinx-autoapi后,我们只需要写好配置,指定好要解析的文件夹位置即可.

  • conf.py
...

# autoapi-python


extensions.append('autoapi.extension')
extensions.append("sphinx.ext.napoleon")
autoapi_type = 'python'
autoapi_dirs = ['../pythonsrc']
# autoapi_options = ['members', 'undoc-members', 'show-inheritance',
#                    'show-module-summary', 'special-members', 'show-inheritance-diagram', 'imported-members']
# autoapi_add_toctree_entry = False

我们需要在配置中导入插件sphinx.ext.napoleon来支持解析google风格的docstring.指定autoapi_typepython,并使用autoapi_dirs指名python脚本所在目录.

注意autoapi会扫描并解析autoapi_dirs指定目录下的所有.py.pyi文件,因此要注意下项目结构,不要将虚拟环境文件夹包含进去.

autoapi_options可以指定解析的范围:

枚举值 说明
members 展示对象的子对象
inherited-members 展示对象的继承对象
undoc-members 展示没有docstring的对象
private-members 展示私有对象(以_开头命名的对象)
special-members 展示特殊对象(以__开头命名的对象)
show-inheritance 展示继承关系
show-inheritance-diagram 以图的形式展示继承关系,需要使用插件sphinx.ext.inheritance_diagram并安装Graphviz
show-module-summary 展示模块的综述
imported-members 展示import进来的模块

默认的设置是['members', 'undoc-members', 'private-members', 'show-inheritance', 'show-module-summary', 'special-members', 'imported-members'].

我们在src文件夹下放入我们的演示python模块sample.py

"""牛顿法扩展都n次方根

:math:`\\sqrt[k] a` .的表达式为:

:math:`x_{n+1} = x_n - \\frac {x_n^k-a} {kx_n^{k-1}} = \\frac {k-1}{k} x_n + \\frac {a}{kx_n^{k-1}}`

"""
from typing import Union


def sqrt_nt(n: Union[int, float], m: Union[int, float], *, round_: int = 5) -> float:
    """牛顿法求n次方根.

    用法: :math:`sqrt\\_nt(n,m,round) = \\sqrt[m] n`


    Parameters:
        n (int,float): 被开方的数
        m (int,float) : 开多少次方
        round(int): 精度

    Returns:
        int,float: 开方结果


    Raises:
        TypeError: 参数类型不对时报错
        ValueError:被开方参数为复数时报错

    >>> sqrt_nt(2,2,round_=2)
    1.41

    """
    if all(map(lambda x: isinstance(x, (int, float)), [n, m])):
        if n < 0:
            raise ValueError(u"必须是整数")
        elif n == 0:
            return 0
        elif n == 1:
            return 1
        else:
            deviation = 0.1**(round_ + 1)
            seed = n / m
            counter = 0
            max_count = 100000
            now_value = seed
            last_value: Union[int, float] = 0
            while abs(now_value - last_value) > deviation:
                if counter > max_count:
                    raise ValueError(u"在{count}次循环内未能得到精度为{round}的解".format(
                        count=max_count, round=round_))
                counter += 1
                last_value = now_value
                now_value = (1 - 1.0 / m) * last_value + \
                    n / (m * last_value**(m - 1))
            return round(now_value, round_)

    else:
        raise TypeError(u"必须是数")


class A:
    """一个测试类.

    Attributes:
        a (str): 测试元素

    """

    def __init__(self, a: str) -> None:
        self.a = a

    def echo(self, n: int) -> int:
        """测试原样返回.

        Args:
            n (int): n

        Returns:
            int: n
        """
        return n

之后执行sphinx-build document docs即可.

自动生成C/Cpp项目的API

本部分的例子在sphinx-example-c

我们需要先安装doxygen,这是一个为多种编程语言构造api文档的命令行工具,可以在linux,macos,windows上执行,不过需要注意的是在windows上只支持cmd命令行.因此我们编译文档的时候需要在cmd命令行中执行.

接下来是安装插件breatheexhale.这两个包是python包,pip安装即可.

接着是该配置:

  • conf.py

      # C/CPP 语言支持
      extensions.append('breathe')
      extensions.append('exhale')
      # 指定doxyout生成的xml文件的位置,相对于我们的文档源文件所在文件夹的位置
      breathe_projects = {
          "Sample": "./doxyoutput/xml"
      }
      # 项目名
      breathe_default_project = "Sample"
    
      exhale_args = {
          # 必填配置(不建议更改)
          "containmentFolder": "./api",# api文档的输出位置,相对于
          "rootFileName": "index.rst", # api文档的入口文件,建议写成这样
          "rootFileTitle": "Library API", # api文档的入口标题
          "doxygenStripFromPath": "..", # doxygen的执行位置
          # 推荐填的配置
          "createTreeView": True, # 是否创建树状视图
          "exhaleExecutesDoxygen": True, # 由exhale执行Doxygen而非手工执行
          "exhaleDoxygenStdin": "INPUT = ../include" # c/cpp的头文件位置
      }
    
    
      # Tell sphinx what the primary language being documented is.
      primary_domain = 'cpp'
    
      # Tell sphinx what the pygments highlight language should be.
      highlight_language = 'cpp'
    

然后我们在待编译的项目入口文件index.md中添加对api入口文件的引用

* [api文档](api/index.rst)

最后就是执行sphinx-build document docs就可以了.