diff mbox series

[RFC,04/08] kernel-devsrc: add full and tarball PACKAGECONFIG levels

Message ID 20261106173235.4155305-5-bruce.ashfield@gmail.com
State New
Headers show
Series enhance kernel -devsrc output options | expand

Commit Message

Bruce Ashfield Nov. 6, 2026, 5:32 p.m. UTC
From: Bruce Ashfield <bruce.ashfield@gmail.com>

The 'source' PACKAGECONFIG packages what a debugger needs to debug a
kernel built for a specific MACHINE. Other use cases need the entire
tree, either installed in a rootfs or as a package on a feed.

Add two more levels to the same kernel-devsrc tree:

  full:    the whole source tree (without the git metadata), a
           superset of 'source', uncompressed at /usr/src/kernel.
  tarball: the whole tree as /usr/src/kernel-source-<version>.tar.bz2
           instead of uncompressed. It can't be debugged or built
           against, it is a copy to unpack elsewhere.

The scripts in a 'full' tree are not run from it, so unless 'build' is
also enabled, file dependencies are skipped for the package. Otherwise
it pulls in perl, python3, make, etc, and can fail to install when an
interpreter path isn't provided (/bin/awk on usrmerge).

With 'build', the file dependencies are kept, so a few scripts in the
tree that use #!/bin/awk or #!/bin/env (arm64 and x86 awk tools,
selftests) would make kernel-devsrc uninstallable: no package provides
those paths. Point them at ${bindir}, as the 'build' level already does
for the arm64 awk tools. The package QA file-rdeps check doesn't catch
this, since it is skipped for module-base recipes.

With 'build' and the whole tree ('full', or 'tarball' unpacked on the
target), more than 'make scripts prepare' can be built from it (the
kernel itself, modules_install, compressed images and modules, module
signing), so add the tools those run that aren't found by file
dependencies: perl, kmod, cpio, tar, gzip, xz, zstd, lz4 and openssl.
This is a fixed list, not derived from the kernel's configuration.
pahole (for BTF) isn't in oe-core, so it isn't included.

'tarball' adds bzip2 on its own: unpacking the tarball is the only
use of it, and tar runs bzip2 to do that.

Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
---
 meta/recipes-kernel/linux/kernel-devsrc.bb | 70 ++++++++++++++++++++--
 1 file changed, 66 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/meta/recipes-kernel/linux/kernel-devsrc.bb b/meta/recipes-kernel/linux/kernel-devsrc.bb
index 3b83fd145c..46337bd79b 100644
--- a/meta/recipes-kernel/linux/kernel-devsrc.bb
+++ b/meta/recipes-kernel/linux/kernel-devsrc.bb
@@ -35,9 +35,20 @@  PACKAGE_ARCH = "${MACHINE_ARCH}"
 #   source: the source needed to debug a kernel built for a specific
 #           MACHINE, see KERNELDEV_SOURCE_SPINE. No runtime dependencies,
 #           so it can go in a debug rootfs without the build tools.
+#   full:   the whole source tree (a superset of 'source').
+#   tarball: the whole source tree as /usr/src/kernel-source-<version>.tar.bz2,
+#           in place of the uncompressed tree from 'full'. Not usable by
+#           debuggers or for building, it is a copy to unpack elsewhere.
 PACKAGECONFIG ?= "build"
 PACKAGECONFIG[build] = ",,,${KERNELDEV_BUILD_RDEPENDS}"
 PACKAGECONFIG[source] = ",,"
+PACKAGECONFIG[full] = ",,"
+PACKAGECONFIG[tarball] = ",,,bzip2"
+
+# The scripts in a 'full' tree are not run from it, so unless 'build' needs
+# them, don't generate runtime dependencies from their interpreters (perl,
+# python3, make, ...).
+SKIP_FILEDEPS:${PN} = "${@'1' if bb.utils.contains('PACKAGECONFIG', 'full', True, False, d) and not bb.utils.contains_any('PACKAGECONFIG', 'build tarball', True, False, d) else '0'}"
 
 # The curated part of the 'source' level, copied in full along with
 # arch/${ARCH}. The rest (drivers, sound, samples, ...) is not curated: the
@@ -469,6 +480,45 @@  kernel_devsrc_install_source() {
     )
 }
 
+# The files of the whole source tree, NUL separated, for 'full' and
+# 'tarball'. Run from ${S}. The git metadata and kernel-meta are left out.
+kernel_devsrc_tree_files() {
+    find . -type d -name '.git*' -prune -o -type d -name '.kernel-meta' -prune -o -type f -print0
+}
+
+# The 'full' level: the whole source tree, without the git metadata.
+kernel_devsrc_install_full() {
+    kerneldir=${D}${KERNEL_BUILD_ROOT}${KERNEL_VERSION}
+
+    # With 'build' also enabled, this runs after it and copies over the
+    # source files it installed (cpio -u). Most are identical, but the
+    # 'build' level's customizations are lost: scripts/package/debian/rules
+    # comes back, and the arm64 awk and python shebang fixups are undone (the
+    # awk ones are redone below). Generated files from ${B} aren't in ${S}, so
+    # they are kept. Skipping the files 'build' installed isn't worth the
+    # complexity: 'full' is meant to be the whole tree.
+    (
+        cd ${S}
+        kernel_devsrc_tree_files | cpio --quiet --null -pdlu $kerneldir/build
+    )
+
+    # The whole tree brings in scripts the 'build' level doesn't copy, and
+    # some use #!/bin/awk or #!/bin/env, which no package provides. Point them
+    # at ${bindir}, keeping their arguments (awk -f). sed -i writes a new file,
+    # so the hardlinks into ${S} are not modified.
+    grep -rlZE '^#! */bin/(awk|env)( |$)' $kerneldir/build | \
+        xargs -0 -r sed -i -E -e '1s,^#! */bin/(awk|env)( |$),#!${bindir}/\1\2,'
+}
+
+# The 'tarball' level: the whole source tree, compressed.
+kernel_devsrc_install_tarball() {
+    (
+        cd ${S}
+        kernel_devsrc_tree_files | \
+            tar --null --no-recursion -cjf ${D}/usr/src/kernel-source-${KERNEL_VERSION}.tar.bz2 --files-from -
+    )
+}
+
 do_install() {
     kerneldir=${D}${KERNEL_BUILD_ROOT}${KERNEL_VERSION}
     install -d $kerneldir
@@ -496,18 +546,25 @@  do_install() {
         kernel_devsrc_install_build
     fi
 
-    # The 'source' level goes in the same tree, at /usr/src/kernel, which is
-    # where the kernel's debug info points.
-    if [ -n "${@bb.utils.contains('PACKAGECONFIG', 'source', '1', '', d)}" ]; then
+    # The source levels go in the same tree, at /usr/src/kernel, which is
+    # where the kernel's debug info points. 'full' is a superset of 'source',
+    # and 'tarball' replaces the uncompressed 'full' tree.
+    if [ -n "${@bb.utils.contains('PACKAGECONFIG', 'full', '1', '', d)}" ] &&
+       [ -z "${@bb.utils.contains('PACKAGECONFIG', 'tarball', '1', '', d)}" ]; then
+        kernel_devsrc_install_full
+    elif [ -n "${@bb.utils.contains('PACKAGECONFIG', 'source', '1', '', d)}" ]; then
         kernel_devsrc_install_source
     fi
+    if [ -n "${@bb.utils.contains('PACKAGECONFIG', 'tarball', '1', '', d)}" ]; then
+        kernel_devsrc_install_tarball
+    fi
     chown -R root:root ${D}
 }
 
 # Ensure we don't race against "make scripts" during cpio
 do_install[lockfiles] = "${TMPDIR}/kernel-scripts.lock"
 
-FILES:${PN} = "${KERNEL_BUILD_ROOT} ${KERNEL_SRC_PATH}"
+FILES:${PN} = "${KERNEL_BUILD_ROOT} ${KERNEL_SRC_PATH} /usr/src/kernel-source-*.tar.bz2"
 
 # Added to RDEPENDS:${PN} by the 'build' PACKAGECONFIG
 KERNELDEV_BUILD_RDEPENDS = "bc python3-core flex bison ${TCLIBC}-utils gawk"
@@ -521,3 +578,8 @@  KERNELDEV_BUILD_RDEPENDS += "${@bb.utils.contains('ARCH', 'powerpc', 'elfutils-d
 KERNELDEV_BUILD_RDEPENDS += "gcc-plugins libmpc-dev"
 # 5.13+ needs grep for powerpc
 KERNELDEV_BUILD_RDEPENDS:append:powerpc = " grep"
+# With the whole tree as well ('full', or 'tarball' unpacked on target), more
+# than 'make scripts prepare' can be built: a whole kernel, modules_install,
+# compressed images and modules, module signing.
+KERNELDEV_FULL_BUILD_RDEPENDS = "perl kmod cpio tar gzip xz zstd lz4 openssl"
+KERNELDEV_BUILD_RDEPENDS += "${@bb.utils.contains_any('PACKAGECONFIG', 'full tarball', '${KERNELDEV_FULL_BUILD_RDEPENDS}', '', d)}"