From 9057a81645899da8b2d74c4389c5ebdc242befe7 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 26 Aug 2026 22:16:34 -0700 Subject: [PATCH 1/3] docs(pathfinder): define candidate search order --- .../cuda/pathfinder/_binaries/supported_nvidia_binaries.py | 2 +- .../cuda/pathfinder/_headers/header_descriptor_catalog.py | 2 ++ .../cuda/pathfinder/_static_libs/find_bitcode_lib.py | 2 ++ cuda_pathfinder/cuda/pathfinder/_static_libs/find_static_lib.py | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_binaries/supported_nvidia_binaries.py b/cuda_pathfinder/cuda/pathfinder/_binaries/supported_nvidia_binaries.py index ac70378f112..d547782d8da 100644 --- a/cuda_pathfinder/cuda/pathfinder/_binaries/supported_nvidia_binaries.py +++ b/cuda_pathfinder/cuda/pathfinder/_binaries/supported_nvidia_binaries.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 import os -# Site-packages bin directories where binaries might be found +# Site-packages bin directories where binaries might be found, in search order. # Based on NVIDIA wheel layouts (same for Linux and Windows) _CUDA_NVCC_BIN = os.path.join("nvidia", "cuda_nvcc", "bin") _CUDA13_BIN = os.path.join("nvidia", "cu13", "bin") diff --git a/cuda_pathfinder/cuda/pathfinder/_headers/header_descriptor_catalog.py b/cuda_pathfinder/cuda/pathfinder/_headers/header_descriptor_catalog.py index 14e4a3a28e6..66570bd264d 100644 --- a/cuda_pathfinder/cuda/pathfinder/_headers/header_descriptor_catalog.py +++ b/cuda_pathfinder/cuda/pathfinder/_headers/header_descriptor_catalog.py @@ -13,6 +13,8 @@ @dataclass(frozen=True, slots=True) class HeaderDescriptorSpec: + """Header metadata with ordered alternatives searched first-to-last.""" + name: str packaged_with: HeaderPackagedWith header_basename: str diff --git a/cuda_pathfinder/cuda/pathfinder/_static_libs/find_bitcode_lib.py b/cuda_pathfinder/cuda/pathfinder/_static_libs/find_bitcode_lib.py index 803abecaaae..fd9f3cdfe55 100644 --- a/cuda_pathfinder/cuda/pathfinder/_static_libs/find_bitcode_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_static_libs/find_bitcode_lib.py @@ -27,6 +27,8 @@ class LocatedBitcodeLib: class _BitcodeLibInfo(TypedDict): + """Bitcode-library metadata with ordered alternatives searched first-to-last.""" + filename: str rel_path: str site_packages_dirs: tuple[str, ...] diff --git a/cuda_pathfinder/cuda/pathfinder/_static_libs/find_static_lib.py b/cuda_pathfinder/cuda/pathfinder/_static_libs/find_static_lib.py index a5b1e84fc42..f0f1c85f538 100644 --- a/cuda_pathfinder/cuda/pathfinder/_static_libs/find_static_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_static_libs/find_static_lib.py @@ -28,6 +28,8 @@ class LocatedStaticLib: class _StaticLibInfo(TypedDict): + """Static-library metadata with ordered alternatives searched first-to-last.""" + filename: str ctk_rel_paths: tuple[str, ...] conda_rel_paths: tuple[str, ...] From 4918eff6de3764645544f1566879283f33c8116f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 26 Aug 2026 22:34:12 -0700 Subject: [PATCH 2/3] refactor(pathfinder): author library names in search order --- .../_dynamic_libs/descriptor_catalog.py | 140 +++++++++--------- .../_dynamic_libs/lib_descriptor.py | 6 - .../pathfinder/_dynamic_libs/load_dl_linux.py | 5 +- .../_dynamic_libs/load_dl_windows.py | 10 +- .../_dynamic_libs/search_platform.py | 9 +- .../_dynamic_libs/supported_nvidia_libs.py | 30 +++- .../tests/test_descriptor_catalog.py | 6 +- cuda_pathfinder/tests/test_lib_descriptor.py | 37 +++-- cuda_pathfinder/tests/test_load_dl_linux.py | 6 +- cuda_pathfinder/tests/test_load_dl_windows.py | 31 +++- cuda_pathfinder/tests/test_search_steps.py | 34 ++--- 11 files changed, 174 insertions(+), 140 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/descriptor_catalog.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/descriptor_catalog.py index cefba58f2ad..3b51f486278 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/descriptor_catalog.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/descriptor_catalog.py @@ -17,7 +17,7 @@ @dataclass(frozen=True, slots=True) class WindowsSearchDirs: - """Ordered Windows search locations grouped by process architecture.""" + """Windows search locations, highest priority first, grouped by architecture.""" x64: tuple[str, ...] = () arm64: tuple[str, ...] = () @@ -57,9 +57,11 @@ def _ctk_windows_wheel_dirs(cuda13_bin_dir: str, cuda12_dir: str) -> WindowsSear @dataclass(frozen=True, slots=True) class DescriptorSpec: + """Dynamic-library metadata; ordered search candidates are tried first-to-last.""" + name: str packaged_with: PackagedWith - # Keep declared SONAMEs in oldest -> newest order. + # Library filenames are authored in search/load preference order, most preferred first. linux_sonames: tuple[str, ...] = () windows_dlls: tuple[str, ...] = () supported_windows_arch: tuple[WindowsArch, ...] = () @@ -87,8 +89,8 @@ class DescriptorSpec: DescriptorSpec( name="cudart", packaged_with="ctk", - linux_sonames=("libcudart.so.12", "libcudart.so.13"), - windows_dlls=("cudart64_12.dll", "cudart64_13.dll"), + linux_sonames=("libcudart.so.13", "libcudart.so.12"), + windows_dlls=("cudart64_13.dll", "cudart64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cuda_runtime/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cuda_runtime/bin"), @@ -96,8 +98,8 @@ class DescriptorSpec: DescriptorSpec( name="nvfatbin", packaged_with="ctk", - linux_sonames=("libnvfatbin.so.12", "libnvfatbin.so.13"), - windows_dlls=("nvfatbin_120_0.dll", "nvfatbin_130_0.dll"), + linux_sonames=("libnvfatbin.so.13", "libnvfatbin.so.12"), + windows_dlls=("nvfatbin_130_0.dll", "nvfatbin_120_0.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/nvfatbin/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/nvfatbin/bin"), @@ -105,8 +107,8 @@ class DescriptorSpec: DescriptorSpec( name="nvJitLink", packaged_with="ctk", - linux_sonames=("libnvJitLink.so.12", "libnvJitLink.so.13"), - windows_dlls=("nvJitLink_120_0.dll", "nvJitLink_130_0.dll"), + linux_sonames=("libnvJitLink.so.13", "libnvJitLink.so.12"), + windows_dlls=("nvJitLink_130_0.dll", "nvJitLink_120_0.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/nvjitlink/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/nvjitlink/bin"), @@ -114,8 +116,8 @@ class DescriptorSpec: DescriptorSpec( name="nvrtc", packaged_with="ctk", - linux_sonames=("libnvrtc.so.12", "libnvrtc.so.13"), - windows_dlls=("nvrtc64_120_0.dll", "nvrtc64_130_0.dll"), + linux_sonames=("libnvrtc.so.13", "libnvrtc.so.12"), + windows_dlls=("nvrtc64_130_0.dll", "nvrtc64_120_0.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cuda_nvrtc/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cuda_nvrtc/bin"), @@ -124,8 +126,8 @@ class DescriptorSpec: DescriptorSpec( name="nvvm", packaged_with="ctk", - linux_sonames=("libnvvm.so", "libnvvm.so.4"), - windows_dlls=("nvvm64.dll", "nvvm64_40_0.dll", "nvvm70.dll"), + linux_sonames=("libnvvm.so.4", "libnvvm.so"), + windows_dlls=("nvvm70.dll", "nvvm64_40_0.dll", "nvvm64.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cuda_nvcc/nvvm/lib64"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cuda_nvcc/nvvm/bin"), @@ -146,8 +148,8 @@ class DescriptorSpec: DescriptorSpec( name="cublas", packaged_with="ctk", - linux_sonames=("libcublas.so.12", "libcublas.so.13"), - windows_dlls=("cublas64_12.dll", "cublas64_13.dll"), + linux_sonames=("libcublas.so.13", "libcublas.so.12"), + windows_dlls=("cublas64_13.dll", "cublas64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cublas/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cublas/bin"), @@ -156,8 +158,8 @@ class DescriptorSpec: DescriptorSpec( name="cublasLt", packaged_with="ctk", - linux_sonames=("libcublasLt.so.12", "libcublasLt.so.13"), - windows_dlls=("cublasLt64_12.dll", "cublasLt64_13.dll"), + linux_sonames=("libcublasLt.so.13", "libcublasLt.so.12"), + windows_dlls=("cublasLt64_13.dll", "cublasLt64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cublas/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cublas/bin"), @@ -165,8 +167,8 @@ class DescriptorSpec: DescriptorSpec( name="cufft", packaged_with="ctk", - linux_sonames=("libcufft.so.11", "libcufft.so.12"), - windows_dlls=("cufft64_11.dll", "cufft64_12.dll"), + linux_sonames=("libcufft.so.12", "libcufft.so.11"), + windows_dlls=("cufft64_12.dll", "cufft64_11.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cufft/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cufft/bin"), @@ -175,8 +177,8 @@ class DescriptorSpec: DescriptorSpec( name="cufftw", packaged_with="ctk", - linux_sonames=("libcufftw.so.11", "libcufftw.so.12"), - windows_dlls=("cufftw64_11.dll", "cufftw64_12.dll"), + linux_sonames=("libcufftw.so.12", "libcufftw.so.11"), + windows_dlls=("cufftw64_12.dll", "cufftw64_11.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cufft/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cufft/bin"), @@ -185,8 +187,8 @@ class DescriptorSpec: DescriptorSpec( name="curand", packaged_with="ctk", - linux_sonames=("libcurand.so.10", "libcurand.so.11"), - windows_dlls=("curand64_10.dll", "curand64_11.dll"), + linux_sonames=("libcurand.so.11", "libcurand.so.10"), + windows_dlls=("curand64_11.dll", "curand64_10.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/curand/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/curand/bin"), @@ -194,8 +196,8 @@ class DescriptorSpec: DescriptorSpec( name="cusolver", packaged_with="ctk", - linux_sonames=("libcusolver.so.11", "libcusolver.so.12"), - windows_dlls=("cusolver64_11.dll", "cusolver64_12.dll"), + linux_sonames=("libcusolver.so.12", "libcusolver.so.11"), + windows_dlls=("cusolver64_12.dll", "cusolver64_11.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cusolver/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cusolver/bin"), @@ -204,8 +206,8 @@ class DescriptorSpec: DescriptorSpec( name="cusolverMg", packaged_with="ctk", - linux_sonames=("libcusolverMg.so.11", "libcusolverMg.so.12"), - windows_dlls=("cusolverMg64_11.dll", "cusolverMg64_12.dll"), + linux_sonames=("libcusolverMg.so.12", "libcusolverMg.so.11"), + windows_dlls=("cusolverMg64_12.dll", "cusolverMg64_11.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cusolver/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cusolver/bin"), @@ -224,8 +226,8 @@ class DescriptorSpec: DescriptorSpec( name="nppc", packaged_with="ctk", - linux_sonames=("libnppc.so.12", "libnppc.so.13"), - windows_dlls=("nppc64_12.dll", "nppc64_13.dll"), + linux_sonames=("libnppc.so.13", "libnppc.so.12"), + windows_dlls=("nppc64_13.dll", "nppc64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -233,8 +235,8 @@ class DescriptorSpec: DescriptorSpec( name="nppial", packaged_with="ctk", - linux_sonames=("libnppial.so.12", "libnppial.so.13"), - windows_dlls=("nppial64_12.dll", "nppial64_13.dll"), + linux_sonames=("libnppial.so.13", "libnppial.so.12"), + windows_dlls=("nppial64_13.dll", "nppial64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -243,8 +245,8 @@ class DescriptorSpec: DescriptorSpec( name="nppicc", packaged_with="ctk", - linux_sonames=("libnppicc.so.12", "libnppicc.so.13"), - windows_dlls=("nppicc64_12.dll", "nppicc64_13.dll"), + linux_sonames=("libnppicc.so.13", "libnppicc.so.12"), + windows_dlls=("nppicc64_13.dll", "nppicc64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -253,8 +255,8 @@ class DescriptorSpec: DescriptorSpec( name="nppidei", packaged_with="ctk", - linux_sonames=("libnppidei.so.12", "libnppidei.so.13"), - windows_dlls=("nppidei64_12.dll", "nppidei64_13.dll"), + linux_sonames=("libnppidei.so.13", "libnppidei.so.12"), + windows_dlls=("nppidei64_13.dll", "nppidei64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -263,8 +265,8 @@ class DescriptorSpec: DescriptorSpec( name="nppif", packaged_with="ctk", - linux_sonames=("libnppif.so.12", "libnppif.so.13"), - windows_dlls=("nppif64_12.dll", "nppif64_13.dll"), + linux_sonames=("libnppif.so.13", "libnppif.so.12"), + windows_dlls=("nppif64_13.dll", "nppif64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -273,8 +275,8 @@ class DescriptorSpec: DescriptorSpec( name="nppig", packaged_with="ctk", - linux_sonames=("libnppig.so.12", "libnppig.so.13"), - windows_dlls=("nppig64_12.dll", "nppig64_13.dll"), + linux_sonames=("libnppig.so.13", "libnppig.so.12"), + windows_dlls=("nppig64_13.dll", "nppig64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -283,8 +285,8 @@ class DescriptorSpec: DescriptorSpec( name="nppim", packaged_with="ctk", - linux_sonames=("libnppim.so.12", "libnppim.so.13"), - windows_dlls=("nppim64_12.dll", "nppim64_13.dll"), + linux_sonames=("libnppim.so.13", "libnppim.so.12"), + windows_dlls=("nppim64_13.dll", "nppim64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -293,8 +295,8 @@ class DescriptorSpec: DescriptorSpec( name="nppist", packaged_with="ctk", - linux_sonames=("libnppist.so.12", "libnppist.so.13"), - windows_dlls=("nppist64_12.dll", "nppist64_13.dll"), + linux_sonames=("libnppist.so.13", "libnppist.so.12"), + windows_dlls=("nppist64_13.dll", "nppist64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -303,8 +305,8 @@ class DescriptorSpec: DescriptorSpec( name="nppisu", packaged_with="ctk", - linux_sonames=("libnppisu.so.12", "libnppisu.so.13"), - windows_dlls=("nppisu64_12.dll", "nppisu64_13.dll"), + linux_sonames=("libnppisu.so.13", "libnppisu.so.12"), + windows_dlls=("nppisu64_13.dll", "nppisu64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -313,8 +315,8 @@ class DescriptorSpec: DescriptorSpec( name="nppitc", packaged_with="ctk", - linux_sonames=("libnppitc.so.12", "libnppitc.so.13"), - windows_dlls=("nppitc64_12.dll", "nppitc64_13.dll"), + linux_sonames=("libnppitc.so.13", "libnppitc.so.12"), + windows_dlls=("nppitc64_13.dll", "nppitc64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -323,8 +325,8 @@ class DescriptorSpec: DescriptorSpec( name="npps", packaged_with="ctk", - linux_sonames=("libnpps.so.12", "libnpps.so.13"), - windows_dlls=("npps64_12.dll", "npps64_13.dll"), + linux_sonames=("libnpps.so.13", "libnpps.so.12"), + windows_dlls=("npps64_13.dll", "npps64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/npp/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/npp/bin"), @@ -333,8 +335,8 @@ class DescriptorSpec: DescriptorSpec( name="nvblas", packaged_with="ctk", - linux_sonames=("libnvblas.so.12", "libnvblas.so.13"), - windows_dlls=("nvblas64_12.dll", "nvblas64_13.dll"), + linux_sonames=("libnvblas.so.13", "libnvblas.so.12"), + windows_dlls=("nvblas64_13.dll", "nvblas64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cublas/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/cublas/bin"), @@ -343,8 +345,8 @@ class DescriptorSpec: DescriptorSpec( name="nvjpeg", packaged_with="ctk", - linux_sonames=("libnvjpeg.so.12", "libnvjpeg.so.13"), - windows_dlls=("nvjpeg64_12.dll", "nvjpeg64_13.dll"), + linux_sonames=("libnvjpeg.so.13", "libnvjpeg.so.12"), + windows_dlls=("nvjpeg64_13.dll", "nvjpeg64_12.dll"), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/nvjpeg/lib"), site_packages_windows=_ctk_windows_wheel_dirs("nvidia/cu13/bin", "nvidia/nvjpeg/bin"), @@ -358,24 +360,24 @@ class DescriptorSpec: DescriptorSpec( name="cupti", packaged_with="ctk", - linux_sonames=("libcupti.so.12", "libcupti.so.13"), + linux_sonames=("libcupti.so.13", "libcupti.so.12"), windows_dlls=( - "cupti64_2022.4.1.dll", - "cupti64_2023.1.1.dll", - "cupti64_2023.2.2.dll", - "cupti64_2023.3.1.dll", - "cupti64_2024.1.1.dll", - "cupti64_2024.2.1.dll", - "cupti64_2024.3.2.dll", - "cupti64_2025.1.1.dll", - "cupti64_2025.2.1.dll", - "cupti64_2025.3.1.dll", - "cupti64_2025.4.1.dll", - "cupti64_2026.1.0.dll", - "cupti64_2026.1.1.dll", - "cupti64_2026.2.0.dll", - "cupti64_2026.2.1.dll", "cupti64_2026.3.0.dll", + "cupti64_2026.2.1.dll", + "cupti64_2026.2.0.dll", + "cupti64_2026.1.1.dll", + "cupti64_2026.1.0.dll", + "cupti64_2025.4.1.dll", + "cupti64_2025.3.1.dll", + "cupti64_2025.2.1.dll", + "cupti64_2025.1.1.dll", + "cupti64_2024.3.2.dll", + "cupti64_2024.2.1.dll", + "cupti64_2024.1.1.dll", + "cupti64_2023.3.1.dll", + "cupti64_2023.2.2.dll", + "cupti64_2023.1.1.dll", + "cupti64_2022.4.1.dll", ), supported_windows_arch=("x64", "arm64"), site_packages_linux=("nvidia/cu13/lib", "nvidia/cuda_cupti/lib"), @@ -413,7 +415,7 @@ class DescriptorSpec: DescriptorSpec( name="cufftMp", packaged_with="other", - linux_sonames=("libcufftMp.so.11", "libcufftMp.so.12"), + linux_sonames=("libcufftMp.so.12", "libcufftMp.so.11"), site_packages_linux=("nvidia/cufftmp/cu13/lib", "nvidia/cufftmp/cu12/lib"), dependencies=("nvshmem_host",), requires_rtld_deepbind=True, diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/lib_descriptor.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/lib_descriptor.py index 433f636c10e..f5e643e28fa 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/lib_descriptor.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/lib_descriptor.py @@ -22,9 +22,3 @@ #: Canonical registry of all known libraries. LIB_DESCRIPTORS: dict[str, LibDescriptor] = {desc.name: desc for desc in DESCRIPTOR_CATALOG} - - -def linux_soname_candidates(desc: LibDescriptor) -> tuple[str, ...]: - """Return declared Linux SONAMEs in runtime preference order.""" - # The catalog is authored oldest -> newest; loading prefers newest -> oldest. - return tuple(reversed(desc.linux_sonames)) 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 429d37b5f62..d9b6f2d8d9f 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -10,7 +10,6 @@ import sys from typing import TYPE_CHECKING, cast -from cuda.pathfinder._dynamic_libs.lib_descriptor import linux_soname_candidates from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL if TYPE_CHECKING: @@ -133,7 +132,7 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.CDLL) -> str: if sys.platform == "linux": def check_if_already_loaded_from_elsewhere(desc: LibDescriptor) -> LoadedDL | None: - for soname in linux_soname_candidates(desc): + for soname in desc.linux_sonames: try: handle = ctypes.CDLL(soname, mode=os.RTLD_NOLOAD) except OSError: @@ -171,7 +170,7 @@ def load_with_system_search(desc: LibDescriptor) -> LoadedDL | None: A LoadedDL object if successful, None if the library cannot be loaded """ - for soname in linux_soname_candidates(desc): + for soname in desc.linux_sonames: try: handle = _load_lib(desc, soname) except OSError: 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 ef11e6ae042..a659409fc83 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -9,7 +9,6 @@ import struct import sys import warnings -from collections.abc import Iterator from typing import TYPE_CHECKING from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL @@ -121,13 +120,8 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.wintypes.HMODULE) return buffer.value -def _candidate_dll_names(desc: LibDescriptor) -> Iterator[str]: - """Yield tabulated DLL names from newest to oldest.""" - return reversed(desc.windows_dlls) - - def check_if_already_loaded_from_elsewhere(desc: LibDescriptor) -> LoadedDL | None: - for dll_name in _candidate_dll_names(desc): + for dll_name in desc.windows_dlls: handle = kernel32.GetModuleHandleW(dll_name) if handle: abs_path = abs_path_for_dynamic_library(desc.name, handle) @@ -154,7 +148,7 @@ def load_with_system_search(desc: LibDescriptor) -> LoadedDL | None: Returns: A LoadedDL object if successful, None if the library cannot be loaded """ - for dll_name in _candidate_dll_names(desc): + for dll_name in desc.windows_dlls: handle = kernel32.LoadLibraryExW(dll_name, None, 0) if handle: abs_path = abs_path_for_dynamic_library(desc.name, handle) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/search_platform.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/search_platform.py index a9afb545409..71a92b00924 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/search_platform.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/search_platform.py @@ -16,7 +16,7 @@ from pathlib import PurePath from typing import Protocol, cast -from cuda.pathfinder._dynamic_libs.lib_descriptor import LibDescriptor, linux_soname_candidates +from cuda.pathfinder._dynamic_libs.lib_descriptor import LibDescriptor from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import is_suppressed_dll_file from cuda.pathfinder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages from cuda.pathfinder._utils.platform_aware import IS_WINDOWS @@ -34,7 +34,7 @@ def _no_such_file_in_sub_dirs( def _find_descriptor_so_under_dir(dirpath: str, desc: LibDescriptor) -> str | None: - for soname in linux_soname_candidates(desc): + for soname in desc.linux_sonames: path = os.path.join(dirpath, soname) if os.path.isfile(path): return path @@ -73,8 +73,7 @@ def candidate_is_usable(path: str) -> bool: return False return target_arch is None or windows_pe_matches_arch(path, target_arch) - # Try the descriptor's known DLL names in its established search order. - for dll_basename in reversed(cast(tuple[str, ...], desc.windows_dlls)): + for dll_basename in desc.windows_dlls: path = os.path.join(dirpath, dll_basename) if candidate_is_usable(path): return path @@ -138,7 +137,7 @@ def find_in_lib_dir( @dataclass(frozen=True, slots=True) class LinuxSearchPlatform: def lib_searched_for(self, desc: LibDescriptor) -> str: - return " or ".join(linux_soname_candidates(desc)) + return " or ".join(desc.linux_sonames) def site_packages_rel_dirs(self, desc: LibDescriptor) -> tuple[str, ...]: return cast(tuple[str, ...], desc.site_packages_linux) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py index daf696b638e..02951cba52e 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py @@ -24,6 +24,12 @@ _DRIVER_DESCRIPTORS = tuple(desc for desc in DESCRIPTOR_CATALOG if desc.packaged_with == "driver") _NON_CTK_DESCRIPTORS = _OTHER_DESCRIPTORS + _DRIVER_DESCRIPTORS + +def _legacy_least_preferred_first(names: tuple[str, ...]) -> tuple[str, ...]: + """Preserve the historical ordering of legacy filename projections.""" + return tuple(reversed(names)) + + SUPPORTED_LIBNAMES_COMMON = tuple(desc.name for desc in _CTK_DESCRIPTORS if desc.linux_sonames and desc.windows_dlls) SUPPORTED_LIBNAMES_LINUX_ONLY = tuple( desc.name for desc in _CTK_DESCRIPTORS if desc.linux_sonames and not desc.windows_dlls @@ -60,14 +66,26 @@ DIRECT_DEPENDENCIES_CTK = {desc.name: desc.dependencies for desc in _CTK_DESCRIPTORS if desc.dependencies} DIRECT_DEPENDENCIES = {desc.name: desc.dependencies for desc in DESCRIPTOR_CATALOG if desc.dependencies} -SUPPORTED_LINUX_SONAMES_CTK = {desc.name: desc.linux_sonames for desc in _CTK_DESCRIPTORS if desc.linux_sonames} -SUPPORTED_LINUX_SONAMES_OTHER = {desc.name: desc.linux_sonames for desc in _OTHER_DESCRIPTORS if desc.linux_sonames} -SUPPORTED_LINUX_SONAMES_DRIVER = {desc.name: desc.linux_sonames for desc in _DRIVER_DESCRIPTORS if desc.linux_sonames} +SUPPORTED_LINUX_SONAMES_CTK = { + desc.name: _legacy_least_preferred_first(desc.linux_sonames) for desc in _CTK_DESCRIPTORS if desc.linux_sonames +} +SUPPORTED_LINUX_SONAMES_OTHER = { + desc.name: _legacy_least_preferred_first(desc.linux_sonames) for desc in _OTHER_DESCRIPTORS if desc.linux_sonames +} +SUPPORTED_LINUX_SONAMES_DRIVER = { + desc.name: _legacy_least_preferred_first(desc.linux_sonames) for desc in _DRIVER_DESCRIPTORS if desc.linux_sonames +} SUPPORTED_LINUX_SONAMES = SUPPORTED_LINUX_SONAMES_CTK | SUPPORTED_LINUX_SONAMES_OTHER | SUPPORTED_LINUX_SONAMES_DRIVER -SUPPORTED_WINDOWS_DLLS_CTK = {desc.name: desc.windows_dlls for desc in _CTK_DESCRIPTORS if desc.windows_dlls} -SUPPORTED_WINDOWS_DLLS_OTHER = {desc.name: desc.windows_dlls for desc in _OTHER_DESCRIPTORS if desc.windows_dlls} -SUPPORTED_WINDOWS_DLLS_DRIVER = {desc.name: desc.windows_dlls for desc in _DRIVER_DESCRIPTORS if desc.windows_dlls} +SUPPORTED_WINDOWS_DLLS_CTK = { + desc.name: _legacy_least_preferred_first(desc.windows_dlls) for desc in _CTK_DESCRIPTORS if desc.windows_dlls +} +SUPPORTED_WINDOWS_DLLS_OTHER = { + desc.name: _legacy_least_preferred_first(desc.windows_dlls) for desc in _OTHER_DESCRIPTORS if desc.windows_dlls +} +SUPPORTED_WINDOWS_DLLS_DRIVER = { + desc.name: _legacy_least_preferred_first(desc.windows_dlls) for desc in _DRIVER_DESCRIPTORS if desc.windows_dlls +} SUPPORTED_WINDOWS_DLLS = SUPPORTED_WINDOWS_DLLS_CTK | SUPPORTED_WINDOWS_DLLS_OTHER | SUPPORTED_WINDOWS_DLLS_DRIVER LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY = tuple( diff --git a/cuda_pathfinder/tests/test_descriptor_catalog.py b/cuda_pathfinder/tests/test_descriptor_catalog.py index a4b3227018b..835e7572ef0 100644 --- a/cuda_pathfinder/tests/test_descriptor_catalog.py +++ b/cuda_pathfinder/tests/test_descriptor_catalog.py @@ -14,7 +14,6 @@ import pytest from cuda.pathfinder._dynamic_libs.descriptor_catalog import DESCRIPTOR_CATALOG, DescriptorSpec, WindowsSearchDirs -from cuda.pathfinder._utils.path_sort import numeric_aware_path_sort_key _VALID_NAME_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$") _VALID_PACKAGED_WITH_VALUES = {"ctk", "other", "driver"} @@ -92,8 +91,9 @@ def test_linux_sonames_look_like_sonames(spec: DescriptorSpec): @pytest.mark.parametrize("spec", DESCRIPTOR_CATALOG, ids=lambda s: s.name) @pytest.mark.agent_authored(model="gpt-5.6-sol") -def test_linux_sonames_are_ordered_oldest_to_newest(spec: DescriptorSpec): - assert spec.linux_sonames == tuple(sorted(spec.linux_sonames, key=numeric_aware_path_sort_key)) +def test_library_filenames_are_unique_per_platform(spec: DescriptorSpec): + assert len(spec.linux_sonames) == len(set(spec.linux_sonames)) + assert len(spec.windows_dlls) == len({dll.casefold() for dll in spec.windows_dlls}) @pytest.mark.parametrize("spec", DESCRIPTOR_CATALOG, ids=lambda s: s.name) diff --git a/cuda_pathfinder/tests/test_lib_descriptor.py b/cuda_pathfinder/tests/test_lib_descriptor.py index cdfac333c9d..d56ee464378 100644 --- a/cuda_pathfinder/tests/test_lib_descriptor.py +++ b/cuda_pathfinder/tests/test_lib_descriptor.py @@ -1,12 +1,11 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -"""Tests verifying that the LibDescriptor registry faithfully represents -the existing data tables in supported_nvidia_libs.py.""" +"""Tests for the canonical library descriptors and their legacy projections.""" import pytest -from cuda.pathfinder._dynamic_libs.lib_descriptor import LIB_DESCRIPTORS, linux_soname_candidates +from cuda.pathfinder._dynamic_libs.lib_descriptor import LIB_DESCRIPTORS from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( DIRECT_DEPENDENCIES, LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY, @@ -54,12 +53,12 @@ def test_registry_has_no_extra_entries(): @pytest.mark.parametrize("name", sorted(LIB_DESCRIPTORS)) def test_linux_sonames_match(name): - assert LIB_DESCRIPTORS[name].linux_sonames == SUPPORTED_LINUX_SONAMES.get(name, ()) + assert tuple(reversed(LIB_DESCRIPTORS[name].linux_sonames)) == SUPPORTED_LINUX_SONAMES.get(name, ()) @pytest.mark.parametrize("name", sorted(LIB_DESCRIPTORS)) def test_windows_dlls_match(name): - assert LIB_DESCRIPTORS[name].windows_dlls == SUPPORTED_WINDOWS_DLLS.get(name, ()) + assert tuple(reversed(LIB_DESCRIPTORS[name].windows_dlls)) == SUPPORTED_WINDOWS_DLLS.get(name, ()) @pytest.mark.parametrize("name", sorted(LIB_DESCRIPTORS)) @@ -156,23 +155,35 @@ def test_descriptor_is_frozen(): @pytest.mark.agent_authored(model="gpt-5.6-sol") -def test_linux_soname_candidates_are_declared_names_newest_first(): +def test_linux_sonames_are_authored_in_runtime_preference_order(): desc = LIB_DESCRIPTORS["cudart"] - assert desc.linux_sonames == ("libcudart.so.12", "libcudart.so.13") - assert linux_soname_candidates(desc) == ("libcudart.so.13", "libcudart.so.12") + assert desc.linux_sonames == ("libcudart.so.13", "libcudart.so.12") @pytest.mark.agent_authored(model="gpt-5.6-sol") -def test_linux_soname_candidates_preserve_explicit_unversioned_name(): +def test_linux_sonames_preserve_explicit_unversioned_name(): desc = LIB_DESCRIPTORS["nvcudla"] - assert linux_soname_candidates(desc) == ("libnvcudla.so",) + assert desc.linux_sonames == ("libnvcudla.so",) @pytest.mark.agent_authored(model="gpt-5.6-sol") -def test_linux_soname_candidates_prefer_versioned_name_over_declared_unversioned_name(): +def test_linux_sonames_prefer_versioned_name_over_declared_unversioned_name(): desc = LIB_DESCRIPTORS["nvvm"] - assert desc.linux_sonames == ("libnvvm.so", "libnvvm.so.4") - assert linux_soname_candidates(desc) == ("libnvvm.so.4", "libnvvm.so") + assert desc.linux_sonames == ("libnvvm.so.4", "libnvvm.so") + + +@pytest.mark.agent_authored(model="gpt-5.6-sol") +def test_windows_dlls_are_authored_in_runtime_preference_order(): + desc = LIB_DESCRIPTORS["nvvm"] + + assert desc.windows_dlls == ("nvvm70.dll", "nvvm64_40_0.dll", "nvvm64.dll") + + +@pytest.mark.agent_authored(model="gpt-5.6-sol") +def test_cufft_mp_sonames_preserve_abi_preference(): + desc = LIB_DESCRIPTORS["cufftMp"] + + assert desc.linux_sonames == ("libcufftMp.so.12", "libcufftMp.so.11") diff --git a/cuda_pathfinder/tests/test_load_dl_linux.py b/cuda_pathfinder/tests/test_load_dl_linux.py index cfcf0ef29f8..df7b1718a1b 100644 --- a/cuda_pathfinder/tests/test_load_dl_linux.py +++ b/cuda_pathfinder/tests/test_load_dl_linux.py @@ -17,12 +17,12 @@ def _descriptor() -> DescriptorSpec: return DescriptorSpec( name="probe", packaged_with="other", - linux_sonames=("libprobe.so.12", "libprobe.so.13"), + linux_sonames=("libprobe.so.13", "libprobe.so.12"), ) @pytest.mark.agent_authored(model="gpt-5.6-sol") -def test_already_loaded_library_checks_only_declared_sonames_newest_first(mocker): +def test_already_loaded_library_checks_declared_sonames_in_preference_order(mocker): queried_sonames: list[tuple[str, int]] = [] def cdll(soname, mode): @@ -41,7 +41,7 @@ def cdll(soname, mode): @pytest.mark.agent_authored(model="gpt-5.6-sol") -def test_system_search_checks_only_declared_sonames_newest_first(mocker): +def test_system_search_checks_declared_sonames_in_preference_order(mocker): queried_sonames: list[str] = [] def load_lib(_desc, soname): diff --git a/cuda_pathfinder/tests/test_load_dl_windows.py b/cuda_pathfinder/tests/test_load_dl_windows.py index bf5b8ecd88d..28a2e51b368 100644 --- a/cuda_pathfinder/tests/test_load_dl_windows.py +++ b/cuda_pathfinder/tests/test_load_dl_windows.py @@ -13,28 +13,45 @@ @pytest.mark.agent_authored(model="gpt-5.6-sol") -def test_already_loaded_library_checks_known_dlls_newest_first(mocker): +def test_already_loaded_library_checks_known_dlls_in_preference_order(mocker): desc = LIB_DESCRIPTORS["cublasLt"] - oldest_dll = desc.windows_dlls[0] - newest_dll = desc.windows_dlls[-1] + preferred_dll = desc.windows_dlls[0] + fallback_dll = desc.windows_dlls[-1] queried_dlls: list[str] = [] handle = 0xBEEF def get_module_handle(dll_name): queried_dlls.append(dll_name) - return handle if dll_name == oldest_dll else 0 + return handle if dll_name == fallback_dll else 0 mocker.patch.object(load_dl_windows.kernel32, "GetModuleHandleW", side_effect=get_module_handle) mocker.patch.object( load_dl_windows, "abs_path_for_dynamic_library", - return_value=rf"C:\CUDA\bin\{oldest_dll}", + return_value=rf"C:\CUDA\bin\{fallback_dll}", ) loaded = load_dl_windows.check_if_already_loaded_from_elsewhere(desc) assert loaded is not None - assert queried_dlls == [newest_dll, oldest_dll] + assert queried_dlls == list(desc.windows_dlls) + + +@pytest.mark.agent_authored(model="gpt-5.6-sol") +def test_system_search_checks_known_dlls_in_preference_order(mocker): + desc = LIB_DESCRIPTORS["cublasLt"] + queried_dlls: list[str] = [] + + def load_library(dll_name, _file, _flags): + queried_dlls.append(dll_name) + return 0 + + mocker.patch.object(load_dl_windows.kernel32, "LoadLibraryExW", side_effect=load_library) + + loaded = load_dl_windows.load_with_system_search(desc) + + assert loaded is None + assert queried_dlls == list(desc.windows_dlls) @pytest.mark.parametrize( @@ -46,7 +63,7 @@ def test_already_loaded_library_registers_resolved_directory_by_descriptor_polic mocker, tmp_path, libname, register_directory ): desc = LIB_DESCRIPTORS[libname] - resolved_path = str(tmp_path / desc.windows_dlls[-1]) + resolved_path = str(tmp_path / desc.windows_dlls[0]) handle = 0xBEEF mocker.patch.object(load_dl_windows.kernel32, "GetModuleHandleW", return_value=handle) mocker.patch.object(load_dl_windows, "abs_path_for_dynamic_library", return_value=resolved_path) diff --git a/cuda_pathfinder/tests/test_search_steps.py b/cuda_pathfinder/tests/test_search_steps.py index 85f60861dab..5fa194d544a 100644 --- a/cuda_pathfinder/tests/test_search_steps.py +++ b/cuda_pathfinder/tests/test_search_steps.py @@ -366,15 +366,15 @@ def test_windows_matching_rejects_unlisted_cupti_name(self, mocker, tmp_path): assert result is None @pytest.mark.agent_authored(model="gpt-5.6-sol") - def test_windows_known_cupti_names_prefer_newest(self, tmp_path): - older_dll = tmp_path / "cupti64_2026.2.1.dll" - newer_dll = tmp_path / "cupti64_2026.3.0.dll" - older_dll.touch() - newer_dll.touch() + def test_windows_known_cupti_names_follow_declared_preference_order(self, tmp_path): + preferred_dll = tmp_path / "cupti64_2026.3.0.dll" + fallback_dll = tmp_path / "cupti64_2026.2.1.dll" + preferred_dll.touch() + fallback_dll.touch() result = _find_descriptor_dll_under_dir(str(tmp_path), LIB_DESCRIPTORS["cupti"]) - assert result == str(newer_dll) + assert result == str(preferred_dll) @pytest.mark.parametrize( ("libname", "sibling_dll"), @@ -497,30 +497,30 @@ def test_linux_declared_versioned_soname_does_not_need_unversioned_link(self, mo return_value=[str(lib_dir)], ) - desc = _make_desc(linux_sonames=("libcudart.so.12", "libcudart.so.13")) + desc = _make_desc(linux_sonames=("libcudart.so.13", "libcudart.so.12")) result = find_in_site_packages(_ctx(desc, platform=LinuxSearchPlatform())) assert result is not None assert result.abs_path == str(versioned) assert result.found_via == "site-packages" @pytest.mark.agent_authored(model="gpt-5.6-sol") - def test_linux_declared_sonames_prefer_newest(self, mocker, tmp_path): + def test_linux_declared_sonames_follow_preference_order(self, mocker, tmp_path): lib_dir = tmp_path / "nvidia" / "cuda_runtime" / "lib" lib_dir.mkdir(parents=True) - older = lib_dir / "libcudart.so.12" - newer = lib_dir / "libcudart.so.13" - older.touch() - newer.touch() + preferred = lib_dir / "libcudart.so.13" + fallback = lib_dir / "libcudart.so.12" + preferred.touch() + fallback.touch() mocker.patch( f"{_PLAT_MOD}.find_sub_dirs_all_sitepackages", return_value=[str(lib_dir)], ) - desc = _make_desc(linux_sonames=("libcudart.so.12", "libcudart.so.13")) + desc = _make_desc(linux_sonames=("libcudart.so.13", "libcudart.so.12")) result = find_in_site_packages(_ctx(desc, platform=LinuxSearchPlatform())) assert result is not None - assert result.abs_path == str(newer) + assert result.abs_path == str(preferred) assert result.found_via == "site-packages" @pytest.mark.parametrize( @@ -538,7 +538,7 @@ def test_linux_rejects_undeclared_filename(self, mocker, tmp_path, undeclared_fi return_value=[str(lib_dir)], ) - desc = _make_desc(linux_sonames=("libcudart.so.12", "libcudart.so.13")) + desc = _make_desc(linux_sonames=("libcudart.so.13", "libcudart.so.12")) ctx = _ctx(desc, platform=LinuxSearchPlatform()) result = find_in_site_packages(ctx) assert result is None @@ -612,7 +612,7 @@ def test_linux_declared_versioned_soname_found_in_lib_dir(self, mocker, tmp_path mocker.patch.dict(os.environ, {"CONDA_PREFIX": str(tmp_path)}) - desc = _make_desc(linux_sonames=("libcudart.so.12", "libcudart.so.13")) + desc = _make_desc(linux_sonames=("libcudart.so.13", "libcudart.so.12")) result = find_in_conda(_ctx(desc, platform=LinuxSearchPlatform())) assert result is not None assert result.abs_path == str(versioned) @@ -630,7 +630,7 @@ def test_linux_rejects_undeclared_filename_in_lib_dir(self, mocker, tmp_path, un mocker.patch.dict(os.environ, {"CONDA_PREFIX": str(tmp_path)}) - desc = _make_desc(linux_sonames=("libcudart.so.12", "libcudart.so.13")) + desc = _make_desc(linux_sonames=("libcudart.so.13", "libcudart.so.12")) ctx = _ctx(desc, platform=LinuxSearchPlatform()) result = find_in_conda(ctx) assert result is None From e7705a77eb84e91050134115a91f814d26108939 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 26 Aug 2026 22:36:43 -0700 Subject: [PATCH 3/3] docs(pathfinder): document candidate order cleanup --- .../docs/source/release/1.8.0-notes.rst | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/cuda_pathfinder/docs/source/release/1.8.0-notes.rst b/cuda_pathfinder/docs/source/release/1.8.0-notes.rst index 0caa72652ed..7b707087881 100644 --- a/cuda_pathfinder/docs/source/release/1.8.0-notes.rst +++ b/cuda_pathfinder/docs/source/release/1.8.0-notes.rst @@ -27,10 +27,20 @@ Bugfixes (`PR #2689 `_) * Make Linux filesystem discovery, already-loaded detection, and native loading - use one descriptor-declared, newest-first library filename list. Remove the - implicit ``lib.so`` and broad ``.so*`` filesystem fallbacks, so - explicit directory layouts must expose a declared filename. Explicitly - declare the unversioned ``libnvvm.so`` wheel filename to preserve CUDA 12.9 - wheel discovery, and correct the ``cufftMp`` catalog order so ABI 12 is - preferred over ABI 11. + use one descriptor-declared library filename list in runtime preference + order. Remove the implicit ``lib.so`` and broad ``.so*`` filesystem + fallbacks, so explicit directory layouts must expose a declared filename. + Explicitly declare the unversioned ``libnvvm.so`` wheel filename to preserve + CUDA 12.9 wheel discovery, and correct the ``cufftMp`` catalog order so ABI + 12 is preferred over ABI 11. (`PR #2689 `_) + +Internal maintenance +-------------------- + +* Author dynamic-library filename candidates directly in runtime preference + order and consume them without catalog-to-runtime reversals. Document the + same first-to-last candidate convention for dynamic libraries, headers, + binary utilities, static libraries, and bitcode libraries. Runtime selection + is unchanged. + (`PR #2708 `_)