Building the Linux kernel with Clang and LLVM
 help / color / mirror / Atom feed
* [PATCH v7 00/24] Split sphinx call logic from docs Makefile
@ 2025-09-17 12:14 Mauro Carvalho Chehab
  2025-09-17 12:15 ` [PATCH v7 22/24] tools/docs: sphinx-build-wrapper: move rust doc builder to wrapper Mauro Carvalho Chehab
  0 siblings, 1 reply; 2+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-17 12:14 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List
  Cc: Mauro Carvalho Chehab, Mauro Carvalho Chehab, linux-kernel,
	Akira Yokosawa, Björn Roy Baron, Thomas Weißschuh,
	Alex Gaynor, Alex Shi, Alice Ryhl, Andreas Hindborg, Benno Lossin,
	Bill Wendling, Boqun Feng, Danilo Krummrich, Dongliang Mu,
	Federico Vaga, Gary Guo, Justin Stitt, Masahiro Yamada,
	Miguel Ojeda, Nathan Chancellor, Nick Desaulniers, Nicolas Schier,
	Randy Dunlap, Tamir Duberstein, Trevor Gross, Yanteng Si,
	linux-kbuild, llvm, rust-for-linux

Hi Jon,

This series should probably be called:

    "Move the trick-or-treat build hacks accumulated over time
     into a single place and document them."

as this reflects its main goal. As such:

- it places the jobserver logic on a library;
- it removes sphinx/parallel-wrapper.sh;
- the code now properly implements a jobserver-aware logic
  to do the parallelism when called via GNU make, failing back to
  "-j" when there's  no jobserver;
- converts check-variable-fonts.sh to Python and uses it via
  function call;
- drops an extra script to generate man pages, adding a makefile
  target for it;
- ensures that return code is 0 when PDF successfully builds;
- about half of the script is comments and documentation.

I tried to do my best to document all tricks that are inside the
script. This way, the docs build steps is now documented.

It should be noticed that it is out of the scope of this series
to change the implementation. Surely the process can be improved,
but first let's consolidate and document everything on a single
place.

Such script was written in a way that it can be called either
directly or via a Makefile. Running outside Makefile is
interesting specially when debug is needed. The command line
interface replaces the need of having lots of env vars before
calling sphinx-build:

    $ ./tools/docs/sphinx-build-wrapper --help
    usage: sphinx-build-wrapper [-h]
           [--sphinxdirs SPHINXDIRS [SPHINXDIRS ...]] [--conf CONF]
           [--builddir BUILDDIR] [--theme THEME] [--css CSS] [--paper {,a4,letter}] [-v]
           [-j JOBS] [-i] [-V [VENV]]
           {cleandocs,linkcheckdocs,htmldocs,epubdocs,texinfodocs,infodocs,mandocs,latexdocs,pdfdocs,xmldocs}

    Kernel documentation builder

    positional arguments:
      {cleandocs,linkcheckdocs,htmldocs,epubdocs,texinfodocs,infodocs,mandocs,latexdocs,pdfdocs,xmldocs}
                            Documentation target to build

    options:
      -h, --help            show this help message and exit
      --sphinxdirs SPHINXDIRS [SPHINXDIRS ...]
                            Specific directories to build
      --conf CONF           Sphinx configuration file
      --builddir BUILDDIR   Sphinx configuration file
      --theme THEME         Sphinx theme to use
      --css CSS             Custom CSS file for HTML/EPUB
      --paper {,a4,letter}  Paper size for LaTeX/PDF output
      -v, --verbose         place build in verbose mode
      -j, --jobs JOBS       Sets number of jobs to use with sphinx-build
      -i, --interactive     Change latex default to run in interactive mode
      -V, --venv [VENV]     If used, run Sphinx from a venv dir (default dir: sphinx_latest)

the only mandatory argument is the target, which is identical with
"make" targets.

The call inside Makefile doesn't use the last four arguments. They're
there to help identifying problems at the build:

    -v makes the output verbose;
    -j helps to test parallelism;
    -i runs latexmk in interactive mode, allowing to debug PDF
       build issues;
    -V is useful when testing it with different venvs.

When used with GNU make (or some other make which implements jobserver),
a call like:

    make -j <targets> htmldocs

will make the wrapper to automatically use POSIX jobserver to claim 
the number of available job slots, calling sphinx-build with a
"-j" parameter reflecting it. ON such case, the default can be
overriden via SPHINXDIRS argument.

Visiable changes when compared with the old behavior:

When V=0, the only visible difference is that:
- pdfdocs target now returns 0 on success, 1 on failures.
  This addresses an issue over the current process where we
  it always return success even on failures;
- it will now print the name of PDF files that failed to build,
  if any.

In verbose mode, sphinx-build-wrapper and sphinx-build command lines
are now displayed.

---

v7:
- added a --help option to ./tools/docs/check-variable-fonts.py;
- document FONTS_CONF_DENY_VF=;
- moved the python_version changes to be earlier in the series,
  before moving it to a separate library, as suggested by Jani;
- added a --rustdoc to the wrapper, cleaning up Makefile
  even further;
- solved some problems related to DENY_VF logic.

v6:
- On success, PDF output is identical as before when V=0;
- when V=1 is used, PDF output will print a build summary,
  as on v5;
- solved a problem when multiple PDF files have the same
  basename but are located on different directories;
- merged a patch series converting check-variable-fonts.sh
  to Python. Its logic is now called directly without running
  a subprocess.
- venv patch moved to the end.

v5:
- merged comments with the script;
- placed n_jobs on a separate function;
- nitpick: dropped a for loop used instead of list append.

v4:
- updated references for sphinx-pre-install after its rename;
- added some extra patches to add more options to python_version,
  allowing it to bail out and suggest alternatives;
- added a patch at the end to explicitly break doc builds when
  python3 points to python3.6 or older.

v3:
- rebased on the top of docs-next;
- added two patches to build man files that were on a separate
  patch series.

v2:
- there's no generic exception handler anymore;
- it moves sphinx-pre-install to tools/docs;
- the logic which ensures a minimal Python version got moved
  to a library, which is now used by both pre-install and wrapper;
- The first wrapper (05/13) doesn't contain comments (except for
  shebang and SPDX). The goal is to help showing the size increase
  when moving from Makefile to Python. Some file increase is
  unavoidable, as Makefile is more compact: no includes, multple
  statements per line, no argparse, etc;
- The second patch adds docstrings and comments. It has almost
  the same size of the code itself;
- I moved the venv logic to a third wrapper patch;
- I fixed an issue at the paraller build logic;
- There are no generic except blocks anymore.

Mauro Carvalho Chehab (24):
  scripts/jobserver-exec: move the code to a class
  scripts/jobserver-exec: move its class to the lib directory
  scripts/jobserver-exec: add a help message
  scripts: check-variable-fonts.sh: convert to Python
  tools/docs: check-variable-fonts.py: split into a lib and an exec file
  check-variable-fonts.py: add a helper to display instructions
  scripts: sphinx-pre-install: move it to tools/docs
  tools/docs: sphinx-pre-install: drop a debug print
  tools/docs: sphinx-pre-install: allow check for alternatives and bail
    out
  tools/docs: python_version: move version check from sphinx-pre-install
  tools/docs: sphinx-build-wrapper: add a wrapper for sphinx-build
  docs: parallel-wrapper.sh: remove script
  docs: Makefile: document latex/PDF PAPER= parameter
  docs: Makefile: document FONTS_CONF_DENY_VF= parameter
  tools/docs: sphinx-build-wrapper: add an argument for LaTeX
    interactive mode
  tools/docs: sphinx-build-wrapper: allow building PDF files in parallel
  tools/docs,scripts: sphinx-*: prevent sphinx-build crashes
  tools/docs: sphinx-build-wrapper: Fix output for duplicated names
  docs: add support to build manpages from kerneldoc output
  tools: kernel-doc: add a see also section at man pages
  scripts: kdoc_parser.py: warn about Python version only once
  tools/docs: sphinx-build-wrapper: move rust doc builder to wrapper
  tools/docs: sphinx-* break documentation bulds on openSUSE
  tools/docs: sphinx-build-wrapper: add support to run inside venv

 Documentation/Makefile                        | 144 +---
 Documentation/doc-guide/kernel-doc.rst        |  29 +-
 Documentation/doc-guide/sphinx.rst            |   4 +-
 Documentation/sphinx/kerneldoc-preamble.sty   |   2 +-
 Documentation/sphinx/parallel-wrapper.sh      |  33 -
 .../translations/it_IT/doc-guide/sphinx.rst   |   4 +-
 .../translations/zh_CN/doc-guide/sphinx.rst   |   4 +-
 Documentation/translations/zh_CN/how-to.rst   |   2 +-
 MAINTAINERS                                   |   4 +-
 Makefile                                      |   2 +-
 scripts/check-variable-fonts.sh               | 115 ---
 scripts/jobserver-exec                        |  88 +-
 scripts/lib/jobserver.py                      | 149 ++++
 scripts/lib/kdoc/kdoc_files.py                |   5 +-
 scripts/lib/kdoc/kdoc_output.py               |  84 +-
 scripts/lib/kdoc/kdoc_parser.py               |   7 +-
 scripts/split-man.pl                          |  28 -
 tools/docs/check-variable-fonts.py            |  30 +
 tools/docs/lib/latex_fonts.py                 | 166 ++++
 tools/docs/lib/python_version.py              | 178 ++++
 tools/docs/sphinx-build-wrapper               | 816 ++++++++++++++++++
 {scripts => tools/docs}/sphinx-pre-install    | 135 +--
 22 files changed, 1536 insertions(+), 493 deletions(-)
 delete mode 100644 Documentation/sphinx/parallel-wrapper.sh
 delete mode 100755 scripts/check-variable-fonts.sh
 create mode 100755 scripts/lib/jobserver.py
 delete mode 100755 scripts/split-man.pl
 create mode 100755 tools/docs/check-variable-fonts.py
 create mode 100755 tools/docs/lib/latex_fonts.py
 create mode 100644 tools/docs/lib/python_version.py
 create mode 100755 tools/docs/sphinx-build-wrapper
 rename {scripts => tools/docs}/sphinx-pre-install (93%)

-- 
2.51.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH v7 22/24] tools/docs: sphinx-build-wrapper: move rust doc builder to wrapper
  2025-09-17 12:14 [PATCH v7 00/24] Split sphinx call logic from docs Makefile Mauro Carvalho Chehab
@ 2025-09-17 12:15 ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 2+ messages in thread
From: Mauro Carvalho Chehab @ 2025-09-17 12:15 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List
  Cc: Mauro Carvalho Chehab, Akira Yokosawa, Björn Roy Baron,
	Mauro Carvalho Chehab, Alex Gaynor, Alice Ryhl, Andreas Hindborg,
	Benno Lossin, Bill Wendling, Boqun Feng, Danilo Krummrich,
	Gary Guo, Justin Stitt, Miguel Ojeda, Nathan Chancellor,
	Nick Desaulniers, Trevor Gross, linux-kernel, llvm,
	rust-for-linux

Simplify even further the docs Makefile by moving rust build logic
to the wrapper.

After this change, running make on an environment with rust enabled
works as expected.

With CONFIG_RUST:

    $ make O=/tmp/foo LLVM=1 SPHINXDIRS=peci htmldocs
    make[1]: Entrando no diretório '/tmp/foo'

    Using alabaster theme
    Using Python kernel-doc
      GEN     Makefile
      DESCEND objtool
      CC      arch/x86/kernel/asm-offsets.s
      INSTALL libsubcmd_headers
      CALL    /new_devel/docs/scripts/checksyscalls.sh
      RUSTC L rust/core.o
      BINDGEN rust/bindings/bindings_generated.rs
      BINDGEN rust/bindings/bindings_helpers_generated.rs
    ...

Without it:
    $ make SPHINXDIRS=peci htmldocs
    Using alabaster theme
    Using Python kernel-doc

Both work as it is it is supposed to do.

After the change, it is also possible to build directly with the script
by passing "--rustodoc".

if CONFIG_RUST, this works fine:

    $ ./tools/docs/sphinx-build-wrapper --sphinxdirs peci --rustdoc -- htmldocs
    Using alabaster theme
    Using Python kernel-doc
      SYNC    include/config/auto.conf
    ...
      RUSTC L rust/core.o
    ...

If not, it will produce a warning that RUST may be disabled:

    $ ./tools/docs/sphinx-build-wrapper --sphinxdirs peci --rustdoc -- htmldocs
    Using alabaster theme
    Using Python kernel-doc
    ***
    *** Configuration file ".config" not found!
    ***
    *** Please run some configurator (e.g. "make oldconfig" or
    *** "make menuconfig" or "make xconfig").
    ***
    make[1]: *** [/new_devel/docs/Makefile:829: .config] Error 1
    make: *** [Makefile:248: __sub-make] Error 2
    Ignored errors when building rustdoc: Command '['make', 'LLVM=1', 'rustdoc']' returned non-zero exit status 2.. Is RUST enabled?

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/Makefile          | 29 +++++-----------
 tools/docs/sphinx-build-wrapper | 59 ++++++++++++++++++---------------
 2 files changed, 41 insertions(+), 47 deletions(-)

diff --git a/Documentation/Makefile b/Documentation/Makefile
index aa42b2cb7030..b32f68387dfc 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -23,6 +23,7 @@ SPHINXOPTS    =
 SPHINXDIRS    = .
 DOCS_THEME    =
 DOCS_CSS      =
+RUSTDOC       =
 SPHINX_CONF   = conf.py
 PAPER         =
 BUILDDIR      = $(obj)/output
@@ -42,6 +43,10 @@ FONTS_CONF_DENY_VF ?= $(HOME)/deny-vf
 # User-friendly check for sphinx-build
 HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
 
+ifeq ($(CONFIG_RUST),y)
+	RUSTDOC="--rustdoc"
+endif
+
 ifeq ($(HAVE_SPHINX),0)
 
 .DEFAULT:
@@ -53,10 +58,10 @@ ifeq ($(HAVE_SPHINX),0)
 else # HAVE_SPHINX
 
 # Common documentation targets
-mandocs infodocs texinfodocs latexdocs epubdocs xmldocs pdfdocs linkcheckdocs:
+htmldocs mandocs infodocs texinfodocs latexdocs epubdocs xmldocs pdfdocs linkcheckdocs:
 	$(Q)@$(srctree)/tools/docs/sphinx-pre-install --version-check
-	+$(Q)$(PYTHON3) $(BUILD_WRAPPER) $@ \
-		--sphinxdirs="$(SPHINXDIRS)" --conf="$(SPHINX_CONF)" \
+	+$(Q)$(PYTHON3) $(BUILD_WRAPPER) $@ $(RUSTDOC)\
+		--sphinxdirs="$(SPHINXDIRS)" --conf="$(SPHINX_CONF)" $(RUSTDOC)\
 		--builddir="$(BUILDDIR)" --deny-vf=$(FONTS_CONF_DENY_VF) \
 		--theme=$(DOCS_THEME) --css=$(DOCS_CSS) --paper=$(PAPER)
 
@@ -67,24 +72,6 @@ pdfdocs:
 	@echo "  SKIP    Sphinx $@ target."
 endif
 
-# HTML main logic is identical to other targets. However, if rust is enabled,
-# an extra step at the end is required to generate rustdoc.
-htmldocs:
-	$(Q)@$(srctree)/tools/docs/sphinx-pre-install --version-check
-	+$(Q)$(PYTHON3) $(BUILD_WRAPPER) $@ \
-		--sphinxdirs="$(SPHINXDIRS)" --conf="$(SPHINX_CONF)" \
-		--builddir="$(BUILDDIR)" \
-		--theme=$(DOCS_THEME) --css=$(DOCS_CSS) --paper=$(PAPER)
-# If Rust support is available and .config exists, add rustdoc generated contents.
-# If there are any, the errors from this make rustdoc will be displayed but
-# won't stop the execution of htmldocs
-
-ifneq ($(wildcard $(srctree)/.config),)
-ifeq ($(CONFIG_RUST),y)
-	$(Q)$(MAKE) rustdoc || true
-endif
-endif
-
 endif # HAVE_SPHINX
 
 # The following targets are independent of HAVE_SPHINX, and the rules should
diff --git a/tools/docs/sphinx-build-wrapper b/tools/docs/sphinx-build-wrapper
index 7a6eb41837e6..e24486dede76 100755
--- a/tools/docs/sphinx-build-wrapper
+++ b/tools/docs/sphinx-build-wrapper
@@ -96,14 +96,6 @@ class SphinxBuilder:
     with the Kernel.
     """
 
-    def is_rust_enabled(self):
-        """Check if rust is enabled at .config"""
-        config_path = os.path.join(self.srctree, ".config")
-        if os.path.isfile(config_path):
-            with open(config_path, "r", encoding="utf-8") as f:
-                return "CONFIG_RUST=y" in f.read()
-        return False
-
     def get_path(self, path, use_cwd=False, abs_path=False):
         """
         Ancillary routine to handle patches the right way, as shell does.
@@ -218,8 +210,6 @@ class SphinxBuilder:
                                                       "scripts/kernel-doc.py"))
         self.builddir = self.get_path(builddir, use_cwd=True, abs_path=True)
 
-        self.config_rust = self.is_rust_enabled()
-
         #
         # Get directory locations for LaTeX build toolchain
         #
@@ -274,7 +264,7 @@ class SphinxBuilder:
 
             return subprocess.call(cmd, *args, **pwargs)
 
-    def handle_html(self, css, output_dir):
+    def handle_html(self, css, output_dir, rustdoc):
         """
         Extra steps for HTML and epub output.
 
@@ -282,20 +272,34 @@ class SphinxBuilder:
         copied to the output _static directory
         """
 
-        if not css:
-            return
+        if css:
+            css = os.path.expanduser(css)
+            if not css.startswith("/"):
+                css = os.path.join(self.srctree, css)
 
-        css = os.path.expanduser(css)
-        if not css.startswith("/"):
-            css = os.path.join(self.srctree, css)
+            static_dir = os.path.join(output_dir, "_static")
+            os.makedirs(static_dir, exist_ok=True)
 
-        static_dir = os.path.join(output_dir, "_static")
-        os.makedirs(static_dir, exist_ok=True)
+            try:
+                shutil.copy2(css, static_dir)
+            except (OSError, IOError) as e:
+                print(f"Warning: Failed to copy CSS: {e}", file=sys.stderr)
 
-        try:
-            shutil.copy2(css, static_dir)
-        except (OSError, IOError) as e:
-            print(f"Warning: Failed to copy CSS: {e}", file=sys.stderr)
+        if rustdoc:
+            if "MAKE" in self.env:
+                cmd = [self.env["MAKE"]]
+            else:
+                cmd = ["make", "LLVM=1"]
+
+            cmd += [ "rustdoc"]
+            if self.verbose:
+                print(" ".join(cmd))
+
+            try:
+                subprocess.run(cmd, check=True)
+            except subprocess.CalledProcessError as e:
+                print(f"Ignored errors when building rustdoc: {e}. Is RUST enabled?",
+                      file=sys.stderr)
 
     def build_pdf_file(self, latex_cmd, from_dir, path):
         """Builds a single pdf file using latex_cmd"""
@@ -576,7 +580,7 @@ class SphinxBuilder:
         shutil.rmtree(self.builddir, ignore_errors=True)
 
     def build(self, target, sphinxdirs=None, conf="conf.py",
-              theme=None, css=None, paper=None, deny_vf=None):
+              theme=None, css=None, paper=None, deny_vf=None, rustdoc=False):
         """
         Build documentation using Sphinx. This is the core function of this
         module. It prepares all arguments required by sphinx-build.
@@ -623,7 +627,7 @@ class SphinxBuilder:
 
             args.extend(["-D", f"latex_elements.papersize={paper}paper"])
 
-        if self.config_rust:
+        if rustdoc:
             args.extend(["-t", "rustdoc"])
 
         if conf:
@@ -699,7 +703,7 @@ class SphinxBuilder:
             # Ensure that each html/epub output will have needed static files
             #
             if target in ["htmldocs", "epubdocs"]:
-                self.handle_html(css, output_dir)
+                self.handle_html(css, output_dir, rustdoc)
 
         #
         # Step 2: Some targets (PDF and info) require an extra step once
@@ -756,6 +760,9 @@ def main():
     parser.add_argument('--deny-vf',
                         help="Configuration to deny variable fonts on pdf builds")
 
+    parser.add_argument('--rustdoc', action="store_true",
+                        help="Enable rustdoc build. Requires CONFIG_RUST")
+
     parser.add_argument("-v", "--verbose", action='store_true',
                         help="place build in verbose mode")
 
@@ -775,7 +782,7 @@ def main():
 
     builder.build(args.target, sphinxdirs=args.sphinxdirs, conf=args.conf,
                   theme=args.theme, css=args.css, paper=args.paper,
-                  deny_vf=args.deny_vf)
+                  rustdoc=args.rustdoc, deny_vf=args.deny_vf)
 
 if __name__ == "__main__":
     main()
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-09-17 12:15 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-17 12:14 [PATCH v7 00/24] Split sphinx call logic from docs Makefile Mauro Carvalho Chehab
2025-09-17 12:15 ` [PATCH v7 22/24] tools/docs: sphinx-build-wrapper: move rust doc builder to wrapper Mauro Carvalho Chehab

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox