documenting-code.rst 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. 编写代码文档
  2. ============
  3. :link_to_translation:`en:[English]`
  4. 本文简要介绍了 `espressif/esp-idf`_ 项目库采用的文件风格以及如何在项目库中添加新文件。
  5. 概述
  6. ----
  7. 在项目库内编写代码文档时,请遵循 `Doxygen 代码注释风格 <http://doxygen.nl/manual/docblocks.html#specialblock>`_。要采用这一风格,您可以将 ``@param`` 等特殊命令插入到标准注释块中,比如: ::
  8. /**
  9. * @param ratio this is oxygen to air ratio
  10. */
  11. Doxygen 会解析代码,提取命令和后续文本,生成代码文档。
  12. 注释块通常包含对功能的记述,如下所示。
  13. .. image:: ../../_static/doc-code-documentation-inline.png
  14. :align: center
  15. :alt: 内联代码样本文档
  16. Doxygen 支持多种排版风格,对于文档中可以包含的细节非常灵活。请参考数据丰富、条理清晰的 `Doxygen 手册 <http://doxygen.nl/manual/index.html>`_ 熟悉 Doxygen 特性。
  17. 为什么需要 Doxygen?
  18. --------------------
  19. 使用 Doxygen 的最终目的是确保所有代码编写风格一致,以便在代码变更时使用 `Sphinx`_ 和 `Breathe`_ 等工具协助筹备、自动更新 API 文档。
  20. 使用这类工具时,上文代码渲染后呈现效果如下:
  21. .. image:: ../../_static/doc-code-documentation-rendered.png
  22. :align: center
  23. :alt: 渲染后的内联代码样本文档
  24. 尝试一下!
  25. ----------
  26. 在本项目库编写代码文档时,请遵守下列准则。
  27. 1. 写明代码的基本内容:函数、结构、类型定义、枚举、宏等。请详细说明代码的用途、功能和限制,因为在阅读他人的文档时你也想看到这些信息。
  28. 2. 函数文档需简述该函数的功能,并解释输入参数和返回值的含义。
  29. 3. 请不要在参数或除空格外的其他字符前面添加数据类型。所有空格和换行符都会压缩为一个空格。如需换行,请执行换行操作两次。
  30. .. image:: ../../_static/doc-code-function.png
  31. :align: center
  32. :alt: 内联函数样本文档及渲染后的效果
  33. 4. 如果函数没有输入参数或返回值,请跳过 ``@param`` 或 ``@return``。
  34. .. image:: ../../_static/doc-code-void-function.png
  35. :align: center
  36. :alt: 隐式内联函数样本文档及渲染后的效果
  37. 5. 为 ``define``、``struct`` 和 ``enum`` 的成员编写文档时,请在每一项后添加注释,如下所示。
  38. .. image:: ../../_static/doc-code-member.png
  39. :align: center
  40. :alt: 内联函数成员样本文档及渲染后的效果
  41. 6. 请在命令后换行(如下文中的 ``@return`` ),呈现排版精美的列表。 ::
  42. *
  43. * @return
  44. * - ESP_OK if erase operation was successful
  45. * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
  46. * - ESP_ERR_NVS_READ_ONLY if handle was opened as read only
  47. * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist
  48. * - other error codes from the underlying storage driver
  49. *
  50. 7. 头文件的功能概览和库文件应当存在同一个项目库之下,放入单独的 ``README.rst`` 文件。如果目录下包含不同 API 的头文件,应将文件命名为 ``apiname-readme.rst``。
  51. 进阶
  52. ----
  53. 以下小贴士可以帮助你进一步提高文档质量,增强可读性。
  54. 1. 添加代码片段举例说明。请在片段前后添加 ``@code{c}`` 和 ``@endcode`` 命令。 ::
  55. *
  56. * @code{c}
  57. * // Example of using nvs_get_i32:
  58. * int32_t max_buffer_size = 4096; // default value
  59. * esp_err_t err = nvs_get_i32(my_handle, "max_buffer_size", &max_buffer_size);
  60. * assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND);
  61. * // if ESP_ERR_NVS_NOT_FOUND was returned, max_buffer_size will still
  62. * // have its default value.
  63. * @endcode
  64. *
  65. 代码片段应放入所介绍功能的注释块中。
  66. 2. 使用 ``@attention`` 或 ``@note`` 命令高亮显示重要信息。 ::
  67. *
  68. * @attention
  69. * 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode
  70. * 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect.
  71. *
  72. 上述例子介绍了如何使用编号列表。
  73. 3. 给相似的函数编写文档时,可在前后使用 ``/**@{*/`` 和 ``/**@}*/`` 标记命令。 ::
  74. /**@{*/
  75. /**
  76. * @brief common description of similar functions
  77. *
  78. */
  79. void first_similar_function (void);
  80. void second_similar_function (void);
  81. /**@}*/
  82. 示例请参照 :component_file:`nvs_flash/include/nvs.h`。
  83. 4. 如果想跳过重复的宏定义、枚举项等代码,不添加描述,请在代码前后添加 ``/** @cond */`` 和 ``/** @endcond */`` 命令。示例请参照 :component_file:`driver/include/driver/gpio.h`。
  84. 5. 使用 markdown 增强文档可读性,添加页眉、链接、表格及更多内容。 ::
  85. *
  86. * [{IDF_TARGET_NAME} 技术参考手册]({IDF_TARGET_TRM_CN_URL})
  87. *
  88. .. note::
  89. 代码片段、注释、链接等内容如没有附在所述对象对应的注释块中,将不会添加到文档中。
  90. 6. 准备一个或更多完整的代码示例和描述,将描述放入单独的 ``README.md`` 文件中,置于 :idf:`examples` 目录的特定文件夹中。
  91. .. _link-custom-roles:
  92. 链接到示例
  93. ----------
  94. 链接到 GitHub 上的示例时,请不要使用绝对 URLs 或硬编码 URLs。请使用 Docutils 自定义角色生成链接。自动生成的链接指向项目库中 git commit 编号(或标记)的 tree 或 blob。这种做法可以确保 master 分支上的文件移动或删除时,链接不会失效。
  95. 有如下角色可以选择:
  96. - ``:idf:`path``` - 指向 ESP-IDF 内的目录
  97. - ``:idf_file:`path``` - 指向 ESP-IDF 内的文件
  98. - ``:idf_raw:`path``` - 指向 ESP-IDF 内的原始格式文件
  99. - ``:component:`path``` - 指向 ESP-IDF components 内的文件夹
  100. - ``:component_file:`path``` - 指向 ESP-IDF components 内的文件
  101. - ``:component_raw:`path``` - 指向 ESP-IDF components 内的原始格式文件
  102. - ``:example:`path``` - 指向 ESP-IDF examples 内的文件夹
  103. - ``:example_file:`path``` - 指向 ESP-IDF examples 内的文件
  104. - ``:example_raw:`path``` - 指向 inside ESP-IDF examples 内的原始格式文件
  105. 示例::
  106. * :example:`get-started/hello_world`
  107. * :example:`Hello World! <get-started/hello_world>`
  108. 渲染效果:
  109. * :example:`get-started/hello_world`
  110. * :example:`Hello World! <get-started/hello_world>`
  111. CI build 脚本中添加了检查功能,查找 RST 文件中的硬编码链接(通过 URL 的 tree/master、blob/master 或 raw/master 部分识别)。该功能可通过 ``cd docs`` 和 ``make gh-linkcheck`` 命令手动运行。
  112. .. _link-language-versions:
  113. 链接到其他语言文档
  114. ------------------
  115. 要切换不同语言的文档,可使用 ``:link_to_translation:`` 自定义角色。文档页面中的角色提供其他语言版本的链接。下文的例子说明了如何在文档中添加中英文版本的链接::
  116. :link_to_translation:`zh_CN:中文版`
  117. :link_to_translation:`en:English`
  118. 语言用 ``en`` 或 ``zh_CN`` 等标准简写表示。最后一个分号后的文本非标准化内容,可根据链接的位置自行输入,如::
  119. :link_to_translation:`en:see description in English`
  120. .. _add-illustrations:
  121. 添加图例
  122. --------
  123. 请考虑使用图表和图片解释表述的概念。
  124. 相比于长篇的表述,图例有时可以更好地描述复杂的理念、数据结构或算法。本项目库使用`blockdiag <http://blockdiag.com/en/index.html>`_ 工具包由简单的文本文件生成图表。
  125. 工具包支持下列图表类型:
  126. * `框图 <http://blockdiag.com/en/blockdiag/index.html>`_
  127. * `时序图 <http://blockdiag.com/en/seqdiag/index.html>`_
  128. * `活动图 <http://blockdiag.com/en/actdiag/index.html>`_
  129. * `逻辑网络图 <http://blockdiag.com/en/nwdiag/index.html>`_
  130. 使用该工具包,可以将简单的文本(与 graphviz 的 DOT 格式类似)转换成美观的图片。图中内容自动排版。图标代码之后会转换为 ".png" 图片,在后台添加进 **Sphinx** 文档中。
  131. 要查看图表的渲染效果,可使用线上的 `interactive shell`_ 即时显示生成的图片。
  132. 下面是一些图表示例:
  133. * 简单的 **框图** / ``blockdiag`` - `Wi-Fi Buffer 配置 <http://interactive.blockdiag.com/?compression=deflate&src=eJylUk1rwkAQvfsrBntpIUKiRQqSgK0VSj0EtCi0EjbJxCyuuyG7QW3pf-9m06hJeyg0t33zmHkfCZmItjElGwiLJME8IEwjRFHBA3WAj04H9HcFGyZCwoAoldOwUCgNzkWMwZ7GKgUXnKE9gjOcIt2kSuN39sigMiP8jDqX6GmF_Y3GmJCCqUCmJEM9yEXBY4xDcWjOE8GVpO9oztdaGQmRSRAJlMZysjOCKsVj358Fi_H8GV4Nze2Os4zRyvEbB0XktrseQWVktn_ym-wS-UFb0ilt0pa0N6Vn3i_KUEY5zcqrbXWTx_nDaZHjwYvEHGKiSNeC2q_r3FpQZekObAtMTi4XCi2IBBO5e0Rd5L7ppLG574GvO__PUuO7sXTgweTIyY5GcD1XOtToBhYruDf_VvuUad3tD-0_Xq1TLPPSI84xKvNrF9vzLnrTj1M7rYhrXv24cCPVkZUaOK47n1-lOvbk>`_
  134. * 稍复杂的 **框图** - `Wi-Fi 编程模型 <http://interactive.blockdiag.com/?compression=deflate&src=eJyFk09P40AMxe98CqscIVILq72UIFX8kSoQWy0RHABFTuImFtOZaGYKuyC-O840bagaRI7Pfs7Pz0mmTP5cMJbwynNOa2tKi4sF6zJdmIIUvO_tgTz7UCqToQL03nK29OSCrqUpfeXCVxDD6Gg47tSKuKy8yL9b1dWov1E3E4atWtAcl8qnrsKapGDNUhdUZObfdr2UQp3mRhkrXdpoGq-BGwhQmJFaoSZns_Q2mZxdwUNQ44Eojxqcx_x5cAhzo73jN4pHv55WL7m4u0nSZHLbOeiFtBePR9dvmcxm19sWrGvFOXo2utd4CGH5eHQ8bGfcTy-n6fnfO9jMuOfoksV9bvmFbO-Lr27-JPAQ4oqbGJ62c8iN1pQ3EA4O-lOJTncXDvvupCGdu3vmqFQmSQqm3CIYBx0EWou6pADjQJbw3Bj-h3I4onxpsHrCQLnmoD0yVKgLJXuP1x3GsowPmUpfbay3yH5T7khPoi7NnpU-1nisPdkFyY_gV4x9XB3Y0pHdpfoJ60toURQOtqbYuvpJ1B6zDXYym0qmTVpNnh-fpWcbRA>`_
  135. * **时序图** / ``seqdiag`` - `在所有信道中扫描特定 AP <http://interactive.blockdiag.com/seqdiag/?compression=deflate&src=eJyVkU1PwzAMhu_7FdburUgQXMomTaPcKIdOIIRQlDVuG1EloUknPsR_J2s2rRsT2nKJ9drvY8ex-C4kr8AWXLFSt8waLBg38D0Cf3jh5Io7qRVMQGmFSS-jqJA1qCpXe51cXwTZGg-pUVa1W8tXQRVY8q5xzNbcoNdb3SmBYqk_9vOlVs7Kr3UJoQmMwgDGMMftWwK4QuU28ZOM7uQm3q_zYTQd5OGl4UtsJmMSE5jCXKtSVl2LUPgpXPvpb4Hj1-RUCPWQ3O_K-wKpX84WMLAcB9B-igCouVLYADnDTA_N9GRzHMdnNMoOG2Vb8-4b4CY6Zr4MT3zOF-k9Sx_TbMHy-Sxjtw9Z-mfRHjEA7hD0X8TPLxU91AQ>`_
  136. * **包图** / ``packetdiag`` - `NVS 页面结构 <http://interactive.blockdiag.com/packetdiag/?compression=deflate&src=eJxFkMFOwzAQRO_9ij2mh63idRKaSj1V_ACIE6DIxG4StTgh3oCg6r_j2JTs8c3szNqDqk-GdacasJ-uGlRjKsfjVPM0GriswE_dn786zS3sQRJAYLbXprpRkS-sNV3TcrAGqM1RTWeujr1l1_2Y2U6rIKUod_DIis2LTbJ1YBneeWY-Nj5ts-AtkudPdnJGQ0JppLRFKXZweDhIWrySsPDB95bHb3BzPLx1_K4GSCSt_-4vMizzmykNSuBlgWKuioJYBOHLROnbEBGe_ZfEh-7pNcolIdF_raA8rl5_AaqqWyE>`_
  137. 尝试修改源代码,看看图表会发生什么变化。
  138. .. note::
  139. `interactive shell`_ 使用的字体和 esp-idf 文档使用的字体略有不同。
  140. 添加注释
  141. --------
  142. 写文档时,您可能需要:
  143. - 留下建议,说明之后需添加会修改哪些内容。
  144. - 提醒自己或其他人跟进。
  145. 这时,您可以使用 ``.. todo::`` 命令在 reST 文件中添加待做事项。如:
  146. .. code-block:: none
  147. .. todo::
  148. Add a package diagram.
  149. 如果在 reST 文件中添加 ``.. todolist::`` 命令,整篇文档中的所有待做事项将会罗列成表。
  150. 默认情况下,文档生成器会忽视 ``.. todo::`` 和 ``.. todolist::`` 命令。如果您想在本地生成的文档中显示注释和注释列表,请执行下列步骤:
  151. 1. 打开本地的 ``conf_common.py`` 文件。
  152. 2. 找到 ``todo_include_todos`` 参数。
  153. 3. 将该参数的值由 ``False`` 改为 ``True``。
  154. 将改动推送到远端分支之前,请把 ``todo_include_todos`` 的值重置为 ``False``。
  155. 更多关于扩展的信息,请参阅 `sphinx.ext.todo <https://www.sphinx-doc.org/en/master/usage/extensions/todo.html#directive-todolist>`_ 的相关文档。
  156. 汇总文档
  157. --------
  158. 文档准备好后,请参照 :doc:`../api-reference/template` 的要求创建一个文件,汇总所有准备好的文档。最后,在文件中添加链接指向 ``/docs`` 文件夹或子文件夹下 ``index.rst`` 文件的 ``.. toctree::``。
  159. Sphinx 新手怎么办
  160. ------------------
  161. 1. 不要担心。所有需要的软件均有详细文档,并且开源、免费。您可以先查看 `Sphinx`_ 文档。如果您不清楚如何用 rst markup 语言写作,请查看 `reStructuredText Primer <http://www.sphinx-doc.org/en/stable/rest.html>`_。您也可以使用 markdown (.md) 文件,查找更多在 `Recommonmark parser' 文档页面 <https://recommonmark.readthedocs.io/en/latest/>`_ 使用的特定 markdown 句法信息。
  162. 2. 查看本文档的源文件,了解本文档使用的代码。源文件存储于 GitHub `espressif/esp-idf`_ 项目库的 :idf:`docs` 文件夹下。您可以滑动到页面上方,点击右上角的链接,直接查看本页面的源文件。您也可以通过点击 ``Raw`` 按键打开源文件,在 GitHub 上查看文件的代码。
  163. 3. 想要查看在上传至 GitHub 前文档如何生成、呈现,有两种方式:
  164. * 安装`Sphinx`_、 `Breathe`_、 `Blockdiag <http://blockdiag.com/en/index.html>`_ 和 `Doxygen <http://doxygen.nl/>`_ 本地生成文档,具体可查看下文。
  165. * 在 `Read the Docs <https://readthedocs.org/>`_ 建立账号,在云端生成文档。 Read the Docs 免费提供文档生成和存储,且速度快、质量高。
  166. 4. 在生成文档前预览,可使用 `Sublime Text <https://www.sublimetext.com/>`_ 编辑器和 `OmniMarkupPreviewer <https://github.com/timonwong/OmniMarkupPreviewer>`_ 插件。
  167. .. _setup-for-building-documentation:
  168. 搭建环境本地生成文档
  169. --------------------
  170. 您可以安装下列包,通过搭建环境在电脑上本地生成文档:
  171. 1. Doxygen - http://doxygen.nl/
  172. 2. Sphinx - https://github.com/sphinx-doc/sphinx/#readme-for-sphinx
  173. 3. Breathe - https://github.com/michaeljones/breathe#breathe
  174. 4. Document theme "sphinx_idf_theme" - https://github.com/rtfd/sphinx_idf_theme
  175. 5. Custom 404 page "sphinx-notfound-page" - https://github.com/rtfd/sphinx-notfound-page
  176. 6. Blockdiag - http://blockdiag.com/en/index.html
  177. 7. Recommonmark - https://github.com/rtfd/recommonmark
  178. 添加 "sphinx_idf_theme" 包之后,文档将与 `ESP-IDF 编程指南 <https://docs.espressif.com/projects/esp-idf/en/latest/index.html>`_ 的风格保持一致。
  179. 不用担心需要安装太多包。除 Doxygen 和 sphinx_idf_theme 之外,其他包均使用纯 Python 语言,可一键安装。
  180. Doxygen 的安装取决于操作系统:
  181. **Linux**
  182. ::
  183. sudo apt-get install doxygen
  184. **Windows** - 在 MSYS2 控制台中安装
  185. ::
  186. pacman -S doxygen
  187. **MacOS**
  188. ::
  189. brew install doxygen
  190. .. note::
  191. 如果您是在 Windows 系统上安装(Linux 和 MacOS 用户可以跳过此说明),在安装 **之前**,请完成以下两步。这是安装 :ref:`add-illustrations` 提到的 "blockdiag" 依赖项的必须步骤。
  192. 1. 更新所有系统包:
  193. ::
  194. $ pacman -Syu
  195. 该过程可能需要重启 MSYS2 MINGW32 控制台重复上述命令,直至更新完成。
  196. 2. 安装 *blockdiag* 的依赖项之一 *pillow*:
  197. ::
  198. $ pacman -S mingw32/mingw-w64-i686-python-pillow
  199. 查看屏幕上的记录,确定 ``mingw-w64-i686-python-pillow-4.3.0-1`` 已安装。旧版本 *pillow* 无法运行。
  200. Windows 安装 Doxygen 的缺点是 `blockdiag pictures <add-illustrations>`_ 字体不能正确加载,可能会存在乱码。在此问题解决之前,您可以使用 `interactive shell`_ 查看完整图片。
  201. sphinx_idf_theme
  202. @@@@@@@@@@@@@@@@
  203. 编译 ``sphinx_idf_theme`` 需要同时使用 Python 和 JavaScript。因此,目前要进行本地编译还必须安装 `node.js <https://nodejs.org/en/download/>`_ ,命令如下:
  204. ::
  205. cd ~/esp
  206. git clone https://github.com/espressif/sphinx_idf_theme.git
  207. cd sphinx_idf_theme
  208. npm install
  209. python setup.py build
  210. python setup.py install
  211. 我们计划在不久的将来支持安装预编译 ``sphinx_idf_theme``,给您带来的暂时不便,敬请谅解。
  212. 其他所有应用都是 `Python <https://www.python.org/>`_ 包,可以按照下列步骤一键安装:
  213. ::
  214. cd ~/esp/esp-idf/docs
  215. pip install --user -r requirements.txt
  216. .. note::
  217. 安装步骤设定将 ESP-IDF 放在 ``~/esp/esp-idf`` 目录下,这是文档中使用的 ESP-IDF 默认地址。
  218. 更换到特定语言文件所在的目录::
  219. cd en
  220. 现在可以调用如下命令生成文档::
  221. make html
  222. 这一步骤需要几分钟时间。完成后,文档会放置在 ``~/esp/esp-idf/docs/en/_build/html`` 文件夹下。您可以在网页浏览器中打开 ``index.html`` 查看。
  223. 大功告成
  224. --------
  225. 我们喜欢可以做酷炫事情的好代码。
  226. 但我们更喜欢有清晰文档的好代码,可以让读者快速上手,做酷炫的事情。
  227. 尝试一下,贡献你的代码和文档!
  228. 相关文档
  229. --------
  230. * :doc:`../api-reference/template`
  231. * :doc:`add-ons-reference`
  232. .. _espressif/esp-idf: https://github.com/espressif/esp-idf/
  233. .. _interactive shell: http://interactive.blockdiag.com/?compression=deflate&src=eJxlUMFOwzAMvecrrO3aITYQQirlAIIzEseJQ5q4TUSIq8TVGIh_J2m7jbKc7Ge_5_dSO1Lv2soWvoVYgieNoMh7VGzJR9FJtugZ7lYQ0UcKEbYNOY36rRQHZHUPT68vV5tceGLbWCUzPfeaFFMoBZzecVc56vWwJFnWMmJ59CCZg617xpOFbTSyw0pmvT_HJ7hxtFNGBr6wvuu5SCkchcrZ1vAeXZomznh5YgTqfcpR02cBO6vZVDeXBRjMjKEcFRbLh8f18-Z2UUBDnqP9wmp9ncRmSSfND2ldGo2h_zse407g0Mxc1q7HzJ3-4jzYYTJjtQH3iSV-fgFzx50J
  234. .. _Sphinx: http://www.sphinx-doc.org/
  235. .. _Breathe: https://breathe.readthedocs.io