From 599ef39c6945a74998682729c3b617c37a7b9a89 Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Sat, 27 Sep 2025 12:48:35 -0700 Subject: [PATCH 01/12] outline of something functional for linux --- .../_dynamic_libs/find_nvidia_dynamic_lib.py | 19 +++++++++++++++ .../_dynamic_libs/load_dl_common.py | 6 ++++- .../pathfinder/_dynamic_libs/load_dl_linux.py | 16 +++---------- .../_dynamic_libs/load_nvidia_dynamic_lib.py | 24 ++++++++++--------- 4 files changed, 40 insertions(+), 25 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py index 75ebec3a8..a7105d9ed 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py @@ -7,6 +7,7 @@ from typing import Optional from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFoundError +from cuda.pathfinder._dynamic_libs.load_dl_linux import get_candidate_sonames, _load_lib, abs_path_for_dynamic_library from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( SITE_PACKAGES_LIBDIRS_LINUX, SITE_PACKAGES_LIBDIRS_WINDOWS, @@ -163,6 +164,7 @@ def __init__(self, libname: str): self.error_messages: list[str] = [] self.attachments: list[str] = [] self.abs_path: Optional[str] = None + self.distribution: Optional[str] = None def try_site_packages(self) -> Optional[str]: if IS_WINDOWS: @@ -186,6 +188,21 @@ def try_with_conda_prefix(self) -> Optional[str]: def try_with_cuda_home(self) -> Optional[str]: return self._find_using_lib_dir(_find_lib_dir_using_cuda_home(self.libname)) + def try_with_system_search(self) -> Optional[str]: + + for soname in get_candidate_sonames(self.libname): + try: + handle = _load_lib(self.libname, soname) + except OSError: + pass + else: + abs_path = abs_path_for_dynamic_library(self.libname, handle) + if abs_path is None: + raise RuntimeError(f"No expected symbol for {libname=!r}") + return abs_path + return None + + def _find_using_lib_dir(self, lib_dir: Optional[str]) -> Optional[str]: if lib_dir is None: return None @@ -203,6 +220,8 @@ def _find_using_lib_dir(self, lib_dir: Optional[str]) -> Optional[str]: self.error_messages, self.attachments, ) + if self.abs_path is not None: + self.distribution = "CUDA_HOME" def raise_not_found_error(self) -> None: err = ", ".join(self.error_messages) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 416718f5a..5f3e4698a 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -10,13 +10,17 @@ class DynamicLibNotFoundError(RuntimeError): pass +@dataclass +class Distribution: + name: str + version: str @dataclass class LoadedDL: abs_path: Optional[str] was_already_loaded_from_elsewhere: bool _handle_uint: int # Platform-agnostic unsigned pointer value - + distribution: Optional[Distribution] = None def load_dependencies(libname: str, load_func: Callable[[str], LoadedDL]) -> None: for dep in DIRECT_DEPENDENCIES.get(libname, ()): diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index a7de858b7..874c9a6c3 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -7,7 +7,7 @@ import os from typing import Optional, cast -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, Distribution from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( LIBNAMES_REQUIRING_RTLD_DEEPBIND, SUPPORTED_LINUX_SONAMES, @@ -170,7 +170,7 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]: abs_path = abs_path_for_dynamic_library(libname, handle) if abs_path is None: raise RuntimeError(f"No expected symbol for {libname=!r}") - return LoadedDL(abs_path, False, handle._handle) + return LoadedDL(abs_path, False, handle._handle, Distribution("system", None)) return None @@ -194,21 +194,11 @@ def _work_around_known_bugs(libname: str, found_path: str) -> None: def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: - """Load a dynamic library from the given path. - Args: - libname: The name of the library to load - found_path: The absolute path to the library file - - Returns: - A LoadedDL object representing the loaded library - - Raises: - RuntimeError: If the library cannot be loaded - """ _work_around_known_bugs(libname, found_path) try: handle = _load_lib(libname, found_path) except OSError as e: raise RuntimeError(f"Failed to dlopen {found_path}: {e}") from e return LoadedDL(found_path, False, handle._handle) + diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index 6a8392589..f72664676 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -6,7 +6,7 @@ import sys from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _FindNvidiaDynamicLib -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies, Distribution from cuda.pathfinder._utils.platform_aware import IS_WINDOWS if IS_WINDOWS: @@ -25,9 +25,9 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: finder = _FindNvidiaDynamicLib(libname) - abs_path = finder.try_site_packages() + abs_path, distname = finder.try_site_packages(), 'site-packages' if abs_path is None: - abs_path = finder.try_with_conda_prefix() + abs_path, distname = finder.try_with_conda_prefix(), 'conda ' # If the library was already loaded by someone else, reproduce any OS-specific # side-effects we would have applied on a direct absolute-path load (e.g., @@ -43,14 +43,16 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: return loaded if abs_path is None: - loaded = load_with_system_search(libname) - if loaded is not None: - return loaded - abs_path = finder.try_with_cuda_home() - if abs_path is None: - finder.raise_not_found_error() - - return load_with_abs_path(libname, abs_path) + abs_path, distname = finder.try_with_system_search(), 'system' + if abs_path is None: + abs_path, distname = finder.try_with_cuda_home(), 'CUDA_HOME' + if abs_path is None: + finder.raise_not_found_error() + + dl = load_with_abs_path(libname, abs_path) + dl.distribution = Distribution(name=distname, version='unknown') + return dl + @functools.cache From b5d53c013bc87487f519f05478d523db7025e3d1 Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Sun, 28 Sep 2025 07:25:53 -0700 Subject: [PATCH 02/12] adding/refactoring --- .../_dynamic_libs/find_nvidia_dynamic_lib.py | 19 +-- .../pathfinder/_dynamic_libs/load_dl_linux.py | 12 ++ .../_dynamic_libs/load_dl_windows.py | 18 +++ .../_dynamic_libs/load_nvidia_dynamic_lib.py | 136 ++++++++++++++---- 4 files changed, 145 insertions(+), 40 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py index a7105d9ed..35bc1b4e1 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py @@ -7,7 +7,7 @@ from typing import Optional from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFoundError -from cuda.pathfinder._dynamic_libs.load_dl_linux import get_candidate_sonames, _load_lib, abs_path_for_dynamic_library +from cuda.pathfinder._dynamic_libs.load_dl_linux import get_candidate_sonames, _load_lib, abs_path_for_dynamic_library from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( SITE_PACKAGES_LIBDIRS_LINUX, SITE_PACKAGES_LIBDIRS_WINDOWS, @@ -17,6 +17,10 @@ from cuda.pathfinder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages from cuda.pathfinder._utils.platform_aware import IS_WINDOWS +if IS_WINDOWS: + from cuda.pathfinder._dynamic_libs.load_dl_windows import find_with_system_search_windows as find_with_system_search +else: + from cuda.pathfinder._dynamic_libs.load_dl_linux import find_with_system_search_linux as find_with_system_search def _no_such_file_in_sub_dirs( sub_dirs: Sequence[str], file_wild: str, error_messages: list[str], attachments: list[str] @@ -189,18 +193,7 @@ def try_with_cuda_home(self) -> Optional[str]: return self._find_using_lib_dir(_find_lib_dir_using_cuda_home(self.libname)) def try_with_system_search(self) -> Optional[str]: - - for soname in get_candidate_sonames(self.libname): - try: - handle = _load_lib(self.libname, soname) - except OSError: - pass - else: - abs_path = abs_path_for_dynamic_library(self.libname, handle) - if abs_path is None: - raise RuntimeError(f"No expected symbol for {libname=!r}") - return abs_path - return None + return find_with_system_search(self.libname) def _find_using_lib_dir(self, lib_dir: Optional[str]) -> Optional[str]: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index 874c9a6c3..d61bf7247 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -173,6 +173,18 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]: return LoadedDL(abs_path, False, handle._handle, Distribution("system", None)) return None +def find_with_system_search_linux(libname: str) -> Optional[str]: + for soname in get_candidate_sonames(libname): + try: + handle = _load_lib(libname, soname) + except OSError: + pass + else: + abs_path = abs_path_for_dynamic_library(libname, handle) + if abs_path is None: + raise RuntimeError(f"No expected symbol for {libname=!r}") + return abs_path + return None def _work_around_known_bugs(libname: str, found_path: str) -> None: if libname == "nvrtc": diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 5da6d9b84..1dfde894f 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -132,6 +132,24 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]: return None +def find_with_system_search_windows(libname: str) -> Optional[str]: + """Try to find a DLL using system search paths. + + Args: + libname: The name of the library to find + + Returns: + The absolute path to the DLL if found, None otherwise + """ + # Reverse tabulated names to achieve new → old search order. + for dll_name in reversed(SUPPORTED_WINDOWS_DLLS.get(libname, ())): + handle = kernel32.GetModuleHandleW(dll_name) + if handle: + abs_path = abs_path_for_dynamic_library(libname, handle) + return abs_path + + return None + def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: """Load a dynamic library from the given path. diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index f72664676..e54a78cba 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -22,35 +22,12 @@ load_with_system_search, ) +from typing import Optional -def _load_lib_no_cache(libname: str) -> LoadedDL: - finder = _FindNvidiaDynamicLib(libname) - abs_path, distname = finder.try_site_packages(), 'site-packages' - if abs_path is None: - abs_path, distname = finder.try_with_conda_prefix(), 'conda ' - - # If the library was already loaded by someone else, reproduce any OS-specific - # side-effects we would have applied on a direct absolute-path load (e.g., - # AddDllDirectory on Windows for libs that require it). - loaded = check_if_already_loaded_from_elsewhere(libname, abs_path is not None) - - # Load dependencies regardless of who loaded the primary lib first. - # Doing this *after* the side-effect ensures dependencies resolve consistently - # relative to the actually loaded location. - load_dependencies(libname, load_nvidia_dynamic_lib) - - if loaded is not None: - return loaded - - if abs_path is None: - abs_path, distname = finder.try_with_system_search(), 'system' - if abs_path is None: - abs_path, distname = finder.try_with_cuda_home(), 'CUDA_HOME' - if abs_path is None: - finder.raise_not_found_error() - dl = load_with_abs_path(libname, abs_path) - dl.distribution = Distribution(name=distname, version='unknown') +def _load_lib_no_cache(libname: str) -> LoadedDL: + loader = _LoadNvidiaDynamicLib(libname) + dl = loader.load_lib() return dl @@ -132,3 +109,108 @@ def load_nvidia_dynamic_lib(libname: str) -> LoadedDL: f" {sys.version_info.major}.{sys.version_info.minor}" ) return _load_lib_no_cache(libname) + + +class _LoadNvidiaDynamicLib: + def __init__(self, libname: str): + self.finder = _FindNvidiaDynamicLib(libname) + self.libname = self.finder.libname + + def _load_with_dependencies( + self, get_path_func: callable, dist_name: str + ) -> Optional[LoadedDL]: + abs_path = get_path_func() + if abs_path is None: + return None + + # If the library was already loaded by someone else, reproduce any OS-specific + # side-effects we would have applied on a direct absolute-path load (e.g., + # AddDllDirectory on Windows for libs that require it). + loaded = check_if_already_loaded_from_elsewhere(self.libname, True) + + # Load dependencies regardless of who loaded the primary lib first. + # Doing this *after* the side-effect ensures dependencies resolve consistently + # relative to the actually loaded location. + load_dependencies(self.libname, load_nvidia_dynamic_lib) + dist = Distribution(name=dist_name, version="unknown") + if loaded is not None: + loaded.distribution = dist + return loaded + + dl = load_with_abs_path(self.libname, abs_path) + dl.distribution = dist + return dl + + def _load_simple( + self, get_path_func: callable, dist_name: str + ) -> Optional[LoadedDL]: + abs_path = get_path_func() + if abs_path is None: + return None + + dl = load_with_abs_path(self.libname, abs_path) + dl.distribution = Distribution(name=dist_name, version="unknown") + return dl + + def load_with_site_packages(self) -> Optional[LoadedDL]: + return self._load_with_dependencies(self.finder.try_site_packages, "site-packages") + + def load_with_conda_prefix(self) -> Optional[LoadedDL]: + return self._load_with_dependencies(self.finder.try_with_conda_prefix, "conda") + + def load_with_system_search(self) -> Optional[LoadedDL]: + return self._load_simple(self.finder.try_with_system_search, "system") + + def load_with_cuda_home(self) -> Optional[LoadedDL]: + return self._load_simple(self.finder.try_with_cuda_home, "CUDA_HOME") + + def load_lib(self): + dl = self.load_with_site_packages() + if dl is not None: + return dl + + + dl = self.load_with_conda_prefix() + if dl is not None: + return dl + + + dl = self.load_with_system_search() + if dl is not None: + return dl + + + dl = self.load_with_cuda_home() + if dl is not None: + return dl + + self.finder.raise_not_found_error() + +def _load_lib_no_cache(libname: str) -> LoadedDL: + finder = _FindNvidiaDynamicLib(libname) + abs_path = finder.try_site_packages() + if abs_path is None: + abs_path = finder.try_with_conda_prefix() + + # If the library was already loaded by someone else, reproduce any OS-specific + # side-effects we would have applied on a direct absolute-path load (e.g., + # AddDllDirectory on Windows for libs that require it). + loaded = check_if_already_loaded_from_elsewhere(libname, abs_path is not None) + + # Load dependencies regardless of who loaded the primary lib first. + # Doing this *after* the side-effect ensures dependencies resolve consistently + # relative to the actually loaded location. + load_dependencies(libname, load_nvidia_dynamic_lib) + + if loaded is not None: + return loaded + + if abs_path is None: + loaded = load_with_system_search(libname) + if loaded is not None: + return loaded + abs_path = finder.try_with_cuda_home() + if abs_path is None: + finder.raise_not_found_error() + + return load_with_abs_path(libname, abs_path) From 8746a22299c9552599b794b7aec6ee94bb617b2a Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Mon, 29 Sep 2025 11:26:22 -0700 Subject: [PATCH 03/12] updates --- .../_dynamic_libs/load_nvidia_dynamic_lib.py | 64 ++++--------------- 1 file changed, 14 insertions(+), 50 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index e54a78cba..b5322d292 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -6,23 +6,21 @@ import sys from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _FindNvidiaDynamicLib -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies, Distribution +from cuda.pathfinder._dynamic_libs.load_dl_common import Distribution, LoadedDL, load_dependencies from cuda.pathfinder._utils.platform_aware import IS_WINDOWS if IS_WINDOWS: from cuda.pathfinder._dynamic_libs.load_dl_windows import ( check_if_already_loaded_from_elsewhere, load_with_abs_path, - load_with_system_search, ) else: from cuda.pathfinder._dynamic_libs.load_dl_linux import ( check_if_already_loaded_from_elsewhere, load_with_abs_path, - load_with_system_search, ) -from typing import Optional +from typing import Callable, Optional def _load_lib_no_cache(libname: str) -> LoadedDL: @@ -31,7 +29,6 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: return dl - @functools.cache def load_nvidia_dynamic_lib(libname: str) -> LoadedDL: """Load an NVIDIA dynamic library by name. @@ -117,12 +114,8 @@ def __init__(self, libname: str): self.libname = self.finder.libname def _load_with_dependencies( - self, get_path_func: callable, dist_name: str + self, get_path_func: Callable[[], Optional[LoadedDL]], dist_name: str ) -> Optional[LoadedDL]: - abs_path = get_path_func() - if abs_path is None: - return None - # If the library was already loaded by someone else, reproduce any OS-specific # side-effects we would have applied on a direct absolute-path load (e.g., # AddDllDirectory on Windows for libs that require it). @@ -132,6 +125,11 @@ def _load_with_dependencies( # Doing this *after* the side-effect ensures dependencies resolve consistently # relative to the actually loaded location. load_dependencies(self.libname, load_nvidia_dynamic_lib) + + abs_path = get_path_func() + if abs_path is None: + return None + dist = Distribution(name=dist_name, version="unknown") if loaded is not None: loaded.distribution = dist @@ -141,9 +139,7 @@ def _load_with_dependencies( dl.distribution = dist return dl - def _load_simple( - self, get_path_func: callable, dist_name: str - ) -> Optional[LoadedDL]: + def _load_simple(self, get_path_func: Callable[[], Optional[LoadedDL]], dist_name: str) -> Optional[LoadedDL]: abs_path = get_path_func() if abs_path is None: return None @@ -153,64 +149,32 @@ def _load_simple( return dl def load_with_site_packages(self) -> Optional[LoadedDL]: - return self._load_with_dependencies(self.finder.try_site_packages, "site-packages") + return self._load_simple(self.finder.try_site_packages, "site-packages") def load_with_conda_prefix(self) -> Optional[LoadedDL]: - return self._load_with_dependencies(self.finder.try_with_conda_prefix, "conda") + return self._load_simple(self.finder.try_with_conda_prefix, "conda") def load_with_system_search(self) -> Optional[LoadedDL]: - return self._load_simple(self.finder.try_with_system_search, "system") + return self._load_with_dependencies(self.finder.try_with_system_search, "system") def load_with_cuda_home(self) -> Optional[LoadedDL]: - return self._load_simple(self.finder.try_with_cuda_home, "CUDA_HOME") + return self._load_with_dependencies(self.finder.try_with_cuda_home, "CUDA_HOME") - def load_lib(self): + def load_lib(self) -> LoadedDL: dl = self.load_with_site_packages() if dl is not None: return dl - dl = self.load_with_conda_prefix() if dl is not None: return dl - dl = self.load_with_system_search() if dl is not None: return dl - dl = self.load_with_cuda_home() if dl is not None: return dl self.finder.raise_not_found_error() - -def _load_lib_no_cache(libname: str) -> LoadedDL: - finder = _FindNvidiaDynamicLib(libname) - abs_path = finder.try_site_packages() - if abs_path is None: - abs_path = finder.try_with_conda_prefix() - - # If the library was already loaded by someone else, reproduce any OS-specific - # side-effects we would have applied on a direct absolute-path load (e.g., - # AddDllDirectory on Windows for libs that require it). - loaded = check_if_already_loaded_from_elsewhere(libname, abs_path is not None) - - # Load dependencies regardless of who loaded the primary lib first. - # Doing this *after* the side-effect ensures dependencies resolve consistently - # relative to the actually loaded location. - load_dependencies(libname, load_nvidia_dynamic_lib) - - if loaded is not None: - return loaded - - if abs_path is None: - loaded = load_with_system_search(libname) - if loaded is not None: - return loaded - abs_path = finder.try_with_cuda_home() - if abs_path is None: - finder.raise_not_found_error() - - return load_with_abs_path(libname, abs_path) From 95d913cad0059d7a3b6ba43d7ef8c6be2d65beef Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Wed, 1 Oct 2025 07:59:03 -0700 Subject: [PATCH 04/12] actually pass tests --- .../_dynamic_libs/load_nvidia_dynamic_lib.py | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index b5322d292..28d6a1b05 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -6,21 +6,23 @@ import sys from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _FindNvidiaDynamicLib -from cuda.pathfinder._dynamic_libs.load_dl_common import Distribution, LoadedDL, load_dependencies +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies from cuda.pathfinder._utils.platform_aware import IS_WINDOWS if IS_WINDOWS: from cuda.pathfinder._dynamic_libs.load_dl_windows import ( check_if_already_loaded_from_elsewhere, load_with_abs_path, + load_with_system_search, ) else: from cuda.pathfinder._dynamic_libs.load_dl_linux import ( check_if_already_loaded_from_elsewhere, load_with_abs_path, + load_with_system_search, ) -from typing import Callable, Optional +from typing import Optional def _load_lib_no_cache(libname: str) -> LoadedDL: @@ -113,52 +115,55 @@ def __init__(self, libname: str): self.finder = _FindNvidiaDynamicLib(libname) self.libname = self.finder.libname - def _load_with_dependencies( - self, get_path_func: Callable[[], Optional[LoadedDL]], dist_name: str - ) -> Optional[LoadedDL]: + def _maybe_return_loaded(self, check_if_loaded_from_elsewhere: bool = True) -> Optional[LoadedDL]: # If the library was already loaded by someone else, reproduce any OS-specific # side-effects we would have applied on a direct absolute-path load (e.g., - # AddDllDirectory on Windows for libs that require it). - loaded = check_if_already_loaded_from_elsewhere(self.libname, True) + # AddDllDirectory on Windows for libs that re + loaded = check_if_already_loaded_from_elsewhere(self.libname, check_if_loaded_from_elsewhere) # Load dependencies regardless of who loaded the primary lib first. # Doing this *after* the side-effect ensures dependencies resolve consistently # relative to the actually loaded location. load_dependencies(self.libname, load_nvidia_dynamic_lib) - abs_path = get_path_func() - if abs_path is None: - return None - - dist = Distribution(name=dist_name, version="unknown") if loaded is not None: - loaded.distribution = dist return loaded + return None - dl = load_with_abs_path(self.libname, abs_path) - dl.distribution = dist - return dl + def load_with_site_packages(self) -> Optional[LoadedDL]: + if loaded := self._maybe_return_loaded(True): + return loaded - def _load_simple(self, get_path_func: Callable[[], Optional[LoadedDL]], dist_name: str) -> Optional[LoadedDL]: - abs_path = get_path_func() + abs_path = self.finder.try_site_packages() if abs_path is None: return None - - dl = load_with_abs_path(self.libname, abs_path) - dl.distribution = Distribution(name=dist_name, version="unknown") - return dl - - def load_with_site_packages(self) -> Optional[LoadedDL]: - return self._load_simple(self.finder.try_site_packages, "site-packages") + return load_with_abs_path(self.libname, abs_path) def load_with_conda_prefix(self) -> Optional[LoadedDL]: - return self._load_simple(self.finder.try_with_conda_prefix, "conda") + if loaded := self._maybe_return_loaded(True): + return loaded + + abs_path = self.finder.try_with_conda_prefix() + if abs_path is None: + return None + return load_with_abs_path(self.libname, abs_path) def load_with_system_search(self) -> Optional[LoadedDL]: - return self._load_with_dependencies(self.finder.try_with_system_search, "system") + if loaded := self._maybe_return_loaded(False): + return loaded + loaded = load_with_system_search(self.libname) + if loaded is not None: + return loaded + return None def load_with_cuda_home(self) -> Optional[LoadedDL]: - return self._load_with_dependencies(self.finder.try_with_cuda_home, "CUDA_HOME") + if loaded := self._maybe_return_loaded(False): + return loaded + + abs_path = self.finder.try_with_cuda_home() + if abs_path is None: + return None + return load_with_abs_path(self.libname, abs_path) def load_lib(self) -> LoadedDL: dl = self.load_with_site_packages() From 9c5a05910a9116c1c46d4d5e2feb6dfc33e432ff Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Wed, 1 Oct 2025 08:47:51 -0700 Subject: [PATCH 05/12] findvia --- .../_dynamic_libs/find_nvidia_dynamic_lib.py | 9 -------- .../_dynamic_libs/load_dl_common.py | 9 +++++--- .../pathfinder/_dynamic_libs/load_dl_linux.py | 18 ++------------- .../_dynamic_libs/load_dl_windows.py | 18 --------------- .../_dynamic_libs/load_nvidia_dynamic_lib.py | 22 ++++++++----------- 5 files changed, 17 insertions(+), 59 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py index 35bc1b4e1..6b6665372 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py @@ -7,7 +7,6 @@ from typing import Optional from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFoundError -from cuda.pathfinder._dynamic_libs.load_dl_linux import get_candidate_sonames, _load_lib, abs_path_for_dynamic_library from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( SITE_PACKAGES_LIBDIRS_LINUX, SITE_PACKAGES_LIBDIRS_WINDOWS, @@ -17,10 +16,6 @@ from cuda.pathfinder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages from cuda.pathfinder._utils.platform_aware import IS_WINDOWS -if IS_WINDOWS: - from cuda.pathfinder._dynamic_libs.load_dl_windows import find_with_system_search_windows as find_with_system_search -else: - from cuda.pathfinder._dynamic_libs.load_dl_linux import find_with_system_search_linux as find_with_system_search def _no_such_file_in_sub_dirs( sub_dirs: Sequence[str], file_wild: str, error_messages: list[str], attachments: list[str] @@ -192,10 +187,6 @@ def try_with_conda_prefix(self) -> Optional[str]: def try_with_cuda_home(self) -> Optional[str]: return self._find_using_lib_dir(_find_lib_dir_using_cuda_home(self.libname)) - def try_with_system_search(self) -> Optional[str]: - return find_with_system_search(self.libname) - - def _find_using_lib_dir(self, lib_dir: Optional[str]) -> Optional[str]: if lib_dir is None: return None diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 5f3e4698a..7a79db55f 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -10,17 +10,20 @@ class DynamicLibNotFoundError(RuntimeError): pass + @dataclass -class Distribution: +class FoundVia: name: str - version: str + version: Optional[str] = None + @dataclass class LoadedDL: abs_path: Optional[str] was_already_loaded_from_elsewhere: bool _handle_uint: int # Platform-agnostic unsigned pointer value - distribution: Optional[Distribution] = None + foundvia: Optional[FoundVia] = None + def load_dependencies(libname: str, load_func: Callable[[str], LoadedDL]) -> None: for dep in DIRECT_DEPENDENCIES.get(libname, ()): diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index d61bf7247..d26578af1 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -7,7 +7,7 @@ import os from typing import Optional, cast -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, Distribution +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( LIBNAMES_REQUIRING_RTLD_DEEPBIND, SUPPORTED_LINUX_SONAMES, @@ -170,21 +170,9 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]: abs_path = abs_path_for_dynamic_library(libname, handle) if abs_path is None: raise RuntimeError(f"No expected symbol for {libname=!r}") - return LoadedDL(abs_path, False, handle._handle, Distribution("system", None)) + return LoadedDL(abs_path, False, handle._handle) return None -def find_with_system_search_linux(libname: str) -> Optional[str]: - for soname in get_candidate_sonames(libname): - try: - handle = _load_lib(libname, soname) - except OSError: - pass - else: - abs_path = abs_path_for_dynamic_library(libname, handle) - if abs_path is None: - raise RuntimeError(f"No expected symbol for {libname=!r}") - return abs_path - return None def _work_around_known_bugs(libname: str, found_path: str) -> None: if libname == "nvrtc": @@ -206,11 +194,9 @@ def _work_around_known_bugs(libname: str, found_path: str) -> None: def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: - _work_around_known_bugs(libname, found_path) try: handle = _load_lib(libname, found_path) except OSError as e: raise RuntimeError(f"Failed to dlopen {found_path}: {e}") from e return LoadedDL(found_path, False, handle._handle) - diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 1dfde894f..5da6d9b84 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -132,24 +132,6 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]: return None -def find_with_system_search_windows(libname: str) -> Optional[str]: - """Try to find a DLL using system search paths. - - Args: - libname: The name of the library to find - - Returns: - The absolute path to the DLL if found, None otherwise - """ - # Reverse tabulated names to achieve new → old search order. - for dll_name in reversed(SUPPORTED_WINDOWS_DLLS.get(libname, ())): - handle = kernel32.GetModuleHandleW(dll_name) - if handle: - abs_path = abs_path_for_dynamic_library(libname, handle) - return abs_path - - return None - def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: """Load a dynamic library from the given path. diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index 28d6a1b05..49dd4ba18 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -6,7 +6,7 @@ import sys from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _FindNvidiaDynamicLib -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies +from cuda.pathfinder._dynamic_libs.load_dl_common import FoundVia, LoadedDL, load_dependencies from cuda.pathfinder._utils.platform_aware import IS_WINDOWS if IS_WINDOWS: @@ -166,20 +166,16 @@ def load_with_cuda_home(self) -> Optional[LoadedDL]: return load_with_abs_path(self.libname, abs_path) def load_lib(self) -> LoadedDL: - dl = self.load_with_site_packages() - if dl is not None: + if dl := self.load_with_site_packages(): + dl.foundvia = FoundVia("site-packages") return dl - - dl = self.load_with_conda_prefix() - if dl is not None: + if dl := self.load_with_conda_prefix(): + dl.foundvia = FoundVia("conda") return dl - - dl = self.load_with_system_search() - if dl is not None: + if dl := self.load_with_system_search(): + dl.foundvia = FoundVia("system") return dl - - dl = self.load_with_cuda_home() - if dl is not None: + if dl := self.load_with_cuda_home(): + dl.foundvia = FoundVia("CUDA_HOME") return dl - self.finder.raise_not_found_error() From 7557d50a597c41cca5f6e13b8d431146a3a60110 Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Wed, 1 Oct 2025 08:58:53 -0700 Subject: [PATCH 06/12] cleanup --- .../cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py index 6b6665372..c0f84c176 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py @@ -204,8 +204,6 @@ def _find_using_lib_dir(self, lib_dir: Optional[str]) -> Optional[str]: self.error_messages, self.attachments, ) - if self.abs_path is not None: - self.distribution = "CUDA_HOME" def raise_not_found_error(self) -> None: err = ", ".join(self.error_messages) From 936cd20430e55f46252ddba027355f4d161661ff Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Mon, 6 Oct 2025 08:49:46 -0700 Subject: [PATCH 07/12] reset --- .../_dynamic_libs/find_nvidia_dynamic_lib.py | 1 - .../pathfinder/_dynamic_libs/load_dl_linux.py | 12 ++ .../_dynamic_libs/load_nvidia_dynamic_lib.py | 105 +++++------------- 3 files changed, 40 insertions(+), 78 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py index c0f84c176..75ebec3a8 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py @@ -163,7 +163,6 @@ def __init__(self, libname: str): self.error_messages: list[str] = [] self.attachments: list[str] = [] self.abs_path: Optional[str] = None - self.distribution: Optional[str] = None def try_site_packages(self) -> Optional[str]: if IS_WINDOWS: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index d26578af1..a7de858b7 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -194,6 +194,18 @@ def _work_around_known_bugs(libname: str, found_path: str) -> None: def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: + """Load a dynamic library from the given path. + + Args: + libname: The name of the library to load + found_path: The absolute path to the library file + + Returns: + A LoadedDL object representing the loaded library + + Raises: + RuntimeError: If the library cannot be loaded + """ _work_around_known_bugs(libname, found_path) try: handle = _load_lib(libname, found_path) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index 49dd4ba18..6a8392589 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -6,7 +6,7 @@ import sys from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _FindNvidiaDynamicLib -from cuda.pathfinder._dynamic_libs.load_dl_common import FoundVia, LoadedDL, load_dependencies +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies from cuda.pathfinder._utils.platform_aware import IS_WINDOWS if IS_WINDOWS: @@ -22,13 +22,35 @@ load_with_system_search, ) -from typing import Optional - def _load_lib_no_cache(libname: str) -> LoadedDL: - loader = _LoadNvidiaDynamicLib(libname) - dl = loader.load_lib() - return dl + finder = _FindNvidiaDynamicLib(libname) + abs_path = finder.try_site_packages() + if abs_path is None: + abs_path = finder.try_with_conda_prefix() + + # If the library was already loaded by someone else, reproduce any OS-specific + # side-effects we would have applied on a direct absolute-path load (e.g., + # AddDllDirectory on Windows for libs that require it). + loaded = check_if_already_loaded_from_elsewhere(libname, abs_path is not None) + + # Load dependencies regardless of who loaded the primary lib first. + # Doing this *after* the side-effect ensures dependencies resolve consistently + # relative to the actually loaded location. + load_dependencies(libname, load_nvidia_dynamic_lib) + + if loaded is not None: + return loaded + + if abs_path is None: + loaded = load_with_system_search(libname) + if loaded is not None: + return loaded + abs_path = finder.try_with_cuda_home() + if abs_path is None: + finder.raise_not_found_error() + + return load_with_abs_path(libname, abs_path) @functools.cache @@ -108,74 +130,3 @@ def load_nvidia_dynamic_lib(libname: str) -> LoadedDL: f" {sys.version_info.major}.{sys.version_info.minor}" ) return _load_lib_no_cache(libname) - - -class _LoadNvidiaDynamicLib: - def __init__(self, libname: str): - self.finder = _FindNvidiaDynamicLib(libname) - self.libname = self.finder.libname - - def _maybe_return_loaded(self, check_if_loaded_from_elsewhere: bool = True) -> Optional[LoadedDL]: - # If the library was already loaded by someone else, reproduce any OS-specific - # side-effects we would have applied on a direct absolute-path load (e.g., - # AddDllDirectory on Windows for libs that re - loaded = check_if_already_loaded_from_elsewhere(self.libname, check_if_loaded_from_elsewhere) - - # Load dependencies regardless of who loaded the primary lib first. - # Doing this *after* the side-effect ensures dependencies resolve consistently - # relative to the actually loaded location. - load_dependencies(self.libname, load_nvidia_dynamic_lib) - - if loaded is not None: - return loaded - return None - - def load_with_site_packages(self) -> Optional[LoadedDL]: - if loaded := self._maybe_return_loaded(True): - return loaded - - abs_path = self.finder.try_site_packages() - if abs_path is None: - return None - return load_with_abs_path(self.libname, abs_path) - - def load_with_conda_prefix(self) -> Optional[LoadedDL]: - if loaded := self._maybe_return_loaded(True): - return loaded - - abs_path = self.finder.try_with_conda_prefix() - if abs_path is None: - return None - return load_with_abs_path(self.libname, abs_path) - - def load_with_system_search(self) -> Optional[LoadedDL]: - if loaded := self._maybe_return_loaded(False): - return loaded - loaded = load_with_system_search(self.libname) - if loaded is not None: - return loaded - return None - - def load_with_cuda_home(self) -> Optional[LoadedDL]: - if loaded := self._maybe_return_loaded(False): - return loaded - - abs_path = self.finder.try_with_cuda_home() - if abs_path is None: - return None - return load_with_abs_path(self.libname, abs_path) - - def load_lib(self) -> LoadedDL: - if dl := self.load_with_site_packages(): - dl.foundvia = FoundVia("site-packages") - return dl - if dl := self.load_with_conda_prefix(): - dl.foundvia = FoundVia("conda") - return dl - if dl := self.load_with_system_search(): - dl.foundvia = FoundVia("system") - return dl - if dl := self.load_with_cuda_home(): - dl.foundvia = FoundVia("CUDA_HOME") - return dl - self.finder.raise_not_found_error() From 4f1abfd6b030b00b84afaf3ce5a2b32ec944327a Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Mon, 6 Oct 2025 09:20:09 -0700 Subject: [PATCH 08/12] pass FoundVia through where necessary --- .../pathfinder/_dynamic_libs/load_dl_linux.py | 14 ++++++++------ .../pathfinder/_dynamic_libs/load_dl_windows.py | 14 ++++++++------ .../_dynamic_libs/load_nvidia_dynamic_lib.py | 15 ++++++++++++--- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index a7de858b7..bc8392c8b 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -7,7 +7,7 @@ import os from typing import Optional, cast -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL +from cuda.pathfinder._dynamic_libs.load_dl_common import FoundVia, LoadedDL from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( LIBNAMES_REQUIRING_RTLD_DEEPBIND, SUPPORTED_LINUX_SONAMES, @@ -131,14 +131,16 @@ def get_candidate_sonames(libname: str) -> list[str]: return candidate_sonames -def check_if_already_loaded_from_elsewhere(libname: str, _have_abs_path: bool) -> Optional[LoadedDL]: +def check_if_already_loaded_from_elsewhere( + libname: str, _have_abs_path: bool, found_via: Optional[FoundVia] = None +) -> Optional[LoadedDL]: for soname in get_candidate_sonames(libname): try: handle = ctypes.CDLL(soname, mode=os.RTLD_NOLOAD) except OSError: continue else: - return LoadedDL(abs_path_for_dynamic_library(libname, handle), True, handle._handle) + return LoadedDL(abs_path_for_dynamic_library(libname, handle), True, handle._handle, found_via) return None @@ -170,7 +172,7 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]: abs_path = abs_path_for_dynamic_library(libname, handle) if abs_path is None: raise RuntimeError(f"No expected symbol for {libname=!r}") - return LoadedDL(abs_path, False, handle._handle) + return LoadedDL(abs_path, False, handle._handle, FoundVia("system")) return None @@ -193,7 +195,7 @@ def _work_around_known_bugs(libname: str, found_path: str) -> None: ctypes.CDLL(dep_path, CDLL_MODE) -def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: +def load_with_abs_path(libname: str, found_path: str, found_via: Optional[FoundVia] = None) -> LoadedDL: """Load a dynamic library from the given path. Args: @@ -211,4 +213,4 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: handle = _load_lib(libname, found_path) except OSError as e: raise RuntimeError(f"Failed to dlopen {found_path}: {e}") from e - return LoadedDL(found_path, False, handle._handle) + return LoadedDL(found_path, False, handle._handle, found_via) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 5da6d9b84..187aeaaf2 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -7,7 +7,7 @@ import struct from typing import Optional -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL +from cuda.pathfinder._dynamic_libs.load_dl_common import FoundVia, LoadedDL from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY, SUPPORTED_WINDOWS_DLLS, @@ -100,7 +100,9 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.wintypes.HMODULE) return buffer.value -def check_if_already_loaded_from_elsewhere(libname: str, have_abs_path: bool) -> Optional[LoadedDL]: +def check_if_already_loaded_from_elsewhere( + libname: str, have_abs_path: bool, found_via: Optional[FoundVia] = None +) -> Optional[LoadedDL]: for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): handle = kernel32.GetModuleHandleW(dll_name) if handle: @@ -110,7 +112,7 @@ def check_if_already_loaded_from_elsewhere(libname: str, have_abs_path: bool) -> # load_with_abs_path(). To make the side-effect more deterministic, # activate it even if the library was already loaded from elsewhere. add_dll_directory(abs_path) - return LoadedDL(abs_path, True, ctypes_handle_to_unsigned_int(handle)) + return LoadedDL(abs_path, True, ctypes_handle_to_unsigned_int(handle), found_via) return None @@ -128,12 +130,12 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]: handle = kernel32.LoadLibraryExW(dll_name, None, 0) if handle: abs_path = abs_path_for_dynamic_library(libname, handle) - return LoadedDL(abs_path, False, ctypes_handle_to_unsigned_int(handle)) + return LoadedDL(abs_path, False, ctypes_handle_to_unsigned_int(handle), FoundVia("system")) return None -def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: +def load_with_abs_path(libname: str, found_path: str, found_via: Optional[FoundVia] = None) -> LoadedDL: """Load a dynamic library from the given path. Args: @@ -156,4 +158,4 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: error_code = ctypes.GetLastError() # type: ignore[attr-defined] raise RuntimeError(f"Failed to load DLL at {found_path}: Windows error {error_code}") - return LoadedDL(found_path, False, ctypes_handle_to_unsigned_int(handle)) + return LoadedDL(found_path, False, ctypes_handle_to_unsigned_int(handle), found_via) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index 6a8392589..debbe315f 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -6,7 +6,7 @@ import sys from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _FindNvidiaDynamicLib -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies +from cuda.pathfinder._dynamic_libs.load_dl_common import FoundVia, LoadedDL, load_dependencies from cuda.pathfinder._utils.platform_aware import IS_WINDOWS if IS_WINDOWS: @@ -26,13 +26,20 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: finder = _FindNvidiaDynamicLib(libname) abs_path = finder.try_site_packages() + if abs_path is None: abs_path = finder.try_with_conda_prefix() + if abs_path is not None: + found_via = FoundVia("conda") + else: + found_via = FoundVia("site-packages") # If the library was already loaded by someone else, reproduce any OS-specific # side-effects we would have applied on a direct absolute-path load (e.g., # AddDllDirectory on Windows for libs that require it). - loaded = check_if_already_loaded_from_elsewhere(libname, abs_path is not None) + loaded = check_if_already_loaded_from_elsewhere( + libname, abs_path is not None, found_via if abs_path is not None else None + ) # Load dependencies regardless of who loaded the primary lib first. # Doing this *after* the side-effect ensures dependencies resolve consistently @@ -49,8 +56,10 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: abs_path = finder.try_with_cuda_home() if abs_path is None: finder.raise_not_found_error() + else: + found_via = FoundVia("CUDA_HOME") - return load_with_abs_path(libname, abs_path) + return load_with_abs_path(libname, abs_path, found_via) @functools.cache From a9697311d919c4c17f691a7e279311475cc5855f Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Wed, 8 Oct 2025 11:53:49 -0700 Subject: [PATCH 09/12] address reviews --- .../pathfinder/_dynamic_libs/load_dl_common.py | 8 +------- .../cuda/pathfinder/_dynamic_libs/load_dl_linux.py | 14 +++++++------- .../pathfinder/_dynamic_libs/load_dl_windows.py | 11 ++++++----- .../_dynamic_libs/load_nvidia_dynamic_lib.py | 12 +++++------- .../tests/child_load_nvidia_dynamic_lib_helper.py | 1 + 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 7a79db55f..5d7cdfaf7 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -11,18 +11,12 @@ class DynamicLibNotFoundError(RuntimeError): pass -@dataclass -class FoundVia: - name: str - version: Optional[str] = None - - @dataclass class LoadedDL: abs_path: Optional[str] was_already_loaded_from_elsewhere: bool _handle_uint: int # Platform-agnostic unsigned pointer value - foundvia: Optional[FoundVia] = None + foundvia: Optional[str] = None def load_dependencies(libname: str, load_func: Callable[[str], LoadedDL]) -> None: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index bc8392c8b..db43cd3a2 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -7,7 +7,7 @@ import os from typing import Optional, cast -from cuda.pathfinder._dynamic_libs.load_dl_common import FoundVia, LoadedDL +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( LIBNAMES_REQUIRING_RTLD_DEEPBIND, SUPPORTED_LINUX_SONAMES, @@ -131,16 +131,16 @@ def get_candidate_sonames(libname: str) -> list[str]: return candidate_sonames -def check_if_already_loaded_from_elsewhere( - libname: str, _have_abs_path: bool, found_via: Optional[FoundVia] = None -) -> Optional[LoadedDL]: +def check_if_already_loaded_from_elsewhere(libname: str, _have_abs_path: bool) -> Optional[LoadedDL]: for soname in get_candidate_sonames(libname): try: handle = ctypes.CDLL(soname, mode=os.RTLD_NOLOAD) except OSError: continue else: - return LoadedDL(abs_path_for_dynamic_library(libname, handle), True, handle._handle, found_via) + return LoadedDL( + abs_path_for_dynamic_library(libname, handle), True, handle._handle, "arleady-loaded-from-elsewhere" + ) return None @@ -172,7 +172,7 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]: abs_path = abs_path_for_dynamic_library(libname, handle) if abs_path is None: raise RuntimeError(f"No expected symbol for {libname=!r}") - return LoadedDL(abs_path, False, handle._handle, FoundVia("system")) + return LoadedDL(abs_path, False, handle._handle, "system-search") return None @@ -195,7 +195,7 @@ def _work_around_known_bugs(libname: str, found_path: str) -> None: ctypes.CDLL(dep_path, CDLL_MODE) -def load_with_abs_path(libname: str, found_path: str, found_via: Optional[FoundVia] = None) -> LoadedDL: +def load_with_abs_path(libname: str, found_path: str, found_via: Optional[str] = None) -> LoadedDL: """Load a dynamic library from the given path. Args: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 187aeaaf2..5987e78b9 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -7,7 +7,7 @@ import struct from typing import Optional -from cuda.pathfinder._dynamic_libs.load_dl_common import FoundVia, LoadedDL +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY, SUPPORTED_WINDOWS_DLLS, @@ -101,7 +101,8 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.wintypes.HMODULE) def check_if_already_loaded_from_elsewhere( - libname: str, have_abs_path: bool, found_via: Optional[FoundVia] = None + libname: str, + have_abs_path: bool, ) -> Optional[LoadedDL]: for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): handle = kernel32.GetModuleHandleW(dll_name) @@ -112,7 +113,7 @@ def check_if_already_loaded_from_elsewhere( # load_with_abs_path(). To make the side-effect more deterministic, # activate it even if the library was already loaded from elsewhere. add_dll_directory(abs_path) - return LoadedDL(abs_path, True, ctypes_handle_to_unsigned_int(handle), found_via) + return LoadedDL(abs_path, True, ctypes_handle_to_unsigned_int(handle), "already-loaded-from-elsewhere") return None @@ -130,12 +131,12 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]: handle = kernel32.LoadLibraryExW(dll_name, None, 0) if handle: abs_path = abs_path_for_dynamic_library(libname, handle) - return LoadedDL(abs_path, False, ctypes_handle_to_unsigned_int(handle), FoundVia("system")) + return LoadedDL(abs_path, False, ctypes_handle_to_unsigned_int(handle), "system-search") return None -def load_with_abs_path(libname: str, found_path: str, found_via: Optional[FoundVia] = None) -> LoadedDL: +def load_with_abs_path(libname: str, found_path: str, found_via: Optional[str] = None) -> LoadedDL: """Load a dynamic library from the given path. Args: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index debbe315f..cb344958d 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -6,7 +6,7 @@ import sys from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _FindNvidiaDynamicLib -from cuda.pathfinder._dynamic_libs.load_dl_common import FoundVia, LoadedDL, load_dependencies +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies from cuda.pathfinder._utils.platform_aware import IS_WINDOWS if IS_WINDOWS: @@ -30,16 +30,14 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: if abs_path is None: abs_path = finder.try_with_conda_prefix() if abs_path is not None: - found_via = FoundVia("conda") + found_via = "conda" else: - found_via = FoundVia("site-packages") + found_via = "site-packages" # If the library was already loaded by someone else, reproduce any OS-specific # side-effects we would have applied on a direct absolute-path load (e.g., # AddDllDirectory on Windows for libs that require it). - loaded = check_if_already_loaded_from_elsewhere( - libname, abs_path is not None, found_via if abs_path is not None else None - ) + loaded = check_if_already_loaded_from_elsewhere(libname, abs_path is not None) # Load dependencies regardless of who loaded the primary lib first. # Doing this *after* the side-effect ensures dependencies resolve consistently @@ -57,7 +55,7 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: if abs_path is None: finder.raise_not_found_error() else: - found_via = FoundVia("CUDA_HOME") + found_via = "CUDA_HOME" return load_with_abs_path(libname, abs_path, found_via) diff --git a/cuda_pathfinder/tests/child_load_nvidia_dynamic_lib_helper.py b/cuda_pathfinder/tests/child_load_nvidia_dynamic_lib_helper.py index 72ee80c89..c644e59a8 100644 --- a/cuda_pathfinder/tests/child_load_nvidia_dynamic_lib_helper.py +++ b/cuda_pathfinder/tests/child_load_nvidia_dynamic_lib_helper.py @@ -43,6 +43,7 @@ def child_process_func(libname): if loaded_dl_fresh.was_already_loaded_from_elsewhere: raise RuntimeError("loaded_dl_fresh.was_already_loaded_from_elsewhere") validate_abs_path(loaded_dl_fresh.abs_path) + assert loaded_dl_fresh.foundvia is not None loaded_dl_from_cache = load_nvidia_dynamic_lib(libname) if loaded_dl_from_cache is not loaded_dl_fresh: From 8df1369906452df9c455042f5c80d815e25a0396 Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Wed, 8 Oct 2025 11:55:04 -0700 Subject: [PATCH 10/12] already :) --- cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index db43cd3a2..b91b9b62b 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -139,7 +139,7 @@ def check_if_already_loaded_from_elsewhere(libname: str, _have_abs_path: bool) - continue else: return LoadedDL( - abs_path_for_dynamic_library(libname, handle), True, handle._handle, "arleady-loaded-from-elsewhere" + abs_path_for_dynamic_library(libname, handle), True, handle._handle, "already-loaded-from-elsewhere" ) return None From f7994fcff7de89d506988b382ce6ccc5ad93c262 Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Thu, 9 Oct 2025 19:05:14 -0700 Subject: [PATCH 11/12] address reviews --- .../cuda/pathfinder/_dynamic_libs/load_dl_common.py | 2 +- .../cuda/pathfinder/_dynamic_libs/load_dl_linux.py | 2 +- .../cuda/pathfinder/_dynamic_libs/load_dl_windows.py | 2 +- .../pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py | 7 ++++--- .../tests/child_load_nvidia_dynamic_lib_helper.py | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 5d7cdfaf7..2e6c9eb17 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -16,7 +16,7 @@ class LoadedDL: abs_path: Optional[str] was_already_loaded_from_elsewhere: bool _handle_uint: int # Platform-agnostic unsigned pointer value - foundvia: Optional[str] = None + found_via: str def load_dependencies(libname: str, load_func: Callable[[str], LoadedDL]) -> None: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index b91b9b62b..040e24705 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -139,7 +139,7 @@ def check_if_already_loaded_from_elsewhere(libname: str, _have_abs_path: bool) - continue else: return LoadedDL( - abs_path_for_dynamic_library(libname, handle), True, handle._handle, "already-loaded-from-elsewhere" + abs_path_for_dynamic_library(libname, handle), True, handle._handle, "was-already-loaded-from-elsewhere" ) return None diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 5987e78b9..d8ac53fe8 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -113,7 +113,7 @@ def check_if_already_loaded_from_elsewhere( # load_with_abs_path(). To make the side-effect more deterministic, # activate it even if the library was already loaded from elsewhere. add_dll_directory(abs_path) - return LoadedDL(abs_path, True, ctypes_handle_to_unsigned_int(handle), "already-loaded-from-elsewhere") + return LoadedDL(abs_path, True, ctypes_handle_to_unsigned_int(handle), "was-already-loaded-from-elsewhere") return None diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index cb344958d..fe553a434 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -27,12 +27,13 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: finder = _FindNvidiaDynamicLib(libname) abs_path = finder.try_site_packages() - if abs_path is None: + abs_path = finder.try_site_packages() + if abs_path is not None: + found_via = "site-packages" + else: abs_path = finder.try_with_conda_prefix() if abs_path is not None: found_via = "conda" - else: - found_via = "site-packages" # If the library was already loaded by someone else, reproduce any OS-specific # side-effects we would have applied on a direct absolute-path load (e.g., diff --git a/cuda_pathfinder/tests/child_load_nvidia_dynamic_lib_helper.py b/cuda_pathfinder/tests/child_load_nvidia_dynamic_lib_helper.py index c644e59a8..685d2eda2 100644 --- a/cuda_pathfinder/tests/child_load_nvidia_dynamic_lib_helper.py +++ b/cuda_pathfinder/tests/child_load_nvidia_dynamic_lib_helper.py @@ -43,7 +43,7 @@ def child_process_func(libname): if loaded_dl_fresh.was_already_loaded_from_elsewhere: raise RuntimeError("loaded_dl_fresh.was_already_loaded_from_elsewhere") validate_abs_path(loaded_dl_fresh.abs_path) - assert loaded_dl_fresh.foundvia is not None + assert loaded_dl_fresh.found_via is not None loaded_dl_from_cache = load_nvidia_dynamic_lib(libname) if loaded_dl_from_cache is not loaded_dl_fresh: From e02bf250416b3e22fda22b2b3de9d04732ad5f38 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 9 Oct 2025 22:13:41 -0700 Subject: [PATCH 12/12] =?UTF-8?q?Update=20cuda-pathfinder=20version=20to?= =?UTF-8?q?=201.3.1=20(for=20release),=20move=201.X.Y-notes.rst=20?= =?UTF-8?q?=E2=86=92=201.3.1-notes.rst,=20add=20PR=201049=20to=20release?= =?UTF-8?q?=20notes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cuda_pathfinder/cuda/pathfinder/_version.py | 2 +- cuda_pathfinder/docs/nv-versions.json | 4 ++++ cuda_pathfinder/docs/source/release.rst | 1 + .../source/release/{1.X.Y-notes.rst => 1.3.1-notes.rst} | 7 +++++-- 4 files changed, 11 insertions(+), 3 deletions(-) rename cuda_pathfinder/docs/source/release/{1.X.Y-notes.rst => 1.3.1-notes.rst} (72%) diff --git a/cuda_pathfinder/cuda/pathfinder/_version.py b/cuda_pathfinder/cuda/pathfinder/_version.py index 56364e619..cb42a4a3c 100644 --- a/cuda_pathfinder/cuda/pathfinder/_version.py +++ b/cuda_pathfinder/cuda/pathfinder/_version.py @@ -1,4 +1,4 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -__version__ = "1.3.1a0" +__version__ = "1.3.1" diff --git a/cuda_pathfinder/docs/nv-versions.json b/cuda_pathfinder/docs/nv-versions.json index db8fecd82..f25c50bc6 100644 --- a/cuda_pathfinder/docs/nv-versions.json +++ b/cuda_pathfinder/docs/nv-versions.json @@ -3,6 +3,10 @@ "version": "latest", "url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/latest/" }, + { + "version": "1.3.1", + "url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/1.3.1/" + }, { "version": "1.3.0", "url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/1.3.0/" diff --git a/cuda_pathfinder/docs/source/release.rst b/cuda_pathfinder/docs/source/release.rst index b46579557..cd837b57f 100644 --- a/cuda_pathfinder/docs/source/release.rst +++ b/cuda_pathfinder/docs/source/release.rst @@ -7,6 +7,7 @@ Release Notes .. toctree:: :maxdepth: 3 + 1.3.1 1.3.0 1.2.3 1.2.2 diff --git a/cuda_pathfinder/docs/source/release/1.X.Y-notes.rst b/cuda_pathfinder/docs/source/release/1.3.1-notes.rst similarity index 72% rename from cuda_pathfinder/docs/source/release/1.X.Y-notes.rst rename to cuda_pathfinder/docs/source/release/1.3.1-notes.rst index 55a9c0628..8214716ca 100644 --- a/cuda_pathfinder/docs/source/release/1.X.Y-notes.rst +++ b/cuda_pathfinder/docs/source/release/1.3.1-notes.rst @@ -3,10 +3,10 @@ .. py:currentmodule:: cuda.pathfinder -``cuda-pathfinder`` 1.X.Y Release notes +``cuda-pathfinder`` 1.3.1 Release notes ======================================= -Released on TBD +Released on Oct 13, 2025 Highlights ---------- @@ -14,3 +14,6 @@ Highlights * supported_nvidia_libs.py updates: add nvidia-cublasmp-cu12, nvidia-cublasmp-cu13, nvidia-cudss-cu13 (`PR #1089 `_) + +* Add ``LoadedDL.found_via`` + (`PR #1049 `_)