diff mbox series

[v2,2/2] spdx30_tasks: Add support for exporting PACKAGECONFIG to SPDX

Message ID 20250728133044.39757-3-kamel.bouhara@bootlin.com
State New
Headers show
Series spdx3: Add optional support for exporting | expand

Commit Message

Kamel Bouhara July 28, 2025, 1:30 p.m. UTC
Introduce the SPDX_INCLUDE_PACKAGECONFIG variable, which when enabled causes
PACKAGECONFIG features to be recorded in the SPDX document as build parameters.

Each feature is recorded as a DictionaryEntry with key PACKAGECONFIG:<feature>
and value enabled or disabled, depending on whether the feature is active in
the current build.

This makes the build-time configuration more transparent in SPDX output and
improves reproducibility tracking.

This makes the build-time configuration more transparent in SPDX output and
improves reproducibility tracking. In particular, it allows consumers of the
SBOM to identify enabled/disabled features that may affect security posture
or feature set.

Signed-off-by: Kamel Bouhara <kamel.bouhara@bootlin.com>
---
 meta/classes/create-spdx-3.0.bbclass |  5 +++++
 meta/lib/oe/spdx30_tasks.py          | 20 ++++++++++++++++++++
 2 files changed, 25 insertions(+)

Comments

Joshua Watt July 29, 2025, 2:57 p.m. UTC | #1
I'm not quite sure about this. The PACKAGECONFIG value is already captured
if you do `SPDX_INCLUDE_BUILD_VARIABLES = "1"`, so having a explicit way to
capture it doesn't seem necessary.

If the build variables are too much data, I'd prefer some way to filter
which ones get included in the SPDX data rather than add special cases for
special variables (for example, maybe `SPDX_INCLUDE_BUILD_VARIABLES = "1"`
include all variables, but `SPDX_INCLUDE_BUILD_VARIABLES = "PACKAGECONFIG"`
would only include the value of PACKAGECONFIG)

On Mon, Jul 28, 2025 at 7:30 AM Kamel Bouhara <kamel.bouhara@bootlin.com>
wrote:

> Introduce the SPDX_INCLUDE_PACKAGECONFIG variable, which when enabled
> causes
> PACKAGECONFIG features to be recorded in the SPDX document as build
> parameters.
>
> Each feature is recorded as a DictionaryEntry with key
> PACKAGECONFIG:<feature>
> and value enabled or disabled, depending on whether the feature is active
> in
> the current build.
>
> This makes the build-time configuration more transparent in SPDX output and
> improves reproducibility tracking.
>
> This makes the build-time configuration more transparent in SPDX output and
> improves reproducibility tracking. In particular, it allows consumers of
> the
> SBOM to identify enabled/disabled features that may affect security posture
> or feature set.
>
> Signed-off-by: Kamel Bouhara <kamel.bouhara@bootlin.com>
> ---
>  meta/classes/create-spdx-3.0.bbclass |  5 +++++
>  meta/lib/oe/spdx30_tasks.py          | 20 ++++++++++++++++++++
>  2 files changed, 25 insertions(+)
>
> diff --git a/meta/classes/create-spdx-3.0.bbclass
> b/meta/classes/create-spdx-3.0.bbclass
> index 15c31ba9a3..6125e8b547 100644
> --- a/meta/classes/create-spdx-3.0.bbclass
> +++ b/meta/classes/create-spdx-3.0.bbclass
> @@ -56,6 +56,11 @@ and each CONFIG_* value will be included in the
> Build.build_parameter list as Di
>  items. Set to '0' to disable exporting kernel configuration to improve
> performance or reduce \
>  SPDX document size."
>
> +SPDX_INCLUDE_PACKAGECONFIG ??= "0"
> +SPDX_INCLUDE_PACKAGECONFIG[doc] = "If set to '1', each PACKAGECONFIG
> feature is recorded in the \
> +build_Build object's build_parameter list as a DictionaryEntry with key \
> +'PACKAGECONFIG:<feature>' and value 'enabled' or 'disabled'"
> +
>  SPDX_IMPORTS ??= ""
>  SPDX_IMPORTS[doc] = "SPDX_IMPORTS is the base variable that describes how
> to \
>      reference external SPDX ids. Each import is defined as a key in this \
> diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py
> index c352dab152..d708715981 100644
> --- a/meta/lib/oe/spdx30_tasks.py
> +++ b/meta/lib/oe/spdx30_tasks.py
> @@ -815,6 +815,26 @@ def create_spdx(d):
>              sorted(list(build_inputs)) + sorted(list(debug_source_ids)),
>          )
>
> +    if d.getVar("SPDX_INCLUDE_PACKAGECONFIG", True) != "0":
> +        packageconfig = (d.getVar("PACKAGECONFIG") or "").split()
> +        all_features = (d.getVarFlags("PACKAGECONFIG") or {}).keys()
> +
> +        if all_features:
> +            enabled = set(packageconfig)
> +            all_features_set = set(all_features)
> +            disabled = all_features_set - enabled
> +
> +            for feature in sorted(all_features):
> +                status = "enabled" if feature in enabled else "disabled"
> +                build.build_parameter.append(
> +                    oe.spdx30.DictionaryEntry(
> +                        key=f"PACKAGECONFIG:{feature}",
> +                        value=status
> +                    )
> +                )
> +
> +            bb.note(f"Added PACKAGECONFIG entries: {len(enabled)}
> enabled, {len(disabled)} disabled")
> +
>      oe.sbom30.write_recipe_jsonld_doc(d, build_objset, "recipes",
> deploydir)
>
>
> --
> 2.43.0
>
>
Kamel Bouhara July 29, 2025, 3:54 p.m. UTC | #2
On Tue, Jul 29, 2025 at 08:57:53AM -0600, Joshua Watt wrote:
>    I'm not quite sure about this. The PACKAGECONFIG value is already
>    captured if you do `SPDX_INCLUDE_BUILD_VARIABLES = "1"`, so having a
>    explicit way to capture it doesn't seem necessary.
>    If the build variables are too much data, I'd prefer some way to filter
>    which ones get included in the SPDX data rather than add special cases
>    for special variables (for example, maybe `SPDX_INCLUDE_BUILD_VARIABLES
>    = "1"` include all variables, but `SPDX_INCLUDE_BUILD_VARIABLES =
>    "PACKAGECONFIG"` would only include the value of PACKAGECONFIG)

Hello Joshua,

You are right, parsing the raw PACKAGECONFIG string isn’t fundamentally
more complex for most SPDX consumers, especially for diff or comparison
tooling where raw strings are straightforward to compare.

I’m happy to revise the patch accordingly if that sounds good.

Cheers,
Kamel

>    On Mon, Jul 28, 2025 at 7:30 AM Kamel Bouhara
>    <[1]kamel.bouhara@bootlin.com> wrote:
>
>      Introduce the SPDX_INCLUDE_PACKAGECONFIG variable, which when
>      enabled causes
>      PACKAGECONFIG features to be recorded in the SPDX document as build
>      parameters.
>      Each feature is recorded as a DictionaryEntry with key
>      PACKAGECONFIG:<feature>
>      and value enabled or disabled, depending on whether the feature is
>      active in
>      the current build.
>      This makes the build-time configuration more transparent in SPDX
>      output and
>      improves reproducibility tracking.
>      This makes the build-time configuration more transparent in SPDX
>      output and
>      improves reproducibility tracking. In particular, it allows
>      consumers of the
>      SBOM to identify enabled/disabled features that may affect security
>      posture
>      or feature set.
>      Signed-off-by: Kamel Bouhara <[2]kamel.bouhara@bootlin.com>
>      ---
>       meta/classes/create-spdx-3.0.bbclass |  5 +++++
>       meta/lib/oe/spdx30_tasks.py          | 20 ++++++++++++++++++++
>       2 files changed, 25 insertions(+)
>      diff --git a/meta/classes/create-spdx-3.0.bbclass
>      b/meta/classes/create-spdx-3.0.bbclass
>      index 15c31ba9a3..6125e8b547 100644
>      --- a/meta/classes/create-spdx-3.0.bbclass
>      +++ b/meta/classes/create-spdx-3.0.bbclass
>      @@ -56,6 +56,11 @@ and each CONFIG_* value will be included in the
>      Build.build_parameter list as Di
>       items. Set to '0' to disable exporting kernel configuration to
>      improve performance or reduce \
>       SPDX document size."
>      +SPDX_INCLUDE_PACKAGECONFIG ??= "0"
>      +SPDX_INCLUDE_PACKAGECONFIG[doc] = "If set to '1', each
>      PACKAGECONFIG feature is recorded in the \
>      +build_Build object's build_parameter list as a DictionaryEntry with
>      key \
>      +'PACKAGECONFIG:<feature>' and value 'enabled' or 'disabled'"
>      +
>       SPDX_IMPORTS ??= ""
>       SPDX_IMPORTS[doc] = "SPDX_IMPORTS is the base variable that
>      describes how to \
>           reference external SPDX ids. Each import is defined as a key in
>      this \
>      diff --git a/meta/lib/oe/spdx30_tasks.py
>      b/meta/lib/oe/spdx30_tasks.py
>      index c352dab152..d708715981 100644
>      --- a/meta/lib/oe/spdx30_tasks.py
>      +++ b/meta/lib/oe/spdx30_tasks.py
>      @@ -815,6 +815,26 @@ def create_spdx(d):
>                   sorted(list(build_inputs)) +
>      sorted(list(debug_source_ids)),
>               )
>      +    if d.getVar("SPDX_INCLUDE_PACKAGECONFIG", True) != "0":
>      +        packageconfig = (d.getVar("PACKAGECONFIG") or "").split()
>      +        all_features = (d.getVarFlags("PACKAGECONFIG") or
>      {}).keys()
>      +
>      +        if all_features:
>      +            enabled = set(packageconfig)
>      +            all_features_set = set(all_features)
>      +            disabled = all_features_set - enabled
>      +
>      +            for feature in sorted(all_features):
>      +                status = "enabled" if feature in enabled else
>      "disabled"
>      +                build.build_parameter.append(
>      +                    oe.spdx30.DictionaryEntry(
>      +                        key=f"PACKAGECONFIG:{feature}",
>      +                        value=status
>      +                    )
>      +                )
>      +
>      +            bb.note(f"Added PACKAGECONFIG entries: {len(enabled)}
>      enabled, {len(disabled)} disabled")
>      +
>           oe.sbom30.write_recipe_jsonld_doc(d, build_objset, "recipes",
>      deploydir)
>      --
>      2.43.0
>
> References
>
>    1. mailto:kamel.bouhara@bootlin.com
>    2. mailto:kamel.bouhara@bootlin.com

--
Kamel Bouhara, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com
Kamel Bouhara July 30, 2025, 8:31 a.m. UTC | #3
On Tue, Jul 29, 2025 at 05:54:49PM +0200, Kamel Bouhara wrote:
> On Tue, Jul 29, 2025 at 08:57:53AM -0600, Joshua Watt wrote:
> >    I'm not quite sure about this. The PACKAGECONFIG value is already
> >    captured if you do `SPDX_INCLUDE_BUILD_VARIABLES = "1"`, so having a
> >    explicit way to capture it doesn't seem necessary.
> >    If the build variables are too much data, I'd prefer some way to filter
> >    which ones get included in the SPDX data rather than add special cases
> >    for special variables (for example, maybe `SPDX_INCLUDE_BUILD_VARIABLES
> >    = "1"` include all variables, but `SPDX_INCLUDE_BUILD_VARIABLES =
> >    "PACKAGECONFIG"` would only include the value of PACKAGECONFIG)
>
> Hello Joshua,
>
> You are right, parsing the raw PACKAGECONFIG string isn’t fundamentally
> more complex for most SPDX consumers, especially for diff or comparison
> tooling where raw strings are straightforward to compare.
>
> I’m happy to revise the patch accordingly if that sounds good.
>

Hi Joshua,

I took a closer look at what SPDX_INCLUDE_BUILD_VARIABLES actually exports,
and you're right that PACKAGECONFIG is included but only as a raw,
unevaluated string like:

	{ "key": "PACKAGECONFIG", "value": "editline gdbm ${@bb.utils.filter('DISTRO_FEATURES', 'lto', d)}" }

This doesn't show which features are enabled or disabled, nor does it
reflect the final evaluated configuration. So from a consumer/tooling
perspective, it lacks the granularity needed to understand the actual
build toggles.

That’s why I originally chose to export each PACKAGECONFIG feature
explicitly as a DictionaryEntry, with enabled/disabled values.
It makes feature selection clear and machine-readable, which is especially
helpful when diffing builds.

Given this, would you reconsider accepting the original approach with
structured PACKAGECONFIG export as an optional feature?

Alternatively, I could still integrate this into a filtered variable
export system, but with special logic just for how PACKAGECONFIG is interpreted.

Let me know what you'd prefer to adjust accordingly!

Kamel

--
Kamel Bouhara, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com
diff mbox series

Patch

diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass
index 15c31ba9a3..6125e8b547 100644
--- a/meta/classes/create-spdx-3.0.bbclass
+++ b/meta/classes/create-spdx-3.0.bbclass
@@ -56,6 +56,11 @@  and each CONFIG_* value will be included in the Build.build_parameter list as Di
 items. Set to '0' to disable exporting kernel configuration to improve performance or reduce \
 SPDX document size."
 
+SPDX_INCLUDE_PACKAGECONFIG ??= "0"
+SPDX_INCLUDE_PACKAGECONFIG[doc] = "If set to '1', each PACKAGECONFIG feature is recorded in the \
+build_Build object's build_parameter list as a DictionaryEntry with key \
+'PACKAGECONFIG:<feature>' and value 'enabled' or 'disabled'"
+
 SPDX_IMPORTS ??= ""
 SPDX_IMPORTS[doc] = "SPDX_IMPORTS is the base variable that describes how to \
     reference external SPDX ids. Each import is defined as a key in this \
diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py
index c352dab152..d708715981 100644
--- a/meta/lib/oe/spdx30_tasks.py
+++ b/meta/lib/oe/spdx30_tasks.py
@@ -815,6 +815,26 @@  def create_spdx(d):
             sorted(list(build_inputs)) + sorted(list(debug_source_ids)),
         )
 
+    if d.getVar("SPDX_INCLUDE_PACKAGECONFIG", True) != "0":
+        packageconfig = (d.getVar("PACKAGECONFIG") or "").split()
+        all_features = (d.getVarFlags("PACKAGECONFIG") or {}).keys()
+
+        if all_features:
+            enabled = set(packageconfig)
+            all_features_set = set(all_features)
+            disabled = all_features_set - enabled
+
+            for feature in sorted(all_features):
+                status = "enabled" if feature in enabled else "disabled"
+                build.build_parameter.append(
+                    oe.spdx30.DictionaryEntry(
+                        key=f"PACKAGECONFIG:{feature}",
+                        value=status
+                    )
+                )
+
+            bb.note(f"Added PACKAGECONFIG entries: {len(enabled)} enabled, {len(disabled)} disabled")
+
     oe.sbom30.write_recipe_jsonld_doc(d, build_objset, "recipes", deploydir)