Re: [PATCH v2 3/5] docs: sphinx-build-wrapper: prefer gmake

From: Chen Miao

Date: Tue Aug 11 2026 - 09:09:06 EST


Mauro Carvalho Chehab <mchehab+huawei@xxxxxxxxxx> 于2026年8月11日周二 12:51写道:
>
> On Mon, 10 Aug 2026 22:33:07 +0800
> Chen Miao <chenmiao.ku@xxxxxxxxx> wrote:
>
> > Homebrew installs GNU Make as gmake on macOS, but the Sphinx build
> > wrapper invokes make directly when generating Info and Rust
> > documentation. This can make the dependency check succeed while those
> > documentation targets still use an incompatible make implementation.
> >
> > Honor MAKE when it names a compatible GNU Make. Otherwise check gmake
> > and then make, selecting the first GNU Make 4.0 or newer. This keeps the
> > wrapper's selection consistent with sphinx-pre-install.
> >
> > Signed-off-by: Chen Miao <chenmiao.ku@xxxxxxxxx>
> > ---
> > tools/docs/sphinx-build-wrapper | 55 ++++++++++++++++++++++++++++-----
> > 1 file changed, 48 insertions(+), 7 deletions(-)
> >
> > diff --git a/tools/docs/sphinx-build-wrapper b/tools/docs/sphinx-build-wrapper
> > index 1bb962202..aa6a297db 100755
> > --- a/tools/docs/sphinx-build-wrapper
> > +++ b/tools/docs/sphinx-build-wrapper
> > @@ -71,6 +71,7 @@ from jobserver import JobserverExec # pylint: disable=C0413,C0411,E0401
> > #
> > VENV_DEFAULT = "sphinx_latest"
> > MIN_PYTHON_VERSION = PythonVersion("3.7").version
> > +MIN_MAKE_VERSION = PythonVersion("4.0").version
> > PAPER = ["", "a4", "letter"]
> >
> > TARGETS = {
> > @@ -97,6 +98,46 @@ class SphinxBuilder:
> > with the Kernel.
> > """
> >
> > + @staticmethod
> > + def get_make_version(cmd):
> > + """Return the GNU Make version, or None for another make."""
> > + if not cmd:
> > + return None
> > +
> > + try:
> > + result = subprocess.run(
> > + [cmd, "--version"],
> > + stdout=subprocess.PIPE,
> > + stderr=subprocess.PIPE,
> > + text=True,
> > + check=True,
> > + )
> > + except (OSError, subprocess.CalledProcessError):
> > + return None
> > +
> > + match = re.search(
> > + r"^GNU Make\s+([0-9]+(?:\.[0-9]+)*)", result.stdout, re.MULTILINE
> > + )
> > + if not match:
> > + return None
> > +
> > + return PythonVersion.parse_version(match.group(1))
> > +
> > + def get_make(self):
> > + """Select the first GNU Make 4.0 or newer in preference order."""
> > + candidates = [
> > + self.env.get("MAKE"),
> > + shutil.which("gmake"),
> > + shutil.which("make"),
> > + ]
> > +
> > + for cmd in candidates:
> > + version = self.get_make_version(cmd)
> > + if version and version >= MIN_MAKE_VERSION:
> > + return cmd
> > +
> > + sys.exit("GNU Make 4.0 or newer is required")
> > +
>
> As the code here seems to be duplicated, please add it on a library
> to be used by both scripts, as this makes easier to maintain it.
>
> The doc tools libraries are located under tools/lib/python/kdoc.
>
> Both scripts are already prepared to use it. For instance:
>
> from kdoc.python_version import PythonVersion
>
> PythonVersion belongs to a common library.
>
> As make is unrelated, please create something like:
>
> tools/lib/python/kdoc/gmake_detect.py
>
> adding the code there, and then use from/import to pick the
> needed class or method.
>
> Regards,
> Mauro
>
Indeed, sharing it in kdoc makes more sense. I'll do that in v3.

Thanks,
Chen Miao
>
> > def get_path(self, path, use_cwd=False, abs_path=False):
> > """
> > Ancillary routine to handle patches the right way, as shell does.
> > @@ -569,9 +610,10 @@ class SphinxBuilder:
> > texinfo directory.
> > """
> >
> > + make = self.get_make()
> > for output_dir in output_dirs:
> > try:
> > - subprocess.run(["make", "info"], cwd=output_dir, check=True)
> > + subprocess.run([make, "info"], cwd=output_dir, check=True)
> > except subprocess.CalledProcessError as e:
> > sys.exit(f"Error generating info docs: {e}")
> >
> > @@ -787,12 +829,11 @@ class SphinxBuilder:
> >
> > if rustdoc and target in ["htmldocs", "epubdocs"]:
> > print("Building rust docs")
> > - if "MAKE" in self.env:
> > - cmd = [self.env["MAKE"]]
> > - else:
> > - cmd = ["make", "LLVM=1"]
> > -
> > - cmd += [ "rustdoc"]
> > + make = self.get_make()
> > + cmd = [make]
> > + if make != self.env.get("MAKE"):
> > + cmd.append("LLVM=1")
> > + cmd.append("rustdoc")
> > if self.verbose:
> > print(" ".join(cmd))
> >
>
>
>
> Thanks,
> Mauro