#!/bin/sh # Build a .deb package for gKeyMapper. # Usage: scripts/make-deb.sh [version] [arch] set -e VERSION="${1:-0.1.2}" 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" < 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" # 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 # 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 # 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" # 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" # 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"