Skip to content

Commit 76602b0

Browse files
committed
docs: add Doxygen API reference to the versioned documentation site
Generate the Doxygen API reference of the core and publish it with each documentation version, so it is available at /dev/doxygen/, /latest/doxygen/ and /<X.Y.Z>/doxygen/. - Add doxygen/Doxyfile covering cores, libraries, system and variants, excluding cores/arduino/api, system/Drivers and system/Middlewares. Source listings are disabled to keep each published version small. __cplusplus and the HAL module macros used as guards are predefined so that classes such as HardwareTimer are documented. - Add an HTML header and version-selector.js: every Doxygen page links back to the documentation home of the same version and provides a version selector (dev, latest, releases) fed by the mike versions.json. When a page does not exist in the selected version, it falls back to the Doxygen home page, then to the documentation home page. - Add docs/hooks/doxygen.py, a MkDocs hook adding the Doxygen output to the site, or a placeholder page when it is absent so that documentation only builds still pass mkdocs build --strict. - Build the Doxygen output in docs-check.yml and publish-docs.yml before MkDocs, check that it is part of the site, and also trigger both workflows on changes to the documented sources. - Ignore doxygen/** in the Arduino, CMake and PlatformIO build workflows. - Link the reference from API.md, the home page, the Core Reference navigation and README.md. - Document the Doxygen generation, publication and version selector in Documentation-workflow.md. - Restrict the release tag pattern to a major version below 1000 in publish-docs.yml (tag validation and "latest" computation) and in the supported boards generator. The legacy date tags 2017.8.31 to 2018.1.18 matched X.Y.Z and were seen as the highest tag, so "latest" and the site default would never have moved to a new release. - Document in Documentation-workflow.md how the supported boards "Next release" labels are resolved from the release tags, and that docs/supported-boards/index.md must be regenerated and committed after a release tag. Assisted-by: GitHub Copilot: Claude Sonnet 5.5 Signed-off-by: Frederic Pillon <frederic.pillon@st.com>
1 parent 1c47407 commit 76602b0

16 files changed

Lines changed: 423 additions & 10 deletions

‎.github/workflows/Arduino-build.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
- '*.json'
1010
- '**.md'
1111
- docs/**
12+
- doxygen/**
1213
- mkdocs.yml
1314
- requirements-docs.txt
1415
- keywords.txt
@@ -24,6 +25,7 @@ on:
2425
- '*.json'
2526
- '**.md'
2627
- docs/**
28+
- doxygen/**
2729
- mkdocs.yml
2830
- requirements-docs.txt
2931
- keywords.txt

‎.github/workflows/Cmake.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
- '*.json'
1111
- '**.md'
1212
- docs/**
13+
- doxygen/**
1314
- mkdocs.yml
1415
- requirements-docs.txt
1516
- keywords.txt
@@ -22,6 +23,7 @@ on:
2223
- '*.json'
2324
- '**.md'
2425
- docs/**
26+
- doxygen/**
2527
- mkdocs.yml
2628
- requirements-docs.txt
2729
- keywords.txt

‎.github/workflows/PIO-build.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
- '*.json'
1111
- '**.md'
1212
- docs/**
13+
- doxygen/**
1314
- mkdocs.yml
1415
- requirements-docs.txt
1516
- keywords.txt
@@ -26,6 +27,7 @@ on:
2627
- '*.json'
2728
- '**.md'
2829
- docs/**
30+
- doxygen/**
2931
- mkdocs.yml
3032
- requirements-docs.txt
3133
- keywords.txt

‎.github/workflows/docs-check.yml‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ on:
1010
- boards.txt
1111
- mkdocs.yml
1212
- requirements-docs.txt
13+
- doxygen/**
14+
- cores/**
15+
- libraries/**
16+
- variants/**
17+
- system/**
18+
- "!system/Drivers/**"
19+
- "!system/Middlewares/**"
1320
- .github/workflows/docs-check.yml
1421

1522
permissions:
@@ -26,6 +33,16 @@ jobs:
2633
with:
2734
python-version: "3.x"
2835
- run: python -m pip install -r requirements-docs.txt
36+
- name: Install Doxygen
37+
run: sudo apt-get update && sudo apt-get install --yes doxygen
38+
- name: Build Doxygen API reference
39+
run: |
40+
STM32_CORE_VERSION=$(sed -n 's/^version=//p' platform.txt)
41+
export STM32_CORE_VERSION
42+
doxygen doxygen/Doxyfile
43+
test -f build/doxygen/index.html
2944
- run: mkdocs build --strict
45+
- name: Check the Doxygen API reference is part of the site
46+
run: grep -q 'name="generator" content="Doxygen' site/doxygen/index.html
3047
- name: Check generated supported boards page is committed
3148
run: git diff --exit-code -- docs/supported-boards/index.md || { echo "::error::Run 'python docs/hooks/supported_boards.py' and commit docs/supported-boards/index.md"; exit 1; }

‎.github/workflows/publish-docs.yml‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ on:
1111
- boards.txt
1212
- mkdocs.yml
1313
- requirements-docs.txt
14+
- doxygen/**
15+
- cores/**
16+
- libraries/**
17+
- variants/**
18+
- system/**
19+
- "!system/Drivers/**"
20+
- "!system/Middlewares/**"
1421
- .github/workflows/publish-docs.yml
1522
workflow_dispatch:
1623

@@ -33,6 +40,14 @@ jobs:
3340
with:
3441
python-version: "3.x"
3542
- run: python -m pip install -r requirements-docs.txt
43+
- name: Install Doxygen
44+
run: sudo apt-get update && sudo apt-get install --yes doxygen
45+
- name: Build Doxygen API reference
46+
run: |
47+
STM32_CORE_VERSION=$(sed -n 's/^version=//p' platform.txt)
48+
export STM32_CORE_VERSION
49+
doxygen doxygen/Doxyfile
50+
test -f build/doxygen/index.html
3651
- name: Configure Git author
3752
run: |
3853
git config user.name "github-actions[bot]"
@@ -68,11 +83,13 @@ jobs:
6883
env:
6984
VERSION: ${{ github.ref_name }}
7085
run: |
71-
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
86+
# Core releases have a major version below 1000: this excludes the
87+
# legacy date tags such as 2018.1.18, which would otherwise sort last.
88+
if [[ ! "$VERSION" =~ ^[0-9]{1,3}\.[0-9]+\.[0-9]+$ ]]; then
7289
echo "Unsupported documentation release tag: $VERSION" >&2
7390
exit 1
7491
fi
75-
latest=$(git tag --list | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1)
92+
latest=$(git tag --list | grep -E '^[0-9]{1,3}\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1)
7693
if git ls-remote --exit-code --heads pages gh-pages >/dev/null; then
7794
git fetch pages gh-pages:gh-pages
7895
fi

‎README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
* [Getting Started](https://github.com/stm32duino/Arduino_Core_STM32#getting-started)<br>
1717
* [Supported boards](docs/supported-boards/index.md)<br>
1818
* [Troubleshooting](https://github.com/stm32duino/Arduino_Core_STM32#troubleshooting)<br>
19-
* [Documentation](https://stm32duino.github.io/latest/)
19+
* [Documentation](https://stm32duino.github.io/latest/)<br>
20+
* [API reference (Doxygen)](https://stm32duino.github.io/dev/doxygen/)
2021

2122
## Introduction
2223

‎docs/API.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
66
This page documents STM32-specific additions and extensions. For the standard Arduino API, see the [Arduino language reference](https://docs.arduino.cc/language-reference/) and the [ArduinoCore-API documentation](https://github.com/arduino/ArduinoCore-API).
77

8+
> [!TIP]
9+
> The source-level reference of the core, generated with Doxygen from the code comments (classes, structures, functions and their parameters), is available in the [Doxygen API reference](doxygen/index.html). It follows the documentation version selected in this site: use the version selector to switch between `dev` and the released versions.
10+
811
## Core
912

1013
This part describes the STM32 core functions.

‎docs/development/Documentation-workflow.md‎

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ The STM32 core documentation is maintained in the `docs/` directory of the `stm3
88
2. Add new pages to the `nav` section in `mkdocs.yml`. The navigation is explicit, so a file that is not listed there will not appear in the sidebar.
99
3. Use relative links to other Markdown files and verify that image paths resolve from the page containing them.
1010
4. The [Supported boards](../supported-boards/index.md) page is generated from `boards.txt`: do not edit it. After changing `boards.txt`, run `python docs/hooks/supported_boards.py` (or any MkDocs build) and commit the updated `docs/supported-boards/index.md`; the documentation check fails if it is out of date. Optional `# Docs: field=value` comments placed directly above a board option (`<group>.menu.pnum.<option>=...`) add metadata: `release`, `mcu`, `url` and `notes`; above a `<group>.name=` line, `url` links the category. Options without `release` get their first release from Git tags, so keep full Git history and tags available when building the documentation.
11-
5. Create a persistent virtual environment under your home directory once, then install or update the documentation dependencies from the core repository:
11+
5. The [Doxygen API reference](#doxygen-api-reference) is generated from the comments in the source code: to change it, edit the comments in the sources, not the documentation pages. Documentation-only builds work without Doxygen installed.
12+
6. Create a persistent virtual environment under your home directory once, then install or update the documentation dependencies from the core repository:
1213

1314
```bash
1415
python3 -m venv "$HOME/.venvs/stm32duino-docs"
@@ -39,18 +40,79 @@ Open `http://127.0.0.1:8000/dev/`. This exercises links under the `/dev/` prefix
3940

4041
The static preview tests the selected version's files and paths, not Mike's deployed version list or redirects. To inspect the actual locally deployed versions and default redirect, use `mike serve` from a checkout whose configured `gh-pages` branch already contains those deployments.
4142

43+
## Doxygen API reference
44+
45+
The source-level API reference (classes, structures, functions and their parameters of the core, its libraries, the STM32 system files and the variants) is generated with [Doxygen](https://www.doxygen.nl/) from the comments in the source code. It is not written by hand: improve it by editing the Doxygen comments in the sources, not the generated pages.
46+
47+
The reference is part of the versioned site and is published at `/<version>/doxygen/`, for example `/dev/doxygen/` or `/latest/doxygen/`. It is linked from the [Arduino API](../API.md) page, from the home page, and from the **Core Reference** section of the navigation.
48+
49+
### Files
50+
51+
| File | Purpose |
52+
| --- | --- |
53+
| `doxygen/Doxyfile` | Doxygen configuration: scope, preprocessor definitions, output location. |
54+
| `doxygen/mainpage.md` | Main page of the reference. |
55+
| `doxygen/html-header.html` | HTML header template: link back to the documentation site and version selector. |
56+
| `doxygen/version-selector.js` | Version selector: lists the versions from the Mike `versions.json` file of the site. |
57+
| `docs/hooks/doxygen.py` | MkDocs hook that adds the generated Doxygen pages to the site under the same version prefix. |
58+
59+
### Comment conventions
60+
61+
- API contracts (`@brief`, `@param`, `@return`, `@note`) are written in the header files. Do not duplicate them in the source file.
62+
- Static and source-only functions are documented directly above their definition in the `.c`/`.cpp` file.
63+
- The ST HAL, LL and CMSIS drivers (`system/Drivers`), the middlewares (`system/Middlewares`) and `cores/arduino/api` (ArduinoCore-API) are excluded from the reference.
64+
- Only documented items are listed (`EXTRACT_ALL = NO`).
65+
- Code under a guard such as `HAL_TIM_MODULE_ENABLED` is only documented if the macro is listed in `PREDEFINED` in `doxygen/Doxyfile`. Add the macro there when a new guard hides documented code.
66+
- Source listings are not generated, to keep every published version small; the reference links to the declarations, and the sources are on GitHub.
67+
68+
### Build locally
69+
70+
Install Doxygen 1.9.8 or later (`sudo apt-get install doxygen` on Debian/Ubuntu), then run, from the repository root:
71+
72+
```bash
73+
STM32_CORE_VERSION=$(sed -n 's/^version=//p' platform.txt) doxygen doxygen/Doxyfile
74+
```
75+
76+
The HTML pages are written to `build/doxygen/`, which is ignored by Git. Open `build/doxygen/index.html` to review them. Doxygen warnings are printed on the standard error: fix those that concern the comments you changed.
77+
78+
To check the reference inside the documentation site, run the Doxygen command above first, then build or serve the site as described in [Update documentation](#update-documentation) and [Preview locally](#preview-locally). When `build/doxygen/` exists, MkDocs adds its pages to the site at `doxygen/`. When it does not, MkDocs adds a placeholder `doxygen/index.html` page, so documentation-only builds, including `mkdocs build --strict`, work without Doxygen installed; the workflows never publish the placeholder because they build the real reference first.
79+
80+
### Version selector
81+
82+
Every Doxygen page shows a **← STM32duino documentation** link, which goes to the home page of the same documentation version, and a **Version** selector. The selector lists the versions published by Mike (`dev`, `latest` and each release) and opens the same page in the selected version. If that page does not exist in the selected version, for example because the version was published before the reference was added or the page was renamed, it opens the Doxygen home page of that version, and then the documentation home page of that version.
83+
84+
The selector reads `versions.json` from the site root, so it only appears on a published site or on a preview that contains it. A preview built with `mkdocs build --site-dir /tmp/stm32duino-docs-preview/dev` has no `versions.json`: the selector is hidden, the link back still works.
85+
86+
### Maintenance
87+
88+
- `doxygen/html-header.html` is based on the default header of Doxygen 1.9.8 (`doxygen -w html header.html footer.html style.css`). When the Doxygen version used by the workflows changes, regenerate the default header, reapply the two additions (the `version-selector.js` script and the `doc-nav` cell with the link and the selector) and check the pages again.
89+
- The Doxygen version is the one installed from the `ubuntu-latest` runner image by the workflows.
90+
4291
## Pull request checks
4392

44-
The `Documentation build` workflow runs `mkdocs build --strict` on every pull request, including pull requests that do not edit documentation. It also runs on `main` when documentation sources, the MkDocs configuration, its dependencies, or the workflow change. The `main` branch requires the `Documentation build / build` status check, including for administrators, so a failed or missing result blocks merging.
93+
The `Documentation build` workflow installs Doxygen, builds the API reference, runs `mkdocs build --strict` and fails if the reference is not part of the generated site. It runs on every pull request, including pull requests that do not edit documentation. It also runs on `main` when documentation sources, the Doxygen configuration, the MkDocs configuration, its dependencies, the workflow, or the sources documented by Doxygen (`cores/`, `libraries/`, `variants/`, `system/` except `Drivers/` and `Middlewares/`) change. The `main` branch requires the `Documentation build / build` status check, including for administrators, so a failed or missing result blocks merging.
94+
95+
Doxygen warnings do not fail the check, but they are visible in the log of the `Build Doxygen API reference` step.
4596

4697
If branch protection for `main` is recreated or changed, keep `Documentation build / build` as a required status check.
4798

4899
## Publish a release
49100

50-
The documentation publisher uses Mike to keep versioned snapshots on the `gh-pages` branch of `stm32duino/stm32duino.github.io`:
101+
The documentation publisher uses Mike to keep versioned snapshots on the `gh-pages` branch of `stm32duino/stm32duino.github.io`. Before running Mike, the workflow installs Doxygen and builds the API reference, so each snapshot contains the Doxygen pages generated from the sources of the commit or tag being published:
51102

52-
- Documentation changes merged to `main` publish the development version at `/dev/`. The first publish sets `dev` as the site default; later development publishes leave the existing default unchanged.
53-
- Pushing an exact semantic-version tag such as `3.0.0` publishes that release at `/3.0.0/`.
103+
- Documentation or documented-source changes merged to `main` publish the development version at `/dev/` (documentation at `/dev/`, API reference at `/dev/doxygen/`). The first publish sets `dev` as the site default; later development publishes leave the existing default unchanged.
104+
- Pushing an exact semantic-version tag such as `3.0.0` publishes that release at `/3.0.0/` (API reference at `/3.0.0/doxygen/`).
54105
- When the pushed tag is the highest semantic-version tag in the core repository, the workflow also moves the `latest` alias and sets it as the site default. Older release tags are published without changing `latest`.
55106

56-
Use the normal core release process to create and push the release tag. The documentation workflow runs from that tag automatically; no manual Mike command is needed. GitHub release tags must use the exact `MAJOR.MINOR.PATCH` form for this workflow.
107+
Use the normal core release process to create and push the release tag. The documentation workflow runs from that tag automatically; no manual Mike command is needed. GitHub release tags must use the exact `MAJOR.MINOR.PATCH` form, with a major version below 1000, for this workflow. The legacy date tags such as `2018.1.18` are not release tags: they are ignored when the highest release is computed, so they never prevent `latest` from moving, and a new tag in that form is rejected.
108+
109+
Releases published before the Doxygen reference was added do not contain it; the version selector falls back to the documentation home page of those versions.
110+
111+
### Supported boards after a release
112+
113+
The **First release** column of the [Supported boards](../supported-boards/index.md) page is computed from the Git tags each time the documentation is built. A board that is in `boards.txt` but in no release tag yet shows **Next release**.
114+
115+
- The workflow builds from the release tag, which is fetched with the full history, so the `/<X.Y.Z>/` documentation published for the tag already shows the new release number for the boards it contains. Pages of older versions are not rebuilt and keep their labels.
116+
- The generated `docs/supported-boards/index.md` committed on `main` is not updated by the workflow. Once the tag exists, it differs from a fresh build, so the `Documentation build` check fails on the next pull request until it is regenerated. After pushing a release tag, run `python docs/hooks/supported_boards.py` from a clone that has the tags (`git fetch --tags`) and commit `docs/supported-boards/index.md`.
117+
- The `dev` documentation shows the new release numbers at its next publish.
118+
- To pin a different value for a board, add a `# Docs: release=<version>` comment above its option in `boards.txt`.

‎docs/hooks/doxygen.py‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import logging
2+
from pathlib import Path
3+
4+
from mkdocs.structure.files import File
5+
6+
log = logging.getLogger("mkdocs.hooks.doxygen")
7+
8+
# Doxygen HTML output, see doxygen/Doxyfile (relative to the repository root).
9+
# Its last component is the folder of the generated site: <site>/<version>/doxygen/
10+
DOXYGEN_OUTPUT = Path("build/doxygen")
11+
12+
PLACEHOLDER = """<!DOCTYPE html>
13+
<html lang="en">
14+
<head><meta charset="utf-8"><title>Doxygen API reference not generated</title></head>
15+
<body>
16+
<h1>Doxygen API reference not generated</h1>
17+
<p>This build does not contain the Doxygen API reference.
18+
Run <code>doxygen doxygen/Doxyfile</code> from the repository root, then build the site again.</p>
19+
</body>
20+
</html>
21+
"""
22+
23+
24+
def on_files(files, config):
25+
"""Add the Doxygen HTML pages to the site, under the same version prefix."""
26+
output = Path(config.config_file_path).parent / DOXYGEN_OUTPUT
27+
if not (output / "index.html").is_file():
28+
# Keep the links to the reference valid in builds made without Doxygen.
29+
log.info(
30+
"Doxygen output not found in '%s': adding a placeholder page. "
31+
"Run 'doxygen doxygen/Doxyfile' before building to include the API reference.",
32+
DOXYGEN_OUTPUT,
33+
)
34+
files.append(File.generated(config, f"{DOXYGEN_OUTPUT.name}/index.html", content=PLACEHOLDER))
35+
return files
36+
37+
count = 0
38+
for path in sorted(output.rglob("*")):
39+
if path.is_file():
40+
files.append(
41+
File(
42+
path.relative_to(output.parent).as_posix(),
43+
str(output.parent),
44+
config.site_dir,
45+
config.use_directory_urls,
46+
)
47+
)
48+
count += 1
49+
log.info("Added %d Doxygen API reference files from '%s'", count, DOXYGEN_OUTPUT)
50+
return files

‎docs/hooks/supported_boards.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from pathlib import Path
44

55

6-
RELEASE_TAG_PATTERN = re.compile(r"^\d+\.\d+\.\d+$")
6+
RELEASE_TAG_PATTERN = re.compile(r"^\d{1,3}\.\d+\.\d+$")
77
DOCS_PATTERN = re.compile(r"^# Docs: (mcu|url|notes|release)=(.*)$")
88
PART_PATTERN = re.compile(
99
r"MP1\d\d[A-F]|WBA\d\d[A-Z][0-9A-Z]|WLE\d[A-Z][0-9A-Z]|W[BL][0-9A-Z]{2}[A-Z][0-9A-Z]"

0 commit comments

Comments
 (0)