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