mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Luis Augenstein <luis.augenstein@tngtech.com>
To: nathan@kernel.org, nsc@kernel.org
Cc: linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org,
	akpm@linux-foundation.org, gregkh@linuxfoundation.org,
	kstewart@linuxfoundation.org, maximilian.huber@tngtech.com,
	Luis Augenstein <luis.augenstein@tngtech.com>
Subject: [PATCH v3 6/7] scripts/sbom: use make_prereqs to determine build inputs
Date: Mon, 12 Oct 2026 23:33:21 +0200	[thread overview]
Message-ID: <20261012213337.2466524-7-luis.augenstein@tngtech.com> (raw)
In-Reply-To: <20261012213337.2466524-1-luis.augenstein@tngtech.com>

Build the list of file dependencies of a target from the
make_prereqs_<target> field and the deps_<target> entries of the .cmd
file instead of parsing the shell command stored in savedcmd_.

The prerequisites include more than KernelSbom wants to track: files
should be tracked if they end up in the kernel image or loadable
modules, but not each and every host tool or helper script used to
build them. Add a manually maintained exclude list for such
dependencies. It is still manual, but much easier to maintain than
the command-specific parsers that were needed to extract the relevant
inputs from each individual build command.

Assisted-by: LLM
Co-developed-by: Maximilian Huber <maximilian.huber@tngtech.com>
Signed-off-by: Maximilian Huber <maximilian.huber@tngtech.com>
Signed-off-by: Luis Augenstein <luis.augenstein@tngtech.com>
---
 scripts/sbom/sbom/cmd_graph/cmd_file.py       | 46 ++-----------
 .../sbom/sbom/cmd_graph/dependency_filter.py  | 59 +++++++++++++++++
 scripts/sbom/sbom/spdx_graph/kernel_file.py   | 64 ++++++++++++-------
 3 files changed, 105 insertions(+), 64 deletions(-)
 create mode 100644 scripts/sbom/sbom/cmd_graph/dependency_filter.py

diff --git a/scripts/sbom/sbom/cmd_graph/cmd_file.py b/scripts/sbom/sbom/cmd_graph/cmd_file.py
index cc576c7c6be..ab4b00b252b 100644
--- a/scripts/sbom/sbom/cmd_graph/cmd_file.py
+++ b/scripts/sbom/sbom/cmd_graph/cmd_file.py
@@ -5,7 +5,7 @@ import os
 import re
 from dataclasses import dataclass, field
 from sbom.cmd_graph.deps_parser import parse_cmd_file_deps
-from sbom.cmd_graph.savedcmd_parser import parse_inputs_from_commands
+from sbom.cmd_graph.dependency_filter import should_include_dependency
 import sbom.sbom_logging as sbom_logging
 from sbom.path_utils import PathStr
 
@@ -85,51 +85,17 @@ class CmdFile:
         Returns:
             list[PathStr]: dependency file paths relative to `obj_tree`.
         """
-        input_files: list[PathStr] = [
-            str(p) for p in parse_inputs_from_commands(self.savedcmd, fail_on_unknown_build_command)
-        ]
+        input_files: list[PathStr] = list(self.make_prereqs)
+
         if self.deps:
             input_files += [str(p) for p in parse_cmd_file_deps(self.deps)]
-        input_files = _expand_resolve_files(input_files, obj_tree)
 
         cmd_file_dependencies: list[PathStr] = []
         for input_file in input_files:
-            # input files are either absolute or relative to the object tree
+            # input files are either absolute or already relative to the object tree
             if os.path.isabs(input_file):
                 input_file = os.path.relpath(input_file, obj_tree)
-            if input_file == target_path:
-                # Skip target file to prevent cycles. This is necessary because some multi stage commands first create an output and then pass it as input to the next command, e.g., objcopy.
-                continue
-            cmd_file_dependencies.append(input_file)
+            if should_include_dependency(input_file):
+                cmd_file_dependencies.append(input_file)
         unique_cmd_file_dependencies = list(dict.fromkeys(cmd_file_dependencies))
         return unique_cmd_file_dependencies
-
-
-def _expand_resolve_files(input_files: list[PathStr], obj_tree: PathStr) -> list[PathStr]:
-    """
-    Expands resolve files which may reference additional files via '@' notation.
-
-    Args:
-        input_files (list[PathStr]): List of file paths relative to the object tree, where paths starting with '@' refer to files
-                                     containing further file paths, each on a separate line.
-        obj_tree: Absolute path to the root of the object tree.
-
-    Returns:
-        list[PathStr]: Flattened list of all input file paths, with any nested '@' file references resolved recursively.
-    """
-    expanded_input_files: list[PathStr] = []
-    for input_file in input_files:
-        if not input_file.startswith("@"):
-            expanded_input_files.append(input_file)
-            continue
-        resolve_file_path = os.path.join(obj_tree, input_file.removeprefix("@"))
-        if not os.path.exists(resolve_file_path):
-            sbom_logging.error(
-                "Skip resolving '{resolve_file_path}' because the response file does not exist.",
-                resolve_file_path=resolve_file_path,
-            )
-            continue
-        with open(resolve_file_path, "rt", encoding="utf-8") as f:
-            resolve_file_content = [line_stripped for line in f.readlines() if (line_stripped := line.strip())]
-        expanded_input_files += _expand_resolve_files(resolve_file_content, obj_tree)
-    return expanded_input_files
diff --git a/scripts/sbom/sbom/cmd_graph/dependency_filter.py b/scripts/sbom/sbom/cmd_graph/dependency_filter.py
new file mode 100644
index 00000000000..f1fdc2cb965
--- /dev/null
+++ b/scripts/sbom/sbom/cmd_graph/dependency_filter.py
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: GPL-2.0-only OR MIT
+# Copyright (C) 2025 TNG Technology Consulting GmbH
+
+import re
+
+from sbom.path_utils import PathStr
+
+# Regex patterns for dependencies that should not be tracked in the dependency graph.
+_COMPILED_EXCLUDE_PATTERNS: tuple[re.Pattern[str], ...] = (
+    # scripts in source tree (except module-common.c, which is compiled into every module)
+    re.compile(r"^\.\./scripts/(?!module-common\.c$)"),
+    # scripts and tools in obj tree
+    re.compile(r"^scripts/"),
+    re.compile(r"^tools/"),
+    re.compile(r"^arch/[^/]+/tools/"),
+    # Host helper scripts
+    re.compile(r".*\.sh$"),
+    re.compile(r".*\.py$"),
+    re.compile(r".*\.pl$"),
+    # Host-tool executables
+    re.compile(r"^certs/extract-cert$"),
+    re.compile(r"^security/selinux/genheaders$"),
+    re.compile(r"^usr/gen_init_cpio$"),
+    re.compile(r"^drivers/gpu/drm/radeon/mkregtable$"),
+    re.compile(r"^drivers/video/logo/pnmtologo$"),
+    re.compile(r"^lib/raid/raid6/mktables$"),
+    re.compile(r"^\.\./fs/smb/client/gen_smb1_mapping$"),
+    re.compile(r"^\.\./fs/smb/client/gen_smb2_mapping$"),
+    # Other
+    re.compile(r".*\.xsd$"),
+    re.compile(r".*purgatory\.chk$"),
+    re.compile(r".*\.genkey$"),
+    re.compile(r".*\.md$"),
+    re.compile(r"^include/config/"),
+    # x86
+    re.compile(r"^arch/x86/boot/compressed/mkpiggy$"),
+    re.compile(r"^arch/x86/boot/mkcpustr$"),
+    # arm
+    re.compile(r"^arch/arm/vdso/vdsomunge$"),
+    # arm64
+    re.compile(r"^arch/arm64/kvm/hyp/nvhe/gen-hyprel$"),
+    re.compile(r"^arch/arm64/kernel/pi/relacheck$"),
+)
+
+def should_include_dependency(path: PathStr) -> bool:
+    """
+    Return whether a `.cmd` dependency should appear in the tracked dependency graph.
+
+    Track files that are inputs to compiling or linking artifacts that end up in the
+    kernel image or loadable modules (e.g. source → object → archive → image/module).
+    Exclude host tools and helper scripts whose code is not linked into the kernel.
+
+    Args:
+        path: Dependency path relative to the object tree.
+
+    Returns:
+        True if the dependency should be included in the dependency graph.
+    """
+    return not any(pattern.match(path) for pattern in _COMPILED_EXCLUDE_PATTERNS)
diff --git a/scripts/sbom/sbom/spdx_graph/kernel_file.py b/scripts/sbom/sbom/spdx_graph/kernel_file.py
index 505f25f66eb..cea14cb3538 100644
--- a/scripts/sbom/sbom/spdx_graph/kernel_file.py
+++ b/scripts/sbom/sbom/spdx_graph/kernel_file.py
@@ -245,7 +245,7 @@ def _get_primary_purpose(absolute_path: PathStr) -> SoftwarePurpose | None:
         return any(segment in absolute_path for segment in path_segments)
 
     # Source code
-    if ends_with([".c", ".h", ".S", ".s", ".rs", ".pl", "gen_smb1_mapping", "gen_smb2_mapping"]):
+    if ends_with([".c", ".h", ".S", ".s", ".rs"]):
         return "source"
 
     # Libraries
@@ -271,45 +271,61 @@ def _get_primary_purpose(absolute_path: PathStr) -> SoftwarePurpose | None:
     # Data files
     if ends_with(
         [
-            ".tbl",
-            ".relocs",
-            ".rmeta",
-            ".in",
+            ".awk",
             ".dbg",
-            ".x509",
-            ".pbm",
-            ".ppm",
             ".dtb",
-            ".uc",
-            ".inc",
+            ".dtbo",
             ".dts",
             ".dtsi",
-            ".dtbo",
-            ".xml",
+            ".dtso",
+            ".in",
+            ".inc",
+            ".json",
+            ".ld",
+            ".lds",
+            ".mod",
+            ".order",
+            ".pbm",
+            ".ppm",
+            ".relocs",
+            ".rmeta",
             ".ro",
-            "initramfs_inc_data",
-            "default_cpio_list",
-            "x509_certificate_list",
-            "utf8data.c_shipped",
+            ".tbl",
+            ".uc",
+            ".x509",
+            ".xml",
             "blacklist_hash_list",
-            "x509_revocation_list",
             "cpucaps",
-            "sysreg",
+            "default_cpio_list",
+            "initramfs_inc_data",
+            "kheaders.md5",
+            "kheaders-objlist",
+            "kheaders-srclist",
             "mach-types",
+            "sysreg",
+            "utf8data.c_shipped",
+            "x509_certificate_list",
+            "x509_revocation_list",
         ]
     ) or includes_path_segments(["drivers/gpu/drm/radeon/reg_srcs/"]):
         return "data"
 
     # Configuration files
-    if ends_with([".pem", ".key", ".conf", ".config", ".cfg", ".bconf"]):
+    if ends_with([
+        ".pem",
+        ".key",
+        ".conf",
+        ".config",
+        ".cfg",
+        ".bconf",
+        "config_data",
+        ".genkey",
+        "bindgen_parameters",
+    ]):
         return "configuration"
 
-    # Documentation
-    if ends_with([".md"]):
-        return "documentation"
-
     # Other / miscellaneous
-    if ends_with([".o", ".tmp"]):
+    if ends_with([".o"]):
         return "other"
 
     sbom_logging.warning("Could not infer primary purpose for {absolute_path}", absolute_path=absolute_path)
-- 
2.43.0


  parent reply	other threads:[~2026-10-12 21:34 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-12 21:33 [PATCH v3 0/7] kbuild: record cmd-prereqs in .cmd files Luis Augenstein
2026-10-12 21:33 ` [PATCH v3 1/7] scripts/make_fit: limit .cmd file parsing to the savedcmd_ line Luis Augenstein
2026-10-12 21:33 ` [PATCH v3 2/7] kbuild: refactor fixdep to collect dependencies before printing Luis Augenstein
2026-10-12 21:33 ` [PATCH v3 3/7] scripts/sbom: skip make_prereqs lines when parsing .cmd files Luis Augenstein
2026-10-12 21:33 ` [PATCH v3 4/7] kbuild: record cmd-prereqs in " Luis Augenstein
2026-10-12 21:33 ` [PATCH v3 5/7] scripts/sbom: parse make_prereqs from " Luis Augenstein
2026-10-12 21:33 ` Luis Augenstein [this message]
2026-10-12 21:33 ` [PATCH v3 7/7] scripts/sbom: remove the command-specific parsers Luis Augenstein

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261012213337.2466524-7-luis.augenstein@tngtech.com \
    --to=luis.augenstein@tngtech.com \
    --cc=akpm@linux-foundation.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=kstewart@linuxfoundation.org \
    --cc=linux-kbuild@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maximilian.huber@tngtech.com \
    --cc=nathan@kernel.org \
    --cc=nsc@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®