使用 Sphinx 进行内核文档编写

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

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

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

Sphinx 安装

Documentation/ 文件当前使用的 ReST 标记旨在与 Sphinx 3.4.3 或更高版本一起构建。

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

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

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

总而言之,如果您想安装最新版本的 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 以来,无需安装任何 texlive 软件包即可构建具有数学表达式的 html 页面。 有关更多信息,请参阅 数学渲染器的选择

检查 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

对 Sphinx 使用 OS 打包,而不是 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 主题。

注意

有些人可能更喜欢为 html 输出使用 RTD 主题。 根据 Sphinx 版本,应使用 pip install sphinx_rtd_theme 单独安装它。

还有另一个 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

SPHINX_IMGMATH=no

mathjax

编写文档

添加新文档可以像

  1. Documentation 下的某个位置添加一个新的 .rst 文件。

  2. Documentation/index.rst 中的 Sphinx 主 TOC 树中引用它。

对于简单的文档(比如您现在阅读的文档),这通常就足够了,但对于较大的文档,建议创建一个子目录(或使用现有的子目录)。 例如,图形子系统文档位于 Documentation/gpu 下,分为几个 .rst 文件,并且有一个单独的 index.rst(带有自己的 toctree),该文件从主索引引用。

有关您可以使用它们做什么,请参阅 SphinxreStructuredText 的文档。 特别是,Sphinx reStructuredText Primer 是开始使用 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

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

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

ReStructuredText 提供了用于表语法的多个选项。 表的内核样式是首选简单表语法或网格表语法。 有关更多详细信息,请参阅 reStructuredText 用户参考中的表语法

列表表

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

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

  • column-span:使用角色 cspan 可以通过其他列扩展单元格

  • row-span:使用角色 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

渲染为

表格标题

表头 col 1

表头 col 2

表头 col 3

表头 col 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 示例

嵌入的渲染标记(或语言),如 Graphviz 的 DOTkernel-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 标记