doc: Generate develop/api/overview.rst API table from doxygen

A new extension, api_overview.py, is used to, leveraging doxygen's
Python module doxmlparser, parse the doxygen generated XML files.
All groups ('defgroup' and 'addtogroup' tags) are collected, alongside
their 'version' and 'since' info.

From there, a new Sphinx directive `api-overview-table` is populated,
including the name of the group, and if available, their 'since' and
'version' information.

Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
Ederson de Souza 2023-08-25 13:58:52 -07:00 committed by Carles Cufí
parent 4fe0a1dc7f
commit 9ab243d671
4 changed files with 236 additions and 373 deletions

View file

@ -0,0 +1,173 @@
# Copyright (c) 2023 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import doxmlparser
from docutils import nodes
from doxmlparser.compound import DoxCompoundKind
from pathlib import Path
from sphinx.application import Sphinx
from sphinx.util.docutils import SphinxDirective
from typing import Any, Dict
class ApiOverview(SphinxDirective):
"""
This is a Zephyr directive to generate a table containing an overview
of all APIs. This table will show the API name, version and since which
version it is present - all information extracted from Doxygen XML output.
It is exclusively used by the doc/develop/api/overview.rst page.
Configuration options:
api_overview_doxygen_xml_dir: Doxygen xml output directory
api_overview_doxygen_base_url: Doxygen base html directory
"""
def run(self):
return [self.env.api_overview_table]
def get_group(innergroup, all_groups):
try:
return [
g
for g in all_groups
if g.get_compounddef()[0].get_id() == innergroup.get_refid()
][0]
except IndexError as e:
raise Exception(f"Unexpected group {innergroup.get_refid()}") from e
def visit_group(app, group, all_groups, rows, indent=0):
version = since = ""
github_uri = "https://github.com/zephyrproject-rtos/zephyr/releases/tag/"
cdef = group.get_compounddef()[0]
ssects = [
s for p in cdef.get_detaileddescription().get_para() for s in p.get_simplesect()
]
for sect in ssects:
if sect.get_kind() == "since":
since = sect.get_para()[0].get_valueOf_()
elif sect.get_kind() == "version":
version = sect.get_para()[0].get_valueOf_()
if since:
since_url = nodes.inline()
reference = nodes.reference(text=f"v{since.strip()}.0", refuri=f"{github_uri}/v{since.strip()}.0")
reference.attributes["internal"] = True
since_url += reference
else:
since_url = nodes.Text("")
url_base = Path(app.config.api_overview_doxygen_base_url)
url = url_base / f"{cdef.get_id()}.html"
title = cdef.get_title()
row_node = nodes.row()
# Next entry will contain the spacer and the link with API name
entry = nodes.entry()
span = nodes.Text("".join(["\U000000A0"] * indent))
entry += span
# API name with link
inline = nodes.inline()
reference = nodes.reference(text=title, refuri=str(url))
reference.attributes["internal"] = True
inline += reference
entry += inline
row_node += entry
version_node = nodes.Text(version)
# Finally, add version and since
for cell in [version_node, since_url]:
entry = nodes.entry()
entry += cell
row_node += entry
rows.append(row_node)
for innergroup in cdef.get_innergroup():
visit_group(
app, get_group(innergroup, all_groups), all_groups, rows, indent + 6
)
def parse_xml_dir(dir_name):
groups = []
root = doxmlparser.index.parse(Path(dir_name) / "index.xml", True)
for compound in root.get_compound():
if compound.get_kind() == DoxCompoundKind.GROUP:
file_name = Path(dir_name) / f"{compound.get_refid()}.xml"
groups.append(doxmlparser.compound.parse(file_name, True))
return groups
def generate_table(app, toplevel, groups):
table = nodes.table()
tgroup = nodes.tgroup()
thead = nodes.thead()
thead_row = nodes.row()
for header_name in ["API", "Version", "Available in Zephyr Since"]:
colspec = nodes.colspec()
tgroup += colspec
entry = nodes.entry()
entry += nodes.Text(header_name)
thead_row += entry
thead += thead_row
tgroup += thead
rows = []
tbody = nodes.tbody()
for t in toplevel:
visit_group(app, t, groups, rows)
tbody.extend(rows)
tgroup += tbody
table += tgroup
return table
def sync_contents(app: Sphinx) -> None:
if app.config.doxyrunner_outdir:
doxygen_out_dir = Path(app.config.doxyrunner_outdir)
else:
doxygen_out_dir = Path(app.outdir) / "_doxygen"
doxygen_xml_dir = doxygen_out_dir / "xml"
groups = parse_xml_dir(doxygen_xml_dir)
toplevel = [
g
for g in groups
if g.get_compounddef()[0].get_id()
not in [
i.get_refid()
for h in [j.get_compounddef()[0].get_innergroup() for j in groups]
for i in h
]
]
app.builder.env.api_overview_table = generate_table(app, toplevel, groups)
def setup(app) -> Dict[str, Any]:
app.add_config_value("api_overview_doxygen_xml_dir", "html/doxygen/xml", "env")
app.add_config_value("api_overview_doxygen_base_url", "../../doxygen/html", "env")
app.add_directive("api-overview-table", ApiOverview)
app.connect("builder-inited", sync_contents)
return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}

View file

@ -95,6 +95,7 @@ extensions = [
"sphinx_togglebutton",
"zephyr.external_content",
"zephyr.domain",
"zephyr.api_overview",
]
# Only use SVG converter when it is really needed, e.g. LaTeX.
@ -364,6 +365,9 @@ linkcheck_timeout = 30
linkcheck_workers = 10
linkcheck_anchors = False
# -- Options for zephyr.api_overview --------------------------------------
api_overview_doxygen_base_url = "../../doxygen/html"
def setup(app):
# theme customizations

View file

@ -20,6 +20,9 @@ no longer optimal or supported by the underlying platforms.
An up-to-date table of all APIs and their maturity level can be found in the
:ref:`api_overview` page.
.. _api_lifecycle_experimental:
Experimental
*************
@ -36,6 +39,10 @@ The following requirements apply to all new APIs:
of said API (in the case of peripheral APIs, this corresponds to one driver)
- At least one sample using the new API (may only build on one single board)
When introducing a new and experimental API, mark the API version in the headers
where the API is defined. An experimental API shall have a version where the minor
version is up to one (0.1.z). (see `api overview <api_overview>`)
Peripheral APIs (Hardware Related)
==================================
@ -46,6 +53,8 @@ the Architecture working group consisting of representatives from different vend
The API shall be promoted to ``unstable`` when it has at least two
implementations on different hardware platforms.
.. _api_lifecycle_unstable:
Unstable
********
@ -53,6 +62,10 @@ The API is in the process of settling, but has not yet had sufficient real-world
testing to be considered stable. The API is considered generic in nature and can
be used on different hardware platforms.
When the API changes status to unstable API, mark the API version in the headers
where the API is defined. Unstable APIs shall have a version where the minor
version is larger than one (0.y.z | y > 1 ). (see `api overview <api_overview>`)
.. note::
Changes will not be announced.
@ -69,6 +82,8 @@ Hardware Agnostic APIs
For hardware agnostic APIs, multiple applications using it are required to
promote an API from ``experimental`` to ``unstable``.
.. _api_lifecycle_stable:
Stable
*******
@ -94,6 +109,11 @@ In order to declare an API ``stable``, the following steps need to be followed:
`Zephyr Architecture meeting`_ where, barring any objections, the Pull Request
will be merged
When the API changes status to stable API, mark the API version in the headers
where the API is defined. Stable APIs shall have a version where the major
version is one or larger (x.y.z | x >= 1 ). (see `api overview <api_overview>`)
.. _breaking_api_changes:
Introducing breaking API changes
@ -177,6 +197,11 @@ for it to be discussed and ultimately even voted on in the `Zephyr TSC meeting`_
If the Pull Request is merged then an email must be sent to the ``devel`` and
``user`` mailing lists informing them of the change.
The API version shall be changed to signal backward incompatible changes. This
is achieved by incrementing the major version (X.y.z | X > 1). It MAY also
include minor and patch level changes. Patch and minor versions MUST be reset to
0 when major version is incremented. (see `api overview <api_overview>`)
.. note::
Breaking API changes will be listed and described in the migration guide.

View file

@ -7,388 +7,49 @@ The table lists Zephyr's APIs and information about them, including their
current :ref:`stability level <api_lifecycle>`. More details about API changes
between major releases are available in the :ref:`zephyr_release_notes`.
.. Keep this list sorted by the name of the API as it appears
in the HTML, *NOT* the :ref: label
The version column uses `semantic version <https://semver.org/>`_, and has the
following expectations:
.. list-table::
:header-rows: 1
* Major version zero (0.y.z) is for initial development. Anything MAY
change at any time. The public API SHOULD NOT be considered stable.
* - API
- Status
- Version Introduced
* If minor version is up to one (0.1.z), API is considered
:ref:`experimental <api_lifecycle_experimental>`.
* If minor version is larger than one (0.y.z | y > 1), API is considered
:ref:`unstable <api_lifecycle_unstable>`.
* - :ref:`adc_api`
- Stable
- 1.0
* Version 1.0.0 defines the public API. The way in which the version number
is incremented after this release is dependent on this public API and how it
changes.
* - :ref:`audio_codec_api`
- Experimental
- 1.13
* APIs with major versions equal or larger than one (x.y.z | x >= 1 ) are
considered :ref:`stable <api_lifecycle_stable>`.
* All existing stable APIs in Zephyr will be start with version 1.0.0.
* - :ref:`audio_dmic_api`
- Experimental
- 1.13
* Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards
compatible bug fixes are introduced. A bug fix is defined as an internal
change that fixes incorrect behavior.
* - :ref:`auxdisplay_api`
- Experimental
- 3.4
* Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards
compatible functionality is introduced to the public API. It MUST be
incremented if any public API functionality is marked as deprecated. It MAY
be incremented if substantial new functionality or improvements are
introduced within the private code. It MAY include patch level changes.
Patch version MUST be reset to 0 when minor version is incremented.
* - :ref:`barriers_api`
- Experimental
- 3.4
* Major version X (x.Y.z | x > 0) MUST be incremented if a compatibility
breaking change was made to the API.
* - :ref:`blinfo_api`
- Experimental
- 3.5
.. note::
Version for existing APIs are initially set based on the current state of the
APIs:
* - :ref:`bluetooth_api`
- Stable
- 1.0
- 0.1.0 denotes an :ref:`experimental <api_lifecycle_experimental>` API
- 0.8.0 denote an :ref:`unstable <api_lifecycle_unstable>` API,
- and finally 1.0.0 indicates a :ref:`stable <api_lifecycle_stable>` APIs.
* - :ref:`clock_control_api`
- Stable
- 1.0
Changes to APIs in the future will require adapting the version following the
guidelines above.
* - :ref:`coap_sock_interface`
- Unstable
- 1.10
* - :ref:`conn_mgr_docs`
- Experimental
- 3.4.0
* - :ref:`can_api`
- Stable
- 1.14
* - :ref:`can_transceiver_api`
- Experimental
- 3.1
* - :ref:`charger_api`
- Experimental
- 3.5
* - :ref:`counter_api`
- Unstable
- 1.14
* - :ref:`crypto_api`
- Stable
- 1.7
* - :ref:`dac_api`
- Unstable
- 2.3
* - :ref:`dai_api`
- Experimental
- 3.1
* - :ref:`dma_api`
- Stable
- 1.5
* - :ref:`device_model_api`
- Stable
- 1.0
* - :ref:`devicetree_api`
- Stable
- 2.2
* - :ref:`disk_access_api`
- Stable
- 1.6
* - :ref:`display_api`
- Unstable
- 1.14
* - :ref:`ec_host_cmd_backend_api`
- Experimental
- 2.4
* - :ref:`edac_api`
- Unstable
- 2.5
* - :ref:`eeprom_api`
- Stable
- 2.1
* - :ref:`entropy_api`
- Stable
- 1.10
* - :ref:`file_system_api`
- Stable
- 1.5
* - :ref:`flash_api`
- Stable
- 1.2
* - :ref:`fcb_api`
- Stable
- 1.11
* - :ref:`fuel_gauge_api`
- Experimental
- 3.3
* - :ref:`flash_map_api`
- Stable
- 1.11
* - :ref:`gnss_api`
- Experimental
- 3.6
* - :ref:`gpio_api`
- Stable
- 1.0
* - :ref:`hwinfo_api`
- Stable
- 1.14
* - :ref:`i2c_eeprom_target_api`
- Stable
- 1.13
* - :ref:`i2c_api`
- Stable
- 1.0
* - :ref:`i2c-target-api`
- Experimental
- 1.12
* - :ref:`i2s_api`
- Stable
- 1.9
* - :ref:`i3c_api`
- Experimental
- 3.2
* - :ref:`ieee802154_driver_api`
- Unstable
- 1.0
* - :ref:`ieee802154_l2_api`
- Unstable
- 1.0
* - :ref:`ieee802154_mgmt_api`
- Unstable
- 1.0
* - :ref:`input`
- Experimental
- 3.4
* - :ref:`ipm_api`
- Stable
- 1.0
* - :ref:`kscan_api`
- Stable
- 2.1
* - :ref:`kernel_api`
- Stable
- 1.0
* - :ref:`led_api`
- Stable
- 1.12
* - :ref:`lwm2m_interface`
- Unstable
- 1.9
* - :ref:`llext`
- Experimental
- 3.5
* - :ref:`logging_api`
- Stable
- 1.13
* - :ref:`lora_api`
- Experimental
- 2.2
* - :ref:`lorawan_api`
- Experimental
- 2.5
* - :ref:`mbox_api`
- Experimental
- 1.0
* - :ref:`mcu_mgr`
- Stable
- 1.11
* - :ref:`modem`
- Experimental
- 3.5
* - :ref:`mqtt_socket_interface`
- Unstable
- 1.14
* - :ref:`mipi_dbi_api`
- Experimental
- 3.6
* - :ref:`mipi_dsi_api`
- Experimental
- 3.1
* - :ref:`misc_api`
- Stable
- 1.0
* - :ref:`networking_api`
- Stable
- 1.0
* - :ref:`nvs_api`
- Stable
- 1.12
* - :ref:`peci_api`
- Stable
- 2.1
* - :ref:`ps2_api`
- Stable
- 2.1
* - :ref:`pwm_api`
- Stable
- 1.0
* - :ref:`pinctrl_api`
- Experimental
- 3.0
* - :ref:`pm_api`
- Experimental
- 1.2
* - :ref:`random_api`
- Stable
- 1.0
* - :ref:`regulator_api`
- Experimental
- 2.4
* - :ref:`reset_api`
- Experimental
- 3.1
* - :ref:`retained_mem_api`
- Unstable
- 3.4
* - :ref:`retention_api`
- Experimental
- 3.4
* - :ref:`rtc_api`
- Experimental
- 3.4
* - :ref:`rtio_api`
- Experimental
- 3.2
* - :ref:`smbus_api`
- Experimental
- 3.4
* - :ref:`spi_api`
- Stable
- 1.0
* - :ref:`sensor_api`
- Stable
- 1.2
* - :ref:`settings_api`
- Stable
- 1.12
* - :ref:`shell_api`
- Stable
- 1.14
* - :ref:`stream_flash`
- Experimental
- 2.3
* - :ref:`sdhc_api`
- Experimental
- 3.1
* - :ref:`task_wdt_api`
- Unstable
- 2.5
* - :ref:`tcpc_api`
- Experimental
- 3.1
* - :ref:`tgpio_api`
- Experimental
- 3.5
* - :ref:`uart_api`
- Stable
- 1.0
* - :ref:`UART async <uart_api>`
- Unstable
- 1.14
* - :ref:`usb_api`
- Stable
- 1.5
* - :ref:`usbc_api`
- Experimental
- 3.3
* - :ref:`usermode_api`
- Stable
- 1.11
* - :ref:`usbc_vbus_api`
- Experimental
- 3.3
* - :ref:`util_api`
- Experimental
- 2.4
* - :ref:`video_api`
- Stable
- 2.1
* - :ref:`w1_api`
- Experimental
- 3.2
* - :ref:`watchdog_api`
- Stable
- 1.0
* - :ref:`zdsp_api`
- Experimental
- 3.3
.. api-overview-table::