Fork of VHSgunzo/sharun. Run dynamically linked ELF binaries everywhere (musl and glibc).
This fork is used by the Anylinux-AppImages project. It is intended for AppImage deployment only.
-
Extra architectures: Builds for
riscv64,loongarch64,powerpc64(big-endian) andppc64lein addition tox86_64andaarch64. Uses a forked userland-execve with support for these architectures. -
SHARUN_MESA_PATH: Point to an external mesa installation (withlib/andshare/subdirs). Allows switching mesa versions at runtime. -
bwrap-wrapper: When
sharunis invoked asbwrap, it interceptsbwraparguments to preserve essential paths and env variables ($APPDIR,/tmp,/proc,$SHARUN_DIR,$PATH). Rewrites hardcoded command paths to their AppDir equivalents. Falls back to systembwrapif real bwrap wasn't deployed. This lets applications that sandbox themselves with bwrap (example WebKitGTK) work correctly as AppImage. -
gio-launch-desktophandler: Whensharunis hardlinked asgio-launch-desktop, it setsGIO_LAUNCHED_DESKTOP_FILE_PIDand launches the target. Required for AppImages that rely on GIO-based.desktopfile launching. -
AppRun.shsupport: If anAppRun.shexists in the sharun directory and sharun is hardlink as theAppRun, it executesAppRun.shwith thedashin the sharun directory if there is one, otherwise with anysh/bashfound in the system or inPATH. With adashthere, theAppRunhas no/bin/shdependency. Everysharun+helper-libs-<arch>.tarhas a static dash in it (dash), built bytools/build-dash.sh(BSD-3-Clause, the notice is in the tar asdash-COPYINGand in the repo atlicenses/dash-COPYING). It is dash 0.5.13.5 withtools/dash-pattern-replace.patch, which adds${var/pat/str},${var//pat/str},${var/#pat/str}and${var/%pat/str}like in bash (tools/test-shell.shchecks them against output made with bash). Otherwise it is plain POSIX sh: no[[ ]],${var:off:len},sourceorfunction,${@/pat/str},${@/#pat/str}and${@/%pat/str}only change the first positional parameter (//changes all), andecho -eprints the-e, these do not give an error. Hooks must use the hostsed,awkandln, dash has no applets, and a hook that runssh -c ...itself still gets the shell found inPATH. -
Old kernel compatibility layer (
x86_64only): Runs AppImages built against a modern glibc on kernels far older than that glibc assumes, down to Linux 2.6.17 (Ubuntu 6.10). Modern glibc (e.g. the--enable-kernel=4.4Arch build) both executes instructions old kernels do not support and calls syscalls that do not exist yet. The layer catches the resultingSIGILLand emulates the instruction (XGETBVetc.), and handles the offending syscalls at trace time. Most are rewritten to an older equivalent; the ones no single older call can answer are emulated with a short sequence of calls made inside the traced process. Each is gated on a one-time probe, or on the kernel version when there is nothing reliable to probe:FUTEX_WAIT_BITSET/FUTEX_WAKE_BITSET(2.6.25) toFUTEX_WAIT/FUTEX_WAKE, andFUTEX_CLOCK_REALTIMEwaits (2.6.29) to plain ones with a relative timeout: on 2.6.25-2.6.28 a realtime wait is rejected withEINVAL, which glibc answers withfutex_fatal_error()instead of falling back.pipe2(2.6.27) topipe.statx(4.11) tonewfstatat/fstat, translatingstruct statback tostruct statx(Qt6 has no fallback whenstatxfails).getrandom(3.17) filled from/dev/urandom(some kernels answer it with their own syscall number, which makes Rust's std panic).ppoll(2.6.19; the x86_64 number was reserved in 2.6.16 but only wired up in 2.6.19) topoll.epoll_pwait(2.6.19) emulated asrt_sigprocmask+epoll_wait+rt_sigprocmask, so the caller's signal mask is in force during the wait and put back afterwards, including when the wait fails. Dropping the mask instead loses wakeups the application is waiting for.epoll_create1(2.6.27) toepoll_create.prlimit64(2.6.36) togetrlimit/setrlimitfor the calling process (modern glibc has no 32-bit fallback, so the runtime's stack and file-descriptor limit lookups fail outright).pwritev/preadv(2.6.30) emulated aslseek+writev/readv(Bun writes buffered output through the offset form).F_DUPFD_CLOEXEC(2.6.24) toF_DUPFDplusFD_CLOEXEC(Bun builds its lazystdout/stderrgetters this way).eventfd/eventfd2(2.6.22/2.6.27) emulated with a self-connectedAF_UNIXsocket, andtimerfd_create/timerfd_settime/timerfd_gettime(2.6.25) with a pipe the tracer writes to when a deadline passes (the timerfd shape needs/procmounted for the traced process, the eventfd one does not).- the termios2 ioctls
TCGETS2/TCSETS2/TCSETSW2/TCSETSF2(2.6.20) toTCGETS/TCSETS*, decoding the line speed out ofc_cflagfor the read side (Bun probes withTCGETS2, and concludes there is no terminal when it fails). - clock ids the kernel predates (
CLOCK_MONOTONIC_RAW2.6.28,CLOCK_REALTIME_COARSE/CLOCK_MONOTONIC_COARSE2.6.32,CLOCK_BOOTTIME2.6.39) to the closest clock it has. ENOSYSis forced for newer syscalls a pre-2.6.19 kernel answers with its own syscall number instead of failing (rseq,clone3,openat2,faccessat2,signalfd/signalfd4,accept4,dup3,inotify_init1, and any other number above its syscall table). Calls the layer translated are left alone, since their result is the real one.
It is enabled automatically on kernels older than 4.0 or when
statxis missing; setSHARUN_OLD_KERNEL_COMPAT=1to force it on and=0to disable. It supports no 32-bit application: a 32-bit process is traced but never translated, so an application that runs 32-bit binaries gets nothing from this layer and pays for the tracing. There is no AppDir-level test for it -- the per-tracee check is what keeps a 32-bit process out of the rewrite tables, wherever it came from.SHARUN_OLD_KERNEL_COMPAT_DEBUG=1prints each translation to stderr;SHARUN_OLD_KERNEL_COMPAT_DEBUG_ALL=1also prints every syscall and its result, which produces tens of megabytes in seconds and slows the traced program down enough to change its timing. While an emulation is running the layer holds back any signal that arrives, so application code cannot run in the middle of it, and delivers it when the emulation is done. On kernels with seccomp-bpf (3.5+) only the affected syscalls are intercepted, but seccomp mode setsno_new_privs, so setuid helpers cannot gain privileges; older kernels fall back to tracing every syscall with ptrace, which is much slower. The tracer is only installed fromAppRun, never from thebin/*hardlinks. Kernels older than 2.6.16 cannot be supported because the AppImage runtime itself needs the*atsyscalls (for exampleopenat). -
Directory structure: Uses
lib/lib32directly instead ofshared/lib/shared/lib32. Fixes libraries that look for a relative../sharedirectory and can't find it. -
Payload directory: the real programs of the
bin/<name>hardlinks can live in.bin/<name>instead ofshared/bin/<name>, sharun looks in.binfirst. In.bina program keeps its name in/proc/self/exe(and ingetauxval(AT_EXECFN)), and../liband../shareresolve to the AppDir like in a normal install. An AppDir that only has.bin, withoutshared, works. A program that re-execs/proc/self/exefrom a memfd (runcandcrundo it) comes back named after that memfd, so when the exe name finds no payload sharun falls back to the basename of the caller'sargv[0]. -
Additional env vars: Auto sets
LADSPA_PATH,FREI0R_PATH,MLT_REPOSITORY,MLT_PROFILES_PATH,MLT_PRESETS_PATH,GS_LIB,OPENSSL_CONF,QT_XKB_CONFIG_ROOT,PEAS_PLUGIN_LOADERS_DIRand likely more in the future. -
Bun workaround: Detects Bun binaries and uses alternative execution paths so they run correctly via temp dynamic linker in
/tmp. (These break when executed with the dynamic linker directly). -
sharun-preloaddir: Every library found in$SHARUN_DIR/lib/sharun-preload/(orlib32/sharun-preload/for 32-bit binaries) is preloaded automatically, no.preloadfile needed. The classic.preloadfile method keeps working and its entries are resolved by name, so it can also reference libraries that live insidesharun-preload/. Files that are not*.soare ignored, andpath-mapping.sois only preloaded whenPATH_MAPPINGis set, which allows shipping the library unconditionally. -
Prebuilt helper libraries: The preload libraries used by quick-sharun originally lived in the Anylinux-AppImages repo and were compiled on the host at deployment time. They are now kept here (see
lib/) and built by the CI withzig ccagainst a glibc 2.31 floor (2.36forloongarch64, the first glibc version that supports that architecture). This guarantees they load inside any AppImage regardless of the glibc that was deployed, instead of depending on whatever glibc the CI host happened to have.ppc64(big-endian) is the exception: it is ELFv2 but zig'spowerpc64-linux-gnuglibc stub is the ELFv1 one, which archlinuxpower's glibc does not define, so the ppc64 preloads are linked against a big-endian build of zig's ppc64le ELFv2 stub instead (see #11). The libraries:anylinux.so- main preload library: unsets problematic environment variables for child/external processes, restores portable home/config/data/cache dirs, fixes broken host locales, redirectsbindtextdomainto the bundled locales, forces NSS to only use bundled modules, can block libraries from being dlopened withANYLINUX_DO_NOT_LOAD_LIBSand can change the running program name withOVERRIDE_ARGV0.gtk-fix-nonsense.so- forces the GTK window class / application id toGTK_WINDOW_CLASS, fixing broken desktop integration in Wayland where GNOME uses a different window class than in X11. It also fixesgi_repository_require_private()/g_irepository_require_private(), which only search the private directory they are given: a/usrprefix is remapped to$APPDIRso apps that look up a compiled-in libdir find the typelibs bundled in the appimage instead of the host copy, and the lookup falls back to the normal typelib search path (GI_TYPELIB_PATH) when the bundle misses. The host private directory is never used; only that fallback can still reach the default host girepository dir. Safe to preload into applications with or without GTK, GLib or glycin.glycin-fix.so- disables the bwrap sandbox of GNOME's glycin image loader, which never works inside an AppImage because glycin incorrectly binds AppImage paths to bwrap, resulting in crashes. Only intended for applications that ship real glycin (libglycin-*), quick-sharun preloads it only for those, there is nothing to fix in glycin-ng based applications since it has a working sandbox. Glycin is only reached viadlsym/dlopen(RTLD_NOLOAD), so the library does not affect applications that do not make use of glycin at all. Note that with the library preloadeddlsym(RTLD_DEFAULT, "gly_loader_new")returns a non-NULL wrapper even before glycin is loaded in, callers must check the returned loader for NULL.path-mapping.so- vendored from pathmap, only the preload library, the standalone tracer binary is not built. Maps hardcoded paths at runtime withPATH_MAPPING/PATHMAP_*env variables, sharun only preloads it whenPATH_MAPPINGis set and it replaces the git clone + C compiler build that deployments used to carry out.
The
stubs/subdirectory holds two dummy libraries that are not preloaded:libsystemd.so.0andlibsndfile.so.1. They export the complete ABI of the real libraries but answer with safe "not available" values, so applications that only get them transitively throughlibpulse/libdbusdo not need to ship systemd or the libsndfile codec chain. Seelib/stubs/README.mdfor what is implemented and how the manifests are generated.quick-sharundecides per application whether to use them and deletes the directory otherwise.Each release contains, per architecture:
sharun-$ARCH- the sharun binary.sharun+helper-libs-$ARCH.tar- sharun plus the prebuilt libraries in a single tar (sharun,anylinux.so,gtk-fix-nonsense.so,glycin-fix.so,path-mapping.so, and thestubs/directory), so consumers get everything with one download and no C compiler is needed on the build host.- A
.sha256checksum file for each of the released assets.
-
lib4bin: Has been removed. Use quick-sharun instead. -
xdg-openwrapper: Has been removed.quick-sharunuses anylinux.so which fixes the same issues that the wrapper did and better. (Works on all external binaries, not justxdg-open). -
sharun-aio: The all-in-one binary with bundledlib4bindependencies is removed. -
sharun-lite: Removed. -
wrappe integration: No
--with-wrappe. Usequick-sharun --make-static-bininstead. -
Python packing with uv: No
--with-pythonsupport for embedding python/pip packages.quick-sharunonly supports deploying the system python installation due to many bugs with uv python. -
Strace mode: No
stracefor library detection at runtime.quick-sharunusesLD_DEBUG=libsinstead (reduces overdeployment of libraries).