On 11/6/26 09:19, Ahmed S. Darwish wrote: > Introduce a kernel configuration checker. > > Validate the passed kernel .config against a YAML rules file and report > problematic configuration issues by severity. > > For correctness, readability, and long-term maintainability, type-annotate > all the Python code and split the tool's logic into a clean set of classes. > > Create a proper Python objects data model for the kconfig checker to work > with. Confine all direct YAML dictionary access to YAML files loading, > validation, and data model construction. > > Document the tool's development rules on top. > > Signed-off-by: Ahmed S. Darwish > --- > tools/kconfig-checker/check.py | 558 +++++++++++++++++++++++++++++++++ > 1 file changed, 558 insertions(+) > create mode 100755 tools/kconfig-checker/check.py > > diff --git a/tools/kconfig-checker/check.py b/tools/kconfig-checker/check.py > new file mode 100755 > index 000000000000..476cd13e59eb > --- /dev/null > +++ b/tools/kconfig-checker/check.py > @@ -0,0 +1,558 @@ > +#!/usr/bin/env python3 > +# > +# SPDX-License-Identifier: GPL-2.0-only > +# > +# Kernel .config checker > +# > +# Main usage: > +# > +# $ check.py list-rules > +# $ check.py check -c path/to/linux/.config -r preempt_rt > +# > +# Notes: > +# > +# - All code is to be fully type-annotated. Before introducing changes, > +# please verify type-safety using: > +# > +# $ mypy --strict --no-warn-return-any check.py > +# > +# - The minimum required Python version must not be newer than what is > +# required by the kernel build at Documentation/process/changes.rst. > +# > +# - The tool must not depend on being run inside the kernel source tree. > +# This simplifies invocation, testing and possible future packaging. > +# > +# - The YAML rule files are only treated as a serialization format. After > +# loading and schema validation, such rules are parsed into an internal > +# data model: Severity, Rule, SymbolRule, PatternRule, Rules, and other > +# related python objects. > +# > +# All checker logic must operate on that typed model, and not on the raw > +# YAML dictionaries. > +# > +# - Minimize external dependencies: this tool is also intended to be run > +# from distribution kernel-package scripts in the future. > +# > +# Script exit codes: > +# > +# os.EX_CONFIG passed kernel .config does not match rules > +# os.EX_NOINPUT input file(s) could not be opened > +# os.EX_DATAERR YAML/schema/rule data is malformed > +# os.EX_UNAVAILABLE Python version or dependency is unavailable > +# > + > +from __future__ import annotations > + > +import argparse > +import os > +import re > +import sys > +import textwrap > + > +from dataclasses import dataclass > +from enum import Enum, auto > +from pathlib import Path > +from typing import Any, NoReturn, Optional > + > +# > +# Initial sanity checks: > +# > + > +def error(message: str, code: int) -> NoReturn: > + print(f'Error: {message}', file=sys.stderr) > + sys.exit(code) > + > +if sys.version_info < (3, 9): > + error('Python 3.9 or later is required', os.EX_UNAVAILABLE) > + > +try: > + import jsonschema # type: ignore > + import yaml as yaml_m # type: ignore > +except ModuleNotFoundError as e: > + error(f'Missing Python module: {e.name}', os.EX_UNAVAILABLE) > + > +# > +# Actual script: > +# > + > +class KernelConfig: > + """.config file parser""" > + > + def __init__(self, file: Path): > + try: > + self.lines = file.read_text().splitlines() > + except OSError as e: > + error(f'Could not open {file}: {e.strerror}', os.EX_NOINPUT) > + > + self.symbols = self._parse_symbols() > + > + def _parse_symbols(self) -> dict[str, str]: > + """Extract CONFIG_* symbol assignments from .config""" > + symbol_set = re.compile(r'^(CONFIG_[A-Za-z0-9_]+)=([ym])$') > + symbol_unset = re.compile(r'^# (CONFIG_[A-Za-z0-9_]+) is not set$') What does this do for Kconfig's int, hex, and string options? - Julian Braha