diff --git a/docs/development/x86-64-steam-client.md b/docs/development/x86-64-steam-client.md index 1c3161448..aebfe5134 100644 --- a/docs/development/x86-64-steam-client.md +++ b/docs/development/x86-64-steam-client.md @@ -193,8 +193,10 @@ alone would then read as an installed client. reproducible, so a tag is never rebuilt over. The release is never the repo's Latest nor a pre-release: it is a component fetched by tag, not something users install. - Releases so far: `fex-2609-r2` (no thunks), `fex-2609-r3` (thunks), `fex-2610-r1`, `fex-2610-r2`, - `fex-2610-r3`, `fex-2610-r4` (current: in-root resolution when openat2 is missing, exact MAP_32BIT - marking). They were built and published in The412Banner/DroidDeck; up to r3 their tags point at that + `fex-2610-r3`, `fex-2610-r4` (in-root resolution when openat2 is missing, exact MAP_32BIT + marking), `fex-2610-r5` (current: bundles libxxhash, which the Linux runtime does not ship; the + build fails when a program in the package needs a library that is neither bundled nor listed in + `tools/fex/runtime-libs.txt`). They were built and published in The412Banner/DroidDeck; up to r3 their tags point at that repository's `main`, from r4 at the commit each was built from. - **Where the app gets it.** The app downloads FEX from Droid-Deck/DroidDeck-Components, where nothing is uploaded by hand: a new tag is published by `build-fex.yml`, recorded in that repository's `fex.json` diff --git a/docs/progress-log.md b/docs/progress-log.md index 8164052aa..65a26cbde 100644 --- a/docs/progress-log.md +++ b/docs/progress-log.md @@ -116,6 +116,29 @@ the timeline, then lessons and backlog. Companion to the README (what the app *d - **Org PR**: the draft #152 from 2026-10-02 (same branch name, 12 commits, conflicting with main) is refreshed as one commit on org main 45513c90 and marked ready, once the review of the translations is clean. Its old head is kept at `refs/backup/20261018/x86-64-steam-client-afa479ee`. +- Korean: the review of the translations found `을(를)` left in the two uninstall strings; both client + names end in a vowel when read, so they take `를`. The next review was clean. +- **Submitted**: #152 is one commit (a53fd117) on org main 45513c90, ready for review; Build APK passed. + Its `kwin` job (Build desktop package, KDE Plasma) failed for an unrelated reason: `build-kwin.sh` + requires Arch Linux ARM's `kwin-6.7.5`, which `extra` replaced with 6.8.0 on 2026-10-15; the job ran + only because refreshing the branch from its 2026-10-14 head spanned main's own `tools/desktop-kde` + changes. This branch changes nothing there. +- **Org review** (CodeRabbit on #152, 7 points): the library cache is saved only by the newest scan; a + session records the client it ran (`steam-client.txt`) so an abandoned session's Steam logs come + from that client; two console logs with the same game and mod get distinct names in the VAC report; + CPU pinning also unwraps `FEXInterpreter`; the VAC hint names the game in pl, ru, uk, cs and bg. + Pinning `actions/download-artifact` to a SHA was left out: no workflow here pins one. Follow-up + commit eb8634ea. +- Merged as ae94d9db. +- **FEX r5** (report: a Galaxy S25 without the KDE desktop): the x86-64 client exited 127 at its first + FEX call, `error while loading shared libraries: libxxhash.so.0`. FEX, FEXServer, FEXRootFSFetcher + and FEXOfflineCompiler link libxxhash; linuxfs-r9 does not ship it, and the test device had it only + from the KDE desktop package. r5 bundles it in `usr/local/lib` with RUNPATH `$ORIGIN/../lib` on + those programs (the runtime has no ld.so.cache), and `build-in-arch.sh` now fails when a program + needs a library that is neither bundled nor listed in `tools/fex/runtime-libs.txt` (the r9 libraries + FEX uses). With the device's libxxhash hidden, r4 failed with the reported error and r5 loaded. + Mirrored in DroidDeck-Components (#5); the app moves to fex-2610-r5 and an installed r4 is replaced + at the next x86-64 start. ## 2026-10-15 - `feat/x86-64-steam-client`: SD card library, ARM parity, org main, Counter-Strike 2 diff --git a/tools/fex/build-in-arch.sh b/tools/fex/build-in-arch.sh index 9226e6dee..ce5f68ceb 100755 --- a/tools/fex/build-in-arch.sh +++ b/tools/fex/build-in-arch.sh @@ -8,7 +8,7 @@ cd "$WORK" grep -q '^DisableSandbox' /etc/pacman.conf || sed -i 's/^\[options\]/[options]\nDisableSandbox/' /etc/pacman.conf { for m in https://ca.us.mirror.archlinuxarm.org https://fl.us.mirror.archlinuxarm.org https://de3.mirror.archlinuxarm.org https://nl.mirror.archlinuxarm.org; do echo "Server = $m/\$arch/\$repo"; done; cat /etc/pacman.d/mirrorlist; } > /etc/pacman.d/mirrorlist.new mv /etc/pacman.d/mirrorlist.new /etc/pacman.d/mirrorlist -pacman -Syu --noconfirm --needed git zstd binutils cmake ninja clang lld llvm python squashfs-tools file +pacman -Syu --noconfirm --needed git zstd binutils cmake ninja clang lld llvm python squashfs-tools file patchelf xxhash # The x86 sysroot is Arch x86_64 and multilib i686 packages unpacked by pacman, never run: no scriptlets or signature checks. THUNKS=${FEX_THUNKS:-0} @@ -60,11 +60,29 @@ cmake -S fex-src -B fex-build -G Ninja \ ninja -C fex-build DESTDIR="$WORK/out" ninja -C fex-build install install -Dm755 /usr/bin/unsquashfs out/usr/local/bin/unsquashfs -# Every NEEDED soname must resolve in a stock guest. +# The Linux runtime has no xxhash and no ld.so.cache: the library goes beside libFEXCore and the programs +# that need it find it through RUNPATH. +install -Dm644 "$(readlink -f /usr/lib/libxxhash.so.0)" out/usr/local/lib/libxxhash.so.0 +bundled=$(cd out/usr/local/lib && ls -- *.so* | sort -u) for f in out/usr/local/bin/*; do + [ -L "$f" ] && continue file "$f" | grep -q ELF || continue + readelf -d "$f" | awk '/NEEDED/ { gsub(/[\[\]]/, "", $5); print $5 }' | grep -qxF "$bundled" \ + && patchelf --set-rpath '$ORIGIN/../lib' "$f" +done +# Every NEEDED soname must resolve in a stock guest: bundled here or provided by the runtime (runtime-libs.txt). +for f in out/usr/local/bin/* out/usr/local/lib/*.so* out/usr/local/lib/fex-emu/HostThunks*/*.so; do + [ -f "$f" ] && file "$f" | grep -q ELF || continue readelf -d "$f" | awk '/NEEDED/ { gsub(/[\[\]]/, "", $5); print $5 }' done | sort -u | tee fex-needed.txt +missing=$(printf '%s\n' "$bundled" | cat - tools/fex/runtime-libs.txt | sort -u | comm -23 fex-needed.txt -) +[ -z "$missing" ] || { echo "not in the Linux runtime or this package:" $missing >&2; exit 1; } +for f in out/usr/local/bin/*; do + [ -L "$f" ] || ! file "$f" | grep -q ELF && continue + if readelf -d "$f" | awk '/NEEDED/ { gsub(/[\[\]]/, "", $5); print $5 }' | grep -qxF "$bundled"; then + readelf -d "$f" | grep -q 'RUNPATH.*\$ORIGIN/\.\./lib' || { echo "$f needs a bundled library but has no RUNPATH" >&2; exit 1; } + fi +done (cd out && find . -type f -o -type l | sort) | tee fex-files.txt tar -C out -c . | zstd -19 -T0 -o fex.tzst sha256sum fex.tzst | tee fex.tzst.sha256 diff --git a/tools/fex/runtime-libs.txt b/tools/fex/runtime-libs.txt new file mode 100644 index 000000000..3073af9bd --- /dev/null +++ b/tools/fex/runtime-libs.txt @@ -0,0 +1,12 @@ +ld-linux-aarch64.so.1 +libGLX.so.0 +libOpenGL.so.0 +libc.so.6 +libgcc_s.so.1 +liblz4.so.1 +liblzma.so.5 +liblzo2.so.2 +libm.so.6 +libstdc++.so.6 +libz.so.1 +libzstd.so.1 diff --git a/tools/linuxfs/overlay/usr/local/bin/droiddeck-steam-x64 b/tools/linuxfs/overlay/usr/local/bin/droiddeck-steam-x64 index f4b71d0da..4a2113fbf 100755 --- a/tools/linuxfs/overlay/usr/local/bin/droiddeck-steam-x64 +++ b/tools/linuxfs/overlay/usr/local/bin/droiddeck-steam-x64 @@ -1,7 +1,7 @@ #!/bin/bash set -eu -FEX_TAG=fex-2610-r4 -FEX_SHA256=0b8b55b663390e35a85871bbd32985bf5ee4f9fbf3a70906255d914ad0257cdf +FEX_TAG=fex-2610-r5 +FEX_SHA256=0fc1ca2ba13817ad70d1ea157119a75c9c02446b57d166e6d676cce0807c19c4 FEX_URL=https://github.com/Droid-Deck/DroidDeck-Components/releases/download/$FEX_TAG/fex.tzst ROOTFS_URL=https://github.com/Droid-Deck/DroidDeck-Components/releases/download/fex-rootfs-ubuntu-24.04-2026-08-11/Ubuntu_24_04.sqsh ROOTFS_SHA256=2854b06d3ff1b8f6e526135bfb6dd5b7b30ab3ab73e79ae933a3d9fed959a178