# PyInstaller runtime hook. The frozen app runs with LD_LIBRARY_PATH pointing # at its bundled libraries, and programs it starts inherit that: Flet's # desktop client then loads the bundled (older) libstdc++ instead of the # system's and won't start ("GLIBCXX_3.4.29 not found"). Give them the # original value back; the app itself has already loaded what it needs. # # Flet's window also needs libsecret, which isn't part of GTK and some # systems don't install ("libsecret-1.so.0: cannot open shared object file"). # The build bundles it in FallbackLibs, with libgcrypt and libgpg-error, which # it needs; the ones this system lacks (only those) are offered to what the # app starts, after the original path. import os import subprocess import sys def SystemHas(Name): """Whether the system itself has a library: asked of its linker cache and standard folders, not dlopen, which would also find this bundle's own copies (PyInstaller adds what bundled libraries need).""" for Folder in ("/usr/lib64", "/usr/lib", "/lib64", "/lib", "/usr/lib/x86_64-linux-gnu", "/lib/x86_64-linux-gnu"): if os.path.exists(os.path.join(Folder, Name)): return True try: Cache = subprocess.run(["ldconfig", "-p"], capture_output=True, text=True, timeout=10, env={"PATH": "/usr/sbin:/usr/bin:/sbin:/bin"}).stdout except (OSError, subprocess.SubprocessError): return False return any(Line.strip().startswith(Name + " ") for Line in Cache.splitlines()) Paths = [os.environ["LD_LIBRARY_PATH_ORIG"]] if os.environ.get("LD_LIBRARY_PATH_ORIG") else [] Bundle = getattr(sys, "_MEIPASS", "") Fallback = os.path.join(Bundle, "FallbackLibs") if sys.platform.startswith("linux") and os.path.isdir(Fallback): InUse = os.path.join(Bundle, "FallbackLibsInUse") os.makedirs(InUse, exist_ok=True) for Name in ("libgpg-error.so.0", "libgcrypt.so.20", "libsecret-1.so.0"): if not SystemHas(Name) and not os.path.lexists(os.path.join(InUse, Name)): os.symlink(os.path.join(Fallback, Name), os.path.join(InUse, Name)) if os.listdir(InUse): Paths.append(InUse) if Paths: os.environ["LD_LIBRARY_PATH"] = os.pathsep.join(Paths) else: os.environ.pop("LD_LIBRARY_PATH", None)