The app template fetched upstream's 0.18.5 archive, carried upstream's homepage and maintainer, and renamed the launchers and desktop entry in post_install. The fork's sdist already names them voculinux, so the template now sources the fork's release asset and installs the names as they are. The checksum is an explicit pending marker until the fork's v0.18.5 release exists, which fails closed in xbps-src and never falls back to the upstream digest. depends now pulls in pipewire (capture), wtype (direct typing on niri), wl-clipboard (clipboard), xdotool (X11 and XWayland) and pulseaudio-utils (pactl), and drops ibus, which cannot inject on niri. Every name is checked against the Void index. INSTALL.msg states the niri first run plainly (no permission prompt; typing goes direct), never points at the portal on niri, and drops the IBus claim. The container smoke queries the fork's distribution name. Tests assert the fork sources, the pending-or-pinned checksum, the runtime helpers, the absence of ibus, and the niri wording.
145 lines
5.6 KiB
Bash
Executable File
145 lines
5.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# Root-side half of the packaging/void container harness. Runs inside the
|
|
# pinned Void container as root: system setup, the void-packages checkout,
|
|
# then the builder half (container-build.sh) as the builder user, then the
|
|
# install plus import smoke as root again.
|
|
#
|
|
# Not executed directly: build.sh mounts this file and runs it. PKGNAME,
|
|
# XBPS_ARGS, EXPECT_VULKAN and VOID_COMMIT arrive via the environment.
|
|
set -eu
|
|
|
|
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
|
xbps-install -Suy xbps >/dev/null
|
|
xbps-install -y git base-devel xtools binutils zstd >/dev/null
|
|
git clone --quiet --depth 1 https://github.com/void-linux/void-packages /void-packages
|
|
git -C /void-packages fetch --quiet --depth 1 origin "$VOID_COMMIT"
|
|
git -C /void-packages checkout --quiet "$VOID_COMMIT"
|
|
cp -r /overlay/. /void-packages/srcpkgs/
|
|
id builder >/dev/null 2>&1 || useradd -m builder
|
|
cp /mnt/container-build.sh /run-build.sh
|
|
chown builder:builder /void-packages /run-build.sh
|
|
chmod +x /run-build.sh
|
|
su -s /bin/sh builder -c /run-build.sh
|
|
|
|
echo "== install $PKGNAME from the local repository"
|
|
PKGFILE=$(ls /void-packages/hostdir/binpkgs/"$PKGNAME"-*.x86_64.xbps /host/binpkgs/"$PKGNAME"-*.x86_64.xbps 2>/dev/null | head -n1)
|
|
[ -n "$PKGFILE" ] || {
|
|
echo "built package not found" >&2
|
|
exit 1
|
|
}
|
|
echo "built: $PKGFILE"
|
|
xbps-install -Sy >/dev/null
|
|
xbps-install -y --repository="$(dirname "$PKGFILE")" "$PKGNAME" >/dev/null
|
|
|
|
case "$PKGNAME" in
|
|
voculinux)
|
|
echo "== payload $PKGNAME: desktop entry, icons, packaged marker"
|
|
tar -tf "$PKGFILE" 2>/dev/null | grep -q "usr/share/applications/voculinux.desktop" || {
|
|
echo "renamed desktop entry missing from the built package" >&2
|
|
exit 1
|
|
}
|
|
tar -tf "$PKGFILE" 2>/dev/null | grep -q "usr/share/icons/hicolor/scalable/apps/voculinux.svg" || {
|
|
echo "renamed icons missing from the built package" >&2
|
|
exit 1
|
|
}
|
|
tar -tf "$PKGFILE" 2>/dev/null | grep -q "usr/share/voculinux/packaged" || {
|
|
echo "packaged-install marker missing from the built package" >&2
|
|
exit 1
|
|
}
|
|
echo "== payload $PKGNAME: no speech models, no vendored wheels"
|
|
if tar -tf "$PKGFILE" 2>/dev/null | grep -E "models/|\.ggml$|\.bin$|\.pt$|\.whl$"; then
|
|
echo "package payload carries models or wheels" >&2
|
|
exit 1
|
|
fi
|
|
echo "no models or wheels in the shipped package"
|
|
echo "== payload $PKGNAME: no pre-rename leftovers"
|
|
if tar -tf "$PKGFILE" 2>/dev/null | grep -E "usr/share/applications/vocalinux|usr/share/icons/.*/vocalinux"; then
|
|
echo "pre-rename file names in the OS-visible payload" >&2
|
|
exit 1
|
|
fi
|
|
echo "no pre-rename leftovers in the shipped package"
|
|
echo "== version and import smoke $PKGNAME"
|
|
voculinux --version
|
|
cat > /voculinux-smoke.py <<'PYEOF'
|
|
# The importable package keeps its retained internal name (vocalinux); the
|
|
# distribution metadata is the fork's own name (voculinux).
|
|
import importlib
|
|
|
|
MODULES = (
|
|
"vocalinux.main",
|
|
"vocalinux.ui.tray_indicator",
|
|
"vocalinux.speech_recognition.recognition_manager",
|
|
"vocalinux.speech_recognition.command_processor",
|
|
"vocalinux.text_injection.text_injector",
|
|
"vocalinux.text_injection.ibus_engine",
|
|
"vocalinux.ui.keyboard_backends",
|
|
"pywhispercpp.model",
|
|
)
|
|
for module in MODULES:
|
|
importlib.import_module(module)
|
|
print("import-smoke OK:", ", ".join(MODULES))
|
|
|
|
from importlib.metadata import version
|
|
print("voculinux", version("voculinux"))
|
|
PYEOF
|
|
python3 /voculinux-smoke.py
|
|
;;
|
|
python3-pywhispercpp)
|
|
echo "== compiler flag scan of the shipped ggml library"
|
|
LIBMEMBER=$(tar -tf "$PKGFILE" 2>/dev/null | grep -E "libggml-cpu\.so" | head -n1)
|
|
[ -n "$LIBMEMBER" ] || {
|
|
echo "libggml-cpu missing from the built package" >&2
|
|
exit 1
|
|
}
|
|
echo "member: $LIBMEMBER"
|
|
mkdir -p /flagscan
|
|
tar -xf "$PKGFILE" -C /flagscan "$LIBMEMBER"
|
|
LIBSCAN="/flagscan/${LIBMEMBER#./}"
|
|
echo "-- .GCC.command.line:"
|
|
readelf -p .GCC.command.line "$LIBSCAN" 2>/dev/null || echo "(section absent)"
|
|
echo "-- .comment:"
|
|
readelf -p .comment "$LIBSCAN" 2>/dev/null || echo "(section absent)"
|
|
if readelf -p .GCC.command.line "$LIBSCAN" 2>/dev/null | grep -E "march=native|mcpu=native|mtune=native"; then
|
|
echo "host-native CPU tuning in the shipped library" >&2
|
|
exit 1
|
|
fi
|
|
echo "no host-native tuning in the shipped library"
|
|
|
|
echo "== import smoke $PKGNAME"
|
|
python3 -c "from pywhispercpp.model import Model; print('model submodule ok')"
|
|
cat > /smoke.py <<'PYEOF'
|
|
import glob
|
|
import os
|
|
import pywhispercpp
|
|
pkgdir = os.path.dirname(pywhispercpp.__file__)
|
|
sitedir = os.path.dirname(pkgdir)
|
|
libs = sorted(os.path.basename(p) for p in glob.glob(sitedir + "/lib*.so*"))
|
|
print("shipped libraries:", libs)
|
|
assert any(n.startswith("libwhisper") for n in libs), "libwhisper missing"
|
|
exts = [n for n in os.listdir(sitedir) if n.startswith("_pywhispercpp") and n.endswith(".so")]
|
|
assert exts, "compiled extension missing"
|
|
print("extension:", exts)
|
|
has_vulkan = any("vulkan" in n for n in libs)
|
|
want_vulkan = bool(int(os.environ["EXPECT_VULKAN"]))
|
|
assert has_vulkan == want_vulkan, "vulkan backend present=%s, expected=%s" % (has_vulkan, want_vulkan)
|
|
print("smoke ok")
|
|
PYEOF
|
|
EXPECT_VULKAN="$EXPECT_VULKAN" python3 /smoke.py
|
|
;;
|
|
python3-PyAudio)
|
|
echo "== import smoke $PKGNAME"
|
|
python3 -c "import pyaudio; print('pyaudio', pyaudio.__version__)"
|
|
;;
|
|
python3-pynput)
|
|
# pynput selects a display backend at import and raises without one;
|
|
# the container has no display, so presence plus the installed
|
|
# version (the same proof the native smoke accepts) is the smoke.
|
|
echo "== import smoke $PKGNAME"
|
|
python3 -c "import importlib.metadata, importlib.util; assert importlib.util.find_spec('pynput'), 'pynput not importable'; print('pynput', importlib.metadata.version('pynput'))"
|
|
;;
|
|
*)
|
|
echo "no smoke recipe for package '$PKGNAME' — add one alongside the template" >&2
|
|
exit 1
|
|
;;
|
|
esac
|