使用 Sphinx 进行内核文档编写

Linux 内核使用 SphinxDocumentation 下的 reStructuredText 文件生成漂亮的文档。要以 HTML 或 PDF 格式构建文档,请使用 make htmldocsmake pdfdocs。生成的文档位于 Documentation/output 中。

reStructuredText 文件可能包含指令,用于包含来自源文件的结构化文档注释或 kernel-doc 注释。通常,这些用于描述代码的功能、类型和设计。kernel-doc 注释具有一些特殊的结构和格式,但除此之外,它们也被视为 reStructuredText。

最后,在 Documentation 周围散布着数千个纯文本文档文件。其中一些可能会随着时间的推移转换为 reStructuredText,但其中大部分将保留为纯文本。

Sphinx 安装

目前 Documentation/ 文件使用的 ReST 标记旨在通过 Sphinx 版本 2.4.4 或更高版本构建。

有一个脚本可以检查 Sphinx 的要求。请参阅 检查 Sphinx 依赖项 了解更多详细信息。

大多数发行版都附带 Sphinx,但其工具链很脆弱,并且在您的机器上升级它或某些其他 Python 包会导致文档构建中断的情况并不少见。

避免这种情况的一种方法是使用与您的发行版附带的版本不同的版本。为了这样做,建议使用 virtualenv-3virtualenv 将 Sphinx 安装在虚拟环境中,具体取决于您的发行版如何打包 Python 3。

注意

  1. 建议对 html 输出使用 RTD 主题。根据 Sphinx 版本,应使用 pip install sphinx_rtd_theme 单独安装它。

总之,如果要安装最新版本的 Sphinx,则应执行

$ virtualenv sphinx_latest
$ . sphinx_latest/bin/activate
(sphinx_latest) $ pip install -r Documentation/sphinx/requirements.txt

运行 . sphinx_latest/bin/activate 后,提示符将更改,以指示您正在使用新环境。如果您打开一个新的 shell,则需要重新运行此命令才能在构建文档之前再次进入虚拟环境。

图像输出

内核文档构建系统包含一个扩展,用于处理 GraphViz 和 SVG 格式的图像(请参阅 图形 & 图像)。

要使其工作,您需要安装 GraphViz 和 ImageMagick 包。如果未安装这些包,构建系统仍将构建文档,但不会在输出中包含任何图像。

PDF 和 LaTeX 构建

当前仅 Sphinx 版本 2.4 及更高版本支持此类构建。

对于 PDF 和 LaTeX 输出,您还需要 XeLaTeX 版本 3.14159265。

根据发行版,您可能还需要安装一系列 texlive 包,这些包提供了 XeLaTeX 工作所需的最少功能集。

HTML 中的数学表达式

一些 ReST 页面包含数学表达式。由于 Sphinx 的工作方式,这些表达式是使用 LaTeX 表示法编写的。Sphinx 在 html 输出中呈现数学表达式有两种选择。一种是名为 imgmath 的扩展,它将数学表达式转换为图像并将其嵌入到 html 页面中。另一种是名为 mathjax 的扩展,它将数学呈现委托给支持 JavaScript 的 Web 浏览器。前者是 6.1 之前的内核文档的唯一选择,它需要相当多的 texlive 包,包括 amsfonts 和 amsmath 等。

自内核版本 6.1 以来,可以构建带有数学表达式的 html 页面,而无需安装任何 texlive 包。有关更多信息,请参阅 数学渲染器的选择

检查 Sphinx 依赖项

有一个脚本会自动检查 Sphinx 依赖项。如果它可以识别您的发行版,它还会提供有关您的发行版的安装命令行选项的提示

$ ./scripts/sphinx-pre-install
Checking if the needed tools for Fedora release 26 (Twenty Six) are available
Warning: better to also install "texlive-luatex85".
You should run:

        sudo dnf install -y texlive-luatex85
        /usr/bin/virtualenv sphinx_2.4.4
        . sphinx_2.4.4/bin/activate
        pip install -r Documentation/sphinx/requirements.txt

Can't build as 1 mandatory dependency is missing at ./scripts/sphinx-pre-install line 468.

默认情况下,它会检查 html 和 PDF 的所有要求,包括图像、数学表达式和 LaTeX 构建的要求,并假定将使用虚拟 Python 环境。html 构建所需的要求被认为是强制性的;其他要求是可选的。

它支持两个可选参数

--no-pdf

禁用 PDF 检查;

--no-virtualenv

使用 OS 打包 Sphinx 而不是 Python 虚拟环境。

Sphinx 构建

生成文档的通常方法是运行 make htmldocsmake pdfdocs。还有其他可用格式:请参阅 make help 的文档部分。生成的文档放置在 Documentation/output 下的特定于格式的子目录中。

要生成文档,显然必须安装 Sphinx (sphinx-build)。对于 PDF 输出,您还需要 XeLaTeX 和 ImageMagick 中的 convert(1) (https://imagemagick.org.cn)。[1] 所有这些都广泛可用并打包在发行版中。

要将额外的选项传递给 Sphinx,您可以使用 SPHINXOPTS make 变量。例如,使用 make SPHINXOPTS=-v htmldocs 来获取更详细的输出。

也可以传递一个额外的 DOCS_CSS 覆盖文件,以通过使用 DOCS_CSS make 变量来自定义 html 布局。

默认情况下,“Alabaster”主题用于构建 HTML 文档;此主题与 Sphinx 捆绑在一起,无需单独安装。可以使用 DOCS_THEME make 变量来覆盖 Sphinx 主题。

还有另一个 make 变量 SPHINXDIRS,当测试构建文档的子集时很有用。例如,您可以通过运行 make SPHINXDIRS=doc-guide htmldocs 来构建 Documentation/doc-guide 下的文档。make help 的文档部分将向您显示您可以指定的子目录列表。

要删除生成的文档,请运行 make cleandocs

数学渲染器的选择

自内核版本 6.1 以来,mathjax 可用作 html 输出的后备数学渲染器。[2]

数学渲染器的选择取决于可用的命令,如下所示

HTML 的数学渲染器选择

数学渲染器

所需命令

图像格式

imgmath

latex, dvipng

PNG (光栅)

mathjax

可以通过设置环境变量 SPHINX_IMGMATH 来覆盖该选择,如下所示

设置 SPHINX_IMGMATH 的效果

设置

渲染器

SPHINX_IMGMATH=yes

imgmath

imgmath

mathjax

mathjax

数学渲染器的回退需要 Sphinx >=1.8。

  1. 编写文档

  2. 添加新文档可以像以下一样简单

对于简单的文档(比如您正在阅读的这份文档)来说,这通常已经足够了,但是对于较大的文档,建议创建一个子目录(或使用现有的子目录)。例如,图形子系统文档位于 Documentation/gpu 下,被拆分为多个 .rst 文件,并且有一个单独的 index.rst 文件(其中包含自己的 toctree),该文件从主索引引用。

请参阅 SphinxreStructuredText 的文档,了解您可以使用它们做什么。 特别是,Sphinx reStructuredText 入门 是开始学习 reStructuredText 的一个好地方。 还有一些 Sphinx 特定的标记结构

内核文档的具体指南

以下是一些关于内核文档的具体指南

  • 请不要过度使用 reStructuredText 标记。 保持简单。 在大多数情况下,文档应该使用纯文本,只需在格式上保持足够的 一致性,以便可以将其转换为其他格式。

  • 将现有文档转换为 reStructuredText 时,请尽量减少格式更改。

  • 在转换文档时,还要更新内容,而不仅仅是格式。

  • 请坚持以下标题修饰顺序

    1. = 用于文档标题,上方加横线

      ==============
      Document title
      ==============
      
    2. = 用于章节

      Chapters
      ========
      
    3. - 用于节

      Section
      -------
      
    4. ~ 用于小节

      Subsection
      ~~~~~~~~~~
      

    虽然 RST 不强制规定特定的顺序(“与其强加固定数量和顺序的节标题修饰样式,不如按照遇到的顺序强制执行。”),但保持较高级别整体相同可以更容易地理解文档。

  • 对于插入固定宽度的文本块(用于代码示例、用例示例等),对于任何不需要语法突出显示的内容,特别是短片段,请使用 :: 。对于需要突出显示的较长代码块,请使用 .. code-block:: <language>。对于嵌入在文本中的短代码片段,请使用 ``。

C 域

Sphinx C 域 (名称为 c) 适用于 C API 的文档。 例如,一个函数原型

.. c:function:: int ioctl( int fd, int request )

kernel-doc 的 C 域有一些额外的功能。例如,您可以使用像 openioctl 这样的常用名称来重命名函数的引用名称

.. c:function:: int ioctl( int fd, int request )
   :name: VIDIOC_LOG_STATUS

函数名(例如 ioctl)保留在输出中,但 ref-name 从 ioctl 更改为 VIDIOC_LOG_STATUS。此函数的索引条目也更改为 VIDIOC_LOG_STATUS

请注意,没有必要使用 c:func: 来生成对函数文档的交叉引用。 由于一些 Sphinx 扩展的魔力,如果存在给定函数名称的索引条目,文档构建系统会自动将对 function() 的引用转换为交叉引用。 如果您在内核文档中看到 c:func: 的使用,请随时将其删除。

表格

ReStructuredText 为表格语法提供了多种选项。表格的内核风格是优先使用简单表格语法或网格表格语法。有关更多详细信息,请参阅 reStructuredText 用户参考表格语法

列表表格

对于不易用通常的 Sphinx ASCII 艺术格式布局的表格,列表表格格式可能很有用。 然而,对于纯文本文档的读者来说,这些格式几乎不可能理解,因此在没有充分理由的情况下应避免使用。

flat-table 是一个类似于 list-table 的双阶段列表,具有一些附加功能

  • 列跨度:使用角色 cspan,单元格可以扩展到其他列

  • 行跨度:使用角色 rspan,单元格可以扩展到其他行

  • 自动跨越表格行最右侧的单元格,覆盖该表格行右侧缺少的单元格。使用选项 :fill-cells:,此行为可以从自动跨越更改为自动填充,这将自动插入(空)单元格而不是跨越最后一个单元格。

选项

  • :header-rows: [int] 标题行的计数

  • :stub-columns: [int] 存根列的计数

  • :widths: [[int] [int] ... ] 列的宽度

  • :fill-cells: 插入缺失的单元格,而不是自动跨越缺失的单元格

角色

  • :cspan: [int] 附加列 (morecols)

  • :rspan: [int] 附加行 (morerows)

下面的示例展示了如何使用此标记。 分阶段列表的第一级是表格行。 在表格行中,只允许一个标记,即此表格行中单元格的列表。 例外是注释 ( .. ) 和目标 (例如,对 :ref:`last row <last row>` / 最后一行 的引用)。

.. flat-table:: table title
   :widths: 2 1 1 3

   * - head col 1
     - head col 2
     - head col 3
     - head col 4

   * - row 1
     - field 1.1
     - field 1.2 with autospan

   * - row 2
     - field 2.1
     - :rspan:`1` :cspan:`1` field 2.2 - 3.3

   * .. _`last row`:

     - row 3

渲染为

表格标题

头列 1

头列 2

头列 3

头列 4

行 1

字段 1.1

具有自动跨越的字段 1.2

行 2

字段 2.1

字段 2.2 - 3.3

行 3

交叉引用

从一个文档页面到另一个文档页面的交叉引用可以通过简单地编写文档文件的路径来完成,不需要特殊的语法。 该路径可以是绝对路径或相对路径。 对于绝对路径,以“Documentation/”开头。 例如,要交叉引用到此页面,以下所有选项均有效,具体取决于当前文档的目录(请注意,需要 .rst 扩展名)

See Documentation/doc-guide/sphinx.rst. This always works.
Take a look at sphinx.rst, which is at this same directory.
Read ../sphinx.rst, which is one directory above.

如果您希望链接的呈现文本与文档的标题不同,则需要使用 Sphinx 的 doc 角色。 例如

See :doc:`my custom link text for document sphinx <sphinx>`.

对于大多数用例,前者是首选,因为它更简洁,更适合阅读源文件的人。 如果您遇到没有添加任何值的 :doc: 用法,请随时将其转换为仅文档路径。

有关交叉引用 kernel-doc 函数或类型的信息,请参阅 编写 kernel-doc 注释

引用提交

如果以以下格式之一编写,则对 git 提交的引用会自动进行超链接

commit 72bf4f1767f0
commit 72bf4f1767f0 ("net: do not leave an empty skb in write queue")

图形 & 图像

如果要添加图像,应使用 kernel-figurekernel-image 指令。 例如,要插入具有可缩放图像格式的图形,请使用 SVG (SVG 图像示例)

.. kernel-figure::  svg_image.svg
   :alt:    simple SVG image

   SVG image example
simple SVG image

SVG 图像示例

内核图形(和图像)指令支持 DOT 格式的文件,请参阅

一个简单的示例 (DOT 的 hello world 示例)

.. kernel-figure::  hello.dot
   :alt:    hello world

   DOT's hello world example
hello world

DOT 的 hello world 示例

嵌入的 render 标记(或语言),例如 Graphviz 的 DOT,由 kernel-render 指令提供。

.. kernel-render:: DOT
   :alt: foobar digraph
   :caption: Embedded **DOT** (Graphviz) code

   digraph foo {
    "bar" -> "baz";
   }

这将如何呈现取决于已安装的工具。 如果安装了 Graphviz,您将看到矢量图像。 如果没有,则原始标记将作为文字块插入 (嵌入的 DOT (Graphviz) 代码)。

foobar digraph

嵌入的 DOT (Graphviz) 代码

render 指令具有从 figure 指令已知的所有选项,以及选项 caption。如果 caption 具有值,则会插入 figure 节点。如果不是,则插入 image 节点。 如果您想引用它,还需要 caption (嵌入的 SVG 标记)。

嵌入的 SVG

.. kernel-render:: SVG
   :caption: Embedded **SVG** markup
   :alt: so-nw-arrow

   <?xml version="1.0" encoding="UTF-8"?>
   <svg xmlns="http://www.w3.org/2000/svg" version="1.1" ...>
      ...
   </svg>
so-nw-arrow

嵌入式 SVG 标记