Wayland-enabled, bionic-native Hangover (Wine + FEX WoW64) for Android arm64, built in CI and published as Release assets for the Piperella Wayland compositor.
Android apps targeting API ≥ 29 can't execve() app-data binaries; the only legal
launch path is /system/bin/linker64 <elf>, and linker64 loads bionic ELFs,
not glibc. Upstream Hangover ships a glibc build, so it can't be launched that
way. Termux builds Hangover against bionic (NDK + llvm-mingw), but its package
lacks winewayland.drv, ships stale FEX backends, and isn't hardened for the
linker64/W^X launch. This repo fixes all of that and publishes the result.
One GitHub Release per successful build, each marked latest, so a stable URL
always resolves to the newest build:
https://github.com/piperella/Piperella-Hangover-Bionic/releases/latest/download/hangover-bionic-aarch64.tar
The tar holds the bionic hangover-wine_<ver>_aarch64.deb plus the bionic
runtime-dependency .debs it links against. The Piperella app downloads it the
same way it already downloads upstream Hangover.
Everything is applied as idempotent overlays on the upstream termux recipe at build time (nothing is forked or version-pinned), so it survives upstream updates.
- Wayland (
patches/enable-wayland.sh) — addslibwayland/libxkbcommon+--with-wayland, sowinewayland.drvis built and talks to the compositor. - Audio (
patches/enable-pulseaudio.sh) — adds thepulseaudiodep so Wine buildswinepulse.drv(no moremmdevapi:init_driver No driver), and ships the PulseAudio daemon + libpulse + Android sink modules (module-sles-sink/module-aaudio-sink) in the tar. The app runs the daemon with an OpenSL ES / AAudio sink and points Wine at it via$PULSE_SERVER. - Real FEX backends (
patches/install-fex-backends.sh+build-fex-arm64ec.sh) — the upstream package silently drops the x86→ARM64 recompiler DLLs, and Hangover's bundled ones are a stale FEX that crash-loops 64-bit/arm64ec apps (Steam's CEF, FEX-Emu #4493). CI compiles fresh FEX-2607 (libwow64fex+libarm64ecfex, with the #4493 MEM_RESET fix) and forces them into the package;wowbox64(Box64) is kept from the bundle. - Runtime hardening for the
linker64launch:fix-wineserver-dir.sh— wineserver/temp dir honors$XDG_RUNTIME_DIR/$TMPDIRinstead of a baked Termux path; dropswine-preloader(unloadable at API 36).fix-nls-dir.sh— wineserver resolves its NLS/install dir via$WINELOADER(not/proc/self/exe, which islinker64).fix-exec-wx.sh— PE image loader backs executable sections with anonymous memory (execmem), avoiding theexecmodSELinux denial under Android W^X.fix-rpc-contexthandle.sh/fix-rpc-ctx-marshall.sh— two NULL/low-pointer guards in RPC client context-handle unmarshalling, so a bad handle raisesRPC_X_SS_CONTEXT_MISMATCH(or is redirected to a scratch) instead of crashing the 64-bit Steam client (c0000005).fix-vulkan-lib-env.sh— win32u's host Vulkan loader honors$PIPERELLA_VULKAN_LIB, so the app can point Wine at a non-public Vulkan driver (our AdrenoTools→Turnip bridge) instead of the allowlisted systemlibvulkan.so.1. Unset → default behaviour unchanged.inject-steamwebhelper-args.sh—kernelbaseCreateProcessInternalWappends$STEAMWEBHELPER_EXTRA_ARGStosteamwebhelper.exe(and its gpu/renderer/utility children), so extra Chromium switches (e.g.--disable-direct-composition) can be tested as a client-side env change instead of a rebuild. Steam doesn't forward those flags itself. Unset → default behaviour unchanged.add-winewayland-xdg-foreign.sh— cross-process window presentation forwinewayland.drvviaxdg-foreign-unstable-v2: an owner process exports its toplevel and a child process (e.g. Steam'ssteamwebhelper.exeCEF UI, which renders in a separate Wine process andSetParents intosteam.exe) imports the handle andset_parent_ofs, so the child maps as a realxdg_toplevelunder the compositor instead of a black screen. Handle transported via a cross-process global atom in a window property.
.github/workflows/build.yml— clones termux-packages (latest), builds fresh FEX, applies the overlays, builds with Termux's pinned Docker builder (free unlimited Actions on a public repo), gates the result, and publishes the Release. The Hangover version is read from the recipe, not hardcoded.inspect-deb.sh— release gate: fails the build unless the.debcontainswinewayland.drv, all three WoW64 backends (as PE), fresh (non-stale) FEX with aFEX_BUILD_INFOrecord, and the runtime fixes above. A broken package is never published.fetch-runtime-deps.sh— resolves + downloads the bionic.sodependency closure from the Termux apt repos (now includingpulseaudio+ its closure).docs/FEX-CODE-CACHE.md— investigation: FEX-2607 has no persistent code cache (AOTIR/ObjectCache removed upstream), so cold-start JIT cost can't be cached in this build; see the doc for evidence and options.build.sh/install-host-deps.sh— optional local (no-Docker) native build.
Push to patches/** (or Actions tab → Run workflow) to build + publish. To
build a different Hangover version, dispatch with another termux_ref.