From patchwork Thu Jun 18 15:38: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: 90446 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 8CD3CCD98F6 for ; Thu, 18 Jun 2026 16:50:47 +0000 (UTC) Received: from mail-oi1-f173.google.com (mail-oi1-f173.google.com [209.85.167.173]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24329.1781801438593549813 for ; Thu, 18 Jun 2026 09:50:38 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=YzyXaTx1; spf=pass (domain: gmail.com, ip: 209.85.167.173, mailfrom: jpewhacker@gmail.com) Received: by mail-oi1-f173.google.com with SMTP id 5614622812f47-4863cd278d7so707264b6e.1 for ; Thu, 18 Jun 2026 09:50:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781801438; x=1782406238; 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=By2fzdEquICbd2WFM4T1/QHgso7zQg6C7IZVavp1eXw=; b=YzyXaTx10elBbSf+9Ycbi0ch1d1GsjhRg7zMknqW1T1WYGlpRpPn8ojvCdTX/RDKLM JP+2PnlVY0Ho9SyQirb1SAOsjiMiaa4cWvKkKuP0Ze/luBH0MJDzkp1AnEalfQ5PcIMi Y+HFiIZbL+CizcbifGE0WNY+eTwKLeljEl4I/vlqi5hhVU5DANz6XDmL0++DSpOwJ6zr KhBY3iDCm5YaoQ8vbcHJJgcX04pWPDJbXKibCbqH4xuzMcJIVxRqfoLEdJC9EsmWFhDO 7nqce3jesz7xiRRHVgYIoO5/fgUSGh+x0tU6SAIeMIbo69WCfYYggVfJKEB2MBEasIeG O5/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781801438; x=1782406238; 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=By2fzdEquICbd2WFM4T1/QHgso7zQg6C7IZVavp1eXw=; b=RVN5mzYqWAe5B+gpXy3lZJk4rqKEQ++v/uARyqxOZ0Z2iuHtP/If70mCtYg+s/N6Ir njBN4Ya6kO7AKAe8MQz/sIY4wUWbR205y+YsbAouscXriTW7VcYr6UWOLkqpDfFUunC2 pXb1XrvhXlVHKAXfSAATPdbiHEAsDP7uYalCWq1WKu+j4KsHP1NIXcS+ET15hfd3fVuE TbUfFh8QbMLq1QaY1iNRAgwS2KN0ZYnZSR7JKtx/tb86e343AX5GdWJ2mY+2EoiXt168 xPdpveBFAgMU24qrV5S3iR7vVgmmukdHkDO/vz4J+zM3iLgxOFg2tSAMFP7wE5YWsql8 LDoQ== X-Gm-Message-State: AOJu0YyCUglIxfTIJns7k/6m65mqcRcQFLmwd7WgYmi7PT65KJQZHcz0 dkZvFFq77deZ0vZXMozw8fWYBAQduD/bu/utPBkRQTue6hotMdZmARZ3Dbbt8A== X-Gm-Gg: AfdE7clN52UvuPqxt7n9Q02zIpmsh1S2BMiO7IunQedvboeSlWsm70UesX4M04+FFgA o7W+y82fRxz2ukkWzZh/qJoByDOqN2GSlEbrlF3OP97YdNcwjv4jyQD7E22XZppwSFFEU6KJq8F kY44T942S13Tl3NaQZjo7fcQhu1QTX0AOf6ISnBWaJBz89wOlv40JIGkTg7S8H//sT2Ygg93jwc LlbY5wwJSTrvhFiqp6ABB1YVbj9msnEatQ0oSmSdTTRX1yHi7aMnAwOZ40Z+b5jfsMr2WDAPBdt euqgCquThDrcdSigZCd6UnJGAA3SqJEVXXsBOI9sU1wzQN1WELucDFMEqI1RByuFQ3heD8x9bYR kHQN/u64vm0fBrADbQd94KbuR1ug7h5yAozoYEAq2i+l8c5I+5E596NA+WZskNSBHZN7WEdGZVP tAPuzDDVJ94Xogz8D60rYQ X-Received: by 2002:a05:6808:d47:b0:482:4df4:ef5 with SMTP id 5614622812f47-4896aa3340dmr177001b6e.3.1781801437514; Thu, 18 Jun 2026 09:50:37 -0700 (PDT) Received: from localhost.localdomain ([2601:283:4b02:22d0::8b4b]) by smtp.gmail.com with ESMTPSA id 5614622812f47-4875dda5ee5sm8732987b6e.2.2026.06.18.09.50.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 09:50:37 -0700 (PDT) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v2 1/5] spdx: Add ability for deploy tasks to create SPDX Date: Thu, 18 Jun 2026 09:38:41 -0600 Message-ID: <20260618165032.347436-2-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618165032.347436-1-JPEWhacker@gmail.com> References: <20260609222331.1293007-1-JPEWhacker@gmail.com> <20260618165032.347436-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 ; Thu, 18 Jun 2026 16:50:47 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/239091 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 | 176 +++++++++++ meta/classes/spdx-common.bbclass | 1 + meta/lib/oe/sbom30.py | 46 +-- meta/lib/oe/spdx30_tasks.py | 282 +++++++++++++++--- meta/lib/oe/spdx_common.py | 2 +- 8 files changed, 448 insertions(+), 65 deletions(-) diff --git a/meta/classes-recipe/create-spdx-image-3.0.bbclass b/meta/classes-recipe/create-spdx-image-3.0.bbclass index 15a91e90e2..a96cfb25ed 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 7c99fcd1ec..b405f57d11 100644 --- a/meta/classes-recipe/nospdx.bbclass +++ b/meta/classes-recipe/nospdx.bbclass @@ -11,3 +11,4 @@ deltask do_create_package_spdx deltask do_create_rootfs_spdx deltask do_create_image_spdx deltask do_create_image_sbom +deltask do_create_deploy_sbom diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index 56fd01fd53..13d1de2774 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -163,6 +163,49 @@ 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." + IMAGE_CLASSES:append = " create-spdx-image-3.0" SDK_CLASSES += "create-spdx-sdk-3.0" @@ -291,3 +334,136 @@ 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() + d.setVarFlag(task, "postfuncs", " ".join( + [f for f in postfuncs if not before_postfunc(f)] + + [func] + + [f for f in postfuncs if before_postfunc(f)] + )) + 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} ") + + 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 0926266295..16f42f41d6 100644 --- a/meta/lib/oe/sbom30.py +++ b/meta/lib/oe/sbom30.py @@ -1048,6 +1048,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, @@ -1055,6 +1074,7 @@ def write_recipe_jsonld_doc( deploydir, *, create_spdx_id_links=True, + create_task_link=False, ): pkg_arch = d.getVar("SSTATE_PKGARCH") @@ -1062,23 +1082,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() @@ -1094,6 +1098,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 72d17aade6..4a7d442ac7 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -605,6 +605,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") @@ -795,7 +924,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): @@ -809,17 +940,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") @@ -947,10 +1067,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) @@ -1130,7 +1252,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): @@ -1364,26 +1488,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) @@ -1416,14 +1523,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): @@ -1503,10 +1616,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, ) @@ -1527,7 +1643,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): @@ -1705,3 +1823,77 @@ 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: + 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 6b1a409c40..0337d1deb5 100644 --- a/meta/lib/oe/spdx_common.py +++ b/meta/lib/oe/spdx_common.py @@ -113,7 +113,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 Thu Jun 18 15:38: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: 90447 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 B8BEFCD98F2 for ; Thu, 18 Jun 2026 16:50:47 +0000 (UTC) Received: from mail-ot1-f43.google.com (mail-ot1-f43.google.com [209.85.210.43]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24330.1781801439345593785 for ; Thu, 18 Jun 2026 09:50:39 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=GVgZCiaL; spf=pass (domain: gmail.com, ip: 209.85.210.43, mailfrom: jpewhacker@gmail.com) Received: by mail-ot1-f43.google.com with SMTP id 46e09a7af769-7e6b5737bb2so1048524a34.1 for ; Thu, 18 Jun 2026 09:50:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781801438; x=1782406238; 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=WQCKW8afwcAv+YtjmIMjDljbMzvW2SV26QGVFsGbe4M=; b=GVgZCiaL5y6i8SjQ4maDJ2KEep9cjnux3qu9ii2ttAqc5mqCnFaYFENehuetd3t6NB I7YxcQwe/9Fu/0arowCqw9jzwqvWZ+qWtDOJdRU/0qQAlmALVYNPka8ou8P3lFtsUfVi gMuMLRcQ4KfpSArxgbCw9fVTqBALYuFpgLKTE+eHOQK7fhEQD8HnJF2sLxr2urc4+4v1 vPvAkNue2pupGnfLmD9A+yp7NC76z/wM6JowRHRgVdF9+yWZETn1xjNGt5gKOgkRxLsz Hap+wn/kb8UHLKpQmtqmjCX5Ov15pk3IXrOQeAHbJL/VM6a9QDzYwnPEJwKoj7cSUKgr oTXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781801438; x=1782406238; 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=WQCKW8afwcAv+YtjmIMjDljbMzvW2SV26QGVFsGbe4M=; b=bMPcxcpW8/9EjaiKBIoDrKozanrgmhEa3TGbpaNRsGOY9V4k1HFe6jhMXGuigxTBJ7 2cobLhi31wfI7dCvwtt1SHzSnuta2PpKjjCN+CMH33561QV2YP3eySd1FI4WHMpiWFiv 5ZQ708MpyDEuq8auVovIsayo9DB1FKZtHL3cBhDdmvqclf8XTgJU7ulRe7Ui3G4hHfR0 coAoK+Q4FbLbjPIilzIeVtujdOTXBwtIKcyf/EK3dpVrSzZ5RjMe1NeCkbOfC1x7iRx2 0yEkVh2LWvEkbQecOxPzKEzI0ZYyFcoB9Ag9SmYNrZ/Wav7xpy7+JXbc7BSpy+a8FpeH as/Q== X-Gm-Message-State: AOJu0Yzw9wrtWiCHAsvTalNtluTdmjd8kI4dflFepXdB0BsztGrpPdju W6AvFkwmiYHN8ZYhBFKX9YqTwFHAHg8ba051Phqwc49OGySSQ4NTN+xEvwfCcw== X-Gm-Gg: AfdE7cnlhJcBF+qShZI+NX84gJZ/NoB00VSNfEwk7TI7YvWyM2jQiod2gRDOYvXl2w5 /Qj652WL245OlP7yAgik2HZwxgrwH8Vx1LmStfz/jYzRanw921n/8xilKg07FZJI38XO90sl5ey WcDTQ9Hc53WZubRb0jNGpqxEDvmUC21dssJxNYKVmQOMIPAfy5Ks8U2kf+mKEMW/tmfanuNoVWC Eq/uoFFhGWOePLmLA2+KYIEeqV3G8wXX/7IQpFY9O6drzmrEAaBRf+jvsHDDu/1hCWdXMdbhZWr huS+8WBSETtJU7mFMTtJIXmff5R7q2HKrXrVM9EM1k43eXafZcE8v6HpDx9qNAGyN7Oj17wGzi5 QLhXSazym3byKpOIkhafCgnjjeKiy+/oiG/JtxErfjjWPRST9HaPZYbCdtvvnnegh4SEbso4Zfq QKMFgzRggWyw== X-Received: by 2002:a05:6808:c3cc:b0:479:faf5:ef4c with SMTP id 5614622812f47-4896ac58f84mr134651b6e.32.1781801438488; Thu, 18 Jun 2026 09:50:38 -0700 (PDT) Received: from localhost.localdomain ([2601:283:4b02:22d0::8b4b]) by smtp.gmail.com with ESMTPSA id 5614622812f47-4875dda5ee5sm8732987b6e.2.2026.06.18.09.50.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 09:50:37 -0700 (PDT) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v2 2/5] classes-global/sstate: Keep SPDX generating setscene dependencies Date: Thu, 18 Jun 2026 09:38:42 -0600 Message-ID: <20260618165032.347436-3-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618165032.347436-1-JPEWhacker@gmail.com> References: <20260609222331.1293007-1-JPEWhacker@gmail.com> <20260618165032.347436-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 ; Thu, 18 Jun 2026 16:50:47 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/239092 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 50dd0e51c4..833b78b870 100644 --- a/meta/classes-global/sstate.bbclass +++ b/meta/classes-global/sstate.bbclass @@ -1115,11 +1115,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 @@ -1132,6 +1149,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: @@ -1188,12 +1207,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 Thu Jun 18 15:38: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: 90448 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 C507BCD98FC for ; Thu, 18 Jun 2026 16:50:47 +0000 (UTC) Received: from mail-oi1-f182.google.com (mail-oi1-f182.google.com [209.85.167.182]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24016.1781801440283505915 for ; Thu, 18 Jun 2026 09:50:40 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=gfegvryg; spf=pass (domain: gmail.com, ip: 209.85.167.182, mailfrom: jpewhacker@gmail.com) Received: by mail-oi1-f182.google.com with SMTP id 5614622812f47-488b3fd8d0dso502699b6e.1 for ; Thu, 18 Jun 2026 09:50:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781801439; x=1782406239; 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=htmmbviTFKFO6CGnAjLliWc0qZi9TjaXMmIgPhE5RD0=; b=gfegvrygoBjddg6tcZKEFNPmLCmGKk+Zk2cWCGihQ6FZOPzU5gp4ZTt+XYaMeafFQ6 RzKuFec6c6XGkWfLcbRHUOL3vqMuqR+5za76HlCoKEHhd8vylE1rVrcBu4417PgMB4bh QtKDhEmVKEMfaV7gh/HgFJsten3vbnNM3tKyf/WxnNrFdy+sFiWjXqmfkaM5j8upEdzU DEJG7C3w0qUJ+Zasdf6K7w4dwHyRw+iTdKLUrwlEqWkwwcuhA617aCIRp8ttnIZ+kl4I q3cqPPEXCo8aEjuHtxNgQfFQSU1gqaGncp5rOWHodiouUnz4NrWXPcEyMm+/0LBcAYDL e+ZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781801439; x=1782406239; 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=htmmbviTFKFO6CGnAjLliWc0qZi9TjaXMmIgPhE5RD0=; b=G35uibkoHML99wGLmdg7eHKVSgPP5VKk4S1rBIEWny2qxwOsKKcwq5MBnvIGy+kbEz KiP2EKFua3nQFBlMkhvl0RG9qEcaduQQncQgjcU9zrc6Jr5Qfft7MDJZ/WjPuMkWtgJP bbQzp1m9qTDozhUcyBr910Ywfi8McsgER7Xdii7RU5ZFO3InNcOmW8ceiH9PBRJPmwYR 8yGWVF+SOvPbsunqoql7fpzcv8aZGkQ1sMVTxhaepHCxRCGX7i/1q/TlHdxyBNp3JiNT XfJNc11ArJ851xM6nk3sms6qyth+mrVohRw75SJn4IOFH4CVG1sibI0SSZTjeu+xIa7+ vIjw== X-Gm-Message-State: AOJu0Yx5qqxoPP/IZP+yDvObVlehhunCxC49JzjEFZMFy1Ea6wninwzT y/iwZhDMPuP08/gSjphF+P9ltSxFEDzXpIPKYWx/Cukh9Zw2OXIc89maL29wMQ== X-Gm-Gg: AfdE7cmpf67g77utXRp1lIpua7jPQBDr6w9jA/B5Oi7MqGjcOYi4UJKCfQV3Anx6cYl uGaaHuTB2NaaZKzWk32CPKaS3ABl8u1y/GbmLFwVlHwqpaI99kz7g8kWo6yrMEx3O5y+jZOWwFS DWVd2LXo2FUvff5hdHIej4gS/D2A6i/4rbP1yrFINAsxmzJpOglhD+aKCtHChfg024uoaobQSw8 W7p5ZGsUd1ELsTrYFqaT1locN0mRcUcWSuoqfbwnBPDYVzveY0zp9urTXaAAzBEwQ1hvo6HdMvG 78ePDZ+eQUe/xK8jdAgKs9Dn3GcdIqBlPqvQQQWXsKJXmiHOViwvaZWxR3wo6f/LJ5kaHoHPpwy YZnJ7yX6pW2q7nXNC9js/MpPx4T4q09OACN++e10TgxPaC+zRVOVZLOShA8rfgS+OgEi9OUbsO7 gXe4MFTtgupuIox/E50WvD X-Received: by 2002:a05:6808:7003:b0:486:560d:aa8e with SMTP id 5614622812f47-4896ab9cf48mr176809b6e.22.1781801439108; Thu, 18 Jun 2026 09:50:39 -0700 (PDT) Received: from localhost.localdomain ([2601:283:4b02:22d0::8b4b]) by smtp.gmail.com with ESMTPSA id 5614622812f47-4875dda5ee5sm8732987b6e.2.2026.06.18.09.50.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 09:50:38 -0700 (PDT) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v2 3/5] Add SPDX deploy tasks to various recipes Date: Thu, 18 Jun 2026 09:38:43 -0600 Message-ID: <20260618165032.347436-4-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618165032.347436-1-JPEWhacker@gmail.com> References: <20260609222331.1293007-1-JPEWhacker@gmail.com> <20260618165032.347436-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 ; Thu, 18 Jun 2026 16:50:47 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/239093 Adds SPDX deploy tasks to many recipes to record their output when consumed in an SBoM Signed-off-by: Joshua Watt --- meta/classes-recipe/barebox.bbclass | 1 + meta/classes-recipe/devicetree.bbclass | 1 + meta/classes-recipe/kernel-fit-image.bbclass | 1 + meta/classes-recipe/kernel.bbclass | 1 + meta/recipes-bsp/grub/grub-efi_2.14.bb | 1 + meta/recipes-bsp/opensbi/opensbi_1.8.1.bb | 1 + meta/recipes-bsp/u-boot/u-boot.inc | 1 + meta/recipes-core/systemd/systemd-boot_259.5.bb | 2 +- 8 files changed, 8 insertions(+), 1 deletion(-) diff --git a/meta/classes-recipe/barebox.bbclass b/meta/classes-recipe/barebox.bbclass index 2411fb5caa..60437c1ad1 100644 --- a/meta/classes-recipe/barebox.bbclass +++ b/meta/classes-recipe/barebox.bbclass @@ -158,5 +158,6 @@ barebox_do_deploy () { fi } addtask deploy after do_compile +SPDX_DEPLOY_TASKS += "do_deploy" EXPORT_FUNCTIONS do_configure do_compile do_install do_deploy diff --git a/meta/classes-recipe/devicetree.bbclass b/meta/classes-recipe/devicetree.bbclass index ce9d008aac..35c2499bdb 100644 --- a/meta/classes-recipe/devicetree.bbclass +++ b/meta/classes-recipe/devicetree.bbclass @@ -164,6 +164,7 @@ devicetree_do_deploy() { done } addtask deploy before do_build after do_install +SPDX_DEPLOY_TASKS += "do_deploy" EXPORT_FUNCTIONS do_compile do_install do_deploy diff --git a/meta/classes-recipe/kernel-fit-image.bbclass b/meta/classes-recipe/kernel-fit-image.bbclass index ae8f3c6688..5115482eff 100644 --- a/meta/classes-recipe/kernel-fit-image.bbclass +++ b/meta/classes-recipe/kernel-fit-image.bbclass @@ -241,3 +241,4 @@ do_deploy() { fi } addtask deploy after do_compile before do_build +SPDX_DEPLOY_TASKS += "do_deploy" diff --git a/meta/classes-recipe/kernel.bbclass b/meta/classes-recipe/kernel.bbclass index 50cef17f69..8d0cb91688 100644 --- a/meta/classes-recipe/kernel.bbclass +++ b/meta/classes-recipe/kernel.bbclass @@ -842,6 +842,7 @@ kernel_do_deploy() { do_deploy[prefuncs] += "read_subpackage_metadata" addtask deploy after do_install do_populate_sysroot do_packagedata +SPDX_DEPLOY_TASKS += "do_deploy" EXPORT_FUNCTIONS do_deploy diff --git a/meta/recipes-bsp/grub/grub-efi_2.14.bb b/meta/recipes-bsp/grub/grub-efi_2.14.bb index 6354b43989..e535d99710 100644 --- a/meta/recipes-bsp/grub/grub-efi_2.14.bb +++ b/meta/recipes-bsp/grub/grub-efi_2.14.bb @@ -97,6 +97,7 @@ do_deploy() { } addtask deploy after do_install before do_build +SPDX_DEPLOY_TASKS += "do_deploy" FILES:${PN} = "${libdir}/grub/${GRUB_TARGET}-efi \ ${datadir}/grub \ diff --git a/meta/recipes-bsp/opensbi/opensbi_1.8.1.bb b/meta/recipes-bsp/opensbi/opensbi_1.8.1.bb index 0a9652c283..93646a97df 100644 --- a/meta/recipes-bsp/opensbi/opensbi_1.8.1.bb +++ b/meta/recipes-bsp/opensbi/opensbi_1.8.1.bb @@ -45,6 +45,7 @@ do_deploy () { } addtask deploy before do_build after do_install +SPDX_DEPLOY_TASKS += "do_deploy" FILES:${PN} += "/share/opensbi/*/${RISCV_SBI_PLAT}/firmware/fw_jump.*" FILES:${PN} += "/share/opensbi/*/${RISCV_SBI_PLAT}/firmware/fw_payload.*" diff --git a/meta/recipes-bsp/u-boot/u-boot.inc b/meta/recipes-bsp/u-boot/u-boot.inc index a75948dfc3..acc2bf9819 100644 --- a/meta/recipes-bsp/u-boot/u-boot.inc +++ b/meta/recipes-bsp/u-boot/u-boot.inc @@ -471,3 +471,4 @@ uboot_deploy_spl () { } addtask deploy before do_build after do_compile +SPDX_DEPLOY_TASKS += "do_deploy" diff --git a/meta/recipes-core/systemd/systemd-boot_259.5.bb b/meta/recipes-core/systemd/systemd-boot_259.5.bb index c6c443f929..c887835806 100644 --- a/meta/recipes-core/systemd/systemd-boot_259.5.bb +++ b/meta/recipes-core/systemd/systemd-boot_259.5.bb @@ -72,4 +72,4 @@ do_deploy () { } addtask deploy before do_build after do_compile - +SPDX_DEPLOY_TASKS += "do_deploy" From patchwork Thu Jun 18 15:38: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: 90449 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 DDA0FCD98FF for ; Thu, 18 Jun 2026 16:50:47 +0000 (UTC) Received: from mail-oi1-f174.google.com (mail-oi1-f174.google.com [209.85.167.174]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24331.1781801441069950696 for ; Thu, 18 Jun 2026 09:50:41 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=lgLl+o27; spf=pass (domain: gmail.com, ip: 209.85.167.174, mailfrom: jpewhacker@gmail.com) Received: by mail-oi1-f174.google.com with SMTP id 5614622812f47-4864aea1316so694814b6e.2 for ; Thu, 18 Jun 2026 09:50:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781801440; x=1782406240; 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=jx0YobAOck+2Vy7wKwLs9JsZ95vr20hd0zJqDzYngik=; b=lgLl+o27F9p1pTeTYUmxaXB/4mAfaSS8Pqp/Ax1Z+1hJ8P707Y346KSChHgKbldY7i F+SG/oaVwDJXpt7lv+7gHwcnsqQcOWLPS1av4NiBI2JphHnUABenPrg8yCmeiHk+Eyv5 Tq39jKYQbYl4I6WPvetXZoRF3cIsmws6wAZkWX4T2FcpjlGvVzaleREZUskAmbxt95nE E+j3CkrF7WpHGlTIeNTyhF7IfDh4pzjMFQR9+Gy+uVSHeOPqEEOXYWkXYNZYWv49b0eU zNvDnZs6gTY+ok1YyTSteY+4xsdDsqKg75WImwk8+WkALHAvEmJzIwB4iG2d56kDM/3g n5+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781801440; x=1782406240; 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=jx0YobAOck+2Vy7wKwLs9JsZ95vr20hd0zJqDzYngik=; b=IyO7+u/2zg//Xudt8KSoJW2N2hxrIkPwCR3WJhNpxpnQxyFobbH+tPrN7JQ/nhZliz Mgcz8W6PQrcNUp/cnhtQmHsTvodSFuKDLg0dtNCip7swZJhaCujmoD2Bv5qXd/Urx6ET 6+aZpkpDt1yLgD1rrFn+tCBc4DqjHvUSIDSkP/Vjawc/x5tTawqCd1fRDn+wqzo6ldQG aRqujW5MSJgBFB538drLlE0efF/5DrW2xkv51O40X4UdwVXS+R8Cti2L8wUCfg+12o9n EdVw9Lp+q3q9kOK5NinRy1hMA3MqL7f0CDUxJIs5cOoAUKfSwHVgm6AdWd9d3DuV+OB8 5ioA== X-Gm-Message-State: AOJu0YxNtRVuGWckAdNPx5XnGrABwwfRAIRThJBG3cx3URbwiq2u7yj7 xU1p23VHlI3VYmsadZYyzLSAKwaEGgzDOf7xplmw6qwERiE/ux5BgBcZ/OY7dQ== X-Gm-Gg: AfdE7clYyNLkpjhBT3YC5Bm/+brJnGA0jJtMoN9mGMbn791yJ6x19KLtW7HwHBX3nH0 SVPy2OT1qsgmpvA2UOA8Uke9xVT4I8eiH+99JbfFYWGpiG7RgLuiC98Xzb26TPH4iiyYx7Tpdzx u6ZAxj7V0jDkgN6MlDoq/RqYimYf52ky2VCSVHO/hPIQHZYtGoz+B0DNcnEQbdowd4zw8tZN8fX iFIZxQlKJ5PHNxqWvizU7pXNBt3Y2/6tuWMDta5rFjnupJ10liyC/KPt5UcOh6g6mDrs/MBtmDK TAEBXUVMh1G17wtPQmmppZMEoyCpRd9Uyw4YSw0EqRUJ/Ypv91HxCv/ES+8Ph/YhKcjJkbGPU+l lFJD1uC/J7b5AkuXPV0mmSajTIDk0ZXZsBX0mNDaXhu6LIv6gt8R4h5rWzfiJ9lH0NrBaQZl7Ar SHBi8nphG0Jw== X-Received: by 2002:a05:6808:171a:b0:489:5df6:68ef with SMTP id 5614622812f47-4896accf5a5mr109766b6e.40.1781801440083; Thu, 18 Jun 2026 09:50:40 -0700 (PDT) Received: from localhost.localdomain ([2601:283:4b02:22d0::8b4b]) by smtp.gmail.com with ESMTPSA id 5614622812f47-4875dda5ee5sm8732987b6e.2.2026.06.18.09.50.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 09:50:39 -0700 (PDT) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v2 4/5] spdx: Replace do_create_image_spdx with deploy task Date: Thu, 18 Jun 2026 09:38:44 -0600 Message-ID: <20260618165032.347436-5-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618165032.347436-1-JPEWhacker@gmail.com> References: <20260609222331.1293007-1-JPEWhacker@gmail.com> <20260618165032.347436-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 ; Thu, 18 Jun 2026 16:50:47 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/239094 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 | 21 ++++++++---- 5 files changed, 26 insertions(+), 32 deletions(-) diff --git a/meta/classes-recipe/create-spdx-image-3.0.bbclass b/meta/classes-recipe/create-spdx-image-3.0.bbclass index a96cfb25ed..838a82c802 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 = "1" do_create_image_sbom_spdx[sstate-inputdirs] = "${SPDXIMAGEDEPLOYDIR}" diff --git a/meta/classes-recipe/nospdx.bbclass b/meta/classes-recipe/nospdx.bbclass index b405f57d11..9c30c4d2c0 100644 --- a/meta/classes-recipe/nospdx.bbclass +++ b/meta/classes-recipe/nospdx.bbclass @@ -9,6 +9,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 deltask do_create_deploy_sbom diff --git a/meta/classes/create-spdx-3.0.bbclass b/meta/classes/create-spdx-3.0.bbclass index 13d1de2774..919de094f8 100644 --- a/meta/classes/create-spdx-3.0.bbclass +++ b/meta/classes/create-spdx-3.0.bbclass @@ -373,9 +373,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 4a7d442ac7..6a3a626db1 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py @@ -1539,19 +1539,19 @@ def create_rootfs_spdx(d): ) -def create_image_spdx(d): +def create_image_spdx(d, spdx_deploy_dir): import oe.sbom30 + 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) @@ -1644,13 +1644,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") @@ -1672,7 +1677,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 Thu Jun 18 15:38: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: 90445 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 8BB34CD98ED for ; Thu, 18 Jun 2026 16:50:47 +0000 (UTC) Received: from mail-oi1-f182.google.com (mail-oi1-f182.google.com [209.85.167.182]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24334.1781801442128940098 for ; Thu, 18 Jun 2026 09:50:42 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=BifYfSqT; spf=pass (domain: gmail.com, ip: 209.85.167.182, mailfrom: jpewhacker@gmail.com) Received: by mail-oi1-f182.google.com with SMTP id 5614622812f47-4864a8e80bbso614198b6e.0 for ; Thu, 18 Jun 2026 09:50:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781801441; x=1782406241; 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=lxnLKSe+U84H+E798KYZ1vrCSh9Q/KwJtgJMVpjVg1Y=; b=BifYfSqTg6Cu3MWiR1mWFvaKqDtzJhgzs7E33ixNs2gE8xZLbP2ivBERL/ejTAhfIf mtoCgO+g/UBdBuACyaE42gnCEhtZZUjH4geDWayVYFkPUVPtGxETLTKU4xOzqB9AAzVx TBtX/JdbH3mOgN6et77ST/Dst+xii3zRxhsBfciGchZYpY72wnFR38wnhDOV0prZnWjt y0Nk0z1s433DU3DpQ+D6CiJtXqS60NaV0z8Yrv0urv6XJaTujbpRkQS6JbcfrvHhs5uX 1Aq4kjBDSVVwLigIdEIx3gJGYaWuAYV1XpZtA9rih6Xiy67M92zMfOJEXpYF9O8uRxlt +YbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781801441; x=1782406241; 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=lxnLKSe+U84H+E798KYZ1vrCSh9Q/KwJtgJMVpjVg1Y=; b=L5/9dCzTe261txriot48qgAQ+kFHQ0vsZUVr9Q5t4JO92MeUEjJL7iw9IqJ21VoBxO tTwfbbPOkHv/oSvOXr08sWlgZHsf3cqOoq9ms+Hu0s11Ais/FdnvIe5qTXyYeyELL2JY c5wK/Bq6KbTnv9fTD9pcZERTMxjcHb5bgsz7m2PdWmybAmJxzxtIm5fCtrnkG9QbR32Y K27syu3wlCxjd5CYNcUhdKtaLPKqDmTZ44/YZs7rIWTL5njh/2hgh6vd5Jusn/FIwUwp 5hftTgOqBAPACnY1OGJ4Nfr4xnLJ6+dAmISneDNIQN77YYSyz/Pv/NRteTg1S0SaX/ru 7IkQ== X-Gm-Message-State: AOJu0YwBp0q1bCa9/OMVOqyDaMyJSmEKFXrtUCLGSMlwonWV9KeR8iL3 lRPMdt/y4bBRs4/SBNMA6Fg1bsiURoBfs66YjlH9BFDX39rjWBMgOAlgxho9MQ== X-Gm-Gg: AfdE7clJiT0SKWg9yXfvNUpih5u/lDq/5IT6VS+rXJ0VDf6Ut9W0jv/HuyQMd9G4Vbt fquJyXyXQewFrWdKn4X5rqYu+u1FCsYT8zHLXiEWu8mE59LIHIevuf5wurZiAlbaqh0jhqwCMxi QJbDGJEu15yQwiL+a/jyWYOObxrus2Ize4CBFKqDYcd7bMJAK242G2FiCvDAxPbDuIsL8LHPtXA 6kS2PymFDif0ftjBvVN0VYf0jraUVPsp/MUjLUPXFezEfK+Npm4u1nvkVR9sSjWUQTDf4dDK9O/ XVKDempt4H4CjfwR6iVM30Br/a9hSjSbnTd6QMvw6jXyzWtQ3yXTOXf1XL1ZtDRvZl61wm50St9 UAhft8Jd2fwN4KeqsBm4cuftU+xu7Ru4ysbRNmXuB7BeOcQKNY/b3CWzitBOXCV/DlJHfCVwgcX v7XlJDn2aDtQ== X-Received: by 2002:a05:6808:10ce:b0:489:441c:ca95 with SMTP id 5614622812f47-4896ac4d6b8mr132038b6e.34.1781801441017; Thu, 18 Jun 2026 09:50:41 -0700 (PDT) Received: from localhost.localdomain ([2601:283:4b02:22d0::8b4b]) by smtp.gmail.com with ESMTPSA id 5614622812f47-4875dda5ee5sm8732987b6e.2.2026.06.18.09.50.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 09:50:40 -0700 (PDT) From: Joshua Watt X-Google-Original-From: Joshua Watt To: openembedded-core@lists.openembedded.org Cc: Joshua Watt Subject: [OE-core][PATCH v2 5/5] grub-efi: Change to MACHINE_ARCH Date: Thu, 18 Jun 2026 09:38:45 -0600 Message-ID: <20260618165032.347436-6-JPEWhacker@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618165032.347436-1-JPEWhacker@gmail.com> References: <20260609222331.1293007-1-JPEWhacker@gmail.com> <20260618165032.347436-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 ; Thu, 18 Jun 2026 16:50:47 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/239095 Machines can change EFI_PROVIDER which changes the way grub-efi is built, meaning two machine may not build it the same way. As such, the arch should be MACHINE_ARCH. Signed-off-by: Joshua Watt --- meta/recipes-bsp/grub/grub-efi_2.14.bb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta/recipes-bsp/grub/grub-efi_2.14.bb b/meta/recipes-bsp/grub/grub-efi_2.14.bb index e535d99710..8d8671614a 100644 --- a/meta/recipes-bsp/grub/grub-efi_2.14.bb +++ b/meta/recipes-bsp/grub/grub-efi_2.14.bb @@ -41,6 +41,8 @@ python __anonymous () { d.setVar("GRUB_IMAGE_PREFIX", prefix) } +PACKAGE_ARCH = "${MACHINE_ARCH}" + inherit deploy CACHED_CONFIGUREVARS += "ac_cv_path_HELP2MAN="