Files
OpsLog/scripts/linux-setup.sh
T
rouggy f22058355b fix(linux): the webkit build tag was inverted
Wails v2.11 defaults to webkit2gtk-4.0 and takes 4.1 only when told —

  #cgo !webkit2_41 pkg-config: webkit2gtk-4.0
  #cgo  webkit2_41 pkg-config: webkit2gtk-4.1

— and both the script and the doc had it the other way round: they
treated 4.1 as the default and offered a -tags webkit2_40 that does not
select anything. On a Debian 13 box, which ships only 4.1, the script
therefore detected 4.1, reported it as fine, passed no tag, ran npm for
several minutes and then stopped in cgo with "Package webkit2gtk-4.0 was
not found in the pkg-config search path".

Written from the Wails source rather than from memory this time, which
is where it should have come from in the first place.

libsoup is checked alongside, since it travels with the choice: 4.0
pairs with libsoup-2.4 and 4.1 with libsoup-3.0, and a missing one fails
the same way at the same late moment.
2026-09-11 09:52:47 +02:00

199 lines
8.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# linux-setup.sh — check what a Linux build of OpsLog needs, then build it.
#
# Run it from the repository root: ./scripts/linux-setup.sh
#
# It never installs anything itself. It prints the one command your distribution
# needs and stops, because a script that runs sudo on somebody else's machine is
# a script nobody should run. Once the dependencies are in, run it again and it
# builds.
set -u
red() { printf '\033[31m%s\033[0m\n' "$*"; }
grn() { printf '\033[32m%s\033[0m\n' "$*"; }
ylw() { printf '\033[33m%s\033[0m\n' "$*"; }
head_() { printf '\n\033[1m== %s\033[0m\n' "$*"; }
missing=0
note() { red " MISSING: $*"; missing=1; }
ok() { grn " ok: $*"; }
head_ "Distribution"
if [ -r /etc/os-release ]; then
# shellcheck disable=SC1091
. /etc/os-release
echo " ${PRETTY_NAME:-unknown}"
family="${ID_LIKE:-$ID}"
else
echo " unknown (no /etc/os-release)"
family=""
fi
head_ "Build dependencies"
have() { command -v "$1" >/dev/null 2>&1; }
pkg() { pkg-config --exists "$1" 2>/dev/null; }
have gcc || have cc || note "a C compiler (Wails links against the system WebKit, so cgo is required here)"
have pkg-config || note "pkg-config"
pkg gtk+-3.0 || note "GTK 3 development headers"
# Which webkit, and therefore which build tag.
#
# Wails v2.11 defaults to webkit2gtk-4.0 and takes 4.1 only when told:
# `#cgo !webkit2_41 pkg-config: webkit2gtk-4.0` against
# `#cgo webkit2_41 pkg-config: webkit2gtk-4.1`. This script had it the other
# way round and passed no tag on a Debian 13 box that has only 4.1, so the
# frontend built and then cgo stopped with "Package webkit2gtk-4.0 was not
# found in the pkg-config search path" — after several minutes of npm.
#
# libsoup travels with it: 4.0 pairs with libsoup-2.4, 4.1 with libsoup-3.0.
webkit_tags=""
if pkg webkit2gtk-4.1; then
ok "webkit2gtk-4.1 (building with -tags webkit2_41)"
webkit_tags="-tags webkit2_41"
pkg libsoup-3.0 || note "libsoup 3 development headers (webkit 4.1 links against them)"
elif pkg webkit2gtk-4.0; then
ok "webkit2gtk-4.0 (the default — no tag needed)"
pkg libsoup-2.4 || note "libsoup 2.4 development headers (webkit 4.0 links against them)"
else
note "webkit2gtk development headers (4.1 or 4.0)"
fi
# Node, and its VERSION — this is the trap on an LTS base. Ubuntu 22.04 (so
# Linux Mint 21) ships node 12, and Vite needs 18. The build fails deep inside
# the frontend with a syntax error that says nothing about the real cause, so
# catch it here where it can be named.
if have node; then
nodemaj=$(node -p 'process.versions.node.split(".")[0]' 2>/dev/null || echo 0)
if [ "${nodemaj:-0}" -ge 18 ]; then
ok "node $(node -v)"
else
note "node 18 or newer (you have $(node -v) — the distribution package is too old for Vite)"
ylw " curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install nodejs"
ylw " or use nvm: https://github.com/nvm-sh/nvm"
fi
else
note "node 18+"
fi
have npm || note "npm"
head_ "Go"
if have go; then
gov=$(go version | awk '{print $3}')
ok "$gov"
# 1.25 is what go.mod asks for. No distribution ships it yet — Ubuntu 22.04
# (Mint 21) has 1.18, Ubuntu 24.04 (Mint 22) has 1.22 — so `apt install
# golang-go` gets you a Go that cannot build this repository at all.
if ! go version | grep -Eq 'go1\.(2[5-9]|[3-9][0-9])'; then
note "go 1.25+ — $gov is too old for go.mod, and no apt package is new enough"
ylw " wget https://go.dev/dl/go1.26.3.linux-amd64.tar.gz"
ylw " sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.26.3.linux-amd64.tar.gz"
ylw " echo 'export PATH=/usr/local/go/bin:\$HOME/go/bin:\$PATH' >> ~/.profile # then log out and back in"
fi
# And TOO NEW breaks too, which is the harder one to meet cold. The Wails
# CLI parses this package with the golang.org/x/tools its own go.mod pins,
# and that release cannot read the export data a newer compiler writes. The
# failure names neither Go nor Wails:
#
# internal error: package "math" without types was imported from
# "hamlog/internal/geo"
#
# Met on Debian 13 with go1.27.1, which is simply what go.dev offers as
# latest. 1.25 and 1.26 are the versions this repository is built with.
if go version | grep -Eq 'go1\.(2[7-9]|[3-9][0-9])'; then
ylw " $gov is NEWER than the Wails CLI can parse this package with."
ylw " The build fails with: internal error: package \"math\" without types."
ylw " Install 1.26 (or 1.25) and rebuild the CLI with it:"
ylw " wget https://go.dev/dl/go1.26.3.linux-amd64.tar.gz"
ylw " sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.26.3.linux-amd64.tar.gz"
ylw " go install github.com/wailsapp/wails/v2/cmd/[email protected]"
fi
else
note "go 1.25+ — from https://go.dev/dl/, NOT from apt (no distribution ships 1.25 yet)"
fi
head_ "Wails CLI"
WAILS="$(command -v wails || true)"
[ -z "$WAILS" ] && [ -x "$HOME/go/bin/wails" ] && WAILS="$HOME/go/bin/wails"
if [ -n "$WAILS" ]; then
ok "$($WAILS version 2>/dev/null | head -1)"
else
note "the wails CLI: go install github.com/wailsapp/wails/v2/cmd/[email protected]"
ylw " (then make sure ~/go/bin is on your PATH)"
fi
if [ "$missing" -ne 0 ]; then
head_ "Install these first"
case "$family" in
*debian*|*ubuntu*)
echo " sudo apt install build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev"
echo " (on Debian 12 and older: libwebkit2gtk-4.0-dev)"
echo
echo " Go and node are NOT in that line on purpose — the apt versions are too"
echo " old on every current Ubuntu/Mint base. See the notes above for both." ;;
*fedora*|*rhel*)
echo " sudo dnf install gcc-c++ pkgconf-pkg-config gtk3-devel webkit2gtk4.1-devel nodejs npm" ;;
*arch*)
echo " sudo pacman -S base-devel pkgconf gtk3 webkit2gtk-4.1 nodejs npm" ;;
*suse*)
echo " sudo zypper install -t pattern devel_basis && sudo zypper install pkg-config gtk3-devel webkit2gtk3-soup2-devel nodejs npm" ;;
*)
echo " a C compiler, pkg-config, GTK 3 and webkit2gtk development packages, node and npm" ;;
esac
echo
echo "Then run this script again."
exit 1
fi
head_ "Serial ports"
# The single most common reason a rig that works in WSJT-X refuses to open here.
if id -nG | tr ' ' '\n' | grep -qx 'dialout\|uucp'; then
ok "you are in the serial group"
else
ylw " You are NOT in the 'dialout' group (or 'uucp' on Arch/Fedora)."
ylw " CAT, keyers, rotators and amplifiers will fail with \"permission denied\"."
ylw " sudo usermod -aG dialout \$USER # then log out and back in"
fi
head_ "Sound server"
# OpsLog speaks the PulseAudio protocol itself (jfreymuth/pulse) and connects to
# the NATIVE SOCKET. That socket is what decides whether audio works — not
# whether pactl is installed, which is a separate package (pulseaudio-utils).
# This check used to ask for pactl and told a Debian 13 desktop running PipeWire
# perfectly well that it had no sound server at all.
sock="${PULSE_SERVER:-}"
sock="${sock#unix:}"
if [ -z "$sock" ] && [ -n "${XDG_RUNTIME_DIR:-}" ]; then
sock="$XDG_RUNTIME_DIR/pulse/native"
fi
if [ -n "$sock" ] && [ -S "$sock" ]; then
if have pactl && pactl info >/dev/null 2>&1; then
ok "$(pactl info | sed -n 's/^Server Name: //p')"
else
ok "socket at $sock (install pulseaudio-utils if you want its name)"
fi
else
ylw " No PulseAudio/PipeWire socket found."
ylw " The voice keyer, the QSO recorder and the CW decoder will report they"
ylw " cannot reach it. Everything else works without one."
ylw " sudo apt install pipewire-pulse wireplumber # Debian/Ubuntu"
ylw " And run this from the DESKTOP session: the sound server belongs to the"
ylw " logged-in session, so a remote shell may not see it."
fi
head_ "Building"
echo " wails build $webkit_tags"
# shellcheck disable=SC2086
"$WAILS" build $webkit_tags || { red "Build failed."; exit 1; }
head_ "Done"
grn " ./build/bin/OpsLog"
echo
echo " First run creates build/bin/data/ beside the binary — a fresh, empty"
echo " logbook. Do NOT copy config.json over from Windows: it holds a Windows"
echo " path. Point OpsLog at your real logbook from Settings ▸ Database."
echo
echo " If the window never opens, look at:"
echo " ~/.cache/OpsLog/startup.log (before the window)"
echo " build/bin/data/opslog.log (after it)"