- Shell 91.8%
- CMake 7.7%
- Roff 0.5%
| overusr/lib | ||
| .gitignore | ||
| build-inner.sh | ||
| build.sh | ||
| fexwrap | ||
| LICENSE | ||
| README.md | ||
| toolchain_x86_32.cmake | ||
| toolchain_x86_64.cmake | ||
fexwrap
A janky temporary setup to run x86_64 Flatpaks (namely Steam) with FEX-Emu on aarch64.
"But at least we don't need a random distro rootfs anymore! xD"
How the fsck does it work and can it be turned into something less hacky?
All FEX itself needs to run is to have its own binaries (and a couple native aarch64 shared libraries it depends on) to be present on an otherwise x86_64 rootfs. To run with Full Potential™ i.e. with library forwarding (thunks), it just needs more host native libraries: the graphics drivers, libwayland, libdrm, etc.
The Freedesktop runtime being a usrmerged multiarch system, it's almost trivial to mount the runtimes into each other.
First, we just need the x86_64 org.freedesktop.Platform to include an empty lib/aarch64-linux-gnu mountpoint and a lib/ld-linux-aarch64.so.1 -> aarch64-linux-gnu/ld-linux-aarch64.so.1 symlink.
Something that, interestingly, the Sdk already has! — but we add that in an overlay mount.
Then we mount the lib/aarch64-linux-gnu from the aarch64 Platform into the x86_64 one, mount the /fex overlay that contains our FEX build, and wrap the target program launch in a /fex/bin/FEX invocation.
Boom, done, we don't even need any binfmt registration (!!!) since we don't ever exec aarch64 executables!
What this current setup does with that mechanism is, basically:
- for the FEX build process (
build.sh+build-inner.sh) we just run rawbwrap, using convenient/var/lib/flatpak/runtime/org.freedesktop.Sdk/x86_64/25.08/active/filestype paths to mount everything; - for actually running the flatpaks, we set
FLATPAK_BWRAPto a wrapper scriptfexwrapthat injects a bunch of arguments for mounting overlays and launching under/fex/bin/FEX.
So the plan to make it more official would roughly look like the following:
- add
lib/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1to the x86_64Platform(trivial) - teach Flatpak to mount the aarch64
Platform'slibsubdirectory there (harder / more controversial) or just build anorg.freedesktop.Sdk.Compat.aarch64/x86_64(potentially easier but shame it would waste disk space on repeating the exact same files from the aarch64Platform) - add an extension point for emulators, such as
lib/emuor whatever (easy but with bikeshedding potential) - package FEX as an extension using said extension point (not upstream's job anyway)
- teach Flatpak about running emulators (interesting)
- teach Flatpak about mounting the native host GL extension, to enable thunks for GPU drivers (complicated by ldconfig, see bottom of this readme..)
Building and running
Getting x86 Mesa with the right driver
Unless you're running on a desktop board with a discrete GPU, you'll need this step. We'll be using mesa-git just because it's packaged as a nicely separate repo.
Either on a separate x86_64 machine or with qemu-user-static enabled,
build mesa-git-extension editing elements/mesa.yml to use the GPU drivers your aarch64 machine needs that might be missing, e.g.
- target_arch == "i686" or target_arch == "x86_64":
gallium_drivers: softpipe,llvmpipe,zink,freedreno
vulkan_drivers: swrast,freedreno
Build it for both i686 and x86_64, install it on your aarch64 machine.
If you're lazy, trust me, and are running on a Qualcomm Snapdragon device, you can instead download my build:
- mesa-git-for-emu.32.flatpak (sha256:
846f0a6a880cbcdd165190c113bed6db8a52abc8416659888bb4a02f424d66cd) - mesa-git-for-emu.64.flatpak (sha256:
805daf59db2183ee32932339ae15a588be81c1b3a5760359dc9640c3518fc5f6)
And just flatpak install it.
Well, also pin it to prevent automatic uninstallation:
flatpak pin org.freedesktop.Platform.GL.mesa-git
flatpak pin org.freedesktop.Platform.GL32.mesa-git
Building FEX for the Freedesktop Runtime
Get the build prerequisites (yes we're building with thunks / library forwarding support!):
flatpak install org.freedesktop.Sdk/aarch64/25.08 org.freedesktop.Sdk.Extension.llvm21/aarch64/25.08 org.freedesktop.Sdk/x86_64/25.08 org.freedesktop.Sdk.Compat.i386/x86_64/25.08 org.freedesktop.Sdk.Extension.toolchain-i386/x86_64/25.08
Also git clone https://github.com/FEX-Emu/FEX in this directory here.
Run ./build.sh to build! Hopefully it just works!
Edit fexwrap to make FEXWRAP_CHECKOUT actually point to the path to here (!!!)
(Yes, there's no good installability, intentionally since it's a temporary hack and so using it should remain awkward :p)
Running Steam
Get Steam:
flatpak install --arch=x86_64 flathub com.valvesoftware.Steam
And finally, run:
FLATPAK_BWRAP=<insert path to here>/fexwrap FLATPAK_GL_DRIVERS=mesa-git flatpak run --arch=x86_64 --env=SHARED_LIBRARY_GUARD=0 com.valvesoftware.Steam
Sometimes, it doesn't run on the first attempt (0.o) and the script freezes early before launching everything, in which case Ctrl-C and retry.
Thunks are kinda cursed
You can edit overlay/fex/share/fex-emu/Config.json to enable thunks, for example:
{
"ThunksDB": { "GL": 1 },
"Config": { "SilentLog": "0", "OutputLog": "stderr" }
}
and I've been able to run at least Portal 2 before even having built an x86_64 Mesa with the driver for my machine (freedreno).
But there are some unresolved cursed issues with thunks in this setup for now:
- Somehow, cannot disable GL thunk just for steamwebhelper, because it stops loading with "libGL.so.1 not found"?!
With
"GL": 0in the global config and with"GL": 1in the steamwebhelper appconfig it loads fine. But the combo of"GL": 1in Config and"GL": 0in steamwebhelper AppConfig results in loading failure. Can leave it on and pass-cef-disable-gpuinstead? :/ libGL(GLVND) normally finds the actuallibGLX_mesa.soin this environment using ldconfig (/run/flatpak/ld.so.conf.d/runtime-001-org.freedesktop.Platform.GL.default.confis what actually points to/usr/lib/$ARCH-linux-gnu/GL/default/lib) but ldconfig is not cross-arch: if you feed the x86_64 one an aarch64 path, it ignores those libraries and warns about unknown architecture. So makingHostThunks/libGL-host.sofind aarch64 Mesa is hard.LD_LIBRARY_PATHis fully overwritten a thousand times on the way to the actual game binary by various Steam runtime scripts.HostEnvdoes not seem to affect this (I guess the rtld doesn't reread the environment all the time). The cursed workaround is to edit~/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/common/SteamLinuxRuntime/var/steam-runtime/run.shchangingexport LD_LIBRARY_PATH="$steam_runtime_library_paths"toexport LD_LIBRARY_PATH="$steam_runtime_library_paths:/usr/lib/aarch64-linux-gnu/GL/default/lib"