utils/generate-cyclonedx: fix dependencies w/o virtual

Since its introduction in [1], by default the `generate-cyclonedx`
script doesn't include buildroot's virtual packages in its 'components'
list, unless using the `--virtual` argument.

References to virtual packages present in the 'show-info' output are
filtered out in the resulting dependencies.

This patch fix the default CycloneDX dependencies generation
without virtual packages to reference the packages that provide the
virtual package instead of just dropping the virtual package itself.

If we use the package `lbase64` that depends on the virtual package
`luainterpreter` as an example. The 'dependency' entry looks like the
following:

```
{
  "ref": "lbase64",
  "dependsOn": [
    "host-skeleton",
    "skeleton-init-common",
    "skeleton-init-sysv",
    "toolchain-external-bootlin"
  ]
}
```

The `luainterpreter` dependency is missing.

After applying this patch, package that provides the `luainterpreter` is
present:

```
{
  "ref": "lbase64",
  "dependsOn": [
    "host-skeleton",
    "lua",
    "skeleton-custom",
    "skeleton-init-sysv"
  ]
}
```

In the case of a virtual package provided by multiple packages all those
packages will be listed. This happens when generating an SBOM on the
entire Buildroot packages.

[1] dbab39e2d9 support/scripts/generate-cyclonedx.py: add script to generate CycloneDX-style SBOM

Signed-off-by: Thomas Perale <thomas.perale@mind.be>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
This commit is contained in:
Thomas Perale
2026-01-26 14:04:14 +01:00
committed by Peter Korsgaard
parent 0dd7a3017f
commit 67738a6e1d

View File

@@ -337,7 +337,25 @@ def cyclonedx_vulnerabilities(show_info_dict):
} for cve, components in cves.items()]
def br2_parse_deps(ref, show_info_dict, virtual=False):
def br2_virtual_is_provided_by(ref, show_info_dict) -> list:
"""Retrieve the list of packages that provide a virtual package.
Args:
ref (str): The identifier of the virtual package.
show_info_dict (dict): The JSON output of the show-info
command, parsed into a Python dictionary.
Returns:
list: package list that provides the virtual package.
"""
return [
name
for name, comp in show_info_dict.items()
if "provides" in comp and ref in comp["provides"]
]
def br2_parse_deps(ref, show_info_dict, virtual=False) -> list:
"""This function will collect all dependencies from the show-info output.
The dependency on virtual package will collect the final dependency without
@@ -352,13 +370,15 @@ def br2_parse_deps(ref, show_info_dict, virtual=False):
Returns:
list: A list of dependencies of the 'ref' package.
"""
deps = []
deps = set()
for dep in show_info_dict.get(ref, {}).get("dependencies", []):
if virtual or show_info_dict.get(dep, {}).get("virtual") is False:
deps.append(dep)
if not virtual and show_info_dict.get(dep, {}).get("virtual"):
deps.update(br2_virtual_is_provided_by(dep, show_info_dict))
else:
deps.add(dep)
return deps
return list(deps)
def main():