docs: add support to build manpages from kerneldoc output

Generating man files currently requires running a separate
script. The target also doesn't appear at the docs Makefile.

Add support for mandocs at the Makefile, adding the build
logic inside sphinx-build-wrapper, updating documentation
and dropping the ancillary script.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Message-ID: <3d248d724e7f3154f6e3a227e5923d7360201de9.1758196090.git.mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
This commit is contained in:
Mauro Carvalho Chehab
2025-09-18 13:54:53 +02:00
committed by Jonathan Corbet
parent 0d9abc7627
commit 7e8a8143ec
5 changed files with 98 additions and 50 deletions

View File

@@ -53,7 +53,7 @@ ifeq ($(HAVE_SPHINX),0)
else # HAVE_SPHINX else # HAVE_SPHINX
# Common documentation targets # Common documentation targets
infodocs texinfodocs latexdocs epubdocs xmldocs pdfdocs linkcheckdocs: mandocs infodocs texinfodocs latexdocs epubdocs xmldocs pdfdocs linkcheckdocs:
$(Q)@$(srctree)/tools/docs/sphinx-pre-install --version-check $(Q)@$(srctree)/tools/docs/sphinx-pre-install --version-check
+$(Q)$(PYTHON3) $(BUILD_WRAPPER) $@ \ +$(Q)$(PYTHON3) $(BUILD_WRAPPER) $@ \
--sphinxdirs="$(SPHINXDIRS)" --conf="$(SPHINX_CONF)" \ --sphinxdirs="$(SPHINXDIRS)" --conf="$(SPHINX_CONF)" \
@@ -108,6 +108,7 @@ dochelp:
@echo ' htmldocs-redirects - generate HTML redirects for moved pages' @echo ' htmldocs-redirects - generate HTML redirects for moved pages'
@echo ' texinfodocs - Texinfo' @echo ' texinfodocs - Texinfo'
@echo ' infodocs - Info' @echo ' infodocs - Info'
@echo ' mandocs - Man pages'
@echo ' latexdocs - LaTeX' @echo ' latexdocs - LaTeX'
@echo ' pdfdocs - PDF' @echo ' pdfdocs - PDF'
@echo ' epubdocs - EPUB' @echo ' epubdocs - EPUB'

View File

@@ -579,20 +579,23 @@ source.
How to use kernel-doc to generate man pages How to use kernel-doc to generate man pages
------------------------------------------- -------------------------------------------
If you just want to use kernel-doc to generate man pages you can do this To generate man pages for all files that contain kernel-doc markups, run::
from the kernel git tree::
$ scripts/kernel-doc -man \ $ make mandocs
$(git grep -l '/\*\*' -- :^Documentation :^tools) \
| scripts/split-man.pl /tmp/man
Some older versions of git do not support some of the variants of syntax for Or calling ``script-build-wrapper`` directly::
path exclusion. One of the following commands may work for those versions::
$ scripts/kernel-doc -man \ $ ./tools/docs/sphinx-build-wrapper mandocs
$(git grep -l '/\*\*' -- . ':!Documentation' ':!tools') \
| scripts/split-man.pl /tmp/man
$ scripts/kernel-doc -man \ The output will be at ``/man`` directory inside the output directory
$(git grep -l '/\*\*' -- . ":(exclude)Documentation" ":(exclude)tools") \ (by default: ``Documentation/output``).
| scripts/split-man.pl /tmp/man
Optionally, it is possible to generate a partial set of man pages by
using SPHINXDIRS:
$ make SPHINXDIRS=driver-api/media mandocs
.. note::
When SPHINXDIRS={subdir} is used, it will only generate man pages for
the files explicitly inside a ``Documentation/{subdir}/.../*.rst`` file.

View File

@@ -1799,9 +1799,10 @@ $(help-board-dirs): help-%:
# Documentation targets # Documentation targets
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs htmldocs-redirects \ DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \
epubdocs cleandocs linkcheckdocs dochelp refcheckdocs \ linkcheckdocs dochelp refcheckdocs texinfodocs infodocs mandocs \
texinfodocs infodocs htmldocs-redirects
PHONY += $(DOC_TARGETS) PHONY += $(DOC_TARGETS)
$(DOC_TARGETS): $(DOC_TARGETS):
$(Q)$(MAKE) $(build)=Documentation $@ $(Q)$(MAKE) $(build)=Documentation $@

View File

@@ -1,28 +0,0 @@
#!/usr/bin/env perl
# SPDX-License-Identifier: GPL-2.0
#
# Author: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
#
# Produce manpages from kernel-doc.
# See Documentation/doc-guide/kernel-doc.rst for instructions
if ($#ARGV < 0) {
die "where do I put the results?\n";
}
mkdir $ARGV[0],0777;
$state = 0;
while (<STDIN>) {
if (/^\.TH \"[^\"]*\" 9 \"([^\"]*)\"/) {
if ($state == 1) { close OUT }
$state = 1;
$fn = "$ARGV[0]/$1.9";
print STDERR "Creating $fn\n";
open OUT, ">$fn" or die "can't open $fn: $!\n";
print OUT $_;
} elsif ($state != 0) {
print OUT $_;
}
}
close OUT;

View File

@@ -47,12 +47,14 @@ the newer version.
import argparse import argparse
import locale import locale
import os import os
import re
import shlex import shlex
import shutil import shutil
import subprocess import subprocess
import sys import sys
from concurrent import futures from concurrent import futures
from glob import glob
from lib.python_version import PythonVersion from lib.python_version import PythonVersion
from lib.latex_fonts import LatexFontChecker from lib.latex_fonts import LatexFontChecker
@@ -77,6 +79,7 @@ TARGETS = {
"epubdocs": { "builder": "epub", "out_dir": "epub" }, "epubdocs": { "builder": "epub", "out_dir": "epub" },
"texinfodocs": { "builder": "texinfo", "out_dir": "texinfo" }, "texinfodocs": { "builder": "texinfo", "out_dir": "texinfo" },
"infodocs": { "builder": "texinfo", "out_dir": "texinfo" }, "infodocs": { "builder": "texinfo", "out_dir": "texinfo" },
"mandocs": { "builder": "man", "out_dir": "man" },
"latexdocs": { "builder": "latex", "out_dir": "latex" }, "latexdocs": { "builder": "latex", "out_dir": "latex" },
"pdfdocs": { "builder": "latex", "out_dir": "latex" }, "pdfdocs": { "builder": "latex", "out_dir": "latex" },
"xmldocs": { "builder": "xml", "out_dir": "xml" }, "xmldocs": { "builder": "xml", "out_dir": "xml" },
@@ -503,6 +506,71 @@ class SphinxBuilder:
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
sys.exit(f"Error generating info docs: {e}") sys.exit(f"Error generating info docs: {e}")
def handle_man(self, kerneldoc, docs_dir, src_dir, output_dir):
"""
Create man pages from kernel-doc output
"""
re_kernel_doc = re.compile(r"^\.\.\s+kernel-doc::\s*(\S+)")
re_man = re.compile(r'^\.TH "[^"]*" (\d+) "([^"]*)"')
if docs_dir == src_dir:
#
# Pick the entire set of kernel-doc markups from the entire tree
#
kdoc_files = set([self.srctree])
else:
kdoc_files = set()
for fname in glob(os.path.join(src_dir, "**"), recursive=True):
if os.path.isfile(fname) and fname.endswith(".rst"):
with open(fname, "r", encoding="utf-8") as in_fp:
data = in_fp.read()
for line in data.split("\n"):
match = re_kernel_doc.match(line)
if match:
if os.path.isfile(match.group(1)):
kdoc_files.add(match.group(1))
if not kdoc_files:
sys.exit(f"Directory {src_dir} doesn't contain kernel-doc tags")
cmd = [ kerneldoc, "-m" ] + sorted(kdoc_files)
try:
if self.verbose:
print(" ".join(cmd))
result = subprocess.run(cmd, stdout=subprocess.PIPE, text= True)
if result.returncode:
print(f"Warning: kernel-doc returned {result.returncode} warnings")
except (OSError, ValueError, subprocess.SubprocessError) as e:
sys.exit(f"Failed to create man pages for {src_dir}: {repr(e)}")
fp = None
try:
for line in result.stdout.split("\n"):
match = re_man.match(line)
if not match:
if fp:
fp.write(line + '\n')
continue
if fp:
fp.close()
fname = f"{output_dir}/{match.group(2)}.{match.group(1)}"
if self.verbose:
print(f"Creating {fname}")
fp = open(fname, "w", encoding="utf-8")
fp.write(line + '\n')
finally:
if fp:
fp.close()
def cleandocs(self, builder): # pylint: disable=W0613 def cleandocs(self, builder): # pylint: disable=W0613
"""Remove documentation output directory""" """Remove documentation output directory"""
shutil.rmtree(self.builddir, ignore_errors=True) shutil.rmtree(self.builddir, ignore_errors=True)
@@ -531,7 +599,7 @@ class SphinxBuilder:
# Other targets require sphinx-build, so check if it exists # Other targets require sphinx-build, so check if it exists
# #
sphinxbuild = shutil.which(self.sphinxbuild, path=self.env["PATH"]) sphinxbuild = shutil.which(self.sphinxbuild, path=self.env["PATH"])
if not sphinxbuild: if not sphinxbuild and target != "mandocs":
sys.exit(f"Error: {self.sphinxbuild} not found in PATH.\n") sys.exit(f"Error: {self.sphinxbuild} not found in PATH.\n")
if builder == "latex": if builder == "latex":
@@ -619,10 +687,13 @@ class SphinxBuilder:
output_dir, output_dir,
] ]
try: if target == "mandocs":
self.run_sphinx(sphinxbuild, build_args, env=self.env) self.handle_man(kerneldoc, docs_dir, src_dir, output_dir)
except (OSError, ValueError, subprocess.SubprocessError) as e: else:
sys.exit(f"Build failed: {repr(e)}") try:
self.run_sphinx(sphinxbuild, build_args, env=self.env)
except (OSError, ValueError, subprocess.SubprocessError) as e:
sys.exit(f"Build failed: {repr(e)}")
# #
# Ensure that each html/epub output will have needed static files # Ensure that each html/epub output will have needed static files