From 82ffab5673a718a241c916bb5f1b14edb9ad33f9 Mon Sep 17 00:00:00 2001 From: Roman Inflianskas Date: Fri, 14 Aug 2026 12:13:47 +0000 Subject: [PATCH 1/2] fix: raise the supported Linux minimum to Ubuntu 24.04 Every published Lemonade embeddable, v10.2.0 through v11.5.2, is linked against GLIBC_2.38 and GLIBCXX_3.4.32. Ubuntu 22.04 ships glibc 2.35, so the Lemonade engine cannot start there at all, yet README.md advertised Linux x86_64 as "full support ... both inference engines" and docs/wsl.md named 22.04 as a supported WSL base. Document a single minimum of Ubuntu 24.04 for Linux and WSL2, keeping the glibc number as the reason so the requirement stays meaningful on other distributions, and drop 22.04 from the WSL preflight's supported set so the automated check matches the prerequisite it enforces. Fixes #258 Signed-off-by: Roman Inflianskas --- README.md | 11 +++++++++-- docs/wsl.md | 5 ++++- scripts/wsl_preflight.py | 16 ++++++++++++++-- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bae9b4c0..834ac314 100644 --- a/README.md +++ b/README.md @@ -29,15 +29,22 @@ Lemonade and vLLM. | Platform | Prebuilt binary | Notes | |---|---|---| -| Linux (x86_64) | Yes | Full support, including the live dashboard and both inference engines | +| Linux (x86_64) | Yes | Ubuntu 24.04 or newer; full support, including the live dashboard and both inference engines | | Windows (x86_64) | Yes | CLI and Lemonade serving; no live dashboard or vLLM | -| WSL2 (x86_64) | Yes (Linux binary) | Full support, including the live dashboard; see [docs/wsl.md](docs/wsl.md) for setup | +| WSL2 (x86_64) | Yes (Linux binary) | Ubuntu 24.04 or newer; full support, including the live dashboard; see [docs/wsl.md](docs/wsl.md) for setup | | macOS | No | No official installer, release, CI, or QA coverage | Live dashboard telemetry requires Linux or WSL2 (see [Interactive interfaces](#interactive-interfaces)). vLLM serving is Linux/WSL2 only (see [docs/vllm.md](docs/vllm.md)). +The minimum supported Linux release, native or under WSL2, is Ubuntu 24.04. On +other distributions the equivalent requirement is glibc 2.38 with +`GLIBCXX_3.4.32`: that is what the Lemonade engine is linked against, and every +published build of it needs those versions, so there is no older release to fall +back to. Ubuntu 22.04 ships glibc 2.35 and cannot run it; Ubuntu 24.04 provides +glibc 2.39 and `GLIBCXX_3.4.33`. + > [!IMPORTANT] > **Tech Preview** -- This software is provided as-is, without warranty or > guarantee of stability. APIs, commands, and behavior may change without diff --git a/docs/wsl.md b/docs/wsl.md index 1b9a90a1..24a53679 100644 --- a/docs/wsl.md +++ b/docs/wsl.md @@ -14,7 +14,10 @@ virtual environments and ROCDXG (`librocdxg`). The AMD WSL path is: 1. Windows 11 with the AMD Adrenalin WSL-capable driver. -2. WSL2 with Ubuntu 24.04 or Ubuntu 22.04. +2. WSL2 with Ubuntu 24.04 or newer. Ubuntu 22.04 is not supported: it ships + glibc 2.35, below the glibc 2.38 / `GLIBCXX_3.4.32` floor that every + published Lemonade embeddable requires, so the Lemonade engine cannot start + there. Ubuntu 24.04 provides glibc 2.39 and `GLIBCXX_3.4.33`. 3. ROCDXG (`librocdxg`) installed inside WSL. 4. A TheRock runtime installed by `rocm-cli` into a managed Python venv. diff --git a/scripts/wsl_preflight.py b/scripts/wsl_preflight.py index 436b0db2..76bb5af9 100644 --- a/scripts/wsl_preflight.py +++ b/scripts/wsl_preflight.py @@ -258,8 +258,10 @@ def evaluate( sdk_headers = state.get("windows_sdk_headers") or [] version_id = str(os_release.get("VERSION_ID") or "") + # 22.04 is deliberately absent: its glibc 2.35 is below the glibc 2.38 / + # GLIBCXX_3.4.32 floor every published Lemonade embeddable is linked + # against, so the Lemonade engine cannot start on it. See docs/wsl.md. supported_ubuntu = os_release.get("ID") == "ubuntu" and version_id in { - "22.04", "24.04", "26.04", } @@ -270,7 +272,9 @@ def evaluate( checks = [ Check("wsl", bool(state.get("is_wsl")), "WSL marker or /dev/dxg detected"), Check( - "ubuntu", supported_ubuntu, f"Ubuntu VERSION_ID={version_id or ''}" + "ubuntu", + supported_ubuntu, + f"Ubuntu 24.04 or newer (VERSION_ID={version_id or ''})", ), Check("dxg_device", bool(paths.get("/dev/dxg")), "/dev/dxg"), Check( @@ -391,6 +395,14 @@ def self_test() -> None: checks = evaluate(ready_state, require_rocm_tools=False) assert all(check.ok for check in checks if check.required), checks + # 22.04 is below the Lemonade glibc floor, so an otherwise perfect host + # must still fail the ubuntu check rather than report itself ready. + jammy_state = json.loads(json.dumps(ready_state)) + jammy_state["os_release"]["VERSION_ID"] = "22.04" + checks = evaluate(jammy_state, require_rocm_tools=False) + assert any(check.name == "ubuntu" and not check.ok for check in checks), checks + assert not all(check.ok for check in checks if check.required), checks + def main() -> int: parser = argparse.ArgumentParser(description=__doc__) From 803f00ff394b5a9e41e7c9940268eebff7312e2a Mon Sep 17 00:00:00 2001 From: Michael Roy Date: Sat, 15 Aug 2026 11:59:52 -0700 Subject: [PATCH 2/2] fix(wsl): accept Ubuntu releases after 24.04 Signed-off-by: Michael Roy --- scripts/wsl_preflight.py | 41 ++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/scripts/wsl_preflight.py b/scripts/wsl_preflight.py index 76bb5af9..042aab4e 100644 --- a/scripts/wsl_preflight.py +++ b/scripts/wsl_preflight.py @@ -258,13 +258,20 @@ def evaluate( sdk_headers = state.get("windows_sdk_headers") or [] version_id = str(os_release.get("VERSION_ID") or "") - # 22.04 is deliberately absent: its glibc 2.35 is below the glibc 2.38 / + # 22.04 is deliberately unsupported: its glibc 2.35 is below the glibc 2.38 / # GLIBCXX_3.4.32 floor every published Lemonade embeddable is linked # against, so the Lemonade engine cannot start on it. See docs/wsl.md. - supported_ubuntu = os_release.get("ID") == "ubuntu" and version_id in { - "24.04", - "26.04", - } + version_parts = version_id.split(".") + ubuntu_version = None + if len(version_parts) == 2 and all( + part.isascii() and part.isdecimal() for part in version_parts + ): + ubuntu_version = (int(version_parts[0]), int(version_parts[1])) + supported_ubuntu = ( + os_release.get("ID") == "ubuntu" + and ubuntu_version is not None + and ubuntu_version >= (24, 4) + ) build_tools = all( tools.get(name) for name in ["git", "cmake", "gcc", "g++", "make"] ) @@ -395,11 +402,25 @@ def self_test() -> None: checks = evaluate(ready_state, require_rocm_tools=False) assert all(check.ok for check in checks if check.required), checks - # 22.04 is below the Lemonade glibc floor, so an otherwise perfect host - # must still fail the ubuntu check rather than report itself ready. - jammy_state = json.loads(json.dumps(ready_state)) - jammy_state["os_release"]["VERSION_ID"] = "22.04" - checks = evaluate(jammy_state, require_rocm_tools=False) + for version_id in ["24.04", "24.10", "25.04", "26.04", "28.04"]: + supported_state = json.loads(json.dumps(ready_state)) + supported_state["os_release"]["VERSION_ID"] = version_id + checks = evaluate(supported_state, require_rocm_tools=False) + assert any(check.name == "ubuntu" and check.ok for check in checks), checks + assert all(check.ok for check in checks if check.required), checks + + # 22.04 is below the Lemonade glibc floor, and malformed or unknown + # versions must fail closed rather than report an otherwise perfect host ready. + for version_id in ["22.04", "24.04.1", "unknown", ""]: + unsupported_state = json.loads(json.dumps(ready_state)) + unsupported_state["os_release"]["VERSION_ID"] = version_id + checks = evaluate(unsupported_state, require_rocm_tools=False) + assert any(check.name == "ubuntu" and not check.ok for check in checks), checks + assert not all(check.ok for check in checks if check.required), checks + + missing_version_state = json.loads(json.dumps(ready_state)) + del missing_version_state["os_release"]["VERSION_ID"] + checks = evaluate(missing_version_state, require_rocm_tools=False) assert any(check.name == "ubuntu" and not check.ok for check in checks), checks assert not all(check.ok for check in checks if check.required), checks