[PATCH v4 00/19] Split sphinx call logic from docs Makefile

Mauro Carvalho Chehab posted 19 patches 4 weeks ago
There is a newer version of this series
Documentation/Makefile                        | 136 +---
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                                   |   3 +-
Makefile                                      |   2 +-
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/lib/python_version.py              | 178 +++++
tools/docs/sphinx-build-wrapper               | 739 ++++++++++++++++++
{scripts => tools/docs}/sphinx-pre-install    | 135 +---
19 files changed, 1265 insertions(+), 367 deletions(-)
delete mode 100644 Documentation/sphinx/parallel-wrapper.sh
create mode 100755 scripts/lib/jobserver.py
delete mode 100755 scripts/split-man.pl
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 v4 00/19] Split sphinx call logic from docs Makefile
Posted by Mauro Carvalho Chehab 4 weeks ago
Hi Jon,

This series does a major cleanup at docs Makefile by moving the
actual doc build logic to a helper script (scripts/sphinx-build-wrapper).

Such script was written in a way that it can be called either
directly or via a makefile. When running via makefile, it will
use GNU jobserver to ensure that, when sphinx-build is
called, the number of jobs will match at most what it is
specified by the "-j" parameter.

The first 3 patches do a cleanup at scripts/jobserver-exec
and moves the actual code to a library. Such library is used
by both the jobserver-exec command line and by sphinx-build-wrappper.

The change also gets rid of parallel-wrapper.sh, whose
functions are now part of the wrapper code.

I opted to pick patches from:
   https://lore.kernel.org/linux-doc/cover.1756916565.git.mchehab+huawei@kernel.org/T/#t

re-ordering them to make more sense.

The last patch breaks doc build when Python3 < 3.7, as requested,
or when sphinx-pre-install suggests to install an updated Sphinx
version. Matteu suggested adding a PYTHON env to allow overriding it,
but this won't would work with sphinx-pre-install, which is meant to
be executed with older python versions, but still requires to run
python from the suggested package to check if package install
succeded. Currently, sphinx-pre-install recomments to install a newer
Python on 3 distribution types:

    - 3.11 on openSuse Leap;
    - 3.9 on RHEL8 and RHEL8-based distros;
    - 3.13 on openSUSE Thumbleweed.

Patch 19 breaks sphinx-pre-install for those, and adding PYTHON
env won't properly fix it. ATM, I can't think on a good non-hacky
solution, as the only way I can think is to let sphinx-pre-install
(and sphinx-build-wrapper) execute python3.x instead of python3.

---

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 (19):
  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: sphinx-pre-install: move it to tools/docs
  tools/docs: python_version: move version check from sphinx-pre-install
  tools/docs: python_version: drop a debug print
  tools/docs: python_version: allow check for alternatives and bail out
  tools/docs: sphinx-build-wrapper: add a wrapper for sphinx-build
  tools/docs: sphinx-build-wrapper: add comments and blank lines
  tools/docs: sphinx-build-wrapper: add support to run inside venv
  docs: parallel-wrapper.sh: remove script
  docs: Makefile: document latex/PDF PAPER= parameter
  tools/docs: sphinx-build-wrapper: add an argument for LaTeX
    interactive mode
  tools/docs,scripts: sphinx-*: prevent sphinx-build crashes
  tools/docs: sphinx-build-wrapper: allow building PDF files in parallel
  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-* break documentation bulds on openSUSE

 Documentation/Makefile                        | 136 +---
 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                                   |   3 +-
 Makefile                                      |   2 +-
 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/lib/python_version.py              | 178 +++++
 tools/docs/sphinx-build-wrapper               | 739 ++++++++++++++++++
 {scripts => tools/docs}/sphinx-pre-install    | 135 +---
 19 files changed, 1265 insertions(+), 367 deletions(-)
 delete mode 100644 Documentation/sphinx/parallel-wrapper.sh
 create mode 100755 scripts/lib/jobserver.py
 delete mode 100755 scripts/split-man.pl
 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 v4 00/19] Split sphinx call logic from docs Makefile
Posted by Jonathan Corbet 3 weeks, 6 days ago
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:

> This series does a major cleanup at docs Makefile by moving the
> actual doc build logic to a helper script (scripts/sphinx-build-wrapper).
>
> Such script was written in a way that it can be called either
> directly or via a makefile. When running via makefile, it will
> use GNU jobserver to ensure that, when sphinx-build is
> called, the number of jobs will match at most what it is
> specified by the "-j" parameter.

I will try to make another pass over this stuff later today.  I would
really appreciate some more eyes on it, though, and perhaps even some
reports of testing.  This is a significant change, and the presence of
surprised would not be ... surprising ...

Thanks,

jon
Re: [PATCH v4 00/19] Split sphinx call logic from docs Makefile
Posted by Mauro Carvalho Chehab 3 weeks, 5 days ago
Em Fri, 05 Sep 2025 10:07:51 -0600
Jonathan Corbet <corbet@lwn.net> escreveu:

> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
> 
> > This series does a major cleanup at docs Makefile by moving the
> > actual doc build logic to a helper script (scripts/sphinx-build-wrapper).
> >
> > Such script was written in a way that it can be called either
> > directly or via a makefile. When running via makefile, it will
> > use GNU jobserver to ensure that, when sphinx-build is
> > called, the number of jobs will match at most what it is
> > specified by the "-j" parameter.  
> 
> I will try to make another pass over this stuff later today.  I would
> really appreciate some more eyes on it, though, and perhaps even some
> reports of testing.  This is a significant change, and the presence of
> surprised would not be ... surprising ...

Take your time.

Yeah, tests are very welcomed. The change itself is not significant
in the sense that we just moved a complex logic with lots of magic
from Makefile to Python (*) without changing the implementation, but 
yeah, it requires testing. From my side, I've been testing cleandocs,
htmldocs and pdfdocs for 3-4 weeks now on over ~20 different distros,
all without O=, but didn't make any burn-in test for the other targets.

I've got (and fixed) some corner cases, but I won't doubt that other
corner cases might be there.

(*) It actually solved one issue: with current implementation, at least for me,
    using V=1 doesn't show the sphinx-build command line, as this is hidden
    inside the complex makefile foreach macro:

	loop_cmd = $(echo-cmd) $(cmd_$(1)) || exit;

	quiet_cmd_sphinx = SPHINX  $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
	      cmd_sphinx = \
	       PYTHONPYCACHEPREFIX="$(PYTHONPYCACHEPREFIX)" \
	       BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(src)/$5/$(SPHINX_CONF)) \
	       $(PYTHON3) $(srctree)/scripts/jobserver-exec \
	       $(CONFIG_SHELL) $(srctree)/Documentation/sphinx/parallel-wrapper.sh \
	       $(SPHINXBUILD) \
	       -b $2 \
	       -c $(abspath $(src)) \
	       -d $(abspath $(BUILDDIR)/.doctrees/$3) \
	       -D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) \
	       $(ALLSPHINXOPTS) \
	       $(abspath $(src)/$5) \
	       $(abspath $(BUILDDIR)/$3/$4) && \
	       if [ "x$(DOCS_CSS)" != "x" ]; then \
	               cp $(if $(patsubst /%,,$(DOCS_CSS)),$(abspath $(srctree)/$(DOCS_CSS)),$(DOCS_CSS)) $(BUILDDIR)/$3/_static/; \
	       fi

	htmldocs:
	...
	       @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))

    IMHO, this is problematic, as it makes harder to debug corner
    cases. While doing this changeset, I actually had to add an echo
    line to show the command line, to ensure that sphinx-build was
    called with the same arguments.

    On a side note, the above macro is complex and hard to maintain.

    One of the reasons why the Python script is bigger is that it
    has one statement per line instead of trying to do lots of
    calls inside a single statement like above (there, cmd_sphinx
    has 8 function calls; htmldocs foreach line has 3).

    The core of cmd_sphinx grew from 14 LOC on Makefile to 64 lines
    in Python, not counting:

	- comments
	- CSS logic
	- path handling logic
	- jobserver logic (in Makefile, this is a single "+" character,
  	  at the foreach line)

    I remember I had to touch on the foreach/call logic there a couple
    of times in the past. It is not the easiest thing to do.

Thanks,
Mauro