This commit is contained in:
nvrl committed 2026-08-02 19:37:03 +02:00
commit a1b345a029
80 files changed
+28033

No files matched your search

+139
View File
@@ -0,0 +1,139 @@
# Packaging
Everything here is driven by two scripts. `scripts/build.sh` covers Linux and
macOS; `scripts/build.ps1` covers Windows, because the `.exe` and the `.msi`
need MSVC and WiX and neither is reachable from a Unix host.
| Artifact | Command | Host it must run on |
|---|---|---|
| `dist/proton-stream-<ver>-<triple>.tar.gz` | `scripts/build.sh tarball` | Linux or macOS |
| `dist/proton-stream_<ver>-1_amd64.deb` | `scripts/build.sh deb` | any Linux |
| `dist/proton-stream-<ver>-1.x86_64.rpm` | `scripts/build.sh rpm` | any Linux with `rpmbuild` |
| `packaging/*.pkg.tar.zst` | `cd packaging && makepkg -fi` | Arch |
| `dist/Proton Stream.app` + `.dmg` | `scripts/build.sh dmg` | macOS |
| `dist/windows/proton-stream.exe` + `.zip` | `scripts\build.ps1 -Artifacts zip` | Windows |
| `dist/proton-stream-<ver>-x64.msi` | `scripts\build.ps1 -Artifacts msi` | Windows |
`scripts/build.sh` with no arguments produces everything the host can.
## How it fits together
One cargo build feeds every Linux and macOS artifact. The binaries are compiled
once, staged into a filesystem image at `dist/stage` — rooted so that
`dist/stage/usr/bin/pstr` is exactly where the file lands on the target system —
and each packager copies out of that image. A `.deb` and an `.rpm` from the same
run are therefore the same bytes, and neither `dpkg-deb` nor `rpmbuild` needs a
Rust toolchain or libmpv headers.
`--skip-build` reuses `dist/stage`, which is what you want when iterating on a
control file or a spec.
The Arch package is the exception: `makepkg` compiles in place from the
checkout, by Arch convention and to match `../proton-drive-linux`. It ignores
`dist/stage` entirely. `scripts/build.sh arch` runs it for you and copies the
result into `dist/`, but it is not part of `all` — it recompiles, and most hosts
are not Arch.
## Runtime dependencies, and why they are what they are
| | Why |
|---|---|
| **libmpv ≥ 0.34** | The player. `pstr-player` links it directly and drives it through `stream_cb`; nothing here shells out to `mpv(1)`, so packages depend on the library, not the player binary. |
| **libsecret / Secret Service** | The share URL fragment and the custom password are secrets and live in the OS credential store, never in `shares.json`. |
| **libGL, libxkbcommon, libX11, libwayland-client** | eframe on glow, with both display backends compiled in. |
Not dependencies, deliberately: **SQLite** (rusqlite is `bundled`) and
**OpenSSL** (TLS is rustls with webpki-roots). Both are inside the binary.
Per packager that is:
- Debian — `libmpv2 | libmpv1` (trixie | bookworm), `libsecret-1-0`, `libgl1`,
`libxkbcommon0`, `libx11-6`, `libwayland-client0`.
- RPM — `mpv-libs`, `libsecret`, `mesa-libGL`, `libxkbcommon`, `libX11`,
`libwayland-client`.
- Arch — `mpv` (which carries both `libmpv.so` and its headers), `libsecret`.
The `.deb` and `.rpm` are built from binaries compiled on the packaging host, so
they inherit its glibc. A package built on Arch installs on Fedora rawhide but
not on an older distribution — build on the oldest one you intend to support, or
in that distribution's container.
`AutoReqProv: no` in the spec is for the same reason: the ELF scan would generate
soname requirements against whatever the packaging host happens to have, so the
explicit `Requires` list stands instead.
## Windows
libmpv is the whole difficulty. `libmpv2-sys` emits `cargo:rustc-link-lib=mpv`,
so the linker wants an import library named `mpv.lib` and the process wants
`libmpv-2.dll` at run time. Neither ships with mpv's Windows *player* build —
both come from the separate **mpv-dev** archive:
<https://sourceforge.net/projects/mpv-player-windows/files/libmpv/>
Unpack it and point the script at it:
```powershell
scripts\build.ps1 -MpvDev C:\mpv-dev
```
If that directory has `mpv.def` but no `mpv.lib`, the script generates the import
library with `lib.exe` (`/name:libmpv-2.dll`, so it references the DLL that
actually ships). It finds `lib.exe` on `PATH` or imports the MSVC environment via
`vswhere`, so a plain PowerShell session works.
There is no static libmpv worth shipping, so **"standalone exe" means the exe
plus `libmpv-2.dll` beside it** — that pair, plus `pstr.exe` and the README, is
what the portable `.zip` contains and what the `.msi` installs.
The MSI needs the WiX toolset; the script installs it (`dotnet tool install
--global wix`) and adds the UI extension if they are missing. It installs to
`Program Files\Proton Stream`, puts a Start Menu shortcut on the GUI, and adds
the install directory to the system `PATH` so `pstr` works from a shell — that
`PATH` entry is tied to `pstr.exe`'s component, so uninstalling removes it.
`UpgradeCode` in `proton-stream.wxs` is fixed forever: it is what makes 0.2.0
replace 0.1.0 rather than install beside it. Never regenerate it.
Signing is opt-in: `-SignCertThumbprint <thumbprint>` signs both executables and
the MSI.
## macOS
`scripts/build.sh dmg` produces `Proton Stream.app` inside a drag-to-Applications
disk image.
By default it copies libmpv and its non-system dependency closure into
`Contents/Frameworks` and rewrites every install name, because a `.dmg` that
requires the recipient to have run `brew install mpv` is not a `.dmg` anyone can
use. The bundle is then ad-hoc signed — every `install_name_tool` edit
invalidates the signature, and an unsigned-but-modified binary is killed outright
on arm64. Pass `--no-bundle-libs` to link against the host's libmpv instead.
The `.icns` is rasterized from `io.narl.proton-stream.svg` when `rsvg-convert` or
`magick` is available; without either, the bundle ships without an icon.
## Files
| | |
|---|---|
| `PKGBUILD` | Arch, in-tree `makepkg` build |
| `proton-stream.spec` | RPM, installs from `dist/stage` |
| `io.narl.proton-stream.desktop` / `.svg` | Freedesktop entry and icon |
| `macos/Info.plist.in` | `.app` bundle plist; `@VERSION@`/`@BIN@`/`@APP_ID@` substituted at build time |
| `windows/proton-stream.wxs` | WiX v4+ installer definition |
| `windows/proton-stream.ico` | MSI and shortcut icon, rasterized from the SVG |
| `windows/license.rtf` | Fallback for the installer's license dialog; the repo's own `LICENSE` is preferred when it exists |
The Debian `control` file has no template — `scripts/build.sh` writes it, because
almost every field in it is computed.
## Two things to know before releasing
- **The `[patch.crates-io]` block in `Cargo.toml` is development only.** It points
at `../proton-sdk-rs`, so both build scripts refuse to start when it is present
and that checkout is missing. A release must build against the published
crates — drop the block once proton-sdk 0.3.3 is on crates.io.
- **There is no `LICENSE` file in the repository root** even though `Cargo.toml`
declares MIT. Every packager warns and ships without the license text; the MSI
falls back to `windows/license.rtf`. Adding the file fixes all of them at once.