xref: /linux/Documentation/conf.py (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1# SPDX-License-Identifier: GPL-2.0-only
2# pylint: disable=C0103,C0209
3
4"""
5The Linux Kernel documentation build configuration file.
6"""
7
8import os
9import shutil
10import sys
11
12import sphinx
13
14# If extensions (or modules to document with autodoc) are in another directory,
15# add these directories to sys.path here. If the directory is relative to the
16# documentation root, use os.path.abspath to make it absolute, like shown here.
17sys.path.insert(0, os.path.abspath("sphinx"))
18
19from load_config import loadConfig               # pylint: disable=C0413,E0401
20
21# Minimal supported version
22needs_sphinx = "3.4.3"
23
24# Get Sphinx version
25major, minor, patch = sphinx.version_info[:3]          # pylint: disable=I1101
26
27# Include_patterns were added on Sphinx 5.1
28if (major < 5) or (major == 5 and minor < 1):
29    has_include_patterns = False
30else:
31    has_include_patterns = True
32    # Include patterns that don't contain directory names, in glob format
33    include_patterns = ["**.rst"]
34
35# Location of Documentation/ directory
36doctree = os.path.abspath(".")
37
38# Exclude of patterns that don't contain directory names, in glob format.
39exclude_patterns = []
40
41# List of patterns that contain directory names in glob format.
42dyn_include_patterns = []
43dyn_exclude_patterns = ["output"]
44
45# Currently, only netlink/specs has a parser for yaml.
46# Prefer using include patterns if available, as it is faster
47if has_include_patterns:
48    dyn_include_patterns.append("netlink/specs/*.yaml")
49else:
50    dyn_exclude_patterns.append("netlink/*.yaml")
51    dyn_exclude_patterns.append("devicetree/bindings/**.yaml")
52    dyn_exclude_patterns.append("core-api/kho/bindings/**.yaml")
53
54# Properly handle include/exclude patterns
55# ----------------------------------------
56
57def update_patterns(app, config):
58    """
59    On Sphinx, all directories are relative to what it is passed as
60    SOURCEDIR parameter for sphinx-build. Due to that, all patterns
61    that have directory names on it need to be dynamically set, after
62    converting them to a relative patch.
63
64    As Sphinx doesn't include any patterns outside SOURCEDIR, we should
65    exclude relative patterns that start with "../".
66    """
67
68    # setup include_patterns dynamically
69    if has_include_patterns:
70        for p in dyn_include_patterns:
71            full = os.path.join(doctree, p)
72
73            rel_path = os.path.relpath(full, start=app.srcdir)
74            if rel_path.startswith("../"):
75                continue
76
77            config.include_patterns.append(rel_path)
78
79    # setup exclude_patterns dynamically
80    for p in dyn_exclude_patterns:
81        full = os.path.join(doctree, p)
82
83        rel_path = os.path.relpath(full, start=app.srcdir)
84        if rel_path.startswith("../"):
85            continue
86
87        config.exclude_patterns.append(rel_path)
88
89
90# helper
91# ------
92
93
94def have_command(cmd):
95    """Search ``cmd`` in the ``PATH`` environment.
96
97    If found, return True.
98    If not found, return False.
99    """
100    return shutil.which(cmd) is not None
101
102
103# -- General configuration ------------------------------------------------
104
105# Add any Sphinx extensions in alphabetic order
106extensions = [
107    "automarkup",
108    "kernel_abi",
109    "kerneldoc",
110    "kernel_feat",
111    "kernel_include",
112    "kfigure",
113    "maintainers_include",
114    "parser_yaml",
115    "rstFlatTable",
116    "sphinx.ext.autosectionlabel",
117    "sphinx.ext.ifconfig",
118    "translations",
119]
120# Since Sphinx version 3, the C function parser is more pedantic with regards
121# to type checking. Due to that, having macros at c:function cause problems.
122# Those needed to be escaped by using c_id_attributes[] array
123c_id_attributes = [
124    # GCC Compiler types not parsed by Sphinx:
125    "__restrict__",
126
127    # include/linux/compiler_types.h:
128    "__iomem",
129    "__kernel",
130    "noinstr",
131    "notrace",
132    "__percpu",
133    "__rcu",
134    "__user",
135    "__force",
136    "__counted_by_le",
137    "__counted_by_be",
138
139    # include/linux/compiler_attributes.h:
140    "__alias",
141    "__aligned",
142    "__aligned_largest",
143    "__always_inline",
144    "__assume_aligned",
145    "__cold",
146    "__attribute_const__",
147    "__copy",
148    "__pure",
149    "__designated_init",
150    "__visible",
151    "__printf",
152    "__scanf",
153    "__gnu_inline",
154    "__malloc",
155    "__mode",
156    "__no_caller_saved_registers",
157    "__noclone",
158    "__nonstring",
159    "__noreturn",
160    "__packed",
161    "__pure",
162    "__section",
163    "__always_unused",
164    "__maybe_unused",
165    "__used",
166    "__weak",
167    "noinline",
168    "__fix_address",
169    "__counted_by",
170
171    # include/linux/memblock.h:
172    "__init_memblock",
173    "__meminit",
174
175    # include/linux/init.h:
176    "__init",
177    "__ref",
178
179    # include/linux/linkage.h:
180    "asmlinkage",
181
182    # include/linux/btf.h
183    "__bpf_kfunc",
184]
185
186# Ensure that autosectionlabel will produce unique names
187autosectionlabel_prefix_document = True
188autosectionlabel_maxdepth = 2
189
190# Load math renderer:
191# For html builder, load imgmath only when its dependencies are met.
192# mathjax is the default math renderer since Sphinx 1.8.
193have_latex = have_command("latex")
194have_dvipng = have_command("dvipng")
195load_imgmath = have_latex and have_dvipng
196
197# Respect SPHINX_IMGMATH (for html docs only)
198if "SPHINX_IMGMATH" in os.environ:
199    env_sphinx_imgmath = os.environ["SPHINX_IMGMATH"]
200    if "yes" in env_sphinx_imgmath:
201        load_imgmath = True
202    elif "no" in env_sphinx_imgmath:
203        load_imgmath = False
204    else:
205        sys.stderr.write("Unknown env SPHINX_IMGMATH=%s ignored.\n" % env_sphinx_imgmath)
206
207if load_imgmath:
208    extensions.append("sphinx.ext.imgmath")
209    math_renderer = "imgmath"
210else:
211    math_renderer = "mathjax"
212
213# Add any paths that contain templates here, relative to this directory.
214templates_path = ["sphinx/templates"]
215
216# The suffixes of source filenames that will be automatically parsed
217source_suffix = {
218    ".rst": "restructuredtext",
219    ".yaml": "yaml",
220}
221
222# The encoding of source files.
223# source_encoding = 'utf-8-sig'
224
225# The master toctree document.
226master_doc = "index"
227
228# General information about the project.
229project = "The Linux Kernel"
230copyright = "The kernel development community"         # pylint: disable=W0622
231author = "The kernel development community"
232
233# The version info for the project you're documenting, acts as replacement for
234# |version| and |release|, also used in various other places throughout the
235# built documents.
236#
237# In a normal build, version and release are are set to KERNELVERSION and
238# KERNELRELEASE, respectively, from the Makefile via Sphinx command line
239# arguments.
240#
241# The following code tries to extract the information by reading the Makefile,
242# when Sphinx is run directly (e.g. by Read the Docs).
243try:
244    makefile_version = None
245    makefile_patchlevel = None
246    with open("../Makefile", encoding="utf=8") as fp:
247        for line in fp:
248            key, val = [x.strip() for x in line.split("=", 2)]
249            if key == "VERSION":
250                makefile_version = val
251            elif key == "PATCHLEVEL":
252                makefile_patchlevel = val
253            if makefile_version and makefile_patchlevel:
254                break
255except Exception:
256    pass
257finally:
258    if makefile_version and makefile_patchlevel:
259        version = release = makefile_version + "." + makefile_patchlevel
260    else:
261        version = release = "unknown version"
262
263
264def get_cline_version():
265    """
266    HACK: There seems to be no easy way for us to get at the version and
267    release information passed in from the makefile...so go pawing through the
268    command-line options and find it for ourselves.
269    """
270
271    c_version = c_release = ""
272    for arg in sys.argv:
273        if arg.startswith("version="):
274            c_version = arg[8:]
275        elif arg.startswith("release="):
276            c_release = arg[8:]
277    if c_version:
278        if c_release:
279            return c_version + "-" + c_release
280        return c_version
281    return version  # Whatever we came up with before
282
283
284# The language for content autogenerated by Sphinx. Refer to documentation
285# for a list of supported languages.
286#
287# This is also used if you do content translation via gettext catalogs.
288# Usually you set "language" from the command line for these cases.
289language = "en"
290
291# There are two options for replacing |today|: either, you set today to some
292# non-false value, then it is used:
293# today = ''
294# Else, today_fmt is used as the format for a strftime call.
295# today_fmt = '%B %d, %Y'
296
297# The reST default role (used for this markup: `text`) to use for all
298# documents.
299# default_role = None
300
301# If true, '()' will be appended to :func: etc. cross-reference text.
302# add_function_parentheses = True
303
304# If true, the current module name will be prepended to all description
305# unit titles (such as .. function::).
306# add_module_names = True
307
308# If true, sectionauthor and moduleauthor directives will be shown in the
309# output. They are ignored by default.
310# show_authors = False
311
312# The name of the Pygments (syntax highlighting) style to use.
313pygments_style = "sphinx"
314
315# A list of ignored prefixes for module index sorting.
316# modindex_common_prefix = []
317
318# If true, keep warnings as "system message" paragraphs in the built documents.
319# keep_warnings = False
320
321# If true, `todo` and `todoList` produce output, else they produce nothing.
322todo_include_todos = False
323
324primary_domain = "c"
325highlight_language = "none"
326
327# -- Options for HTML output ----------------------------------------------
328
329# The theme to use for HTML and HTML Help pages.  See the documentation for
330# a list of builtin themes.
331
332# Default theme
333html_theme = "alabaster"
334html_css_files = []
335
336if "DOCS_THEME" in os.environ:
337    html_theme = os.environ["DOCS_THEME"]
338
339if html_theme in ["sphinx_rtd_theme", "sphinx_rtd_dark_mode"]:
340    # Read the Docs theme
341    try:
342        import sphinx_rtd_theme
343
344        html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
345
346        # Add any paths that contain custom static files (such as style sheets) here,
347        # relative to this directory. They are copied after the builtin static files,
348        # so a file named "default.css" will overwrite the builtin "default.css".
349        html_css_files = [
350            "theme_overrides.css",
351        ]
352
353        # Read the Docs dark mode override theme
354        if html_theme == "sphinx_rtd_dark_mode":
355            try:
356                import sphinx_rtd_dark_mode            # pylint: disable=W0611
357
358                extensions.append("sphinx_rtd_dark_mode")
359            except ImportError:
360                html_theme = "sphinx_rtd_theme"
361
362        if html_theme == "sphinx_rtd_theme":
363            # Add color-specific RTD normal mode
364            html_css_files.append("theme_rtd_colors.css")
365
366        html_theme_options = {
367            "navigation_depth": -1,
368        }
369
370    except ImportError:
371        html_theme = "alabaster"
372
373if "DOCS_CSS" in os.environ:
374    css = os.environ["DOCS_CSS"].split(" ")
375
376    for l in css:
377        html_css_files.append(l)
378
379if html_theme == "alabaster":
380    html_theme_options = {
381        "description": get_cline_version(),
382        "page_width": "65em",
383        "sidebar_width": "15em",
384        "fixed_sidebar": "true",
385        "font_size": "inherit",
386        "font_family": "serif",
387    }
388
389sys.stderr.write("Using %s theme\n" % html_theme)
390
391# Add any paths that contain custom static files (such as style sheets) here,
392# relative to this directory. They are copied after the builtin static files,
393# so a file named "default.css" will overwrite the builtin "default.css".
394html_static_path = ["sphinx-static"]
395
396# If true, Docutils "smart quotes" will be used to convert quotes and dashes
397# to typographically correct entities.  However, conversion of "--" to "—"
398# is not always what we want, so enable only quotes.
399smartquotes_action = "q"
400
401# Custom sidebar templates, maps document names to template names.
402# Note that the RTD theme ignores this
403html_sidebars = {"**": ["searchbox.html",
404                        "kernel-toc.html",
405                        "sourcelink.html"]}
406
407# about.html is available for alabaster theme. Add it at the front.
408if html_theme == "alabaster":
409    html_sidebars["**"].insert(0, "about.html")
410
411# The name of an image file (relative to this directory) to place at the top
412# of the sidebar.
413html_logo = "images/logo.svg"
414
415# Output file base name for HTML help builder.
416htmlhelp_basename = "TheLinuxKerneldoc"
417
418# -- Options for LaTeX output ---------------------------------------------
419
420latex_elements = {
421    # The paper size ('letterpaper' or 'a4paper').
422    "papersize": "a4paper",
423    # The font size ('10pt', '11pt' or '12pt').
424    "pointsize": "11pt",
425    # Latex figure (float) alignment
426    # 'figure_align': 'htbp',
427    # Don't mangle with UTF-8 chars
428    "inputenc": "",
429    "utf8extra": "",
430    # Set document margins
431    "sphinxsetup": """
432        hmargin=0.5in, vmargin=1in,
433        parsedliteralwraps=true,
434        verbatimhintsturnover=false,
435    """,
436    #
437    # Some of our authors are fond of deep nesting; tell latex to
438    # cope.
439    #
440    "maxlistdepth": "10",
441    # For CJK One-half spacing, need to be in front of hyperref
442    "extrapackages": r"\usepackage{setspace}",
443    # Additional stuff for the LaTeX preamble.
444    "preamble": """
445        % Use some font with UTF-8 support with XeLaTeX
446        \\usepackage{fontspec}
447        \\setsansfont{DejaVu Sans}
448        \\setromanfont{DejaVu Serif}
449        \\setmonofont{DejaVu Sans Mono}
450    """,
451}
452
453# Load kerneldoc specific LaTeX settings
454latex_elements["preamble"] += """
455        % Load kerneldoc specific LaTeX settings
456        \\input{kerneldoc-preamble.sty}
457"""
458
459# Grouping the document tree into LaTeX files. List of tuples
460# (source start file, target name, title,
461#  author, documentclass [howto, manual, or own class]).
462# Sorted in alphabetical order
463latex_documents = []
464
465# Add all other index files from Documentation/ subdirectories
466for fn in os.listdir("."):
467    doc = os.path.join(fn, "index")
468    if os.path.exists(doc + ".rst"):
469        has = False
470        for l in latex_documents:
471            if l[0] == doc:
472                has = True
473                break
474        if not has:
475            latex_documents.append(
476                (
477                    doc,
478                    fn + ".tex",
479                    "Linux %s Documentation" % fn.capitalize(),
480                    "The kernel development community",
481                    "manual",
482                )
483            )
484
485# The name of an image file (relative to this directory) to place at the top of
486# the title page.
487# latex_logo = None
488
489# For "manual" documents, if this is true, then toplevel headings are parts,
490# not chapters.
491# latex_use_parts = False
492
493# If true, show page references after internal links.
494# latex_show_pagerefs = False
495
496# If true, show URL addresses after external links.
497# latex_show_urls = False
498
499# Documents to append as an appendix to all manuals.
500# latex_appendices = []
501
502# If false, no module index is generated.
503# latex_domain_indices = True
504
505# Additional LaTeX stuff to be copied to build directory
506latex_additional_files = [
507    "sphinx/kerneldoc-preamble.sty",
508]
509
510
511# -- Options for manual page output ---------------------------------------
512
513# One entry per manual page. List of tuples
514# (source start file, name, description, authors, manual section).
515man_pages = [
516    (master_doc, "thelinuxkernel", "The Linux Kernel Documentation", [author], 1)
517]
518
519# If true, show URL addresses after external links.
520# man_show_urls = False
521
522
523# -- Options for Texinfo output -------------------------------------------
524
525# Grouping the document tree into Texinfo files. List of tuples
526# (source start file, target name, title, author,
527#  dir menu entry, description, category)
528texinfo_documents = [(
529        master_doc,
530        "TheLinuxKernel",
531        "The Linux Kernel Documentation",
532        author,
533        "TheLinuxKernel",
534        "One line description of project.",
535        "Miscellaneous",
536    ),]
537
538# -- Options for Epub output ----------------------------------------------
539
540# Bibliographic Dublin Core info.
541epub_title = project
542epub_author = author
543epub_publisher = author
544epub_copyright = copyright
545
546# A list of files that should not be packed into the epub file.
547epub_exclude_files = ["search.html"]
548
549# =======
550# rst2pdf
551#
552# Grouping the document tree into PDF files. List of tuples
553# (source start file, target name, title, author, options).
554#
555# See the Sphinx chapter of https://ralsina.me/static/manual.pdf
556#
557# FIXME: Do not add the index file here; the result will be too big. Adding
558# multiple PDF files here actually tries to get the cross-referencing right
559# *between* PDF files.
560pdf_documents = [
561    ("kernel-documentation", "Kernel", "Kernel", "J. Random Bozo"),
562]
563
564# kernel-doc extension configuration for running Sphinx directly (e.g. by Read
565# the Docs). In a normal build, these are supplied from the Makefile via command
566# line arguments.
567kerneldoc_bin = "../scripts/kernel-doc.py"
568kerneldoc_srctree = ".."
569
570# ------------------------------------------------------------------------------
571# Since loadConfig overwrites settings from the global namespace, it has to be
572# the last statement in the conf.py file
573# ------------------------------------------------------------------------------
574loadConfig(globals())
575
576
577def setup(app):
578    """Patterns need to be updated at init time on older Sphinx versions"""
579
580    app.connect('config-inited', update_patterns)
581