Bundle libxml2 + libicu74 to support Ubuntu 25.10 / 26.04#14
Merged
Conversation
Ubuntu 25.10 (Plucky) shipped libxml2 2.14, which bumped the SONAME from .so.2 to .so.16, and renamed the apt package from libxml2 to libxml2-16. ICU also moved from 74 to 76. The theseus-rs PostgreSQL binaries that pg0 bundles are linked against libxml2.so.2 and libicu*.so.74, both of which are unavailable on 25.10 (and inherited on the upcoming 26.04 LTS), so `pg0 start` failed with "missing required system libraries". Reproduction added in docker-tests/test_ubuntu_amd64.sh: ubuntu:24.04 passes against the released v0.13.0 binary; ubuntu:25.10 fails. Fix: download libxml2 (2.9.14) and libicu74 (74.2-1ubuntu3.1) from the Ubuntu 24.04 archive at build time, embed the .so files into the pg0 binary, extract them into <installation>/<ver>/lib/ at runtime alongside the postgres binary, create the SONAME symlinks (libxml2.so.2 -> libxml2.so.2.9.14 etc.), and prepend that lib dir to LD_LIBRARY_PATH so postgres / initdb / pg_ctl / psql resolve through the bundled copies. Bundle is built only for Linux GNU targets (x86_64 + aarch64). macOS, Windows, and the musl Linux builds get an empty bundle - on those platforms the libs are either system-provided in a forward-compatible way (Alpine 3.20/3.21 with ICU 74) or shipped by other means (macOS frameworks, Windows .dlls beside postgres.exe). Upgrade safety: the runtime extraction runs even when postgres is already extracted from a previous pg0 release, so users on existing ~/.pg0/installation/ trees pick up the new libs automatically without having to wipe the directory. Other: - versions.env now pins exact .deb URLs + SHA256s for reproducibility. - ar / zstd / tar / flate2 / sha2 / hex added as build-dependencies for cracking open the .deb (ar archive of zstd-compressed tar). - Linux GNU binary grows ~10 MB (matches the gz-compressed bundle). - test_missing_libs.sh now uses libgssapi-krb5-2 as the canary missing lib, since libxml2 is no longer required from the host. - New docker-tests/test_ubuntu_amd64.sh covers ubuntu:24.04 + ubuntu:25.10 and is wired into CI (with PG0_BINARY_PATH built fresh, like the existing missing-libs job). - README updated: removes libxml2 / libicu from the apt install snippets, adds a "Tested and Supported Platforms" table that explicitly calls out which Alpine versions work (3.20 / 3.21) vs not (3.22+), and adds Ubuntu 24.04 / 25.10 / 26.04 as supported.
…eline
The previous commit pulled libxml2 and libicu74 from Ubuntu 24.04, but
those .so files require GLIBC 2.38, which is newer than the manylinux_2_35
baseline (Ubuntu 22.04 / Debian 12) the wheel ships under. CI's
Linux x86_64-gnu wheel test failed on the ubuntu-22.04 runner with:
postgres: libm.so.6: version `GLIBC_2.38' not found
(required by libxml2.so.2)
Root-cause realization: the bundled postgres binary itself does NOT have
libicu in DT_NEEDED. It only links against libxml2.so.2; libxml2 is what
pulls libicu in transitively. So the ICU major version we ship just
needs to match whatever ICU the bundled libxml2 was built against - it
does not have to match the original SONAME `.so.74` from Ubuntu 24.04.
Switch to Ubuntu 22.04 sources:
- libxml2 2.9.13+dfsg-1ubuntu0.11 (.so.2 SONAME, transitively wants .so.70)
- libicu70 70.1-2ubuntu1 (icudata + icui18n + icuuc)
These libs require at most GLIBC 2.34, comfortably below our 2.35 wheel
baseline, and are still ABI-compatible everywhere we care about (22.04,
24.04, 25.10, 26.04). They sit alongside whatever libicu the host has
installed - on 24.04 the system libicu74 is unused; on 25.10 the system
libicu76 is unused; in both cases the bundled postgres resolves through
our libxml2 -> our libicu70.
Verified locally:
- Vanilla ubuntu:22.04 (glibc 2.35, no libxml2/libicu installed):
pg0 start + psql + stop works.
- ubuntu:24.04 + ubuntu:25.10: docker-tests/test_ubuntu_amd64.sh passes.
- python:3.11-slim debian: docker-tests/test_debian_amd64.sh passes.
- missing-libs detection still works.
Comments in build.rs and main.rs updated to reflect the new sourcing
rationale; README's Ubuntu 25.10 row updated from "ICU 74" to "libicu70".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ubuntu 25.10 (Plucky) shipped libxml2 2.14 with a SONAME bump from `.so.2` to `.so.16` (and renamed the apt package to `libxml2-16`); ICU jumped from 74 to 76. The theseus-rs PostgreSQL binaries pg0 ships are linked against `libxml2.so.2` and `libicu*.so.74`, both unavailable on 25.10 - and on the upcoming 26.04 LTS that inherits from it. Result: `pg0 start` fails with "missing required system libraries" out of the box.
The fix: download `libxml2` (2.9.14) and `libicu74` (74.2-1ubuntu3.1) from the Ubuntu 24.04 archive at build time, embed the `.so` files in the pg0 binary, extract them next to the bundled postgres at first run, create the SONAME symlinks the dynamic linker resolves (`libxml2.so.2` -> `libxml2.so.2.9.14`, etc.), and prepend that lib dir to `LD_LIBRARY_PATH` so initdb / postgres / pg_ctl / psql find them.
The bundle ships only on Linux GNU targets. macOS, Windows and the musl Linux builds get an empty bundle - they either have the libs system-side in a forward-compatible way (Alpine 3.20 / 3.21) or ship them through other means (macOS frameworks, Windows DLLs alongside postgres.exe).
Changes
Cost
Linux GNU binaries grow by ~10 MB (matches the gz-compressed runtime libs bundle). macOS / Windows / musl binaries are unchanged.
Backwards compatibility
Verified locally
Test plan