From patchwork Mon Nov 9 19:45:37 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 103528 Received: from mail-ot1-f42.google.com (mail-ot1-f42.google.com [209.85.210.42]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.3696.1794253684246225957 for ; Mon, 09 Nov 2026 11:48:04 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20260707 header.b=MFd1ySPs; 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-85a6c747dc9so812481a34.0 for ; Mon, 09 Nov 2026 11:48:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794253683; x=1794858483; 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:content-type; bh=k6HhJL9qpsmK5T5siTyfRkDD4MIqxFfeTZ9MsiurJnE=; b=MFd1ySPsl+ZWA8t2f1gr/Djq+CJKAtfMvCyY3xPqG5/p7cZYB0p7m2Xhs0xkRPXAIP nWr3kBmy8u6O/0lYzZ3FcVre7Nl5jGOgTJMmYQdcSeSa2gHChDAFWBwmUGTR6AzB9+pk BL39lyZ1tuGUXZjELyGwqQA7WMAS85VgpGsO/FhQWcd/UQW1rv4qXtowpYiKUhwPPk69 JfydyHhfhKKNHiGkDV95x3RwQ/eArV8mbZ6bnuiRiR1xu/LRQJ5kIG9lE5nf8LRbHeBf lqimhelwWIGrmoUBV5gBa34BGku2tYZlwzHlQFFfYd4hLvp2vWgz+ooYhAZDV99Huacj asPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794253683; x=1794858483; 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:content-type; bh=k6HhJL9qpsmK5T5siTyfRkDD4MIqxFfeTZ9MsiurJnE=; b=JDkJGGEsJkWzXMcRTklQdyEdngkaWe1XelkARgcevrzhA1yClmOW8X4YG0WUCqHm7r IaZ0Vin6+j+3qVMJxWsNg+wk4KBMV4z8y9orox008JiEN9JHJmajoteWK/4rOxybDENP /lyVNGakWpIldcaHykN2U4fVqWNDl3vRJBCZCMvCwLjTZWWmOMaomD4Kz0UYKQfWTizn qPpVZ01jvuddFxccqfl+Z9ExVhiuWhPRwTANgqYKaf45fuTK/Nv0JlH9r5fFs5Sje5i6 GNY0QcynRS19m0CHe4Gt+J+be60+WQotW23Qy6iTOFcAnHTrX8zJeQ1KJqSskZ8fV509 iWxw== X-Gm-Message-State: APuU4Z+8m6Kn7OOjh1BLPfFaY6mvHIw2KyXeUVqKtyIOLarsXcU+kNet uNNrcruevZuVZ5P2YC2n2ovsLp2iijw7lAu/dSlao2K6/b2YJvQRu9yLVWy9CA== X-Gm-Gg: AYBFou2AgRMWyKEBqynLuqGA1t7UdoHJ+YJcfe+9Gc7gcgSJ/5rBbD5rfpSkpUfBvnZ ewhgEQT4ypeTBQwnmpjs2ANla7ylLfo41rmRvN7UjZ6nnT34tfvxpouLAm4H5tffNWtuKyF3iRm AOdJZdyFFddMpz84m6CCmTFXj1GocrrS7n5cpmAjPMrW40dSihG2wINN1nzTZYNnWDeXNQa54HZ pkONMYugVO8awPIV31eNvkODiw9B9aUoeTEQgA121s9hxU4vlWo8lTNX3AT8rsXLQsEGNk4dwNr 8m89GJYoEFIldVmWyyoGoRzQnhlAxE1IiHa1fkoUm2FibG1ooQfdx+jVS5Zlwpy6E9jRjwm8YPP 3Aqxv8wyckZCxUECC/32n/uQWrArjbOF2wTNSK6z87ypJU0ZjS7Yqc+qqx9O/x5S/row2XgvlMC EYQ1CGAjWC/X45zprCit6AnndiWkNB1w3S5SQ9Kl5/beDdoJ1dh9WubNuAEnjwbtaD8cCP9x5Uk 1Ey4HCQZrpMtLdrwvSGn+6JRZrFm4GZqOqLH/s65d+69w75s5/zaH71jz6tSN6ekw0kkXO9V1+d YkIIwZBHtgsMRUs9vyL2QbM6lQI= X-Received: by 2002:a05:6820:3401:20b0:716:ab86:59f6 with SMTP id 006d021491bc7-718a5288860mr50493eaf.8.1794253683257; Mon, 09 Nov 2026 11:48:03 -0800 (PST) Return-Path: Received: from localhost.localdomain ([2601:283:4b01:ba50::3232]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-718aa132e65sm70363eaf.14.2026.11.09.11.48.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:48:02 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v9 1/9] spdx: Skip dependencies that are not in the taskhash Date: Mon, 9 Nov 2026 12:45:37 -0700 Message-ID: <20261109194759.550935-2-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109194759.550935-1-JPEWhacker@gmail.com> References: <20261104153535.3184146-1-JPEWhacker@gmail.com> <20261109194759.550935-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 lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 19:48:07 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249866 If a dependency is not in the taskhash, it cannot be included in the SPDX data because the dependency may not trigger the recipe to rebuild if it changes (although aliases help with this), but more importantly bitbake may not restore the sstate object associated with the dependency which causes errors when constructing the final SBoM Signed-off-by: Joshua Watt --- meta/lib/oe/spdx30_tasks.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index 646ec7d074..3c3ba15e74 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -306,13 +306,14 @@ def collect_dep_objsets(d, direct_deps, subdir, fn_prefix, obj_type, **attr_filt 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 - # will not rebuilt if dependency changes - if dep.in_taskhash: - dep_objsets.append(dep_objset) + # If the dependency is not part of the task hash, do not include it + # since the dependency may not be present in subsequent runs, and may + # not rebuild if it changes + if not dep.in_taskhash: + bb.debug(1, f"Skipping dependency {dep.pn} (not in taskhash)") + continue - # The object _can_ be linked against (by alias) + dep_objsets.append(dep_objset) dep_objs.add(dep_obj) return dep_objsets, dep_objs From patchwork Mon Nov 9 19:45:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 103529 Received: from mail-oo1-f52.google.com (mail-oo1-f52.google.com [209.85.161.52]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.3698.1794253685243316415 for ; Mon, 09 Nov 2026 11:48:05 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20260707 header.b=ONzKHo4O; spf=pass (domain: gmail.com, ip: 209.85.161.52, mailfrom: jpewhacker@gmail.com) Received: by mail-oo1-f52.google.com with SMTP id 006d021491bc7-6dde81a6820so765000eaf.2 for ; Mon, 09 Nov 2026 11:48:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794253684; x=1794858484; 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:content-type; bh=UytyvyRONmp5d0bwaTp/b814IGGDC2jbzr3kbbxx+kQ=; b=ONzKHo4O4yXrnzWCrMhteamSj2N6Iqc7IGhZYyANrjPqIfvz3q337U1WQBIrLI+53n MkPoI7E6mYqAfQVPxbe37/YmU4vTW5VImvFhYgUVUlToo5j3XoJfMel0pWWfnEC7dP0H /V/dr3/SrmhRC8ZshMg0PB29LrIO6QkGJ3fx+SmASNOyLzHV/OFfOwui714pkJkAtf2h yH402GYuWZPyG0cytwKZ0UV/g+H3VKidCelnszaPVT7zjo0lXeneUwLFhXfM/ZHga4mQ 6sf/XfbYLL3B/zYt9NViergMOHcpfjwSc3R5j14o2eWrZdy/KWe37TFRZCRzyGYlVqOR sKOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794253684; x=1794858484; 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:content-type; bh=UytyvyRONmp5d0bwaTp/b814IGGDC2jbzr3kbbxx+kQ=; b=gfHnBCoVSko0ouJe74GbI2vdrLsO+7QxxT/R3GUX+8EE+Y43Yq1thcfL8kLbJ+xy9E X28jjDcuxxEsI5E18pN75/1upxKvm7z8QRDf21VVmJdzEq8WCWAuVBABvhsXPPiBVAVl yBhaUQsRPH29BqWNRkIQTMhvET2rIL+CiKhxvDFxyhNGqbDFOc+m/Nmz4LGwnpsZv623 EelVcx2qIalvug6csEx7e/ckc2bpuF1qKqEO2820l0Axl5mIZN4cLnQ8ucrd+iQ+XImZ P54wRVsmTdFYhI+yEC5WAkot7cKlOISjfCsASQOIDZP/NLzhx3JUh2N6dQaEEM9HJsmr mZgw== X-Gm-Message-State: APuU4Z+x5S3cfhSUi2hBcrnz7CFyzw/7UrX4sKIEZtW+LhcrYXmaUiK+ 5lMnw8fD33dedurSRt0cc4Uk1hH00Dz8jTxmzGAKzFndU/0daXWeoToIkMzEQg== X-Gm-Gg: AYBFou26A3Ot4GEfHxp7WhNE5A0ZQJjTCFcizb4bXsNpc7F4R4WzMLB+JegBFbWrSd1 IPizqJlI1OF2yEePTVyR5vxlUGmGih91ylC5/gKgxYfL3wJOLlIODdOOnpl3o8h3fSMeSAtLl8e 0/l5CCxHMIGOirsePbCMaxz0eZiwPLHmO5yuza4gUr0EB2iN8YwYur3IhYdKGkmhpJgGTjET93T jJAP0MZ/AohuYYRUlU5jXrAk6I1BVvQ/YMsjdtPYlNEPVzx+OQB7UgYiSxUF/TdrixshtKSFeNH Kz69kRrH3YPdHCLveig35mRW8RpCnqeQCo5hetqqnhpJQYsiEl58o8DebXDC51BXGnmZWVso1/S tAWy7RpvjbPEW3Gzd3cmQSYjkcW5y65lJIy9NFlC8tPkT7y0FQZnOcY01YA0tLUiaUkieV1jLp3 oX8lVoHXo+49PmbsAt2ML4qrVywyfD3yoWsNcUxOQyY4z5evLDupZ5AgpMZd9d0/O1R0sj+IaHb +keJiZlxlhwtfwC0giW+O2TzEZEK4l3+WyWff47s1s+JImOEPrEUENZzetWzLbWeg/u9exFkj8m JTKfHpbzfw3lbT8yJcx+RV/Ipxg= X-Received: by 2002:a05:6820:1686:b0:6dc:99b3:2edc with SMTP id 006d021491bc7-718a77f16f6mr80522eaf.84.1794253684054; Mon, 09 Nov 2026 11:48:04 -0800 (PST) Return-Path: Received: from localhost.localdomain ([2601:283:4b01:ba50::3232]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-718aa132e65sm70363eaf.14.2026.11.09.11.48.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:48:03 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v9 2/9] spdx: Add ability for deploy tasks to create SPDX Date: Mon, 9 Nov 2026 12:45:38 -0700 Message-ID: <20261109194759.550935-3-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109194759.550935-1-JPEWhacker@gmail.com> References: <20261104153535.3184146-1-JPEWhacker@gmail.com> <20261109194759.550935-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 lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 19:48:08 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249867 Adds support for "deploy" tasks (like do_deploy) to write out SPDX documents that describe what has been deployed. Deploy tasks will automatically detect many dependencies on other recipes; specifically they will correctly detect dependencies on any do_create_spdx task, and also other deploy tasks that generate SPDX output. The only known notable exception are transitive (e.g. originating from other upstream tasks) dependencies on do_image_complete, and do_populate_sysroot. However, these are detected if a direct dependency of the deploy task (via translation of the task dependencies). This same dependency finding algorithm is now applied to the image generation SBoM; this means that if an image creation task depends on a task that generates a deploy SBoM, it will show up in the dependency graph of the image. A typical example is a wic file that consumes the kernel, u-boot, etc. will now correctly list those as a dependency, as long as their do_deploy step is added to SPDX_DEPLOY_TASKS. Signed-off-by: Joshua Watt --- .../create-spdx-image-3.0.bbclass | 4 +- meta/classes-recipe/deploy.bbclass | 1 + meta/classes-recipe/nospdx.bbclass | 1 + meta/classes/create-spdx-3.0.bbclass | 188 ++++++++++++ meta/classes/spdx-common.bbclass | 1 + meta/lib/oe/sbom30.py | 46 +-- meta/lib/oe/spdx30_tasks.py | 289 +++++++++++++++--- meta/lib/oe/spdx_common.py | 2 +- 8 files changed, 466 insertions(+), 66 deletions(-) diff --git a/meta/classes-recipe/create-spdx-image-3.0.bbclass b/meta/classes-recipe/create-spdx-image-3.0.bbclass index cf79ef5b01..b60cdd826f 100644 --- a/meta/classes-recipe/create-spdx-image-3.0.bbclass +++ b/meta/classes-recipe/create-spdx-image-3.0.bbclass @@ -30,7 +30,7 @@ python do_create_rootfs_spdx() { import oe.spdx30_tasks oe.spdx30_tasks.create_rootfs_spdx(d) } -addtask do_create_rootfs_spdx after do_rootfs before do_image +addtask do_create_rootfs_spdx after do_rootfs do_create_recipe_spdx before do_image SSTATETASKS += "do_create_rootfs_spdx" do_create_rootfs_spdx[sstate-inputdirs] = "${SPDXROOTFSDEPLOY}" do_create_rootfs_spdx[sstate-outputdirs] = "${DEPLOY_DIR_SPDX}" @@ -47,7 +47,7 @@ python do_create_image_spdx() { import oe.spdx30_tasks oe.spdx30_tasks.create_image_spdx(d) } -addtask do_create_image_spdx after do_image_complete do_create_rootfs_spdx before do_build +addtask do_create_image_spdx after do_image_complete do_create_rootfs_spdx do_create_recipe_spdx before do_build SSTATETASKS += "do_create_image_spdx" SSTATE_SKIP_CREATION:task-create-image-spdx = "1" do_create_image_spdx[sstate-inputdirs] = "${SPDXIMAGEWORK}" diff --git a/meta/classes-recipe/deploy.bbclass b/meta/classes-recipe/deploy.bbclass index f56fe98d6d..f222a8560f 100644 --- a/meta/classes-recipe/deploy.bbclass +++ b/meta/classes-recipe/deploy.bbclass @@ -6,6 +6,7 @@ DEPLOYDIR = "${WORKDIR}/deploy-${PN}" SSTATETASKS += "do_deploy" +SPDX_DEPLOY_ARTIFACTS_DIR:task-deploy = "${DEPLOYDIR}" do_deploy[sstate-inputdirs] = "${DEPLOYDIR}" do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" diff --git a/meta/classes-recipe/nospdx.bbclass b/meta/classes-recipe/nospdx.bbclass index 6ccb93ba01..723194da2d 100644 --- a/meta/classes-recipe/nospdx.bbclass +++ b/meta/classes-recipe/nospdx.bbclass @@ -12,3 +12,4 @@ deltask do_create_package_spdx deltask do_create_rootfs_spdx deltask do_create_image_spdx deltask do_create_image_sbom_spdx +deltask do_create_deploy_sbom diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index 6d47aa1301..fb6a4f249e 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -163,6 +163,55 @@ SPDX_GIT_PURL_MAPPINGS[doc] = "A space separated list of domain:purl_type \ on gitlab.example.com to the pkg:gitlab PURL type. \ github.com is always mapped to pkg:github by default." +SPDX_DEPLOY_TASKS ?= "" +SPDX_DEPLOY_TASKS[doc] = "A space separated list of sstate tasks that produce \ + deployed output (usually written to DEPLOY_DIR_IMAGE). Tasks in this list \ + will produce SPDX documents that describe the deployed output. Items in \ + list have the format 'TASK(:FUNCTION)' where 'TASK' is the sstate task \ + (which must start with 'do_deploy'), and 'FUNCTION' is the optional \ + function to call to produce the deploy SPDX. If 'FUNCTION' is omitted \ + a default function is provided that uses SPDX_DEPLOY_ARTIFACTS and \ + SPDX_DEPLOY_ARTIFACTS_DIR to configure what deploy artifacts it describes \ + in the SPDX output.\ + \ + Dependencies of deploy tasks that produce SPDX data will be automatically \ + linked in as a build time dependency of the deploy task's SBoM. (for \ + example, if one do_deploy depends on another recipes do_deploy, this will \ + be reflected in the SPDX data)." + +SPDX_DEPLOY_SBOM ??= "1" +SPDX_DEPLOY_SBOM[doc] = "If '1' (the default) a task named \ + do_create_deploy_sbom will be created to automatically collect all deploy \ + SPDX documents (from SPDX_DEPLOY_TASKS) and combine them into a SBoM \ + which will be placed in DEPLOY_DIR_IMAGE. This task is added as a \ + dependency of do_build, so it will run whenever the recipe is built \ + directly. The name of the document can be set with SPDX_DEPLOY_SBOM_NAME. \ + If the recipe already has another task to create an SBoM, this should be \ + set to '0' to prevent multiple SBoMs from being created." + +SPDX_DEPLOY_SBOM_NAME ?= "${PN}-deploy-sbom" +SPDX_DEPLOY_SBOM_NAME[doc] = "The name of the output deploy SBoM when using \ + create_deploy_sbom" + +SPDX_DEPLOY_ARTIFACTS = "AUTO" +SPDX_DEPLOY_ARITFACTS[doc] = "A space separated list of deployed artifacts, \ + relative to SPDX_DEPLOY_ARTIFACTS_DIR that should be included in the SBoM. \ + If 'AUTO' (the default), all files in SPDX_DEPLOY_ARITFACTS_DIR will be \ + added. A :task- override *must* be used to set this value so that it is \ + scoped to a specific task" + +SPDX_DEPLOY_ARTIFACTS_DIR = "" +SPDX_DEPLOY_ARTIFACTS_DIR[doc] = "The directory recipe specific directory \ + where artifacts are deployed for staging to sstate (e.g. for do_deploy, \ + this is DEPLOY_DIR). A :task- override *must* be used to set this value so \ + that it is scoped to a specific task." + +SPDX_DEPLOY_ALLOW_EMPTY = "0" +SPDX_DEPLOY_ALLOW_EMPTY[doc] = "If set to '1', SPDX deploy task is allowed to \ + have no output artifacts. A SPDX document will still be produced, but it \ + will have no output files. This must always be set with a task override, \ + e.g.: SPDX_DEPLOY_ALLOW_EMPTY:task-deploy = '1'" + IMAGE_CLASSES:append = " create-spdx-image-3.0" SDK_CLASSES += "create-spdx-sdk-3.0" @@ -293,3 +342,142 @@ python spdx30_build_started_handler () { addhandler spdx30_build_started_handler spdx30_build_started_handler[eventmask] = "bb.event.BuildStarted" +python create_deploy_spdx() { + import oe.spdx30_tasks + from pathlib import Path + current_task = "do_" + d.getVar("BB_CURRENTTASK") + + spdxdeploydir = Path(d.getVar("SPDXDIR") + "/deploy-" + current_task) + + artifactsdir = d.getVar("SPDX_DEPLOY_ARTIFACTS_DIR") + if not artifactsdir: + bb.fatal(f"{pn}: spdx-artifactsdir must be set for task {current_task}") + return + + artifacts = d.getVar("SPDX_DEPLOY_ARTIFACTS") + + oe.spdx30_tasks.create_deploy_spdx(d, spdxdeploydir, artifactsdir, artifacts) +} +oe.spdx30_tasks.find_build_dep_objsets[vardepsexclude] += "BB_TASKDEPDATA" + +python () { + # Most recipes generate SPDX output in a distinct task from the task that + # actually is the relevant dependency. As such, we need to map the task + # that we care about to the task that generates the corresponding SPDX + # output so that we can rely on the SPDX output being present when the time + # comes to use it downstream. + # + # The down side of this is that only the first level of dependencies (e.g + # tasks listed in SPDX_DEPLOY_TASKS) will have the mapping done and thus + # find the dependencies. Transitive dependencies will not be mapped and + # thus the SPDX data will not be linked in. + # + # Ideally, this will be able to go away once more tasks directly generate + # SPDX files for their output instead of combining it into monolithic + # functions; tasks listed in this map are the best candidates to have this + # done first. + TASK_MAP = { + # If a task requires the RSS be extended, depend on the SPDX build task + # for the recipe, at least until it's possible for do_populate_sysroot + # to describe it's own output. + "do_populate_sysroot": "do_create_spdx", + # If an image is needed, also depend on the task to create the SBoM for + # the image + "do_image_complete": "do_create_image_spdx", + } + + def map_task_deps(task, flag): + task_flags= (d.getVarFlag(task, flag) or "").split() + for t in task_flags: + if t in TASK_MAP and TASK_MAP[t] not in task_flags: + d.appendVarFlag(task, flag, f" {TASK_MAP[t]}") + + def before_postfunc(f): + return f == "sstate_task_postfunc" or "buildhistory" in f + + if bb.data.inherits_class("nospdx", d): + return + + sstate_tasks = set((d.getVar("SSTATETASKS") or "").split()) + deploy_sbom_tasks = [] + for task in (d.getVar("SPDX_DEPLOY_TASKS") or "").split(): + if ":" in task: + task, func = task.split(":") + else: + func = "create_deploy_spdx" + + if not task.startswith("do_deploy") and not task == "do_image_complete": + bb.fatal(f"Task {task} is not allowed to deploy SPDX data. Must start with 'do_deploy'") + + deploy_sbom_tasks.append(task) + + if task not in sstate_tasks: + bb.fatal(f"{task} is not an sstate task") + + spdx_deploy = "${SPDXDIR}/deploy-" + task + + # Ensure function is sorted properly. It should be right before + # sstate_task_postfunc + postfuncs = (d.getVarFlag(task, "postfuncs") or "").split() + + new_postfuncs = [] + while True: + if not postfuncs or before_postfunc(postfuncs[0]): + break + new_postfuncs.append(postfuncs.pop(0)) + new_postfuncs.append(func) + new_postfuncs.extend(postfuncs) + + d.setVarFlag(task, "postfuncs", " ".join(new_postfuncs)) + d.prependVarFlag(task, "sstate-inputdirs", f"{spdx_deploy} ") + d.prependVarFlag(task, "sstate-outputdirs", "${DEPLOY_DIR_SPDX} ") + d.prependVarFlag(task, "file-checksums", "${SPDX3_DEP_FILES} ") + d.prependVarFlag(task, "dirs", f"{spdx_deploy} ") + d.prependVarFlag(task, "cleandirs", f"{spdx_deploy} ") + d.prependVarFlag(task, "vardeps", "SPDX_DEPLOY_ALLOW_EMPTY") + + deps = (d.getVarFlag(task, "depends") or "").split() + extra_deps = ["${PN}:do_create_recipe_spdx", "${PN}:do_create_spdx"] + for dep in deps: + _, fn, taskname = bb.runqueue.split_tid(dep) + if taskname in TASK_MAP: + extra_deps.append(f"{fn}:{TASK_MAP[taskname]}") + + d.prependVarFlag(task, "depends", " ".join(extra_deps) + " ") + + map_task_deps(task, "deptask") + map_task_deps(task, "rdeptask") + map_task_deps(task, "recrdeptask") + + # For now, if a recipe is directly built, deploy all of it's deploy tasks + # into a single SBoM. We may need an option in the future to have tasks + # that don't do this (e.g. because they do not deploy to a location that is + # intended to be consumed by the user) + if deploy_sbom_tasks and (d.getVar("SPDX_DEPLOY_SBOM") or "") == "1": + bb.build.addtask("do_create_deploy_sbom", "do_build", " ".join(deploy_sbom_tasks), d) +} + +python do_create_deploy_sbom() { + import oe.spdx30_tasks + from pathlib import Path + deploydir = Path(d.getVar("SPDXDEPLOYSBOMDEPLOY")) + deploy_tasks = [] + for task in (d.getVar("SPDX_DEPLOY_TASKS") or "").split(): + if ":" in task: + task, _ = task.split(":") + deploy_tasks.append(task) + + oe.spdx30_tasks.create_deploy_sbom(d, deploydir, deploy_tasks) +} +do_create_deploy_sbom[sstate-inputdirs] = "${SPDXDEPLOYSBOMDEPLOY}" +do_create_deploy_sbom[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" +do_create_deploy_sbom[recrdeptask] += "do_create_recipe_spdx do_create_spdx" +do_create_deploy_sbom[cleandirs] += "${SPDXDEPLOYSBOMDEPLOY}" +do_create_deploy_sbom[file-checksums] += "${SPDX3_DEP_FILES}" + +SSTATETASKS += "do_create_deploy_sbom" +python do_create_deploy_sbom_setscene() { + sstate_setscene(d) +} +addtask do_create_deploy_sbom_setscene +SSTATE_SKIP_CREATION:task-create-deploy-sbom = "1" diff --git a/meta/classes/spdx-common.bbclass b/meta/classes/spdx-common.bbclass index 40701730a6..bca169670d 100644 --- a/meta/classes/spdx-common.bbclass +++ b/meta/classes/spdx-common.bbclass @@ -26,6 +26,7 @@ SPDX_TOOL_VERSION ??= "1.0" SPDXRECIPEDEPLOY = "${SPDXDIR}/recipe-deploy" SPDXRUNTIMEDEPLOY = "${SPDXDIR}/runtime-deploy" SPDXRECIPESBOMDEPLOY = "${SPDXDIR}/recipes-bom-deploy" +SPDXDEPLOYSBOMDEPLOY = "${SPDXDIR}/deploy-bom-deploy" SPDX_INCLUDE_SOURCES ??= "0" SPDX_INCLUDE_SOURCES[doc] = "If set to '1', include source code files in the \ diff --git a/meta/lib/oe/sbom30.py b/meta/lib/oe/sbom30.py index e279cfc82b..520f9df3ef 100644 --- a/meta/lib/oe/sbom30.py +++ b/meta/lib/oe/sbom30.py @@ -1108,6 +1108,25 @@ def write_jsonld_doc(d, objset, dest): objset.objects.remove(objset.doc) +def make_jsonld_link(d, fn, subdir, name, deploydir): + pkg_arch = d.getVar("SSTATE_PKGARCH") + + link_name = jsonld_arch_path( + d, + pkg_arch, + subdir, + name, + deploydir=deploydir, + ) + try: + link_name.parent.mkdir(exist_ok=True, parents=True) + link_name.symlink_to(os.path.relpath(fn, link_name.parent)) + except: + target = link_name.readlink() + bb.warn(f"Unable to link {fn} as {link_name}. Already points to {target}") + raise + + def write_recipe_jsonld_doc( d, objset, @@ -1115,6 +1134,7 @@ def write_recipe_jsonld_doc( deploydir, *, create_spdx_id_links=True, + create_task_link=False, ): pkg_arch = d.getVar("SSTATE_PKGARCH") @@ -1122,23 +1142,7 @@ def write_recipe_jsonld_doc( def link_id(_id): hash_path = jsonld_hash_path(hash_id(_id)) - - link_name = jsonld_arch_path( - d, - pkg_arch, - *hash_path, - deploydir=deploydir, - ) - try: - link_name.parent.mkdir(exist_ok=True, parents=True) - link_name.symlink_to(os.path.relpath(dest, link_name.parent)) - except: - target = link_name.readlink() - bb.warn( - f"Unable to link {_id} in {dest} as {link_name}. Already points to {target}" - ) - raise - + make_jsonld_link(d, dest, *hash_path, deploydir) return hash_path[-1] objset.add_aliases() @@ -1154,6 +1158,14 @@ def write_recipe_jsonld_doc( # out, so always do that even if there is an error making the links write_jsonld_doc(d, objset, dest) + if create_task_link: + pn = d.getVar("PN") + current_task = "do_" + d.getVar("BB_CURRENTTASK") + + make_jsonld_link(d, dest, "by-task", f"{pn}:{current_task}", deploydir) + + return dest + def find_root_obj_in_jsonld(d, subdir, fn_name, obj_type, **attr_filter): objset, fn = find_jsonld(d, subdir, fn_name, required=True) diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index 3c3ba15e74..43e196806f 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -80,7 +80,9 @@ def add_license_expression( if lic is None: p, _ = oe.license.get_license_path(d, node) if p is None: - bb.fatal(f"{pn}: No generic license file exists for: {node.ident} in any provider") + bb.fatal( + f"{pn}: No generic license file exists for: {node.ident} in any provider" + ) return with open(p, errors="replace") as f: @@ -598,6 +600,135 @@ def get_is_native(d): return bb.data.inherits_class("native", d) or bb.data.inherits_class("cross", d) +def set_var_field(d, 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) + + +def find_build_dep_objsets(d, start_task): + def find_deps(d, taskdepdata, current_dep, start_dep, visited, depth=0): + key = f"{current_dep.pn}:{current_dep.taskname}" + + dep_objsets = [] + + if key not in visited: + visited.add(key) + + for n in current_dep.deps: + dep = taskdepdata[n] + dep_name = f"{dep.pn}:{dep.taskname}" + + dep_objset, dep_path = oe.sbom30.find_jsonld(d, "by-task", dep_name) + if dep_objset: + dep_objsets.append(dep_objset) + + elif dep.pn == start_dep.pn: + # If this task is still part of the same recipe, continue + # searching up the dependency tree until a valid dependency + # is found. This detects transitive dependencies that may + # have been pulled in by previous tasks in the same recipe. + dep_objsets.extend( + find_deps(d, taskdepdata, dep, start_dep, visited, depth + 1) + ) + + return dep_objsets + + pn = d.getVar("PN") + taskdepdata = d.getVar("BB_TASKDEPDATA", False) + for dep in taskdepdata.values(): + if dep.pn == pn and dep.taskname == start_task: + start_dep = dep + break + else: + bb.fatal(f"Unable to find {pn}:{start_task} in taskdepdata") + + return find_deps(d, taskdepdata, start_dep, start_dep, set()) + + +def create_deploy_package(d, objset, build, spdxid, name, start_task, files, **attrs): + recipe, _ = load_recipe_spdx(d) + + deploy_package = objset.add_root( + oe.spdx30.software_Package( + _id=spdxid, + creationInfo=objset.doc.creationInfo, + name=name, + software_packageVersion=d.getVar("PV"), + ) + ) + + objset.new_scoped_relationship( + [oe.sbom30.get_element_link_id(recipe)], + oe.spdx30.RelationshipType.generates, + oe.spdx30.LifecycleScopeType.build, + [deploy_package], + ) + + set_var_field(d, "HOMEPAGE", deploy_package, "software_homePage") + set_var_field(d, "SUMMARY", deploy_package, "summary") + set_var_field(d, "DESCRIPTION", deploy_package, "description") + + set_purls(deploy_package, (d.getVar("SPDX_PACKAGE_URLS") or "").split()) + + set_timestamp_now(d, deploy_package, "builtTime") + + supplier = objset.new_agent("SPDX_PACKAGE_SUPPLIER") + if supplier is not None: + deploy_package.suppliedBy = ( + supplier if isinstance(supplier, str) else supplier._id + ) + + if files: + objset.new_relationship( + [deploy_package], + oe.spdx30.RelationshipType.contains, + sorted(list(files)), + ) + + objset.new_scoped_relationship( + [build], + oe.spdx30.RelationshipType.hasOutput, + oe.spdx30.LifecycleScopeType.build, + sorted(list(files) + [deploy_package]), + ) + + # Collect dependencies + if start_task is not None: + dep_builds = set() + dep_packages = set() + for o in find_build_dep_objsets(d, start_task): + if obj := o.find_root(oe.spdx30.software_Package): + dep_packages.add(oe.sbom30.get_element_link_id(obj)) + + if obj := o.find_root(oe.spdx30.build_Build): + dep_builds.add(oe.sbom30.get_element_link_id(obj)) + + if dep_packages: + objset.new_scoped_relationship( + [deploy_package], + oe.spdx30.RelationshipType.dependsOn, + oe.spdx30.LifecycleScopeType.build, + sorted(list(dep_packages)), + ) + + if dep_builds: + objset.new_scoped_relationship( + [build], + oe.spdx30.RelationshipType.dependsOn, + oe.spdx30.LifecycleScopeType.build, + sorted(list(dep_builds)), + ) + + return deploy_package + + def create_recipe_spdx(d): deploydir = Path(d.getVar("SPDXRECIPEDEPLOY")) pn = d.getVar("PN") @@ -790,7 +921,9 @@ def create_recipe_spdx(d): sorted(list(all_cves)), ) - oe.sbom30.write_recipe_jsonld_doc(d, recipe_objset, "static", deploydir) + oe.sbom30.write_recipe_jsonld_doc( + d, recipe_objset, "static", deploydir, create_task_link=True + ) def load_recipe_spdx(d): @@ -804,17 +937,6 @@ def load_recipe_spdx(d): 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") @@ -943,10 +1065,12 @@ def create_spdx(d): ) set_var_field( - "HOMEPAGE", spdx_package, "software_homePage", package=package + d, "HOMEPAGE", spdx_package, "software_homePage", package=package + ) + set_var_field(d, "SUMMARY", spdx_package, "summary", package=package) + set_var_field( + d, "DESCRIPTION", spdx_package, "description", package=package ) - set_var_field("SUMMARY", spdx_package, "summary", package=package) - set_var_field("DESCRIPTION", spdx_package, "description", package=package) purls = ( d.getVar("SPDX_PACKAGE_URLS:%s" % package) @@ -1133,7 +1257,9 @@ def create_spdx(d): f"Added PACKAGECONFIG entries: {len(enabled)} enabled, {len(disabled)} disabled" ) - oe.sbom30.write_recipe_jsonld_doc(d, build_objset, "builds", deploydir) + oe.sbom30.write_recipe_jsonld_doc( + d, build_objset, "builds", deploydir, create_task_link=True + ) def create_package_spdx(d): @@ -1369,26 +1495,9 @@ def create_rootfs_spdx(d): d, "%s-%s-rootfs" % (image_basename, machine) ) - rootfs = objset.add_root( - oe.spdx30.software_Package( - _id=objset.new_spdxid("rootfs", image_basename), - creationInfo=objset.doc.creationInfo, - name=image_basename, - software_primaryPurpose=oe.spdx30.software_SoftwarePurpose.archive, - ) - ) - set_timestamp_now(d, rootfs, "builtTime") - rootfs_build = objset.add_root(objset.new_task_build("rootfs", "rootfs")) set_timestamp_now(d, rootfs_build, "build_buildEndTime") - objset.new_scoped_relationship( - [rootfs_build], - oe.spdx30.RelationshipType.hasOutput, - oe.spdx30.LifecycleScopeType.build, - [rootfs], - ) - files_by_hash = {} collect_build_package_inputs(d, objset, rootfs_build, packages, files_by_hash) @@ -1421,14 +1530,20 @@ def create_rootfs_spdx(d): ) ) - if files: - objset.new_relationship( - [rootfs], - oe.spdx30.RelationshipType.contains, - sorted(list(files)), - ) + rootfs = create_deploy_package( + d, + objset, + rootfs_build, + objset.new_spdxid("rootfs", image_basename), + image_basename, + None, + files, + ) + rootfs.software_primaryPurpose = oe.spdx30.software_SoftwarePurpose.archive - oe.sbom30.write_recipe_jsonld_doc(d, objset, "rootfs", deploydir) + oe.sbom30.write_recipe_jsonld_doc( + d, objset, "rootfs", deploydir, create_task_link=True + ) def create_image_spdx(d): @@ -1508,10 +1623,13 @@ def create_image_spdx(d): set_timestamp_now(d, a, "builtTime") if artifacts: - objset.new_scoped_relationship( - [image_build], - oe.spdx30.RelationshipType.hasOutput, - oe.spdx30.LifecycleScopeType.build, + create_deploy_package( + d, + objset, + image_build, + objset.new_spdxid(taskname, "image", imagetype), + "image", + f"do_{taskname}", artifacts, ) @@ -1532,7 +1650,9 @@ def create_image_spdx(d): objset.add_aliases() objset.link() - oe.sbom30.write_recipe_jsonld_doc(d, objset, "image", spdx_work_dir) + oe.sbom30.write_recipe_jsonld_doc( + d, objset, "image", spdx_work_dir, create_task_link=True + ) def create_image_sbom_spdx(d): @@ -1720,3 +1840,80 @@ def create_recipe_sbom(d, deploydir): objset, sbom = oe.sbom30.create_sbom(d, sbom_name, [recipe], [recipe_objset]) oe.sbom30.write_jsonld_doc(d, objset, deploydir / (sbom_name + ".spdx.json")) + + +def create_deploy_spdx(d, spdxdeploydir, artifactsdir, artifacts): + pn = d.getVar("PN") + current_task = "do_" + d.getVar("BB_CURRENTTASK") + + recipe, recipe_objset = load_recipe_spdx(d) + + if artifacts == "AUTO": + artifacts = [] + for root, dirs, files in os.walk(artifactsdir): + for p in [Path(os.path.join(root, f)) for f in files]: + if p.is_file(): + artifacts.append(p) + else: + artifacts = [artifactsdir / p for p in artifacts.split()] + + artifacts.sort(key=lambda p: (p.is_symlink(), p)) + + objset = oe.sbom30.ObjectSet.new_objset(d, f"{pn}-{current_task}-deploy") + + build = objset.add_root(objset.new_task_build(current_task, "deploy")) + set_timestamp_now(d, build, "build_buildEndTime") + objset.set_is_native(get_is_native(d)) + + files = set() + for a in artifacts: + relpath = a.relative_to(artifactsdir) + f = objset.new_file( + objset.new_spdxid("deploy", str(relpath)), + a.name, + a, + ) + files.add(f) + + if not files: + if ( + d.getVar("SPDX_DEPLOY_ALLOW_EMPTY:task-" + d.getVar("BB_CURRENTTASK")) or "" + ) != "1": + bb.fatal(f"No deployed artifacts found in {artifactsdir}") + return + + create_deploy_package( + d, + objset, + build, + objset.new_spdxid("deploy", pn, current_task), + pn, + current_task, + files, + ) + + # Create document + dest = oe.sbom30.write_recipe_jsonld_doc( + d, + objset, + "deploy", + spdxdeploydir, + create_task_link=True, + ) + + +def create_deploy_sbom(d, deploydir, deploy_tasks): + pn = d.getVar("PN") + sbom_name = d.getVar("SPDX_DEPLOY_SBOM_NAME") + + objsets = [] + for t in deploy_tasks: + o, _ = oe.sbom30.find_jsonld(d, "deploy", f"{pn}-{t}-deploy", required=True) + objsets.append(o) + + root_objs = [] + for o in objsets: + root_objs.extend(o.doc.rootElement) + + objset, sbom = oe.sbom30.create_sbom(d, sbom_name, root_objs, objsets) + oe.sbom30.write_jsonld_doc(d, objset, deploydir / (sbom_name + ".spdx.json")) diff --git a/meta/lib/oe/spdx_common.py b/meta/lib/oe/spdx_common.py index 07bf9650e2..9a862d9f5a 100644 --- a/meta/lib/oe/spdx_common.py +++ b/meta/lib/oe/spdx_common.py @@ -118,7 +118,7 @@ def collect_direct_deps(d, dep_task): ) for this_dep in taskdepdata.values(): - if this_dep[0] == pn and this_dep[1] == current_task: + if this_dep.pn == pn and this_dep.taskname == current_task: break else: bb.fatal(f"Unable to find this {pn}:{current_task} in taskdepdata") From patchwork Mon Nov 9 19:45:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 103530 Received: from mail-oo1-f48.google.com (mail-oo1-f48.google.com [209.85.161.48]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.3755.1794253685566848246 for ; Mon, 09 Nov 2026 11:48:05 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20260707 header.b=oYV4xDrq; spf=pass (domain: gmail.com, ip: 209.85.161.48, mailfrom: jpewhacker@gmail.com) Received: by mail-oo1-f48.google.com with SMTP id 006d021491bc7-6f8a519e215so1045365eaf.1 for ; Mon, 09 Nov 2026 11:48:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794253685; x=1794858485; 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:content-type; bh=Z1y3RBDJoDIw4KgYSPBJM4umu5zeYQMe7A/eNaaMe0w=; b=oYV4xDrqqid7qwsuke4X3QHZ9e++rcYM8l56C2d0yFQofGoJ1V+hSvnxcC/iy2AP2O qx7ShuR3R6pLD29uaQ1NQ4xS98LcpEMTW0rh56Odd4oZZmWxa8kw9LPx8+hujH5kuIcs Ykd66xl/tY7ruad5PbV837zIuYJDVI0iRRv8FQzZcTzAWaVLt1SVooTrAr+fQGL/z2tE snEYY8khcZs9yWdXAcHINqh+EjgjzS7n8AtCS0HOkbL05IrPhT2MIvZ41xNgMhtzG41e FoZX+i82ISnf7AVIKSHTvUs8fjLYqY/Kw9M6/VdLKu7hDp00uPQg9kPyd7S4ao3rLHHg p8Ug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794253685; x=1794858485; 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:content-type; bh=Z1y3RBDJoDIw4KgYSPBJM4umu5zeYQMe7A/eNaaMe0w=; b=qg8HRcXOj8nZh8YUWbFkkY08QrqilYH0sPvPpeOnOtL39eq8Yc2ACk0iC8PKmW1iwv rqToMHYz7l6Z0CrH5byXhD0SjDgpahIDOdCiumKDe5rKYxNwOYow/9d0jeg3LTxgPdmq mpKHf3/tf3Inb3pj9BrlhEuwmq4tdh8X6fzyirYh+3MBWgJozzvJWG8RjhXZQ5SxSCpE baO6hWbDfhbyrePRO5ReSLJLGk9s8B17SIe7zAyw3FSDA9MomGeqbC8HSJQU7cAAf5cj LYiXEvbmW13mchsSX/I4XEdcXGipWceRAiKrqahgVBVmZLC1j+AcayYELSWMeSF57FGf r2tA== X-Gm-Message-State: APuU4Z/Nd6LCrRu9xmLi31h5XZkKoVrEnR2ZT+cOGw7kFL7qjLbdPAok Kl1MioG18BVwXZqtC9h9rSEei9Q3Zwvy1Ii0X9HpJ9+sXqyxRYhovK/je0u4ig== X-Gm-Gg: AYBFou14756yeR8WnHusiZbj3Tp92SQXvaWhuVmFt8nN0U3KdRnrUik2WMCMzXbNvZL EyvkO+QvrLd6BeGvTZVl7CKJijFA0SpPxZ9MycL89cKmbOka2zlk38FYgwb/QnttZ4fhSGWwJ2I VmpwLQAAT8d1eQgSQMO+NWLVPvbQK0sOsXAdETOKidu+CrRom1O3DXFOTI3wLE8b6MVoVoPaxbc HN2FIPx0K5Ztyo9uU0Ld//l1J0AoW4qtw4xqSjw7bS1ckhEbY7dNDWTOOedgai6/YSu15xZFgSB RClunVz536cBsT6NgEI+MMzau2sLUGUyrhPAonR8jvumlr8l8miCulCtZ93JXDj+gfNVEymED+s 8cWqY1FTTh3G12+UMemwoXcJJWZHopX1KY4FOoZwzixCgR4aPtWfP6x6lAtcJTdfpMZesyE7kkn 0o1SwtdThdBBld9WIdwfxZ1CMjyENnJJ2FDgTXIhUW2XDsuQvXDxwksjdQd57CEHtHMYYKY2FGZ S8J2yN43IAlcD+QZb8VHz4kCFmD580iXDxfDGgwaDCJxmZAHAVUXZgTWZi0JQuBoi6dXHtHsfHB qvMw+iy3gN48Kiyuj8Zry+F4oNXvf/iIa/hN6o8Os3djFBMb X-Received: by 2002:a05:6820:55c8:20b0:6f4:fb85:5e42 with SMTP id 006d021491bc7-718a625b59emr46131eaf.21.1794253684765; Mon, 09 Nov 2026 11:48:04 -0800 (PST) Return-Path: Received: from localhost.localdomain ([2601:283:4b01:ba50::3232]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-718aa132e65sm70363eaf.14.2026.11.09.11.48.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:48:04 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v9 3/9] oeqa: Add SPDX deploy SBoM test Date: Mon, 9 Nov 2026 12:45:39 -0700 Message-ID: <20261109194759.550935-4-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109194759.550935-1-JPEWhacker@gmail.com> References: <20261104153535.3184146-1-JPEWhacker@gmail.com> <20261109194759.550935-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 lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 19:48:08 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249868 Adds a test that verifies that the deploy SBoM is created correctly Signed-off-by: Joshua Watt --- meta/lib/oeqa/selftest/cases/spdx.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/spdx.py b/meta/lib/oeqa/selftest/cases/spdx.py index c900558b44..8cc51c1369 100644 --- a/meta/lib/oeqa/selftest/cases/spdx.py +++ b/meta/lib/oeqa/selftest/cases/spdx.py @@ -485,3 +485,14 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): for candidate in objset.foreach_type(oe.spdx30.software_Package): self.assertIsNone(candidate.releaseTime) + + def test_deploy_sbom(self): + kernel_recipe = get_bb_var("PREFERRED_PROVIDER_virtual/kernel") + + objset = self.check_recipe_spdx( + "virtual/kernel", + f"{{DEPLOY_DIR_IMAGE}}/{kernel_recipe}-deploy-sbom.spdx.json", + ) + + # Document should be fully linked + self.check_objset_missing_ids(objset) From patchwork Mon Nov 9 19:45:40 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 103526 Received: from mail-oo1-f51.google.com (mail-oo1-f51.google.com [209.85.161.51]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.3700.1794253686309113381 for ; Mon, 09 Nov 2026 11:48:06 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20260707 header.b=q+WbQhBK; spf=pass (domain: gmail.com, ip: 209.85.161.51, mailfrom: jpewhacker@gmail.com) Received: by mail-oo1-f51.google.com with SMTP id 006d021491bc7-70059e4dab6so684421eaf.3 for ; Mon, 09 Nov 2026 11:48:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794253685; x=1794858485; 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:content-type; bh=/2WIZpwPimqavDkzbT1ZpVYufGFe+CtcAal/HZACf5Y=; b=q+WbQhBK+t6kZSRig4nsTYrY/Jewxa2Rn04A+YiYM4ZuYJghnfDNqtAiW6mR2W6qA5 H7gOA7laYWI32qpn5qF/0rRAwyWyt+CFocSN6qVsQKnSqdO7JWTbXpZspzVtL+QYpZmt 9KLQBQgJyJPoQ1cToYZRESX5eOrnPr/WIlqF+ktExg0xb8JJt2ip4HNZvlNhz1AAuj/N 96drW47vzpJfPo7pSyIm+RnnoWxmhtrZFG/poUVOjA5EEpdLkCu8k53Us83hPot2HOEs HRfEyRoeRTws8eKfT4SYgkTwXFkGB58SjbHyMcf0FCzHk1Ee14LHs2PysvO4AJPOpRoo 1kOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794253685; x=1794858485; 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:content-type; bh=/2WIZpwPimqavDkzbT1ZpVYufGFe+CtcAal/HZACf5Y=; b=zSOf1lqw2HGC2ol1vWou6m2JvALQA935AfOvKEIowUSH7CXRT2Yi+8vPqPRl7qfxmV HHrfhDWTz1iu2qyT8UU5RKN2bKndMhoVEki/svPxb7wefkHsVM2MyM2OZhhmjUC1N076 cmbaR0CNo/BRmEUNqUlRHbJ4PkSMqv3sFkcj5JJiNRzFVcDq8wy5ZEey/NduixarQB03 Rc6c3NE6r6wKTyFUZhBom+XIy1d9kdUNiJw6JIZDmhgZ2jhqnMbL6s+B7VGDFzWP2ncF J15ru9IfXESU4KiWJ/DTDBGzbLVBMXQWrxEsLiZd0kX8CJgat3KwMlLiSlza3ZW6c79d 81bQ== X-Gm-Message-State: APuU4Z8rnpPkdgC/M7fqQYcE41k5WrmhsCnJ/0UPh1hthl39y2+spzg/ Zs5hp8SWb3N5nh0UflBLuPThVZ+7RrHZsNFYEr/CmoL04GezBOoY9CtZEbHFRA== X-Gm-Gg: AYBFou0sakk4MdJBiziubwHN6rBQsKhEqnxfGuiifIu1DnfCGZge0hzY31HyjOj7C1v 6NpynM386bbZvhu7ACS7rQvQ2wp+B4Ph6O2UaEnCYmKq3qFbL0mhEh2mmuXPbpxinNmaTj2aC85 /t0PmDIfwd7JCDrc7CxxVGj31J7iepFNSi9EQMk4wIn9qu1xqA8D4o4QivvLR0YAQvEhHd/QI/J Ce/WZFHU93+BEagbYiRjTvD3esJ4O4paDF3qMW68iWyDqyq0BJGGnByY97tLF7aUVUUFOlnFsn7 UVEFYMU+Gr3Tla6i1+8qT0ktSMVs92Z88OywdSQA/F24W4q+0mcNqmjkF/n+uC8lwXrtXXdg4Km eA9pq/LiEvvmZgjOHAdEGVDrhMXZKHAKtykkT/vxKfYH0gZSDGZhChIImZVg4tIZoJrRhF6P0X+ 9ZsjVnlD9tq8dFJnTVQSVG40GW1zMlWQ/Wchs4nBXPSgaK5OBhggROSG0qMDHwHFR7KcHvuhGhx 5GR3XZLKlNqDvgZfQITeE5mhQdtV5IxgGJE2B2ThpWAvJ/TA4DUHZIDuLqbAfxoGMfVsIqzhndL uDQ3Avn49tp++qQGPGABKCRSGu8VG5koHWS7VlSOhsB06HBY X-Received: by 2002:a05:6820:6fc5:b0:714:adb2:3245 with SMTP id 006d021491bc7-718a5f4ab69mr79054eaf.37.1794253685424; Mon, 09 Nov 2026 11:48:05 -0800 (PST) Return-Path: Received: from localhost.localdomain ([2601:283:4b01:ba50::3232]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-718aa132e65sm70363eaf.14.2026.11.09.11.48.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:48:05 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v9 4/9] classes-global/sstate: Keep SPDX generating setscene dependencies Date: Mon, 9 Nov 2026 12:45:40 -0700 Message-ID: <20261109194759.550935-5-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109194759.550935-1-JPEWhacker@gmail.com> References: <20261104153535.3184146-1-JPEWhacker@gmail.com> <20261109194759.550935-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 lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 19:48:07 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249869 Tasks that create SPDX documents can reference SPDX ids from documents created by any task they depend on. When it comes time to create the final SBoM, these referenced SPDX ids must be present so that they can be merged into the SBoM. Specifically, when a task that restores from sstate (a setscene task) is one that can create an SPDX document, and that task is depended on by at least one other task that can create an SPDX document, it must always be restored. Signed-off-by: Joshua Watt --- meta/classes-global/sstate.bbclass | 38 ++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass index b2fa93650a..c6d9459182 100644 --- a/meta/classes-global/sstate.bbclass +++ b/meta/classes-global/sstate.bbclass @@ -1125,11 +1125,28 @@ 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_create_recipe_spdx", "do_deploy_archives"] + directtasks = ["do_populate_lic", "do_deploy_source_date_epoch", "do_shared_workdir", "do_stash_locale", "do_gcc_stash_builddir", "do_deploy_archives"] + + # SPDX tasks are only needed if depended on directly, unless they are + # needed by another task that is creating SPDX documents + SPDX_TASKS = {"do_create_spdx", "do_create_recipe_spdx", "do_create_package_spdx"} def isNativeCross(x): return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x or x.endswith("-cross") + def isSpdxTask(key): + taskname = taskdependees[key][1] + # Tasks that start with "do_deploy" might be included in + # SPDX_DEPLOY_TASKS and should be kept + if taskname.startswith("do_deploy"): + return True + + # Tasks that are don't start with do_deploy, but still deploy SPDX data + if taskname in {"do_image_complete", "do_populate_sdk", "do_populate_sdk_ext"}: + return True + + return taskname in SPDX_TASKS + # We only need to trigger deploy_source_date_epoch through direct dependencies if taskdependees[task][1] in directtasks: return True @@ -1142,6 +1159,8 @@ def setscene_depvalid(task, taskdependees, notneeded, d, log=None): return False return True + spdx_deps = [] + for dep in taskdependees: logit(" considering dependency: %s" % (str(taskdependees[dep])), log) if task == dep: @@ -1198,12 +1217,27 @@ def setscene_depvalid(task, taskdependees, notneeded, d, log=None): # Target populate_sysroot need their dependencies return False - if taskdependees[dep][1] in directtasks: + # Collect dependees that create SPDX documents + if isSpdxTask(dep): + spdx_deps.append(dep) + continue + + if taskdependees[dep][1] in directtasks or taskdependees[dep][1] in SPDX_TASKS: continue # Safe fallthrough default logit(" Default setscene dependency fall through due to dependency: %s" % (str(taskdependees[dep])), log) return False + + # SPDX generating tasks can refer to the SPDXID from the SPDX output of + # their dependencies. Therefore if the current task can generate SPDX and + # is depended on by another SPDX generating task, it must be kept so that + # the IDs can be correctly resolved when merging SPDX output into a + # complete SBoM + if spdx_deps and isSpdxTask(task): + logit(f"Keeping SPDX task {taskdependees[task]} needed by SPDX task(s) {', '.join(str(taskdependees[k]) for k in spdx_deps)}", log) + return False + return True addhandler sstate_eventhandler From patchwork Mon Nov 9 19:45:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 103527 Received: from mail-oo1-f47.google.com (mail-oo1-f47.google.com [209.85.161.47]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.3758.1794253686954455223 for ; Mon, 09 Nov 2026 11:48:07 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20260707 header.b=ewXR4vex; spf=pass (domain: gmail.com, ip: 209.85.161.47, mailfrom: jpewhacker@gmail.com) Received: by mail-oo1-f47.google.com with SMTP id 006d021491bc7-6aa9606ddadso694174eaf.0 for ; Mon, 09 Nov 2026 11:48:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794253686; x=1794858486; 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:content-type; bh=BWf9nPwSiawEirgLzEzSMAEs/S1YebD127It0ONYkPc=; b=ewXR4vexress13mExhd+g/oH16BTVLTKkmtyS3g2Ml5ZKzZDcQIRpldJ1mQZGXD92H r5xwS2GM57rk0jK7qE/VnPuZyXLsD3TNDBASIQincXOspQ9blg+2SDs54kQu4MgqW1mZ HoAvjnIXNKc01uDsEb92XyCujgBPYPfVU8B7unA3CB7xWH9yvmfM9i5FsCJDp8NvLGAd 2O3Mw0mWzJS19LMZEJUplZi7o9YHpo6QMBL1xHeJmniY1zwxYZVPZdf0uleydAclaPLg Ddx10DxngjhX2S6kh9hg8Btq4vozkMsAHxBMzLoxNVqF9xGiVTYuWOJwYUHaLClKSwZ6 jXuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794253686; x=1794858486; 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:content-type; bh=BWf9nPwSiawEirgLzEzSMAEs/S1YebD127It0ONYkPc=; b=llZSM8KjQN6jKLyJA6ydq3Wwf17I9+0zlif1Mt26hbHihwQ0SkiO7huX75FK8lidww pE1/yR+VDDubK6Xtg1k2MJlfXldkbtDpS/+MyV7HpFS8iQbkk91Xor2nzV1jogbZP+i+ DjjHF00bxQt1LEUohPfimGu4ru2L91BogKPLHSukdkJPPsjWGioDLHtZ2cO9yhTnihls J4kMAKoIf2qUBrutraSAmYVyKii9KVLO09rflAEwYkmZfG8KH08s6w4/xO4i66ZpzHPk Kitq7mM2vVy6oKHeRuLmp4ns2GVOyaYkmO8BJJe+v39d1iKc2mBIOdpEEucxz0KgyIAT 0s7A== X-Gm-Message-State: APuU4Z+823Rx5TU4H0lvJ9NdhIgiQq5WA1o52+K9wiTLW4CXIdXNP8JU +3qyhGqCY/Q7oHTgToVpK7nGqa/jjEQJBycmUUamglveld+4y7m3IrFT/OE3JA== X-Gm-Gg: AYBFou0XvaxAHTsTQqG71BVavh1HE1Yq5yM4kQEQOL+XIxYrsbOHCvQxy+YQn8Bi19G jHCsqU6qvQa2CLe7EqW27wzPAt5flo81yLok5WsYH52tc7uacnfgMARap85Jng5zOqy63exFeML MkvjQk1JAS7/h76J8uxWZdE3KmfXW8nH5eY8qPL/0wDh8wn7kMG6C2A+CNKReWEh6CtgJghD+pK rHK98xJ8WtiRUrx8Bze0I+9/Mb/2ty4KuiHCBmWXQTwT9h2ss/XR1jXdMkwdnoTTw7YSSzm2QAb OKSGiOf56of35rmeqWOvHAf+MfgtsnX/M9lPFONirHmXJo/SSI9qlLnGSQ34zBRe3FK8xUOGDUE NaagbVogV35oJysmDTybA9L20w/34qhRBhfsxJTnieiAXkkeiyDIAy46sbHsr7HU8va/LQYd3pl hKvQOjISPZ5voQSaNrTHRbbsjfA+iE6UFUYN2ECeOB5UVYNwVkxaByQP4KeOmAVCBwSacbZP5bs A6r+dgqoAazvyUvMsGh9/dVjvhYZbS/DF+vqkNP4r9dwvBYVpDFXc6tYF/vnWXctLWpO0HLNiG1 msu6IaLma7NKR10DBAy+Gy1jeVw= X-Received: by 2002:a05:6820:5717:10b0:6f9:59ee:cfb7 with SMTP id 006d021491bc7-718a499ca38mr72828eaf.23.1794253686095; Mon, 09 Nov 2026 11:48:06 -0800 (PST) Return-Path: Received: from localhost.localdomain ([2601:283:4b01:ba50::3232]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-718aa132e65sm70363eaf.14.2026.11.09.11.48.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:48:05 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v9 5/9] classes-recipe/deploy: Add do_deploy to SPDX_DEPLOY_TASKS Date: Mon, 9 Nov 2026 12:45:41 -0700 Message-ID: <20261109194759.550935-6-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109194759.550935-1-JPEWhacker@gmail.com> References: <20261104153535.3184146-1-JPEWhacker@gmail.com> <20261109194759.550935-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 lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 19:48:07 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249870 Any recipe that inherits this class will automatically generate deploy SPDX data for the do_deploy task Signed-off-by: Joshua Watt --- meta/classes-recipe/deploy.bbclass | 1 + 1 file changed, 1 insertion(+) diff --git a/meta/classes-recipe/deploy.bbclass b/meta/classes-recipe/deploy.bbclass index f222a8560f..a3b48d6f7a 100644 --- a/meta/classes-recipe/deploy.bbclass +++ b/meta/classes-recipe/deploy.bbclass @@ -6,6 +6,7 @@ DEPLOYDIR = "${WORKDIR}/deploy-${PN}" SSTATETASKS += "do_deploy" +SPDX_DEPLOY_TASKS += "do_deploy" SPDX_DEPLOY_ARTIFACTS_DIR:task-deploy = "${DEPLOYDIR}" do_deploy[sstate-inputdirs] = "${DEPLOYDIR}" do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" From patchwork Mon Nov 9 19:45:42 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 103531 Received: from mail-oo1-f43.google.com (mail-oo1-f43.google.com [209.85.161.43]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.3759.1794253687841315510 for ; Mon, 09 Nov 2026 11:48:07 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20260707 header.b=t42GyvD7; spf=pass (domain: gmail.com, ip: 209.85.161.43, mailfrom: jpewhacker@gmail.com) Received: by mail-oo1-f43.google.com with SMTP id 006d021491bc7-70b875f6f1fso927167eaf.2 for ; Mon, 09 Nov 2026 11:48:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794253687; x=1794858487; 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:content-type; bh=znJsOH+KAlXRhXhiVX0zyArJLwg5I7pykD+KpriRkIo=; b=t42GyvD7IkcO9Q7+X+2Xjzlu+zFnFPsYMUaXQV6X8vjFXNOpk5H4Kk/pW+SMRXnv24 O5SEN8w6H9cMlRofvheDV8aiodJsG5dL3huOEyscVs64XScIaovdF5tyl6+Q0TTDILVU eC/MbGyd64boQGiHNQ4i/BxkqnygvKwCSd0pgWa06alef96VgzQarmVi2tylBat1ZEmF P7CtmLFKcfK2uQfV3PjVZiqdS01WfcWY/RMdHbEthe3EoXZ0rhwiVRAO1ElHzqwANcTY BuzLKs+zlgmkZ0CMej25GExnko+z7vyheOfGcBRW/7z8eysz1PQYOVnzDJ/yRpViC/fO 4XiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794253687; x=1794858487; 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:content-type; bh=znJsOH+KAlXRhXhiVX0zyArJLwg5I7pykD+KpriRkIo=; b=pnnH/9anEPJioRkP/u1gtRVSOwXaatLnKJqph/tpmV2y3DRxjhX/RGSxTgapUnLVJI eTEdGwQxhXDsrzdV8cSeuoCXU7ruOEeoWRvOo1byuz//x22TpuORrF9M90rCaolr62IG eksY8OKQOdXUw6iX3CiOpkvXI4IyFMziB+NO/P0vRaDFdHFOSrkwbMYSktDmslcgUxhl 0vrNYesUyrcsD6fZwkpp4NF0yayKPGNd0S0Q2uXLMWg9DkfclCFet31en2iESeUFdA5c WRQb+NWogaf7CYqTEmErjwsjiDmq0Ge/mQfZQvr3tV/bBHbIsg651dHHnAzMd6lWeUT+ fJag== X-Gm-Message-State: APuU4Z+mhjI0GV85gh7d9NA01FwkRhA/5Arqw0AvgBeilIgsAev+fOPM EHdsx44xCYwYFcrUeiDrzgCeDnhrcJqkI5VK1tVaCU6gQX+HyEwKxQsZI2uyBQ== X-Gm-Gg: AYBFou2meY+rLbepXMTTwdMch4wGVtpswnKc74MY1Pf2XsYwpz6Oe7HVZlP6KYQIMIf Dv2OufkIXKgfrHRcqALHxiar3YNPa5PBlACyecM5Bt/a2nRO7bsZEsLYthXWSGz6OUAx9qAEIQZ K88ZVCqJHVbftSBjiclJPUd/5jWm0qdIf23H/AOzymKUutjIvO0i6bD5JrJ/aLk2as5TBvxyvcD 79fZLixwFQZzqu/dtNPE0LIG/VvRRPoJy1M4AiV16s32+1Vz+28ijh4CMPeCAGTUbUWev27RsoM bXELarEW90GeUdT8T/CQH/Q+C9+lDpzZ8HIh0+7euWkr7+JnZa/3MDtzT+npJ5si/tow9V6w/sQ nHbop9Hxi459zmCSYIRUhic0ZJLzAB7lWab6UI55WdtfTmCGx+35e1b9UT06GfealsMqetTeK44 H2m3s1fknrNMUihSPpJgza72DQMRGB2qcIRBeEWyBcIFDuMQ8oXkV506ckxa5WOT47CpZTeV2j8 rQJqSvg30uWnGpTA2yoNfBE8JHgzKWBeWQsX0ka5MYsHIRhcVa2eMVMKgNlJElROhecbRxUAa+t /O59NqevHhTlhswsVknyVYJ5cCk= X-Received: by 2002:a05:6820:8593:20b0:715:264c:2330 with SMTP id 006d021491bc7-718a5e4b845mr66558eaf.33.1794253686951; Mon, 09 Nov 2026 11:48:06 -0800 (PST) Return-Path: Received: from localhost.localdomain ([2601:283:4b01:ba50::3232]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-718aa132e65sm70363eaf.14.2026.11.09.11.48.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:48:06 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v9 6/9] spdx: Replace do_create_image_spdx with deploy task Date: Mon, 9 Nov 2026 12:45:42 -0700 Message-ID: <20261109194759.550935-7-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109194759.550935-1-JPEWhacker@gmail.com> References: <20261104153535.3184146-1-JPEWhacker@gmail.com> <20261109194759.550935-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 lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 19:48:18 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249871 Replaces the dedicated do_create_image_spdx task with a deploy task tied to do_image_complete (which is task that deploys images). This has the advantage that images recipe SPDX dependencies are now completely automatically detected in the task graph, and the SPDX documents are merged in automatically when dependencies on do_image_complete are detected Signed-off-by: Joshua Watt --- .../create-spdx-image-3.0.bbclass | 32 +++++++------------ meta/classes-recipe/nospdx.bbclass | 1 - meta/classes/create-spdx-3.0.bbclass | 3 -- meta/classes/spdx-common.bbclass | 1 - meta/lib/oe/spdx30_tasks.py | 23 ++++++++----- 5 files changed, 27 insertions(+), 33 deletions(-) diff --git a/meta/classes-recipe/create-spdx-image-3.0.bbclass b/meta/classes-recipe/create-spdx-image-3.0.bbclass index b60cdd826f..64cb065632 100644 --- a/meta/classes-recipe/create-spdx-image-3.0.bbclass +++ b/meta/classes-recipe/create-spdx-image-3.0.bbclass @@ -30,7 +30,7 @@ python do_create_rootfs_spdx() { import oe.spdx30_tasks oe.spdx30_tasks.create_rootfs_spdx(d) } -addtask do_create_rootfs_spdx after do_rootfs do_create_recipe_spdx before do_image +addtask do_create_rootfs_spdx after do_rootfs do_create_recipe_spdx before do_image do_image_complete SSTATETASKS += "do_create_rootfs_spdx" do_create_rootfs_spdx[sstate-inputdirs] = "${SPDXROOTFSDEPLOY}" do_create_rootfs_spdx[sstate-outputdirs] = "${DEPLOY_DIR_SPDX}" @@ -43,33 +43,25 @@ python do_create_rootfs_spdx_setscene() { } addtask do_create_rootfs_spdx_setscene -python do_create_image_spdx() { +python create_image_spdx() { import oe.spdx30_tasks - oe.spdx30_tasks.create_image_spdx(d) -} -addtask do_create_image_spdx after do_image_complete do_create_rootfs_spdx do_create_recipe_spdx before do_build -SSTATETASKS += "do_create_image_spdx" -SSTATE_SKIP_CREATION:task-create-image-spdx = "1" -do_create_image_spdx[sstate-inputdirs] = "${SPDXIMAGEWORK}" -do_create_image_spdx[sstate-outputdirs] = "${DEPLOY_DIR_SPDX}" -do_create_image_spdx[cleandirs] = "${SPDXIMAGEWORK}" -do_create_image_spdx[dirs] = "${SPDXIMAGEWORK}" -do_create_image_spdx[file-checksums] += "${SPDX3_DEP_FILES}" -do_create_image_spdx[vardeps] += "\ - SPDX_IMAGE_PURPOSE \ - " + from pathlib import Path + current_task = "do_" + d.getVar("BB_CURRENTTASK") -python do_create_image_spdx_setscene() { - sstate_setscene(d) -} -addtask do_create_image_spdx_setscene + spdxdeploydir = Path(d.getVar("SPDXDIR") + "/deploy-" + current_task) + oe.spdx30_tasks.create_image_spdx(d, spdxdeploydir) +} +oe.spdx30_tasks.create_image_spdx[vardeps] += "SPDX_IMAGE_PURPOSE" +SPDX_DEPLOY_TASKS += "do_image_complete:create_image_spdx" +# No deploy sbom is needed since do_create_image_sbom_spdx() is used instead +SPDX_DEPLOY_SBOM = "0" python do_create_image_sbom_spdx() { import oe.spdx30_tasks oe.spdx30_tasks.create_image_sbom_spdx(d) } -addtask do_create_image_sbom_spdx after do_create_rootfs_spdx do_create_image_spdx before do_build +addtask do_create_image_sbom_spdx after do_create_rootfs_spdx do_image_complete before do_build SSTATETASKS += "do_create_image_sbom_spdx" SSTATE_SKIP_CREATION:task-create-image-sbom-spdx = "1" do_create_image_sbom_spdx[sstate-inputdirs] = "${SPDXIMAGEDEPLOYDIR}" diff --git a/meta/classes-recipe/nospdx.bbclass b/meta/classes-recipe/nospdx.bbclass index 723194da2d..fafcdd0a13 100644 --- a/meta/classes-recipe/nospdx.bbclass +++ b/meta/classes-recipe/nospdx.bbclass @@ -10,6 +10,5 @@ deltask do_create_spdx deltask do_create_spdx_runtime deltask do_create_package_spdx deltask do_create_rootfs_spdx -deltask do_create_image_spdx deltask do_create_image_sbom_spdx deltask do_create_deploy_sbom diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index fb6a4f249e..0d0bddcc67 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -381,9 +381,6 @@ python () { # for the recipe, at least until it's possible for do_populate_sysroot # to describe it's own output. "do_populate_sysroot": "do_create_spdx", - # If an image is needed, also depend on the task to create the SBoM for - # the image - "do_image_complete": "do_create_image_spdx", } def map_task_deps(task, flag): diff --git a/meta/classes/spdx-common.bbclass b/meta/classes/spdx-common.bbclass index bca169670d..13839aac3a 100644 --- a/meta/classes/spdx-common.bbclass +++ b/meta/classes/spdx-common.bbclass @@ -15,7 +15,6 @@ CVE_VERSION ??= "${PV}" SPDXDIR ??= "${WORKDIR}/spdx/${SPDX_VERSION}" SPDXDEPLOY = "${SPDXDIR}/deploy" SPDXWORK = "${SPDXDIR}/work" -SPDXIMAGEWORK = "${SPDXDIR}/image-work" SPDXSDKWORK = "${SPDXDIR}/sdk-work" SPDXSDKEXTWORK = "${SPDXDIR}/sdk-ext-work" SPDXDEPS = "${SPDXDIR}/deps.json" diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index 43e196806f..069c759523 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -1546,19 +1546,19 @@ def create_rootfs_spdx(d): ) -def create_image_spdx(d): +def create_image_spdx(d, spdx_deploy_dir): import oe.sbom30 - image_deploy_dir = Path(d.getVar("DEPLOY_DIR_IMAGE")) + pn = d.getVar("PN") + current_task = "do_" + d.getVar("BB_CURRENTTASK") + + image_deploy_dir = Path(d.getVar("IMGDEPLOYDIR")) manifest_path = Path(d.getVar("IMAGE_OUTPUT_MANIFEST")) - spdx_work_dir = Path(d.getVar("SPDXIMAGEWORK")) image_basename = d.getVar("IMAGE_BASENAME") machine = d.getVar("MACHINE") - objset = oe.sbom30.ObjectSet.new_objset( - d, "%s-%s-image" % (image_basename, machine) - ) + objset = oe.sbom30.ObjectSet.new_objset(d, f"{pn}-{current_task}-deploy") with manifest_path.open("r") as f: manifest = json.load(f) @@ -1651,13 +1651,18 @@ def create_image_spdx(d): objset.add_aliases() objset.link() oe.sbom30.write_recipe_jsonld_doc( - d, objset, "image", spdx_work_dir, create_task_link=True + d, + objset, + "deploy", + spdx_deploy_dir, + create_task_link=True, ) def create_image_sbom_spdx(d): import oe.sbom30 + pn = d.getVar("PN") image_name = d.getVar("IMAGE_NAME") image_basename = d.getVar("IMAGE_BASENAME") image_link_name = d.getVar("IMAGE_LINK_NAME") @@ -1679,7 +1684,9 @@ def create_image_sbom_spdx(d): root_elements.append(oe.sbom30.get_element_link_id(rootfs_image)) image_objset, _ = oe.sbom30.find_jsonld( - d, "image", "%s-%s-image" % (image_basename, machine), required=True + d, + "deploy", + f"{pn}-do_image_complete-deploy", ) for o in image_objset.foreach_root(oe.spdx30.software_File): root_elements.append(oe.sbom30.get_element_link_id(o)) From patchwork Mon Nov 9 19:45:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 103532 Received: from mail-oo1-f41.google.com (mail-oo1-f41.google.com [209.85.161.41]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.3701.1794253688406538284 for ; Mon, 09 Nov 2026 11:48:08 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20260707 header.b=lt4vdIMz; spf=pass (domain: gmail.com, ip: 209.85.161.41, mailfrom: jpewhacker@gmail.com) Received: by mail-oo1-f41.google.com with SMTP id 006d021491bc7-6aa9606ddadso694190eaf.0 for ; Mon, 09 Nov 2026 11:48:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794253687; x=1794858487; 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:content-type; bh=/qc9A3xDZL0PLR2xUGS0JajTq0EAjpbSucIh696uA48=; b=lt4vdIMzKmTJcZkpH1pPjYtS6uY5QR+5Q5f4c7bjIS7+fc2+KoP5N3jC6ZGb11TF3D 0xL2DweHBoJbtpH3VjAX38FwtTIpptHS3bO8cp2uA0erWTIjKUgfXUFkYuLQtkWZwozk oFbmBkpBVmO5DxuMwkYnofZ5bJ6TDnvv4+VHr9ZKeUTfuo0A8BMMcH3X1pb2i/RPq4DQ NOFvQYp7AgoCbe8G/nCiCp5paOB5OPRnqeYCD5hvGhYM5ujnYJBe59JvOBdl6+0gcOID 51XukbRVrDfWIrqnKlq7qCtrpekwD0W87esCaPQsHu9Fme6rWcJDj+zTolml8Fy0anFX 26yQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794253687; x=1794858487; 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:content-type; bh=/qc9A3xDZL0PLR2xUGS0JajTq0EAjpbSucIh696uA48=; b=EwZ5a5CbsfcCoVMckJnQ3YQHySdsOalNMLmJNgd7GXMwnUXsrrX3AXZFB/3vDLmUIM cET17Q7v72VHCvwOdyLf3f74xnHvVfIPAx9mkMgX0XTIO4/S+AQPWhboHHR6u4sZfkji VQ1mcF+HjxwiCO06I+uNAIlGj771ppW7lEZ+P0WKQwDWrmO1+JXOQiyYKRWWXXKXP+/G /ZiCjd77zyr3RGZCxEq0PrsMpv20fBd++5GFfVzvgyXs2eLvXK6EN8YgFTE+KXr2Wgrk /Q96D/l+m+skdFfzs/wHXZ7V4l/jquLW3GBt4bHu3spxEQDk5Jm2XHDEECad2dFQwpD7 va8w== X-Gm-Message-State: APuU4Z+oDx/hE7em32LpwuQpUKfclxFB9n0utET13eUHVTPw2ZWgc5jU Yxmb+UCIPzZ/fmWuHb94A+h8bP0vnapThG5QyM7C13z+rb11KJ28lBuB5Vej6Q== X-Gm-Gg: AYBFou1ARG+syDUcRRmD6xhJOADynleAbKdGicyf3zQymtzNFuPKH7gkFPbS3ibXY3d HwisHMu/ZNQ12yFll3+ACnWbII3+AzUg6lb7tiQmtbteBYCXnE0NwSv80RsdLv+pVm4eJI3O7pF rZ29iEVxeHRAlLottfCyppyKi4/JFBCwYD9H0aKl39qoh0qzaqUv6McO5U/rAWUzpZpDFvZPv2b Ix6Jdrpn+qpRHV/W9UJ6NZj+08XfBMi5wBowWD5USam8Ek9k1FgftuZIax1h9CK96JTUW1OTw52 p72yXVKxGrvCNqBXSS+XeeYZo8gUdqdwx7FTbP7TfplI6nt7Ispkw1wMmMk/nOQIVrDW4FUsh/u HSA+0oEczOs16aO7qWTBHwhNePEJKn83lgSoglQodDEFHjr6kcucpUXwNVjf4c2TMlY8fTDN9Oy n4Ds6Wm/qpKcefWNawE4V1FWQI6R3hX1QNEaBB36/0rc6OE31ZKNmoD7nXvFdfxk7skfilKdOji k3thKo5OinCiq0Jq5yoUjfZzEQoKb2x1MpO64hkMHZq5SOuP/xOL2qxWnbjTI9+l9AI03toZliK z0gnOafIWqwHxDiBexxzKifah54= X-Received: by 2002:a05:6820:1395:b0:6b7:8415:d78f with SMTP id 006d021491bc7-718a5f4034bmr100677eaf.58.1794253687564; Mon, 09 Nov 2026 11:48:07 -0800 (PST) Return-Path: Received: from localhost.localdomain ([2601:283:4b01:ba50::3232]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-718aa132e65sm70363eaf.14.2026.11.09.11.48.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:48:07 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v9 7/9] layer.conf: Fix initramfs-framework not knowing which udev it has Date: Mon, 9 Nov 2026 12:45:43 -0700 Message-ID: <20261109194759.550935-8-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109194759.550935-1-JPEWhacker@gmail.com> References: <20261104153535.3184146-1-JPEWhacker@gmail.com> <20261109194759.550935-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 lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 19:48:18 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249872 The SIGGEN_EXCLUDE_SAFE_RECIPE_DEPS from initramfs-framework to eudev and systemd meant that it would not correctly update when switching udev providers (for example, when switching from the "poky" distro to "poky-altcfg" distro). Fix this by removing both entries. This also requires that the recipe no longer be allarch since it will change based on distro, which in turn requires initramfs-module-setup-live to exclude it from signature generation so that it can remain allarch. Signed-off-by: Joshua Watt --- meta/conf/layer.conf | 3 +-- meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/meta/conf/layer.conf b/meta/conf/layer.conf index 13c920be6c..67fef79154 100644 --- a/meta/conf/layer.conf +++ b/meta/conf/layer.conf @@ -59,8 +59,6 @@ SIGGEN_EXCLUDE_SAFE_RECIPE_DEPS += " \ docbook-xsl-stylesheets->perl \ ca-certificates->openssl \ initramfs-framework->${VIRTUAL-RUNTIME_base-utils} \ - initramfs-framework->eudev \ - initramfs-framework->systemd \ initramfs-module-install-efi->dosfstools \ initramfs-module-install-efi->e2fsprogs \ initramfs-module-install-efi->parted \ @@ -69,6 +67,7 @@ SIGGEN_EXCLUDE_SAFE_RECIPE_DEPS += " \ initramfs-module-install->grub \ initramfs-module-install->parted \ initramfs-module-install->util-linux \ + initramfs-module-setup-live->initramfs-framework \ initramfs-module-setup-live->udev-extraconf \ grub-efi->grub-bootconf \ liberation-fonts->fontconfig \ diff --git a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb index 2ec03bc34c..2c5ff10813 100644 --- a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb +++ b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb @@ -4,8 +4,6 @@ LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384 RDEPENDS:${PN} += "${VIRTUAL-RUNTIME_base-utils}" RRECOMMENDS:${PN} = "${VIRTUAL-RUNTIME_base-utils-syslog}" -inherit allarch - SRC_URI = "file://init \ file://exec \ file://nfsrootfs \ From patchwork Mon Nov 9 19:45:44 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 103533 Received: from mail-oo1-f52.google.com (mail-oo1-f52.google.com [209.85.161.52]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.3760.1794253689325049251 for ; Mon, 09 Nov 2026 11:48:09 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20260707 header.b=GUTVTybZ; spf=pass (domain: gmail.com, ip: 209.85.161.52, mailfrom: jpewhacker@gmail.com) Received: by mail-oo1-f52.google.com with SMTP id 006d021491bc7-6e560e00a86so734648eaf.1 for ; Mon, 09 Nov 2026 11:48:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794253688; x=1794858488; 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:content-type; bh=BTYMigd0+ZyC4B85UyNY8s3jidM5wVxaP5djY52xhfM=; b=GUTVTybZ4FmZ4CSW7pCCuD7dxYRCLzExR7IRMr/L01QvWGT4UJ6HZnCaF+GogKxHR1 CO1+atUdaFikE+cW/nvdi6+I37V7uXGEjiKqH9pPlOQXV2zI/iEHosnSUdwUGWNViAov 1+klZKjTjCGciFGp7GvTw0iB43Fghx9PypiDXzG5IyWfNQvhsTbD5ex7aHO39m0IovPk CjQ3pJn19Q11IkPVPWOjmeWIxhQNo6g1mwdFRYCQp/h/wa/pvE5vw+boOGZqb9hHqFKU YOo8jndMHIXS06HJL3dOeImg9MD1fJPlcojlybBTKWpMH7LCuXPScjdY6rOz62hiuoie V7jQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794253688; x=1794858488; 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:content-type; bh=BTYMigd0+ZyC4B85UyNY8s3jidM5wVxaP5djY52xhfM=; b=m4G6QGoQY/4VN0+HKf7NlzE/ci+cx/upIWAvobVdIMfWRx99TQxBQsDbyxnYgcvPGl ZbRfimrgMmGzvvdRoToZJ2gdwizPqZuC0ghJ2apnx2vo91Yw+2XSf/9zg9Wg0ZpVMMrc sLAm9bfDvsAHpEyJuuuLyCTUa9ol8z49NFcpaL8S87AniIIyQSv+aQlxzwGPwNJr70Fg TQDv3p2LcdMvGQsWQNDdO/bRVoWNyT+gmCLeT7oscXxQyaDCiyuu3vqYTO3vkPzcBUCg 3XfB5+4jDexVGybG3Sny8RU6i25raM31qHQ2wtoBTrcuA9vkdemP51gK3TeJCnrdz3ko iwsw== X-Gm-Message-State: APuU4Z8G7Eo9i+BVc/2LCXi5FKFj68ouH3r6gqnu8a/4ML/QsKv06Vao jQr6373fBNRfcRde2S+5TvEH4rOvxpnPkjEEG30zSJWEchKjp4XJ/g6oG/+wVQ== X-Gm-Gg: AYBFou2i69G0KBiWWN486JMguw/iyPqPFQSA1Yw8TJblH8xzG7wqwyvjZmRPI37ShI2 /MnxX4cJe0sryWZZU68J3eQrVPb+YmWh9Zzy3Ny1bWlo1Topo9tElw3eHLIb/BEuhK10Kwrlb3N m9I8eBVBHypmlBHKoO6qG/ReHkhj34H+5QfH603xDMF5P2ZR9PruWfAla/Lw2p3F3tYxPTa2C0q 4cNAuEQlCZSAPcvNdGpDrrcQ0ZJczyzlg4vNQo5GdBXH/L2J6I48kb55XBCBq6C96QM8gkONba2 s1ER5n1d/3LZiyYrOEQ24rP2N7+hGEEXO7OVO3h2cjSvhhT/hIaHcrxdfl03nU1zVqOYgjkfO2e OCMLy+3+TvYhbHRQexzYup/KeHa9ySbLY5jVgs7O7/17qeZxrZolxsYRw6zswkP1L4ahGcVPrY8 tOo3vR1QFB/fQwyHtWeO6/fyoAOOp0V4cwpcmCyEag8TWkUraqHV38QBa+E8VQGowDe1RqtM71R j+6xn2qDm8ZCTuqdvcPh83kC1CoJShvhis9OgOEdyhUkXNyBvL5jhNhjaiUpp2lAe6joJ226jiH LPTLfEux7DxSEHT/Bt/oSiNoREw= X-Received: by 2002:a05:6820:440d:b0:716:e855:4ffc with SMTP id 006d021491bc7-718a615adc9mr83582eaf.42.1794253688442; Mon, 09 Nov 2026 11:48:08 -0800 (PST) Return-Path: Received: from localhost.localdomain ([2601:283:4b01:ba50::3232]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-718aa132e65sm70363eaf.14.2026.11.09.11.48.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:48:08 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v9 8/9] ovmf: Allow empty SPDX deploy artifacts Date: Mon, 9 Nov 2026 12:45:44 -0700 Message-ID: <20261109194759.550935-9-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109194759.550935-1-JPEWhacker@gmail.com> References: <20261104153535.3184146-1-JPEWhacker@gmail.com> <20261109194759.550935-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 lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 19:48:18 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249873 In native builds, ovfm do_deploy doesn't produce any artifacts. Set the SPDX_DEPLOY_ALLOW_EMPTY flag to prevent SPDX from erroring when this occurs. Signed-off-by: Joshua Watt --- meta/recipes-core/ovmf/ovmf_git.bb | 1 + 1 file changed, 1 insertion(+) diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb index bf69108f0a..7cc844dfa6 100644 --- a/meta/recipes-core/ovmf/ovmf_git.bb +++ b/meta/recipes-core/ovmf/ovmf_git.bb @@ -249,5 +249,6 @@ do_deploy:class-target() { fi } addtask do_deploy after do_compile before do_build +SPDX_DEPLOY_ALLOW_EMPTY:task-deploy = "1" BBCLASSEXTEND = "native" From patchwork Mon Nov 9 19:45:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joshua Watt X-Patchwork-Id: 103534 Received: from mail-oo1-f41.google.com (mail-oo1-f41.google.com [209.85.161.41]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.3761.1794253690075745992 for ; Mon, 09 Nov 2026 11:48:10 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20260707 header.b=fWkvgYHg; spf=pass (domain: gmail.com, ip: 209.85.161.41, mailfrom: jpewhacker@gmail.com) Received: by mail-oo1-f41.google.com with SMTP id 006d021491bc7-716ea2598eeso727638eaf.0 for ; Mon, 09 Nov 2026 11:48:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794253689; x=1794858489; 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:content-type; bh=eQGYr8GCQvUsr05n7h4ns23NXlVBlfSkuZZYFiRn/H0=; b=fWkvgYHgOGa5umfjYVV78QPIdOpH2lFaUELq2tP3rn4pjtLFof47WICnw5iGcrIeFX M4kUNGrNgsgQIlNFGFy62tuJgeiygL9jpp0YvSZs/G6kkzsq6MJearMz9YmZSUr6S2KY TH8iME/+NmDyAt3mwlXdBvidaMxAGKEzHIggRswvF+ZYacGAMsCb5mPpyWkFmoj9IikV MAWmzDlt3ivJeUrg8dMHIP/Kg8MJCEd5DKJNETuWjhoI8uXww0CV1EbEFL4nNzhP6gWv jLXl6Jmr87dPJXQLSI/Lj4gbnZ4eGHlMgd8WC6LH5s9iwZJLOm6Ues4eGzA5+rVfMooW mkFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794253689; x=1794858489; 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:content-type; bh=eQGYr8GCQvUsr05n7h4ns23NXlVBlfSkuZZYFiRn/H0=; b=V51dcCBpxUGyFhS63LOWdLoeMjBYmStPIBtmnDSUgEIE/D737UnkIFbnJQCp4db3lc g90AsgZQnGVC+tWBFLQtGJWKAW+R7yz82X9FcOPokM+wCJ40bfylk5mo8ws6pd5I32A1 BgOW8O7p3lfnbiOJSvKnm2M0c7BuqMEAIJdRozy2cyBDW1L+ys73el7QiytvYSdTvcVR bLalStNew3F8StshiYSpJCKg+G0VoMKC86dPQz3MV7Z9kg35zADjJgeryYwkPwwMJQfJ rKPT9dYSEKTv36F0++syvot6FTHdOCwCFmmKVup56lVcHamDqwPtS+Jh0s+OEkDTkSgv Liow== X-Gm-Message-State: APuU4Z9sYInylO4WzQNoa7Ri3SRBKPjYcD668OqMEK8ejSsaKPqL2Vi7 WkCvKwEDFACRUEC2rQVDJssZIHJ4k4DDjKICgOW8MPREc/IqQVyIz3qCRs4NFw== X-Gm-Gg: AYBFou0zGocN3ddCTzxsZkhU21B2+/rohy8NWapMptWs5evb5CkGNDmgLMrrt0+Ltsf hePV64L9B8rSMB2QR37eHhfMPQ6jupDy8o6X0U/AagM6kVDnvvehcuWNEhDZl9712FAGGX9YoMd JoK/1GNycb4vM0aonWVuVcdPHkRIZJQ4sp3mIls9n8QH65RfpPdnfyeJSM/xV1E6wQ7LVjzIbka fHkp9ZL/SShjnjmod18N+1NjgfTVEttAUcxl7aToTpWiELlwzLFUVvJOOHfKOrA1UMHxvmFWjVC cIOAew0lkdSgZtpCWKKGBD8lmqkBzp+A/YjyKFsMRslmtlsneEW+l518OV8YlATsx1IyONQx/vm ASP3sWle3bcuZT21VRc6BQLd5YOdDBD70jBBbG2p4aEvQUg9gkQ2jd/T+kgtbYcRV1WwZaxUSLN knFDQJEOmGVRRQMKPH4kuJsAIUjCuTbYGh9E88okjO0XyikT+MkFIBXgwBvHWLM4UlHY00mvVEk TVIdyw6jLP67R8y8Zba4Ap79IE61xwrJA0GmRWJrTp0AweFLCR04faXQWMeoCZVSo8z4GjDQu7C GoqhI2hf8q1v1q3ik2koxsbN2YM= X-Received: by 2002:a05:6820:806:b0:6f8:2346:cd8e with SMTP id 006d021491bc7-718a78edb80mr85402eaf.80.1794253689268; Mon, 09 Nov 2026 11:48:09 -0800 (PST) Return-Path: Received: from localhost.localdomain ([2601:283:4b01:ba50::3232]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-718aa132e65sm70363eaf.14.2026.11.09.11.48.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:48:08 -0800 (PST) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v9 9/9] linux-dummy: Allow empty SPDX deploy artifacts Date: Mon, 9 Nov 2026 12:45:45 -0700 Message-ID: <20261109194759.550935-10-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109194759.550935-1-JPEWhacker@gmail.com> References: <20261104153535.3184146-1-JPEWhacker@gmail.com> <20261109194759.550935-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 lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 19:48:18 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249874 The recipe doesn't deploy anything so set SPDX_DEPLOY_ALLOW_EMPTY so that it doesn't generate an error Signed-off-by: Joshua Watt --- meta/recipes-kernel/linux/linux-dummy.bb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta/recipes-kernel/linux/linux-dummy.bb b/meta/recipes-kernel/linux/linux-dummy.bb index d7f39a452d..c45352aab2 100644 --- a/meta/recipes-kernel/linux/linux-dummy.bb +++ b/meta/recipes-kernel/linux/linux-dummy.bb @@ -23,6 +23,8 @@ FILES:kernel-vmlinux = "" ALLOW_EMPTY:kernel-vmlinux = "1" DESCRIPTION:kernel-vmlinux = "Kernel vmlinux meta package" +SPDX_DEPLOY_ALLOW_EMPTY:task-deploy = "1" + INHIBIT_DEFAULT_DEPS = "1" COMPATIBLE_HOST = ".*-linux"