[PATCH v8 00/24] Split sphinx call logic from docs Makefile

Mauro Carvalho Chehab posted 24 patches 1 week, 6 days ago
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            |  33 +
tools/docs/lib/latex_fonts.py                 | 167 ++++
tools/docs/lib/python_version.py              | 178 ++++
tools/docs/sphinx-build-wrapper               | 816 ++++++++++++++++++
{scripts => tools/docs}/sphinx-pre-install    | 135 +--
22 files changed, 1540 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%)
[PATCH v8 00/24] Split sphinx call logic from docs Makefile
Posted by Mauro Carvalho Chehab 1 week, 6 days ago
Hi Jon,

v8 contains a bug fix for ./tools/docs/check-variable-fonts.py command
line together with a new --deny-vf argument to it, plus addresses
a couple checkpatch warnings. Only 4 patches changed: patches 1, 2, 4
and 5.

-

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.

---

v8:
- fixed a typo at check-variable-fonts.py libary causing the
  command line to not work properly;
- added a --deny-vf command line arg for check-variable-fonts.py;
- fixed two checkpatch warnings (duplicated "allows" word on
  a patch description, and "childs" instead of "children).

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            |  33 +
 tools/docs/lib/latex_fonts.py                 | 167 ++++
 tools/docs/lib/python_version.py              | 178 ++++
 tools/docs/sphinx-build-wrapper               | 816 ++++++++++++++++++
 {scripts => tools/docs}/sphinx-pre-install    | 135 +--
 22 files changed, 1540 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
Re: [PATCH v8 00/24] Split sphinx call logic from docs Makefile
Posted by Jonathan Corbet 1 week, 6 days ago
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:

> Hi Jon,
>
> v8 contains a bug fix for ./tools/docs/check-variable-fonts.py command
> line together with a new --deny-vf argument to it, plus addresses
> a couple checkpatch warnings. Only 4 patches changed: patches 1, 2, 4
> and 5.

OK.  I have applied this to a branch called build-script in my tree.
Applying it to current docs-mw (or docs-next) was a bit of a challenge,
due to merge conflicts with the makefiles, but I got there.

This work is now merged in docs-next (and will thus show in linux-next),
but it's not yet in docs-mw, so we're not committed to putting it into
6.18.  My current thinking, if all goes well, is to shift it to docs-mw
just after the merge window.

It all seems to work for me, with one little oddity: the "Indices"
section in Documentation/rust/index.rst (which is protected by the usual
".. only::" block) is being included in the htmldocs build, leading to a
spurious "Indices" entry in the left column.  Something about the way
the rust directory is being build sets "subproject" maybe?  I haven't
had the time to figure it out.

Thanks,

jon
Re: [PATCH v8 00/24] Split sphinx call logic from docs Makefile
Posted by Mauro Carvalho Chehab 1 week, 6 days ago
Em Thu, 18 Sep 2025 11:47:59 -0600
Jonathan Corbet <corbet@lwn.net> escreveu:

> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
> 
> > Hi Jon,
> >
> > v8 contains a bug fix for ./tools/docs/check-variable-fonts.py command
> > line together with a new --deny-vf argument to it, plus addresses
> > a couple checkpatch warnings. Only 4 patches changed: patches 1, 2, 4
> > and 5.  
> 
> OK.  I have applied this to a branch called build-script in my tree.

Thanks!

> Applying it to current docs-mw (or docs-next) was a bit of a challenge,
> due to merge conflicts with the makefiles, but I got there.
> 
> This work is now merged in docs-next (and will thus show in linux-next),
> but it's not yet in docs-mw, so we're not committed to putting it into
> 6.18.  My current thinking, if all goes well, is to shift it to docs-mw
> just after the merge window.

Sounds like a plan.

> It all seems to work for me, with one little oddity: the "Indices"
> section in Documentation/rust/index.rst (which is protected by the usual
> ".. only::" block) is being included in the htmldocs build, leading to a
> spurious "Indices" entry in the left column.  Something about the way
> the rust directory is being build sets "subproject" maybe?  

The only differences with rust is that:

1) it calls sphinx-build with:

       if rustdoc:
            args.extend(["-t", "rustdoc"])
	
   where -t is:

	  --tag, -t TAG         define tag: include "only" blocks with TAG

2) it calls rust makefile at the end of the build with:

        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)

Both are there to mimic the original behavior, but maybe we need to
use cwd=<some_dir> to simulate the exact makefile behavior (although,
on my tests, not setting it seems to be the right choice, due
to O=build_dir).

> I haven't
> had the time to figure it out.

I don't remember anymore what "subproject" really means inside
".. only::", block, but I guess it is meant to be used when one
passes SPHINXDIRS.

Anyway, if I have to guess, I would try commenting out the "-t"
logic and see how it affects the output. If nobody steps up, I'll
try to do it probably next week, as I'm a little busy tomorrow.

Thanks,
Mauro
Re: [PATCH v8 00/24] Split sphinx call logic from docs Makefile
Posted by Jonathan Corbet 1 week, 6 days ago
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:

>> I haven't
>> had the time to figure it out.
>
> I don't remember anymore what "subproject" really means inside
> ".. only::", block, but I guess it is meant to be used when one
> passes SPHINXDIRS.

I found myself in a similar position...  it is set in
Documentation/sphinx/load_config.py, it seems a certain Mauro added that
in 2019 :)  Since then, it has seemingly been cargo-culted all over the
place; I wonder if we really need it.

jo
Re: [PATCH v8 00/24] Split sphinx call logic from docs Makefile
Posted by Mauro Carvalho Chehab 1 week, 6 days ago
Em Thu, 18 Sep 2025 13:33:53 -0600
Jonathan Corbet <corbet@lwn.net> escreveu:

> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
> 
> >> I haven't
> >> had the time to figure it out.  
> >
> > I don't remember anymore what "subproject" really means inside
> > ".. only::", block, but I guess it is meant to be used when one
> > passes SPHINXDIRS.  
> 
> I found myself in a similar position...  it is set in
> Documentation/sphinx/load_config.py, it seems a certain Mauro added that
> in 2019 :) 

LOL!

> Since then, it has seemingly been cargo-culted all over the
> place; I wonder if we really need it.

It looks to me that it have been ages since last touched load_config.py,
as it is hard to remember about its dirty secrets.... Maybe it is part
of some traumatic experiences that we shared ;-)

Anyway, looking at:
	a84d9e899683 ("docs: load_config.py: avoid needing a conf.py just due to LaTeX docs")

and seeking for what we had before, you might noticed that, in the
early days, someone called Jonathan wrote patches for instance, adding
core-api docs, including this one:
	
	commit 22917b992d3713157e759f23a5a090687d004331
	Author: Jonathan Corbet <corbet@lwn.net>
	Date:   Wed Nov 16 16:07:02 2016 -0700

	    docs: Add more manuals to the PDF build
    
	    There were a few manuals that weren't being built in PDF format, but
	    there's no reason not to...
    
	    Signed-off-by: Jonathan Corbet <corbet@lwn.net>

	diff --git a/Documentation/core-api/conf.py b/Documentation/core-api/conf.py
	index fed87ab7f486..db1f7659f3da 100644
	--- a/Documentation/core-api/conf.py
	+++ b/Documentation/core-api/conf.py
	@@ -3,3 +3,8 @@
	 project = "Core-API Documentation"
 
	 tags.add("subproject")
	+
	+latex_documents = [
	+    ('index', 'core-api.tex', project,
	+     'The kernel development community', 'manual'),
	+]

there you can see that our mistic "subproject" tag was already present :-D

What happens is that, before a84d9e899683, for every single book we
wanted to build via SPHINXDIRS, a conf.py file was required. 

The actual logic is a way more complex than that, but what it does is
similar to (untested):

    #
    # namespace comes from conf.py: loadConfig(globals())
    #
    def loadConfig(namespace):
	if os.path.basename(os.getcwd()) != "Documentation":
		config = namespace.copy()
	        config['tags'].add("subproject")
	        namespace.update(config)

(it also has some logic there for latex_documents)

On other words:

- subproject exists only on Documentation subdirs. It is basically
  used to tell *.rst files that SPHINXDIRS=<subdirs>

- its goal is to run genindex when SPHINXDIRS is used to build
  html documentation.

And that explains why when rust is built, it has a duplicated indexes:
neither the current docs Makefile nor sphinx-build-wrapper should be
manually adding "-t subproject".

-

That's said, as part of our doc build cleanups, IMHO we should add on
our todo to drop load_config.py, adding the missing bits on conf.py
while properly documenting it.

Thanks,
Mauro