| |
| |
|
|
| import glob |
| import os |
| from collections.abc import Sequence |
|
|
| from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFoundError |
| from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( |
| SITE_PACKAGES_LIBDIRS_LINUX, |
| SITE_PACKAGES_LIBDIRS_WINDOWS, |
| is_suppressed_dll_file, |
| ) |
| from cuda.pathfinder._utils.env_vars import get_cuda_home_or_path |
| from cuda.pathfinder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages |
| from cuda.pathfinder._utils.platform_aware import IS_WINDOWS |
|
|
|
|
| def _no_such_file_in_sub_dirs( |
| sub_dirs: Sequence[str], file_wild: str, error_messages: list[str], attachments: list[str] |
| ) -> None: |
| error_messages.append(f"No such file: {file_wild}") |
| for sub_dir in find_sub_dirs_all_sitepackages(sub_dirs): |
| attachments.append(f' listdir("{sub_dir}"):') |
| for node in sorted(os.listdir(sub_dir)): |
| attachments.append(f" {node}") |
|
|
|
|
| def _find_so_using_nvidia_lib_dirs( |
| libname: str, so_basename: str, error_messages: list[str], attachments: list[str] |
| ) -> str | None: |
| rel_dirs = SITE_PACKAGES_LIBDIRS_LINUX.get(libname) |
| if rel_dirs is not None: |
| sub_dirs_searched = [] |
| file_wild = so_basename + "*" |
| for rel_dir in rel_dirs: |
| sub_dir = tuple(rel_dir.split(os.path.sep)) |
| for abs_dir in find_sub_dirs_all_sitepackages(sub_dir): |
| |
| so_name = os.path.join(abs_dir, so_basename) |
| if os.path.isfile(so_name): |
| return so_name |
| |
| |
| for so_name in sorted(glob.glob(os.path.join(abs_dir, file_wild))): |
| if os.path.isfile(so_name): |
| return so_name |
| sub_dirs_searched.append(sub_dir) |
| for sub_dir in sub_dirs_searched: |
| _no_such_file_in_sub_dirs(sub_dir, file_wild, error_messages, attachments) |
| return None |
|
|
|
|
| def _find_dll_under_dir(dirpath: str, file_wild: str) -> str | None: |
| for path in sorted(glob.glob(os.path.join(dirpath, file_wild))): |
| if not os.path.isfile(path): |
| continue |
| if not is_suppressed_dll_file(os.path.basename(path)): |
| return path |
| return None |
|
|
|
|
| def _find_dll_using_nvidia_bin_dirs( |
| libname: str, lib_searched_for: str, error_messages: list[str], attachments: list[str] |
| ) -> str | None: |
| rel_dirs = SITE_PACKAGES_LIBDIRS_WINDOWS.get(libname) |
| if rel_dirs is not None: |
| sub_dirs_searched = [] |
| for rel_dir in rel_dirs: |
| sub_dir = tuple(rel_dir.split(os.path.sep)) |
| for abs_dir in find_sub_dirs_all_sitepackages(sub_dir): |
| dll_name = _find_dll_under_dir(abs_dir, lib_searched_for) |
| if dll_name is not None: |
| return dll_name |
| sub_dirs_searched.append(sub_dir) |
| for sub_dir in sub_dirs_searched: |
| _no_such_file_in_sub_dirs(sub_dir, lib_searched_for, error_messages, attachments) |
| return None |
|
|
|
|
| def _find_lib_dir_using_anchor_point(libname: str, anchor_point: str, linux_lib_dir: str) -> str | None: |
| |
| |
| if IS_WINDOWS: |
| if libname == "nvvm": |
| rel_paths = [ |
| "nvvm/bin/*", |
| "nvvm/bin", |
| ] |
| else: |
| rel_paths = [ |
| "bin/x64", |
| "bin", |
| ] |
| else: |
| if libname == "nvvm": |
| rel_paths = ["nvvm/lib64"] |
| else: |
| rel_paths = [linux_lib_dir] |
|
|
| for rel_path in rel_paths: |
| for dirname in sorted(glob.glob(os.path.join(anchor_point, rel_path))): |
| if os.path.isdir(dirname): |
| return dirname |
|
|
| return None |
|
|
|
|
| def _find_lib_dir_using_cuda_home(libname: str) -> str | None: |
| cuda_home = get_cuda_home_or_path() |
| if cuda_home is None: |
| return None |
| return _find_lib_dir_using_anchor_point(libname, anchor_point=cuda_home, linux_lib_dir="lib64") |
|
|
|
|
| def _find_lib_dir_using_conda_prefix(libname: str) -> str | None: |
| conda_prefix = os.environ.get("CONDA_PREFIX") |
| if not conda_prefix: |
| return None |
| return _find_lib_dir_using_anchor_point( |
| libname, anchor_point=os.path.join(conda_prefix, "Library") if IS_WINDOWS else conda_prefix, linux_lib_dir="lib" |
| ) |
|
|
|
|
| def _find_so_using_lib_dir( |
| lib_dir: str, so_basename: str, error_messages: list[str], attachments: list[str] |
| ) -> str | None: |
| so_name = os.path.join(lib_dir, so_basename) |
| if os.path.isfile(so_name): |
| return so_name |
| error_messages.append(f"No such file: {so_name}") |
| attachments.append(f' listdir("{lib_dir}"):') |
| if not os.path.isdir(lib_dir): |
| attachments.append(" DIRECTORY DOES NOT EXIST") |
| else: |
| for node in sorted(os.listdir(lib_dir)): |
| attachments.append(f" {node}") |
| return None |
|
|
|
|
| def _find_dll_using_lib_dir( |
| lib_dir: str, libname: str, error_messages: list[str], attachments: list[str] |
| ) -> str | None: |
| file_wild = libname + "*.dll" |
| dll_name = _find_dll_under_dir(lib_dir, file_wild) |
| if dll_name is not None: |
| return dll_name |
| error_messages.append(f"No such file: {file_wild}") |
| attachments.append(f' listdir("{lib_dir}"):') |
| for node in sorted(os.listdir(lib_dir)): |
| attachments.append(f" {node}") |
| return None |
|
|
|
|
| class _FindNvidiaDynamicLib: |
| def __init__(self, libname: str): |
| self.libname = libname |
| if IS_WINDOWS: |
| self.lib_searched_for = f"{libname}*.dll" |
| else: |
| self.lib_searched_for = f"lib{libname}.so" |
| self.error_messages: list[str] = [] |
| self.attachments: list[str] = [] |
| self.abs_path: str | None = None |
|
|
| def try_site_packages(self) -> str | None: |
| if IS_WINDOWS: |
| return _find_dll_using_nvidia_bin_dirs( |
| self.libname, |
| self.lib_searched_for, |
| self.error_messages, |
| self.attachments, |
| ) |
| else: |
| return _find_so_using_nvidia_lib_dirs( |
| self.libname, |
| self.lib_searched_for, |
| self.error_messages, |
| self.attachments, |
| ) |
|
|
| def try_with_conda_prefix(self) -> str | None: |
| return self._find_using_lib_dir(_find_lib_dir_using_conda_prefix(self.libname)) |
|
|
| def try_with_cuda_home(self) -> str | None: |
| return self._find_using_lib_dir(_find_lib_dir_using_cuda_home(self.libname)) |
|
|
| def _find_using_lib_dir(self, lib_dir: str | None) -> str | None: |
| if lib_dir is None: |
| return None |
| if IS_WINDOWS: |
| return _find_dll_using_lib_dir( |
| lib_dir, |
| self.libname, |
| self.error_messages, |
| self.attachments, |
| ) |
| else: |
| return _find_so_using_lib_dir( |
| lib_dir, |
| self.lib_searched_for, |
| self.error_messages, |
| self.attachments, |
| ) |
|
|
| def raise_not_found_error(self) -> None: |
| err = ", ".join(self.error_messages) |
| att = "\n".join(self.attachments) |
| raise DynamicLibNotFoundError(f'Failure finding "{self.lib_searched_for}": {err}\n{att}') |
|
|