Ticket xavierk/voculinux#28, needs #27. One documented command (packaging/void/smoke.sh, just void-smoke) lints, builds, installs and smoke-tests every template under packaging/void/srcpkgs in dependency order in the pinned Void container via podman, failing fast naming the package with the harness echoing each stage. The gate caught three latent breaks in the per-package harness and the app template, fixed here: - container-main.sh scoped the libggml scan to python3-pywhispercpp and gave the leaf packages their own import smokes (pynput by presence: no display in the container), failing loudly for packages without a smoke recipe; - voculinux template drops the deprecated wrksrc override (xbps-src renames the single-top-dir archive itself; xlint rejects wrksrc) and builds the PEP 517 wheel (the sdist ships no setup.py); - post_install promotes the pre-rename sdist names (desktop entry content, icons, /usr/bin launchers) to the renamed identity, and the payload smoke rejects pre-rename leftovers in OS-visible paths. Offline policy tests (tests/test_void_smoke_gate.py) pin the gate to the template set, the app-last order, podman-only pinned inputs and per-package failure identity; the #27 policy tests and the rename sweep cover the harness and template contracts.
6.2 KiB
Void packaging
Void Linux (glibc, x86_64) templates in void-packages layout, built with the standard Void source tooling. Submission to upstream void-packages is out of scope for spec #16; these templates serve the signed personal xbps repository first.
Layout
packaging/void/
├── README.md this file
├── build.sh podman harness: lint + xbps-src build + import smoke
├── smoke.sh ticket #28 gate: every template, one command
├── tool_checksums.txt pinned base image and void-packages commit
└── srcpkgs/
├── python3-pywhispercpp/ ticket #26: whisper.cpp Python binding
├── ... ticket #25: small Python dependencies
└── voculinux ticket #27: the application
srcpkgs/ mirrors void-packages so the tree overlays cleanly:
cp -r packaging/void/srcpkgs/. /path/to/void-packages/srcpkgs/
(build.sh does this inside the container.)
Templates
| Template | Ticket | Notes |
|---|---|---|
python3-pywhispercpp |
#26 | Vulkan backend on by default; see below |
voculinux |
#27 | The app, from the canonical release sdist; see below |
python3-pywhispercpp
Version 1.5.0, pinned to the same version install.sh
(PYWHISPERCPP_VERSION) and uv.lock pin — never newest upstream.
The sdist checksum in the template must equal the sha256 uv.lock records
for the sdist; tests/test_void_pywhispercpp_template.py fails otherwise.
- Vulkan is a build option, on by default. Rebuild CPU-only with
build.sh python3-pywhispercpp -- -o ~vulkan pkg. There is no CUDA build: Void ships no CUDA toolkit package. Rebuilding locally with a hand-installed toolkit (GGML_CUDA=1) is a documented, unsupported escape hatch. - Portable CPU flags: every ggml SIMD option is pinned off
(
-DGGML_NATIVE=OFF -DGGML_SSE42=OFF ...), the plain x86-64 baseline already used by the Flatpak (#938,#957). The offline test asserts each pin in the template (the build configuration), and the harness scans the shippedlibggml-cpu(.GCC.command.line,.comment) for recorded-march=native/-mcpu=native/-mtune=nativeflags and fails on a match. The recorded-flags scan is a tripwire, not a proof: the proof is the pinned configuration plussetup.py's documentedCMAKE_ARGSpassthrough. - Shared libraries:
BUILD_SHARED_LIBS=ONwith an$ORIGINrpath (asinstall.shdoes), so the extension resolves the whisper.cpp libraries installed beside it with noLD_LIBRARY_PATH. - Offline build: the sdist vendors whisper.cpp, pybind11, and the
ggml sources; the build fetches nothing beyond the declared distfiles.
PYWHISPERCPP_VERSIONis injected because the sdist carries noversion.txt(its version otherwise comes from git metadata). - Runtime deps (
python3-numpy,python3-requests,python3-tqdm,python3-platformdirs) are the sdist's owninstall_requiresand were verified to exist in current void-packages; the container build re-verifies via dependency resolution.
voculinux
Version 0.18.5, matching src/vocalinux/version.py — never newest
upstream. The template builds the canonical release source distribution
(the releases/download sdist, the same bytes published to PyPI) with a
pinned checksum; tests/test_void_app_template.py fails otherwise.
The 0.18.5 asset still carries the pre-rename archive root; xbps-src
moves the single top-level directory to pkgname-version itself, so no
wrksrc override is needed (wrksrc is deprecated and xlint rejects
it). The first release cut after the rename points distfiles at the
renamed asset.
- Runtime deps are Void's own interpreter, GTK and desktop bindings
(
python3,python3-gobject,python3-cairo,gtk+3,libayatana-appindicator,ibus,gobject-introspection), the packaged Python libraries, and the three templates from tickets #25 and #26 (python3-pynput,python3-PyAudio,python3-pywhispercpp). Every name was verified to exist in current void-packages; the container build re-verifies via dependency resolution. - No payload beyond the app: no speech models (they download on first run), no vendored wheels, no pip at build or install time. The container smoke fails the build if the payload carries model weights or wheels.
- Renamed paths: the
voculinux.desktopentry, the hicolor icons, and ausr/share/voculinux/packagedmarker the app reads to present package-manager updates. The 0.18.5 sdist predates the rename, sopost_installpromotes the old file names at install time; the payload smoke rejects any pre-rename leftovers in the OS-visible paths. - INSTALL.msg covers what xbps cannot express: the
inputgroup for the evdev hotkey backend, first-run model downloads, optional engines as manual additions (vosk, OpenAI whisper, Parakeet, faster-whisper, onnxruntime), the absentydotoolrung, and updating through xbps. - Update checker: packaged installs keep background checks as a
signal, but every update affordance (tray entry, notification, About
page) presents the package-manager path
(
src/vocalinux/utils/packaging.py).
Building
packaging/void/build.sh python3-pywhispercpp
packaging/void/build.sh python3-pywhispercpp -- -o ~vulkan pkg
packaging/void/build.sh voculinux
Podman only, never Docker. The base image digest and the void-packages
commit come from tool_checksums.txt; bump them there, never in the
script.
Smoke gate
One command runs the whole gate from a clean checkout — no host Void
install — linting, building, installing and smoke-testing every
template under srcpkgs in dependency order (the app last):
packaging/void/smoke.sh
# or: just void-smoke
Each package delegates to build.sh, so the pinned container and the
per-package stages (xlint, xbps-src, install, payload/version/import
smoke) stay implemented once. The gate fails fast: a broken package
prints FAIL: <pkgname> naming which package broke, above it the
harness echoes which stage broke. tests/test_void_smoke_gate.py
asserts offline that the gate stays wired to every srcpkgs template,
so a renamed or added template cannot silently drop out.