Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pkg-linux-qcom/
│ │ ├── qcom-imsdk.config ← DMABUF heaps for Qualcomm IMSDK/GStreamer
│ │ ├── qemu-boot.config ← virtio drivers for QEMU testing
│ │ └── usb-can.config ← USB CAN adapters
│ ├── dkms-modules ← Manifest of out-of-tree modules to bundle at build time
│ └── scripts/
│ └── bundle-dkms-modules.sh ← DKMS build-and-bundle tool (called by rules; standalone-capable)
├── .gitignore
└── README.md
```
Expand All @@ -70,6 +73,8 @@ pkg-linux-qcom/
| `debian/linux-image.postrm` | ✅ Committed | Post-remove maintainer script |
| `debian/config/*.config` | ✅ Committed | Always-applied config fragments |
| `debian/config-available/*.config` | ✅ Committed | Optional fragment library |
| `debian/dkms-modules` | ✅ Committed | Manifest of out-of-tree DKMS modules to bundle |
| `debian/scripts/bundle-dkms-modules.sh` | ✅ Committed | DKMS build-and-bundle tool |
| `debian/control` | 🔄 Generated | Produced by `make -f debian/rules prepare KVER=...` |
| `debian/changelog` | 🔄 Generated | Produced by `make -f debian/rules prepare KVER=...` |
| `debian/kernel.release` | 🔄 Generated | Produced during `dpkg-buildpackage` |
Expand Down Expand Up @@ -307,6 +312,65 @@ Virtual packages provided: `linux-image-dbg`

---

## DKMS module bundling

Out-of-tree kernel modules listed in `debian/dkms-modules` are built at
`dpkg-buildpackage` time and bundled directly into `linux-image-<KVER>-qcom`.
The target device receives the pre-built `.ko` without needing a compiler,
kernel headers, or DKMS tooling installed.

### How it works

`debian/rules` calls `debian/scripts/bundle-dkms-modules.sh` at the end of
`override_dh_auto_install`, after the kernel image, modules, headers, and debug
packages have been staged. The script:

1. Reads the module list from `debian/dkms-modules` (one name per line, without
the `-dkms` suffix; comments and blank lines ignored).
2. Resolves each module's source tree via `dpkg -L <name>-dkms` (authoritative;
no `/usr/src/` globbing).
3. Reads `PACKAGE_NAME` / `PACKAGE_VERSION` from the package's `dkms.conf`.
4. Builds with `dkms build` against the staged kernel headers, using a private
`--dkmstree` (`mktemp`) to avoid writing to the root-owned `/var/lib/dkms/`.
5. Judges the outcome by `.ko` artifact presence, not `dkms` exit code.
On failure: prints `make.log` tail (compile error) or `BUILD_EXCLUSIVE` gate
analysis (skip), then hard-fails — a manifest entry is a presence contract.
6. For each produced `.ko`: collision-checks against already-bundled and in-tree
modules; installs to `lib/modules/<KVER>/extra/`; extracts debug symbols via
`objcopy --only-keep-debug` into the `-dbg` package; strips with
`strip --strip-debug` (required for kernel modules — a full strip drops the
symtab and relocations needed by the module loader).

### `debian/dkms-modules` manifest

```
# One module name per line (without the -dkms suffix).
# A corresponding Build-Depends entry must exist in debian/control.in.
kgsl
```

To add a module: append its name and add `<name>-dkms (>= <version>)` to
`Build-Depends` in `debian/control.in`. To disable temporarily: comment out
the line. `debian/rules` and `bundle-dkms-modules.sh` are untouched in either case.

### Standalone developer use

`bundle-dkms-modules.sh` can be invoked directly after a manual build has staged
the kernel trees, without re-running the full `dpkg-buildpackage`:

```bash
debian/scripts/bundle-dkms-modules.sh \
--kver 6.12.0-qcom-next-20260210 \
--headers-dir /path/to/kernel-source/debian/linux-headers-6.12.0-qcom-next-20260210-qcom/usr/src/linux-headers-6.12.0-qcom-next-20260210 \
--image-pkg-dir /path/to/kernel-source/debian/linux-image-6.12.0-qcom-next-20260210-qcom \
--dbg-pkg-dir /path/to/kernel-source/debian/linux-image-6.12.0-qcom-next-20260210-qcom-dbg
```

Run `debian/scripts/bundle-dkms-modules.sh --help` for full usage, prerequisites,
and all available options (`--arch`, `--objcopy`, `--modules-manifest`).

---

## The `build` and `source` symlinks

`/lib/modules/<KVER>/build` and `/lib/modules/<KVER>/source` are symlinks
Expand Down Expand Up @@ -481,3 +545,9 @@ Merges `arch/arm64/configs/debug.config` from the kernel source if present.
| Ubuntu 26.04 | `resolute` | |
| Debian 13 | `trixie` | Default |
| Debian unstable | `sid` | |

---

## License

pkg-linux-qcom is licensed under the BSD-3-Clause License. See [LICENSE.txt](LICENSE.txt) for the full license text.
3 changes: 2 additions & 1 deletion debian/control.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ Maintainer: Bjordis Collaku <bcollaku@qti.qualcomm.com>
Standards-Version: 4.6.2
Build-Depends: debhelper-compat (= 13),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We also need to add something to make sure we don't allow users to manually install camx-dkms, iris-vpu-dkms, kgsl-dkms to the kernel binary package?

Provides: camx-dkms, iris-vpu-dkms, kgsl-dkms
Conflicts: camx-dkms, iris-vpu-dkms, kgsl-dkms
Replaces: camx-dkms, iris-vpu-dkms, kgsl-dkms

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed we shouldn't let both land, I'll add Conflicts. I'd leave Provides out though, since the kernel package ships the built module and not the dkms source, so it would satisfy a Depends: kgsl-dkms from something that actually wants the source.

bc, bison, flex, libssl-dev, libelf-dev, dwarves,
python3, kmod, cpio, rsync, pkg-config, gcc, make
python3, kmod, cpio, rsync, pkg-config, gcc, make,
kgsl-dkms (>= 1.0.2), dkms

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'd rather this was split into two independent commits:

  • one adding dkms / gcc and other deps
  • one adding kgsl-dkms

Also, we now have kgsl 1.0.4 in qli (1.0.10 in qli-staging), can we remove the pinned version for kgsl-dkms?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call, I'll split it into deps vs the kgsl-dkms build-dep. And yeah, (>= 1.0.2) was just a floor, with 1.0.4/1.0.10 out now I'll drop the pin.

Homepage: https://kernel.org
Rules-Requires-Root: binary-targets

Expand Down
12 changes: 12 additions & 0 deletions debian/dkms-modules
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# DKMS modules to build and bundle into linux-image-<KVER>-qcom.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this may be better in a README file on how to add additional dkms modules?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The how-to is in the manifest header and the PR description at the moment. I like having it next to the thing you actually edit, but happy to move it to a README if you prefer.

#
# One entry per line: the DKMS package name without the -dkms suffix.
# A corresponding Build-Depends entry must exist in debian/control.in.
#
# To add a module:
# 1. Append the module name here.
# 2. Add <name>-dkms (>= <version>) to Build-Depends in debian/control.in.
#
# To disable a module temporarily: comment out the line with #.
# debian/rules and debian/scripts/bundle-dkms-modules.sh are untouched in either case.
kgsl
22 changes: 21 additions & 1 deletion debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ PARALLEL ?= $(shell nproc)
# Prefer the aarch64 cross-compiler's objcopy; fall back to the host objcopy.
OBJCOPY ?= $(shell which aarch64-linux-gnu-objcopy 2>/dev/null || which objcopy 2>/dev/null || echo objcopy)

# dkms identifies architectures in uname -m vocabulary (aarch64), unlike the
# kbuild ARCH token above (arm64). The distinction matters for dkms.conf
# BUILD_EXCLUSIVE_ARCH gates, which match against this value.
DKMS_ARCH ?= aarch64


# File that caches the kernelrelease (BASE, i.e., uname -r)
KREL_FILE := debian/kernel.release
Expand Down Expand Up @@ -374,7 +379,22 @@ override_dh_auto_install:
$$DBG_PKG/usr/lib/debug/vmlinux-$$BASE; \
else \
echo "Warning: vmlinux not found at $$VMLINUX_PATH — debug package will not contain vmlinux"; \
fi
fi; \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

also need to build camx-dkms and iris-vpu-dkms, would be good to do that at the same time...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

With the generic tool it's a two-line change per module (manifest + Build-Depends). I'd keep this PR to the mechanism + kgsl since that's the one validated on resolute and trixie, then turn camx and iris-vpu on in follow-ups so any per-module issues don't hold up the mechanism.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

squash this commit :-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same here, this one gets folded into the extraction commit too.

\
# ── DKMS module integration ──────────────────────────────────────────────────

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

can we make this generic for any DKMS build ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah this is the first inline cut. 1a833dd pulls it all out into bundle-dkms-modules.sh, which is fully generic (no module names in it), driven by the manifest + Build-Depends. Agreed the intermediate commits are noisy to read though, I'll squash them into the extraction so it reads as the generic tool directly.

# Delegated to debian/scripts/bundle-dkms-modules.sh.
# The script reads debian/dkms-modules, builds each listed module against the
# staging headers produced earlier in this same dpkg-buildpackage run, and
# bundles the resulting .ko files into the linux-image and -dbg staging trees.
# It can also be invoked directly by a developer — see the script's --help.
$(CURDIR)/debian/scripts/bundle-dkms-modules.sh \
--kver "$$BASE" \
--headers-dir "$(CURDIR)/debian/linux-headers-$$BASE-qcom/usr/src/linux-headers-$$BASE" \
--image-pkg-dir "$(CURDIR)/$$PKG" \
--dbg-pkg-dir "$(CURDIR)/$$DBG_PKG" \
--arch "$(DKMS_ARCH)" \
--objcopy "$(OBJCOPY)" \
--modules-manifest "$(CURDIR)/debian/dkms-modules"

# Skip automatic dh_installmodules - we'll call it manually in override_dh_installdeb
override_dh_installmodules:
Expand Down
Loading
Loading