# Desktop packaging (Linux, Arch, Windows)

How to produce distributable desktop packages for JellyTau. All three flows can
run in Docker so no host toolchain setup is required. Outputs land in `./dist`.

## One builder image (shared with CI)

The deb/rpm and Windows-cross flows build on the **unified registry builder**
([../Dockerfile.builder](../../Dockerfile.builder) →
`gitea.tourolle.paris/dtourolle/jellytau-builder`), the same image CI uses. It
carries every packaging tool: Android SDK/NDK, `rpm`/`file` (Linux bundler),
`cargo-xwin` + `lld` + `llvm` + `nsis` + the `x86_64-pc-windows-msvc` rust target
(Windows). There is **one** dependency source of truth — no per-stage tool
installs.

The desktop stages in [../Dockerfile](../../Dockerfile) are thin `FROM
${BUILDER_IMAGE}` environments; the actual build runs at container-run time on
your bind-mounted source (like the `dev` service), so source edits need no image
rebuild.

**If you changed `Dockerfile.builder`** (e.g. added a tool), rebuild and push it
first, or the packaging flows use the stale registry image:

```bash
scripts/build-builder-image.sh           # build + push :latest to the registry
# ...or iterate locally without pushing:
docker build -f Dockerfile.builder -t jellytau-builder:latest .
BUILDER_IMAGE=jellytau-builder:latest bun run docker:build:windows
```

Arch uses a separate `archlinux` image ([../Dockerfile.arch](../../Dockerfile.arch))
because `makepkg` is Arch-specific — it is not part of the unified builder.

| Target | Format | Docker command | Functional? |
|--------|--------|----------------|-------------|
| Debian/Ubuntu, Fedora | `.deb`, `.rpm` | `bun run docker:build:linux` | ✅ yes |
| Arch Linux | `.pkg.tar.zst` | `bun run docker:build:arch` | ✅ yes |
| Windows | NSIS installer + `.exe` | `bun run docker:build:windows` | ✅ yes (unsigned) |

## Linux: deb + rpm

Tauri's bundler produces these natively. The build runs on the existing Ubuntu
builder image ([../Dockerfile](../../Dockerfile), `desktop-linux-build` stage):

```bash
bun run docker:build:linux            # deb + rpm -> ./dist
# or, on a host with the Tauri Linux deps installed:
BUNDLES="deb,rpm" scripts/build-desktop-linux.sh
```

Runtime dependency: the app links libmpv (audio) and WebKitGTK (webview + HTML5
transcoded video). The deb/rpm declare these.

> Note: `appimage` is also a valid Tauri target if you want a portable bundle —
> add it to `BUNDLES`.

## Arch Linux: pacman package

**Tauri has no `pacman` bundle target** (as of tauri-cli 2.9.x — valid targets
are deb/rpm/appimage/msi/nsis/app/dmg). So we ship a hand-written PKGBUILD in
[../packaging/arch/PKGBUILD](../../packaging/arch/PKGBUILD) and build it with
`makepkg` on an Arch base image ([../Dockerfile.arch](../../Dockerfile.arch)):

```bash
bun run docker:build:arch             # .pkg.tar.zst -> ./dist
```

The PKGBUILD is AUR-ready: swap its `source=()` for a release tarball/VCS URL to
publish. Runtime deps: `webkit2gtk-4.1`, `mpv`, `gtk3`, `libayatana-appindicator`.

`makepkg` refuses to run as root, so the Docker stage builds as a non-root
`builder` user. Because the image `COPY`s the source at build time, the
`arch-build` compose service does **not** bind-mount the repo — rebuild the image
to pick up source changes.

## Windows: NSIS installer cross-compiled from Linux

Produces a working (unsigned) NSIS installer + `.exe` via the official Tauri
cross-compile path — the `x86_64-pc-windows-msvc` target driven by `cargo-xwin`.
Video plays via WebView2 and audio via the webview `<audio>` backend. See
[build-windows.md](build-windows.md) for the full explanation.

```bash
bun run docker:build:windows                     # NSIS installer + .exe -> ./dist
WIN_BUNDLES=none bun run docker:build:windows     # exe only, skip bundling
```

The Docker `windows-cross` stage is a thin layer over the builder, which carries
`cargo-xwin` + `lld` + `llvm` + `nsis` + the `x86_64-pc-windows-msvc` target.
Cross-compilation is Tauri's "last resort" path (less tested than building on
Windows); a `windows-latest` CI job is the fallback if it misbehaves.
