Files
gKeyMapper/scripts/make-deb.sh

255 lines
9.6 KiB
Bash
Raw Permalink Normal View History

2026-10-18 22:53:39 +02:00
#!/bin/sh
# Build a .deb package for gKeyMapper.
# Usage: scripts/make-deb.sh [version] [arch]
set -e
2026-10-27 18:57:14 +01:00
VERSION="${1:-0.1.2}"
2026-10-18 22:53:39 +02:00
ARCH="${2:-$(dpkg --print-architecture 2>/dev/null || echo amd64)}"
PACKAGE="gkeymapper"
STAGING="build/deb"
DEB_NAME="${PACKAGE}_${VERSION}_${ARCH}.deb"
# Build everything first.
make all translations
rm -rf "$STAGING"
mkdir -p "$STAGING/DEBIAN"
# Stage files with Debian layout (PREFIX=/usr).
make install DESTDIR="$STAGING" PREFIX=/usr
# Calculate installed size (in KB) for the control file.
INSTALLED_SIZE=$(du -sk "$STAGING" | cut -f1)
# Control file.
cat > "$STAGING/DEBIAN/control" <<EOF
Package: $PACKAGE
Version: $VERSION
Section: utils
Installed-Size: $INSTALLED_SIZE
Priority: optional
Architecture: $ARCH
2026-10-27 18:57:14 +01:00
Depends: libc6, libgtk-4-1, libxkbcommon0, libglib2.0-0, systemd, udev
2026-10-18 22:53:39 +02:00
Maintainer: gKeyMapper <gkeymapper@rager.dev>
Description: Remap G1-G9 keys of the Logitech G910
A GTK4 GUI plus a background daemon for remapping the G1-G9 keys
of a Logitech G910 keyboard to keys or commands.
EOF
# preinst: stop any running daemon and re-attach the kernel driver BEFORE
# upgrading. The old (libusb-based) daemon detached the kernel driver from
# interface 1; if it was not stopped gracefully, the driver stays detached
# and the new (hidraw-based) daemon cannot find the device.
cat > "$STAGING/DEBIAN/preinst" <<'EOF'
#!/bin/sh
set -e
case "$1" in
install|upgrade)
# Stop any running daemon (old or new).
for pid in $(pgrep -f gkeymapper-daemon 2>/dev/null); do
kill "$pid" 2>/dev/null || true
done
sleep 1
# Re-attach the kernel driver to interface 1 if it was detached by
# an older (libusb-based) daemon.
for _dev in /sys/bus/usb/devices/*; do
_vendor=$(cat "$_dev/idVendor" 2>/dev/null) || continue
_product=$(cat "$_dev/idProduct" 2>/dev/null) || continue
case "$_vendor" in
046d)
case "$_product" in
c32b|c335)
for _iface in "$_dev"/*:*; do
case "$_iface" in
*:1.*)
_name=$(basename "$_iface")
if [ -w /sys/bus/usb/drivers/usbhid/bind ]; then
echo "$_name" > /sys/bus/usb/drivers/usbhid/bind 2>/dev/null || true
fi
;;
esac
done
;;
esac
;;
esac
done
;;
esac
exit 0
EOF
chmod 755 "$STAGING/DEBIAN/preinst"
2026-10-18 22:53:39 +02:00
# postinst: reload udev/systemd and enable the user daemon.
cat > "$STAGING/DEBIAN/postinst" <<'EOF'
#!/bin/sh
set -e
case "$1" in
configure)
if command -v udevadm >/dev/null 2>&1; then
udevadm control --reload-rules 2>/dev/null || true
udevadm trigger --subsystem-match=usb 2>/dev/null || true
udevadm trigger --subsystem-match=input 2>/dev/null || true
fi
# Remove stale service file from old "make install" (PREFIX=/usr/local)
# so the new one from /usr takes precedence.
rm -f /usr/local/lib/systemd/user/gkeymapper-daemon.service
2026-10-27 18:57:14 +01:00
# Re-attach the kernel driver to interface 1 if it was detached by an
# older (libusb-based) daemon. Without this the new (hidraw-based)
# daemon cannot find /dev/hidraw for interface 1.
for _dev in /sys/bus/usb/devices/*; do
_vendor=$(cat "$_dev/idVendor" 2>/dev/null) || continue
_product=$(cat "$_dev/idProduct" 2>/dev/null) || continue
case "$_vendor" in
046d)
case "$_product" in
c32b|c335)
for _iface in "$_dev"/*:*; do
case "$_iface" in
*:1.*)
_name=$(basename "$_iface")
if [ -w /sys/bus/usb/drivers/usbhid/bind ]; then
echo "$_name" > /sys/bus/usb/drivers/usbhid/bind 2>/dev/null || true
fi
;;
esac
done
;;
esac
;;
esac
done
2026-10-18 22:53:39 +02:00
# Helper: run a command as a given user with the D-Bus session bus
# available. "systemctl --user" needs DBUS_SESSION_BUS_ADDRESS, which
# is not set in a plain "su -" login shell.
run_as_user() {
_user="$1"; shift
_uid=$(id -u "$_user" 2>/dev/null) || return 1
_bus="unix:path=/run/user/$_uid/bus"
runuser -u "$_user" -- env DBUS_SESSION_BUS_ADDRESS="$_bus" "$@" 2>&1
}
_target_user=""
if [ -n "$SUDO_USER" ]; then
_target_user="$SUDO_USER"
fi
if [ -n "$_target_user" ]; then
echo "gkeymapper: enabling daemon for user $_target_user ..."
if run_as_user "$_target_user" systemctl --user daemon-reload; then
echo " daemon-reload: OK"
else
echo " daemon-reload: FAILED (is the user session running?)"
fi
if run_as_user "$_target_user" systemctl --user enable --now gkeymapper-daemon; then
echo " enable --now gkeymapper-daemon: OK"
else
echo " enable --now gkeymapper-daemon: FAILED"
echo " -> run manually: systemctl --user enable --now gkeymapper-daemon"
fi
else
echo "gkeymapper: no installing user detected (SUDO_USER empty)."
echo " Enable the daemon manually with:"
echo " systemctl --user daemon-reload"
echo " systemctl --user enable --now gkeymapper-daemon"
for _user in $(loginctl list-users --no-legend 2>/dev/null | awk '{print $2}'); do
_uid=$(id -u "$_user" 2>/dev/null) || continue
echo " trying user $_user ..."
run_as_user "$_user" systemctl --user daemon-reload >/dev/null 2>&1 || true
run_as_user "$_user" systemctl --user enable --now gkeymapper-daemon >/dev/null 2>&1 || true
done
fi
;;
esac
exit 0
EOF
chmod 755 "$STAGING/DEBIAN/postinst"
2026-10-27 18:57:14 +01:00
# prerm: stop the daemon and re-attach the kernel driver before upgrading.
# The old (libusb-based) daemon detached the kernel driver from interface 1;
# if it was not stopped gracefully, the driver stays detached and the new
# (hidraw-based) daemon cannot find the device.
cat > "$STAGING/DEBIAN/prerm" <<'EOF'
#!/bin/sh
set -e
case "$1" in
remove|upgrade|deconfigure)
# Stop the daemon if running.
if [ -n "$SUDO_USER" ]; then
runuser -u "$SUDO_USER" -- systemctl --user stop gkeymapper-daemon >/dev/null 2>&1 || true
runuser -u "$SUDO_USER" -- systemctl --user daemon-reload >/dev/null 2>&1 || true
else
for _user in $(loginctl list-users --no-legend 2>/dev/null | awk '{print $2}'); do
runuser -u "$_user" -- systemctl --user stop gkeymapper-daemon >/dev/null 2>&1 || true
done
fi
# Re-attach the kernel driver to interface 1 if it was detached by
# an older (libusb-based) daemon. Without this, the new daemon
# (hidraw-based) cannot find /dev/hidraw for interface 1.
for _dev in /sys/bus/usb/devices/*; do
_vendor=$(cat "$_dev/idVendor" 2>/dev/null) || continue
_product=$(cat "$_dev/idProduct" 2>/dev/null) || continue
case "$_vendor" in
046d)
case "$_product" in
c32b|c335)
for _iface in "$_dev"/*:*; do
case "$_iface" in
*:1.*)
_name=$(basename "$_iface")
if [ -w /sys/bus/usb/drivers/usbhid/bind ]; then
echo "$_name" > /sys/bus/usb/drivers/usbhid/bind 2>/dev/null || true
fi
;;
esac
done
;;
esac
;;
esac
done
;;
esac
exit 0
EOF
chmod 755 "$STAGING/DEBIAN/prerm"
2026-10-18 22:53:39 +02:00
# postrm: disable the user daemon on removal.
cat > "$STAGING/DEBIAN/postrm" <<'EOF'
#!/bin/sh
set -e
case "$1" in
remove|purge)
if [ -n "$SUDO_USER" ]; then
su - "$SUDO_USER" -c "systemctl --user disable --now gkeymapper-daemon" >/dev/null 2>&1 || true
su - "$SUDO_USER" -c "systemctl --user daemon-reload" >/dev/null 2>&1 || true
fi
;;
esac
exit 0
EOF
chmod 755 "$STAGING/DEBIAN/postrm"
# Fix ownership (files must be owned by root in a .deb).
# Strip debug symbols from binaries.
strip "$STAGING/usr/bin/gkeymapper" "$STAGING/usr/bin/gkeymapper-daemon" 2>/dev/null || true
# Remove generated cache files (they are regenerated on the target).
rm -f "$STAGING/usr/share/applications/mimeinfo.cache"
rm -f "$STAGING/usr/share/icons/hicolor/icon-theme.cache"
# Fix file permissions.
chmod 644 "$STAGING"/usr/share/applications/* 2>/dev/null || true
chmod 755 "$STAGING"/usr/bin/* 2>/dev/null || true
# Build the .deb.
dpkg-deb --root-owner-group --build "$STAGING" "$DEB_NAME"
echo ""
echo "Built: $DEB_NAME"