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