From patchwork Fri Mar 20 16:49: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: 83999 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 7197510987B9 for ; Fri, 20 Mar 2026 16:50:05 +0000 (UTC) Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.17790.1774025395840007923 for ; Fri, 20 Mar 2026 09:49:56 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=BBShmPWw; spf=pass (domain: gmail.com, ip: 209.85.128.48, mailfrom: stondo@gmail.com) Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-486fb14227cso21146835e9.3 for ; Fri, 20 Mar 2026 09:49:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1774025394; x=1774630194; 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=BBShmPWwtQlxeapoqk1LKMYVx3QeWGXiNvjk8/ZcQ7lOihmqq67+9GCboWXAW3bwS5 iJm8fLLG+9M9fOAMFSUswxF5qgANAf1/pC2K4uPeUajV8y80Xpq3LDWSi1/zkJxQo3y/ Nf7iOy9C0Yq4gFbhsmzqoYE4EN7EAg6ObpsCPYsEZhegT+BawpVa6RsGpCRz3dfyAmx/ zsO4MsEDO6ncf3QWX4pFyZ/7HMPaNmwvt/pxi8eSpolySWTfCOELm2I/DOw+Ic8rl+2P hykUaPSrMRY7Dl+H9udM7F16kf8CNxcuc+XTp1QXM+TV2hT0tRqkS+LXcLe9SxcK6Rgb MhEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774025394; x=1774630194; 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=baXpLvTeaIFmi7zRUukjOM6RMKyG711OGiCFFgyZHNnfMuqYI/lGkS80Jbh2IFhxAA 6T2RL6MgVWIAM0N1TblZxu1rgd0Rfbb+DxbwQoMPu6C67mH6KgLmD3OEL2z0j68aAGsg 5TZQOkV162U/+btDwkT/n5Qohc5JkddPxqFsl/GU/SHcCYpTNyupCUrKlzr0Exjxnw7m kLauLXk10UAlgC7062NiT5lYS4c0mTwOe3Vq1PwrNyQp1II8NH7L4E92PIAPExWq5XK4 0rbGWQdhXRnFok+EqWDy9xu7rubQYOf1FW/4RqUEgF37739k2CCRaiKQVo61fdIO22ik /bkA== X-Gm-Message-State: AOJu0Yzj4yTOYRfcbVob61phaWVPHQ8KK446HU8GA0h8F7OWJiowO8ne /hzeX4/PiHsqUuzl6hdN1s01dOB5utrkT8rdG3e1w5bE9WXAXTgFkabqJ6aHtSG2 X-Gm-Gg: ATEYQzzN125++sYlRj5TYMkRSczzbAYVgKArBLxcYsuychG3xL5KlBzdRFGzepx0gim Y1EobK0ZbJKHHGrjeIIKptSTFHOsq1OxTieHkOgSPcDHX6obZolik4VCGx5rk5VBSm+9TjMkIJ/ TlvYO1Yu00JDmpG2sSYlzlBkulYFG7Vjhqu5rtC7Kmzm3BgmAqchtKnMWvoEe7AF2YhBa7u2BDd aOlQji7+MPPAT9dSar5Ze5ZWp3lBEL1dhmNJtEkw3kmZVr0oWbOyWbjL2FZMVVSICUgVBm+R/wV Vk6VFET0cJ6hr9oNv2ZpLzHdU0GgqjM7qYXU9qTtwpMgCHSIR1vpdFFSf+z78IH4v0jDVUs+YCB GuU+DABBQPJjU+TvtMv37wENCodTOAj28Lyl+p22MmAnLZPjCf14gXqXLT0rM8trSYMpyMpvpBV quIydTJFCq34dhiVET552TPWBzmJ8Nq7T6FbY= X-Received: by 2002:a05:600c:3b07:b0:485:3aa1:a7f1 with SMTP id 5b1f17b1804b1-486fedab4bdmr56341075e9.7.1774025393692; Fri, 20 Mar 2026 09:49:53 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486fe6d91fbsm73018905e9.3.2026.03.20.09.49.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Mar 2026 09:49:53 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, richard.purdie@linuxfoundation.org, stefano.tondo.ext@siemens.com, Peter.Marko@siemens.com, adrian.freihofer@siemens.com Subject: [OE-core][PATCH v10 1/7] spdx30: Add configurable file exclusion pattern support Date: Fri, 20 Mar 2026 17:49:45 +0100 Message-ID: <20260320164951.128572-2-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260320164951.128572-1-stondo@gmail.com> References: <20260312153845.164369-1-stondo@gmail.com> <20260320164951.128572-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 ; Fri, 20 Mar 2026 16:50:05 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233621 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 Fri Mar 20 16:49:46 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83996 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 822B210987BC for ; Fri, 20 Mar 2026 16:50:05 +0000 (UTC) Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.17791.1774025396944649310 for ; Fri, 20 Mar 2026 09:49:57 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=Ag1cCv+M; spf=pass (domain: gmail.com, ip: 209.85.128.45, mailfrom: stondo@gmail.com) Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-4852b81c73aso7751605e9.3 for ; Fri, 20 Mar 2026 09:49:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1774025395; x=1774630195; 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=Ag1cCv+MR3pxjh2Rrv8/m9qKAbIppuW+dCRQIeYbTZrtqsh0fzqAvjp1BLcyj2qFrq F0T98oE9d88kSk9h1TlGrBnOgjR2c5A1MQF13FwrHtCzsaY6JhiHjEDUH38gaaW7QAg7 Oe0JQ/2fx8R1SPsrqapKaUL9B1vRg9fyxyCJEM5F4jSwf1aCLctlX3Qtupj0JtgB1Etn pd07Msqq1URyucxyaT41kWRcuQJQaUqCIubbE5d+LOZpMHdZT/9t/D/Kxtmo9XBCsdRz qTTQYDHQ8mKcpI3IpphRsdMtHFk1/6WFLcn5Zd70aumNdJlTl1boVXbpRPwfGd42/2Xa i8+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774025395; x=1774630195; 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=IBvb0poCizBxnkpIQkibYVBcdXCsY0bVbBb48GXZ0tuG43FfYqePvUTE0C66s8DxY9 mSDwWL9aER2eV1J9Uldx//q7hlvEUUHSy5Rzl4Mlf3It3DrmSFc5Tammhk9vgz3ucBmh W22rji2mdzTK+3IpQl78tFbC8x//eIvT2TyUribWjTMaoKhYSynGH7Y8ByqD8/+f9qx4 GyA5iGPxJHxz/E4Gzbg0WnCzHa6pExtCn1BDdopPSVi8zV9mRdnPlDNnVUcK1jxxbtHu rYi8BbYtoIN01U14JjHpxMitf2lRqHG0YXcglNNBf5Hy5sexf+yWiNLMtYncNHXfuUZK s5dg== X-Gm-Message-State: AOJu0YzBCO/aKcQ0Mwz3TAzA2pjzk6S3A1bRhQctgFxYp9P6Eo8EgLRF 9GQO27a4XF8Czr/ONJv4qPNMcC/VvOBFSzRezHs/rh0S2+neB/gAVznzyL5N54w3 X-Gm-Gg: ATEYQzzUTwbhru6VzAUqxkfDMu9s7BEUf1tzw9WzhqlNAPXRoRCFt9nfXF818AAQQRo VH+AE8H+Dy3x4KxozUwRiubwtDrI7Eso9RzelH9/3R0ptgHu6XvUzKNFo/FOi2iYvwNqYH4+AJy OzQWwGRsQw7IHiwDz1IUiqtacnvV7QiJxNKGv45slnk+borQgT3bsA8/7Oh0wgHIJCu3UKSTl/s vZ2gWsRnwFQodQ1amCSTuaLBhS+7h8Xr6lCUZH0hMapXh7lepeDjoKx8tBywPT8GMWpw7fk8VMw V2a07qsxg36wSHGNGnxEmswot8IEszrZ/G726lyFKpkfN93FLpJaDaV6FE3FahZSw2rb1m3dDik kS4q0XjKjPpGWraj8dNQ+k1PlBbC82LzUpH8J5fEg8mvATlRZ/hWTx7Alj8M+8HsF5YMwTU1i5i NV371SmwdTJRkU3gwTBNIJbx9IoFheIz1B584= X-Received: by 2002:a05:600c:8b24:b0:485:3dfc:57c with SMTP id 5b1f17b1804b1-486fee0fcf6mr54506115e9.21.1774025394928; Fri, 20 Mar 2026 09:49:54 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486fe6d91fbsm73018905e9.3.2026.03.20.09.49.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Mar 2026 09:49:54 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, richard.purdie@linuxfoundation.org, stefano.tondo.ext@siemens.com, Peter.Marko@siemens.com, adrian.freihofer@siemens.com Subject: [OE-core][PATCH v10 2/7] spdx30: Add supplier support for image and SDK SBOMs Date: Fri, 20 Mar 2026 17:49:46 +0100 Message-ID: <20260320164951.128572-3-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260320164951.128572-1-stondo@gmail.com> References: <20260312153845.164369-1-stondo@gmail.com> <20260320164951.128572-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 ; Fri, 20 Mar 2026 16:50:05 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233622 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 Fri Mar 20 16:49:47 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83998 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 A70B71075269 for ; Fri, 20 Mar 2026 16:50:05 +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.msgproc02-g2.17748.1774025398018252441 for ; Fri, 20 Mar 2026 09:49:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=EPq5HCgV; 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-4853e1ce427so7768305e9.3 for ; Fri, 20 Mar 2026 09:49:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1774025396; x=1774630196; 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=ls1UDLDCD1jxOHvKl4hO48AAskAjKnISa9I2igIpNdI=; b=EPq5HCgVHbI4xHwoJ+ceLoF2aZqoNBHISbKcFaVAui5yTPkRPXMS/2tc2/IW0NNsjj OZQdvv4MmQUQY9zR8sSGUPxVQYXpzTOiRzq8u/GJzmQcb5qKBrX8sP6M5OPPZXL/E8E+ rvQld7baWtQdR30FZtbTnzYnsfcQqxmQNqjuW9xtbwd/18nsmC3+lkupHi+q0vyOJlez kDo6KXlYKxWcfolPeI+6ymZKmCVDfrq1za83bjGjktwcPHDzTFLHF1dOmgiR/T58GtQY 9YI5JoP9gd0pWr90xmLWBRjTdk7GmTV4YpYD6Ma4PynBuYMQEXP6navQhnrt19ixYzJB p03A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774025396; x=1774630196; 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=ls1UDLDCD1jxOHvKl4hO48AAskAjKnISa9I2igIpNdI=; b=hMReBb4xyRauck1oOUIyPsupPFRKr/k90Tlh46+TeRH0HlMe+aHkEiEn1lr9LthOg5 690xL4xAxELySK598bB3iP6VubNtGjuTUF1F85X5QNUWV/3G2QIxY6sUg8/P5r3Inh0p VkqPzAxTnbseAxJRnvmwD57GTMbU4siopV10q2XlWuDxSCmUHZtY7RXDAeSfjmgYM7yy 4yVH0PsVQ3WQzC5U/oj3ZeTNlpTVYvsYBUowEMwFNnFs7pgICkN0nwX6M9d8fsb7bsVZ HwQ/KKogVgTzGIuH1/GsrG/Xev88SkJYVP3GZwW8YRZlszdfAaOEA54kWKtZJJp3w5Kf zcmA== X-Gm-Message-State: AOJu0Yxye7cN60O/rt34xoLTsZJ5CiYV666SLpgiTIISDhPG+y92xUeO vPA5wcqHn9IbonmZPE1X706CeuQhOi1V+6ZG3mkiLbd1OiOw717ZVbGLVOcAHs49 X-Gm-Gg: ATEYQzxiPPEI1ExYAdFR8h/y8SSRb+3V106c0ndSz6QtX/KVShsKOCGrfZcszLYVFfM npCm8xvILKeZykVapEwhmSdLk1cVsIUSm5c3IqreE0JUnLEt+810pK1Dmc2VeEUNdxvywFp1jqH pGClLtTlGTA9too+bka8Eea9u9LM6RkaT/lYZsDTR+DycG1DwCmwFeNol1gEyvSGfgbQFJvWJ5R J+8V+usBRoQ6QdeTi7kzwuaxUMEUJwglJXYCtHZWiY1Tm5Sc/LtnOPbnfSgxy+CNpdI/oNEu2jY ILrNHg0EDz6XxLMjgpOJ1W87mrIcJ5EX6nUA0Oala8Uox/8LhTkEPox4RUVeM1nOxx4XI9J/0+a 4QRZ1MYUKvqWGzHso3kMEM2gup1zUN8sfq65SAN9JlwVnN/M8Bv3ZK/FdDmQ9Vy2922ygXMbEZ2 P0oGvOPsY9YrcJBN/LscE6vuSI6cgvq1M0xQi7ElnE4p/Z2A== X-Received: by 2002:a05:600c:3b8c:b0:486:d76c:fa51 with SMTP id 5b1f17b1804b1-486ff03ffa5mr49013895e9.27.1774025396003; Fri, 20 Mar 2026 09:49:56 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486fe6d91fbsm73018905e9.3.2026.03.20.09.49.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Mar 2026 09:49:55 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, richard.purdie@linuxfoundation.org, stefano.tondo.ext@siemens.com, Peter.Marko@siemens.com, adrian.freihofer@siemens.com Subject: [OE-core][PATCH v10 3/7] spdx30: Add ecosystem-specific PURL generation via bbclasses Date: Fri, 20 Mar 2026 17:49:47 +0100 Message-ID: <20260320164951.128572-4-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260320164951.128572-1-stondo@gmail.com> References: <20260312153845.164369-1-stondo@gmail.com> <20260320164951.128572-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 ; Fri, 20 Mar 2026 16:50:05 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233623 From: Stefano Tondo Generate ecosystem-specific Package URLs for recipes that inherit common language and package-manager classes. Add class-level SPDX_PACKAGE_URLS entries for Cargo, CPAN, Go modules, npm, and PyPI so source download enrichment can attach ecosystem PURLs without recipe-specific duplication. 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..0d3edfe4a7 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 =+ "pkg:cargo/${BPN}@${PV} " diff --git a/meta/classes-recipe/cpan.bbclass b/meta/classes-recipe/cpan.bbclass index bb76a5b326..87ebed124a 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 =+ "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..0f5835f26e 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 =+ "pkg:golang/${GO_IMPORT}@${PV} " diff --git a/meta/classes-recipe/npm.bbclass b/meta/classes-recipe/npm.bbclass index 344e8b4bec..7bb791d543 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 =+ "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..e2d054af6d 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 =+ "pkg:pypi/${@pypi_normalize(d)}@${PV} " From patchwork Fri Mar 20 16:49:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83997 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 B75F4108B91C for ; Fri, 20 Mar 2026 16:50:05 +0000 (UTC) Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.17793.1774025399248973155 for ; Fri, 20 Mar 2026 09:49:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=UnGQZhlj; spf=pass (domain: gmail.com, ip: 209.85.128.54, mailfrom: stondo@gmail.com) Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-485410a0a8aso6675635e9.2 for ; Fri, 20 Mar 2026 09:49:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1774025397; x=1774630197; 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=UnGQZhljmKWfV8DCZCghHZPlTORv/aAHWTZAYcBm9VHcBGOxhXe6l3LBX49GywYv0G mBg1on0T/0OdCJgX0NG3X8pQtm3ddK/bbgTWjyNp8YRgFMqaY540VOo0KHQYAXnh/hiT /SQEObMItXGLthCC0JYIYO4DghKyZcCpZI0aJIjTbC84vKlNm/3D3ng6ydp7WAoFeHt3 iFDG+1Jh1RxCA5buwJy45ywVfk9+SF2rfGDYbnDytoEBIGIkrdSf/XlOAM54hoFHqZA8 wva4AgtSKuG1TVS4owBytPzmjSPp1le2/2aPTZDJ3qB6VqgfbQiVOcAf8ZjH3MThHanM 29+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774025397; x=1774630197; 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=Ir2siG1K/9z3OKRIDurmDR5fjmwIShmQfh2whZMinAe4B4Y5JAZBbleCryjcSYjb++ qsuO3AhUBKCLNQBa0e15ee9tw3EjM65bpqFJ0f2g4JBCyqYa1oIhDZIK054vNHIZp7bX Qt5ezgs1C9pGrZbVA1Z1IEIU+8E4tmwBGnR3b5346wwHQXeAkopEfdOieq6edvzPhM7d nEhTLVsT2zj8ZUO7DcDKyf/JtPRfE1XWR1kx9Th78Pct1Yz+u/INJPJGVKeHwFrK8zgt 2uG6XIaOKSKdhZV0VvncTmVkn/bteASZmQnKCCYNh/miP+O2Uxl9i+O6DLrLzvMD297e d8qA== X-Gm-Message-State: AOJu0YxfJDtgRsa92x7PAb47E7YdB2jC//TEyQIUdroBgbeAkwKv59jh l6ClJUA0XQY/luBz0GFFmMsx6lGrj+umBO2QBeWxwnOvW2DjN8ir6VnQKMw8ZoJs X-Gm-Gg: ATEYQzzvJ1bhZZc7xYrpzUlhfF0LVQ3kpYV/GZALdE3daY8pIf8jABRBHF11OPrl993 6j6tuAvntFLzG2klMTfIef/XaC+1K2lBNKTgSYjWqTNd95aZaMB3IEROSneDEbDiDBUoszD0DYB Gq47mF9oZPnhTimCotAFcxr34PYQmhusr+wmQv3MI1cTZUbjwIfgqH50ivxtAASs7xFGGYk2BpB J+bX+h9SWGce9BkTES8BUSnDZKJ2E+tEiPLPO7GfjRaasl9DfsRAH5Fra/KbEy1LenZFOMVQA+g SdwsgbXXZnHo4StGWJuf1Iq4S4TBCL9WLYjIXI24jiPg5rxvyCXglUUMOZMISjQ69JjTo4vfU8x BlITCd9C4T+HUPQO+1tMJW0RyR7pUjNk8yPLqDbxnpOIEaPC/JHhieMzqA+3LubGMaomKwB6NkD nlKuqC5+diAmnHkSEiwWV50EiGed+pKRfcNmc= X-Received: by 2002:a05:600c:c84:b0:485:39d1:b500 with SMTP id 5b1f17b1804b1-486fee0d859mr54370205e9.16.1774025397192; Fri, 20 Mar 2026 09:49:57 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486fe6d91fbsm73018905e9.3.2026.03.20.09.49.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Mar 2026 09:49:56 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, richard.purdie@linuxfoundation.org, stefano.tondo.ext@siemens.com, Peter.Marko@siemens.com, adrian.freihofer@siemens.com Subject: [OE-core][PATCH v10 4/7] spdx30: Enrich source downloads with version and PURL Date: Fri, 20 Mar 2026 17:49:48 +0100 Message-ID: <20260320164951.128572-5-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260320164951.128572-1-stondo@gmail.com> References: <20260312153845.164369-1-stondo@gmail.com> <20260320164951.128572-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 ; Fri, 20 Mar 2026 16:50:05 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233624 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 Fri Mar 20 16:49:49 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83995 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 6D00C10987BB for ; Fri, 20 Mar 2026 16:50:05 +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.msgproc01-g2.17795.1774025400839661577 for ; Fri, 20 Mar 2026 09:50:01 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=UB46GnlI; 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-48334ee0aeaso18838935e9.1 for ; Fri, 20 Mar 2026 09:50:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1774025399; x=1774630199; 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=UB46GnlI5wkFpeWhTtpeuKsbKH8Z+NwzbbyIO8p/aPeIZPuvG61GTpFJYUiHOfY5j1 j9K8Xt9vnDWOBKDC7l3Sa1T1LuUBCkmvPcdQaYLI2EJ2eKoaut3NuJsRHZgFY/YLm1vG WOilIj2sbiQ4IpEOvOAHN2xEVDx7Q/w9lx1MtTy0xaYuuS4vjFJN3vDmAuLTfLSP37PB /loiVWIFTknH4g07o1IUMXgtI7N9khubWj2wAHiLJKJLA6fyh4Jm8W0nlj+iMtiWbHUc gmdkajSzJzmyy2fsAKBbZB3LIFQn8vUS6xBE+cND/27UKXt8GUqnx6fAaL77+PatT5MM Atjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774025399; x=1774630199; 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=lOLvU3fOZVm4Ep9LGCFQXsDPjr10uiYCADyeldvJpxy3T28d3nROz8ZdoZBF55mWOP V18R0cqmPtz4TaY+bwS/qiL/Yzrm6YlaouiizFRq2cYM0yHyZdpkd1QLED0orQ9y6VAA VU70jNNe7zw4/CDFZxr4EKSs97pxQbvUHwOEW1rtmogqFiXr6j+tgQ0ZrYziJv+sd8SD H9ttulnf5HTxd1XsyTxaSQ7FZMFvuT5Dy1Y5WPXScY8cyCc/TML6tUBkBZ0XX6Bg5sQp YMlFzaLyTE7boQuo2kkyZbj7EpEGRkR25B+xqUfAGaBvfLyWuiGwVNDvNwEd43Nhth2P a6Ug== X-Gm-Message-State: AOJu0Yz6RuyelutSMydhxjjHdmK4qZlDyb0zYXoNm1tfVJo3rduhxxdH NU79OktuDtqC5qPShloqWiFNMjMq7RSpOPGca9FEqAJOa3wfuISCBpQiyxZ3kr17 X-Gm-Gg: ATEYQzwuPUsg1Rt74nauCmd/0qBl0X+0DL97oe5CkirROJAJ0vr32MFW9FVSwCuxCxw FYuf2gDVCKYo9uQdsvkUd20KlCTMEuw1d72QEnVGzf0wTx1FVRUvoCO9oiYR/nx3RlZk99c3y6r s80xznmxDt+8cWq39JGALDZ216b26UjY1CsvQ4giUTTIEJ1o9RbUP51MBUoE0APsrr9BWpXFNEq 7L8Uj/JutOLgpqGELJUtS6x0Gczq6Dz0LI3JoLuIjIzq5h88f9NYBLRsREA+749Lq2MVAjVXwvl 1seUwCwsrdn8afHUVsRKtD+cfDrrlHmFCztRNYIB+XQLEBq22Af93QjLFOLM6fNaSyONCEqXLZz 5vFwGCpsV/aXa5y4Qa+wFXqjk6ERJNvxK0y+aR/AJHsJ/83qs3oXaAGobBHogEbDjoPojDu8M+p /jdf/ptBYn6SqFcEol7zAf3r9FuI1cFFrABC0= X-Received: by 2002:a05:600c:630d:b0:485:364e:934e with SMTP id 5b1f17b1804b1-486ff02c698mr59992365e9.21.1774025398367; Fri, 20 Mar 2026 09:49:58 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486fe6d91fbsm73018905e9.3.2026.03.20.09.49.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Mar 2026 09:49:57 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, richard.purdie@linuxfoundation.org, stefano.tondo.ext@siemens.com, Peter.Marko@siemens.com, adrian.freihofer@siemens.com Subject: [OE-core][PATCH v10 5/7] oeqa/selftest: Add tests for source download enrichment Date: Fri, 20 Mar 2026 17:49:49 +0100 Message-ID: <20260320164951.128572-6-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260320164951.128572-1-stondo@gmail.com> References: <20260312153845.164369-1-stondo@gmail.com> <20260320164951.128572-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 ; Fri, 20 Mar 2026 16:50:05 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233625 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 Fri Mar 20 16:49:50 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 84000 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 EC8771091914 for ; Fri, 20 Mar 2026 16:50:05 +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.17749.1774025401700724751 for ; Fri, 20 Mar 2026 09:50:02 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=gzyEx2iy; 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-4852b81c73aso7752125e9.3 for ; Fri, 20 Mar 2026 09:50:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1774025399; x=1774630199; 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=gzyEx2iyMAM+63rKtAmCDauoa5u5u4cy2pH/SsibqtSKspC1TGISYRX6db5ikJEe+b +HnLddOtsV8nJn1MvEf5iHGPTgZgKXeV4us4XVlxX/7q6Ofs4lz7mm/OCloqd1dACpEs 2PUrIUHQQxtJVgBLbwUDkZvqQRGqH3lv8SNKtODdV9NSqu+o+GIpxD810iM7RCrEMscn 8yIiTZelv3VRpzI2HeaIIFcYhpDfwOmqKVAlALxSS9+ZQCaLAhj4iqANyiqiNJ7FnvQE ZYcKnhqyPpYzd2s+B4jtYNOHGhtJ5znxqSi+PSjbHy21jHEh8Wg6FlxoYFA3Xku8Wg9C 38hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774025399; x=1774630199; 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=eKKu0WSQ6FdrhUgIf6VYfYzQbIlcPmATn/P157g7WM5voMGTqFltc6ODWV3wgX6h5T kDYJXsFn212ECbBIY5MVc1BZxHxo1TwXXxxXS08RVk17EefHww+60jxphojEvUXkTszO YtOW3A03raY8yQgP1CqnkbTNMWTJG19vVDWUHlMYNAPBEWyTm18ZgohruEKGLQXrON2w +xGrQi6ezlcCKA4aZU3YstUKAtqN6VcTT2BZk7IoP65TCjhvl/039RzmAQzai7MNF2IW 3KCs5J/pTGzA+X2zcHbq1N6FApFkSXdzln3dqghYbDjpGqWEVOL375L4TWCkCotFEF7Q suvA== X-Gm-Message-State: AOJu0YxPUD95VcSy4Ym5cokT22yXMfHd+QNPzK4IPhyBoYiGucyzqJGU 2f+w3LD2Z3ZRbPOvyRUQO1g7BkhEFwfhjqwhTjDDC8BedR+cJ1n1MrfDXEALytEB X-Gm-Gg: ATEYQzzT70zaszKDZm8uQ+XBhlp677HkBqdgG9nYJb09yoDF8SgBBbAsP8UqXol/5CH IY9XbOAVi7JE8A8LRaFpevIrYqn0ilQoPrfzdMOiuVUhdLAJhIHN8SVLXOpgkooEfYFZMWs6Lvb spifoCAzj68t0zCuQbLZmNkvphR97MxIL0f+RZTMuM9qVtBh3YzZDqsOWYko6TwoMC2AkhdICGk cKDYkawF5ANQyUGJFnsJSi9thqEFoPOUOEWo+VBUSSe6JQyhGgrvFdCFZtKVi+72gUtMnhzQPeR VeGoPFyX0yWX8mjzmeP4Bagw2aKX3wmMaRMwdAU/2LM1YVQS7NBZ9MYyp/EMZM+RdnNn0GUxAk4 yy3vzxJgePSEZQIDk5Ezt4kWiqwsh7J4xf4bqbEz36S/7YDRbdySajCItYwzm3lC7RY25ydiyun Pt+Oe3T6PFeXrwncImwbDoZ19XSvxiaBlvriw= X-Received: by 2002:a05:600c:620c:b0:485:3dfc:569 with SMTP id 5b1f17b1804b1-486fee0fa70mr53296585e9.16.1774025399464; Fri, 20 Mar 2026 09:49:59 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486fe6d91fbsm73018905e9.3.2026.03.20.09.49.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Mar 2026 09:49:58 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, richard.purdie@linuxfoundation.org, stefano.tondo.ext@siemens.com, Peter.Marko@siemens.com, adrian.freihofer@siemens.com Subject: [OE-core][PATCH v10 6/7] cve_check: Escape special characters in CPE 2.3 strings Date: Fri, 20 Mar 2026 17:49:50 +0100 Message-ID: <20260320164951.128572-7-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260320164951.128572-1-stondo@gmail.com> References: <20260312153845.164369-1-stondo@gmail.com> <20260320164951.128572-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 ; Fri, 20 Mar 2026 16:50:05 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233626 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 Fri Mar 20 16:49:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Tondo X-Patchwork-Id: 83994 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 2A42510987A9 for ; Fri, 20 Mar 2026 16:50:05 +0000 (UTC) Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.17797.1774025402803068079 for ; Fri, 20 Mar 2026 09:50:03 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=QuYODkwL; spf=pass (domain: gmail.com, ip: 209.85.128.45, mailfrom: stondo@gmail.com) Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-48702d51cd0so3390525e9.2 for ; Fri, 20 Mar 2026 09:50:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1774025401; x=1774630201; 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=QuYODkwLOMBMPraE1CNm0d4kK0tJdiV2T/y9ADee0rQd/OkgOW3ijQ5nJWzgbjPzXh luGFAU9/7JfgxRhvbXeyYuTzGNOeyNo/pajdNdNyg6SqTi03XlsB1HZ/YEaWCYVhW82z UTNNW3Udffd07wtNghyezKO4UvavQDIgHrQFvDM+j3HStazySy0Sgz2sJL34eJitbQw3 q/qctvhqzqudXC2DJE0XYbFUhpbs1nKMkXaMguEhFvg+J6KTnRngOQZXpySwLhb2SfQr t/foMbUrA60mhj/bcFbviWMvjymv3uODlkXtbxQ12VhqbFqilESduw2dRJl8kEhAKxLy YiSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774025401; x=1774630201; 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=f27zsf+dHCuGpQJ7gywZ9+LNHrTZK/nPjUNFtmfFP+1gfZCmFQb75DkzuqEbUDG+z8 JPK1U0bAD8K/dRpci+zFjKRoViyHxvLQVs6Kr3IbfH/RnR1Oni+G8q6FbHbGe8+qJwlb G9ki1VUzioLT5qGdyF6mlwFIjpBWp2FdTMKQIPkptTWkYDmx1OQauJkxGhhNJslMz6KZ 74UJ3gEIQFPapc4sELiGVa36u+YgFDoDoYdPaWeeC0zKWTqPLjkxl0FPbXeEqblrmQao KLezXx1u157G9+E9tIgm2M/f+yxfgOUcXNQiv+NdLygvkdh3aBOJswD18EBR6WVk8fwH yN3w== X-Gm-Message-State: AOJu0Yw2tZwKioZfosMrKOIwQPSL72Ja4kd+0aRjVlJ4musr2MhvOqvu PIQYQeQtY6QjCLpuaqKUrmfsjQVc6yyBSvlamqILTm+EMYL1AYSVihuZ9LxigFer X-Gm-Gg: ATEYQzzHcgNZdDMLLhY+eg+GjP0n30n/YvZodgoGWa55yjJwEyEsYfF7eZzc9cELvei zpavo6+bEOda1VqX9pO7zoJBMzdhpMT3MTo9K+T9Wp9gWIF71RSZJpzIfbrTjPsoVP5txvTulV5 4SlR1vD3mqwA38gKxcWBE14CMkyipWycV0+MgvpQHkNMQ49v6EjXtGgy7u56K14Vlad/u7ob/Wd sHSz3ra97wQ9+eqTWoCyRlTkc3PNeyb/tfWHRekcPAxc4qKGuJQGK9YdnmH9yGldu0eLhJGnfV2 bjwwNPQ/8+ASNBAKHVvmSH3k37q+9eN9jMJzlQEYqVSXsGjdxYV7mIPRV4nb7yQA+7DwkhyTP/m CxGGO9REiUUlLjqjA6yUZa5gAN+CRgudx9NFb73wxI5cKdDRr8wwgor0EbAC9r4k9fjzQbeolyx 6R3KIz7+MWIg/dy9eqvkJr/z3C4+CyRehetz0= X-Received: by 2002:a05:600c:3212:b0:487:1c2:6a4c with SMTP id 5b1f17b1804b1-48701c26b76mr21008975e9.4.1774025400756; Fri, 20 Mar 2026 09:50:00 -0700 (PDT) Received: from fedora ([81.6.40.67]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486fe6d91fbsm73018905e9.3.2026.03.20.09.49.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Mar 2026 09:49:59 -0700 (PDT) From: stondo@gmail.com To: openembedded-core@lists.openembedded.org Cc: JPEWhacker@gmail.com, richard.purdie@linuxfoundation.org, stefano.tondo.ext@siemens.com, Peter.Marko@siemens.com, adrian.freihofer@siemens.com Subject: [OE-core][PATCH v10 7/7] spdx-common: Add documentation for undocumented SPDX variables Date: Fri, 20 Mar 2026 17:49:51 +0100 Message-ID: <20260320164951.128572-8-stondo@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260320164951.128572-1-stondo@gmail.com> References: <20260312153845.164369-1-stondo@gmail.com> <20260320164951.128572-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 ; Fri, 20 Mar 2026 16:50:05 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233627 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 \