# 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 vtabs" 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 vtabs in a throwaway headless compositor" depends = ["build-debug"] run = "nix develop --command ./shot.sh" [tasks.install] description = "Install vtabs 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/vtabs" apps="$data/applications" icons="$data/icons/hicolor/scalable/apps" gcroots="$data/vtabs/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 VTABS_GSETTINGS_SCHEMA_DIR)" datadirs="$(nix develop --command printenv VTABS_RUNTIME_DATA_DIRS)" giomodules="$(nix develop --command printenv VTABS_GIO_MODULE_DIR)" eglvendor="$(nix develop --command printenv VTABS_EGL_VENDOR_DIR)" dridrivers="$(nix develop --command printenv VTABS_DRI_DRIVERS_PATH)" gbmbackends="$(nix develop --command printenv VTABS_GBM_BACKENDS_PATH)" mkdir -p "$bindir" "$libexec" "$apps" "$icons" "$gcroots" install -m755 zig-out/bin/vtabs "$libexec/vtabs" # 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/vtabs" < "$apps/dev.greyson.vtabs.desktop" install -m644 dist/dev.greyson.vtabs.svg "$icons/dev.greyson.vtabs.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/vtabs" \ | 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/vtabs" 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/vtabs" rm -rf "$HOME/.local/libexec/vtabs" rm -f "$apps/dev.greyson.vtabs.desktop" rm -f "$data/icons/hicolor/scalable/apps/dev.greyson.vtabs.svg" # Dropping the roots lets Nix reclaim the runtime closure on its next GC. rm -rf "$data/vtabs" 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 vtabs" '''