[2/2] fix(rootfs): generate in-tree initrd as part of image install

Message ID 20260714133422.1792603-3-felix.moessbauer@siemens.com
State Priority Review
Headers show
Series Fix issue around missing initrd on partial rebuilds | expand

Commit Message

Felix Moessbauer July 14, 2026, 1:34 p.m. UTC
When working with a in-tree initrd, the generation of the initrd has the
side effect of placing the initrd in /boot as well (in addition to the
deployment to the deploy dir). This part is currently skipped in case
the initrd is taken from the sstate cache, leading to reproducibility
issues of non-wic images (e.g. a rootfs tarball).

This issue remained unnoticed, as all image types that go through wic
anyways replace the /boot part with the artifacts from the deploy dir.

We now run the initrd generator as part of the rootfs_install in case an
in-tree initrd is used. If an out-of-tree initrd is used, the current
logic is kept, as the rootfs from the initrd generation is not used.

Fixes: b0913306 ("Delay creation of initrd until end of rootfs ...")
Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
---
 meta/classes-recipe/image.bbclass     |  2 +-
 meta/classes-recipe/initramfs.bbclass | 38 +++++++++++++++++++++++++++
 meta/classes-recipe/rootfs.bbclass    | 33 ++++-------------------
 3 files changed, 44 insertions(+), 29 deletions(-)

Patch

diff --git a/meta/classes-recipe/image.bbclass b/meta/classes-recipe/image.bbclass
index 4194dda4..03127ded 100644
--- a/meta/classes-recipe/image.bbclass
+++ b/meta/classes-recipe/image.bbclass
@@ -488,7 +488,7 @@  EOSUDO
         -exec touch '{}' -h -d@${SOURCE_DATE_EPOCH} ';'
 }
 do_rootfs_finalize[network] = "${TASK_USE_SUDO}"
-addtask rootfs_finalize before do_rootfs after do_rootfs_postprocess do_generate_initramfs
+addtask rootfs_finalize before do_rootfs after do_rootfs_postprocess
 
 ROOTFS_QA_FIND_ARGS ?= ""
 
diff --git a/meta/classes-recipe/initramfs.bbclass b/meta/classes-recipe/initramfs.bbclass
index e0a5f5ab..bfe530c4 100644
--- a/meta/classes-recipe/initramfs.bbclass
+++ b/meta/classes-recipe/initramfs.bbclass
@@ -44,4 +44,42 @@  python do_validate_rootfs_packages () {
                 bb.error(f"{pkg} is incompatible with the selected generator '{initrd_generator}'")
 }
 addtask do_validate_rootfs_packages before do_rootfs_install
+
+SSTATETASKS += "do_generate_initramfs"
+do_generate_initramfs[cleandirs] += "${DEPLOYDIR}"
+do_generate_initramfs[network] = "${TASK_USE_SUDO}"
+do_generate_initramfs[sstate-inputdirs] = "${DEPLOYDIR}"
+do_generate_initramfs[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}"
+python do_generate_initramfs() {
+    bb.build.exec_func('rootfs_do_mounts', d)
+    bb.build.exec_func('rootfs_do_qemu', d)
+
+    progress_reporter = bb.progress.ProgressHandler(d)
+    d.rootfs_progress = progress_reporter
+
+    try:
+        bb.build.exec_func('rootfs_generate_initramfs', d)
+        bb.build.exec_func('rootfs_purge_initramfs', d)
+    finally:
+        bb.build.exec_func('rootfs_do_umounts', d)
+}
+
+python do_generate_initramfs_setscene () {
+    sstate_setscene(d)
+}
+
+# When generating an external initrd, remove it from the rootfs to ensure
+# identical artifacts when using the sstate cache. The remaining rootfs
+# is not used for booting.
+rootfs_purge_initramfs[weight] = "1"
+rootfs_purge_initramfs() {
+    sudo find ${ROOTFSDIR}/boot -name "initrd.img-*" -delete
+}
+
+# If an external initrd shall be used, run it as a task
+# instead of as part of the rootfs install.
+addtask do_generate_initramfs before do_rootfs_postprocess after do_rootfs_install
+addtask do_generate_initramfs_setscene
+ROOTFS_INSTALL_COMMAND:remove = "rootfs_generate_initramfs"
+
 inherit rootfs
diff --git a/meta/classes-recipe/rootfs.bbclass b/meta/classes-recipe/rootfs.bbclass
index aaacd1e6..f46df2bc 100644
--- a/meta/classes-recipe/rootfs.bbclass
+++ b/meta/classes-recipe/rootfs.bbclass
@@ -424,6 +424,9 @@  rootfs_clear_initrd_symlinks() {
 }
 
 do_rootfs_install[root_cleandirs] = "${ROOTFSDIR}"
+do_rootfs_install[cleandirs] += "${DEPLOYDIR}"
+do_rootfs_install[sstate-inputdirs] = "${DEPLOYDIR}"
+do_rootfs_install[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}"
 do_rootfs_install[vardeps] += "${ROOTFS_CONFIGURE_COMMAND} ${ROOTFS_INSTALL_COMMAND} ${ROOTFS_VARDEPS}"
 do_rootfs_install[vardepsexclude] += "IMAGE_ROOTFS"
 do_rootfs_install[depends] = "bootstrap-${@'target' if d.getVar('ROOTFS_ARCH') == d.getVar('DISTRO_ARCH') else 'host'}:do_build"
@@ -630,28 +633,8 @@  python do_rootfs_postprocess() {
 }
 addtask rootfs_postprocess before do_rootfs after do_unpack
 
-SSTATETASKS += "do_generate_initramfs"
-do_generate_initramfs[network] = "${TASK_USE_SUDO}"
-do_generate_initramfs[cleandirs] += "${DEPLOYDIR}"
-do_generate_initramfs[sstate-inputdirs] = "${DEPLOYDIR}"
-do_generate_initramfs[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}"
-python do_generate_initramfs() {
-    bb.build.exec_func('rootfs_do_mounts', d)
-    bb.build.exec_func('rootfs_do_qemu', d)
-
-    progress_reporter = bb.progress.ProgressHandler(d)
-    d.rootfs_progress = progress_reporter
-
-    try:
-        bb.build.exec_func('rootfs_generate_initramfs', d)
-    finally:
-        bb.build.exec_func('rootfs_do_umounts', d)
-}
-
-python do_generate_initramfs_setscene () {
-    sstate_setscene(d)
-}
-
+ROOTFS_INSTALL_COMMAND += "${@bb.utils.contains('ROOTFS_FEATURES', 'generate-initrd', 'rootfs_generate_initramfs', '', d)}"
+rootfs_generate_initramfs[weight] = "1000"
 rootfs_generate_initramfs[progress] = "custom:rootfs_progress.InitrdProgressHandler"
 rootfs_generate_initramfs() {
     if [ -n "$(sudo find '${ROOTFSDIR}/boot' -type f -name 'vmlinu[xz]*')" ]; then
@@ -671,12 +654,6 @@  rootfs_generate_initramfs() {
     fi
 }
 
-python() {
-    if 'generate-initrd' in d.getVar('ROOTFS_FEATURES', True).split():
-        bb.build.addtask('do_generate_initramfs', 'do_rootfs', 'do_rootfs_postprocess', d)
-        bb.build.addtask('do_generate_initramfs_setscene', None, None, d)
-}
-
 python do_rootfs() {
     """Virtual task"""
     pass