Files
playpen/mise.toml
T
2026-08-11 14:26:12 -04:00

143 lines
5.7 KiB
TOML

# Nix supplies the whole toolchain (Zig, GTK, libadwaita), so there is
# nothing for mise to install; these tasks just drive it.
[tasks.build]
description = "Build a release binary into zig-out/bin"
run = "nix develop --command zig build -Doptimize=ReleaseFast"
[tasks.build-debug]
description = "Build a debug binary (leak checking, safety checks)"
run = "nix develop --command zig build"
[tasks.run]
description = "Build and run playpen"
run = "nix develop --command zig build run"
[tasks.fmt]
description = "Format all Zig source"
run = "nix develop --command zig fmt build.zig src"
[tasks.screenshot]
description = "Screenshot playpen in a throwaway headless compositor"
depends = ["build-debug"]
run = "nix develop --command ./shot.sh"
[tasks.install]
description = "Install playpen into ~/.local with a desktop entry and icon"
depends = ["build"]
run = '''
#!/usr/bin/env bash
set -euo pipefail
data="${XDG_DATA_HOME:-$HOME/.local/share}"
bindir="$HOME/.local/bin"
libexec="$HOME/.local/libexec/playpen"
apps="$data/applications"
icons="$data/icons/hicolor/scalable/apps"
gcroots="$data/playpen/gcroots"
# The binary carries an RPATH into the Nix store, so it runs anywhere, but it
# still has to be told where GTK's GSettings schemas and icon themes live or
# it aborts on a missing schema, where GIO's TLS module lives or every
# https:// page in a web pane fails, and which mesa to render web panes
# through or WebKit's web process dies on startup. Read those paths back out
# of the dev shell that built it rather than hardcoding store hashes.
schemas="$(nix develop --command printenv PLAYPEN_GSETTINGS_SCHEMA_DIR)"
datadirs="$(nix develop --command printenv PLAYPEN_RUNTIME_DATA_DIRS)"
giomodules="$(nix develop --command printenv PLAYPEN_GIO_MODULE_DIR)"
eglvendor="$(nix develop --command printenv PLAYPEN_EGL_VENDOR_DIR)"
dridrivers="$(nix develop --command printenv PLAYPEN_DRI_DRIVERS_PATH)"
gbmbackends="$(nix develop --command printenv PLAYPEN_GBM_BACKENDS_PATH)"
mkdir -p "$bindir" "$libexec" "$apps" "$icons" "$gcroots"
install -m755 zig-out/bin/playpen "$libexec/playpen"
# A launcher script rather than a symlink: a desktop launcher starts the app
# with a minimal environment, so the GTK runtime paths must be set here.
# Existing values are preserved so this composes with the rest of the session.
cat > "$bindir/playpen" <<EOF
#!/bin/sh
# Generated by \`mise run install\` — re-run that instead of editing.
export GSETTINGS_SCHEMA_DIR="$schemas\${GSETTINGS_SCHEMA_DIR:+:\$GSETTINGS_SCHEMA_DIR}"
export XDG_DATA_DIRS="$datadirs:\${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
export GIO_EXTRA_MODULES="$giomodules\${GIO_EXTRA_MODULES:+:\$GIO_EXTRA_MODULES}"
# Web panes render through the mesa this was built against. Mixing it with
# the host's mesa aborts WebKit's web process, so these are set outright
# rather than appended to whatever the session already had.
export __EGL_VENDOR_LIBRARY_DIRS="$eglvendor"
export LIBGL_DRIVERS_PATH="$dridrivers"
export GBM_BACKENDS_PATH="$gbmbackends"
exec "$libexec/playpen" "\$@"
EOF
chmod 755 "$bindir/playpen"
sed "s|@EXEC@|$bindir/playpen|" dist/dev.greyson.playpen.desktop.in \
> "$apps/dev.greyson.playpen.desktop"
install -m644 dist/dev.greyson.playpen.svg "$icons/dev.greyson.playpen.svg"
# Pin the store paths the installed binary links against. Without this a
# later `nix-collect-garbage` deletes GTK and the installed app stops
# starting, with no obvious connection to the command that broke it.
# Nix roots are transitive, so rooting each RPATH entry covers its closure.
rm -f "$gcroots"/*
{
# What the dynamic linker needs, read straight out of the binary.
if command -v readelf >/dev/null; then
readelf -d "$libexec/playpen" \
| sed -n 's/.*R\(UN\)\?PATH.*\[\(.*\)\]/\2/p' \
| tr ':' '\n'
else
echo "warning: readelf not found; only the launcher's own paths are pinned" >&2
fi
# What the launcher points at. These are opened by name at runtime rather
# than linked, so they never show up in the RPATH and would otherwise be
# left for the collector — losing the TLS module breaks https in web panes
# long after the command that deleted it.
printf '%s\n' "$schemas" "$datadirs" "$giomodules" \
"$eglvendor" "$dridrivers" "$gbmbackends" | tr ':' '\n'
} \
| sed -n 's|^\(/nix/store/[^/]*\).*|\1|p' \
| sort -u \
| while read -r path; do
nix-store --realise --add-root "$gcroots/$(basename "$path")" \
--indirect "$path" >/dev/null 2>&1 || true
done
echo "pinned $(find "$gcroots" -maxdepth 1 -type l | wc -l) store paths against garbage collection"
# Let the desktop notice the new entry and icon right away.
command -v update-desktop-database >/dev/null && update-desktop-database -q "$apps" || true
command -v gtk-update-icon-cache >/dev/null && gtk-update-icon-cache -qtf "$data/icons/hicolor" 2>/dev/null || true
echo "installed $bindir/playpen"
case ":$PATH:" in
*":$bindir:"*) ;;
*) echo "note: $bindir is not on your PATH; the desktop entry still works" >&2 ;;
esac
'''
[tasks.uninstall]
description = "Remove everything `install` put into ~/.local"
run = '''
#!/usr/bin/env bash
set -euo pipefail
data="${XDG_DATA_HOME:-$HOME/.local/share}"
apps="$data/applications"
rm -f "$HOME/.local/bin/playpen"
rm -rf "$HOME/.local/libexec/playpen"
rm -f "$apps/dev.greyson.playpen.desktop"
rm -f "$data/icons/hicolor/scalable/apps/dev.greyson.playpen.svg"
# Dropping the roots lets Nix reclaim the runtime closure on its next GC.
rm -rf "$data/playpen"
command -v update-desktop-database >/dev/null && update-desktop-database -q "$apps" || true
command -v gtk-update-icon-cache >/dev/null && gtk-update-icon-cache -qtf "$data/icons/hicolor" 2>/dev/null || true
echo "uninstalled playpen"
'''