From patchwork Thu Mar 12 15:38:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83259 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 206A11067056 for ; Thu, 12 Mar 2026 15:38:53 +0000 (UTC) Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24658.1773329931843881812 for ; Thu, 12 Mar 2026 08:38:52 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=WPi7J1In; spf=pass (domain: gmail.com, ip: 209.85.128.49, mailfrom: stondo@gmail.com) Received: by mail-wm1-f49.google.com with SMTP id 5b1f17b1804b1-4852f73d0a3so10914255e9.3 for ; Thu, 12 Mar 2026 08:38:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773329930; x=1773934730; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LnHu1dogLqpbSXYIDWE5Sv/OgVTOq5twkElAyshUXjc=; b=WPi7J1In7jJEl4QPR/Ypcc2mh+YrOT1tcJjs69ac413xGAkaJIEvOM4dtvi45PcecZ GiN/8yRV3hZrpR707VzpyO+pSqE1kWynBQSHw1OGu0oHMxvmYTz/lofb0yvh7JkNjExU CBkkm/smi6WvGhi+yPFcrDqTAWi0nyPBG+TZaH/zXho+Xr8t8M+gTr7w59Gwqj1jUZ9Z K1aJSGedIrronSj2jaiSY7YCFb2Zj3rthfSIG+L4hUgXSwsecBwknxzoMOUg5aCtd3kp Vkvvn/y0z4mBo+5N0pbEu9EIDF4IGL5parPfDGOaJP++jvz1t285V1qV89dKMvEbiRvM kvSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773329930; x=1773934730; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=LnHu1dogLqpbSXYIDWE5Sv/OgVTOq5twkElAyshUXjc=; b=vqAgskM7YTMx2D78aAjgVB9Gssf/I9uU7dnCR2xU/aC1lT8CCviKSsT1uj2E+mtA6J dE/uVod7gAxy5r8h1crEAptKLpo8pyvXm8keuokeVkpeZzS8+I4W3xKnsFa/922LNJFn HERKz6b+Q4a99ym8pPDsbvs/rN+snuDOMmasHJnTfJVD+Nc2XVqKqWsE0BNX6w2C0JwJ hciVJ242u0Wtvs5pUNl0bflAUyDczpzVlVs+OfbHq1MDl4NnXxh6XW4JRKkz/dUudiYb rFLNUMjPN5u0HcRYgHUrco9l6/atx33S9cOcMbza0EMoHCwQK7VYVkVBnpykzm7F4iIG yBxg== X-Gm-Message-State: AOJu0YwASPJqLjlUwyvjlbMbRLw25NupmbA12wFCFN02sghkazc+gmjb nV5HIchpn72441U+O1QVXhaRKi0skP8cAb2SbnY5ZqYcZEGvKO8+Uf9bWhFEtA== X-Gm-Gg: ATEYQzzF5PhVbAgY9TeKVwKtXPyDqi3ZKAakk3ZGDlKCM4T8BmxThbfGt062JSj5qN4 foha5FYRv5UxHwpHLwhPYCc2a+Yy+Cz9wdl4AT4JEhgnmoiwYAm6pM+nJIASbm5+kUgN3gAShJ+ hYOvk9pNJTiztJUEW64igkablu5K1LOZ3xV+rJic/JZpNJbcrw57iWvhgDie50+DDR48BWZTbnQ xHKVhe25FH1XoKDfQOZ/5qsFJAFLAAmnAFKNtZsCHaE0i6eY/T7TR5jWGnc4cmXvnjL3ZDvU7AW PC2rUR/sij0ZYE+JB5x7CSEfNc9rsN6Ip6FW3IwXFmMFLb3QBtmPz6toLp6NSC8jlkRMOVvfDCx +SI9nBfS7F7sVkAnWFQswsyGnm5HJQTt9590GxiSCL7loJ5HRMoHJXuMYUeIfBrM/0QjwrHWimT 7ua5RG6YOkE3dT4/K8Ya1szC/BvwogmaCCe+AlIAp1Hscjbw== X-Received: by 2002:a05:600c:1f10:b0:483:8062:b2f with SMTP id 5b1f17b1804b1-4854b0ae55amr127051135e9.6.1773329929670; Thu, 12 Mar 2026 08:38:49 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4854b0dcf2asm74857385e9.8.2026.03.12.08.38.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Mar 2026 08:38:48 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, Stefano Tondo Subject: [OE-core][PATCH v9 1/7] spdx30: Add configurable file exclusion pattern support Date: Thu, 12 Mar 2026 16:38:39 +0100 Message-ID: <20260312153845.164369-2-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260312153845.164369-1-stondo@gmail.com> References: <20260309132854.128375-1-stondo@gmail.com> <20260312153845.164369-1-stondo@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 12 Mar 2026 15:38:53 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232974 From: Stefano Tondo Add SPDX_FILE_EXCLUDE_PATTERNS variable that allows filtering files from SPDX output by regex matching. The variable accepts a space-separated list of Python regular expressions; files whose paths match any pattern (via re.search) are excluded. When empty (the default), no filtering is applied and all files are included, preserving existing behavior. This enables users to reduce SBOM size by excluding files that are not relevant for compliance (e.g., test files, object files, patches). Excluded files are tracked in a set returned from add_package_files() and passed to get_package_sources_from_debug(), which uses the set for precise cross-checking rather than re-evaluating patterns. Signed-off-by: Stefano Tondo --- meta/classes/spdx-common.bbclass | 7 ++++++ meta/lib/oe/spdx30_tasks.py | 38 +++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/meta/classes/spdx-common.bbclass b/meta/classes/spdx-common.bbclass index 3110230c9e..5cba52eedc 100644 --- a/meta/classes/spdx-common.bbclass +++ b/meta/classes/spdx-common.bbclass @@ -54,6 +54,13 @@ SPDX_CONCLUDED_LICENSE[doc] = "The license concluded by manual or external \ SPDX_MULTILIB_SSTATE_ARCHS ??= "${SSTATE_ARCHS}" +SPDX_FILE_EXCLUDE_PATTERNS ??= "" +SPDX_FILE_EXCLUDE_PATTERNS[doc] = "Space-separated list of Python regular \ + expressions to exclude files from SPDX output. Files whose paths match \ + any pattern (via re.search) will be filtered out. Defaults to empty \ + (no filtering). Example: \ + SPDX_FILE_EXCLUDE_PATTERNS = '\\.patch$ \\.diff$ /test/ \\.pyc$ \\.o$'" + python () { from oe.cve_check import extend_cve_status extend_cve_status(d) diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index 99f2892dfb..bc02b319c8 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -13,6 +13,7 @@ import oe.spdx30 import oe.spdx_common import oe.sdk import os +import re from contextlib import contextmanager from datetime import datetime, timezone @@ -154,13 +155,17 @@ def add_package_files( file_counter = 1 if not os.path.exists(topdir): bb.note(f"Skip {topdir}") - return spdx_files + return spdx_files, set() check_compiled_sources = d.getVar("SPDX_INCLUDE_COMPILED_SOURCES") == "1" if check_compiled_sources: compiled_sources, types = oe.spdx_common.get_compiled_sources(d) bb.debug(1, f"Total compiled files: {len(compiled_sources)}") + # File exclusion filtering + exclude_patterns = [re.compile(p) for p in (d.getVar("SPDX_FILE_EXCLUDE_PATTERNS") or "").split()] + excluded_files = set() + for subdir, dirs, files in os.walk(topdir, onerror=walk_error): dirs[:] = [d for d in dirs if d not in ignore_dirs] if subdir == str(topdir): @@ -174,6 +179,13 @@ def add_package_files( continue filename = str(filepath.relative_to(topdir)) + + # Apply file exclusion filtering + if exclude_patterns: + if any(p.search(filename) for p in exclude_patterns): + excluded_files.add(filename) + continue + file_purposes = get_purposes(filepath) # Check if file is compiled @@ -213,12 +225,15 @@ def add_package_files( bb.debug(1, "Added %d files to %s" % (len(spdx_files), objset.doc._id)) - return spdx_files + return spdx_files, excluded_files def get_package_sources_from_debug( - d, package, package_files, sources, source_hash_cache + d, package, package_files, sources, source_hash_cache, excluded_files=None ): + if excluded_files is None: + excluded_files = set() + def file_path_match(file_path, pkg_file): if file_path.lstrip("/") == pkg_file.name.lstrip("/"): return True @@ -251,6 +266,12 @@ def get_package_sources_from_debug( continue if not any(file_path_match(file_path, pkg_file) for pkg_file in package_files): + if file_path.lstrip("/") in excluded_files: + bb.debug( + 1, + f"Skipping debug source lookup for excluded file {file_path} in {package}", + ) + continue bb.fatal( "No package file found for %s in %s; SPDX found: %s" % (str(file_path), package, " ".join(p.name for p in package_files)) @@ -559,7 +580,7 @@ def create_spdx(d): bb.debug(1, "Adding source files to SPDX") oe.spdx_common.get_patched_src(d) - files = add_package_files( + files, _ = add_package_files( d, build_objset, spdx_workdir, @@ -775,7 +796,7 @@ def create_spdx(d): ) bb.debug(1, "Adding package files to SPDX for package %s" % pkg_name) - package_files = add_package_files( + package_files, excluded_files = add_package_files( d, pkg_objset, pkgdest / package, @@ -798,7 +819,8 @@ def create_spdx(d): if include_sources: debug_sources = get_package_sources_from_debug( - d, package, package_files, dep_sources, source_hash_cache + d, package, package_files, dep_sources, source_hash_cache, + excluded_files=excluded_files, ) debug_source_ids |= set( oe.sbom30.get_element_link_id(d) for d in debug_sources @@ -810,7 +832,7 @@ def create_spdx(d): if include_sources: bb.debug(1, "Adding sysroot files to SPDX") - sysroot_files = add_package_files( + sysroot_files, _ = add_package_files( d, build_objset, d.expand("${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}"), @@ -1196,7 +1218,7 @@ def create_image_spdx(d): image_filename = image["filename"] image_path = image_deploy_dir / image_filename if os.path.isdir(image_path): - a = add_package_files( + a, _ = add_package_files( d, objset, image_path, From patchwork Thu Mar 12 15:38:40 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83260 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 01DE01067055 for ; Thu, 12 Mar 2026 15:39:03 +0000 (UTC) Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24659.1773329933015674904 for ; Thu, 12 Mar 2026 08:38:53 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=HRu4/zO8; spf=pass (domain: gmail.com, ip: 209.85.128.41, mailfrom: stondo@gmail.com) Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-48538c5956bso11860775e9.0 for ; Thu, 12 Mar 2026 08:38:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773329931; x=1773934731; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VBYoliMG7reUnNZuziuNn9Wy67z+GP84Mrqbrk8JaKc=; b=HRu4/zO8+Jm8vFgw/8AQF29Gxy8bHwsHs22bqB2UsRfOprTg80IHyjzUVKm9xm354W XSPigVHJ1dFG19q155I8hd9dumioXtFGcUdwcS1tqP+x8xzE2O2uMKZPDb01xIm2VNCe LsJ9WS6x8iLFbXvUr3xkYFGVjp3Wv5rKyMz2rD6Io28Usavge4Etjb/6ieo4tTbTEXnn M4FUj8por9bmqaUZRorRXMde8srCBlj8B4eZ7X/7zGXazQCeGpwMmfD36sbjzs1qwU7C K9vHbq+ZgDF5GjOOZG+95gvcv29YwLtbqZxjTvfg85HVOE5mAWRba3a96FcNjK0mUNUb 7k+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773329931; x=1773934731; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=VBYoliMG7reUnNZuziuNn9Wy67z+GP84Mrqbrk8JaKc=; b=A6sW4zPBnreqHK+4won4zD1in0lWfH/XyZs7tIPwWz5vfypSwSA3MhrmCzSjpBn8xt 6htenRRDmmLN1N/LMU6ZAqgn4YyWI6pf9U96jeA2ieVPu7/QlDQtc9qxSe99+COhVQpi 0ponI5boAh11vyh8Zi9N0c4HZ5i07zGZlL5OdyhqbcaMSlq+cLsYT+zMLazQolDtLgGA njoWaZ8xIh7tKB8s8ufbphPp+zAYqASlQcTmaPSifPgFOecH00euBgHgxqqhVDuB8AII WBw1M3hE+T35b9A2ROpSjpGxYLzPUHfCGQ6uLWcR2qYKCKEdGmwcjFqw0CBECY+Z2qBi l5ug== X-Gm-Message-State: AOJu0Ywxvk1cBkSa2mbIWtu7ZZOTXqo0HltijwnThkN7aaQ/A+VOLxC7 EEpCYroqud6IHeT1fJkVi8+q7N0/Y5aeoHWPMZ1jJbg1Dg//L046jDjpmHjoRw== X-Gm-Gg: ATEYQzyw8LznJgjpbthIAZS1wJZji1V8ggqj0yjfEB5gr/x3OZ0Mf/T3qZTb1/ZoNaR k9yFbM+Bz+JEGhR4zCe7jgYFwRdEc3rattYhQVnfNADdILKXciCsMYvo9NZLCQ+djYjoII6K63/ VepwzEsf8XDmKER2VXwrNAcUmUDUBbRztlPY/He76YMFv7elZXw/xAGH24WW31kSSmpMpvCg3JZ Jd/8vpmanYsFqSRtWlgV7pqWnKLTR2SMlnJvJZ0Nij1TE/hoVXZaxwy8JDCMPFyf/SrXjlL5FI8 w3XrCObnw40clGMAcKHakslLQrhnvlJyWHwfZTWobCAalk168GTH6GNwkdfTncI9E9ZkZKfTSdh fF1cD2wYwBRztyscaNssojqYF7PAmIc1AUNE+GVPGUOljF6erSI1FtuArdDd+8eHXSN0UuWXD9j m0ZtAWd8bNt5DCdqBr+93oHdTGopzIjozwAdA= X-Received: by 2002:a05:600c:350e:b0:483:6d9e:e4f5 with SMTP id 5b1f17b1804b1-48555ac7160mr2223575e9.5.1773329930941; Thu, 12 Mar 2026 08:38:50 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4854b0dcf2asm74857385e9.8.2026.03.12.08.38.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Mar 2026 08:38:50 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, Stefano Tondo Subject: [OE-core][PATCH v9 2/7] spdx30: Add supplier support for image and SDK SBOMs Date: Thu, 12 Mar 2026 16:38:40 +0100 Message-ID: <20260312153845.164369-3-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260312153845.164369-1-stondo@gmail.com> References: <20260309132854.128375-1-stondo@gmail.com> <20260312153845.164369-1-stondo@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 12 Mar 2026 15:39:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232975 From: Stefano Tondo Add SPDX_IMAGE_SUPPLIER and SPDX_SDK_SUPPLIER variables that allow setting a supplier agent on image and SDK SBOM root elements using the suppliedBy property. These follow the existing SPDX_PACKAGE_SUPPLIER pattern and use the standard agent variable system to define supplier information. Signed-off-by: Stefano Tondo Reviewed-by: Joshua Watt --- meta/classes/create-spdx-3.0.bbclass | 10 ++++++++++ meta/lib/oe/spdx30_tasks.py | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index d4575d61c4..def2dacbc3 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -124,6 +124,16 @@ SPDX_ON_BEHALF_OF[doc] = "The base variable name to describe the Agent on who's SPDX_PACKAGE_SUPPLIER[doc] = "The base variable name to describe the Agent who \ is supplying artifacts produced by the build" +SPDX_IMAGE_SUPPLIER[doc] = "The base variable name to describe the Agent who \ + is supplying the image SBOM. The supplier will be set on all root elements \ + of the image SBOM using the suppliedBy property. If not set, no supplier \ + information will be added to the image SBOM." + +SPDX_SDK_SUPPLIER[doc] = "The base variable name to describe the Agent who \ + is supplying the SDK SBOM. The supplier will be set on all root elements \ + of the SDK SBOM using the suppliedBy property. If not set, no supplier \ + information will be added to the SDK SBOM." + SPDX_PACKAGE_VERSION ??= "${PV}" SPDX_PACKAGE_VERSION[doc] = "The version of a package, software_packageVersion \ in software_Package" diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index bc02b319c8..8aaafea616 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -1316,6 +1316,16 @@ def create_image_sbom_spdx(d): objset, sbom = oe.sbom30.create_sbom(d, image_name, root_elements) + # Set supplier on root elements if SPDX_IMAGE_SUPPLIER is defined + supplier = objset.new_agent("SPDX_IMAGE_SUPPLIER", add=False) + if supplier is not None: + supplier_id = supplier if isinstance(supplier, str) else supplier._id + if not isinstance(supplier, str): + objset.add(supplier) + for elem in sbom.rootElement: + if hasattr(elem, "suppliedBy"): + elem.suppliedBy = supplier_id + oe.sbom30.write_jsonld_doc(d, objset, spdx_path) def make_image_link(target_path, suffix): @@ -1427,6 +1437,16 @@ def create_sdk_sbom(d, sdk_deploydir, spdx_work_dir, toolchain_outputname): d, toolchain_outputname, sorted(list(files)), [rootfs_objset] ) + # Set supplier on root elements if SPDX_SDK_SUPPLIER is defined + supplier = objset.new_agent("SPDX_SDK_SUPPLIER", add=False) + if supplier is not None: + supplier_id = supplier if isinstance(supplier, str) else supplier._id + if not isinstance(supplier, str): + objset.add(supplier) + for elem in sbom.rootElement: + if hasattr(elem, "suppliedBy"): + elem.suppliedBy = supplier_id + oe.sbom30.write_jsonld_doc( d, objset, sdk_deploydir / (toolchain_outputname + ".spdx.json") ) From patchwork Thu Mar 12 15:38:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83261 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5BED01067058 for ; Thu, 12 Mar 2026 15:39:03 +0000 (UTC) Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24809.1773329934152694100 for ; Thu, 12 Mar 2026 08:38:54 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=TEn/9DWc; spf=pass (domain: gmail.com, ip: 209.85.128.50, mailfrom: stondo@gmail.com) Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-48334ee0aeaso10973705e9.1 for ; Thu, 12 Mar 2026 08:38:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773329932; x=1773934732; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mONOHvk/OmqCLm44EETWVV+hfJKTNVXf0N35fgzzKWM=; b=TEn/9DWcZoCY/NBhAsnTgeXJqgP60EzlXaZXcukAWMwV7HL13QFg+tutsK9QCor13T hT8tj2EnRuRaGKWjoFSn8FdfnQJevMudV7zkwPyqAk3I6WuOHYXuqijgDcusYoyqSjI+ jIrCtteifYMrp/6vLlUH8QHmvNfu9cyNbgFN06AYXOut5VXEVQGGU7x81/MW6CiRh6yB 57omczWO6E8f7Fai2fXvtXOO3CPp4yHRhdVOASiuyQjmeKK5mlxf8X2w+Xkk4DAl7eBT Ehfp2wAzCDDG7NENUBTB7NdtNtSEQ3JGMmTzT1S8//vP20KKRHrscY5lw74x0HCNFMCV Znsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773329932; x=1773934732; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=mONOHvk/OmqCLm44EETWVV+hfJKTNVXf0N35fgzzKWM=; b=ap6+eq4fuDv5Quk9tuqcn4zFC53b7VxR90Nb9ny5Mlmmeu0uu/zPIv9z5kAV6umm2n Qkqp25zbpd1JiiQKBwiJl5l8zfchswiS7Zrv7xCkQBUkSlLforMt8oET40HwbSVKtGxT /5GiZ+CSkEhYm/HzIhVZmUX+LHXn4gGeCaB14oyBKlw4CU93dBdmLDbQX8fNxk/yOt9T F0cceDx6wt3w7uqhdutgeNtrqOa/ulfBTvMUy4URifoltq6KyI71pSlycGnT8KAz31sl 0r0627JgbAVRqbxXSK0sTKTbTjMCbfR4yNxIRJA3ymssumlEM7+QdrMHJKwRMazcPn5w dhRg== X-Gm-Message-State: AOJu0YyDck12pAXRDd7bIgeXX7nIx48W5FkG4jNw78VegPGoFy9ElzXY DC4w+kkGwpGf3BC1WhaSSl5WG/a4hmanZjEt4S3lHwLKyhKcFU6t5WN3K/Vnlg== X-Gm-Gg: ATEYQzxY2tlNOuqJ9taoanzE/QXltkh3gaDPLCTKhaAN7jpE3+5HjztWr2mT/tRBQU6 kpEGmUNL9qJ10Tw4LIvzGDNClGz1uh+rqRPss7kjZVDE5gdS68wWV0N16VqlWcM03km2Rek5Bda 34joVRgO0tk/UwB4LaRF/IdHUfHiV0k2/OpkGDSVbqHUEYqvJ7sUVTD7nouH6iNQSDmH8+P6v2S 1OBRncOKYYXwVz6cQDkHr785ZmmJnMoDpVimV5Gehryfjoo5pK2F3PGJXrQEPmWnTiZugQpF98J gsjWSl7UWZ9sn+msxADZ65j3XAM6ccy418aS76CPrGb3lmiENcu+8rnQHQ2GVBbtGd0Mh1SpN0N KJv0Am+FYSTjgfG0SX17cREBc92yB1buC054O0CW6KkbbzktYHYudly2FvFWG6ndi6jgrumily/ XbfgWyJyIolPHUpDKz0f0brXy/hTM+8YhrJ/g= X-Received: by 2002:a05:600c:4fc9:b0:483:b505:9db7 with SMTP id 5b1f17b1804b1-4854b136cd2mr121062935e9.32.1773329932088; Thu, 12 Mar 2026 08:38:52 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4854b0dcf2asm74857385e9.8.2026.03.12.08.38.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Mar 2026 08:38:51 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, Stefano Tondo Subject: [OE-core][PATCH v9 3/7] spdx30: Add ecosystem-specific PURL generation via bbclasses Date: Thu, 12 Mar 2026 16:38:41 +0100 Message-ID: <20260312153845.164369-4-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260312153845.164369-1-stondo@gmail.com> References: <20260309132854.128375-1-stondo@gmail.com> <20260312153845.164369-1-stondo@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 12 Mar 2026 15:39:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232976 From: Stefano Tondo Have each ecosystem bbclass set its own Package URL by prepending to SPDX_PACKAGE_URLS, rather than detecting inherited classes from the SPDX code. This follows the principle that each class should know how to describe itself. The following bbclasses now generate ecosystem PURLs: - pypi.bbclass: pkg:pypi/@PV - npm.bbclass: pkg:npm/@PV - cargo_common.bbclass: pkg:cargo/@PV - go-mod.bbclass: pkg:golang/@PV - cpan.bbclass: pkg:cpan/@PV Additional ecosystems (nuget, maven, dotnet) can follow the same pattern in their respective layers. Signed-off-by: Stefano Tondo --- meta/classes-recipe/cargo_common.bbclass | 3 +++ meta/classes-recipe/cpan.bbclass | 11 +++++++++++ meta/classes-recipe/go-mod.bbclass | 3 +++ meta/classes-recipe/npm.bbclass | 7 +++++++ meta/classes-recipe/pypi.bbclass | 3 +++ 5 files changed, 27 insertions(+) diff --git a/meta/classes-recipe/cargo_common.bbclass b/meta/classes-recipe/cargo_common.bbclass index bc44ad7918..e884b344ef 100644 --- a/meta/classes-recipe/cargo_common.bbclass +++ b/meta/classes-recipe/cargo_common.bbclass @@ -240,3 +240,6 @@ EXPORT_FUNCTIONS do_configure # https://github.com/rust-lang/libc/issues/3223 # https://github.com/rust-lang/libc/pull/3175 INSANE_SKIP:append = " 32bit-time" + +# Generate ecosystem-specific Package URL for SPDX +SPDX_PACKAGE_URLS:prepend = "pkg:cargo/${BPN}@${PV} " diff --git a/meta/classes-recipe/cpan.bbclass b/meta/classes-recipe/cpan.bbclass index bb76a5b326..355e7e6adf 100644 --- a/meta/classes-recipe/cpan.bbclass +++ b/meta/classes-recipe/cpan.bbclass @@ -68,4 +68,15 @@ cpan_do_install () { done } +# Generate ecosystem-specific Package URL for SPDX +def cpan_spdx_name(d): + bpn = d.getVar('BPN') + if bpn.startswith('perl-'): + return bpn[5:] + elif bpn.startswith('libperl-'): + return bpn[8:] + return bpn + +SPDX_PACKAGE_URLS:prepend = "pkg:cpan/${@cpan_spdx_name(d)}@${PV} " + EXPORT_FUNCTIONS do_configure do_compile do_install diff --git a/meta/classes-recipe/go-mod.bbclass b/meta/classes-recipe/go-mod.bbclass index a15dda8f0e..344712b193 100644 --- a/meta/classes-recipe/go-mod.bbclass +++ b/meta/classes-recipe/go-mod.bbclass @@ -32,3 +32,6 @@ do_compile[dirs] += "${B}/src/${GO_WORKDIR}" # Make go install unpack the module zip files in the module cache directory # before the license directory is polulated with license files. addtask do_compile before do_populate_lic + +# Generate ecosystem-specific Package URL for SPDX +SPDX_PACKAGE_URLS:prepend = "pkg:golang/${GO_IMPORT}@${PV} " diff --git a/meta/classes-recipe/npm.bbclass b/meta/classes-recipe/npm.bbclass index 344e8b4bec..a0adcfa240 100644 --- a/meta/classes-recipe/npm.bbclass +++ b/meta/classes-recipe/npm.bbclass @@ -354,4 +354,11 @@ FILES:${PN} += " \ ${nonarch_libdir} \ " +# Generate ecosystem-specific Package URL for SPDX +def npm_spdx_name(d): + bpn = d.getVar('BPN') + return bpn[5:] if bpn.startswith('node-') else bpn + +SPDX_PACKAGE_URLS:prepend = "pkg:npm/${@npm_spdx_name(d)}@${PV} " + EXPORT_FUNCTIONS do_configure do_compile do_install diff --git a/meta/classes-recipe/pypi.bbclass b/meta/classes-recipe/pypi.bbclass index 1372d85e8d..fd5cd7af95 100644 --- a/meta/classes-recipe/pypi.bbclass +++ b/meta/classes-recipe/pypi.bbclass @@ -55,3 +55,6 @@ UPSTREAM_CHECK_URI ?= "https://pypi.org/simple/${@pypi_normalize(d)}/" UPSTREAM_CHECK_REGEX ?= "${UPSTREAM_CHECK_PYPI_PACKAGE}-(?P(\d+[\.\-_]*)+).(tar\.gz|tgz|zip|tar\.bz2)" CVE_PRODUCT ?= "python:${PYPI_PACKAGE}" + +# Generate ecosystem-specific Package URL for SPDX +SPDX_PACKAGE_URLS:prepend = "pkg:pypi/${@pypi_normalize(d)}@${PV} " From patchwork Thu Mar 12 15:38:42 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83264 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76888106705A for ; Thu, 12 Mar 2026 15:39:03 +0000 (UTC) Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24662.1773329936329513915 for ; Thu, 12 Mar 2026 08:38:56 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=gf141tqf; spf=pass (domain: gmail.com, ip: 209.85.128.42, mailfrom: stondo@gmail.com) Received: by mail-wm1-f42.google.com with SMTP id 5b1f17b1804b1-48534e9076fso10096155e9.0 for ; Thu, 12 Mar 2026 08:38:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773329934; x=1773934734; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=iw9KMhneNLxFC5Oi4hbEI3PniGR7wgbL42SCaPNNwIk=; b=gf141tqfLOHQzTN1gTZCCbiaq71Pfp+wTPiCCAqMyCc60XvEY01JrtvJsfqUOInPZD EClwXZwxFLl6rOiJfPigs5UpnARHAfrelpl8x8vAx5Z6QmAgzwLNP+Wl58m9EVic5lJS MT63nPTapzsXl+ehMu9/teOIwMFIA5NBsxgdjdDJVsD1tzVkxcDaRXBrixoFKjcGSu/c yfR2GP16wcEBo/sYULP3lQi36/lDTk56aZzd4JgNix9y0S/JQkMToybsi6urbMet+3VQ 60NsNt0p08EDsMoTyul6nQvo0h0AAusywZibfK0JQrmF8GxIjwVgr7ZlNDwKOArwAvl9 QBQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773329934; x=1773934734; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=iw9KMhneNLxFC5Oi4hbEI3PniGR7wgbL42SCaPNNwIk=; b=RaTMy8tUiYuwPxf8zWJZlLlh2VQiNZssrTKnnbT77QOhvtRAnlbd/gsuWaq7A4T9yE 7eCCiDGPSUy2OZ69GhWBLczsZwTDliiOtDg2neVG9sVBYuC3E6xokntR/U4lGURHHLSP Sn6NKoYYH2zhfc0s3FkcFzjvEB0NmvOrgbKnvyXTUlGI8uo7LdQCAmNEFKgYL8ECtXst uxh+sSOTHRXzxoZvACnoY7R/+J8d02O6u6eGlWX8J6yR+yDZzvA5H2xHTtgqaBM/GSpK O/eDupw22y1SDjYVe4Iw4QZY5hzVdAWSga/wb2WyYfBQYQdQdufroy8UEnxJY5KsjVib RH5Q== X-Gm-Message-State: AOJu0YzeenGW7nPvu1xIWjFo0MyfUq14iQVNan9ME94CX4B26NGFR538 CmfNO6sZV4tBlfRfm2emH6sZiZhc1vWqLSkoPzn7xQfFcwEVohi4TbvudQpNBw== X-Gm-Gg: ATEYQzwVdM3Iw8qq8RvC5V9+40a0htZcJDoiywX2HIox8VwAFQ6eVIxOim/yuROJvYz YVEeih95VSqg21NoTGxvofEJxayH7kA4KPhAH7wdYVJvPzje5ccY0knfrO7cvtjrhs/dHw+A08T PimTnkxVscvCEBTmfgqjMAQwO/g0zoqI3g/NPtJx9co3Fsf/auWwSBm+1NqgL3bS+MzepzqaOxO TAM1dvp8eIBch/ZSVguTx4K225XVtXMCadZaB0zyF91DQ/XRwkoHxMRwXq8CplM5+I1KME/IsZL zn4pnJ60NvdhKE4Ez+iN3ihaRt/OZ0okE1QHq5EDOGByxZFE9hb7S2igmWDEUaXjNPDcZ2Ot2Ww Au+IMHStgFcRVqFcfUTadzfX8OoF7i7XC9izz4v38Z4vesBy1Hyu1RRVAH1kOlz47iqFJOoB9dd mxZ4MH6eo5dUwdo4Yf0oNxMCv+Fs/UvEfds/Y= X-Received: by 2002:a05:600c:19cf:b0:485:49c5:8eb7 with SMTP id 5b1f17b1804b1-4854b1012b7mr113347445e9.22.1773329933877; Thu, 12 Mar 2026 08:38:53 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4854b0dcf2asm74857385e9.8.2026.03.12.08.38.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Mar 2026 08:38:52 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, Stefano Tondo Subject: [OE-core][PATCH v9 4/7] spdx30: Enrich source downloads with version and PURL Date: Thu, 12 Mar 2026 16:38:42 +0100 Message-ID: <20260312153845.164369-5-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260312153845.164369-1-stondo@gmail.com> References: <20260309132854.128375-1-stondo@gmail.com> <20260312153845.164369-1-stondo@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 12 Mar 2026 15:39:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232977 From: Stefano Tondo Add version extraction, PURL generation, and external references to source download packages in SPDX 3.0 SBOMs: - Extract version from SRCREV for Git sources (full SHA-1) - Generate PURLs for Git sources on github.com by default - Support custom mappings via SPDX_GIT_PURL_MAPPINGS variable (format: "domain:purl_type", split(':', 1) for parsing) - Use ecosystem PURLs from SPDX_PACKAGE_URLS for non-Git - Add VCS external references for Git downloads - Add distribution external references for tarball downloads - Parse Git URLs using urllib.parse - Extract logic into _generate_git_purl() and _enrich_source_package() helpers For non-Git sources, version is not set from PV since the recipe version does not necessarily reflect the version of individual downloaded files. Ecosystem PURLs (which include version) from SPDX_PACKAGE_URLS are still used when available. The SPDX_GIT_PURL_MAPPINGS variable allows configuring PURL generation for self-hosted Git services (e.g., GitLab). github.com is always mapped to pkg:github by default. Signed-off-by: Stefano Tondo --- meta/classes/create-spdx-3.0.bbclass | 7 ++ meta/lib/oe/spdx30_tasks.py | 117 +++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index def2dacbc3..9e912b34e1 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -152,6 +152,13 @@ SPDX_PACKAGE_URLS[doc] = "A space separated list of Package URLs (purls) for \ Override this variable to replace the default, otherwise append or prepend \ to add additional purls." +SPDX_GIT_PURL_MAPPINGS ??= "" +SPDX_GIT_PURL_MAPPINGS[doc] = "A space separated list of domain:purl_type \ + mappings to configure PURL generation for Git source downloads. \ + For example, "gitlab.example.com:pkg:gitlab" maps repositories hosted \ + on gitlab.example.com to the pkg:gitlab PURL type. \ + github.com is always mapped to pkg:github by default." + IMAGE_CLASSES:append = " create-spdx-image-3.0" SDK_CLASSES += "create-spdx-sdk-3.0" diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index 8aaafea616..5639137520 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -14,6 +14,7 @@ import oe.spdx_common import oe.sdk import os import re +import urllib.parse from contextlib import contextmanager from datetime import datetime, timezone @@ -378,6 +379,120 @@ def collect_dep_sources(dep_objsets, dest): index_sources_by_hash(e.to, dest) +def _generate_git_purl(d, download_location, srcrev): + """Generate a Package URL for a Git source from its download location. + + Parses the Git URL to identify the hosting service and generates the + appropriate PURL type. Supports github.com by default and custom + mappings via SPDX_GIT_PURL_MAPPINGS. + + Returns the PURL string or None if no mapping matches. + """ + if not download_location or not download_location.startswith('git+'): + return None + + git_url = download_location[4:] # Remove 'git+' prefix + + # Default handler: github.com + git_purl_handlers = { + 'github.com': 'pkg:github', + } + + # Custom PURL mappings from SPDX_GIT_PURL_MAPPINGS + # Format: "domain1:purl_type1 domain2:purl_type2" + custom_mappings = d.getVar('SPDX_GIT_PURL_MAPPINGS') + if custom_mappings: + for mapping in custom_mappings.split(): + parts = mapping.split(':', 1) + if len(parts) == 2: + git_purl_handlers[parts[0]] = parts[1] + bb.debug(2, f"Added custom Git PURL mapping: {parts[0]} -> {parts[1]}") + else: + bb.warn(f"Invalid SPDX_GIT_PURL_MAPPINGS entry: {mapping} (expected format: domain:purl_type)") + + try: + parsed = urllib.parse.urlparse(git_url) + except Exception: + return None + + hostname = parsed.hostname + if not hostname: + return None + + for domain, purl_type in git_purl_handlers.items(): + if hostname == domain: + path = parsed.path.strip('/') + path_parts = path.split('/') + if len(path_parts) >= 2: + owner = path_parts[0] + repo = path_parts[1].replace('.git', '') + return f"{purl_type}/{owner}/{repo}@{srcrev}" + break + + return None + + +def _enrich_source_package(d, dl, fd, file_name, primary_purpose): + """Enrich a source download package with version, PURL, and external refs. + + Extracts version from SRCREV for Git sources, generates PURLs for + known hosting services, and adds external references for VCS, + distribution URLs, and homepage. + """ + version = None + purl = None + + if fd.type == "git": + # Use full SHA-1 from fd.revision + srcrev = getattr(fd, 'revision', None) + if srcrev and srcrev not in {'${AUTOREV}', 'AUTOINC', 'INVALID'}: + version = srcrev + + # Generate PURL for Git hosting services + download_location = getattr(dl, 'software_downloadLocation', None) + if version and download_location: + purl = _generate_git_purl(d, download_location, version) + else: + # Use ecosystem PURL from SPDX_PACKAGE_URLS if available + package_urls = (d.getVar('SPDX_PACKAGE_URLS') or '').split() + for url in package_urls: + if not url.startswith('pkg:yocto'): + purl = url + break + + if version: + dl.software_packageVersion = version + + if purl: + dl.software_packageUrl = purl + + # Add external references + download_location = getattr(dl, 'software_downloadLocation', None) + if download_location and isinstance(download_location, str): + dl.externalRef = dl.externalRef or [] + + if download_location.startswith('git+'): + # VCS reference for Git repositories + git_url = download_location[4:] + if '@' in git_url: + git_url = git_url.split('@')[0] + + dl.externalRef.append( + oe.spdx30.ExternalRef( + externalRefType=oe.spdx30.ExternalRefType.vcs, + locator=[git_url], + ) + ) + elif download_location.startswith(('http://', 'https://', 'ftp://')): + # Distribution reference for tarball/archive downloads + dl.externalRef.append( + oe.spdx30.ExternalRef( + externalRefType=oe.spdx30.ExternalRefType.altDownloadLocation, + locator=[download_location], + ) + ) + + def add_download_files(d, objset): inputs = set() @@ -441,6 +556,8 @@ def add_download_files(d, objset): ) ) + _enrich_source_package(d, dl, fd, file_name, primary_purpose) + if fd.method.supports_checksum(fd): # TODO Need something better than hard coding this for checksum_id in ["sha256", "sha1"]: From patchwork Thu Mar 12 15:38:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83262 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8F620106705C for ; Thu, 12 Mar 2026 15:39:03 +0000 (UTC) Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24664.1773329937720964021 for ; Thu, 12 Mar 2026 08:38:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=nChQGFYo; spf=pass (domain: gmail.com, ip: 209.85.221.50, mailfrom: stondo@gmail.com) Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-439aeed8a5bso1247499f8f.3 for ; Thu, 12 Mar 2026 08:38:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773329936; x=1773934736; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zYp17iBPaoPjczXO5fSA5dfgjKxYkDwyVIKWeVby3wk=; b=nChQGFYoU1itVl3Xk2Up6BBydMlbSeoyHmu8MZrFXSVT7KmEaVjAzdoq91gog6JoGw pqR0cKUmXERLZ6QZHK1orEoVIDvKMYzYFnqUJHNVYu62B83fwbVhw29WM171j11MqY8G SvLBerRLMo90g+JJS5ah1Suc+t8fjBpQVGRyeUe6xU35ayN+VHNTufQX1scKt3vW7oJ/ oXq20XQ572wYQ2rM0wQ8YSMk5fBFcLXhqjm5NWV+iIfuVAIyG0DQJILhDdoJFQ6NZWwd GAugMQFmrlAVJnUJtf+M3eFGGkQUCLkjJQ4AiGpAVjxwiOcrL0SAADJMxRI2dgwiLNiB IoKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773329936; x=1773934736; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=zYp17iBPaoPjczXO5fSA5dfgjKxYkDwyVIKWeVby3wk=; b=JI53KridVrSPp28PfhiQVdlB8SnTom1KGzr/pPAczPiFiTdWfuOTiudCHw2lFvAP5/ ifxJwCRoJq4Kun02lE8MDSUr8fpbj/jSKjTihw9RtMCZRoQ9UViT/sMyIp2/0eGX4kek xvqjTVMQHeLSD1hpPTdAQwr25iTh/W6xcNRp65U+k+Eh+VODaRxEBlGHYRVEByahrvE4 /u5ImCZzRyl0xjzQoFQNc7T+pchpT1frVbk0uSgrMA/5UO6QIiYf3DcQiMKvFTOFr/WJ B7GSGzElB7yadG53nOyvKLtIciWJ4RiRuOAbP7dZSXdyIuG9ZWBXx0kdmiHKcc0x7e+j ZCrg== X-Gm-Message-State: AOJu0YzZvAynY+5OXFrXcxBEF+amQiC2O7YWvCjDjp2J4TJAVjhZy4lV m58BZ6XMgIupYdPgYi+f3VQ9NXOx+M5NZXfp7YApIwX70v8gIZ3G9tKSqaQ6uA== X-Gm-Gg: ATEYQzy4PpziG2sLnFgt2PWXFxEBUGtaTKpmqpMVe7YWGomBPYyiQUb3uiPC8xe9Jof 6LI2M92ErRkOlrp+o354Gt0+aGKuvUldcLfgtsIe4IRWvsumCqTl+9itC50LFH4PpLfYjPvmGUo 2gQYnqldKE/QrzkZRfUWEFEfuUgfPvJwFRgfoD8K5PB/LWLT1DE8I+EbhrdZaFu/K1Kj9kDqqX8 4Ouq1ezr2Ph48rWuejbTNCtaefEArSL9xEMLC/ltVGjguSIg93bLkmBc/0VXya5G0+Mk7gJ77KB m37Vm5BWxFA9Yacqj0DdyvXHUeby2VJ0tQI8jJJa+p/KLQPYcj77qnV9IJlzxnb5tfPkZPH8AVv gKmww+CVMlqdsf+CARRG3c5dlvdWbm6yTWcvohcq4W7FmIo+6etUbV7qQVTH5IhMHyeFdm1Q4oo GsG9iohmsgphr87vntOw5+ZgNeyhy19qlN9bw= X-Received: by 2002:a05:600c:46d2:b0:485:38fc:7080 with SMTP id 5b1f17b1804b1-4854b10ef23mr107245975e9.28.1773329935404; Thu, 12 Mar 2026 08:38:55 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4854b0dcf2asm74857385e9.8.2026.03.12.08.38.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Mar 2026 08:38:54 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, Stefano Tondo Subject: [OE-core][PATCH v9 5/7] oeqa/selftest: Add tests for source download enrichment Date: Thu, 12 Mar 2026 16:38:43 +0100 Message-ID: <20260312153845.164369-6-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260312153845.164369-1-stondo@gmail.com> References: <20260309132854.128375-1-stondo@gmail.com> <20260312153845.164369-1-stondo@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 12 Mar 2026 15:39:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232978 From: Stefano Tondo Add two new SPDX 3.0 selftest cases: test_download_location_defensive_handling: Verifies SPDX generation succeeds for recipes with tarball sources and that external references are properly structured (ExternalRef locator is a list of strings per SPDX 3.0 spec). test_version_extraction_patterns: Verifies that version extraction works correctly and all source packages have proper version strings containing digits. These tests validate the source download enrichment added in the previous commit. Signed-off-by: Stefano Tondo --- meta/lib/oeqa/selftest/cases/spdx.py | 71 +++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/meta/lib/oeqa/selftest/cases/spdx.py b/meta/lib/oeqa/selftest/cases/spdx.py index 41ef52fce1..859667dd6b 100644 --- a/meta/lib/oeqa/selftest/cases/spdx.py +++ b/meta/lib/oeqa/selftest/cases/spdx.py @@ -392,7 +392,7 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): def test_packageconfig_spdx(self): objset = self.check_recipe_spdx( "tar", - "{DEPLOY_DIR_SPDX}/{SSTATE_PKGARCH}/recipes/recipe-tar.spdx.json", + "{DEPLOY_DIR_SPDX}/{SSTATE_PKGARCH}/recipes/build-tar.spdx.json", extraconf="""\ SPDX_INCLUDE_PACKAGECONFIG = "1" """, @@ -414,3 +414,72 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): value, ["enabled", "disabled"], f"Unexpected PACKAGECONFIG value '{value}' for {key}" ) + + def test_download_location_defensive_handling(self): + """Test that download_location handling is defensive. + + Verifies SPDX generation succeeds and external references are + properly structured when download_location retrieval works. + """ + objset = self.check_recipe_spdx( + "m4", + "{DEPLOY_DIR_SPDX}/{SSTATE_PKGARCH}/recipes/build-m4.spdx.json", + ) + + found_external_refs = False + for pkg in objset.foreach_type(oe.spdx30.software_Package): + if pkg.externalRef: + found_external_refs = True + for ref in pkg.externalRef: + self.assertIsNotNone(ref.externalRefType) + self.assertIsNotNone(ref.locator) + self.assertGreater(len(ref.locator), 0, "Locator should have at least one entry") + for loc in ref.locator: + self.assertIsInstance(loc, str) + break + + self.logger.info( + f"External references {'found' if found_external_refs else 'not found'} " + f"in SPDX output (defensive handling verified)" + ) + + def test_version_extraction_patterns(self): + """Test that version extraction works for various package formats. + + Verifies that version patterns correctly extract versions from + tarball sources and that all packages have proper version strings. + """ + objset = self.check_recipe_spdx( + "tar", + "{DEPLOY_DIR_SPDX}/{SSTATE_PKGARCH}/recipes/build-tar.spdx.json", + ) + + # Collect all packages with versions + packages_with_versions = [] + for pkg in objset.foreach_type(oe.spdx30.software_Package): + if pkg.software_packageVersion: + packages_with_versions.append((pkg.name, pkg.software_packageVersion)) + + self.assertGreater( + len(packages_with_versions), 0, + "Should find packages with extracted versions" + ) + + self.logger.info(f"Found {len(packages_with_versions)} packages with versions") + + # Log some examples for debugging + for name, version in packages_with_versions[:5]: + self.logger.info(f" {name}: {version}") + + # Verify that versions follow expected patterns + for name, version in packages_with_versions: + # Version should not be empty + self.assertIsNotNone(version) + self.assertNotEqual(version, "") + + # Version should contain digits + self.assertRegex( + version, + r'\d', + f"Version '{version}' for package '{name}' should contain digits" + ) From patchwork Thu Mar 12 15:38:44 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83263 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A438A106705E for ; Thu, 12 Mar 2026 15:39:03 +0000 (UTC) Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24811.1773329939135434886 for ; Thu, 12 Mar 2026 08:38:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=O0Nzflas; spf=pass (domain: gmail.com, ip: 209.85.221.51, mailfrom: stondo@gmail.com) Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-439c5b40f60so1071540f8f.0 for ; Thu, 12 Mar 2026 08:38:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773329937; x=1773934737; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=F2ST2hgit7R7JDdz4yfdMgwx/zS66swVCh9Bow1twfw=; b=O0NzflasT8k8A20ZZ+jzVuURrUceYKoNjPV/wOKsxojCyhhXULmc/rKIcAGQ+22b8h QEJTaKJtmaxVnot1VIf2yCKWfX8AHpM7+Nwlv+4T3+1QZ2Wbd1NMjttyGjjViwunp0q6 G2srOZx+vyuAusZIIoTsReS0FF0DDOndjyuXuaRwsDMdBgf5bUN1hEH7FfvAgfEgEx+Y obnLkiUx4OE2zWRnOcg9Ljb4hfNvoqiUrfbjMGOgDYUmw9zXJj4ztqFyNVf1kna0wVrH HjTF2VhO3Hyj2x3u+VnEZLCwkKvdXRJWMF901cC3CzFPgBAA+BtI0lnPVJTleTuhVIm+ 6jfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773329937; x=1773934737; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=F2ST2hgit7R7JDdz4yfdMgwx/zS66swVCh9Bow1twfw=; b=N1e+yXqCt+kVQZahEcHpM0+AkrOi9503uvpCFU0YV7e4VWf8IbmU2sp0YePESkJmzE 2T4wNYzIOINOnqy7G8tsRM7GDCmpziNJ+npwfYGzjLgIAhaq7aeeWrhFZVHvQ3jU/slq vWRYcUvORrLz+5DjSrze4ZljW3cNpVXyIy31nuIA9GPECUrXIceIRH6Zxxmc+Vc5DUiw KQY6v9/ioB9zrUrmsIvWvuQtzFtYJV9pclnqGwS2d0LKC+hCjGpGLpcZTeGVz04BIKux v67kBVcEorvH45ElnJBtCqNvnduFiI7A4P5xuTdnwitMNe50zLxp4ZKp+C+ybudWL++u 3JhA== X-Gm-Message-State: AOJu0Ywt8rvqUfYKLjXFMohuIerAS4XkRs+IRI6Soz/x9xrT2vBbo3N9 a5oRXKrItm4wSqAI9zS6FzuGi3ZUJiNDwlARxvvU7rpLa7LS0Q0XRjlmJqjQLg== X-Gm-Gg: ATEYQzzHd0HpOkoEbOlkBnEFsP/LBxfl7oqOhhx7x5lg1Uf/aa4/yIezCKYfIe3c1UV Y60hFi5Sp6z1otLHAPdhQfuhiRqw8q9NdHVM2UDvvM3MmQFMM4zcYlE6rYpwCDQ9xjWbmyPDolQ Q4IDlkp/HI23Vb712kDcFk8w/3LDYCpUxLZmthKVQWuD/mZuCx7wwXoldST99/7OxovIpKI8lbb W8qZfyjHBKFUpigFYfGGuw4tfyaIn88zT8LaA9jND9g55rssMn1FmkduxwnZWcrcZscecmEVFX0 MLS9alkqvN/BM9w7Bo1ToTc+NlfmxdfGDoTbpflrVwjGnl2BKEDAT7o7zMuXdO6BHa/tRFL3JPf ihbUcMkWgTi/I3sNFOiaXZFdY7KOk3DxFqNQVfqL47TqVXFe7auQhZx1rKfRbcG1C2rTGcGmNdB +bzA4x9oj6UYjr2p9fYE7OHcy3c7OJh0kxY5k= X-Received: by 2002:a05:600c:3106:b0:485:39d1:b500 with SMTP id 5b1f17b1804b1-4854b10576cmr141380595e9.16.1773329936769; Thu, 12 Mar 2026 08:38:56 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4854b0dcf2asm74857385e9.8.2026.03.12.08.38.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Mar 2026 08:38:55 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, Stefano Tondo Subject: [OE-core][PATCH v9 6/7] cve_check: Escape special characters in CPE 2.3 strings Date: Thu, 12 Mar 2026 16:38:44 +0100 Message-ID: <20260312153845.164369-7-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260312153845.164369-1-stondo@gmail.com> References: <20260309132854.128375-1-stondo@gmail.com> <20260312153845.164369-1-stondo@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 12 Mar 2026 15:39:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232979 From: Stefano Tondo CPE 2.3 formatted string binding (cpe:2.3:...) requires backslash escaping for special meta-characters per NISTIR 7695. Characters like '++' and ':' in product names must be escaped. The CPE 2.3 specification defines two bindings: - URI binding (cpe:/...) uses percent-encoding - Formatted string (cpe:2.3:...) uses backslash escaping Escape the required meta-characters with backslash: - Backslash (\\) -> \\ - Question mark (?) -> \? - Asterisk (*) -> \* - Colon (:) -> \: - Plus (+) -> \+ All other characters are kept as-is without encoding. Example CPE identifiers: - cpe:2.3:*:*:crow:1.0\+x:*:*:*:*:*:*:* - cpe:2.3:*:*:sdbus-c\+\+:2.2.1:*:*:*:*:*:*:* Signed-off-by: Stefano Tondo Reviewed-by: Joshua Watt --- meta/lib/oe/cve_check.py | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/meta/lib/oe/cve_check.py b/meta/lib/oe/cve_check.py index ae194f27cf..6555743514 100644 --- a/meta/lib/oe/cve_check.py +++ b/meta/lib/oe/cve_check.py @@ -205,6 +205,35 @@ def get_patched_cves(d): return patched_cves +def cpe_escape(value): + r""" + Escape special characters for CPE 2.3 formatted string binding. + + CPE 2.3 formatted string binding (cpe:2.3:...) uses backslash escaping + for special meta-characters, NOT percent-encoding. Percent-encoding is + only used in the URI binding (cpe:/...). + + According to NISTIR 7695, these characters need escaping: + - Backslash (\) -> \\ + - Question mark (?) -> \? + - Asterisk (*) -> \* + - Colon (:) -> \: + - Plus (+) -> \+ (required by some SBOM validators) + """ + if not value: + return value + + # Escape special meta-characters for CPE 2.3 formatted string binding + # Order matters: escape backslash first to avoid double-escaping + result = value.replace('\\', '\\\\') + result = result.replace('?', '\\?') + result = result.replace('*', '\\*') + result = result.replace(':', '\\:') + result = result.replace('+', '\\+') + + return result + + def get_cpe_ids(cve_product, version): """ Get list of CPE identifiers for the given product and version @@ -221,7 +250,14 @@ def get_cpe_ids(cve_product, version): else: vendor = "*" - cpe_id = 'cpe:2.3:*:{}:{}:{}:*:*:*:*:*:*:*'.format(vendor, product, version) + # Encode special characters per CPE 2.3 specification + encoded_vendor = cpe_escape(vendor) if vendor != "*" else vendor + encoded_product = cpe_escape(product) + encoded_version = cpe_escape(version) + + cpe_id = 'cpe:2.3:*:{}:{}:{}:*:*:*:*:*:*:*'.format( + encoded_vendor, encoded_product, encoded_version + ) cpe_ids.append(cpe_id) return cpe_ids From patchwork Thu Mar 12 15:38:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83265 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B680E1125853 for ; Thu, 12 Mar 2026 15:39:03 +0000 (UTC) Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24812.1773329940515790896 for ; Thu, 12 Mar 2026 08:39:00 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=nH89zOKC; spf=pass (domain: gmail.com, ip: 209.85.128.41, mailfrom: stondo@gmail.com) Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-482f454be5bso24088765e9.0 for ; Thu, 12 Mar 2026 08:39:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773329938; x=1773934738; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Cg3sZ18qawjT8A4dzIzDtBflRtGjsWCVhz/NhFC+NrM=; b=nH89zOKCMa06+k+8SLLjYQI1bQShAUABV9CNkmRn41u6NBPn7Arc18+tgIR2pPbUBy PaVbpMwKOme3aPI1+StkW6X2jsWj+Uqt8E/LgSwGTW9xunQkVEKqu3XsLSR5xsOcjoIV A7UZvwo3/4R40Dt/340OekhcHgnR/IlcTReve28yppZoyNQD596FMJb+5y1vxWRHBEtk ET2sFjDsgrUCWd2/SGFFJNFicC++eKygU0O/e5OJOMAk2znJ8BRx4a9g6lxoIEHM8KPV wFtTK+muNQM14MDQb1AXJsqSXOMHdm5lRIUAdmWP9lGPkREkl7hWXFxa/JJEJxDuxSdC jxqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773329938; x=1773934738; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Cg3sZ18qawjT8A4dzIzDtBflRtGjsWCVhz/NhFC+NrM=; b=Y4CT5OVydqLeTtkxw4jcgqOARksnzXKCHlR8+iovBVExJgUNKczTYUZcolb7ds6IKZ ZeZkxrUAa4K7xnM9yVtAUoWjvspSoUacoLqPa5UTbJlb+ZJlYx+IG9CId4O/ZDdL+bv/ gNjs1oJJVcCFbl+5zb3NO3k7RQOJ2xYAVDCvGAK7l/k0Sgn5max7mchSL1e+SlQuHAJW b/b167Q2NpsMTH+x3r6JYjvajzJmYtKQkcxfnEw0SlRG/Xv5703x/ITwWG2LdCp3mb0m BZklz8aR2XQI251tiYMg06fbOOyaw3NCdzbt4j2bjUSSG8QNwydI49fRnVpyRBvfXeeH foAA== X-Gm-Message-State: AOJu0YyAXNRu17KCC668Dqeak+ZF8QjO9+YeUZq0T+pKuo5AbBygtEnM ZiYB7IjrQsnj9ZD4tUJBcFkNu/+QcyPOwjWDk5O57NfxGWE04JQvg+vXElAsvg== X-Gm-Gg: ATEYQzyxlXCRCyrsl9RwU9i4dXZsKsBDUMeO4OcRtM2li4Vs/nmBXCRAsvvXMyEFl49 6agSK76T96s//zWR4Ou0nDj9xYv9edceEE+JhvbIIKjJDxpqRT1poMUTqF78UkmG+IJ5U48RHt1 8FdORigH2nR/GWXltNFMp3jLuW6L406t89scZGif6vQLsHfgbsv4WFzoC3PFX0phfd4r1gswbsS GfnnD1C76W73XVOM2jv9EVLGsKFu5Rxk4sOvVe03kxcCUz+04OIoSroeEbuEgG5welePgv9y5M/ xreWIGOlhtlnsgeL3muYbCksxHC8r865mKnDO5Yk53lWVZMj6ur7GtQbvlR5qb6Tpn/re0tyusk j5tinJ65krJvLIkVjHoiH/ol2vrYFTnOfk11ZK/IDBMpsTEwsJN3/DcRGDwuc26EJJpsyG65+ML bDx8nZeBnLENNT0X3PPJUZe0g1qIYPosuQq6w= X-Received: by 2002:a05:600c:1907:b0:485:50ac:b8cf with SMTP id 5b1f17b1804b1-48555a5689amr3179245e9.0.1773329938193; Thu, 12 Mar 2026 08:38:58 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4854b0dcf2asm74857385e9.8.2026.03.12.08.38.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Mar 2026 08:38:57 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, Stefano Tondo Subject: [OE-core][PATCH v9 7/7] spdx-common: Add documentation for undocumented SPDX variables Date: Thu, 12 Mar 2026 16:38:45 +0100 Message-ID: <20260312153845.164369-8-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260312153845.164369-1-stondo@gmail.com> References: <20260309132854.128375-1-stondo@gmail.com> <20260312153845.164369-1-stondo@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 12 Mar 2026 15:39:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232980 From: Stefano Tondo Add [doc] strings for eight undocumented SPDX-related BitBake variables in spdx-common.bbclass. Variables documented: - SPDX_INCLUDE_SOURCES - SPDX_INCLUDE_COMPILED_SOURCES - SPDX_UUID_NAMESPACE - SPDX_NAMESPACE_PREFIX - SPDX_PRETTY - SPDX_LICENSES - SPDX_CUSTOM_ANNOTATION_VARS - SPDX_MULTILIB_SSTATE_ARCHS This makes variables discoverable via bitbake-getvar and IDE completion, improving usability for SBOM generation. Signed-off-by: Stefano Tondo Reviewed-by: Joshua Watt --- meta/classes/spdx-common.bbclass | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/meta/classes/spdx-common.bbclass b/meta/classes/spdx-common.bbclass index 5cba52eedc..00438458e0 100644 --- a/meta/classes/spdx-common.bbclass +++ b/meta/classes/spdx-common.bbclass @@ -26,15 +26,38 @@ SPDX_TOOL_VERSION ??= "1.0" SPDXRUNTIMEDEPLOY = "${SPDXDIR}/runtime-deploy" SPDX_INCLUDE_SOURCES ??= "0" +SPDX_INCLUDE_SOURCES[doc] = "If set to '1', include source code files in the \ + SPDX output. This will create File objects for all source files used during \ + the build. Note: This significantly increases SBOM size and generation time." + SPDX_INCLUDE_COMPILED_SOURCES ??= "0" +SPDX_INCLUDE_COMPILED_SOURCES[doc] = "If set to '1', include compiled source \ + files (object files, etc.) in the SPDX output. This automatically enables \ + SPDX_INCLUDE_SOURCES. Note: This significantly increases SBOM size." SPDX_UUID_NAMESPACE ??= "sbom.openembedded.org" +SPDX_UUID_NAMESPACE[doc] = "The namespace used for generating UUIDs in SPDX \ + documents. This should be a domain name or unique identifier for your \ + organization to ensure globally unique SPDX IDs." + SPDX_NAMESPACE_PREFIX ??= "http://spdx.org/spdxdocs" +SPDX_NAMESPACE_PREFIX[doc] = "The URI prefix used for SPDX document namespaces. \ + Combined with other identifiers to create unique document URIs." + SPDX_PRETTY ??= "0" +SPDX_PRETTY[doc] = "If set to '1', generate human-readable formatted JSON output \ + with indentation and line breaks. If '0', generate compact JSON output. \ + Pretty formatting makes files larger but easier to read." SPDX_LICENSES ??= "${COREBASE}/meta/files/spdx-licenses.json" +SPDX_LICENSES[doc] = "Path to the JSON file containing SPDX license identifier \ + mappings. This file maps common license names to official SPDX license \ + identifiers." SPDX_CUSTOM_ANNOTATION_VARS ??= "" +SPDX_CUSTOM_ANNOTATION_VARS[doc] = "Space-separated list of variable names whose \ + values will be added as custom annotations to SPDX documents. Each variable's \ + name and value will be recorded as an annotation for traceability." SPDX_CONCLUDED_LICENSE ??= "" SPDX_CONCLUDED_LICENSE[doc] = "The license concluded by manual or external \ @@ -53,6 +76,9 @@ SPDX_CONCLUDED_LICENSE[doc] = "The license concluded by manual or external \ SPDX_CONCLUDED_LICENSE:${PN} = 'MIT & Apache-2.0'" SPDX_MULTILIB_SSTATE_ARCHS ??= "${SSTATE_ARCHS}" +SPDX_MULTILIB_SSTATE_ARCHS[doc] = "The list of sstate architectures to consider \ + when collecting SPDX dependencies. This includes multilib architectures when \ + multilib is enabled. Defaults to SSTATE_ARCHS." SPDX_FILE_EXCLUDE_PATTERNS ??= "" SPDX_FILE_EXCLUDE_PATTERNS[doc] = "Space-separated list of Python regular \