Model recommendation keyed to the installed build and free memory, fork-sourced Void templates, signed xbps release workflow on Gitea with the pinned repository key, niri injection guard and wtype-first order, tightened naming sweep, web copy fixes, and CI security and duplication fixes.
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
|