b11146 ships ubuntu-cuda-13.4-arm64 (+ cudart), so llamacpp-cuda gains linux-arm64, auto resolves NVIDIA arm64 Linux to CUDA, and the desktop's localModels flag ships on Linux arm64 too. Every upstream Linux llama.cpp build (CPU included) links the system libgomp, which minimal hosts (WSL, containers) lack, and a normal install never touches the system package manager. Each Linux engine now pins Ubuntu 24.04's libgomp1 .deb (glibc 2.38, the floor upstream already sets) and stages libgomp.so.1 beside llama-server, where the $ORIGIN RUNPATH finds it; the artifact mirror covers the pool URL after 24.04's EOL. DebPackage's ar+tar unpack becomes pm.package.unpack_deb and reads zstd data.tar (Ubuntu's default) with the stdlib codec PM's 3.14 runtime has. Pre-PM engines on Linux carry only llama.cpp's own archives, so adoption maps their manifests to those and records them as outdated (usable now, update offered) instead of failing to match. Verified on an RTX Spark N1X (WSL, Ubuntu 26.04, no system libgomp): ensure_engine() for cuda, cpu and vulkan through PM's real download/stage/ verify path; ldd resolves libgomp from the entry; llama-server serves completions (CUDA0 at 445 tok/s). linux-x64 cpu/vulkan staged through the same path with no NEEDED library missing beyond glibc/libstdc++/OpenSSL 3.
60 lines
2.5 KiB
Python
60 lines
2.5 KiB
Python
"""Backend selection uses reviewed target pins and never installs on lookup."""
|
|
|
|
import pytest
|
|
|
|
import pm
|
|
from hermes_cli.local_runtime import binaries
|
|
from pm import paths
|
|
from pm.lock import Lockfile
|
|
|
|
|
|
@pytest.mark.parametrize("target,vendor,expected", [
|
|
("linux-x64", "nvidia", "cuda"),
|
|
("linux-arm64", "nvidia", "cuda"),
|
|
("win32-arm64", "nvidia", "cuda"),
|
|
("win32-arm64", "AMD Radeon", "cpu"),
|
|
("win32-x64", "AMD Radeon", "vulkan"),
|
|
("win32-x64", None, "cpu"),
|
|
("darwin-arm64", None, "metal"),
|
|
])
|
|
def test_auto_backend_uses_only_compatible_pins(target, vendor, expected):
|
|
assert binaries.resolve_backend("auto", gpu_vendor=vendor, target=target) == expected
|
|
with pytest.raises(binaries.BinaryResolutionError):
|
|
binaries.resolve_backend("cuda", target="darwin-arm64")
|
|
|
|
|
|
def test_linux_cuda_runtime_libraries_land_beside_the_server(tmp_path):
|
|
"""The engine's RUNPATH is $ORIGIN and its archive carries neither the CUDA
|
|
runtime nor OpenMP, so the cudart tarball's top-level dir and the libgomp
|
|
.deb's usr/lib/<triplet>/ library must both end up next to llama-server."""
|
|
package = pm.get_package("llamacpp-cuda")
|
|
staged = tmp_path / "tree"
|
|
(staged / "llama-b1").mkdir(parents=True)
|
|
(staged / "llama-b1" / "llama-server").write_bytes(b"engine")
|
|
(staged / "cudart-llama-b1-bin-ubuntu-cuda-13.4-x64").mkdir()
|
|
(staged / "cudart-llama-b1-bin-ubuntu-cuda-13.4-x64" / "libcudart.so.13").write_bytes(b"rt")
|
|
gomp = staged / "usr" / "lib" / "x86_64-linux-gnu"
|
|
gomp.mkdir(parents=True)
|
|
(gomp / "libgomp.so.1.0.0").write_bytes(b"omp")
|
|
(gomp / "libgomp.so.1").symlink_to("libgomp.so.1.0.0")
|
|
|
|
package.stage(None, staged, "1", "linux-x64")
|
|
|
|
assert package.binary(staged, "linux-x64").is_file()
|
|
assert (staged / "libcudart.so.13").is_file()
|
|
assert not list(staged.glob("cudart-*"))
|
|
assert not (staged / "libgomp.so.1").is_symlink()
|
|
assert (staged / "libgomp.so.1").read_bytes() == b"omp"
|
|
assert not (staged / "usr").exists()
|
|
|
|
|
|
def test_missing_pin_is_refused_instead_of_constructing_download_url(tmp_path, monkeypatch):
|
|
lock_path = tmp_path / "lock.json"
|
|
monkeypatch.setattr(paths, "lockfile_path", lambda: lock_path)
|
|
lock = Lockfile(lock_path)
|
|
lock.set_pin("llamacpp-cpu", "123", {})
|
|
lock.save()
|
|
assert binaries.pinned_tag("cpu") == "b123"
|
|
with pytest.raises(binaries.BinaryResolutionError, match="not pinned"):
|
|
binaries.resolve_backend("cpu", target=pm.current_target())
|