Skip to content

packaging: enable parameterized multi-variant kernel packages - #62

Open
Bjordis Collaku (bjordiscollaku) wants to merge 8 commits into
qcom/debian/latestfrom
feat/matrix-expansion-packaging
Open

packaging: enable parameterized multi-variant kernel packages#62
Bjordis Collaku (bjordiscollaku) wants to merge 8 commits into
qcom/debian/latestfrom
feat/matrix-expansion-packaging

Conversation

@bjordiscollaku

@bjordiscollaku Bjordis Collaku (bjordiscollaku) commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What This Enables

This PR turns the Debian packaging branch into a parameterized kernel-package builder. A matrix row can select the package identity, configuration fragments, Debian revision, and kernel release inputs for a kernel variant without duplicating packaging logic.

Matrix-to-Package Contract

Matrix or build input Packaging behavior
srcpkg Generates the Debian source package identity, currently linux-qcom-next.
binpkg Generates the image metapackage identity, currently linux-image-qcom-next.
Resolved kernel release Defines versioned image, headers, and debug package names, module paths, boot assets, and DTB locations.
kernel_config Selects a comma-separated set of validated fragments from debian/config-available/.
debian_revision Forms the Debian package version together with the resolved upstream kernel version. Received as one complete, opaque string; this branch has no knowledge of, and does not parse, how the CI side derives it.
LOCALVERSION and KVER_EXTRA Form the build-time kernel release suffix used by uname -r and versioned package names.

For the current Qualcomm Next delivery, the packaging flow produces the following set:

Package role Generated package
Source package linux-qcom-next
Versioned kernel image linux-image-<kernelrelease>
Image metapackage linux-image-qcom-next
Versioned headers linux-headers-<kernelrelease>
Headers metapackage linux-headers-qcom-next
Debug packages Versioned image debug and headers debug-symbol packages

Implementation

  • Add matrix-driven source-package and image-metapackage naming.
  • Generate debian/control, debian/changelog, debian/localversion, and debian/pkgversion from the selected inputs and resolved kernel release.
  • Keep the actual kernel release authoritative for versioned package names, installed module paths, boot files, DTBs, and headers.
  • Move optional target fragments under debian/config-available/, activate only requested fragments, and reject unknown fragment names before the build begins.
  • Keep kernel-side baseline fragments such as qcom.config and prune.config in the normal build path.
  • Align prepare-source.sh and build-kernel.sh so local and CI builds invoke the same preparation interface.
  • Preserve generated version metadata across the prepared-source build boundary required by dpkg-buildpackage.
  • Convert -rcN to ~rcN only in the Debian version. Preserve -rcN in uname -r, package names, and installed paths.
  • Keep KVER_EXTRA and LOCALVERSION consistent between preparation, build execution, and package naming.
  • Fail on unknown preparation options and mismatches between generated image metadata and the resolved kernel release.
  • Enable KBUILD_VERBOSE := 1 for complete distribution-build logs.

Required Check Fixes

Two changes outside this PR's packaging scope were required to satisfy this repository's mandatory checks on the base branch:

  • Add a ## License section to README.md referencing LICENSE.txt, satisfying Repolinter's readme-references-license rule. README.md had no reference to a license anywhere.
  • Change qcom-preflight-checks.yml's trigger from pull_request_target to pull_request, resolving a finding from the required workflow-security scan. That workflow's branches: [main] filter never matches this branch lineage's actual base (qcom/debian/latest), so the change is behavior-neutral for every PR that can currently trigger it.

Validation

Area Result
Debusine package production Generated source, image, metapackage, headers, and debug artifacts.
Package version behavior Validated release-candidate ordering, kernel-release naming, branch/tag handling, and KVER_EXTRA behavior.
Configuration handling Validated configured fragments and intentional failure for an unknown fragment.
Target installation Installed generated Qualcomm ARM64 packages and validated initramfs, boot assets, modules, DTBs, firmware device-tree link, and kernel boot. See Target validation below for the actual commands and output.
Release publication The successful staging Release published the expected binary package set to the qli-staging APT repository for both trixie and forky in the same run, each carrying a distinct, suite-specific Debian revision supplied by the CI side (#63) as one opaque string (0qli+staging1~bpo13+1 for trixie, 0qli+staging1 for forky), confirming this branch threads through any debian_revision value without parsing it.
Version-collision regression check Confirmed clean on a live target, no HTTP 500, no pool-object ambiguity. See Target validation below for the actual commands and output.

Target validation

This is also the regression check for the version-collision defect the CI side (#63) fixed: confirming clean on a live target, no HTTP 500, no pool-object ambiguity. Target: live Debian trixie device. Before upgrade, three kernels are already installed (a prior 20260817 collision-fix validation run added the third):

debian@debian:~$ dpkg -l | grep linux-image-7
ii  linux-image-7.1.0-rc2-g4e0b0df1c84f         7.1.0~rc2-g4e0b0df1c84f-1                arm64        Linux kernel, version 7.1.0-rc2-g4e0b0df1c84f
ii  linux-image-7.2.0-rc3-qcom-next-20260729    7.2.0~rc3+20260729-0qcom1                arm64        Qualcomm ARM64 Linux kernel image 7.2.0-rc3-qcom-next-20260729
ii  linux-image-7.2.0-rc7-qcom-next-20260817    7.2.0~rc7+20260817-0qli+staging1~bpo13+1 arm64        Qualcomm ARM64 Linux kernel image 7.2.0-rc7-qcom-next-20260817

Pulling the trixie package directly from qli-staging:

debian@debian:~$ sudo apt upgrade linux-image-qcom-next
...
Get:2 https://deb.debusine.qualcomm.com/qualcomm/qli-staging trixie/main arm64 linux-image-7.2.0-rc7-qcom-next-20260821 arm64 7.2.0~rc7+20260821-0qli+staging1~bpo13+1 [26.2 MB]
Get:3 https://deb.debusine.qualcomm.com/qualcomm/qli-staging trixie/main arm64 linux-image-qcom-next arm64 7.2.0~rc7+20260821-0qli+staging1~bpo13+1 [1,392 B]
...
Fetched 162 MB in 18s (9,191 kB/s)
...
Unpacking linux-image-7.2.0-rc7-qcom-next-20260821 (7.2.0~rc7+20260821-0qli+staging1~bpo13+1) ...
Unpacking linux-image-qcom-next (7.2.0~rc7+20260821-0qli+staging1~bpo13+1) over (7.2.0~rc7+20260817-0qli+staging1~bpo13+1) ...
...
Setting up linux-image-7.2.0-rc7-qcom-next-20260821 (7.2.0~rc7+20260821-0qli+staging1~bpo13+1) ...
...
update-initramfs: Generating /boot/initrd.img-7.2.0-rc7-qcom-next-20260821
Updating kernel version 7.2.0-rc7-qcom-next-20260821 in systemd-boot...

No Err: lines and no HTTP 500 anywhere in the transfer or install; the two suites' packages no longer collide as ambiguous pool objects in the same repository.

Post-reboot, the new kernel booted cleanly and coexists with all three prior kernels:

debian@debian:~$ dpkg -l | grep linux-image-7
ii  linux-image-7.1.0-rc2-g4e0b0df1c84f         7.1.0~rc2-g4e0b0df1c84f-1                arm64        Linux kernel, version 7.1.0-rc2-g4e0b0df1c84f
ii  linux-image-7.2.0-rc3-qcom-next-20260729    7.2.0~rc3+20260729-0qcom1                arm64        Qualcomm ARM64 Linux kernel image 7.2.0-rc3-qcom-next-20260729
ii  linux-image-7.2.0-rc7-qcom-next-20260817    7.2.0~rc7+20260817-0qli+staging1~bpo13+1 arm64        Qualcomm ARM64 Linux kernel image 7.2.0-rc7-qcom-next-20260817
ii  linux-image-7.2.0-rc7-qcom-next-20260821    7.2.0~rc7+20260821-0qli+staging1~bpo13+1 arm64        Qualcomm ARM64 Linux kernel image 7.2.0-rc7-qcom-next-20260821

debian@debian:~$ uname -r
7.2.0-rc7-qcom-next-20260821

debian@debian:~$ ls /boot/efi/loader/entries/
bc9ca9a5da354d55a221910da4b57135-7.1.0-rc2-g4e0b0df1c84f.conf  bc9ca9a5da354d55a221910da4b57135-7.2.0-rc3-qcom-next-20260729.conf  bc9ca9a5da354d55a221910da4b57135-7.2.0-rc7-qcom-next-20260817.conf  bc9ca9a5da354d55a221910da4b57135-7.2.0-rc7-qcom-next-20260821.conf

debian@debian:~$ dmesg | grep "Linux version"
[    0.000000] Linux version 7.2.0-rc7-qcom-next-20260821 (sbuild@sbuild) (gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44) #1 SMP PREEMPT Fri Aug 21 18:28:01 UTC 2026

All four kernels remain installed side by side with no dpkg conflict, and systemd-boot carries a loader entry for each.

Dependencies

Before Merge

…ig activation

Replace the single hardcoded linux-image-<KVER>-qcom naming scheme with a
fully parameterized model that supports multiple build targets from a single
packaging tree.

Package naming changes:
- Source package name is now driven by SRCPKG make variable (default:
  linux-qcom-next). Previously hardcoded as linux-image-<KVER>-qcom.
- Binary metapackage name is driven by BINPKG (default: linux-image-qcom-next).
  HDRPKG is derived automatically from BINPKG (linux-image- -> linux-headers-).
- Versioned binary packages are linux-image-<KVER> and linux-headers-<KVER>
  (no trailing flavour suffix -- the flavour is embedded in KVER via LOCALVERSION).
- Package version is now a real Debian version (<base>+<date>-<revision>) rather
  than the trivial 1-1. Constructed in the prepare target and written to
  debian/pkgversion for use by override_dh_gencontrol.
- control.in and changelog.in gain @srcpkg@, @binpkg@, @HDRPKG@, @pkgver@
  template variables alongside the existing @kver@ and @distro@.
- control.in now produces 5 binary package stanzas: versioned image, image
  metapackage, versioned headers, headers metapackage, and debug symbols.

LOCALVERSION propagation:
- debian/rules prepare writes the LOCALVERSION suffix to debian/localversion.
  override_dh_auto_build reads it via shell cat, replacing the fragile sed
  back-derivation from the source package name that broke when the source
  package name no longer encodes the kernel version.
- All binary package staging directories (PKG, HDR_PKG, DBG_PKG) and
  maintainer script names are now derived from BASE (cat debian/kernel.release)
  rather than from the source package name read from debian/changelog.

Config fragment activation:
- All 6 packaging config fragments moved from debian/config/ to
  debian/config-available/. debian/config/ is now empty by default.
- prepare-source.sh --kernel-config <comma-list> copies named fragments from
  config-available/ into config/ before the build. debian/rules
  override_dh_auto_configure is unchanged -- it still globs debian/config/*.config.
- Kernel-source fragments (qcom.config, prune.config) remain always-applied
  in override_dh_auto_configure when present in the kernel tree.
- forky added to the list of valid distros in prepare-source.sh.

prepare-source.sh gains --srcpkg, --binpkg, --debian-revision, --kernel-config
flags. All new flags have sensible defaults for local builds.

debian/clean and .gitignore updated to cover all newly generated files:
debian/localversion, debian/pkgversion, and versioned maintainer scripts.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
The prepare target generates debian/localversion and debian/pkgversion
before dpkg-buildpackage starts. Keep those files out of dh_clean and
override_dh_auto_clean so they remain available to the build and
control-generation overrides for the full package build.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
usage() previously ended with exit 0, and the unknown-option catch-all
fell into it. This meant that callers using set -e (including the
docker run step in build-kernel-deb.yml) sailed past a rejected flag
with no error, proceeded with no debian/ directory injected, and
produced a misleading failure much later in the build.

Concretely: merging the CI branch before the packaging branch causes
build-kernel-deb.yml to pass --srcpkg to the old prepare-source.sh.
With exit 0 the prepare step succeeds, the artifact is uploaded with
no debian/, and the failure surfaces inside Debusine's
generate-source-package as a missing debian/changelog rather than at
the argument-parsing stage where it belongs.

Change usage() to exit 1 and make the *) catch-all exit 1 directly
rather than delegating to usage(), so set -e in every caller stops the
build immediately with a clear 'Unknown option' message.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
dpkg version ordering treats '~' as sorting before everything,
including end-of-string, so 7.2.0~rc3 < 7.2.0 (correct: rc before
final). Without the tilde, '-' is an alphanumeric separator and
7.2.0-rc3 > 7.2.0 (wrong: rc after final), which means apt refuses to
upgrade any machine carrying a release-candidate package onto the
corresponding final release.

Confirmed with dpkg --compare-versions:
  7.2.0-rc3+20260722-0qcom1 > 7.2.0+20260901-0qcom1  (broken, current)
  7.2.0~rc3+20260722-0qcom1 < 7.2.0+20260901-0qcom1  (correct, after fix)

This is the standard Debian practice: the official Debian experimental
kernel package linux-image-6.14-rc7-amd64 ships Version: 6.14~rc7-1~exp1
while uname -r reports 6.14.0-rc7-amd64.

The fix introduces EXTRA_DEB, derived from EXTRA by translating a
leading '-rc' to '~rc', and uses it only when building BASE_KVER_CLEAN
for the package version field. EXTRA itself is left unchanged so that
KVER_RESOLVED (which becomes uname -r and the package name) keeps the
kernel's native -rcN form.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
Include KVER_EXTRA in debian/localversion so the suffix passed to the
kernel build matches the package name declared during preparation.

Before staging package files, compare the declared versioned image
package with linux-image-<kernelrelease>. Fail clearly on a mismatch to
avoid silently empty packages caused by inconsistent build suffixes.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
build-kernel.sh was not updated when prepare-source.sh's interface
changed, leaving four divergences:

1. Flag rename: --enable-configs was renamed to --kernel-config in
   prepare-source.sh. build-kernel.sh still forwarded --enable-configs,
   which prepare-source.sh now rejects. Because prepare-source.sh's
   unknown-option path previously exited 0, set -e in the caller did
   not catch it and the build proceeded with no debian/ injected.
   Rename the flag to --kernel-config at the call site (:257) and in
   the parser (:110). Keep --enable-configs as a deprecated alias so
   existing scripts do not break silently.

2. VALID_DISTROS diverged: build-kernel.sh lacked forky and unstable,
   which prepare-source.sh now accepts. A developer running
   build-kernel.sh --distro forky was rejected before prepare-source.sh
   was ever called, making the local entry point unusable for the two
   new suites this branch adds.

3. Default ENABLE_CONFIGS was empty: a plain ./build-kernel.sh
   --latest-tag produced a kernel with zero config fragments, where the
   base branch always applied all six. CI is unaffected (the workflow
   input default hardcodes all six), but the divergence was invisible
   from CI. Default to the same six-fragment set CI uses.

4. Install glob was stale: build-kernel.sh:325 printed
   'sudo dpkg -i .../linux-image-*-qcom_*.deb', which matches zero of
   the produced .debs under the new naming scheme. Confirmed in run
   30053624870: the glob appeared directly above an ls -lh listing five
   non-matching files. Update to linux-image-*_*_arm64.deb.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a quick look at this (just overall diff), it appears to be in the right kind of shape...

Set KBUILD_VERBOSE=1 so distribution builds retain the compiler and
linker command lines needed for post-build diagnosis and build-log QA.
This changes logging only; it does not change the generated packages.

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
Two required checks on this PR were failing on pre-existing conditions
unrelated to the packaging changes in this diff, inherited from
qcom/debian/latest:

- Repolinter's readme-references-license rule failed because README.md
  never mentioned licensing. Add the same "## License" section already used
  on the main-branch README, pointing at LICENSE.txt (BSD 3-Clause).

- The required "Scan workflows for security issues" job (zizmor) flagged
  qcom-preflight-checks.yml's pull_request_target trigger as fundamentally
  insecure. This workflow's branch filter is scoped to `main`, but every
  actual PR against this packaging branch targets qcom/debian/latest, so
  the trigger never fires here in practice — the real "Run QC Preflight
  Checks" jobs seen on PRs come from an org-level required workflow, not
  this file. Switching to pull_request satisfies the linter with no
  behavioral change for same-repository PRs (repo secrets remain available
  since the fork-restriction only applies to pull_request from forks).

Signed-off-by: Bjordis Collaku <bcollaku@qti.qualcomm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants