From 90788d34b9a4a18b940f7ba6557cb7a5d0ee4048 Mon Sep 17 00:00:00 2001 From: Sasha Lopoukhine Date: Wed, 2 Sep 2026 13:20:28 +0200 Subject: [PATCH 1/2] test: move ext_tools test to pytest/unit/ext_tools --- tests/pytest/{utils => unit/ext_tools}/test_ext_tools.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/pytest/{utils => unit/ext_tools}/test_ext_tools.py (100%) diff --git a/tests/pytest/utils/test_ext_tools.py b/tests/pytest/unit/ext_tools/test_ext_tools.py similarity index 100% rename from tests/pytest/utils/test_ext_tools.py rename to tests/pytest/unit/ext_tools/test_ext_tools.py From 092ea519aac2fe2e05ffccbe30bc6b5af512adcf Mon Sep 17 00:00:00 2001 From: Christophe Guillon Date: Wed, 2 Sep 2026 13:27:42 +0200 Subject: [PATCH 2/2] utils: fall back to legacy ldconfig path for get_library_path --- src/xtc/utils/ext_tools.py | 2 + tests/pytest/unit/ext_tools/test_ext_tools.py | 39 ++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/xtc/utils/ext_tools.py b/src/xtc/utils/ext_tools.py index bbc873b0..54bf634e 100644 --- a/src/xtc/utils/ext_tools.py +++ b/src/xtc/utils/ext_tools.py @@ -45,6 +45,8 @@ def get_library_path(libname: str) -> str: return str(candidate) ldconfig = shutil.which("ldconfig") + if ldconfig is None and Path("/sbin/ldconfig").is_file(): + ldconfig = "/sbin/ldconfig" if ldconfig is not None: result = subprocess.run([ldconfig, "-p"], capture_output=True, text=True) for line in result.stdout.splitlines(): diff --git a/tests/pytest/unit/ext_tools/test_ext_tools.py b/tests/pytest/unit/ext_tools/test_ext_tools.py index 4cc29e14..09d72d78 100644 --- a/tests/pytest/unit/ext_tools/test_ext_tools.py +++ b/tests/pytest/unit/ext_tools/test_ext_tools.py @@ -26,7 +26,7 @@ def test_get_library_path_uses_environment_search_paths( assert ext_tools.get_library_path("omp") == str(library) -def test_get_library_path_falls_back_to_ldconfig( +def test_get_library_path_uses_ldconfig_from_path( monkeypatch: pytest.MonkeyPatch, ) -> None: library_name = "libomp.so.5" @@ -38,6 +38,7 @@ def test_get_library_path_falls_back_to_ldconfig( ) monkeypatch.delenv("LD_LIBRARY_PATH", raising=False) monkeypatch.delenv("LIBRARY_PATH", raising=False) + monkeypatch.setenv("PATH", "/usr/bin:/sbin") monkeypatch.setattr(ext_tools.shutil, "which", lambda _name: "/sbin/ldconfig") monkeypatch.setattr( ext_tools.subprocess, @@ -50,3 +51,39 @@ def test_get_library_path_falls_back_to_ldconfig( ) assert ext_tools.get_library_path("omp") == library + + +def test_get_library_path_falls_back_to_sbin_ldconfig_when_not_on_path( + monkeypatch: pytest.MonkeyPatch, +) -> None: + library_name = "libomp.so.5" + library = "/usr/lib/x86_64-linux-gnu/libomp.so.5" + + monkeypatch.setattr(ext_tools.platform, "system", lambda: "Linux") + monkeypatch.setattr( + ext_tools.ctypes.util, "find_library", lambda _name: library_name + ) + monkeypatch.delenv("LD_LIBRARY_PATH", raising=False) + monkeypatch.delenv("LIBRARY_PATH", raising=False) + monkeypatch.setenv("PATH", "/usr/bin:/bin") + monkeypatch.setattr(ext_tools.shutil, "which", lambda _name: None) + + original_is_file = ext_tools.Path.is_file + + def is_file(path: Path) -> bool: + if path == Path("/sbin/ldconfig"): + return True + return original_is_file(path) + + monkeypatch.setattr(ext_tools.Path, "is_file", is_file) + monkeypatch.setattr( + ext_tools.subprocess, + "run", + lambda *_args, **_kwargs: CompletedProcess( + args=["/sbin/ldconfig", "-p"], + returncode=0, + stdout=f"\t{library_name} (libc6,x86-64) => {library}\n", + ), + ) + + assert ext_tools.get_library_path("omp") == library