Skip to content

Commit

Permalink
docs: Auto-generate the Zephyr Kconfig reference
Browse files Browse the repository at this point in the history
Creates the MVP reference documentation for Zephyr Kconfig.
The extension recursively walks the Kconfig tree and generates
documentation for each option. The type and source code URL are
shown for each option. Optional fields like default values and
help text are also shown if available.

Bug: b/288127315
Change-Id: I0ff30a576b4cd84dc68536e4b59ccd438aabead9
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/152533
Reviewed-by: Kayce Basques <kayce@google.com>
Reviewed-by: Anthony DiGirolamo <tonymd@google.com>
Commit-Queue: Kayce Basques <kayce@google.com>
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Kayce Basques <kayce@google.com>
  • Loading branch information
Kayce Basques authored and CQ Bot Account committed Jun 24, 2023
1 parent a6477ac commit 49c6ab6
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pw_doc_group("core_docs") {
"module_structure.rst",
"os/index.rst",
"os/zephyr/index.rst",
"os/zephyr/kconfig.rst",
"size_optimizations.rst",
"style_guide.rst",
]
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

extensions = [
'pw_docgen.sphinx.google_analytics', # Enables optional Google Analytics
'pw_docgen.sphinx.kconfig',
'pw_docgen.sphinx.module_metadata',
'sphinx.ext.autodoc', # Automatic documentation for Python code
'sphinx.ext.napoleon', # Parses Google-style docstrings
Expand Down
7 changes: 7 additions & 0 deletions docs/os/zephyr/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Get started with Zephyr and Pigweed
1. Complete the `Zephyr Getting Started Guide`_.
2. Check out the `zds2023`_ repository for an example of a Zephyr starter
project that has been set up to use Pigweed.
3. See :ref:`docs-os-zephyr-kconfig` to find the Kconfig options for
enabling individual Pigweed modules and features.

-------
Testing
Expand All @@ -38,3 +40,8 @@ Once set up, simply invoke:

.. _Zephyr Getting Started Guide: https://docs.zephyrproject.org/latest/develop/getting_started/index.html#getting-started-guide
.. _zds2023: https://github.com/yperess/zds2023

.. toctree::
:hidden:

kconfig
12 changes: 12 additions & 0 deletions docs/os/zephyr/kconfig.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.. _docs-os-zephyr-kconfig:

========================
Zephyr Kconfig reference
========================
This page is an auto-generated reference of all of the Kconfig-related
options that are available when you use Pigweed with Zephyr.

.. caution::
This document is a work in progress. If something looks incorrect or
incomplete, use the source links to double-check the information in the
Kconfig source code.
1 change: 1 addition & 0 deletions pw_docgen/py/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pw_python_package("py") {
"pw_docgen/docgen.py",
"pw_docgen/sphinx/__init__.py",
"pw_docgen/sphinx/google_analytics.py",
"pw_docgen/sphinx/kconfig.py",
"pw_docgen/sphinx/module_metadata.py",
]
pylintrc = "$dir_pigweed/.pylintrc"
Expand Down
137 changes: 137 additions & 0 deletions pw_docgen/py/pw_docgen/sphinx/kconfig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Copyright 2023 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Auto-generate the Kconfig reference in //docs/os/zephyr/kconfig.rst"""


import os
import re
from typing import Iterable, Dict

import docutils
from docutils.core import publish_doctree
from sphinx.application import Sphinx
from sphinx.addnodes import document


try:
import kconfiglib # type: ignore

KCONFIGLIB_AVAILABLE = True
except ImportError:
KCONFIGLIB_AVAILABLE = False


def rst_to_doctree(rst: str) -> Iterable[docutils.nodes.Node]:
"""Convert raw reStructuredText into doctree nodes."""
# TODO(b/288127315): Properly resolve references within the rst so that
# links are generated more robustly.
while ':ref:`module-' in rst:
rst = re.sub(
r':ref:`module-(.*?)`', r'`\1 <https://pigweed.dev/\1>`_', rst
)
doctree = publish_doctree(rst)
return doctree.children


def create_source_paragraph(name_and_loc: str) -> Iterable[docutils.nodes.Node]:
"""Convert kconfiglib's name and location string into a source code link."""
start = name_and_loc.index('pw_')
end = name_and_loc.index(':')
file_path = name_and_loc[start:end]
url = f'https://cs.opensource.google/pigweed/pigweed/+/main:{file_path}'
link = f'`//{file_path} <{url}>`_'
return rst_to_doctree(f'Source: {link}')


def process_node(
node: kconfiglib.MenuNode, parent: docutils.nodes.Node
) -> None:
"""Recursively generate documentation for the Kconfig nodes."""
while node:
if node.item == kconfiglib.MENU:
name = node.prompt[0]
# All auto-generated sections must have an ID or else the
# get_secnumber() function in Sphinx's HTML5 writer throws an
# IndexError.
menu_section = docutils.nodes.section(ids=[name])
menu_section += docutils.nodes.title(text=f'{name} options')
if node.list:
process_node(node.list, menu_section)
parent += menu_section
elif isinstance(node.item, kconfiglib.Symbol):
name = f'CONFIG_{node.item.name}'
symbol_section = docutils.nodes.section(ids=[name])
symbol_section += docutils.nodes.title(text=name)
symbol_section += docutils.nodes.paragraph(
text=f'Type: {kconfiglib.TYPE_TO_STR[node.item.type]}'
)
if node.item.defaults:
try:
default_value = node.item.defaults[0][0].str_value
symbol_section += docutils.nodes.paragraph(
text=f'Default value: {default_value}'
)
# If the data wasn't found, just contine trying to process
# rest of the documentation for the node.
except IndexError:
pass
if node.item.ranges:
try:
low = node.item.ranges[0][0].str_value
high = node.item.ranges[0][1].str_value
symbol_section += docutils.nodes.paragraph(
text=f'Range of valid values: {low} to {high}'
)
except IndexError:
pass
if node.prompt:
try:
symbol_section += docutils.nodes.paragraph(
text=f'Description: {node.prompt[0]}'
)
except IndexError:
pass
if node.help:
symbol_section += rst_to_doctree(node.help)
if node.list:
process_node(node.list, symbol_section)
symbol_section += create_source_paragraph(node.item.name_and_loc)
parent += symbol_section
# TODO(b/288127315): Render choices?
# elif isinstance(node.item, kconfiglib.Choice):
node = node.next


def generate_kconfig_reference(_, doctree: document, docname: str) -> None:
"""Parse the Kconfig and kick off the doc generation process."""
if 'docs/os/zephyr/kconfig' not in docname:
return
# Assume that the new content should be appended to the last section
# in the doctree.
for child in doctree.children:
if isinstance(child, docutils.nodes.section):
root = child
pw_root = os.environ['PW_ROOT']
file_path = f'{pw_root}/Kconfig.zephyr'
kconfig = kconfiglib.Kconfig(file_path)
# There's no need to render kconfig.top_node (the main menu) or
# kconfig.top_node.list (ZEPHYR_PIGWEED_MODULE).
process_node(kconfig.top_node.list.next, root)


def setup(app: Sphinx) -> Dict[str, bool]:
"""Initialize the Sphinx extension."""
if KCONFIGLIB_AVAILABLE:
app.connect('doctree-resolved', generate_kconfig_reference)
return {'parallel_read_safe': True, 'parallel_write_safe': True}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ isort==5.10.1
jedi==0.18.1
Jinja2==3.0.3
json5==0.9.11
kconfiglib==14.1.0
lazy-object-proxy==1.9.0
MarkupSafe==2.0.1
matplotlib-inline==0.1.3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ sphinx-copybutton==0.5.1
sphinx-tabs==3.4.1
myst-parser==0.18.1
breathe==4.34.0
kconfiglib==14.1.0
# Renode requirements
psutil==5.9.4
robotframework==6.0.2

0 comments on commit 49c6ab6

Please sign in to comment.