From patchwork Wed Mar 4 16:44:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82469 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 B80C9EF900F for ; Wed, 4 Mar 2026 16:48:46 +0000 (UTC) Received: from mail-oi1-f171.google.com (mail-oi1-f171.google.com [209.85.167.171]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.23102.1772642919273944076 for ; Wed, 04 Mar 2026 08:48:39 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=Kwc2Nth2; spf=pass (domain: gmail.com, ip: 209.85.167.171, mailfrom: jpewhacker@gmail.com) Received: by mail-oi1-f171.google.com with SMTP id 5614622812f47-4638a18efc2so4838653b6e.3 for ; Wed, 04 Mar 2026 08:48:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642918; x=1773247718; 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=kZsTCBgME1PNRjxHczDMbLqJbIl+DF2WK2U4einEvRE=; b=Kwc2Nth2ixtQuJrDMidLeHl4syHjtoX8oycayA6k+n/9vsKXt5nKTeSOxCe8renjb1 5aGmiNojmYsrMyw1SST03gauSs3KWmCvn0fgZW1lzYjlKUUrDDF5naYMuxe/AvVgWQ5R gvQqBpU27yfjXNQhD1iW2v4kcXWg2f72/pGLi19pPFgvxhoyyfFNFbhuJg745vypS5rW D0rPcdGtjpRNI/8iUH/JtS0Y/k+BuNHuapRLuzZz44fDcsyRpyzKXA9y+/SFFm0UqOSW 3rhXTAhRkQs3psBZF6KVgjo++tD9HP++mb5qT4jso5B/Im1vofSUIlNMVdpMSdukUKsw uY+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642918; x=1773247718; 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=kZsTCBgME1PNRjxHczDMbLqJbIl+DF2WK2U4einEvRE=; b=Vr09Zu5TenIbnSuxZy5sOkDvAtuYSLjCZguwRpNMOYbee2Uxr0YtoKcWFdnThg1Kgb FtqZ0lNWsouu4c9+0KdcnVUUzMh1ozZhBNrtuASAWYJhgSpzznCPhaHgWgE6cvRLopkd E+zC4zQtZ4b2lU6Z6lLgD4E+4LaK59qYC+PZxhGyhdxjFXgp57iXdLPzvNdUtiNIohTp xqiOPs2dzS0NQawpXrNmXsbxXeGuIUOKw+D2i1s1UQcqlDH/XsiN/PmnXJsivATtrgnR ovmW8gPk9ICPCnT4kpVpy9ukKqMCqpjcBuvd2L522XGemcE28VSXLtoz9Vqw9cI6T/p/ ibgg== X-Gm-Message-State: AOJu0YxczcLXZ2fqHsu7IdAPC2ggh9dxctmuMgu/yUQzFFFOECK+B5Ox PpleieNHafPhblN3jzPpGfnP3+JAxS0xbcFpIZE/eNVZ8pYYN83yoN3DAGanpg== X-Gm-Gg: ATEYQzyEqfGOXcYpaS63Bof4rKhJtt/IayG4BJ+8MI/mzFcsyomq2gUOyd5B5fSMuCa UIheJ1/EoipQzl8lVf2jvuNZhElJwgIZIq2dvoVSHHZC2LV7rdClFZhgzlDVbm6js31lNbsHq5X 0w42LDd0xB5xLBPbq/cCvG3DTCZ/198UblnhpzBsLaW0QyjZY6zLJNEWeBWT4eJijeHpff/3hE8 DsfJaYNcFybKiLGH+jaeKBcMJ5TGOK8tzSX3RWj10yj09wM6UDARQP1acI+rLzeYmTpwr1x9F62 Xa5vMmuQst2euD8M7cx9NpLauIggUpkrTQ5DpPMHFBCl3jdApxDY046XUTLfI7gEGNPqXQBsSol g9i9p9w2InUTriIhigkFU00S239KZEGm7A4e+67zDGWo7We98Nw7oZffHPnv6grKJRUKz6AgwoD H8VyQO4qr4stwoTqZ4zcj9 X-Received: by 2002:a05:6808:c1fb:b0:464:8533:e32f with SMTP id 5614622812f47-4651acb06a0mr1225812b6e.35.1772642918324; Wed, 04 Mar 2026 08:48:38 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:38 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 01/13] llvm-project-source: Use allarch.bbclass Date: Wed, 4 Mar 2026 09:44:12 -0700 Message-ID: <20260304164835.3072507-2-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232385 Converts the recipe to use allarch.bbclass. This is necessary because SSTATE_PKGARCH is set to "allarch" based on if allarch is inherited or not. If it is not, SSTATE_PKGARCH has the value "all", which means any data written out based on it cannot be found (because "all" is not in SSTATE_ARCHS) Signed-off-by: Joshua Watt --- meta/recipes-devtools/clang/llvm-project-source.inc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/meta/recipes-devtools/clang/llvm-project-source.inc b/meta/recipes-devtools/clang/llvm-project-source.inc index 13e54efbc2..6bb595b7bc 100644 --- a/meta/recipes-devtools/clang/llvm-project-source.inc +++ b/meta/recipes-devtools/clang/llvm-project-source.inc @@ -5,7 +5,7 @@ deltask do_populate_sysroot deltask do_populate_lic RM_WORK_EXCLUDE += "${PN}" -inherit nopackages +inherit nopackages allarch PN = "llvm-project-source-${PV}" WORKDIR = "${TMPDIR}/work-shared/llvm-project-source-${PV}-${PR}" @@ -14,14 +14,8 @@ SSTATE_SWSPEC = "sstate:llvm-project-source::${PV}:${PR}::${SSTATE_VERSION}:" STAMP = "${STAMPS_DIR}/work-shared/llvm-project-source-${PV}-${PR}" STAMPCLEAN = "${STAMPS_DIR}/work-shared/llvm-project-source-${PV}-*" -INHIBIT_DEFAULT_DEPS = "1" DEPENDS = "" PACKAGES = "" -TARGET_ARCH = "allarch" -TARGET_AS_ARCH = "none" -TARGET_CC_ARCH = "none" -TARGET_LD_ARCH = "none" -TARGET_OS = "linux" baselib = "lib" PACKAGE_ARCH = "all" From patchwork Wed Mar 4 16:44:13 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82472 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 1C855EF9018 for ; Wed, 4 Mar 2026 16:48:47 +0000 (UTC) Received: from mail-oa1-f50.google.com (mail-oa1-f50.google.com [209.85.160.50]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.22973.1772642920189520576 for ; Wed, 04 Mar 2026 08:48:40 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=QRSiS6G4; spf=pass (domain: gmail.com, ip: 209.85.160.50, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f50.google.com with SMTP id 586e51a60fabf-413d8b8e98aso1069841fac.3 for ; Wed, 04 Mar 2026 08:48:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642919; x=1773247719; 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=7bs/2ESNOjlKv5F2a1L5fY1cfh3Mb2GOypfpxUG+ELw=; b=QRSiS6G4XwGe/1uD8hpnFt9QoJxwI6OG4gn/xaMcmNJ++P3Wo9FamHUYCQuJQmu1+V 2D+3mP5rC+AMncH1KOz3I7SFyf5qXzHOTusqXPwPfftQOaDBu1tRXX2ny9zt43oLjZRl w5ab3GURVZbCKgzdKIhZfDNXkIjT1/h0DjopoAiogxD0L8HWh9gXCfFm/RYtMRNNkfhX QNBCRMNnCs7j3ZePGe7/2DM3SaBvCWitC8lVaAktyohQgq9uJ+7RVUlKQDJHRrVTT9bg 6t/Ls4oT4INoyyPgQNhLkGj6H0Robu5uKXtAqf0S7t0CPDQV75yWDOpHmb3E+O7kxLgq no8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642919; x=1773247719; 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=7bs/2ESNOjlKv5F2a1L5fY1cfh3Mb2GOypfpxUG+ELw=; b=CzMVwoha/zyH5LPN0TMXvZ7T8loa5wYg7Ga09L5Lb8h1rEYYiLB4UIyArdBG+YQXxT vRKyVAuzFDnRN3KwTJYEcg5QYQOwr/Lvs+Sx8IAzcMfSsUckLelV1qWvT9HhXs08kNpB FHVgKI5XU44Qyc3J6kKxtufz6lomObcGgRkHciacFcN1rmHZREi3EbB8IeXpniFmQ4aP h/dYaL5XCi4/j+kPg6rbyU1rBS5N0KQXU72jKZVkTpk5Qi0Sf+/dfKSwh1M5nI3O5kHh CcG/b/woPzX8mz6tr4RoiGSG2yRB+vAnqTijEez3O1v3RL2Gtq77qWInyioib/2fziYJ cibw== X-Gm-Message-State: AOJu0YyY4jLr67lFwZnasuSmKhCcrFqEFuQvbg6TQHNhaiFsd5XK0vcs I/byb7Px8AIWUQ0quE3QmKlCS8wo4wwKsesX1/l63N3X2skwzPriwAGWrfe2uA== X-Gm-Gg: ATEYQzz11fPqUAZnbQhZl10pVoNwHHyfSeYBLWnObhNtClH2GJK9NYAxtHa/ZXJKwRx gvG+0Snm4CXbM06iSwZnAqHBlRrxPR6wYUCSpIG8zZJkmSxcmJOgd38YVW5igEf/TW51iWQHqVN NiLOqfE0/43vDOB47UQce6gsocj/WpJh9Tt1gx4l7mGX3b6tsbkvSlXCXrIKD2+5jDmBszqjMhO YdlNrwE2+Lf5wu6NV6CG/8neeEvjjm0A8UAuzWkeSclx6CsrVYnVoTVWv3+ZYGiIkQpZhEVk87Y NJwsQ09uw2Xy7qLOM3TZAkSTsjExKy5K6B/Vkgxw9tQ8HPV+lVZJxjWmlLcKG0yZBdXGYIml5GI 8JRcczR+I+wXMDx2YNE2AZvxceOrxE7g66saPiUEYUk862pJxy+3gooDb6tYmG00HIatrc0WKo0 sgIMJLhVOcYAO5kDirUNeZ X-Received: by 2002:a05:687c:20cb:b0:40f:2ae3:2601 with SMTP id 586e51a60fabf-416ab4dc13amr1379376fac.10.1772642919087; Wed, 04 Mar 2026 08:48:39 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:38 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 02/13] gcc-source: Use allarch.bbclass Date: Wed, 4 Mar 2026 09:44:13 -0700 Message-ID: <20260304164835.3072507-3-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:47 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232389 Converts the recipe to use allarch.bbclass. This is necessary because SSTATE_PKGARCH is set to "allarch" based on if allarch is inherited or not. If it is not, SSTATE_PKGARCH has the value "all", which means any data written out based on it cannot be found (because "all" is not in SSTATE_ARCHS) Signed-off-by: Joshua Watt --- meta/recipes-devtools/gcc/gcc-source.inc | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/meta/recipes-devtools/gcc/gcc-source.inc b/meta/recipes-devtools/gcc/gcc-source.inc index 265bcf4bef..3ac679b1a6 100644 --- a/meta/recipes-devtools/gcc/gcc-source.inc +++ b/meta/recipes-devtools/gcc/gcc-source.inc @@ -1,11 +1,11 @@ -deltask do_configure -deltask do_compile -deltask do_install +deltask do_configure +deltask do_compile +deltask do_install deltask do_populate_sysroot -deltask do_populate_lic +deltask do_populate_lic RM_WORK_EXCLUDE += "${PN}" -inherit nopackages +inherit nopackages allarch PN = "gcc-source-${PV}" WORKDIR = "${TMPDIR}/work-shared/gcc-${PV}-${PR}" @@ -14,14 +14,8 @@ SSTATE_SWSPEC = "sstate:gcc::${PV}:${PR}::${SSTATE_VERSION}:" STAMP = "${STAMPS_DIR}/work-shared/gcc-${PV}-${PR}" STAMPCLEAN = "${STAMPS_DIR}/work-shared/gcc-${PV}-*" -INHIBIT_DEFAULT_DEPS = "1" DEPENDS = "" PACKAGES = "" -TARGET_ARCH = "allarch" -TARGET_AS_ARCH = "none" -TARGET_CC_ARCH = "none" -TARGET_LD_ARCH = "none" -TARGET_OS = "linux" baselib = "lib" PACKAGE_ARCH = "all" From patchwork Wed Mar 4 16:44:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82470 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 B76B9EF900B for ; Wed, 4 Mar 2026 16:48:46 +0000 (UTC) Received: from mail-oa1-f46.google.com (mail-oa1-f46.google.com [209.85.160.46]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.23105.1772642921102381714 for ; Wed, 04 Mar 2026 08:48:41 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=G0Vcu+jX; spf=pass (domain: gmail.com, ip: 209.85.160.46, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f46.google.com with SMTP id 586e51a60fabf-408778a8ec4so1305564fac.0 for ; Wed, 04 Mar 2026 08:48:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642920; x=1773247720; 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=733+vfQTssEm3IWSGM7mOkOZQibcuFrzuyMXEjUYiFw=; b=G0Vcu+jX7i9xMD5qihTB25QSM4ZqKVOQ+NRkPCEsBVWW86n7JhSIz72KqY4djxb9hZ NRkXPUFjTi0UX3vuId8u+MuD7udzhOma9rvz20n7nDNQkMVfGixcMvZbxNMngsNXTZUz kJbAia1WCGdJYc0h7yr0ZXu/twealfeOy9qeCVYdvd0JwVO1YlcxeuCu0NSD7WVvCs/n KRwF/nDnPU+nDYt0nqEa61geihAuWu7Abkmb3jqNbeqgDb56FerRPCTtvMG7pMBclRH2 asL/xK4idj/wWntoXYcIVla27cjEBCVmb1iXJYHHHATwSmLYD2qaKGtYDyEzuOfo23EC GMyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642920; x=1773247720; 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=733+vfQTssEm3IWSGM7mOkOZQibcuFrzuyMXEjUYiFw=; b=TO0TiwqoZfVDcOvtS5pDoaegLPzCxeJ1lQKKFkhUlLnimX5emKC/h5cbSs6y9GuoTq nQy/6huO+hLIldrWTUC2VTu2m/35elLTjWcCOUcrmH6E24YUSME6rqm28TWnYcWRgqrp Vf6h7/l1it1pb7DMOsOUKm0CqGYWszjiZM7K3J/fRxhTRkfQTvali/mivIbhpM8X65Qo YCbetpQwrlTaRc+ZrNc6+nR9Q3aWu698Ac3iO4ONIC1zSl1FMqjuGqXqDZKtd1ztZBrA 6kLUYzXGkcAZi4n4xr+QXFEvZulyfOuPArNOpoPl/2sy6LKJWd1Wwve2tQpqmZZbgUNU ryZA== X-Gm-Message-State: AOJu0YyR34ZkAe23EzPbzbTJm6cMDrKyD45hfaKsHiNxGu1NptJxLmG8 LmtFwkwUzMU3i6sD0wxZ4kM7tGsBWMEJUF8EQeRJ0uzMLywogaNfiEb1vmG03Q== X-Gm-Gg: ATEYQzzBL7JNZUwfFWWCPhmnttMV6+PAqwsL9zYPvvyY/6nxy+58ozJlnEQ1PnwYurV A9Y2y2Myxj/8golW+v5lwohxiHrowuV6SBTFVCrzaKawQjtg57ySVf6VPC8T5przQ0UYg8gvV6X I7PR+36J2nsJbQYMW5cWp+QF19zCSmhn9Of3V9x64gr/rvREmsUlXJD8Swy+uOJqhx3WiZ3mGm5 sS4cvdgCc9XsHH+OJpT/ONItWhjWleUIis2OX0yKteaoYD9ajaM4VUoYbCumbirl1BH0nbSteEF ySXhXB8uYXt+Jbc0m+M0qoGDTWnO/M78ZogjnPCpEN25iy9nk36dP6ViX7Td3KHOzixerkBJizn gCalwjaLQH0uklXG1zZXQTvRmhT6D9bMfeMU6uFZbW+GkoN55y8pLbtW7fKRIwSgvqLLiSP7HvQ jkqXyHzXfCDz21qzGP770X X-Received: by 2002:a05:6871:ea0a:b0:409:8bfb:c7ba with SMTP id 586e51a60fabf-416abad94fbmr1505119fac.37.1772642919938; Wed, 04 Mar 2026 08:48:39 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:39 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 03/13] spdx3: Add recipe SPDX data Date: Wed, 4 Mar 2026 09:44:14 -0700 Message-ID: <20260304164835.3072507-4-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232392 Adds a new package to the SPDX output that represents the recipe data for a given recipe. Importantly, this data contains only things that can be determined statically from only the recipe, so it doesn't require fetching or building anything. This means that build time dependencies and CVE information for recipes can be analyzed without needing to actually do any builds. Sadly, license data cannot be included because NO_GENERIC_LICENSE means that actual license text might only be available after do_fetch Signed-off-by: Joshua Watt --- meta/classes-global/sstate.bbclass | 4 +- .../create-spdx-image-3.0.bbclass | 4 +- .../create-spdx-sdk-3.0.bbclass | 4 +- meta/classes-recipe/kernel.bbclass | 2 +- meta/classes-recipe/nospdx.bbclass | 1 + meta/classes/create-spdx-2.2.bbclass | 12 +- meta/classes/create-spdx-3.0.bbclass | 51 ++- meta/classes/spdx-common.bbclass | 21 +- meta/lib/oe/spdx30_tasks.py | 402 ++++++++++++------ meta/lib/oeqa/selftest/cases/spdx.py | 19 +- 10 files changed, 354 insertions(+), 166 deletions(-) diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass index 2fd29d7323..95c44f404e 100644 --- a/meta/classes-global/sstate.bbclass +++ b/meta/classes-global/sstate.bbclass @@ -954,7 +954,7 @@ def sstate_checkhashes(sq_data, d, siginfo=False, currentcount=0, summary=True, extrapath = d.getVar("NATIVELSBSTRING") + "/" else: extrapath = "" - + tname = bb.runqueue.taskname_from_tid(task)[3:] if tname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and splithashfn[2]: @@ -1116,7 +1116,7 @@ def setscene_depvalid(task, taskdependees, notneeded, d, log=None): logit("Considering setscene task: %s" % (str(taskdependees[task])), log) - directtasks = ["do_populate_lic", "do_deploy_source_date_epoch", "do_shared_workdir", "do_stash_locale", "do_gcc_stash_builddir", "do_create_spdx", "do_deploy_archives"] + directtasks = ["do_populate_lic", "do_deploy_source_date_epoch", "do_shared_workdir", "do_stash_locale", "do_gcc_stash_builddir", "do_create_spdx", "do_create_recipe_spdx", "do_deploy_archives"] def isNativeCross(x): return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x or x.endswith("-cross") diff --git a/meta/classes-recipe/create-spdx-image-3.0.bbclass b/meta/classes-recipe/create-spdx-image-3.0.bbclass index 636ab14eb0..15a91e90e2 100644 --- a/meta/classes-recipe/create-spdx-image-3.0.bbclass +++ b/meta/classes-recipe/create-spdx-image-3.0.bbclass @@ -34,7 +34,7 @@ addtask do_create_rootfs_spdx after do_rootfs before do_image SSTATETASKS += "do_create_rootfs_spdx" do_create_rootfs_spdx[sstate-inputdirs] = "${SPDXROOTFSDEPLOY}" do_create_rootfs_spdx[sstate-outputdirs] = "${DEPLOY_DIR_SPDX}" -do_create_rootfs_spdx[recrdeptask] += "do_create_spdx do_create_package_spdx" +do_create_rootfs_spdx[recrdeptask] += "do_create_recipe_spdx do_create_spdx do_create_package_spdx" do_create_rootfs_spdx[cleandirs] += "${SPDXROOTFSDEPLOY}" do_create_rootfs_spdx[file-checksums] += "${SPDX3_DEP_FILES}" @@ -76,7 +76,7 @@ do_create_image_sbom_spdx[sstate-inputdirs] = "${SPDXIMAGEDEPLOYDIR}" do_create_image_sbom_spdx[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" do_create_image_sbom_spdx[stamp-extra-info] = "${MACHINE_ARCH}" do_create_image_sbom_spdx[cleandirs] = "${SPDXIMAGEDEPLOYDIR}" -do_create_image_sbom_spdx[recrdeptask] += "do_create_spdx do_create_package_spdx" +do_create_image_sbom_spdx[recrdeptask] += "do_create_recipe_spdx do_create_spdx do_create_package_spdx" do_create_image_sbom_spdx[file-checksums] += "${SPDX3_DEP_FILES}" python do_create_image_sbom_spdx_setscene() { diff --git a/meta/classes-recipe/create-spdx-sdk-3.0.bbclass b/meta/classes-recipe/create-spdx-sdk-3.0.bbclass index e5f220cdfa..a4b8ed3bf9 100644 --- a/meta/classes-recipe/create-spdx-sdk-3.0.bbclass +++ b/meta/classes-recipe/create-spdx-sdk-3.0.bbclass @@ -5,14 +5,14 @@ # # SPDX SDK tasks -do_populate_sdk[recrdeptask] += "do_create_spdx do_create_package_spdx" +do_populate_sdk[recrdeptask] += "do_create_recipe_spdx do_create_spdx do_create_package_spdx" do_populate_sdk[cleandirs] += "${SPDXSDKWORK}" do_populate_sdk[postfuncs] += "sdk_create_sbom" do_populate_sdk[file-checksums] += "${SPDX3_DEP_FILES}" POPULATE_SDK_POST_HOST_COMMAND:append:task-populate-sdk = " sdk_host_create_spdx" POPULATE_SDK_POST_TARGET_COMMAND:append:task-populate-sdk = " sdk_target_create_spdx" -do_populate_sdk_ext[recrdeptask] += "do_create_spdx do_create_package_spdx" +do_populate_sdk_ext[recrdeptask] += "do_create_recipe_spdx do_create_spdx do_create_package_spdx" do_populate_sdk_ext[cleandirs] += "${SPDXSDKEXTWORK}" do_populate_sdk_ext[postfuncs] += "sdk_ext_create_sbom" do_populate_sdk_ext[file-checksums] += "${SPDX3_DEP_FILES}" diff --git a/meta/classes-recipe/kernel.bbclass b/meta/classes-recipe/kernel.bbclass index 22568d6e9c..6621a17f85 100644 --- a/meta/classes-recipe/kernel.bbclass +++ b/meta/classes-recipe/kernel.bbclass @@ -895,7 +895,7 @@ do_create_spdx:append() { except Exception as e: bb.error(f"Failed to parse kernel config file: {e}") - path = oe.sbom30.jsonld_arch_path(d, pkg_arch, "recipes", f"recipe-{pn}", deploydir=deploydir) + path = oe.sbom30.jsonld_arch_path(d, pkg_arch, "builds", f"build-{pn}", deploydir=deploydir) build_objset = oe.sbom30.load_jsonld(d, path, required=True) build = build_objset.find_root(oe.spdx30.build_Build) if not build: diff --git a/meta/classes-recipe/nospdx.bbclass b/meta/classes-recipe/nospdx.bbclass index b20e28218b..90e14442ba 100644 --- a/meta/classes-recipe/nospdx.bbclass +++ b/meta/classes-recipe/nospdx.bbclass @@ -5,6 +5,7 @@ # deltask do_collect_spdx_deps +deltask do_create_recipe_spdx deltask do_create_spdx deltask do_create_spdx_runtime deltask do_create_package_spdx diff --git a/meta/classes/create-spdx-2.2.bbclass b/meta/classes/create-spdx-2.2.bbclass index 65d10d86db..3288cdf75a 100644 --- a/meta/classes/create-spdx-2.2.bbclass +++ b/meta/classes/create-spdx-2.2.bbclass @@ -399,6 +399,15 @@ def get_license_list_version(license_data, d): return ".".join(license_data["licenseListVersion"].split(".")[:2]) +# This task is added for compatibility with tasks shared with SPDX 3, but +# doesn't do anything +do_create_recipe_spdx() { + : +} +do_create_recipe_spdx[noexec] = "1" +addtask do_create_recipe_spdx after do_collect_spdx_deps + + python do_create_spdx() { from datetime import datetime, timezone import oe.sbom @@ -594,7 +603,7 @@ python do_create_spdx() { } do_create_spdx[vardepsexclude] += "BB_NUMBER_THREADS" # NOTE: depending on do_unpack is a hack that is necessary to get it's dependencies for archive the source -addtask do_create_spdx after do_package do_packagedata do_unpack do_collect_spdx_deps before do_populate_sdk do_build do_rm_work +addtask do_create_spdx after do_create_recipe_spdx do_package do_packagedata do_unpack do_patch do_collect_spdx_deps before do_populate_sdk do_build do_rm_work SSTATETASKS += "do_create_spdx" do_create_spdx[sstate-inputdirs] = "${SPDXDEPLOY}" @@ -605,6 +614,7 @@ python do_create_spdx_setscene () { } addtask do_create_spdx_setscene +do_create_spdx[deptask] += "do_create_spdx" do_create_spdx[dirs] = "${SPDXWORK}" do_create_spdx[cleandirs] = "${SPDXDEPLOY} ${SPDXWORK}" do_create_spdx[depends] += " \ diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index d4575d61c4..672ca27cd0 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -159,11 +159,18 @@ SPDX3_DEP_FILES = "\ ${SPDX_LICENSES}:True \ " -python do_create_spdx() { +python do_create_recipe_spdx() { import oe.spdx30_tasks - oe.spdx30_tasks.create_spdx(d) + oe.spdx30_tasks.create_recipe_spdx(d) } -do_create_spdx[vardeps] += "\ +addtask do_create_recipe_spdx after do_collect_spdx_deps + +SSTATETASKS += "do_create_recipe_spdx" +do_create_recipe_spdx[sstate-inputdirs] = "${SPDXRECIPEDEPLOY}" +do_create_recipe_spdx[sstate-outputdirs] = "${DEPLOY_DIR_SPDX}" +do_create_recipe_spdx[file-checksums] += "${SPDX3_DEP_FILES}" +do_create_recipe_spdx[cleandirs] = "${SPDXRECIPEDEPLOY}" +do_create_recipe_spdx[vardeps] += "\ SPDX_INCLUDE_BITBAKE_PARENT_BUILD \ SPDX_PACKAGE_ADDITIONAL_PURPOSE \ SPDX_PROFILES \ @@ -171,7 +178,19 @@ do_create_spdx[vardeps] += "\ SPDX_UUID_NAMESPACE \ " +python do_create_recipe_spdx_setscene () { + sstate_setscene(d) +} +addtask do_create_recipe_spdx_setscene + +python do_create_spdx() { + import oe.spdx30_tasks + oe.spdx30_tasks.create_spdx(d) +} addtask do_create_spdx after \ + do_unpack \ + do_patch \ + do_create_recipe_spdx \ do_collect_spdx_deps \ do_deploy_source_date_epoch \ do_populate_sysroot do_package do_packagedata \ @@ -181,18 +200,25 @@ SSTATETASKS += "do_create_spdx" do_create_spdx[sstate-inputdirs] = "${SPDXDEPLOY}" do_create_spdx[sstate-outputdirs] = "${DEPLOY_DIR_SPDX}" do_create_spdx[file-checksums] += "${SPDX3_DEP_FILES}" - -python do_create_spdx_setscene () { - sstate_setscene(d) -} -addtask do_create_spdx_setscene - +do_create_spdx[deptask] += "do_create_spdx" do_create_spdx[dirs] = "${SPDXWORK}" do_create_spdx[cleandirs] = "${SPDXDEPLOY} ${SPDXWORK}" do_create_spdx[depends] += " \ ${PATCHDEPENDENCY} \ ${@create_spdx_source_deps(d)} \ " +do_create_spdx[vardeps] += "\ + SPDX_INCLUDE_BITBAKE_PARENT_BUILD \ + SPDX_PACKAGE_ADDITIONAL_PURPOSE \ + SPDX_PROFILES \ + SPDX_NAMESPACE_PREFIX \ + SPDX_UUID_NAMESPACE \ + " + +python do_create_spdx_setscene () { + sstate_setscene(d) +} +addtask do_create_spdx_setscene python do_create_package_spdx() { import oe.spdx30_tasks @@ -205,16 +231,15 @@ SSTATETASKS += "do_create_package_spdx" do_create_package_spdx[sstate-inputdirs] = "${SPDXRUNTIMEDEPLOY}" do_create_package_spdx[sstate-outputdirs] = "${DEPLOY_DIR_SPDX}" do_create_package_spdx[file-checksums] += "${SPDX3_DEP_FILES}" +do_create_package_spdx[dirs] = "${SPDXRUNTIMEDEPLOY}" +do_create_package_spdx[cleandirs] = "${SPDXRUNTIMEDEPLOY}" +do_create_package_spdx[rdeptask] = "do_create_spdx" python do_create_package_spdx_setscene () { sstate_setscene(d) } addtask do_create_package_spdx_setscene -do_create_package_spdx[dirs] = "${SPDXRUNTIMEDEPLOY}" -do_create_package_spdx[cleandirs] = "${SPDXRUNTIMEDEPLOY}" -do_create_package_spdx[rdeptask] = "do_create_spdx" - python spdx30_build_started_handler () { import oe.spdx30_tasks d = e.data.createCopy() diff --git a/meta/classes/spdx-common.bbclass b/meta/classes/spdx-common.bbclass index 3110230c9e..3c239a718b 100644 --- a/meta/classes/spdx-common.bbclass +++ b/meta/classes/spdx-common.bbclass @@ -23,6 +23,7 @@ SPDXDEPS = "${SPDXDIR}/deps.json" SPDX_TOOL_NAME ??= "oe-spdx-creator" SPDX_TOOL_VERSION ??= "1.0" +SPDXRECIPEDEPLOY = "${SPDXDIR}/recipe-deploy" SPDXRUNTIMEDEPLOY = "${SPDXDIR}/runtime-deploy" SPDX_INCLUDE_SOURCES ??= "0" @@ -67,12 +68,6 @@ def create_spdx_source_deps(d): deps = [] if d.getVar("SPDX_INCLUDE_SOURCES") == "1": pn = d.getVar('PN') - # do_unpack is a hack for now; we only need it to get the - # dependencies do_unpack already has so we can extract the source - # ourselves - if oe.spdx_common.has_task(d, "do_unpack"): - deps.append("%s:do_unpack" % pn) - if oe.spdx_common.is_work_shared_spdx(d) and \ oe.spdx_common.process_sources(d): # For kernel source code @@ -84,8 +79,6 @@ def create_spdx_source_deps(d): # For gcc-source-${PV} source code if oe.spdx_common.has_task(d, "do_preconfigure"): deps.append("%s:do_preconfigure" % pn) - elif oe.spdx_common.has_task(d, "do_patch"): - deps.append("%s:do_patch" % pn) # For gcc-cross-x86_64 source code elif oe.spdx_common.has_task(d, "do_configure"): deps.append("%s:do_configure" % pn) @@ -97,8 +90,8 @@ python do_collect_spdx_deps() { # This task calculates the build time dependencies of the recipe, and is # required because while a task can deptask on itself, those dependencies # do not show up in BB_TASKDEPDATA. To work around that, this task does the - # deptask on do_create_spdx and writes out the dependencies it finds, then - # do_create_spdx reads in the found dependencies when writing the actual + # deptask on do_create_recipe_spdx and writes out the dependencies it finds, then + # downstream tasks read in the found dependencies when writing the actual # SPDX document import json import oe.spdx_common @@ -106,15 +99,13 @@ python do_collect_spdx_deps() { spdx_deps_file = Path(d.getVar("SPDXDEPS")) - deps = oe.spdx_common.collect_direct_deps(d, "do_create_spdx") + deps = oe.spdx_common.collect_direct_deps(d, "do_create_recipe_spdx") with spdx_deps_file.open("w") as f: json.dump(deps, f) } -# NOTE: depending on do_unpack is a hack that is necessary to get it's dependencies for archive the source -addtask do_collect_spdx_deps after do_unpack -do_collect_spdx_deps[depends] += "${PATCHDEPENDENCY}" -do_collect_spdx_deps[deptask] = "do_create_spdx" +addtask do_collect_spdx_deps +do_collect_spdx_deps[deptask] = "do_create_recipe_spdx" do_collect_spdx_deps[dirs] = "${SPDXDIR}" oe.spdx_common.collect_direct_deps[vardepsexclude] += "BB_TASKDEPDATA" diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index 99f2892dfb..a8b4525e3d 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -32,7 +32,9 @@ def set_timestamp_now(d, o, prop): delattr(o, prop) -def add_license_expression(d, objset, license_expression, license_data): +def add_license_expression( + d, objset, license_expression, license_data, search_objsets=[] +): simple_license_text = {} license_text_map = {} license_ref_idx = 0 @@ -44,14 +46,15 @@ def add_license_expression(d, objset, license_expression, license_data): if name in simple_license_text: return simple_license_text[name] - lic = objset.find_filter( - oe.spdx30.simplelicensing_SimpleLicensingText, - name=name, - ) + for o in [objset] + search_objsets: + lic = o.find_filter( + oe.spdx30.simplelicensing_SimpleLicensingText, + name=name, + ) - if lic is not None: - simple_license_text[name] = lic - return lic + if lic is not None: + simple_license_text[name] = lic + return lic lic = objset.add( oe.spdx30.simplelicensing_SimpleLicensingText( @@ -178,7 +181,9 @@ def add_package_files( # Check if file is compiled if check_compiled_sources: - if not oe.spdx_common.is_compiled_source(filename, compiled_sources, types): + if not oe.spdx_common.is_compiled_source( + filename, compiled_sources, types + ): continue spdx_file = objset.new_file( @@ -293,17 +298,16 @@ def get_package_sources_from_debug( return dep_source_files -def collect_dep_objsets(d, build): +def collect_dep_objsets(d, subdir, fn_prefix, obj_type, **attr_filter): deps = oe.spdx_common.get_spdx_deps(d) dep_objsets = [] - dep_builds = set() + dep_objs = set() - dep_build_spdxids = set() for dep in deps: bb.debug(1, "Fetching SPDX for dependency %s" % (dep.pn)) - dep_build, dep_objset = oe.sbom30.find_root_obj_in_jsonld( - d, "recipes", "recipe-" + dep.pn, oe.spdx30.build_Build + dep_obj, dep_objset = oe.sbom30.find_root_obj_in_jsonld( + d, subdir, fn_prefix + dep.pn, obj_type, **attr_filter ) # If the dependency is part of the taskhash, return it to be linked # against. Otherwise, it cannot be linked against because this recipe @@ -311,10 +315,10 @@ def collect_dep_objsets(d, build): if dep.in_taskhash: dep_objsets.append(dep_objset) - # The build _can_ be linked against (by alias) - dep_builds.add(dep_build) + # The object _can_ be linked against (by alias) + dep_objs.add(dep_obj) - return dep_objsets, dep_builds + return dep_objsets, dep_objs def index_sources_by_hash(sources, dest): @@ -423,9 +427,7 @@ def add_download_files(d, objset): if fd.method.supports_checksum(fd): # TODO Need something better than hard coding this for checksum_id in ["sha256", "sha1"]: - expected_checksum = getattr( - fd, "%s_expected" % checksum_id, None - ) + expected_checksum = getattr(fd, "%s_expected" % checksum_id, None) if expected_checksum is None: continue @@ -462,50 +464,96 @@ def set_purposes(d, element, *var_names, force_purposes=[]): ] -def create_spdx(d): - def set_var_field(var, obj, name, package=None): - val = None - if package: - val = d.getVar("%s:%s" % (var, package)) +def set_purls(spdx_package, purls): + if purls: + spdx_package.software_packageUrl = purls[0] - if not val: - val = d.getVar(var) + for p in sorted(set(purls)): + spdx_package.externalIdentifier.append( + oe.spdx30.ExternalIdentifier( + externalIdentifierType=oe.spdx30.ExternalIdentifierType.packageUrl, + identifier=p, + ) + ) - if val: - setattr(obj, name, val) + +def create_recipe_spdx(d): + deploydir = Path(d.getVar("SPDXRECIPEDEPLOY")) + deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) + pn = d.getVar("PN") license_data = oe.spdx_common.load_spdx_license_data(d) - deploydir = Path(d.getVar("SPDXDEPLOY")) - deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) - spdx_workdir = Path(d.getVar("SPDXWORK")) - include_sources = d.getVar("SPDX_INCLUDE_SOURCES") == "1" - pkg_arch = d.getVar("SSTATE_PKGARCH") - is_native = bb.data.inherits_class("native", d) or bb.data.inherits_class( - "cross", d - ) include_vex = d.getVar("SPDX_INCLUDE_VEX") if not include_vex in ("none", "current", "all"): bb.fatal("SPDX_INCLUDE_VEX must be one of 'none', 'current', 'all'") - build_objset = oe.sbom30.ObjectSet.new_objset(d, "recipe-" + d.getVar("PN")) + recipe_objset = oe.sbom30.ObjectSet.new_objset(d, "static-" + pn) - build = build_objset.new_task_build("recipe", "recipe") - build_objset.set_element_alias(build) + recipe = recipe_objset.add_root( + oe.spdx30.software_Package( + _id=recipe_objset.new_spdxid("recipe", pn), + creationInfo=recipe_objset.doc.creationInfo, + name=d.getVar("PN"), + software_packageVersion=d.getVar("PV"), + software_primaryPurpose=oe.spdx30.software_SoftwarePurpose.specification, + software_sourceInfo=json.dumps( + { + "FILENAME": os.path.basename(d.getVar("FILE")), + "FILE_LAYERNAME": d.getVar("FILE_LAYERNAME"), + }, + separators=(",", ":"), + ), + ) + ) - build_objset.doc.rootElement.append(build) + set_purls(recipe, (d.getVar("SPDX_PACKAGE_URLS") or "").split()) + + # TODO: This doesn't work before do_unpack because the license text has to + # be available for recipes with NO_GENERIC_LICENSE + # recipe_spdx_license = add_license_expression( + # d, + # recipe_objset, + # d.getVar("LICENSE"), + # license_data, + # ) + # recipe_objset.new_relationship( + # [recipe], + # oe.spdx30.RelationshipType.hasDeclaredLicense, + # [oe.sbom30.get_element_link_id(recipe_spdx_license)], + # ) + + if val := d.getVar("HOMEPAGE"): + recipe.software_homePage = val + + if val := d.getVar("SUMMARY"): + recipe.summary = val + + if val := d.getVar("DESCRIPTION"): + recipe.description = val + + for cpe_id in oe.cve_check.get_cpe_ids( + d.getVar("CVE_PRODUCT"), d.getVar("CVE_VERSION") + ): + recipe.externalIdentifier.append( + oe.spdx30.ExternalIdentifier( + externalIdentifierType=oe.spdx30.ExternalIdentifierType.cpe23, + identifier=cpe_id, + ) + ) - build_objset.set_is_native(is_native) + dep_objsets, dep_recipes = collect_dep_objsets( + d, "static", "static-", oe.spdx30.software_Package + ) - for var in (d.getVar("SPDX_CUSTOM_ANNOTATION_VARS") or "").split(): - build_objset.new_annotation( - build, - "%s=%s" % (var, d.getVar(var)), - oe.spdx30.AnnotationType.other, + if dep_recipes: + recipe_objset.new_scoped_relationship( + [recipe], + oe.spdx30.RelationshipType.dependsOn, + oe.spdx30.LifecycleScopeType.build, + sorted(oe.sbom30.get_element_link_id(dep) for dep in dep_recipes), ) - build_inputs = set() - # Add CVEs cve_by_status = {} if include_vex != "none": @@ -514,7 +562,7 @@ def create_spdx(d): decoded_status = { "mapping": patched_cve["abbrev-status"], "detail": patched_cve["status"], - "description": patched_cve.get("justification", None) + "description": patched_cve.get("justification", None), } # If this CVE is fixed upstream, skip it unless all CVEs are @@ -531,8 +579,7 @@ def create_spdx(d): bb.debug(1, "Skipping %s since it is already fixed upstream" % cve) continue - spdx_cve = build_objset.new_cve_vuln(cve) - build_objset.set_element_alias(spdx_cve) + spdx_cve = recipe_objset.new_cve_vuln(cve) cve_by_status.setdefault(decoded_status["mapping"], {})[cve] = ( spdx_cve, @@ -540,13 +587,118 @@ def create_spdx(d): decoded_status["description"], ) + all_cves = set() + for status, cves in cve_by_status.items(): + for cve, items in cves.items(): + spdx_cve, detail, description = items + spdx_cve_id = oe.sbom30.get_element_link_id(spdx_cve) + + all_cves.add(spdx_cve) + + if status == "Patched": + recipe_objset.new_vex_patched_relationship([spdx_cve_id], [recipe]) + elif status == "Unpatched": + recipe_objset.new_vex_unpatched_relationship([spdx_cve_id], [recipe]) + elif status == "Ignored": + spdx_vex = recipe_objset.new_vex_ignored_relationship( + [spdx_cve_id], + [recipe], + impact_statement=description, + ) + + vex_just_type = d.getVarFlag("CVE_CHECK_VEX_JUSTIFICATION", detail) + if vex_just_type: + if ( + vex_just_type + not in oe.spdx30.security_VexJustificationType.NAMED_INDIVIDUALS + ): + bb.fatal( + f"Unknown vex justification '{vex_just_type}', detail '{detail}', for ignored {cve}" + ) + + for v in spdx_vex: + v.security_justificationType = ( + oe.spdx30.security_VexJustificationType.NAMED_INDIVIDUALS[ + vex_just_type + ] + ) + + elif status == "Unknown": + bb.note(f"Skipping {cve} with status 'Unknown'") + else: + bb.fatal(f"Unknown {cve} status '{status}'") + + if all_cves: + recipe_objset.new_relationship( + [recipe], + oe.spdx30.RelationshipType.hasAssociatedVulnerability, + sorted(list(all_cves)), + ) + + oe.sbom30.write_recipe_jsonld_doc(d, recipe_objset, "static", deploydir) + + +def load_recipe_spdx(d): + + return oe.sbom30.find_root_obj_in_jsonld( + d, + "static", + "static-" + d.getVar("PN"), + oe.spdx30.software_Package, + ) + + +def create_spdx(d): + def set_var_field(var, obj, name, package=None): + val = None + if package: + val = d.getVar("%s:%s" % (var, package)) + + if not val: + val = d.getVar(var) + + if val: + setattr(obj, name, val) + + license_data = oe.spdx_common.load_spdx_license_data(d) + + pn = d.getVar("PN") + deploydir = Path(d.getVar("SPDXDEPLOY")) + deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) + spdx_workdir = Path(d.getVar("SPDXWORK")) + include_sources = d.getVar("SPDX_INCLUDE_SOURCES") == "1" + pkg_arch = d.getVar("SSTATE_PKGARCH") + is_native = bb.data.inherits_class("native", d) or bb.data.inherits_class( + "cross", d + ) + + recipe, recipe_objset = load_recipe_spdx(d) + + build_objset = oe.sbom30.ObjectSet.new_objset(d, "build-" + pn) + + build = build_objset.new_task_build("recipe", "recipe") + build_objset.set_element_alias(build) + + build_objset.doc.rootElement.append(build) + + build_objset.set_is_native(is_native) + + for var in (d.getVar("SPDX_CUSTOM_ANNOTATION_VARS") or "").split(): + build_objset.new_annotation( + build, + "%s=%s" % (var, d.getVar(var)), + oe.spdx30.AnnotationType.other, + ) + + build_inputs = set() + cpe_ids = oe.cve_check.get_cpe_ids(d.getVar("CVE_PRODUCT"), d.getVar("CVE_VERSION")) source_files = add_download_files(d, build_objset) build_inputs |= source_files recipe_spdx_license = add_license_expression( - d, build_objset, d.getVar("LICENSE"), license_data + d, build_objset, d.getVar("LICENSE"), license_data, [recipe_objset] ) build_objset.new_relationship( source_files, @@ -575,7 +727,10 @@ def create_spdx(d): build_inputs |= files index_sources_by_hash(files, dep_sources) - dep_objsets, dep_builds = collect_dep_objsets(d, build) + dep_objsets, dep_builds = collect_dep_objsets( + d, "builds", "build-", oe.spdx30.build_Build + ) + if dep_builds: build_objset.new_scoped_relationship( [build], @@ -587,6 +742,22 @@ def create_spdx(d): debug_source_ids = set() source_hash_cache = {} + # Collect all VEX statements from the recipe + vex_statements = {} + for rel in recipe_objset.foreach_filter( + oe.spdx30.Relationship, + relationshipType=oe.spdx30.RelationshipType.hasAssociatedVulnerability, + ): + for cve in rel.to: + vex_statements[cve] = [] + + for cve in vex_statements.keys(): + for rel in recipe_objset.foreach_filter( + oe.spdx30.security_VexVulnAssessmentRelationship, + from_=cve, + ): + vex_statements[cve].append(rel) + # Write out the package SPDX data now. It is not complete as we cannot # write the runtime data, so write it to a staging area and a later task # will write out the final collection @@ -645,16 +816,7 @@ def create_spdx(d): or "" ).split() - if purls: - spdx_package.software_packageUrl = purls[0] - - for p in sorted(set(purls)): - spdx_package.externalIdentifier.append( - oe.spdx30.ExternalIdentifier( - externalIdentifierType=oe.spdx30.ExternalIdentifierType.packageUrl, - identifier=p, - ) - ) + set_purls(spdx_package, purls) pkg_objset.new_scoped_relationship( [oe.sbom30.get_element_link_id(build)], @@ -663,6 +825,13 @@ def create_spdx(d): [spdx_package], ) + pkg_objset.new_scoped_relationship( + [oe.sbom30.get_element_link_id(recipe)], + oe.spdx30.RelationshipType.generates, + oe.spdx30.LifecycleScopeType.build, + [spdx_package], + ) + for cpe_id in cpe_ids: spdx_package.externalIdentifier.append( oe.spdx30.ExternalIdentifier( @@ -696,7 +865,11 @@ def create_spdx(d): package_license = d.getVar("LICENSE:%s" % package) if package_license and package_license != d.getVar("LICENSE"): package_spdx_license = add_license_expression( - d, build_objset, package_license, license_data + d, + build_objset, + package_license, + license_data, + [recipe_objset], ) else: package_spdx_license = recipe_spdx_license @@ -721,58 +894,41 @@ def create_spdx(d): [oe.sbom30.get_element_link_id(concluded_spdx_license)], ) - # NOTE: CVE Elements live in the recipe collection - all_cves = set() - for status, cves in cve_by_status.items(): - for cve, items in cves.items(): - spdx_cve, detail, description = items - spdx_cve_id = oe.sbom30.get_element_link_id(spdx_cve) - - all_cves.add(spdx_cve_id) + # Copy CVEs from recipe + if vex_statements: + pkg_objset.new_relationship( + [spdx_package], + oe.spdx30.RelationshipType.hasAssociatedVulnerability, + sorted( + oe.sbom30.get_element_link_id(cve) + for cve in vex_statements.keys() + ), + ) - if status == "Patched": + for cve, vexes in vex_statements.items(): + for vex in vexes: + if vex.relationshipType == oe.spdx30.RelationshipType.fixedIn: pkg_objset.new_vex_patched_relationship( - [spdx_cve_id], [spdx_package] + [oe.sbom30.get_element_link_id(cve)], [spdx_package] ) - elif status == "Unpatched": + elif vex.relationshipType == oe.spdx30.RelationshipType.affects: pkg_objset.new_vex_unpatched_relationship( - [spdx_cve_id], [spdx_package] + [oe.sbom30.get_element_link_id(cve)], [spdx_package] ) - elif status == "Ignored": + elif ( + vex.relationshipType == oe.spdx30.RelationshipType.doesNotAffect + ): spdx_vex = pkg_objset.new_vex_ignored_relationship( - [spdx_cve_id], + [oe.sbom30.get_element_link_id(cve)], [spdx_package], - impact_statement=description, + impact_statement=vex.security_impactStatement, ) - vex_just_type = d.getVarFlag( - "CVE_CHECK_VEX_JUSTIFICATION", detail - ) - if vex_just_type: - if ( - vex_just_type - not in oe.spdx30.security_VexJustificationType.NAMED_INDIVIDUALS - ): - bb.fatal( - f"Unknown vex justification '{vex_just_type}', detail '{detail}', for ignored {cve}" - ) - + if vex.security_justificationType: for v in spdx_vex: - v.security_justificationType = oe.spdx30.security_VexJustificationType.NAMED_INDIVIDUALS[ - vex_just_type - ] - - elif status == "Unknown": - bb.note(f"Skipping {cve} with status 'Unknown'") - else: - bb.fatal(f"Unknown {cve} status '{status}'") - - if all_cves: - pkg_objset.new_relationship( - [spdx_package], - oe.spdx30.RelationshipType.hasAssociatedVulnerability, - sorted(list(all_cves)), - ) + v.security_justificationType = ( + vex.security_justificationType + ) bb.debug(1, "Adding package files to SPDX for package %s" % pkg_name) package_files = add_package_files( @@ -851,14 +1007,15 @@ def create_spdx(d): status = "enabled" if feature in enabled else "disabled" build.build_parameter.append( oe.spdx30.DictionaryEntry( - key=f"PACKAGECONFIG:{feature}", - value=status + key=f"PACKAGECONFIG:{feature}", value=status ) ) - bb.note(f"Added PACKAGECONFIG entries: {len(enabled)} enabled, {len(disabled)} disabled") + bb.note( + f"Added PACKAGECONFIG entries: {len(enabled)} enabled, {len(disabled)} disabled" + ) - oe.sbom30.write_recipe_jsonld_doc(d, build_objset, "recipes", deploydir) + oe.sbom30.write_recipe_jsonld_doc(d, build_objset, "builds", deploydir) def create_package_spdx(d): @@ -1197,17 +1354,17 @@ def create_image_spdx(d): image_path = image_deploy_dir / image_filename if os.path.isdir(image_path): a = add_package_files( - d, - objset, - image_path, - lambda file_counter: objset.new_spdxid( - "imagefile", str(file_counter) - ), - lambda filepath: [], - license_data=None, - ignore_dirs=[], - ignore_top_level_dirs=[], - archive=None, + d, + objset, + image_path, + lambda file_counter: objset.new_spdxid( + "imagefile", str(file_counter) + ), + lambda filepath: [], + license_data=None, + ignore_dirs=[], + ignore_top_level_dirs=[], + archive=None, ) artifacts.extend(a) else: @@ -1234,7 +1391,6 @@ def create_image_spdx(d): set_timestamp_now(d, a, "builtTime") - if artifacts: objset.new_scoped_relationship( [image_build], diff --git a/meta/lib/oeqa/selftest/cases/spdx.py b/meta/lib/oeqa/selftest/cases/spdx.py index 5830d7c087..759ca86b73 100644 --- a/meta/lib/oeqa/selftest/cases/spdx.py +++ b/meta/lib/oeqa/selftest/cases/spdx.py @@ -141,6 +141,11 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): SPDX_CLASS = "create-spdx-3.0" def test_base_files(self): + self.check_recipe_spdx( + "base-files", + "{DEPLOY_DIR_SPDX}/{MACHINE_ARCH}/static/static-base-files.spdx.json", + task="create_recipe_spdx", + ) self.check_recipe_spdx( "base-files", "{DEPLOY_DIR_SPDX}/{MACHINE_ARCH}/packages/package-base-files.spdx.json", @@ -149,7 +154,7 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): def test_gcc_include_source(self): objset = self.check_recipe_spdx( "gcc", - "{DEPLOY_DIR_SPDX}/{SSTATE_PKGARCH}/recipes/recipe-gcc.spdx.json", + "{DEPLOY_DIR_SPDX}/{SSTATE_PKGARCH}/builds/build-gcc.spdx.json", extraconf="""\ SPDX_INCLUDE_SOURCES = "1" """, @@ -162,12 +167,12 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): if software_file.name == filename: found = True self.logger.info( - f"The spdxId of {filename} in recipe-gcc.spdx.json is {software_file.spdxId}" + f"The spdxId of {filename} in build-gcc.spdx.json is {software_file.spdxId}" ) break self.assertTrue( - found, f"Not found source file {filename} in recipe-gcc.spdx.json\n" + found, f"Not found source file {filename} in build-gcc.spdx.json\n" ) def test_core_image_minimal(self): @@ -305,7 +310,7 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): # This will fail with NameError if new_annotation() is called incorrectly objset = self.check_recipe_spdx( "base-files", - "{DEPLOY_DIR_SPDX}/{MACHINE_ARCH}/recipes/recipe-base-files.spdx.json", + "{DEPLOY_DIR_SPDX}/{MACHINE_ARCH}/builds/build-base-files.spdx.json", extraconf=textwrap.dedent( f"""\ ANNOTATION1 = "{ANNOTATION_VAR1}" @@ -360,8 +365,8 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): def test_kernel_config_spdx(self): kernel_recipe = get_bb_var("PREFERRED_PROVIDER_virtual/kernel") - spdx_file = f"recipe-{kernel_recipe}.spdx.json" - spdx_path = f"{{DEPLOY_DIR_SPDX}}/{{SSTATE_PKGARCH}}/recipes/{spdx_file}" + spdx_file = f"build-{kernel_recipe}.spdx.json" + spdx_path = f"{{DEPLOY_DIR_SPDX}}/{{SSTATE_PKGARCH}}/builds/{spdx_file}" # Make sure kernel is configured first bitbake(f"-c configure {kernel_recipe}") @@ -392,7 +397,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}/builds/build-tar.spdx.json", extraconf="""\ SPDX_INCLUDE_PACKAGECONFIG = "1" """, From patchwork Wed Mar 4 16:44:15 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82479 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 53E8EEF901E for ; Wed, 4 Mar 2026 16:48:47 +0000 (UTC) Received: from mail-oa1-f47.google.com (mail-oa1-f47.google.com [209.85.160.47]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.22976.1772642921686010018 for ; Wed, 04 Mar 2026 08:48:41 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=ZUusxu6i; spf=pass (domain: gmail.com, ip: 209.85.160.47, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f47.google.com with SMTP id 586e51a60fabf-40438e0cba6so1474095fac.1 for ; Wed, 04 Mar 2026 08:48:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642921; x=1773247721; 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=0AODhThGJ5yZROpI3OOikCCsiX15Pqojv0hH5uqF+es=; b=ZUusxu6ifPjoKqu7kRLk/SKN/CQnHC4Okj9I1lSqcuH2Wh4wM2hUhj62IrpM7xoiZp PghW2zOf993Qud8T6kh9+A0RyF4pUNMhSim+ZvBYr9oyJvNObKnbWwIQqK0XK1gAs/q6 o+aYykrngH7o3T2GnUxuVQlBTcqBLdEuA/xrUdwffkXbZ8ix0vLDWcgzwywGY8Hip9ar CtORD0O8nGRPIavz5PSuUHgAAAajCm7X30QOmm7tAvh3A4QrRx93dXTliYwcd5T89WbV VNICsE+UOdUL6egXohCTdorIeDsf7FAyycQDvFbLXmNWu5BkmiTnLZf3OGZgAkudraTj In5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642921; x=1773247721; 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=0AODhThGJ5yZROpI3OOikCCsiX15Pqojv0hH5uqF+es=; b=g1YX3jR0VWkGO9E6M0LfpIVJ+U22rc+iXityprHrtliM4uaNEgxS/UbA037z4ifXp7 HfV2J6fvpeeb0tpqGTfPBc+im0sPLW2WwmZWmeCOJ33gneY0gPCfkAeHADChF7PCeW5W 3V42K8j1e7D1B0Hs/BttpRi+3q3Vby09yl1C9i+Tatrpd80j22RcTzbbD3Gv9OZpeRHl IM1okbXSg3wL4WwWyrpF0FVnxFZDwK0dFB3Tgl96dNjmywVyiMoaaOuN3E7jcO58wiBP I28PX0wPBmqSLg+ZnBJbCpBPTbSmIYXTneTe9yRUM30MXNN43cg6k5XyfrVKtyqMtDIK pxHQ== X-Gm-Message-State: AOJu0YxLc7Uz8zQjIm3r8rxlK8tZnZaZD5GeVt2AkAWq9Rzn5ZL5WFjK OsgP2gl3hjH3Hs6gk+RlhndFhNDSBZGIuZCcZiXAGz/UuprEyKiWjEg9z+jW9A== X-Gm-Gg: ATEYQzwBugR7qJqNvHdpv4bWSSA0XGXJyUxaCehnlsgaAxEG5kdofi/UUqhmFZ9bHFs Iv99PsIjQKyeOmSgC5RztyVE+YT0K2OMIjU9KJrTrZHgqd/lxZOuuz3vBgFQoRfajZYCo3pq7WH gtMmas8zadlruYMuMGBIefEqFtdPs07KY7OZbWXfoAcjhwdrwC5DvC3tekJt/y3WqDcEjkabcEy qStvGDUC7x1Zwvu7hEjzQG2i6scufooQA2a2fwLIGccrBWuOEz4er15DLqdEWwFpLMMr2lUlpS8 Aula7Ei1GPUUNoifgIdVu/nxlpcCbmBw1mhspfrDCr3tiLjvjjcC4bz1x5ZltKbRA4VErK3G19F Cr1rW9wZJ8/G90U4bBpI9CEzZUjfDTcXnX6yHosPamuKkv4YbEvdLFsOiZTCLI4+xtB/nmxZs4b WgCg3ztO0SsBcVLdaG+qBT X-Received: by 2002:a05:6871:a981:b0:40e:e0b2:e375 with SMTP id 586e51a60fabf-416aba5c9d2mr1543601fac.31.1772642920476; Wed, 04 Mar 2026 08:48:40 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:40 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 04/13] spdx3: Add recipe SBoM task Date: Wed, 4 Mar 2026 09:44:15 -0700 Message-ID: <20260304164835.3072507-5-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:47 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232393 Adds a task that will create the complete recipe-level SBoM for a given target recipe, following all dependencies. For example: ``` bitbake -c create_recipe_sbom zstd ``` Would produce the complete recipe SBoM for the zstd recipe, include all build time dependencies (recursively). The complete SBoM for all (target) recipes can be built with: ``` bitbake -c create_recipe_sbom meta-world-recipe-sbom ``` Signed-off-by: Joshua Watt --- meta/classes/create-spdx-3.0.bbclass | 32 +++++++++++++++++++ meta/classes/spdx-common.bbclass | 1 + meta/conf/distro/include/maintainers.inc | 1 + meta/lib/oe/spdx30_tasks.py | 10 ++++++ meta/lib/oeqa/selftest/cases/spdx.py | 10 ++++++ .../meta/meta-world-recipe-sbom.bb | 29 +++++++++++++++++ 6 files changed, 83 insertions(+) create mode 100644 meta/recipes-core/meta/meta-world-recipe-sbom.bb diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index 672ca27cd0..c3ea95b8bc 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -142,6 +142,10 @@ 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_RECIPE_SBOM_NAME ?= "${PN}-recipe-sbom" +SPDX_RECIPE_SBOM_NAME[doc] = "The name of output recipe SBoM when using \ + create_recipe_sbom" + IMAGE_CLASSES:append = " create-spdx-image-3.0" SDK_CLASSES += "create-spdx-sdk-3.0" @@ -240,6 +244,34 @@ python do_create_package_spdx_setscene () { } addtask do_create_package_spdx_setscene +addtask do_create_recipe_sbom after create_recipe_spdx +python do_create_recipe_sbom() { + import oe.spdx30_tasks + from pathlib import Path + deploydir = Path(d.getVar("SPDXRECIPESBOMDEPLOY")) + oe.spdx30_tasks.create_recipe_sbom(d, deploydir) +} + +SSTATETASKS += "do_create_recipe_sbom" +do_create_recipe_sbom[recrdeptask] = "do_create_recipe_spdx" +do_create_recipe_sbom[nostamp] = "1" +do_create_recipe_sbom[sstate-inputdirs] = "${SPDXRECIPESBOMDEPLOY}" +do_create_recipe_sbom[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" +do_create_recipe_sbom[file-checksums] += "${SPDX3_DEP_FILES}" +do_create_recipe_sbom[cleandirs] = "${SPDXRECIPESBOMDEPLOY}" +do_create_recipe_sbom[vardeps] += "\ + SPDX_INCLUDE_BITBAKE_PARENT_BUILD \ + SPDX_PACKAGE_ADDITIONAL_PURPOSE \ + SPDX_PROFILES \ + SPDX_NAMESPACE_PREFIX \ + SPDX_UUID_NAMESPACE \ + " + +python do_create_recipe_sbom_setscene () { + sstate_setscene(d) +} +addtask do_create_recipe_sbom_setscene + python spdx30_build_started_handler () { import oe.spdx30_tasks d = e.data.createCopy() diff --git a/meta/classes/spdx-common.bbclass b/meta/classes/spdx-common.bbclass index 3c239a718b..abf2332bee 100644 --- a/meta/classes/spdx-common.bbclass +++ b/meta/classes/spdx-common.bbclass @@ -25,6 +25,7 @@ SPDX_TOOL_VERSION ??= "1.0" SPDXRECIPEDEPLOY = "${SPDXDIR}/recipe-deploy" SPDXRUNTIMEDEPLOY = "${SPDXDIR}/runtime-deploy" +SPDXRECIPESBOMDEPLOY = "${SPDXDIR}/recipes-bom-deploy" SPDX_INCLUDE_SOURCES ??= "0" SPDX_INCLUDE_COMPILED_SOURCES ??= "0" diff --git a/meta/conf/distro/include/maintainers.inc b/meta/conf/distro/include/maintainers.inc index b5ab35d92a..5bea863798 100644 --- a/meta/conf/distro/include/maintainers.inc +++ b/meta/conf/distro/include/maintainers.inc @@ -532,6 +532,7 @@ RECIPE_MAINTAINER:pn-meta-go-toolchain = "Richard Purdie X-Patchwork-Id: 82466 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 5B6C1EF9008 for ; Wed, 4 Mar 2026 16:48:46 +0000 (UTC) Received: from mail-oa1-f43.google.com (mail-oa1-f43.google.com [209.85.160.43]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.23107.1772642922380092326 for ; Wed, 04 Mar 2026 08:48:42 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=fvJJj+/m; spf=pass (domain: gmail.com, ip: 209.85.160.43, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-409de4132b5so1500656fac.1 for ; Wed, 04 Mar 2026 08:48:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642921; x=1773247721; 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=+wYSZS61IRGHmLD9OmiNc9hgO2b0xZj5mQwHOFCwfH8=; b=fvJJj+/mkP6kGilcFZQhFieFeReT+9n1ZzWIgvphrjxpO8L+NqCaE4ExlEWF9hkkQB C5ea7pSv8lROn/jyqGZU/vJ7x5vkPaxsbr4z+6sMbHB/MFC8GuYAliJJgFUSgT9TkAHg 3s1H2tEWCD985JpljKQskgfQh+UKShQu4vSrPctuMtemjw1KpvwASgrLc1At5ArfNf0H 5YmgEw2MQmQ7iQRlsnUmq/3Svo8JDQv351jPVoWGDUefoDqbomJqKxTBA1fA9sv1Pu3B +I073/hL79e+XWmBC+wpUcbRVgPV3FOq9sj7CFcU3XPV9NUe3CS/OItOXygzwa6rFuhC 5eQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642921; x=1773247721; 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=+wYSZS61IRGHmLD9OmiNc9hgO2b0xZj5mQwHOFCwfH8=; b=VkWBDiFDHLyo+HWbDp9vkbCnLM/hgkx9vZdRIUwTt1QEuD8Ngb0G8Zve1IZon970kS hMsM+PvGsSBxMK9ldyF9QcQEUwdlo3FcitrBAwb/GW3LKHPW7W2iokkGUb6AP0aeo4zb l5w7olK1hjlhb27dFBGhT4kAOv5NKbdOqdscE5H3NvXQb9hPn2C1AFAPQOL2YXLNfiEr pFDjpuMmKUjH8mR5nUF2lhAhG6cIdv+TeaJA8ESGnOuTi6qJp82pMkXm210o5mBmRSSq ZyWxNbZ3lTwgWtvMXOIGOZCvfws6lWbrNK44zPryIO80oZGmuTMfKRUEDo8GvFehmbuF OWkw== X-Gm-Message-State: AOJu0YzDgil5HhovrBn1lfmcPU97u6hDng8FdBEbr6GzbENo0x4yNutF CVQwwy+SGTWuPK5nMNpSAgDn3FSxXlZQhiFBUA4pKKYnxnLAgTvA+ABuBgB2Fw== X-Gm-Gg: ATEYQzwfzJOFlMuPTZn4sBCrVtcjBJtQQKkc7qaaVjA+CQ2emaH7K7xWfXpVhAaNqwa wgJ4SbuckRT09H2bhPl0K0HUkLPDjSPBb54ClCExUCa1jCp3/rKR6Mj8bxQbVM05Pby8aXYZpUs HFfCGz3zrV9u5z+5GlJR4ygicZ+RmxQRXZrmgJ9mZSGL0GOloem7SLHI5pvAE0oRqu9U/z9DO0W GpOCXifXp/CN3UeF7BAMowxy9f/uE0KYuZg22IHxUP9auXM+IdJVEoFZc4nh07YyK15vK1Tm8WX sDsN1dNE2MjHasXsIr6bQBSBw6kWFGGbfEZ5DPObsVbHBNNGGs+bFzBEqSXnt04TtBnNSj6//qj J5MNICZZjQzfPj9M75rrhs0Wk8E9eNSrQkfwSlR60CkYD7mIWGuJzNHZodi4Iznbpze3DIPghOu /zeYF57xnsFpSX8nA+tpHY X-Received: by 2002:a05:6870:4510:b0:40e:dfb7:d1a8 with SMTP id 586e51a60fabf-416abb66fa5mr1551372fac.33.1772642921362; Wed, 04 Mar 2026 08:48:41 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:40 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 05/13] spdx3: Add is-native property Date: Wed, 4 Mar 2026 09:44:16 -0700 Message-ID: <20260304164835.3072507-6-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232394 Adds a custom is-native property to the recipe package to indicate if it is a native recipe Signed-off-by: Joshua Watt --- meta/lib/oe/sbom30.py | 20 ++++++++++++++++++++ meta/lib/oe/spdx30_tasks.py | 18 +++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/meta/lib/oe/sbom30.py b/meta/lib/oe/sbom30.py index 227ac51877..50a72fce39 100644 --- a/meta/lib/oe/sbom30.py +++ b/meta/lib/oe/sbom30.py @@ -118,6 +118,26 @@ class OEDocumentExtension(oe.spdx30.extension_Extension): ) +@oe.spdx30.register(OE_SPDX_BASE + "recipe-extension") +class OERecipeExtension(oe.spdx30.extension_Extension): + """ + This extension is added to recipe software_Packages to indicate various + useful bits of information about the recipe + """ + + CLOSED = True + + @classmethod + def _register_props(cls): + super()._register_props() + cls._add_property( + "is_native", + oe.spdx30.BooleanProp(), + OE_SPDX_BASE + "is-native", + max_count=1, + ) + + def spdxid_hash(*items): h = hashlib.md5() for i in items: diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index b6c917045e..a8fffbb085 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -477,6 +477,10 @@ def set_purls(spdx_package, purls): ) +def get_is_native(d): + return bb.data.inherits_class("native", d) or bb.data.inherits_class("cross", d) + + def create_recipe_spdx(d): deploydir = Path(d.getVar("SPDXRECIPEDEPLOY")) deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) @@ -507,6 +511,11 @@ def create_recipe_spdx(d): ) ) + if get_is_native(d): + ext = oe.sbom30.OERecipeExtension() + ext.is_native = True + recipe.extension.append(ext) + set_purls(recipe, (d.getVar("SPDX_PACKAGE_URLS") or "").split()) # TODO: This doesn't work before do_unpack because the license text has to @@ -668,9 +677,7 @@ def create_spdx(d): spdx_workdir = Path(d.getVar("SPDXWORK")) include_sources = d.getVar("SPDX_INCLUDE_SOURCES") == "1" pkg_arch = d.getVar("SSTATE_PKGARCH") - is_native = bb.data.inherits_class("native", d) or bb.data.inherits_class( - "cross", d - ) + is_native = get_is_native(d) recipe, recipe_objset = load_recipe_spdx(d) @@ -1021,14 +1028,11 @@ def create_spdx(d): def create_package_spdx(d): deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) deploydir = Path(d.getVar("SPDXRUNTIMEDEPLOY")) - is_native = bb.data.inherits_class("native", d) or bb.data.inherits_class( - "cross", d - ) providers = oe.spdx_common.collect_package_providers(d) pkg_arch = d.getVar("SSTATE_PKGARCH") - if is_native: + if get_is_native(d): return bb.build.exec_func("read_subpackage_metadata", d) From patchwork Wed Mar 4 16:44:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82467 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 69A39EF900A for ; Wed, 4 Mar 2026 16:48:46 +0000 (UTC) Received: from mail-oa1-f47.google.com (mail-oa1-f47.google.com [209.85.160.47]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.22978.1772642923392736850 for ; Wed, 04 Mar 2026 08:48:43 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=OLZTj+1G; spf=pass (domain: gmail.com, ip: 209.85.160.47, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f47.google.com with SMTP id 586e51a60fabf-40ea611d1a4so864693fac.2 for ; Wed, 04 Mar 2026 08:48:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642922; x=1773247722; 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=GygUv99XXYXKewxHRq+dVr3zF/qZkskkMg0YO5XWbQU=; b=OLZTj+1GXjZxvPVlHFHkuZfwE4t4qSaMMtWK4NRvmkBflzCkC/kvjPE1Cl7BLK7+DW N0hWnFmmt+IN5avU2uaL4+fhXtFKV5KtPwqeeaIU0nvsxRxiA1/I2lxCV56CiAGK1Gm7 ctCjZ0kM/HXL7CVgx5GAPpL2Ei0kItvH98neaSFEsuPuz3SLSbFxTmq7V6cZunpV6OWj 4fGgARCpm9uZWV4Qgh8ye0CUJwrlmXVLD42ODJLdIEptSE4UktAfyjWMI/ZTOAvljfYG Kl5z1iHveg0O1rhAx8XgsQpk3A3yqVv3aWk9hVD6uv0oKVkWATw/T6xW98+KCdi04rH3 nJQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642922; x=1773247722; 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=GygUv99XXYXKewxHRq+dVr3zF/qZkskkMg0YO5XWbQU=; b=TggGonzI20KT0PlA1b4nf1Hyie+pe9I67OdLEwVzHgJ//TuP6lJu6YwwJEFSy79fxo YQqXHrRygt9ED9VlIkWdMZlWOxsvoZnCYNmjQnrjzcoFbiGOmilXfMJ6/QmMsMbPwYDY CO7vB6CvOWrUYtpH0MpaZir+WvgI5HOXE2WTLWDfIw+PAfWCtJa2x79h0O1+XTJrzbbV uL/mesV3aOwp+T28YHUwRctrJDAMuagEWRX8lQlJ1vBfNFCJ54iQMsX5qmtOLmBNOOMX bpDaL50p/uPw6RC7sbu2tPAN0mcn26jvmJhBTFLz0sk5N9P5YMKGVs0rLN1hHj5oZBMc 7DsA== X-Gm-Message-State: AOJu0Yxb1iEOMdS98iCN3fcRlFg2G5DQMoBjYUUVOpa3OG9+bM+Fm30X 04RSGbyB0pmqfEIVMd7eNrcl/ehKMwMoOUn+UCC7gw8LNeT10LNqSHs5ktIS9g== X-Gm-Gg: ATEYQzyLHWO06M3pn8n0PmhoL/DJm0T+gYyLYbf6w3qwNG9oPSzDFWFMPtokH46aWWm btv/9LUjgaxbs82IwG9mDq51IS26BUzo6OkAZ6OwNzkJggsBD0M79vY5eEbhZRJX6VH24SNy60O h7y5N91k5DmNLwkT7FobbRZcMW7UlA2s0oNsVtt8Qpm/T0Q+50nFNSkefspimRGMuXk5MnVaCjj OBrYorCkFENukPxrHubaTDbuV2qrPWbAKUAS41oJwM6YlwsAxcpJAJCUIF86LYUMlj365jwdjBo iFqGLihtgQAlmaFzIDYXVtHhL1QodJdiyRs4erlzdSYlWd+DgT/5x0qvcswcHFLDp5OAjcSeSPG GyklltVwo5PXGHiIT0iPtW4i4Hvo98wIFTqw/+jNfGXVM8bP+0xtbN5Bo5gWkJOeixK+QTouzcf NJ0CAb08dYDE4bQo8uRIly X-Received: by 2002:a05:6871:288d:b0:409:4195:5c25 with SMTP id 586e51a60fabf-416ab601af2mr1450449fac.20.1772642922185; Wed, 04 Mar 2026 08:48:42 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:41 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 06/13] spdx30: Include patch file information in VEX Date: Wed, 4 Mar 2026 09:44:17 -0700 Message-ID: <20260304164835.3072507-7-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232395 Modifies the SPDX VEX output to include the patches that fix a particular vulnerability. This is done by adding a `patchedBy` relationship from the `VexFixedVulnAssessmentRelationship` to the `File` that provides the fix. If the file can be located without fetching (e.g. is a file:// in SRC_URI), the checksum will be included. Signed-off-by: Joshua Watt --- meta/lib/oe/sbom30.py | 60 ++++++++++++++------------- meta/lib/oe/spdx30_tasks.py | 81 ++++++++++++++++++++++++++++--------- 2 files changed, 92 insertions(+), 49 deletions(-) diff --git a/meta/lib/oe/sbom30.py b/meta/lib/oe/sbom30.py index 50a72fce39..21f084dc16 100644 --- a/meta/lib/oe/sbom30.py +++ b/meta/lib/oe/sbom30.py @@ -620,37 +620,38 @@ class ObjectSet(oe.spdx30.SHACLObjectSet): ) spdx_file.extension.append(OELicenseScannedExtension()) - def new_file(self, _id, name, path, *, purposes=[]): - sha256_hash = bb.utils.sha256_file(path) + def new_file(self, _id, name, path, *, purposes=[], hashfile=True): + if hashfile: + sha256_hash = bb.utils.sha256_file(path) - for f in self.by_sha256_hash.get(sha256_hash, []): - if not isinstance(f, oe.spdx30.software_File): - continue + for f in self.by_sha256_hash.get(sha256_hash, []): + if not isinstance(f, oe.spdx30.software_File): + continue - if purposes: - new_primary = purposes[0] - new_additional = [] + if purposes: + new_primary = purposes[0] + new_additional = [] - if f.software_primaryPurpose: - new_additional.append(f.software_primaryPurpose) - new_additional.extend(f.software_additionalPurpose) + if f.software_primaryPurpose: + new_additional.append(f.software_primaryPurpose) + new_additional.extend(f.software_additionalPurpose) - new_additional = sorted( - list(set(p for p in new_additional if p != new_primary)) - ) + new_additional = sorted( + list(set(p for p in new_additional if p != new_primary)) + ) - f.software_primaryPurpose = new_primary - f.software_additionalPurpose = new_additional + f.software_primaryPurpose = new_primary + f.software_additionalPurpose = new_additional - if f.name != name: - for e in f.extension: - if isinstance(e, OEFileNameAliasExtension): - e.aliases.append(name) - break - else: - f.extension.append(OEFileNameAliasExtension(aliases=[name])) + if f.name != name: + for e in f.extension: + if isinstance(e, OEFileNameAliasExtension): + e.aliases.append(name) + break + else: + f.extension.append(OEFileNameAliasExtension(aliases=[name])) - return f + return f spdx_file = oe.spdx30.software_File( _id=_id, @@ -661,12 +662,13 @@ class ObjectSet(oe.spdx30.SHACLObjectSet): spdx_file.software_primaryPurpose = purposes[0] spdx_file.software_additionalPurpose = purposes[1:] - spdx_file.verifiedUsing.append( - oe.spdx30.Hash( - algorithm=oe.spdx30.HashAlgorithm.sha256, - hashValue=sha256_hash, + if hashfile: + spdx_file.verifiedUsing.append( + oe.spdx30.Hash( + algorithm=oe.spdx30.HashAlgorithm.sha256, + hashValue=sha256_hash, + ) ) - ) return self.add(spdx_file) diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index a8fffbb085..aec47d4f81 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -568,44 +568,63 @@ def create_recipe_spdx(d): if include_vex != "none": patched_cves = oe.cve_check.get_patched_cves(d) for cve, patched_cve in patched_cves.items(): - decoded_status = { - "mapping": patched_cve["abbrev-status"], - "detail": patched_cve["status"], - "description": patched_cve.get("justification", None), - } + mapping = patched_cve["abbrev-status"] + detail = patched_cve["status"] + description = patched_cve.get("justification", None) + resources = patched_cve.get("resource", []) # If this CVE is fixed upstream, skip it unless all CVEs are # specified. - if ( - include_vex != "all" - and "detail" in decoded_status - and decoded_status["detail"] - in ( - "fixed-version", - "cpe-stable-backport", - ) + if include_vex != "all" and detail in ( + "fixed-version", + "cpe-stable-backport", ): bb.debug(1, "Skipping %s since it is already fixed upstream" % cve) continue spdx_cve = recipe_objset.new_cve_vuln(cve) - cve_by_status.setdefault(decoded_status["mapping"], {})[cve] = ( + cve_by_status.setdefault(mapping, {})[cve] = ( spdx_cve, - decoded_status["detail"], - decoded_status["description"], + detail, + description, + resources, ) all_cves = set() for status, cves in cve_by_status.items(): for cve, items in cves.items(): - spdx_cve, detail, description = items + spdx_cve, detail, description, resources = items spdx_cve_id = oe.sbom30.get_element_link_id(spdx_cve) all_cves.add(spdx_cve) if status == "Patched": - recipe_objset.new_vex_patched_relationship([spdx_cve_id], [recipe]) + spdx_vex = recipe_objset.new_vex_patched_relationship( + [spdx_cve_id], [recipe] + ) + patches = [] + for idx, filepath in enumerate(resources): + patches.append( + recipe_objset.new_file( + recipe_objset.new_spdxid( + "patch", str(idx), os.path.basename(filepath) + ), + os.path.basename(filepath), + filepath, + purposes=[oe.spdx30.software_SoftwarePurpose.patch], + hashfile=os.path.isfile(filepath), + ) + ) + + if patches: + recipe_objset.new_scoped_relationship( + spdx_vex, + oe.spdx30.RelationshipType.patchedBy, + oe.spdx30.LifecycleScopeType.build, + patches, + ) + elif status == "Unpatched": recipe_objset.new_vex_unpatched_relationship([spdx_cve_id], [recipe]) elif status == "Ignored": @@ -751,12 +770,14 @@ def create_spdx(d): # Collect all VEX statements from the recipe vex_statements = {} + vex_patches = {} for rel in recipe_objset.foreach_filter( oe.spdx30.Relationship, relationshipType=oe.spdx30.RelationshipType.hasAssociatedVulnerability, ): for cve in rel.to: vex_statements[cve] = [] + vex_patches[cve] = [] for cve in vex_statements.keys(): for rel in recipe_objset.foreach_filter( @@ -764,6 +785,13 @@ def create_spdx(d): from_=cve, ): vex_statements[cve].append(rel) + if rel.relationshipType == oe.spdx30.RelationshipType.fixedIn: + for patch_rel in recipe_objset.foreach_filter( + oe.spdx30.Relationship, + relationshipType=oe.spdx30.RelationshipType.patchedBy, + from_=rel, + ): + vex_patches[cve].extend(patch_rel.to) # Write out the package SPDX data now. It is not complete as we cannot # write the runtime data, so write it to a staging area and a later task @@ -889,7 +917,9 @@ def create_spdx(d): # Add concluded license relationship if manually set # Only add when license analysis has been explicitly performed - concluded_license_str = d.getVar("SPDX_CONCLUDED_LICENSE:%s" % package) or d.getVar("SPDX_CONCLUDED_LICENSE") + concluded_license_str = d.getVar( + "SPDX_CONCLUDED_LICENSE:%s" % package + ) or d.getVar("SPDX_CONCLUDED_LICENSE") if concluded_license_str: concluded_spdx_license = add_license_expression( d, build_objset, concluded_license_str, license_data @@ -915,9 +945,20 @@ def create_spdx(d): for cve, vexes in vex_statements.items(): for vex in vexes: if vex.relationshipType == oe.spdx30.RelationshipType.fixedIn: - pkg_objset.new_vex_patched_relationship( + spdx_vex = pkg_objset.new_vex_patched_relationship( [oe.sbom30.get_element_link_id(cve)], [spdx_package] ) + if vex_patches[cve]: + pkg_objset.new_scoped_relationship( + spdx_vex, + oe.spdx30.RelationshipType.patchedBy, + oe.spdx30.LifecycleScopeType.build, + [ + oe.sbom30.get_element_link_id(p) + for p in vex_patches[cve] + ], + ) + elif vex.relationshipType == oe.spdx30.RelationshipType.affects: pkg_objset.new_vex_unpatched_relationship( [oe.sbom30.get_element_link_id(cve)], [spdx_package] From patchwork Wed Mar 4 16:44:18 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82465 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 4FD12EF9005 for ; Wed, 4 Mar 2026 16:48:46 +0000 (UTC) Received: from mail-oi1-f170.google.com (mail-oi1-f170.google.com [209.85.167.170]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.22979.1772642923907398085 for ; Wed, 04 Mar 2026 08:48:44 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=kz5ejx1d; spf=pass (domain: gmail.com, ip: 209.85.167.170, mailfrom: jpewhacker@gmail.com) Received: by mail-oi1-f170.google.com with SMTP id 5614622812f47-463208653d6so5349468b6e.3 for ; Wed, 04 Mar 2026 08:48:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642923; x=1773247723; 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=RgZWWYUETcp+KAK54Y1gHYnk1xGLeXOCGllecsNhDhw=; b=kz5ejx1dN1vAvHvuT3u7bqbvo9UDRg3EOrSAe+hhl1LUehiJb9XP1ACePhgRfywsqL hMc32RNgKTo8uN2fx8n0hvHNWRc5q1rpWuG8RhLB5OiYKtxMdh9zhLBefUREBngYAvKU 8WaGyRLD4aAUhibmXD39zFeNZ8Nn+sxupQamPnpo0CTHnJ3PY+PunJGsb9Gex140EOW+ 0kWLfSKPxrdZY5tPFy2abPflK70xMi9BamMiAU2CIowpA8k2+0K1hXl2rs1aqlB3NDpb VfcsiZD95Ud7arq1xQl8FEBn4TglF5DHUNjYbnikp8fOAudCeT7PXK5CCVgaHDVvuGqJ 1S+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642923; x=1773247723; 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=RgZWWYUETcp+KAK54Y1gHYnk1xGLeXOCGllecsNhDhw=; b=mCUSPKNlhovNwqUcF18BuGW47HuzTwBUAQINgnsm++rc6QE2jOEi5kc38f/P1F2TE4 yhwDJ2Kia4opX1ICYfk7ducUKLhX9MNsAB6YkvsvbTshBOKKcL/qIl2h6gvaT8A5U2tB 9x0+gEa0H4cKpDZhxu0hefjbNHr9QeqkixDs8aSCapEfl05LOmyxOAEVRg4V+otCRax4 g77lDAJYDA7OcqBSU5Cpnx24XP1KCFds5D19wMfJS21hP2eXo6rpMVfxDxrRlvfMoSSL r06rAWniH3r+vdxDSrfdiTKUryAhdM1HPA6eHQlHEpVw1oDW1PPx4WRygl8xyGsmdG0O +HSg== X-Gm-Message-State: AOJu0YzSoTEMRHJACqVpzugCJE6qgrWE6yGjDrJCvzEihAuKwBaGpqnQ /jn9GjVAW3SiKgMspE1bGrCs+mVGG1VjC4uiKswaO3tOu+oLWMpUBR1NYQzI+w== X-Gm-Gg: ATEYQzx0mZZ2jGprN03wMFY72QPD9CRCria3NY7HqJ89SGmS9BKiXfLV87qK/JeWVyB uojxuksU7JN46a/sRND2mvxHHiYzU/CFKe8IVwVN5dUibEd0bz1mBEHZHb90jw2+FKf0oxFUskF Cv9Whz/UJLSxG8K5/1rIMh6Dj4XY+k88uAeGv4qsKS33SOOqvom6yqfRlZUlj7sBcF6WX8/loHf adtKxoBKtC0S4ocfW6Zp1IbaZj3zHn20rfOx8r+YoHZPuViC081qsEB3qhUCo3LxUnDQRWsnm8d 1CniOPIh0+EtO01VVY2vNTj2lJ7l4oLb63wElEAIJoLVNV/yamVZnjpU3i3ly2fcNAP9gONPTmK 067j61VcgdLIiaop1XYuumorPZ4vwc3vQZ/rZK2m991cqBef57cOWiCjZ+6CfYPRVCvq0N6UI0o sUptT4KlTRA2HKyeHa7Ymu X-Received: by 2002:a05:6808:4f62:b0:463:8fba:5e0e with SMTP id 5614622812f47-4651ab392b3mr1217133b6e.12.1772642922923; Wed, 04 Mar 2026 08:48:42 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:42 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 07/13] spdx: De-duplicate CreationInfo Date: Wed, 4 Mar 2026 09:44:18 -0700 Message-ID: <20260304164835.3072507-8-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232396 De-duplicates CreationInfo objects that are identical (except for ID) when writing out an SBoM. This significantly reduces the number of CreationInfo objects that end up in the final document. Signed-off-by: Joshua Watt --- meta/lib/oe/sbom30.py | 112 ++++++++++++++++++++++++++++++------------ meta/lib/oe/spdx30.py | 2 +- 2 files changed, 81 insertions(+), 33 deletions(-) diff --git a/meta/lib/oe/sbom30.py b/meta/lib/oe/sbom30.py index 21f084dc16..55a2863d2d 100644 --- a/meta/lib/oe/sbom30.py +++ b/meta/lib/oe/sbom30.py @@ -14,6 +14,7 @@ import uuid import os import oe.spdx_common from datetime import datetime, timezone +from contextlib import contextmanager OE_SPDX_BASE = "https://rdf.openembedded.org/spdx/3.0/" @@ -191,6 +192,25 @@ def to_list(l): return l +class Dedup(object): + def __init__(self, objset): + self.unique = set() + self.dedup = {} + self.objset = objset + + def find_duplicates(self, cmp, typ, **kwargs): + for o in self.objset.foreach_filter(typ, **kwargs): + for u in self.unique: + if cmp(u, o): + self.dedup[o] = u + break + else: + self.unique.add(o) + + def get(self, o): + return self.dedup.get(o, o) + + class ObjectSet(oe.spdx30.SHACLObjectSet): def __init__(self, d): super().__init__() @@ -895,6 +915,45 @@ class ObjectSet(oe.spdx30.SHACLObjectSet): self.missing_ids -= set(imports.keys()) return self.missing_ids + @contextmanager + def deduplicate(self): + d = Dedup(self) + + yield d + + visited = set() + + def visit(o, path): + if isinstance(o, oe.spdx30.SHACLObject): + if o in visited: + return False + visited.add(o) + + for k in o: + v = o[k] + if isinstance(v, oe.spdx30.SHACLObject): + o[k] = d.get(v) + + elif isinstance(o, oe.spdx30.ListProxy): + for idx, v in enumerate(o): + if isinstance(v, oe.spdx30.SHACLObject): + o[idx] = d.get(v) + + return True + + if d.dedup: + for o in self.objects: + o.walk(visit) + + for k, v in d.dedup.items(): + bb.debug( + 1, + f"Removing duplicate {k.__class__.__name__} {k._id or id(k)} -> {v._id or id(v)}", + ) + self.objects.discard(k) + + self.create_index() + def load_jsonld(d, path, required=False): deserializer = oe.spdx30.JSONLDDeserializer() @@ -1080,39 +1139,28 @@ def create_sbom(d, name, root_elements, add_objectsets=[]): # SBoM should be the only root element of the document objset.doc.rootElement = [sbom] - # De-duplicate licenses - unique = set() - dedup = {} - for lic in objset.foreach_type(oe.spdx30.simplelicensing_LicenseExpression): - for u in unique: - if ( - u.simplelicensing_licenseExpression - == lic.simplelicensing_licenseExpression - and u.simplelicensing_licenseListVersion - == lic.simplelicensing_licenseListVersion - ): - dedup[lic] = u - break - else: - unique.add(lic) - - if dedup: - for rel in objset.foreach_filter( - oe.spdx30.Relationship, - relationshipType=oe.spdx30.RelationshipType.hasDeclaredLicense, - ): - rel.to = [dedup.get(to, to) for to in rel.to] - - for rel in objset.foreach_filter( - oe.spdx30.Relationship, - relationshipType=oe.spdx30.RelationshipType.hasConcludedLicense, - ): - rel.to = [dedup.get(to, to) for to in rel.to] + def cmp_license_expression(a, b): + return ( + a.simplelicensing_licenseExpression == b.simplelicensing_licenseExpression + and a.simplelicensing_licenseListVersion + == b.simplelicensing_licenseListVersion + ) - for k, v in dedup.items(): - bb.debug(1, f"Removing duplicate License {k._id} -> {v._id}") - objset.objects.remove(k) + def cmp_creation_info(a, b): + data_a = {k: a[k] for k in a} + data_b = {k: b[k] for k in b} + data_a["@id"] = "" + data_b["@id"] = "" + return data_a == data_b + + with objset.deduplicate() as dedup: + # De-duplicate licenses + dedup.find_duplicates( + cmp_license_expression, + oe.spdx30.simplelicensing_LicenseExpression, + ) - objset.create_index() + # Deduplicate creation info + dedup.find_duplicates(cmp_creation_info, oe.spdx30.CreationInfo) return objset, sbom diff --git a/meta/lib/oe/spdx30.py b/meta/lib/oe/spdx30.py index cd97eebd18..1f58402ffc 100644 --- a/meta/lib/oe/spdx30.py +++ b/meta/lib/oe/spdx30.py @@ -701,7 +701,7 @@ class SHACLObject(object): self.__dict__["_obj_data"][iri] = prop.init() def __iter__(self): - return self._OBJ_PROPERTIES.keys() + return iter(self._OBJ_PROPERTIES.keys()) def walk(self, callback, path=None): """ From patchwork Wed Mar 4 16:44:19 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82468 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 BC747EF9010 for ; Wed, 4 Mar 2026 16:48:46 +0000 (UTC) Received: from mail-oa1-f43.google.com (mail-oa1-f43.google.com [209.85.160.43]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.22980.1772642924620212367 for ; Wed, 04 Mar 2026 08:48:44 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=O8FOu8E+; spf=pass (domain: gmail.com, ip: 209.85.160.43, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-41576c5c01cso1432678fac.3 for ; Wed, 04 Mar 2026 08:48:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642924; x=1773247724; 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=6Tj4cGGvEEbE1QT7Q+4TdJLcoNUT6Vuz9fhKtg+CMko=; b=O8FOu8E+gJFK1+xjJc765DnvaMhumpjALSeI2/o2K2jQQ6JCthuihBbMgrnLcMlPti tFXLHNVHavcjWHW4nK12TjTkYgIHXbyWJdmK8l0u1D/kZmQwQ+DjHyoMJBqdF2+rbtHC TKn4Yj2596lPHWCVBRH+PBhCfmwH+Yri3fOLlelGRNj2NHUZBfOzbe4SwGBe1GGIfyEZ 4DC1TeqCXM1+UWv6faHGA/WLr0wqdbNbVNfO68n11IqFWn4jiBNwjmBjjNrz4W8Iuj21 2IqQywMef8rfY7r7wahgeOziddBchKNILmA8k3b/+1A7OQsukFv0YbrS9mzivsS3z4y+ YCag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642924; x=1773247724; 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=6Tj4cGGvEEbE1QT7Q+4TdJLcoNUT6Vuz9fhKtg+CMko=; b=offgqDHBT6ovbK468VxNnjCn36OaWHvXvL8Wcy/q7k4zs6IbUif8QC+ZMSU/ddnaDh F70/aX4NRBsDKpWzqFzqxsAxdWQY23LcOBTxzg+NrFJ//b4yKxlrT/LFd/J321ypN8qO tdEkwW3BcbsDfh5mMWDN+D8vXFcu/7Y3XwLkaWap0jQmsMjhUz6zR2HKQpN9K0ngHxgH rWwjYqSI0TF3UV8ELjadU/ZEmJsx6RMpPYbUlhtyJXdnnZNFsbHScmKvMgy8ZEWJkPi5 UR9/JfF3avCrKiNES8k0jDdb8fyA3Lo1p44ceiW8zZAvGXAuKUkGthq66JDQ4VkbqUjc jq2A== X-Gm-Message-State: AOJu0YwzLNgQCV48LMIMMWn7Uzc9s/ZMPCcoBGlZDIeanOZpnGoqliiX J74xFJG8d8jdQddo9OT/WzWMZYrKKCcVUmgemZpGBTbjAFuU8fRNcoERoAfBGg== X-Gm-Gg: ATEYQzywtEgorLI7fqf0r88p5VPCqhHp5Z6J2QUY5TiiYTtNGNBQ0kNXgzOb0F7/ipp stdoc1jcs6t0+g/4H1eaMozbMkjAKribqeZlat0Ug7/OISfG6lHOpBdrD9Mp0kfsjqnCsOCRBFG igQg+t3ADwr3sH5dg4Lq8jCGTcrRH6CNMmYvd6pgF1V9tTksE98ZiaYO4f+Tae8PVUaNXvEypro NiNwPDfIlZgOhs51YWWuorGAOPr2MdCaczq9D2kpmo9p/G7KXL4pdzjrsch+zSQTGPo4Dyb/9eI Q8bCXEImG25vutzxBWeT6gNUSLzm9I9RBup9tmVNdzeiqH0hKWE/hZi5D3Bwh4rlLs8vAvs5yEu sggkXi8lV8F+yu9qvCLUSZSAeyNXSuM4xE9z5GMmm6mEHpzzG1STu6F/pRRMvxLZ40vLGBYQFal MHZ/+QKLH3qevMoR7GkdsU X-Received: by 2002:a05:6871:6882:b0:40e:edf1:4c8f with SMTP id 586e51a60fabf-416ab603714mr1387944fac.20.1772642923616; Wed, 04 Mar 2026 08:48:43 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:43 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 08/13] spdx_common: Check for dependent task in task flags Date: Wed, 4 Mar 2026 09:44:19 -0700 Message-ID: <20260304164835.3072507-9-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232397 Checks that the task being used to detect dependencies is present in at least one dependency task flag of the current task. This helps prevent errors where the wrong task is specified and never found. Signed-off-by: Joshua Watt --- meta/lib/oe/spdx_common.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/meta/lib/oe/spdx_common.py b/meta/lib/oe/spdx_common.py index 72c24180d5..3aaf2a9c8b 100644 --- a/meta/lib/oe/spdx_common.py +++ b/meta/lib/oe/spdx_common.py @@ -96,6 +96,17 @@ def collect_direct_deps(d, dep_task): taskdepdata = d.getVar("BB_TASKDEPDATA", False) + # Check that the task is listed one of the task dependency flags of the + # current task + depflags = ( + set((d.getVarFlag(current_task, "deptask") or "").split()) + | set((d.getVarFlag(current_task, "rdeptask") or "").split()) + | set((d.getVarFlag(current_task, "recrdeptask") or "").split()) + ) + + if not dep_task in depflags: + bb.fatal(f"Task {dep_task} was not found in any dependency flag of {pn}:{current_task}") + for this_dep in taskdepdata.values(): if this_dep[0] == pn and this_dep[1] == current_task: break From patchwork Wed Mar 4 16:44:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82477 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 63FC2E67A8A for ; Wed, 4 Mar 2026 16:48:47 +0000 (UTC) Received: from mail-oa1-f51.google.com (mail-oa1-f51.google.com [209.85.160.51]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.23110.1772642926077884454 for ; Wed, 04 Mar 2026 08:48:46 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=grFsEOIW; spf=pass (domain: gmail.com, ip: 209.85.160.51, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f51.google.com with SMTP id 586e51a60fabf-40fb2789476so1812205fac.1 for ; Wed, 04 Mar 2026 08:48:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642925; x=1773247725; 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=9Wsvm7UZ+qXi5zyTV0UmCwyCSQ0eIKoDgVpDnS6yewE=; b=grFsEOIWpfsQOTPKiV+Qib05asz9WnFHQZYrjcMP1tZx40nWOcvsrn+1WbYwuFSWol gBd5KMD8Ko3EPmvNHqamCPnZAcImmc4AhUbzKxLNUuspJ2VXNa6RVZLVUFhahBe5NPkB g8MMfQAbCnULtW4UusAgTaklg2KPNTfln3+hc89qPaPF2TwzWIT/KA71Xie98k59zPgS pfFF1KNeFGKqquvMegSI/yfP+r9y01DcPh7e1PNfzrc6M86VTBuvpz5T2IpQMOhE6jR+ N4dcdZwO43dX/pFSAilQWk1f7kpC0+wUJZyqSJtVMMi3PsjTv+D/05Zs2ywKkt3QIAh/ 884g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642925; x=1773247725; 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=9Wsvm7UZ+qXi5zyTV0UmCwyCSQ0eIKoDgVpDnS6yewE=; b=o5aigUKNB5rmjoqqI6YYtUwECSxvxVwAdq5fVrMkaE6g18PRMR5tQyuiYRk5d6LP5g h8baynWlGPmf7isvg2C1Os2r2VKhrHT4/Ysat8OHdZkx13fR1GjPhAGDFHWLrH7xBRjx xQDXPn8CRm/xxqkIOBIhdLpDLqihUAzCT47qfIy+zVo+ZBZvKHny8zIPY/1RrqwH1d6y DSE2inZuAj+YeBkmOdzDQ/PBJjBTWtrQELA1fDp8lgw7bcNlmNBHaNk/GeTGquMcMF0N b8kcpiJDEl1qK4pllrmaapTcXI5lHTuJeU2Zl09x8TENsUPquXQpQBT5+ptEcitiLOCE Oj8g== X-Gm-Message-State: AOJu0Yxo0vfD1xFGfnjMzySZMb2FyPn2HXJlETOU5fdYo9fnad0LJ7hL /dWTUqkyyud2lmomQRXpYkexO47k0F9KzaMiUmggTqjZPVyIWkVYpSGb1CY9Ow== X-Gm-Gg: ATEYQzzO0gN5rLt9kqcZZQKe1wJZQrDxunp/AtYFKeJ+ABZP60e0wovueYn7mgSDnxt mQ13/j+Ppq8hiVhnIRpsEzQIMTgbRiy3yTGN0ROVaMbYftJzFD/nMose7L+IInilu0Fd/ZOCoMe vdrmrx2sflUpCqZ3ouii/Swz6BWU552VUU5ruVLk450BU8WFK2awdnjAerikeR/7YiFtQbUmRah 8qbXkV60fpUzWiNEuX9u3Zd9tIVP3u+3TuakbMyz3r4NM/oqZdz0bn1Pct/4+7iRGxFDD5OU9yQ ANvOUxCjDd12RB/MvHZGKOV+Fm3zR1+rCUs7FJ4pkv0tygBOHqXF914p6ZxvauQK9rZDYuRTypU 2Qz5AClva2qQwHFmC5aKMEQ21qLS6Wagjq9X3zyyF6dwtHvfqHkmzhI2YdP9bFwPJ3rh+X/Evx5 3fmPWtL1vvITL4QUlRdP6ySu9xL1ak8eE= X-Received: by 2002:a05:6870:21cc:b0:40e:f203:eb4d with SMTP id 586e51a60fabf-41691d7bea9mr3395784fac.2.1772642924854; Wed, 04 Mar 2026 08:48:44 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:43 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 09/13] spdx30: Skip install package CVE information Date: Wed, 4 Mar 2026 09:44:20 -0700 Message-ID: <20260304164835.3072507-10-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:47 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232398 Skips adding the install package CVE information by default. This information grows exponentially, since it ends up be N_CVES * N_PACKAGES. The CVE information for a given installed package can be determined by following the "generates" link between the install package and the recipe and looking at the CVE information for the recipe, meaning that the CVE information is only included once in the SPDX document. If users still need the legacy method of including CVE information for each package, then then can set SPDX_PACKAGE_INCLUDE_VEX = "1" Signed-off-by: Joshua Watt --- meta/classes/create-spdx-3.0.bbclass | 11 ++++++++ meta/lib/oe/spdx30_tasks.py | 39 ++++++++++++++-------------- meta/lib/oeqa/selftest/cases/spdx.py | 12 +++++++++ 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index c3ea95b8bc..88b7ef9f42 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -45,6 +45,17 @@ SPDX_INCLUDE_VEX[doc] = "Controls what VEX information is in the output. Set to including those already fixed upstream (warning: This can be large and \ slow)." +SPDX_PACKAGE_INCLUDE_VEX ?= "0" +SPDX_PACKAGE_INCLUDE_VEX[doc] = "Link VEX information to the binary package outputs. \ + Normally, VEX information is only linked to the common recipe that `generates` the \ + binary packages, but setting this to '1' will cause it to also be linked into the \ + generated binary packages. This is off by default because linking the VEX data to \ + each package causes the SPDX output to grow very large, and the same information \ + can be determined by following the `generates` relationship back to the recipe. \ + Before recipe packages were introduced, this was the only way VEX data was \ + expressed; you may need to enable this if your downstream tools do not \ + understand how to trace back to the recipe to find VEX information." + SPDX_INCLUDE_TIMESTAMPS ?= "0" SPDX_INCLUDE_TIMESTAMPS[doc] = "Include time stamps in SPDX output. This is \ useful if you want to know when artifacts were produced and when builds \ diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index aec47d4f81..887fac813a 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -771,27 +771,28 @@ def create_spdx(d): # Collect all VEX statements from the recipe vex_statements = {} vex_patches = {} - for rel in recipe_objset.foreach_filter( - oe.spdx30.Relationship, - relationshipType=oe.spdx30.RelationshipType.hasAssociatedVulnerability, - ): - for cve in rel.to: - vex_statements[cve] = [] - vex_patches[cve] = [] - - for cve in vex_statements.keys(): + if (d.getVar("SPDX_PACKAGE_INCLUDE_VEX") or "") == "1": for rel in recipe_objset.foreach_filter( - oe.spdx30.security_VexVulnAssessmentRelationship, - from_=cve, + oe.spdx30.Relationship, + relationshipType=oe.spdx30.RelationshipType.hasAssociatedVulnerability, ): - vex_statements[cve].append(rel) - if rel.relationshipType == oe.spdx30.RelationshipType.fixedIn: - for patch_rel in recipe_objset.foreach_filter( - oe.spdx30.Relationship, - relationshipType=oe.spdx30.RelationshipType.patchedBy, - from_=rel, - ): - vex_patches[cve].extend(patch_rel.to) + for cve in rel.to: + vex_statements[cve] = [] + vex_patches[cve] = [] + + for cve in vex_statements.keys(): + for rel in recipe_objset.foreach_filter( + oe.spdx30.security_VexVulnAssessmentRelationship, + from_=cve, + ): + vex_statements[cve].append(rel) + if rel.relationshipType == oe.spdx30.RelationshipType.fixedIn: + for patch_rel in recipe_objset.foreach_filter( + oe.spdx30.Relationship, + relationshipType=oe.spdx30.RelationshipType.patchedBy, + from_=rel, + ): + vex_patches[cve].extend(patch_rel.to) # Write out the package SPDX data now. It is not complete as we cannot # write the runtime data, so write it to a staging area and a later task diff --git a/meta/lib/oeqa/selftest/cases/spdx.py b/meta/lib/oeqa/selftest/cases/spdx.py index efee0214fc..f1ea2694cf 100644 --- a/meta/lib/oeqa/selftest/cases/spdx.py +++ b/meta/lib/oeqa/selftest/cases/spdx.py @@ -429,3 +429,15 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): value, ["enabled", "disabled"], f"Unexpected PACKAGECONFIG value '{value}' for {key}" ) + + def test_package_vex(self): + objset = self.check_recipe_spdx( + "core-image-minimal", + "{DEPLOY_DIR_IMAGE}/core-image-minimal-{MACHINE}.rootfs.spdx.json", + extraconf="""\ + SPDX_PACKAGE_INCLUDE_VEX = "1" + """, + ) + + # Document should be fully linked + self.check_objset_missing_ids(objset) From patchwork Wed Mar 4 16:44:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82476 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 7B99FEB7ED8 for ; Wed, 4 Mar 2026 16:48:47 +0000 (UTC) Received: from mail-oa1-f44.google.com (mail-oa1-f44.google.com [209.85.160.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.22982.1772642926856090964 for ; Wed, 04 Mar 2026 08:48:46 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=k5WRWfPT; spf=pass (domain: gmail.com, ip: 209.85.160.44, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f44.google.com with SMTP id 586e51a60fabf-415e568a7ecso988070fac.0 for ; Wed, 04 Mar 2026 08:48:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642926; x=1773247726; 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=0l9blCT/wsqpVcoJlBIomjEadTw/LWIOr1Fg6FyV5X0=; b=k5WRWfPTW7Bt2raLfydKVmPUv9N73UWAFGJymUMUOF5/BffPInHQ08o3mwMTLLlqxX sfArJWy3YMLewuH+fGZ10aw0uw3Ymg12Sy7hUjGvyF1RAz8fsCjn0L45pHgkrJPrtQa9 F2EiJj6si48lfbSKU3eAWhlXr5Td41jgntnTGciSbJjB7ZQvrrNyfkh0W27cvki9JU0O HSf3JK4uN+qOfQL1R2efdZO928q2vR8uYt5sFh3lLsJlsknWiWUGQ96a6sDbQgGM4oJ4 KOM5Ijx+KguYN2Ig84YZ//fs0N6TmrXXFoNrmykZ1IKNV3EUMXwkWsWzKxhC7yQkCKSY 9rJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642926; x=1773247726; 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=0l9blCT/wsqpVcoJlBIomjEadTw/LWIOr1Fg6FyV5X0=; b=qeE0wfcs5fDNTOdg9yghPhTwsE3YwcKd0K0w/bPem/jbMNQJmGpCru61jzvFkjLUrc W2nPIHB9MGuObgZElBEAzEyQZishguz2oiHcJ+U4UY3VTH6KAxRio7VCSIyd20mR1gu/ s7Vs6+LadaMQ4cHVkBnTgjvffxSJdMlrQmfmTcjPjxH2SedgcUYF71rYw1tdwUTCQE8G XJekQnAW1rGI8wmKgWFMKPH4p5wunWGk+D7eo5qch9Z+EEZ1UHNuN7c92SRg2Bc41Cxg /d5W8cL3IIPx89UojawfnqHct+zO1+cIJ9XlNLu/gEWHx9HG7pxkhR9Pdz7Ax+nTqrbd Ji+Q== X-Gm-Message-State: AOJu0YxqdEkbU6N+74f9VH+WIAATbWWxN36AxIvAbej7PMVj4HCR349h KLQty0UOblYP+xLSD2E8hWSUziZywG9/IUYBcZzcI8VWRT9I9JTslV4qrQec8Q== X-Gm-Gg: ATEYQzzG/nWF3CIHJt+socQyRFO8umCiTAm+cWAJXI6FrUK8ODvArZ1sfRUGvN0OZCd v6hUGwGI620MJRZBmLOp92psbWVscfZvgzhg39yrDbyFhDlg8RhtzU1mAxRhS/7gy/qsjGgreR8 Nw89XPmPykQXVPA2LLHrQeuMCH9OMIeKgPaSXNeJ++oR5u1KvkOefAzCpuPXWbwg+e1He8Lz+tZ mxt/MqiaLyozV2mQVvju6AfXmVbnoWA2pTrBF2tPEQThizNJZc+kJd4b28AZQFdCFu9yJMq3osc 910WqdMXsXjZXroLBtlzod+giT3MmQJJ24b9rt8X88GdVEh3jjKbgrHxiUPMatd8W+6V3r0zbFq mDDFytIXaZTTWKkULsRq3PW0Z1NhVhTN7Ppx65greI99AgPoaTPabE5BNpWARK5DWN+dPL2dse3 xzbWUEE6NwtAdiEaH+bp/HCzmPlFrVUm4= X-Received: by 2002:a05:6870:41d5:b0:3ec:4e22:bbb0 with SMTP id 586e51a60fabf-416ab5fc87amr1399828fac.18.1772642925842; Wed, 04 Mar 2026 08:48:45 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:45 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 10/13] dummy-sdk-package: Disable SPDX Date: Wed, 4 Mar 2026 09:44:21 -0700 Message-ID: <20260304164835.3072507-11-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:47 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232399 The dummy SDK packages do not need SPDX support, and since they play some games with allarch that cause problems, it's simplest to disable their SPDX output. Signed-off-by: Joshua Watt --- meta/recipes-core/meta/dummy-sdk-package.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/meta/recipes-core/meta/dummy-sdk-package.inc b/meta/recipes-core/meta/dummy-sdk-package.inc index bf453cac9b..71e788b0b9 100644 --- a/meta/recipes-core/meta/dummy-sdk-package.inc +++ b/meta/recipes-core/meta/dummy-sdk-package.inc @@ -4,6 +4,7 @@ LICENSE = "MIT" PACKAGE_ARCH = "all" inherit allarch +inherit nospdx INHIBIT_DEFAULT_DEPS = "1" From patchwork Wed Mar 4 16:44:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82478 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 6CCF3EF9008 for ; Wed, 4 Mar 2026 16:48:57 +0000 (UTC) Received: from mail-ot1-f42.google.com (mail-ot1-f42.google.com [209.85.210.42]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.23111.1772642927684437052 for ; Wed, 04 Mar 2026 08:48:47 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=igWjzhg8; spf=pass (domain: gmail.com, ip: 209.85.210.42, mailfrom: jpewhacker@gmail.com) Received: by mail-ot1-f42.google.com with SMTP id 46e09a7af769-7d513bc15c7so8721905a34.1 for ; Wed, 04 Mar 2026 08:48:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642927; x=1773247727; 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=pH0P+1ESZgjWAPDC3epT+SOFN7MIIdYB7o7a9YkSZhs=; b=igWjzhg8h0m9rGNaevK5t4QBfPFNBG00wnSusQ3ja715jaGZRxtMMW2QaWLTcJ4gU5 cCZVYn1n8OgnfsMYLxpBfkqEJHpEAA84O2aU/B5QhINXJKcns3mLHJWvM4UoSE5rEbHw T55EEw6I0XluhKbRq4JIk9Z8sdonwMWXwPNKEOcObldxxV/I7naRDXEWPPKaTc8hzGkT 9qSBzpYH7FWfRAm44WiRredje16j+LY25Vp+kDhW/OMgKGvYt0XXEEAqkVrnxoFJcQlP 46kuQZLIEsVJBdYwY26KFog0bs9OjHaEj/DKU+1yBD6bp0zw7hu55RN98iVuMoJNajl3 fabA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642927; x=1773247727; 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=pH0P+1ESZgjWAPDC3epT+SOFN7MIIdYB7o7a9YkSZhs=; b=CLCaDqzOmUbnF5Wx6rUbK6ZKTVD+gO0xm6lweF8SoYhJsl4esVqn9//elpZtIIXVHE fDDjWHeoqUQKGuZGRuV4ROmRW8jxR3B0nAvKI6xR7cBtflrt6dIq1stVyr16ba9/VeHm O5bUsU8/cxt+IPcO++qIOLo3UqF3lj0U8iLOqw91f78zMabMUfVe6hB5ID5QXWTY8a1d Ypnsh21a8PZOlV5PZr7ZkB6O4N1PMYVN2XLkYgojpSM8tCkBfGFjj4YSsOv86+kFmM9v Mog8t5DXqeHzFgggG0zwZInPmAhgvFNcN3pOObTyPEJTTlhsG5tb65K15h5FBbAK1sqv qAGg== X-Gm-Message-State: AOJu0YzkWyWz3NszhGCPL7+bgwqyLOu0rJvZqASWBsU1r3Ya4WvRxCLO X7QB9whLfoghVqdz+O6YJGrXnj/WcwyoHkxt44w8DcxfXktGpUWEJdX3gfqDIA== X-Gm-Gg: ATEYQzzyyo1dJ09vCTRu2HTo7h04QnuFShc1gEyPG87J/t4vFJDCWO8a4V8+leNi0qC q1oodhkAnCxMbR0RrVckpRqL2d8tEDJgkmG902+cQzMC6lGc7ociFkLejTW5zvlGZYU15Rjn5ON 8EVl83gCDB8Q0Dx4iUCLxlguV7lgA3dq6yDU0R4hKIgDT28dkQ1iY9qxNusRDlFOgtrEqsdFeZK jksoW6I7IP2YdjgiGClIJHc5cJ/JcUrLaIsUISGUA/Ls5nPGLHfNWy843mBJobJvSjA++jMpfzd wEBLX8UJwK2ATw/a2IZdwpEkV14nh03yvqKOCMl04oc6pp1VsADW2G3RhXRQof18kfOBpSXrj2z 8L7NxxsmzNWUNRrinCclZefdYZ+tOr/n3D0nUpKFMGtfLXCPHxNmbcZ+NWMAkWkdZ7jXpgtNAmf XoRqMbG4qhFvE7fIDNu7Fx X-Received: by 2002:a05:6808:3094:b0:44d:a3e3:40a9 with SMTP id 5614622812f47-4651ab4dfecmr1071891b6e.8.1772642926646; Wed, 04 Mar 2026 08:48:46 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:46 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 11/13] spdx: Remove fatal errors for missing providers Date: Wed, 4 Mar 2026 09:44:22 -0700 Message-ID: <20260304164835.3072507-12-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:57 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232400 When creating images and SDKs, do not error on missing providers. This allows recipes to use the `nospdx` inherit to prevent SPDX from being generated, but not result in an error when assembling the final image. Note that runtime packages generation already ignored missing providers, so this is changing image and SDK generation to match Signed-off-by: Joshua Watt --- meta/classes/create-spdx-2.2.bbclass | 3 ++- meta/lib/oe/spdx30_tasks.py | 8 +------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/meta/classes/create-spdx-2.2.bbclass b/meta/classes/create-spdx-2.2.bbclass index 3288cdf75a..aa39208eae 100644 --- a/meta/classes/create-spdx-2.2.bbclass +++ b/meta/classes/create-spdx-2.2.bbclass @@ -858,7 +858,8 @@ def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx if packages: for name in sorted(packages.keys()): if name not in providers: - bb.fatal("Unable to find SPDX provider for '%s'" % name) + bb.note("Unable to find SPDX provider for '%s'" % name) + continue pkg_name, pkg_hashfn = providers[name] diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index 887fac813a..ba15d74278 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -1251,11 +1251,10 @@ def collect_build_package_inputs(d, objset, build, packages, files_by_hash=None) providers = oe.spdx_common.collect_package_providers(d) build_deps = set() - missing_providers = set() for name in sorted(packages.keys()): if name not in providers: - missing_providers.add(name) + bb.note(f"Unable to find SPDX provider for '{name}'") continue pkg_name, pkg_hashfn = providers[name] @@ -1274,11 +1273,6 @@ def collect_build_package_inputs(d, objset, build, packages, files_by_hash=None) for h, f in pkg_objset.by_sha256_hash.items(): files_by_hash.setdefault(h, set()).update(f) - if missing_providers: - bb.fatal( - f"Unable to find SPDX provider(s) for: {', '.join(sorted(missing_providers))}" - ) - if build_deps: objset.new_scoped_relationship( [build], From patchwork Wed Mar 4 16:44:23 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82481 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 7CF6AEF900F for ; Wed, 4 Mar 2026 16:48:57 +0000 (UTC) Received: from mail-oa1-f45.google.com (mail-oa1-f45.google.com [209.85.160.45]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.23113.1772642928410754231 for ; Wed, 04 Mar 2026 08:48:48 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=UI/Wkwgi; spf=pass (domain: gmail.com, ip: 209.85.160.45, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f45.google.com with SMTP id 586e51a60fabf-40ee9b945d5so1344507fac.0 for ; Wed, 04 Mar 2026 08:48:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642927; x=1773247727; 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=XIWNp+jA9fLjpsXG4iRqhfv6oO7L/BK8ilevIn/RjTk=; b=UI/WkwgiRLuA0nMQe3wBhR/2xzbC53uA8KgXW7p8r0JZpNj7uPn7elHmKqXCKZKFvp JVlrGrjdC6iWYjnHf72EO5+HXRUoCuw+pMhuNSPbMF7mSH2V0rms6cH1ZdBh9DBxQvKV X9xtDFIo0yhUylVkAyA/Oab0MqR1Vs172DWmMWsm6qJZFC39yqRDcJy/xBzEw3EPTuUK A/Xs48LaYczCDFuJYErGmBOISVKWFG3PJXQ2kV3lQ9ARKbH+GLGGsoKCuHOSu4xCqkyX s/zABI+4kP30PrEJwYxv47hVda5/bU7UG1qHGRlw27Uo0fnjcKha5jVmY5WDPjXw4jVe iemg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642927; x=1773247727; 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=XIWNp+jA9fLjpsXG4iRqhfv6oO7L/BK8ilevIn/RjTk=; b=dZgUxGl5bmF8N7Yk3/ja1tepF5hSf+VKJwta8Yu+IVJIyEXSLuUvUYS5OqAktfljFm 3CDnhhWADNdA2flzr8QMnzb0aorEbTl7XCAaxbiLr/p/3w6K+tcDvcGoxeXu/zLZVQvQ Qvx6dLyBx5wjdEgrEnRGjU4TKopVjhSNVBYQFRhOqj1j5TRWh5lhKZCteJPSwoiT4JVk 6ok0WDMQ/H4VQdWm09W4ngVAtPWbQ/zasJFAetN9QdBjdR2G7ElYjUwBUuKWmVbe1HIf Q104h5OkJbVsvpX5hvM54fLUKVkbz+Org2CrCSAE7s6EH299Ed/mbsb9P73xQfxbFWdb 1R9A== X-Gm-Message-State: AOJu0YwO2T38StBybZFwDVpx4xa0c9Ts14oznfKITR/qZVN7otUXjZfE eNV1BN27zWwsLPpDuJU1o8nwh7uGzud7X7TSPOttM5XRrQNS8ZnllAtYkk9iIQ== X-Gm-Gg: ATEYQzyZ+1LbuStbhF91a5XlMe3PqYfDyeDMQF0e5nBgJKcMbib7T2QDeM5IJmM8Yvo TjKKixgC9QSfNxH94XY/xxjYdUNn31aYXvcTH26vYWEvmu9lksYEnokXNkH6xWwrkih2N1GNkJg 7yl9ECIjp7lapZZbA+klhhRwVWDJyYga/S+9gtgpHcn61CTJh5YpSp0BpSwi082Td5DL6OGdOWo tlFyJTEiSpOoCGmuExoLm9d9RJ+bszNxj6CGm98p8nFUPbWyMOQQxB42WFABOgu86/Ujfp9/Ed0 xWK8vtHTTY3xt5GRKhxauIVt2UA5WSi/CLH3ziM7PJ8Yk6ly9lfP+RKtne07XA0XIcrGF6+PKiw YaxuGL7PIihUZ1NMB31d01KKnpr1YRXAF5Ylv6oIHIxhfqfmL8PXLZU0kySocUzf+jDPFm72Ivc LNkPj7j/IPqcBk954cdLqVLDvxRXs4+Uc= X-Received: by 2002:a05:6870:ed96:b0:40a:40d3:8727 with SMTP id 586e51a60fabf-416abaec29emr1989197fac.47.1772642927363; Wed, 04 Mar 2026 08:48:47 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:47 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 12/13] spdx3: Use common variable for vardeps Date: Wed, 4 Mar 2026 09:44:23 -0700 Message-ID: <20260304164835.3072507-13-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:57 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232401 Instead of repeating the vardeps for each SPDX task with the necessary variables, use a common variable to make it easier to manage Signed-off-by: Joshua Watt --- meta/classes/create-spdx-3.0.bbclass | 33 ++++++++++------------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index 88b7ef9f42..6df66c193b 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -174,6 +174,14 @@ SPDX3_DEP_FILES = "\ ${SPDX_LICENSES}:True \ " +SPDX3_VAR_DEPS = "\ + SPDX_INCLUDE_BITBAKE_PARENT_BUILD \ + SPDX_PACKAGE_ADDITIONAL_PURPOSE \ + SPDX_PROFILES \ + SPDX_NAMESPACE_PREFIX \ + SPDX_UUID_NAMESPACE \ + " + python do_create_recipe_spdx() { import oe.spdx30_tasks oe.spdx30_tasks.create_recipe_spdx(d) @@ -185,13 +193,7 @@ do_create_recipe_spdx[sstate-inputdirs] = "${SPDXRECIPEDEPLOY}" do_create_recipe_spdx[sstate-outputdirs] = "${DEPLOY_DIR_SPDX}" do_create_recipe_spdx[file-checksums] += "${SPDX3_DEP_FILES}" do_create_recipe_spdx[cleandirs] = "${SPDXRECIPEDEPLOY}" -do_create_recipe_spdx[vardeps] += "\ - SPDX_INCLUDE_BITBAKE_PARENT_BUILD \ - SPDX_PACKAGE_ADDITIONAL_PURPOSE \ - SPDX_PROFILES \ - SPDX_NAMESPACE_PREFIX \ - SPDX_UUID_NAMESPACE \ - " +do_create_recipe_spdx[vardeps] += "${SPDX3_VAR_DEPS}" python do_create_recipe_spdx_setscene () { sstate_setscene(d) @@ -222,13 +224,7 @@ do_create_spdx[depends] += " \ ${PATCHDEPENDENCY} \ ${@create_spdx_source_deps(d)} \ " -do_create_spdx[vardeps] += "\ - SPDX_INCLUDE_BITBAKE_PARENT_BUILD \ - SPDX_PACKAGE_ADDITIONAL_PURPOSE \ - SPDX_PROFILES \ - SPDX_NAMESPACE_PREFIX \ - SPDX_UUID_NAMESPACE \ - " +do_create_spdx[vardeps] += "${SPDX3_VAR_DEPS}" python do_create_spdx_setscene () { sstate_setscene(d) @@ -249,6 +245,7 @@ do_create_package_spdx[file-checksums] += "${SPDX3_DEP_FILES}" do_create_package_spdx[dirs] = "${SPDXRUNTIMEDEPLOY}" do_create_package_spdx[cleandirs] = "${SPDXRUNTIMEDEPLOY}" do_create_package_spdx[rdeptask] = "do_create_spdx" +do_create_package_spdx[vardeps] += "${SPDX3_VAR_DEPS}" python do_create_package_spdx_setscene () { sstate_setscene(d) @@ -270,13 +267,7 @@ do_create_recipe_sbom[sstate-inputdirs] = "${SPDXRECIPESBOMDEPLOY}" do_create_recipe_sbom[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" do_create_recipe_sbom[file-checksums] += "${SPDX3_DEP_FILES}" do_create_recipe_sbom[cleandirs] = "${SPDXRECIPESBOMDEPLOY}" -do_create_recipe_sbom[vardeps] += "\ - SPDX_INCLUDE_BITBAKE_PARENT_BUILD \ - SPDX_PACKAGE_ADDITIONAL_PURPOSE \ - SPDX_PROFILES \ - SPDX_NAMESPACE_PREFIX \ - SPDX_UUID_NAMESPACE \ - " +do_create_recipe_sbom[vardeps] += "${SPDX3_VAR_DEPS}" python do_create_recipe_sbom_setscene () { sstate_setscene(d) From patchwork Wed Mar 4 16:44:24 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 82480 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 8EC65EF901F for ; Wed, 4 Mar 2026 16:48:57 +0000 (UTC) Received: from mail-oa1-f51.google.com (mail-oa1-f51.google.com [209.85.160.51]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.23114.1772642929361181152 for ; Wed, 04 Mar 2026 08:48:49 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=UAsGofG6; spf=pass (domain: gmail.com, ip: 209.85.160.51, mailfrom: jpewhacker@gmail.com) Received: by mail-oa1-f51.google.com with SMTP id 586e51a60fabf-413c2977db8so1458999fac.3 for ; Wed, 04 Mar 2026 08:48:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772642928; x=1773247728; 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=AOEUATX1R3zaee+T2FPZecNpF7K6G1L1mqigJuVHEzo=; b=UAsGofG6MdGM9Ja6vDTAQju3v7azsdKbkOubvm3seDd1EeZsWEoQUt8DSLdfML5Can IXdFJqL8/V9g/hOVq5zRdMsmfy8x0bnQiXH48O+Qf2XcNXZh/Ml0YuLFEeUxxI7WI2zJ in1bTaa9cpBfiHqnpXSZaTkanobodq3o2aa5Ry+glO+uwnqadiKobueyKFzjDeBtxw8r rPWN1K4t/HlMGWBaBa4r5i2YN+MR5IK4wfLaNyTGIq57FhcORZ2R6vAMGjOuQWNXDGlJ vextzWIZZipqDgm7pccGvMWHrGm+x/RcxNVRslb45k1+/3CpJYqiW2f+UKIFi3/O3+bp M83w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772642928; x=1773247728; 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=AOEUATX1R3zaee+T2FPZecNpF7K6G1L1mqigJuVHEzo=; b=DjqcrEUuNRXW8lrJiqAuO/A+uTGdTC/1zvcFfwIEpXVEw7oMIIQOh8KgFhSFyPbvri XsdoUa2wguvqlcrwf/zxIYre/x9P0OW876LREnH7Xf68InMQohg0Has6QUWu8PC7tFtF 7J8WVhC4Q34y09CUNhNdezWW4l1PCxfatYnJSjypE2woUA0qmths6O6GdL9hSKQkr1K1 JsQZLRSApxrIEYJgyEd5kzDaAqvrngAunH0OwVYlLs/7GdRTs5/dTIY9oDDpF1O2jHiX cScu8o3KxX28HDKDMzVYcduzb3H7xns7Za049/YJZ1/0GKNkin+lw/EOUHQ9q2BqjQR+ 2CeA== X-Gm-Message-State: AOJu0YzEjwuU8NkAZaO0wcQn+wBP9Q6nkMD/XTNxQ9xUBI3yswtpgxtp ev2jVfuTEZcMn141Pm0h0C1B2tduYzciBoVmKbhuawDsFiEi2lu3S2A8cnauxw== X-Gm-Gg: ATEYQzym12JnBdNqU9iwvFspBqegX5H5n5dW1mOl7P2vAnY+wSkpwiivTeQ/nJJeWSm Hx2wTgreyEVAZQoM9PkV2jMxreObxESr3Tv5SF5b4CabYL1Ab1S/bvP9TrPNKl+K1eEX14sgssM HROISkPD4I1kV8LSTwUWGee78IsLJQQwal0gbMi4AiXJWjmmAWjFWV3myeI9fSKnPdlnU6uonfK sQoQfIDboitAXQh8FStg/S+sxSEKSmv6cHIBhUW9vOzupybrJZTSn4UUoZldN6oRjAekUL1Q+X8 C7aHBuWzTd0IXpDXgF9YbM13TvQ2/Iow9NgbmAJ0t7WOvKd3BO4Nx8tIR//fiAi+eX4J+A6/qRN 7ZwJbPM2tVH6VqtBdvE1s3FywGCsI8IEknubeJyB/EHVpQmGCMvI/S9hjPmtEcfeLQ/qZ9pDNiI npzFNL2O5c5mBKRpeUHIKBJV6ZO/kVDWs= X-Received: by 2002:a05:6871:2b86:b0:416:b429:28e with SMTP id 586e51a60fabf-416b4290b37mr845674fac.20.1772642928385; Wed, 04 Mar 2026 08:48:48 -0800 (PST) Received: from localhost.localdomain ([2601:282:4200:11c0::f681]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4160d2c9fc2sm18466442fac.18.2026.03.04.08.48.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 08:48:47 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v5 13/13] glibc-testsuite: Do not generate SPDX Date: Wed, 4 Mar 2026 09:44:24 -0700 Message-ID: <20260304164835.3072507-14-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260304164835.3072507-1-JPEWhacker@gmail.com> References: <20260303004550.650726-1-JPEWhacker@gmail.com> <20260304164835.3072507-1-JPEWhacker@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 ; Wed, 04 Mar 2026 16:48:57 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/232402 glibc-testsuite does not run on target or factor into the build supply chain, since its purpose is run tests in Qemu at build time Signed-off-by: Joshua Watt --- meta/recipes-core/glibc/glibc-testsuite_2.42.bb | 1 + 1 file changed, 1 insertion(+) diff --git a/meta/recipes-core/glibc/glibc-testsuite_2.42.bb b/meta/recipes-core/glibc/glibc-testsuite_2.42.bb index 6477612feb..1a83a09802 100644 --- a/meta/recipes-core/glibc/glibc-testsuite_2.42.bb +++ b/meta/recipes-core/glibc/glibc-testsuite_2.42.bb @@ -32,6 +32,7 @@ do_check:append () { } inherit nopackages +inherit nospdx deltask do_stash_locale deltask do_install deltask do_populate_sysroot