From 0af9b429aa16951ebc3d03d2bad77e2d43aae5cd Mon Sep 17 00:00:00 2001 From: LucBennett <61855787+LucBennett@users.noreply.github.com> Date: Mon, 3 Aug 2026 20:34:41 -0700 Subject: [PATCH] Add debian/ubuntu build instructions and scripts --- dev/README.md | 2 +- dev/linux/README.md | 60 ++++++++++++++++++++++++++++++++++ dev/linux/build.sh | 79 +++++++++++++++++++++++++++++++++++++++++++++ dev/linux/setup.sh | 37 +++++++++++++++++++++ 4 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 dev/linux/README.md create mode 100755 dev/linux/build.sh create mode 100755 dev/linux/setup.sh diff --git a/dev/README.md b/dev/README.md index 033d212..4258614 100644 --- a/dev/README.md +++ b/dev/README.md @@ -8,7 +8,7 @@ git submodule update --init --recursive Platform-specific build instructions: - [macOS](macos/README.md) - [Windows](windows/README.md) -- Linux: See [GitHub Actions workflow](../.github/workflows/test.yml) - install deps from `debian/control`, then CMake build +- [Linux](linux/README.md) ## Web Debugger diff --git a/dev/linux/README.md b/dev/linux/README.md new file mode 100644 index 0000000..171060b --- /dev/null +++ b/dev/linux/README.md @@ -0,0 +1,60 @@ +# Building Jellyfin Desktop on Linux + +## Quick Start + +### Setup and build + +```bash +dev/linux/setup.sh # First time: install dependencies (Debian/Ubuntu) +dev/linux/build.sh # Configure, build, and optionally install +``` + +## Prerequisites + +- **Debian/Ubuntu** (or derivative) with `apt-get` + +`setup.sh` installs everything else: + +- Build tooling: `devscripts`, `equivs`, `ninja-build`, `cmake` +- Build-time packages from [`../../debian/control`](../../debian/control)'s `Build-Depends`, including the required Qt6 modules (`qt6-base-dev`, `qt6-base-private-dev`, `qt6-declarative-dev`, `qt6-webengine-dev`, `qt6-wayland-dev`), `libmpv-dev`, `libcec-dev`, and the rest of the native toolchain +- Runtime QML plugins from `debian/control`'s `Depends:` field (`qml6-module-qtwebengine`, `qml6-module-qtwebchannel`, `qml6-module-qtquick-controls`, `qml6-module-qtquick-window`, `qml6-module-qtqml-workerscript`, `qml6-module-qtquick-templates`, `qml6-module-qt-labs-platform`), none of these are pulled in transitively by the `-dev` packages above, so they're installed separately + +## Install + +`build.sh` asks for confirmation separately before each `sudo` step: + +1. **Install Binary** @ `/usr/local/bin/jellyfin-desktop` +2. **Desktop integration** (`.desktop` file, icon, appdata metadata) @ `/usr/local/share/{applications,icons,metainfo}/` + +Answer `n` to either prompt to skip it. The built binary at `build/src/jellyfin-desktop` still runs without installing. + +## Directory Structure + +- `build/` - Build output (safe to delete) +- `build/src/jellyfin-desktop` - Built executable + +## Scripts + +- `setup.sh` - Install build and runtime dependencies +- `build.sh` - Initialize submodules, configure, build, and optionally install + +## Clean Build + +```bash +rm -rf build +dev/linux/build.sh +``` + +## Troubleshooting + +### Missing Qt6 packages + +``` +error: Qt6 dev packages not found. Run setup.sh first +``` + +Run `dev/linux/setup.sh`. + +## Notes + +- Data/config/cache/log file locations are documented in the [main README](../../README.md#file-locations) diff --git a/dev/linux/build.sh b/dev/linux/build.sh new file mode 100755 index 0000000..f07ad71 --- /dev/null +++ b/dev/linux/build.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +# Jellyfin Desktop - Linux build & install script +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +BUILD_DIR="${PROJECT_ROOT}/build" +PREFIX="/usr/local" + +confirm() { + local reply + read -r -p "${1} [y/N] " reply + [[ "${reply}" =~ ^[Yy]([Ee][Ss])?$ ]] +} + +if ! pkg-config --exists Qt6Core 2>/dev/null; then + echo "error: Qt6 dev packages not found. Run setup.sh first" >&2 + exit 1 +fi + +# Submodules (e.g. external/mpvqt) are required for -DUSE_STATIC_MPVQT=ON. +if [[ -z "$(ls -A "${PROJECT_ROOT}/external/mpvqt" 2>/dev/null)" ]]; then + echo "Initializing submodules..." + git -C "${PROJECT_ROOT}" submodule update --init --recursive +fi + +if [[ -f "${BUILD_DIR}/CMakeCache.txt" ]]; then + cached_source="$(sed -n 's/^CMAKE_HOME_DIRECTORY:INTERNAL=//p' "${BUILD_DIR}/CMakeCache.txt")" + if [[ "${cached_source}" != "${PROJECT_ROOT}" ]]; then + echo "Build directory was configured from ${cached_source}, removing stale build/" + rm -rf "${BUILD_DIR}" + fi +fi + +echo "Configuring..." +cmake -B "${BUILD_DIR}" -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DUSE_STATIC_MPVQT=ON \ + "${PROJECT_ROOT}" + +echo "Building..." +cmake --build "${BUILD_DIR}" + +BINARY="${BUILD_DIR}/src/jellyfin-desktop" +if [[ ! -x "${BINARY}" ]]; then + echo "error: build did not produce ${BINARY}" >&2 + exit 1 +fi + +echo "" +echo "Build complete: ${BINARY}" +echo "" + +BIN_DEST="${PREFIX}/bin/jellyfin-desktop" +DESKTOP_SRC="${PROJECT_ROOT}/resources/meta/org.jellyfin.JellyfinDesktop.desktop" +APPDATA_SRC="${PROJECT_ROOT}/resources/meta/org.jellyfin.JellyfinDesktop.appdata.xml" +ICON_SRC="${PROJECT_ROOT}/resources/images/icon.svg" +DESKTOP_DEST="${PREFIX}/share/applications/org.jellyfin.JellyfinDesktop.desktop" +APPDATA_DEST="${PREFIX}/share/metainfo/org.jellyfin.JellyfinDesktop.appdata.xml" +ICON_DEST="${PREFIX}/share/icons/hicolor/scalable/apps/org.jellyfin.JellyfinDesktop.svg" + +if confirm "Install binary to ${BIN_DEST} (requires sudo)?"; then + sudo install -Dm755 "${BINARY}" "${BIN_DEST}" + echo "Installed ${BIN_DEST}" +else + echo "Skipped binary install." +fi + +if confirm "Copy .desktop file, icon, and appdata metadata for app menu integration (requires sudo)?"; then + sudo install -Dm644 "${DESKTOP_SRC}" "${DESKTOP_DEST}" + sudo install -Dm644 "${APPDATA_SRC}" "${APPDATA_DEST}" + sudo install -Dm644 "${ICON_SRC}" "${ICON_DEST}" + echo "Installed desktop entry, icon, and appdata metadata." +else + echo "Skipped desktop integration files." +fi + +echo "" +echo "Done." diff --git a/dev/linux/setup.sh b/dev/linux/setup.sh new file mode 100755 index 0000000..a89d955 --- /dev/null +++ b/dev/linux/setup.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# Jellyfin Desktop - Linux dependency installer +# Run once (Debian/Ubuntu) before build.sh. +# +# Installs everything listed under Build-Depends in ../../debian/control, +# then installs the runtime QML plugins the app imports (Qt.labs.platform, +# WebEngine, etc.). +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" + +if ! command -v apt-get >/dev/null; then + echo "error: apt-get not found. This script targets Debian/Ubuntu." >&2 + echo "See ${PROJECT_ROOT}/debian/control for the full dependency list." >&2 + exit 1 +fi + +echo "Installing build tooling (devscripts, equivs, ninja-build)..." +sudo apt-get update +sudo apt-get install --yes devscripts equivs ninja-build + +echo "Installing build dependencies from debian/control..." +sudo mk-build-deps -i -r -t "apt-get --yes" "${PROJECT_ROOT}/debian/control" + +echo "Installing runtime QML modules..." +sudo apt-get install --yes \ + qml6-module-qtwebengine \ + qml6-module-qtwebchannel \ + qml6-module-qtquick-controls \ + qml6-module-qtquick-window \ + qml6-module-qtqml-workerscript \ + qml6-module-qtquick-templates \ + qml6-module-qt-labs-platform + +echo "" +echo "Setup complete. Run build.sh to build."