| from __future__ import annotations |
|
|
| import ctypes |
| import os |
| import sys |
| from pathlib import Path |
|
|
| _PRELOADED_LIBSTDCXX: str | None = None |
|
|
|
|
| def _loaded_libstdcxx_paths() -> list[str]: |
| if not sys.platform.startswith("linux"): |
| return [] |
| maps_path = Path("/proc/self/maps") |
| if not maps_path.is_file(): |
| return [] |
|
|
| paths: list[str] = [] |
| try: |
| with maps_path.open("r", encoding="utf-8") as reader: |
| for line in reader: |
| if "libstdc++.so.6" not in line: |
| continue |
| path = line.rsplit(None, 1)[-1] |
| if path not in paths: |
| paths.append(path) |
| except OSError: |
| return [] |
| return paths |
|
|
|
|
| def _candidate_libstdcxx_paths() -> list[str]: |
| prefixes = [sys.prefix, sys.exec_prefix, os.environ.get("CONDA_PREFIX")] |
| paths: list[str] = [] |
| seen: set[str] = set() |
| for prefix in prefixes: |
| if not prefix: |
| continue |
| path = str(Path(prefix) / "lib" / "libstdc++.so.6") |
| norm_path = os.path.normcase(os.path.abspath(path)) |
| if norm_path in seen or not os.path.isfile(path): |
| continue |
| seen.add(norm_path) |
| paths.append(path) |
| return paths |
|
|
|
|
| def _prepend_library_path(path: str) -> None: |
| directory = os.path.dirname(path) |
| if not directory: |
| return |
| current = os.environ.get("LD_LIBRARY_PATH", "") |
| parts = [part for part in current.split(os.pathsep) if part] |
| if directory in parts: |
| return |
| os.environ["LD_LIBRARY_PATH"] = os.pathsep.join([directory, *parts]) |
|
|
|
|
| def preload_preferred_libstdcxx() -> str | None: |
| global _PRELOADED_LIBSTDCXX |
| if _PRELOADED_LIBSTDCXX is not None: |
| return _PRELOADED_LIBSTDCXX |
| if not sys.platform.startswith("linux"): |
| return None |
|
|
| loaded_paths = _loaded_libstdcxx_paths() |
| if loaded_paths: |
| return None |
|
|
| for path in _candidate_libstdcxx_paths(): |
| try: |
| mode = getattr(os, "RTLD_GLOBAL", 0) | getattr(os, "RTLD_NOW", 0) |
| ctypes.CDLL(path, mode=mode) |
| except OSError: |
| continue |
| _prepend_library_path(path) |
| _PRELOADED_LIBSTDCXX = path |
| return path |
| return None |
|
|