#!/usr/bin/env sh # Devbox installs library packages as their -dev outputs, which carry no # shared objects; the outs they reference do. Put the GUI stack's real lib # dirs on LD_LIBRARY_PATH — wayland, xkbcommon, EGL, vulkan, gtk — all of # which are dlopened or linked at runtime, so neither rpath nor a # DT_NEEDED scan can cover them. Package names match exactly up to the # version suffix: a substring match would drag glibc onto the path for # every process in the shell ("glib" matches "glibc") and crash them. set -e if [ -z "$DEVBOX_PACKAGES_DIR" ]; then return 0 2>/dev/null || exit 0 fi MANIFEST="$DEVBOX_PACKAGES_DIR/manifest.json" [ -f "$MANIFEST" ] || return 0 2>/dev/null || exit 0 libs=$(python3 - "$MANIFEST" <<'EOF' import json, os, re, subprocess, sys WANTED = { "wayland", "libxkbcommon", "libglvnd", "vulkan-loader", "mesa", "gtk4", "libadwaita", "glib", "pango", "cairo", "gdk-pixbuf", "graphene", "harfbuzz", "libepoxy", "freetype", "fribidi", "fontconfig", "libpng", "pixman", "libxml2", "libtiff", "libjpeg_turbo", } def pkg_name(path): base = os.path.basename(path.rstrip("/")) # "pango-1.56.0-dev" -> "pango" m = re.match(r"([A-Za-z0-9_.-]+?)(-[0-9].*)?$", base) return m.group(1).rstrip("-") if m else base manifest = json.load(open(sys.argv[1])) seen, dirs = set(), [] paths = [p for el in manifest["elements"].values() for p in el.get("storePaths", [])] for path in paths: candidates = [path] try: candidates += subprocess.run( ["nix-store", "-q", "--references", path], capture_output=True, text=True, ).stdout.split() except OSError: pass for cand in candidates: lib = os.path.join(cand, "lib") if lib in seen or not os.path.isdir(lib): continue if pkg_name(cand) not in WANTED: continue if any(name.endswith(".so") or ".so." in name for name in os.listdir(lib)): seen.add(lib) dirs.append(lib) print(":".join(dirs)) EOF ) export LD_LIBRARY_PATH="${libs}:${DEVBOX_PACKAGES_DIR}/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" # GTK finds schemas, icons and themes through XDG_DATA_DIRS. export XDG_DATA_DIRS="${DEVBOX_PACKAGES_DIR}/share:${XDG_DATA_DIRS:-/usr/share:/usr/local/share}"