mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

The logic there which adds a dependency note to Sphinx cache is not taking into account that the build dir may not be the source dir. This causes a performance regression: $ time make O=/tmp/foo SPHINXDIRS=admin-guide htmldocs [OUTDATED] Added: set() Changed: {'abi-obsolete', 'abi-removed', 'abi-stable-files', 'abi-obsolete-files', 'abi-stable', 'abi', 'abi-removed-files', 'abi-testing-files', 'abi-testing', 'gpio/index', 'gpio/obsolete'} Removed: set() All docs count: 385 Found docs count: 385 real 0m11,324s user 0m15,783s sys 0m1,164s To get the root cause of the problem (ABI files reported as changed), I used this changeset: diff --git a/Documentation/conf.py b/Documentation/conf.py index e8766e689c1b..ab486623bd8b 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py @@ -571,3 +571,16 @@ def setup(app): """Patterns need to be updated at init time on older Sphinx versions""" app.connect('config-inited', update_patterns) + app.connect('env-get-outdated', on_outdated) + +def on_outdated(app, env, added, changed, removed): + """Track cache outdated due to added/changed/removed files""" + print("\n[OUTDATED]") + print(f"Added: {added}") + print(f"Changed: {changed}") + print(f"Removed: {removed}") + print(f"All docs count: {len(env.all_docs)}") + print(f"Found docs count: {len(env.found_docs)}") + + # Just return what we have + return added | changed | removed Reported-by: Akira Yokosawa <akiyks@gmail.com> Closes: https://lore.kernel.org/linux-doc/c174f7c5-ec21-4eae-b1c3-f643cca90d9d@gmail.com/ Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Tested-by: Akira Yokosawa <akiyks@gmail.com> Signed-off-by: Jonathan Corbet <corbet@lwn.net> Link: https://lore.kernel.org/r/e25673d87357457bc54ee863e97ff8f75956580d.1752752211.git.mchehab+huawei@kernel.org
173 lines
5 KiB
Python
173 lines
5 KiB
Python
# -*- coding: utf-8; mode: python -*-
|
|
# coding=utf-8
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
#
|
|
"""
|
|
kernel-abi
|
|
~~~~~~~~~~
|
|
|
|
Implementation of the ``kernel-abi`` reST-directive.
|
|
|
|
:copyright: Copyright (C) 2016 Markus Heiser
|
|
:copyright: Copyright (C) 2016-2020 Mauro Carvalho Chehab
|
|
:maintained-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
:license: GPL Version 2, June 1991 see Linux/COPYING for details.
|
|
|
|
The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
|
|
scripts/get_abi.py script to parse the Kernel ABI files.
|
|
|
|
Overview of directive's argument and options.
|
|
|
|
.. code-block:: rst
|
|
|
|
.. kernel-abi:: <ABI directory location>
|
|
:debug:
|
|
|
|
The argument ``<ABI directory location>`` is required. It contains the
|
|
location of the ABI files to be parsed.
|
|
|
|
``debug``
|
|
Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
|
|
what reST is generated.
|
|
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
from docutils import nodes, statemachine
|
|
from docutils.statemachine import ViewList
|
|
from docutils.parsers.rst import directives, Directive
|
|
from sphinx.util.docutils import switch_source_input
|
|
from sphinx.util import logging
|
|
|
|
srctree = os.path.abspath(os.environ["srctree"])
|
|
sys.path.insert(0, os.path.join(srctree, "scripts/lib/abi"))
|
|
|
|
from abi_parser import AbiParser
|
|
|
|
__version__ = "1.0"
|
|
|
|
logger = logging.getLogger('kernel_abi')
|
|
path = os.path.join(srctree, "Documentation/ABI")
|
|
|
|
_kernel_abi = None
|
|
|
|
def get_kernel_abi():
|
|
"""
|
|
Initialize kernel_abi global var, if not initialized yet.
|
|
|
|
This is needed to avoid warnings during Sphinx module initialization.
|
|
"""
|
|
global _kernel_abi
|
|
|
|
if not _kernel_abi:
|
|
# Parse ABI symbols only once
|
|
_kernel_abi = AbiParser(path, logger=logger)
|
|
_kernel_abi.parse_abi()
|
|
_kernel_abi.check_issues()
|
|
|
|
return _kernel_abi
|
|
|
|
def setup(app):
|
|
|
|
app.add_directive("kernel-abi", KernelCmd)
|
|
return {
|
|
"version": __version__,
|
|
"parallel_read_safe": True,
|
|
"parallel_write_safe": True
|
|
}
|
|
|
|
|
|
class KernelCmd(Directive):
|
|
"""KernelABI (``kernel-abi``) directive"""
|
|
|
|
required_arguments = 1
|
|
optional_arguments = 3
|
|
has_content = False
|
|
final_argument_whitespace = True
|
|
parser = None
|
|
|
|
option_spec = {
|
|
"debug": directives.flag,
|
|
"no-symbols": directives.flag,
|
|
"no-files": directives.flag,
|
|
}
|
|
|
|
def run(self):
|
|
kernel_abi = get_kernel_abi()
|
|
|
|
doc = self.state.document
|
|
if not doc.settings.file_insertion_enabled:
|
|
raise self.warning("docutils: file insertion disabled")
|
|
|
|
env = self.state.document.settings.env
|
|
content = ViewList()
|
|
node = nodes.section()
|
|
|
|
abi_type = self.arguments[0]
|
|
|
|
if "no-symbols" in self.options:
|
|
show_symbols = False
|
|
else:
|
|
show_symbols = True
|
|
|
|
if "no-files" in self.options:
|
|
show_file = False
|
|
else:
|
|
show_file = True
|
|
|
|
tab_width = self.options.get('tab-width',
|
|
self.state.document.settings.tab_width)
|
|
|
|
old_f = None
|
|
n = 0
|
|
n_sym = 0
|
|
for msg, f, ln in kernel_abi.doc(show_file=show_file,
|
|
show_symbols=show_symbols,
|
|
filter_path=abi_type):
|
|
n_sym += 1
|
|
msg_list = statemachine.string2lines(msg, tab_width,
|
|
convert_whitespace=True)
|
|
if "debug" in self.options:
|
|
lines = [
|
|
"", "", ".. code-block:: rst",
|
|
" :linenos:", ""
|
|
]
|
|
for m in msg_list:
|
|
lines.append(" " + m)
|
|
else:
|
|
lines = msg_list
|
|
|
|
for line in lines:
|
|
# sphinx counts lines from 0
|
|
content.append(line, f, ln - 1)
|
|
n += 1
|
|
|
|
if f != old_f:
|
|
# Add the file to Sphinx build dependencies if the file exists
|
|
fname = os.path.join(srctree, f)
|
|
if os.path.isfile(fname):
|
|
env.note_dependency(fname)
|
|
|
|
old_f = f
|
|
|
|
# Sphinx doesn't like to parse big messages. So, let's
|
|
# add content symbol by symbol
|
|
if content:
|
|
self.do_parse(content, node)
|
|
content = ViewList()
|
|
|
|
if show_symbols and not show_file:
|
|
logger.verbose("%s ABI: %i symbols (%i ReST lines)" % (abi_type, n_sym, n))
|
|
elif not show_symbols and show_file:
|
|
logger.verbose("%s ABI: %i files (%i ReST lines)" % (abi_type, n_sym, n))
|
|
else:
|
|
logger.verbose("%s ABI: %i data (%i ReST lines)" % (abi_type, n_sym, n))
|
|
|
|
return node.children
|
|
|
|
def do_parse(self, content, node):
|
|
with switch_source_input(self.state, content):
|
|
self.state.nested_parse(content, 0, node, match_titles=1)
|