Files
bvandeusenandClaude Opus 5 0a7480cf9b
Desktop (Tauri) / Tauri desktop (Linux) (push) Failing after 48s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 1m50s
Desktop (Tauri) / Update manifest (push) Skipped
core: extract the store and sync engine into a shared crate (M12 step 1)
Android becomes a native Kotlin client over this same code (Scribe note 2730), so
the local store and sync engine stop being modules of the desktop app and become
`thoughtsync-core`, a crate with no UI framework in it at all.

This is a move, not a rewrite, and the measurement is why: every file in local/
and sync/ already carried ZERO Tauri references — 4,980 of 6,372 lines. The
coupling was 473 lines of command shim, which stays behind in the desktop crate
as src/commands/. Kept as git renames so history follows the files.

The desktop imports them under their old names (`use thoughtsync_core::{local,
sync}`) so every call site reads exactly as before. What moved is where they
live, not what they are.

Two things a workspace changes that are easy to miss, both caught before pushing:

[profile.release] now lives at the workspace ROOT. Cargo silently ignores
profiles declared by a non-root member — leaving it in the desktop crate would
have dropped lto/strip/opt-level from every release build with only a warning.

And a workspace shares ONE target dir, so the bundles moved from
desktop/src-tauri/target to target/. Thirteen references across publish-release,
debundle-graphics, verify.sh, package-prebuilt and the workflow now point there.
Pinning target-dir back would have been the smaller diff, but the Android lane
also produces Rust artifacts and they do not belong under desktop/.

Also retires the Tauri Android lane in the same push rather than leaving a path
that is being replaced: gen/android, android.yml and docs/android-dev.md are
gone, the mobile_entry_point attribute with them, and the lib drops to rlib —
staticlib/cdylib existed for Tauri mobile, and the .so Android loads will be
built from the core crate instead. Rule 22, no parallel path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 23:12:26 -04:00

119 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# De-bundle host-coupled graphics/display libraries from the built Tauri AppImage.
#
# WHY: Tauri's AppImage bundles the BUILD host's libEGL/libGL/libdrm/libgbm/
# libwayland-* into usr/lib. On many end-user systems (Arch/CachyOS, NVIDIA,
# Wayland) those bundled copies clash with the running kernel driver + Mesa and
# abort with "Could not create default EGL display: EGL_BAD_PARAMETER" -> a black
# window (issue 2021). They load before any renderer choice, so the runtime env
# fallbacks (WEBKIT_DISABLE_DMABUF_RENDERER etc.) cannot rescue it. Per the
# AppImage excludelist these libraries MUST come from the host. We strip exactly
# that graphics/display subset -- keeping webkit/gtk/javascriptcore bundled for
# portability -- so the dynamic loader falls through to the system copies (the
# AppRun keeps usr/lib first on LD_LIBRARY_PATH, then system paths).
#
# CI-only post-build step: extract -> remove libs -> repackage, overwriting the
# original AppImage in place so the desktop.yml artifact glob emits the
# de-bundled one.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
BUNDLE_DIR="$REPO_ROOT/target/release/bundle/appimage"
# appimagetool is published only under the rolling "continuous" tag (the project
# cuts no semver releases), so this URL is the pinned distribution channel.
# Preferred source is Tauri's own already-downloaded copy (see below); this is
# the network fallback.
APPIMAGETOOL_URL="https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
# Graphics/display libraries that must come from the host, per the AppImage
# excludelist (github.com/AppImage/pkg2appimage/blob/master/excludelist), plus
# the libwayland-* family that slips in through the GTK/WebKit dependency chain.
# Globs (.so*) catch every versioned variant. Only the GPU/driver stack is
# stripped; webkit/gtk stay bundled.
REMOVE_GLOBS=(
'libGL.so*' 'libEGL.so*' 'libGLdispatch.so*' 'libGLX.so*' 'libOpenGL.so*'
'libglapi.so*' 'libgbm.so*' 'libdrm.so*'
'libxcb.so*' 'libxcb-dri2.so*' 'libxcb-dri3.so*'
'libX11.so*' 'libX11-xcb.so*'
'libwayland-client.so*' 'libwayland-cursor.so*'
'libwayland-egl.so*' 'libwayland-server.so*'
)
echo "==> Locating built AppImage under $BUNDLE_DIR"
shopt -s nullglob
appimages=("$BUNDLE_DIR"/*.AppImage)
if [ ${#appimages[@]} -eq 0 ]; then
echo "ERROR: no .AppImage in $BUNDLE_DIR (did the tauri build run?)" >&2
exit 1
fi
APPIMAGE="${appimages[0]}"
echo " $APPIMAGE"
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT
echo "==> Extracting AppImage (FUSE-free)"
cp "$APPIMAGE" "$WORK/app.AppImage"
chmod +x "$WORK/app.AppImage"
(cd "$WORK" && ./app.AppImage --appimage-extract >/dev/null)
LIBDIR="$WORK/squashfs-root/usr/lib"
[ -d "$LIBDIR" ] || {
echo "ERROR: no usr/lib in the extracted AppImage" >&2
exit 1
}
echo "==> Removing host-coupled graphics/display libraries"
before=$(find "$LIBDIR" -maxdepth 1 -type f -name '*.so*' | wc -l)
removed=0
for pat in "${REMOVE_GLOBS[@]}"; do
for f in "$LIBDIR"/$pat; do
echo " - $(basename "$f")"
rm -f "$f"
removed=$((removed + 1))
done
done
if [ -d "$LIBDIR/dri" ]; then
n=$(find "$LIBDIR/dri" -type f | wc -l)
echo " - dri/ (${n} Mesa GPU drivers)"
rm -rf "$LIBDIR/dri"
removed=$((removed + 1))
fi
after=$(find "$LIBDIR" -maxdepth 1 -type f -name '*.so*' | wc -l)
echo " removed ${removed} entries (usr/lib .so files: ${before} -> ${after})"
if [ "$removed" -eq 0 ]; then
echo "WARNING: nothing removed -- excludelist libs were not bundled here." >&2
fi
echo "==> Locating appimagetool"
# Prefer the copy Tauri already downloaded during the build (no network, and
# version-matched to the toolchain that produced the AppImage).
APPIMAGETOOL="$(find "$REPO_ROOT/target" -name 'appimagetool-*.AppImage' -type f 2>/dev/null | head -n1 || true)"
if [ -z "${APPIMAGETOOL:-}" ]; then
echo " not cached by Tauri; downloading from continuous channel"
APPIMAGETOOL="$WORK/appimagetool"
if command -v curl >/dev/null 2>&1; then
curl -fsSL -o "$APPIMAGETOOL" "$APPIMAGETOOL_URL"
elif command -v wget >/dev/null 2>&1; then
wget -qO "$APPIMAGETOOL" "$APPIMAGETOOL_URL"
else
echo "ERROR: need curl or wget to fetch appimagetool" >&2
exit 1
fi
else
echo " reusing Tauri's copy: $APPIMAGETOOL"
fi
chmod +x "$APPIMAGETOOL"
echo "==> Repackaging AppImage (overwriting original)"
rm -f "$APPIMAGE"
# APPIMAGE_EXTRACT_AND_RUN lets appimagetool (itself an AppImage) run without
# FUSE in the CI container; ARCH is required by the embedded runtime.
export APPIMAGE_EXTRACT_AND_RUN=1
ARCH=x86_64 "$APPIMAGETOOL" "$WORK/squashfs-root" "$APPIMAGE"
echo "==> Done: de-bundled AppImage at"
ls -lh "$APPIMAGE"