Skip to content

fix: fall back to AppImage when tarball neovim requires newer glibc#18

Open
YASoftwareDev wants to merge 9 commits intomasterfrom
fix/neovim-appimage-glibc-fallback
Open

fix: fall back to AppImage when tarball neovim requires newer glibc#18
YASoftwareDev wants to merge 9 commits intomasterfrom
fix/neovim-appimage-glibc-fallback

Conversation

@YASoftwareDev
Copy link
Copy Markdown
Owner

Summary

  • Ubuntu 20.04 ships glibc 2.31; neovim ≥ 0.10 tarballs require glibc ≥ 2.32 — binary installs silently but crashes on first run with GLIBC_2.32/2.33/2.34 not found
  • Adds _neovim_try_appimage() which downloads the .appimage release asset and extracts it with --appimage-extract (no FUSE required); squashfs-root/usr/ maps cleanly onto both /usr/local and ~/.local
  • After copying the tarball, install_neovim now verifies the binary executes before declaring success; if not, calls the AppImage fallback → apt as last resort
  • Tightens idempotency skip guard: a version-matching but glibc-broken binary is no longer silently skipped on subsequent runs

Test plan

  • On Ubuntu 20.04 (glibc 2.31): run install.sh workstation — should install via AppImage, nvim --version works
  • On Ubuntu 22.04+ (glibc 2.35): run install.sh workstation — tarball path unchanged, no regression
  • Re-run on already-installed machine with broken binary — idempotency guard detects broken binary and re-installs
  • Existing CI matrix (20.04 / 22.04 / 24.04 × docker / minimal / workstation) passes

🤖 Generated with Claude Code

Ubuntu 20.04 ships glibc 2.31; neovim ≥ 0.10 tarballs require ≥ 2.32.
The binary installs silently but crashes on first run.

Two changes:
- _neovim_try_appimage(): downloads the .appimage release asset and
  extracts it with --appimage-extract (no FUSE required); the resulting
  squashfs-root/usr/ tree maps cleanly onto both /usr/local and ~/.local.
  Falls through to apt if the AppImage asset is absent or extraction fails.
- install_neovim(): after copying the tarball, verifies the binary actually
  executes before declaring success; if it does not, calls the AppImage
  fallback. Also tightens the idempotency skip guard so a version-matching
  but glibc-broken binary is not silently skipped on subsequent runs.
AppImages use the same binary compiled against the same glibc ABI — they
provide no relief for glibc version incompatibility. The fallback was
silently installing a broken binary and reporting success.

Rework the glibc-incompatibility path:
- Test the extracted binary IN tmpdir BEFORE copying to the install prefix,
  so an incompatible new binary never overwrites a working older install.
- On glibc failure, fall directly to apt (the correct fallback), with a
  clear message including the detected system glibc version.
- Improve _neovim_apt nosudo message to explain options when apt is also
  unavailable (no sudo + old glibc = must upgrade OS or build from source).
- Remove _neovim_try_appimage entirely — the appimage asset shares the same
  binary and offers no improvement over the tarball for this failure mode.
A prior failed install could leave an incompatible binary at
$prefix/bin/nvim. Subsequent runs correctly detect and skip the install
but leave the crashing binary in place. Remove it during the glibc
fallback path so nvim is simply absent rather than crashing on every
invocation.
For Ubuntu 20.04 (glibc 2.31) where prebuilt GitHub binaries require
glibc >= 2.32 and the PPA has dropped focal support, build from source.

scripts/install-neovim-src.sh:
- Installs build deps (git, ninja, cmake, gettext, build-essential)
- Resolves latest stable tag via GitHub API (or accepts NEOVIM_TAG env)
- Shallow-clones the tagged commit; CMake FetchContent handles all C deps
- Tests binary before logging success; cleans up build dir on EXIT
- Env vars: NEOVIM_TAG (pin version), NEOVIM_PREFIX (install prefix)
modules/neovim.sh:
- Early glibc detection before download: systems with glibc < 2.32 skip
  the ~100 MB latest tarball entirely and go straight to the legacy path
- _neovim_legacy_binary(): downloads v0.9.5 (built on Ubuntu 18.04 CI,
  glibc 2.17 baseline — runs on glibc 2.31). x86_64 only; ARM64 falls
  back to apt. Verifies binary in tmpdir before copying to prefix.
- Idempotent: keeps any existing working compatible binary on re-runs

nvim/.config/nvim/init.lua:
- blink.cmp: cond = nvim-0.10 (uses vim.snippet built-in, added in 0.10)
- LSP capabilities: blink on nvim≥0.10, protocol default on older
- vim.diagnostic.jump(): guarded; falls back to goto_prev/next on nvim<0.10
- Server registration: vim.lsp.config/enable on nvim≥0.11,
  lspconfig.server.setup() on nvim 0.9–0.10 (automatic_enable only in
  the 0.11+ path where it is a known option)
- servers{} table is single source of truth for ensure_installed,
  enable(), and the lspconfig loop
nvim-lspconfig itself (not just the API) now enforces nvim >= 0.10 at
load time. nvim-treesitter-context uses the LspRequest autocmd event
added in nvim 0.10. Both crash on nvim 0.9.5 before config() runs,
so version guards in config() alone are insufficient — cond is needed.
replace `require('nvim-treesitter.install').ensure_installed` (does not
exist in the post-2024 refactored API) with the correct
`require('nvim-treesitter').install({...})` call which triggers async
parser download on first launch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants