Files
netdesk/native/docs/build-linux.md
T

8.4 KiB

NetDesk — Linux build & packaging

Build the native netdesk-viewer for Linux and bundle the two distributions NetDesk by Akronlogic ships on Linux:

Edition Artifact Install?
AppImage NetDesk-<ver>-x86_64.AppImage No — chmod +x and run anywhere
.deb netdesk_<ver>_amd64.deb Yes — apt install ./… (launcher + icon)

Both are produced by packaging/build-linux.sh. Everything it writes lands in packaging/dist/linux/ (git-ignored). This is the Linux counterpart of the Windows packaging/README.md.

This target must be built on Linux (x86_64). The viewer links the system FFmpeg/VAAPI libraries for the Linux hardware-decode path (core/src/decode_vaapi.rs), which are not present when cross-building from Windows or macOS.


1. Build dependencies

The Linux decode backend pulls in FFmpeg through the ffmpeg-next crate, whose build script (ffmpeg-sys-next) locates libav* with pkg-config and generates bindings with libclang. The GUI (eframe/egui on winit + glow) needs OpenGL at runtime. Install the toolchain + dev libraries first.

Debian / Ubuntu

sudo apt update
sudo apt install -y build-essential clang pkg-config nasm \
  libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \
  libavfilter-dev libavdevice-dev libswresample-dev \
  libva-dev \
  libgl1-mesa-dev
  • build-essential → the C/C++ linker (cc/g++) Rust and openh264-sys2 need.
  • clang → libclang for ffmpeg-sys-next's bindgen.
  • pkg-config → locates the FFmpeg and VAAPI libraries.
  • nasm → assembler for the bundled openh264 software-decode fallback.
  • libav*-dev → FFmpeg ≥ 4 development libraries (the full set matches the default features of ffmpeg-next).
  • libva-dev → VAAPI headers for the hardware-decode path.
  • libgl1-mesa-dev → OpenGL for the glow renderer.

Fedora (FFmpeg dev libs come from RPM Fusion)

sudo dnf install -y gcc gcc-c++ clang pkgconf-pkg-config nasm \
  ffmpeg-devel libva-devel mesa-libGL-devel

Optional — native file-picker

The viewer's File transfer → Upload… button uses rfd, which is compiled with no Linux backend in viewer/Cargo.toml (default-features = false). The build and the app run fine without it, but the picker is a no-op on Linux until rfd is given a backend feature:

  • GTK 3 backend → add features = ["gtk3"] to rfd, then install libgtk-3-dev (build) / libgtk-3-0 (runtime).
  • XDG portal backend (no GTK) → add features = ["xdg-portal", "tokio"]; needs a running xdg-desktop-portal at runtime, nothing extra at build.

This is the only reason libgtk is ever involved on Linux — it is not required to build or run NetDesk as shipped.


2. The one command

export PATH="$HOME/.cargo/bin:$PATH"     # ensure cargo/rustup are reachable
packaging/build-linux.sh

That runs cargo build --release -p netdesk-viewer (target x86_64-unknown-linux-gnu) and then produces both the .deb and the AppImage in packaging/dist/linux/:

packaging/dist/linux/
├── netdesk_0.1.0_amd64.deb          ← dpkg package (launcher + hicolor icons)
├── NetDesk-0.1.0-x86_64.AppImage    ← portable single file
├── com.akronlogic.netdesk.desktop   (generated launcher, shared by both)
├── AppDir/                          (AppImage staging)
└── deb/                             (.deb staging tree)

The underlying build command on its own:

cargo build --release -p netdesk-viewer --target x86_64-unknown-linux-gnu

Flags

Flag Effect
--skip-build reuse an existing target/.../release/netdesk-viewer
--no-appimage build the .deb only
--no-deb build the AppImage only
--target <triple> override the Rust target (default x86_64-unknown-linux-gnu)
LINUXDEPLOY=/path env: use a local linuxdeploy instead of downloading it

The AppImage step downloads linuxdeploy once (cached in packaging/dist/.tools/) and runs it with APPIMAGE_EXTRACT_AND_RUN=1, so it works in containers/CI without FUSE. linuxdeploy ldd-scans the binary and bundles its shared libraries (libavcodec, libavutil, libswscale, …) into the AppImage; libGL, libX11/xcb, Wayland and libva are intentionally not bundled — they are dlopen()ed and must come from the host graphics stack. The .deb instead declares those as package Depends:.


3. VAAPI hardware-decode note

NetDesk hardware-decodes the host's H.264 stream on Linux through VAAPI via FFmpeg/libavcodec (core/src/decode_vaapi.rs): it opens the libavcodec H.264 decoder with a VAAPI hw_device_ctx on the default DRI render node (/dev/dri/renderD128), decodes on the GPU, pulls the surface to system memory (NV12), crops to the true display size, and swscales to the packed RGB8 Frame the viewer paints — see cross-platform-decode.md for the full backend matrix.

Hardware decode is optional at runtime. best_decoder() tries VAAPI first and falls back to the openh264 software decoder if no usable VAAPI device is present, so headless / GPU-less boxes still work. VAAPI is a build dependency (the libraries must link) but not a runtime requirement.

To get the hardware path at runtime on the target machine:

  1. Install a VAAPI driver (the .deb lists these as Recommends):
    • Intel (Broadwell+): intel-media-va-driver (iHD)
    • Intel (older): i965-va-driver
    • AMD / others (Mesa): mesa-va-drivers (radeonsi)
  2. Verify it: vainfo should list an H264 decode profile (e.g. VAProfileH264High : VAEntrypointVLD). Install vainfo from libva-utils.
  3. Render-node access: the user must be able to read /dev/dri/renderD128 — typically by membership of the render (or video) group.
  4. Driver override (if needed): export LIBVA_DRIVER_NAME=iHD (or i965, radeonsi) when autodetection picks the wrong driver.

Confirm which path is live from the viewer's log:

decode: VAAPI H.264 (FFmpeg hardware)        ← hardware path selected
VAAPI init failed (...); using openh264 ...  ← fell back to software

If it fell back, check vainfo, the /dev/dri/renderD128 permissions, and LIBVA_DRIVER_NAME.


4. Troubleshooting

  • libavcodec not found via pkg-config / bindgen errors — the FFmpeg dev libraries or clang are missing. Re-run the install command in §1. For FFmpeg in a non-standard prefix, set PKG_CONFIG_PATH.
  • openh264 build fails for want of an assembler — install nasm.
  • AppImage not produced (linuxdeploy download/FUSE error) — the script warns and still writes the .deb. Supply a local tool with LINUXDEPLOY=/path, or run with --no-appimage. APPIMAGE_EXTRACT_AND_RUN=1 is already exported for FUSE-less hosts.
  • .deb won't install — unmet FFmpeg dependency — soname package names differ per release; the control file lists libavcodec60 | 59 | 58 | ffmpeg (and likewise for libavutil/libswscale). On an unusual release, installing the distro ffmpeg package satisfies the catch-all.
  • Wrong window/taskbar icon on GNOME/Wayland — the launcher file name and its Icon= key both use the app-id com.akronlogic.netdesk, matching the viewer's with_app_id(...); for the .deb, gtk-update-icon-cache runs in postinst. Log out/in if the shell cached the old icon.

5. Test

vainfo                              # confirm a VAAPI driver + H264 profile (optional)
cargo test -p netdesk-core          # core decode/transport tests
./packaging/dist/linux/NetDesk-*.AppImage    # smoke-test the viewer

Smoke-test end to end against a live host; the log line decode: VAAPI H.264 (FFmpeg hardware) confirms the hardware path was selected.