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,
maximilian.huber@tngtech.com,
Luis Augenstein <luis.augenstein@tngtech.com>
Subject: [PATCH v2 05/14] tools/sbom: add additional dependency sources for cmd graph
Date: Tue, 20 Jan 2026 12:53:43 +0100 [thread overview]
Message-ID: <20260120115352.10910-6-luis.augenstein@tngtech.com> (raw)
In-Reply-To: <20260120115352.10910-1-luis.augenstein@tngtech.com>
Add hardcoded dependencies and .incbin directive parsing to
discover dependencies not tracked by .cmd files.
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>
---
tools/sbom/sbom/cmd_graph/cmd_graph_node.py | 24 +++++-
.../sbom/cmd_graph/hardcoded_dependencies.py | 83 +++++++++++++++++++
tools/sbom/sbom/cmd_graph/incbin_parser.py | 42 ++++++++++
tools/sbom/sbom/environment.py | 14 ++++
4 files changed, 162 insertions(+), 1 deletion(-)
create mode 100644 tools/sbom/sbom/cmd_graph/hardcoded_dependencies.py
create mode 100644 tools/sbom/sbom/cmd_graph/incbin_parser.py
create mode 100644 tools/sbom/sbom/environment.py
diff --git a/tools/sbom/sbom/cmd_graph/cmd_graph_node.py b/tools/sbom/sbom/cmd_graph/cmd_graph_node.py
index fdaed0f0ccba..feacdbf76955 100644
--- a/tools/sbom/sbom/cmd_graph/cmd_graph_node.py
+++ b/tools/sbom/sbom/cmd_graph/cmd_graph_node.py
@@ -9,6 +9,8 @@ from typing import Iterator, Protocol
from sbom import sbom_logging
from sbom.cmd_graph.cmd_file import CmdFile
+from sbom.cmd_graph.hardcoded_dependencies import get_hardcoded_dependencies
+from sbom.cmd_graph.incbin_parser import parse_incbin_statements
from sbom.path_utils import PathStr, is_relative_to
@@ -104,14 +106,34 @@ class CmdGraphNode:
)
return node
+ # Search for dependencies to add to the graph as child nodes. Child paths are always relative to the output tree.
+ def _build_child_node(child_path: PathStr) -> "CmdGraphNode":
+ return CmdGraphNode.create(child_path, config, cache, depth + 1)
+
+ node.hardcoded_dependencies = [
+ _build_child_node(hardcoded_dependency_path)
+ for hardcoded_dependency_path in get_hardcoded_dependencies(
+ target_path_absolute, config.obj_tree, config.src_tree
+ )
+ ]
+
if cmd_file is not None:
node.cmd_file_dependencies = [
- CmdGraphNode.create(cmd_file_dependency_path, config, cache, depth + 1)
+ _build_child_node(cmd_file_dependency_path)
for cmd_file_dependency_path in cmd_file.get_dependencies(
target_path, config.obj_tree, config.fail_on_unknown_build_command
)
]
+ if node.absolute_path.endswith(".S"):
+ node.incbin_dependencies = [
+ IncbinDependency(
+ node=_build_child_node(incbin_statement.path),
+ full_statement=incbin_statement.full_statement,
+ )
+ for incbin_statement in parse_incbin_statements(node.absolute_path)
+ ]
+
return node
diff --git a/tools/sbom/sbom/cmd_graph/hardcoded_dependencies.py b/tools/sbom/sbom/cmd_graph/hardcoded_dependencies.py
new file mode 100644
index 000000000000..a5977f14ae49
--- /dev/null
+++ b/tools/sbom/sbom/cmd_graph/hardcoded_dependencies.py
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: GPL-2.0-only OR MIT
+# Copyright (C) 2025 TNG Technology Consulting GmbH
+
+import os
+from typing import Callable
+import sbom.sbom_logging as sbom_logging
+from sbom.path_utils import PathStr, is_relative_to
+from sbom.environment import Environment
+
+HARDCODED_DEPENDENCIES: dict[str, list[str]] = {
+ # defined in linux/Kbuild
+ "include/generated/rq-offsets.h": ["kernel/sched/rq-offsets.s"],
+ "kernel/sched/rq-offsets.s": ["include/generated/asm-offsets.h"],
+ "include/generated/bounds.h": ["kernel/bounds.s"],
+ "include/generated/asm-offsets.h": ["arch/{arch}/kernel/asm-offsets.s"],
+}
+
+
+def get_hardcoded_dependencies(path: PathStr, obj_tree: PathStr, src_tree: PathStr) -> list[PathStr]:
+ """
+ Some files in the kernel build process are not tracked by the .cmd dependency mechanism.
+ Parsing these dependencies programmatically is too complex for the scope of this project.
+ Therefore, this function provides manually defined dependencies to be added to the build graph.
+
+ Args:
+ path: absolute path to a file within the src tree or object tree.
+ obj_tree: absolute Path to the base directory of the object tree.
+ src_tree: absolute Path to the `linux` source directory.
+
+ Returns:
+ list[PathStr]: A list of dependency file paths (relative to the object tree) required to build the file at the given path.
+ """
+ if is_relative_to(path, obj_tree):
+ path = os.path.relpath(path, obj_tree)
+ elif is_relative_to(path, src_tree):
+ path = os.path.relpath(path, src_tree)
+
+ if path not in HARDCODED_DEPENDENCIES:
+ return []
+
+ template_variables: dict[str, Callable[[], str | None]] = {
+ "arch": lambda: _get_arch(path),
+ }
+
+ dependencies: list[PathStr] = []
+ for dependency_template in HARDCODED_DEPENDENCIES[path]:
+ dependency = _evaluate_template(dependency_template, template_variables)
+ if dependency is None:
+ continue
+ if os.path.exists(os.path.join(obj_tree, dependency)):
+ dependencies.append(dependency)
+ elif os.path.exists(os.path.join(src_tree, dependency)):
+ dependencies.append(os.path.relpath(dependency, obj_tree))
+ else:
+ sbom_logging.error(
+ "Skip hardcoded dependency '{dependency}' for '{path}' because the dependency lies neither in the src tree nor the object tree.",
+ dependency=dependency,
+ path=path,
+ )
+
+ return dependencies
+
+
+def _evaluate_template(template: str, variables: dict[str, Callable[[], str | None]]) -> str | None:
+ for key, value_function in variables.items():
+ template_key = "{" + key + "}"
+ if template_key in template:
+ value = value_function()
+ if value is None:
+ return None
+ template = template.replace(template_key, value)
+ return template
+
+
+def _get_arch(path: PathStr):
+ srcarch = Environment.SRCARCH()
+ if srcarch is None:
+ sbom_logging.error(
+ "Skipped architecture specific hardcoded dependency for '{path}' because the SRCARCH environment variable was not set.",
+ path=path,
+ )
+ return None
+ return srcarch
diff --git a/tools/sbom/sbom/cmd_graph/incbin_parser.py b/tools/sbom/sbom/cmd_graph/incbin_parser.py
new file mode 100644
index 000000000000..130f9520837d
--- /dev/null
+++ b/tools/sbom/sbom/cmd_graph/incbin_parser.py
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0-only OR MIT
+# Copyright (C) 2025 TNG Technology Consulting GmbH
+
+from dataclasses import dataclass
+import re
+
+from sbom.path_utils import PathStr
+
+INCBIN_PATTERN = re.compile(r'\s*\.incbin\s+"(?P<path>[^"]+)"')
+"""Regex pattern for matching `.incbin "<path>"` statements."""
+
+
+@dataclass
+class IncbinStatement:
+ """A parsed `.incbin "<path>"` directive."""
+
+ path: PathStr
+ """path to the file referenced by the `.incbin` directive."""
+
+ full_statement: str
+ """Full `.incbin "<path>"` statement as it originally appeared in the file."""
+
+
+def parse_incbin_statements(absolute_path: PathStr) -> list[IncbinStatement]:
+ """
+ Parses `.incbin` directives from an `.S` assembly file.
+
+ Args:
+ absolute_path: Absolute path to the `.S` assembly file.
+
+ Returns:
+ list[IncbinStatement]: Parsed `.incbin` statements.
+ """
+ with open(absolute_path, "rt") as f:
+ content = f.read()
+ return [
+ IncbinStatement(
+ path=match.group("path"),
+ full_statement=match.group(0).strip(),
+ )
+ for match in INCBIN_PATTERN.finditer(content)
+ ]
diff --git a/tools/sbom/sbom/environment.py b/tools/sbom/sbom/environment.py
new file mode 100644
index 000000000000..b3fb2f0ba61d
--- /dev/null
+++ b/tools/sbom/sbom/environment.py
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only OR MIT
+# Copyright (C) 2025 TNG Technology Consulting GmbH
+
+import os
+
+
+class Environment:
+ """
+ Read-only accessor for kernel build environment variables.
+ """
+
+ @classmethod
+ def SRCARCH(cls) -> str | None:
+ return os.getenv("SRCARCH")
--
2.34.1
next prev parent reply other threads:[~2026-01-20 11:55 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-20 11:53 [PATCH v2 00/14] Add SPDX SBOM generation tool Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 01/14] tools/sbom: integrate tool in make process Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 02/14] tools/sbom: setup sbom logging Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 03/14] tools/sbom: add command parsers Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 04/14] tools/sbom: add cmd graph generation Luis Augenstein
2026-01-20 11:53 ` Luis Augenstein [this message]
2026-01-20 11:53 ` [PATCH v2 06/14] tools/sbom: add SPDX classes Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 07/14] tools/sbom: add JSON-LD serialization Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 08/14] tools/sbom: add shared SPDX elements Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 09/14] tools/sbom: collect file metadata Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 10/14] tools/sbom: add SPDX output graph Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 11/14] tools/sbom: add SPDX source graph Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 12/14] tools/sbom: add SPDX build graph Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 13/14] tools/sbom: add unit tests for command parsers Luis Augenstein
2026-01-22 6:00 ` Miguel Ojeda
2026-01-22 20:01 ` Luis Augenstein
2026-01-20 11:53 ` [PATCH v2 14/14] tools/sbom: add unit tests for SPDX-License-Identifier parsing Luis Augenstein
2026-01-20 15:40 ` [PATCH v2 00/14] Add SPDX SBOM generation tool Greg KH
2026-01-20 16:14 ` Luis Augenstein
2026-01-22 6:18 ` Miguel Ojeda
2026-01-22 6:35 ` Greg KH
2026-01-25 15:20 ` Miguel Ojeda
2026-01-25 15:33 ` Miguel Ojeda
2026-01-25 15:40 ` Greg KH
2026-01-25 15:34 ` Greg KH
2026-01-25 17:24 ` Miguel Ojeda
2026-01-27 8:03 ` Luis Augenstein
2026-01-27 23:10 ` Nathan Chancellor
2026-02-02 16:28 ` Luis Augenstein
2026-02-03 0:40 ` Nathan Chancellor
2026-02-03 14:41 ` Luis Augenstein
2026-02-03 20:51 ` Nathan Chancellor
2026-01-22 20:32 ` Luis Augenstein
2026-01-25 15:30 ` Miguel Ojeda
2026-01-26 6:46 ` 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=20260120115352.10910-6-luis.augenstein@tngtech.com \
--to=luis.augenstein@tngtech.com \
--cc=akpm@linux-foundation.org \
--cc=gregkh@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