Files
Gleb Chesnokov 6c3405f5fe scripts: Add Cppcheck with native build contexts
Expose make cppcheck using freshly captured kernel CHECK commands and
real userspace compiler invocations. Keep their include paths and
definitions unchanged and analyze kernel and userspace contexts
separately.

Use the shared source scope without additional input exclusions, project
models or diagnostic suppressions. Relevant diffs trigger full
configured analysis; KUnit coverage follows the actual build
configuration.

Retain build logs, compilation databases, native XML and checker
coverage. Separate source findings from parser failures, missing inputs
and incomplete builds, with isolated report and capture fixtures.
2026-10-19 21:38:56 +03:00

56 lines
2.0 KiB
Python

#!/usr/bin/env python3
"""Record Kbuild CHECK arguments or successful userspace compiler invocations."""
import json
import os
from pathlib import Path
import shlex
import sys
import uuid
sys.dont_write_bytecode = True
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "scripts"))
from lint_common import entrypoint, run # noqa: E402
from lint_scope import in_scope # noqa: E402
def source_files(arguments, profile, root):
if profile == "kernel":
candidates = arguments[-1:]
elif "-c" in arguments:
candidates = [arg for arg in arguments if arg.endswith(".c") and not arg.startswith("-")]
else:
return []
return [Path(arg).resolve() for arg in candidates
if Path(arg).is_file() and in_scope(Path(arg), root, "cppcheck")]
def main():
profile, *arguments = sys.argv[1:]
if profile not in {"kernel", "userspace"}:
raise ValueError(f"unknown capture profile: {profile}")
sources = source_files(arguments, profile, ROOT)
compiler = shlex.split(os.environ.get("SCST_LINT_CC", "cc"))
if not compiler:
raise ValueError("empty userspace compiler command")
# Kernel CHECK receives the real c_flags. It only records; Kbuild still
# invokes its own compiler. Do not run Sparse or add __CHECKER__ definitions.
command = (["cc"] if profile == "kernel" else compiler) + arguments
records = []
for source in sources:
path = Path(os.environ["SCST_LINT_RECORDS"]) / f"{uuid.uuid4()}.json"
record = {"file": str(source), "directory": str(Path.cwd()), "arguments": command,
"profile": profile, "returncode": 2}
path.write_text(json.dumps(record) + "\n")
records.append((path, record))
status = run(command).returncode if profile == "userspace" else 0
for path, record in records:
record["returncode"] = status
path.write_text(json.dumps(record) + "\n")
return status
if __name__ == "__main__":
sys.exit(entrypoint(main))