SimpMusic/conveyor.conf

236 lines
12 KiB
Text

// SimpMusic — Hydraulic Conveyor packaging config (Conveyor 2.0+)
//
// Distribution: installers (Mac .dmg via Mac runner wrap, Windows .msix
// + .appinstaller + .exe wrapper, Linux .AppImage) are uploaded to
// GitHub Releases manually. Conveyor's site.base-url auto-resolves to
// the `releases/latest/download/` URL pattern via `app.vcs-url`, so
// the generated download.html / `.appinstaller` reference the correct
// asset URLs without any extra hosting. Auto-update is disabled (see
// `updates = none` below) — users re-download for new versions.
//
// Pattern adapted from https://github.com/zacharee/Bifrost (KMP +
// Conveyor 2.0 reference).
// CI / local must run `./gradlew :desktopApp:writeConveyorConfig` BEFORE
// invoking Conveyor. The shell-include form (`include "#!..."`) was
// removed because Conveyor parses Gradle stdout as HOCON, and Sentry-
// related `println("Full build detected, ...")` in composeApp+androidApp
// configuration phase corrupts that stdout when `isFullBuild=true` is
// set in CI → "Key 'Full build detected' may not be followed by ','".
include required("desktopApp/generated.conveyor.conf")
// NOTE: deliberately NOT including hydraulic's extract-native-libraries.conf.
// That helper extracts every JAR-embedded native into the top-level lib/app
// AND keeps the source tree intact, so every bundled native gets duplicated
// (with the old VLC plugin set that took output from 989 MB to 1.4 GB).
// Nothing needs it:
// 1. MpvLibrary walks up from the JAR to find mpv/ at runtime
// 2. JNA's own per-JAR native unpacking still runs without the helper
app {
// fsname / display-name / rdns-name are appended by the doLast block in
// desktopApp/build.gradle.kts's writeConveyorConfig customisation.
vendor = "maxrave-dev"
description = "A FOSS YouTube Music client built with Compose Multiplatform."
license = "GPL-3.0-or-later"
// Open source = free Conveyor. Setting `vcs-url` to the public source
// repository qualifies SimpMusic for the OSS tier and removes the paid
// license requirement. See https://hydraulic.dev/pricing.html — "free
// for open source projects if you set the app.vcs-url key to where your
// source repository can be found."
//
// Per the same clause we must advertise "Packaged with Conveyor" + link
// to hydraulic.dev somewhere user-visible (download page, README, or
// about screen). The auto-generated download site already embeds the
// required badge — see TODO in docs/conveyor-local-test.md.
vcs-url = "https://github.com/muriloscolari/SimpMusic"
// Single PNG source → Conveyor auto-derives .icns / .ico / png variants
// for mac, windows, linux. Native .icns / .ico inputs are silently
// ignored by Conveyor 22.0 (it always re-encodes from raster source).
icons = "composeApp/icon/circle_app_icon.png"
// site.base-url auto-inferred from `vcs-url` above to the latest GitHub
// Release for this repo (Conveyor 22.0+ behaviour, per the March 2024
// blog update).
//
// updates = none → Conveyor does not wire Sparkle (Mac) or the
// background .appinstaller update check (Windows). Releases are
// handled by SimpMusic's native in-app updater (AppUpdater.jvm.kt).
updates = none
site {
consistency-checks = warn
}
// Custom URI schemes to register the app for. "simpmusic" backs the deep links
// from simpmusic.org; "wordbyword" is the Last.fm auth callback, whose scheme is
// fixed by the callback URL registered on the Last.fm API account.
//
// This key MUST stay at the top level of `app`. Conveyor binds url-schemes on
// AppConfig, not on MacConfig/WindowsConfig/LinuxConfig — compare
// `MacConfigAccess.getUrlSchemes()` (reads appConfig) with the
// `getFileAssociations()` right next to it (reads mac). We previously set
// `mac.url-schemes` / `windows.url-schemes` / `linux.url-schemes`; HOCON accepts
// unknown keys silently, so all three sat inert and the packaged apps carried NO
// CFBundleURLTypes at all — verified by diffing two mac-app builds that differed
// only in where this key was written. Nothing ever registered, not even
// "simpmusic", from May 2026 until this was moved.
url-schemes = [ "simpmusic", "wordbyword" ]
// Explicit machines list. Two architectures explicitly dropped because
// of missing native dependencies upstream:
//
// • linux.aarch64.glibc — dropped when VLC was the backend, because
// VideoLAN ships no prebuilt Linux ARM binary and the
// mahozad/vlc-plugins-linux artifact was amd64-only. That blocker
// died with VLC: mpv-AppImage does publish an aarch64 build, so this
// is worth revisiting once an ARM libmpv slice is staged.
//
// • windows.aarch64 — androidx.sqlite:sqlite-bundled-jvm 2.6.2 (and
// even 2.7.0-alpha05) lacks a windows_arm64 sqliteJni.dll. The
// bundled driver fails Room init with "Cannot find a suitable
// SQLite binary for windows 11 | aarch64", which we cannot work
// around without building the native ourselves. Windows 11 ARM
// can run the x64 msix under Prism emulation in the meantime —
// re-enable once Google ships the win-arm64 native upstream.
machines = [
"windows.amd64",
"mac.amd64", "mac.aarch64",
"linux.amd64.glibc",
]
// Per-arch libmpv staged by `./gradlew :composeApp:mpvSetupAll`. Each
// per-machine installer carries only the slice it actually needs.
// MpvLibrary resolves this `mpv/` folder by walking up from the JAR
// location — Conveyor does not set compose.application.resources.dir, so
// the packaged app cannot rely on that property.
windows.amd64.inputs += { from = "mpv-natives/windows-x64", to = "mpv" }
mac.amd64.inputs += { from = "mpv-natives/macos-x64", to = "mpv" }
mac.aarch64.inputs += { from = "mpv-natives/macos-arm64", to = "mpv" }
linux.amd64.inputs += { from = "mpv-natives/linux-x64", to = "mpv" }
// --- Per-OS overrides -----------------------------------------------------
// Linux: produce the relocatable directory tree (`linux-app` task) only.
// Conveyor 2.0 dropped native AppImage support — we wrap the tree with
// appimagetool via `./gradlew :desktopApp:packageConveyorAppImage` to
// ship a one-for-all-distros .AppImage. Set `targets = []` so the `site`
// task doesn't try to emit .deb / .tar.gz that we don't ship anyway.
linux.amd64.targets = [ ]
// NOTE: we don't ship the Conveyor Windows .zip (duplicates msix
// payload), .appinstaller (we don't host an update site, URL is 404),
// or .exe installer wrapper (also fetches the missing .appinstaller
// and fails with HRESULT 0x80190194). Setting
// `windows.<arch>.targets = ["windows-msix"]` has no effect on the
// `site` task for Windows machines (verified locally), so we filter at
// the workflow upload step instead and bundle the .msix with our own
// scripts/windows/install.bat for offline install.
mac {
info-plist.LSApplicationCategoryType = "public.app-category.music"
info-plist.UIBackgroundModes = [ "audio", "fetch", "processing" ]
// Turn off Apple's "nano" malloc zone — the macOS counterpart of the
// MALLOC_ARENA_MAX cap the AppImage's AppRun sets for glibc.
//
// The nano zone serves allocations under 256 bytes from its own region and
// has a history of not coalescing what it frees, so the region only grows;
// Electron and Chrome both hit this. mpv/FFmpeg allocate small structures
// constantly on every track change, which is exactly that pattern.
//
// LSEnvironment is applied by LaunchServices, so it covers Finder/Dock/
// Spotlight/`open` launches — i.e. every normal launch of an installed
// .app — but NOT running Contents/MacOS/... directly from a shell.
//
// Declaring this dict also pins the process PATH to the bare
// "/usr/bin:/bin:/usr/sbin:/sbin". Checked before adding: the only
// ProcessBuilder use on this path is the Windows-only powershell/wmic VM
// probe in DesktopApp.kt, and link opening goes through Desktop.browse(),
// which LaunchServices resolves without consulting PATH. Revisit this if
// the macOS build ever shells out to a binary outside those four dirs.
info-plist.LSEnvironment.MallocNanoZone = "0"
// Raised from the implicit 11.0 when the desktop backend moved from VLC to mpv.
// mpv's own macOS release builds target macOS 15: 96 of the 98 bundled arm64 dylibs
// declare minos 15.0, and on Intel libmpv itself does — so Conveyor refuses to package
// an app claiming 11.0 ("Required macOS version mismatch"). VideoLAN still built for
// older systems, which is the only reason 11.0 worked before. There is no mpv artifact
// for macOS < 15 covering both architectures, so this is the floor.
info-plist.LSMinimumSystemVersion = 15.0
}
windows {
start-menu.group = "SimpMusic"
// DEBUG ONLY — remove before shipping a release.
// A Windows GUI binary has no console attached, so everything the app writes to
// stdout/stderr is discarded and a startup failure leaves nothing to look at.
// This attaches a console window that shows both.
// console = true
}
linux {
// Entries belong INSIDE the "Desktop Entry" group — that group is the .desktop
// file's real section, and it is where Conveyor puts Name/Exec/Icon/Comment.
// These three used to sit one level up (desktop-file.Categories, etc.), which
// put them beside the group rather than in it, so none of them reached the
// generated file — same silent-misplacement bug as url-schemes above.
desktop-file."Desktop Entry" {
"Comment[en]" = "A FOSS YouTube Music client"
Categories = "AudioVideo;Audio;Player;Music;"
// Must match the runtime WM_CLASS forced by forceLinuxWmClass() in
// desktopApp/.../Main.kt. Was "java-lang-Thread" (a stale guess that broke
// once AWT started initializing on a coroutine worker thread).
StartupWMClass = "SimpMusic"
}
}
// --- Build settings -------------------------------------------------------
compression-level = low
jvm {
modules = "ALL-MODULE-PATH"
// extract-native-libraries = true // disabled: duplicates the bundled
// natives by extracting them flat while keeping the original tree.
// Not needed — MpvLibrary walks up from the JAR location to find mpv/.
options += "--add-opens=java.base/java.nio=ALL-UNNAMED"
// Without an explicit ceiling the JVM sizes its heap at 1/4 of physical RAM,
// so on a 32 GB machine it will happily grow to several GB before the GC feels
// any pressure — which is why resident memory sat around 1 GB. A music player's
// live set is nowhere near that; the cap makes the GC collect on a sane cadence.
options += "-Xmx512m"
// The G1 heap-trim trio (-XX:MinHeapFreeRatio=20, -XX:MaxHeapFreeRatio=40,
// -XX:G1PeriodicGCInterval=60000) used to live here, handing the unused half of the
// heap back to the OS (measured: 204 MB committed vs 104 MB live). It was removed
// 2026-08-28, NOT because it stopped being right: Conveyor's launcher packs the JVM
// options and the computed app arguments into a fixed 16384-byte buffer, the quickjs
// dependency's jars pushed the total over it ("Your JVM arguments and constant app
// arguments together are too large"), and these three flags were the only bytes that
// could go without opening modules or dropping the -Xmx cap. Idle RSS will sit a bit
// higher until Hydraulic enlarges the buffer — put the trio back when that ships.
}
jvm.mac.options += "--add-opens=java.desktop/sun.awt=ALL-UNNAMED"
jvm.mac.options += "--add-opens=java.desktop/sun.lwawt=ALL-UNNAMED"
jvm.mac.options += "--add-opens=java.desktop/sun.lwawt.macosx=ALL-UNNAMED"
// Linux: allow forceLinuxWmClass() in Main.kt to reflectively overwrite
// sun.awt.X11.XToolkit.awtAppClassName so the dock shows "SimpMusic" instead
// of the coroutine-worker class name. JDK 17+ blocks setAccessible on sun.*
// without this open, and the reflection then silently no-ops.
jvm.linux.options += "--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED"
}
conveyor.compatibility-level = 21
// Loosen disk cache requirement (default 5 GB free) — local dev machines
// often have less headroom while caches keep growing. CI runners with
// fresh disks won't be affected.
conveyor.disk-cache.minimum-free-disk-space = 1 GB