1# Zephyr documentation build configuration file.
2# Reference: https://www.sphinx-doc.org/en/master/usage/configuration.html
3
4import os
5import re
6import sys
7import textwrap
8from pathlib import Path
9
10ZEPHYR_BASE = Path(__file__).resolve().parents[1]
11ZEPHYR_BUILD = Path(os.environ.get("OUTPUT_DIR")).resolve()
12
13# Add the '_extensions' directory to sys.path, to enable finding Sphinx
14# extensions within.
15sys.path.insert(0, str(ZEPHYR_BASE / "doc" / "_extensions"))
16
17# Add the '_scripts' directory to sys.path, to enable finding utility
18# modules.
19sys.path.insert(0, str(ZEPHYR_BASE / "doc" / "_scripts"))
20
21# Add the directory which contains the runners package as well,
22# for autodoc directives on runners.xyz.
23sys.path.insert(0, str(ZEPHYR_BASE / "scripts" / "west_commands"))
24
25# Add the directory which contains the pytest-twister-pytest
26sys.path.insert(0, str(ZEPHYR_BASE / "scripts" / "pylib" / "pytest-twister-harness" / "src"))
27
28import redirects  # noqa: E402
29
30try:
31    import west as west_found
32except ImportError:
33    west_found = False
34
35# -- Project --------------------------------------------------------------
36
37project = "Zephyr Project"
38copyright = "2015-2024 Zephyr Project members and individual contributors"
39author = "The Zephyr Project Contributors"
40
41# parse version from 'VERSION' file
42with open(ZEPHYR_BASE / "VERSION") as f:
43    m = re.match(
44        (
45            r"^VERSION_MAJOR\s*=\s*(\d+)$\n"
46            + r"^VERSION_MINOR\s*=\s*(\d+)$\n"
47            + r"^PATCHLEVEL\s*=\s*(\d+)$\n"
48            + r"^VERSION_TWEAK\s*=\s*\d+$\n"
49            + r"^EXTRAVERSION\s*=\s*(.*)$"
50        ),
51        f.read(),
52        re.MULTILINE,
53    )
54
55    if not m:
56        sys.stderr.write("Warning: Could not extract kernel version\n")
57        version = "Unknown"
58    else:
59        major, minor, patch, extra = m.groups(1)
60        version = ".".join((major, minor, patch))
61        if extra:
62            version += "-" + extra
63
64release = version
65
66# parse SDK version from 'SDK_VERSION' file
67with open(ZEPHYR_BASE / "SDK_VERSION") as f:
68    sdk_version = f.read().strip()
69
70# -- General configuration ------------------------------------------------
71
72extensions = [
73    "sphinx_rtd_theme",
74    "sphinx.ext.todo",
75    "sphinx.ext.extlinks",
76    "sphinx.ext.autodoc",
77    "sphinx.ext.graphviz",
78    "sphinxcontrib.jquery",
79    "zephyr.application",
80    "zephyr.html_redirects",
81    "zephyr.kconfig",
82    "zephyr.dtcompatible-role",
83    "zephyr.link-roles",
84    "sphinx_tabs.tabs",
85    "sphinx_sitemap",
86    "zephyr.doxyrunner",
87    "zephyr.doxybridge",
88    "zephyr.doxytooltip",
89    "zephyr.gh_utils",
90    "zephyr.manifest_projects_table",
91    "notfound.extension",
92    "sphinx_copybutton",
93    "sphinx_togglebutton",
94    "zephyr.external_content",
95    "zephyr.domain",
96    "zephyr.api_overview",
97]
98
99# Only use image conversion when it is really needed, e.g. LaTeX build.
100# Ensure "sphinxcontrib.rsvgconverter" is added before "sphinx.ext.imgconverter"
101# as it's better at converting SVG with extended features (like the ones from
102# draw.io) to PDF format).
103if tags.has("convertimages"):  # pylint: disable=undefined-variable  # noqa: F821
104    extensions.append("sphinxcontrib.rsvgconverter")
105    extensions.append("sphinx.ext.imgconverter")
106
107templates_path = ["_templates"]
108
109exclude_patterns = ["_build"]
110
111if not west_found:
112    exclude_patterns.append("**/*west-apis*")
113else:
114    exclude_patterns.append("**/*west-not-found*")
115
116pygments_style = "sphinx"
117highlight_language = "none"
118
119todo_include_todos = False
120
121nitpick_ignore = [
122    # ignore C standard identifiers (they are not defined in Zephyr docs)
123    ("c:identifier", "FILE"),
124    ("c:identifier", "int8_t"),
125    ("c:identifier", "int16_t"),
126    ("c:identifier", "int32_t"),
127    ("c:identifier", "int64_t"),
128    ("c:identifier", "intptr_t"),
129    ("c:identifier", "off_t"),
130    ("c:identifier", "size_t"),
131    ("c:identifier", "ssize_t"),
132    ("c:identifier", "time_t"),
133    ("c:identifier", "uint8_t"),
134    ("c:identifier", "uint16_t"),
135    ("c:identifier", "uint32_t"),
136    ("c:identifier", "uint64_t"),
137    ("c:identifier", "uintptr_t"),
138    ("c:identifier", "va_list"),
139]
140
141SDK_URL_BASE="https://github.com/zephyrproject-rtos/sdk-ng/releases/download"
142
143rst_epilog = f"""
144.. include:: /substitutions.txt
145
146.. |sdk-version-literal| replace:: ``{sdk_version}``
147.. |sdk-version-trim| unicode:: {sdk_version}
148   :trim:
149.. |sdk-version-ltrim| unicode:: {sdk_version}
150   :ltrim:
151.. _Zephyr SDK bundle: https://github.com/zephyrproject-rtos/sdk-ng/releases/tag/v{sdk_version}
152.. |sdk-url-linux| replace::
153   `{SDK_URL_BASE}/v{sdk_version}/zephyr-sdk-{sdk_version}_linux-x86_64.tar.xz`
154.. |sdk-url-linux-sha| replace::
155   `{SDK_URL_BASE}/v{sdk_version}/sha256.sum`
156.. |sdk-url-macos| replace::
157   `{SDK_URL_BASE}/v{sdk_version}/zephyr-sdk-{sdk_version}_macos-x86_64.tar.xz`
158.. |sdk-url-macos-sha| replace::
159   `{SDK_URL_BASE}/v{sdk_version}/sha256.sum`
160.. |sdk-url-windows| replace::
161   `{SDK_URL_BASE}/v{sdk_version}/zephyr-sdk-{sdk_version}_windows-x86_64.7z`
162"""
163
164# -- Options for HTML output ----------------------------------------------
165
166html_theme = "sphinx_rtd_theme"
167html_theme_options = {
168    "logo_only": True,
169    "prev_next_buttons_location": None,
170    "navigation_depth": 5,
171}
172html_baseurl = "https://docs.zephyrproject.org/latest/"
173html_title = "Zephyr Project Documentation"
174html_logo = str(ZEPHYR_BASE / "doc" / "_static" / "images" / "logo.svg")
175html_favicon = str(ZEPHYR_BASE / "doc" / "_static" / "images" / "favicon.png")
176html_static_path = [str(ZEPHYR_BASE / "doc" / "_static")]
177html_last_updated_fmt = "%b %d, %Y"
178html_domain_indices = False
179html_split_index = True
180html_show_sourcelink = False
181html_show_sphinx = False
182html_search_scorer = str(ZEPHYR_BASE / "doc" / "_static" / "js" / "scorer.js")
183html_additional_pages = {
184    "gsearch": "gsearch.html"
185}
186
187is_release = tags.has("release")  # pylint: disable=undefined-variable  # noqa: F821
188reference_prefix = ""
189if tags.has("publish"):  # pylint: disable=undefined-variable  # noqa: F821
190    reference_prefix = f"/{version}" if is_release else "/latest"
191docs_title = "Docs / {}".format(version if is_release else "Latest")
192html_context = {
193    "show_license": True,
194    "docs_title": docs_title,
195    "is_release": is_release,
196    "current_version": version,
197    "versions": (
198        ("latest", "/"),
199        ("4.0.0", "/4.0.0/"),
200        ("3.7.0 (LTS)", "/3.7.0/"),
201        ("2.7.6 (LTS)", "/2.7.6/"),
202    ),
203    "display_gh_links": True,
204    "reference_links": {
205        "API": f"{reference_prefix}/doxygen/html/index.html",
206        "Kconfig Options": f"{reference_prefix}/kconfig.html",
207        "Devicetree Bindings": f"{reference_prefix}/build/dts/api/bindings.html",
208        "West Projects": f"{reference_prefix}/develop/manifest/index.html",
209    },
210    # Set google_searchengine_id to your Search Engine ID to replace built-in search
211    # engine with Google's Programmable Search Engine.
212    # See https://programmablesearchengine.google.com/ for details.
213    "google_searchengine_id": "746031aa0d56d4912",
214}
215
216# -- Options for LaTeX output ---------------------------------------------
217
218latex_elements = {
219    "papersize": "a4paper",
220    "maketitle": (ZEPHYR_BASE / "doc" / "_static" / "latex" / "title.tex").read_text(),
221    "preamble": (ZEPHYR_BASE / "doc" / "_static" / "latex" / "preamble.tex").read_text(),
222    "makeindex": r"\usepackage[columns=1]{idxlayout}\makeindex",
223    "fontpkg": textwrap.dedent(r"""
224                                    \usepackage{noto}
225                                    \usepackage{inconsolata-nerd-font}
226                                    \usepackage[T1]{fontenc}
227                                """),
228    "sphinxsetup": ",".join(
229        (
230            # NOTE: colors match those found in light.css stylesheet
231            "verbatimwithframe=false",
232            "VerbatimColor={HTML}{f0f2f4}",
233            "InnerLinkColor={HTML}{2980b9}",
234            "warningBgColor={HTML}{e9a499}",
235            "warningborder=0pt",
236            r"HeaderFamily=\rmfamily\bfseries",
237        )
238    ),
239}
240latex_logo = str(ZEPHYR_BASE / "doc" / "_static" / "images" / "logo-latex.pdf")
241latex_documents = [
242    ("index-tex", "zephyr.tex", "Zephyr Project Documentation", author, "manual"),
243]
244latex_engine = "xelatex"
245
246# -- Options for zephyr.doxyrunner plugin ---------------------------------
247
248doxyrunner_doxygen = os.environ.get("DOXYGEN_EXECUTABLE", "doxygen")
249doxyrunner_doxyfile = ZEPHYR_BASE / "doc" / "zephyr.doxyfile.in"
250doxyrunner_outdir = ZEPHYR_BUILD / "doxygen"
251doxyrunner_fmt = True
252doxyrunner_fmt_vars = {"ZEPHYR_BASE": str(ZEPHYR_BASE), "ZEPHYR_VERSION": version}
253doxyrunner_outdir_var = "DOXY_OUT"
254
255# -- Options for zephyr.doxybridge plugin ---------------------------------
256
257doxybridge_dir = doxyrunner_outdir
258
259# -- Options for html_redirect plugin -------------------------------------
260
261html_redirect_pages = redirects.REDIRECTS
262
263# -- Options for zephyr.link-roles ----------------------------------------
264
265link_roles_manifest_project = "zephyr"
266link_roles_manifest_project_broken_links_ignore_globs = [
267    "releases/release-notes-[123].*.rst",
268]
269link_roles_manifest_baseurl = "https://github.com/zephyrproject-rtos/zephyr"
270
271# -- Options for notfound.extension ---------------------------------------
272
273notfound_urls_prefix = f"/{version}/" if is_release else "/latest/"
274
275# -- Options for zephyr.gh_utils ------------------------------------------
276
277gh_link_version = f"v{version}" if is_release else "main"
278gh_link_base_url = "https://github.com/zephyrproject-rtos/zephyr"
279gh_link_prefixes = {
280    "samples/.*": "",
281    "boards/.*": "",
282    "snippets/.*": "",
283    ".*": "doc",
284}
285gh_link_exclude = [
286    "reference/kconfig.*",
287    "build/dts/api/bindings.*",
288    "build/dts/api/compatibles.*",
289]
290
291# -- Options for zephyr.kconfig -------------------------------------------
292
293kconfig_generate_db = True
294kconfig_ext_paths = [ZEPHYR_BASE]
295
296# -- Options for zephyr.external_content ----------------------------------
297
298external_content_contents = [
299    (ZEPHYR_BASE / "doc", "[!_]*"),
300    (ZEPHYR_BASE, "boards/**/*.rst"),
301    (ZEPHYR_BASE, "boards/**/doc"),
302    (ZEPHYR_BASE, "samples/**/*.html"),
303    (ZEPHYR_BASE, "samples/**/*.rst"),
304    (ZEPHYR_BASE, "samples/**/doc"),
305    (ZEPHYR_BASE, "snippets/**/*.rst"),
306    (ZEPHYR_BASE, "snippets/**/doc"),
307    (ZEPHYR_BASE, "tests/**/*.pts"),
308]
309external_content_keep = [
310    "reference/kconfig/*",
311    "develop/manifest/index.rst",
312    "build/dts/api/bindings.rst",
313    "build/dts/api/bindings/**/*",
314    "build/dts/api/compatibles/**/*",
315]
316
317# -- Options for zephyr.domain --------------------------------------------
318
319zephyr_breathe_insert_related_samples = True
320
321# -- Options for sphinx.ext.graphviz --------------------------------------
322
323graphviz_dot = os.environ.get("DOT_EXECUTABLE", "dot")
324graphviz_output_format = "svg"
325graphviz_dot_args = [
326    "-Gbgcolor=transparent",
327    "-Nstyle=filled",
328    "-Nfillcolor=white",
329    "-Ncolor=gray60",
330    "-Nfontcolor=gray25",
331    "-Ecolor=gray60",
332]
333
334# -- Options for sphinx_copybutton ----------------------------------------
335
336copybutton_prompt_text = r"\$ |uart:~\$ "
337copybutton_prompt_is_regexp = True
338
339# -- Options for sphinx-sitemap ----------------------------------------
340
341sitemap_url_scheme = "{link}"
342
343# -- Linkcheck options ----------------------------------------------------
344
345linkcheck_ignore = [
346    r"https://github.com/zephyrproject-rtos/zephyr/issues/.*"
347]
348
349extlinks = {
350    "github": ("https://github.com/zephyrproject-rtos/zephyr/issues/%s", "GitHub #%s"),
351}
352
353linkcheck_timeout = 30
354linkcheck_workers = 10
355linkcheck_anchors = False
356
357# -- Options for zephyr.api_overview --------------------------------------
358
359api_overview_doxygen_base_url = "../../doxygen/html"
360
361def setup(app):
362    # theme customizations
363    app.add_css_file("css/custom.css")
364    app.add_js_file("js/custom.js")
365