carrier/scripts/devbox-libs.sh

61 lines
2.2 KiB
Bash
Executable file

#!/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}"