Skip to content

Commit fc7cd52

Browse files
committed
add conda specific functions to pathfinder and search conda before general system search
1 parent 1137e15 commit fc7cd52

File tree

4 files changed

+196
-4
lines changed

4 files changed

+196
-4
lines changed

cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def _no_such_file_in_sub_dirs(
2727
attachments.append(f" {node}")
2828

2929

30-
def _find_so_using_nvidia_lib_dirs(
30+
def _find_so_using_nvidia_wheel_lib_dirs(
3131
libname: str, so_basename: str, error_messages: list[str], attachments: list[str]
3232
) -> Optional[str]:
3333
rel_dirs = SITE_PACKAGES_LIBDIRS_LINUX.get(libname)
@@ -61,7 +61,7 @@ def _find_dll_under_dir(dirpath: str, file_wild: str) -> Optional[str]:
6161
return None
6262

6363

64-
def _find_dll_using_nvidia_bin_dirs(
64+
def _find_dll_using_nvidia_wheel_bin_dirs(
6565
libname: str, lib_searched_for: str, error_messages: list[str], attachments: list[str]
6666
) -> Optional[str]:
6767
rel_dirs = SITE_PACKAGES_LIBDIRS_WINDOWS.get(libname)
@@ -157,7 +157,7 @@ def __init__(self, libname: str):
157157
if IS_WINDOWS:
158158
self.lib_searched_for = f"{libname}*.dll"
159159
if self.abs_path is None:
160-
self.abs_path = _find_dll_using_nvidia_bin_dirs(
160+
self.abs_path = _find_dll_using_nvidia_wheel_bin_dirs(
161161
libname,
162162
self.lib_searched_for,
163163
self.error_messages,
@@ -166,7 +166,7 @@ def __init__(self, libname: str):
166166
else:
167167
self.lib_searched_for = f"lib{libname}.so"
168168
if self.abs_path is None:
169-
self.abs_path = _find_so_using_nvidia_lib_dirs(
169+
self.abs_path = _find_so_using_nvidia_wheel_lib_dirs(
170170
libname,
171171
self.lib_searched_for,
172172
self.error_messages,

cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,135 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]:
173173
return None
174174

175175

176+
def load_with_conda_search(libname: str) -> Optional[LoadedDL]:
177+
"""Try to load a library using conda search paths.
178+
179+
Args:
180+
libname: The name of the library to load
181+
182+
Returns:
183+
A LoadedDL object if successful, None if the library cannot be loaded
184+
"""
185+
in_conda_build = False
186+
in_conda_env = False
187+
if os.getenv("CONDA_BUILD") == "1":
188+
in_conda_build = True
189+
elif os.getenv("CONDA_PREFIX"):
190+
in_conda_env = True
191+
else:
192+
return None
193+
194+
normal_conda_lib_path = os.path.join("lib")
195+
# TODO KEITH: All the libs in the targets directory are symlinked into the lib directory, do we need to search it?
196+
# TODO KEITH: Should we do platform detection here to avoid extra searches? Any considerations we need to do in a
197+
# cross compilation build environment?
198+
nvidia_conda_target_lib_paths = [
199+
os.path.join("targets", "x86_64-linux", "lib"),
200+
os.path.join("targets", "sbsa-linux", "lib"),
201+
]
202+
if libname == "nvvm":
203+
normal_conda_lib_path = os.path.join("nvvm")
204+
nvidia_conda_target_lib_paths = [
205+
os.path.join("targets", "x86_64-linux", "nvvm", "lib64"),
206+
os.path.join("targets", "sbsa-linux", "nvvm", "lib64"),
207+
]
208+
209+
for soname in get_candidate_sonames(libname):
210+
if in_conda_build:
211+
if prefix := os.getenv("PREFIX"):
212+
for nvidia_conda_target_lib_path in nvidia_conda_target_lib_paths:
213+
prefix_target_lib_path = os.path.join(prefix, nvidia_conda_target_lib_path)
214+
if os.path.isdir(prefix_target_lib_path):
215+
soname = os.path.join(prefix_target_lib_path, soname)
216+
try:
217+
handle = _load_lib(libname, soname)
218+
except OSError:
219+
pass
220+
else:
221+
# TODO KEITH: Do we need this abs_path_for_dynamic_library call?
222+
# We're already resolving the absolute path based on the conda environment variables
223+
abs_path = abs_path_for_dynamic_library(libname, handle)
224+
if abs_path is None:
225+
raise RuntimeError(f"No expected symbol for {libname=!r}")
226+
return LoadedDL(abs_path, False, handle._handle)
227+
# Only run if not found in the target lib paths
228+
prefix_normal_lib_path = os.path.join(prefix, normal_conda_lib_path)
229+
if os.path.isdir(prefix_normal_lib_path):
230+
soname = os.path.join(prefix_normal_lib_path, soname)
231+
try:
232+
handle = _load_lib(libname, soname)
233+
except OSError:
234+
pass
235+
else:
236+
# TODO KEITH: Do we need this abs_path_for_dynamic_library call?
237+
# We're already resolving the absolute path based on the conda environment variables
238+
abs_path = abs_path_for_dynamic_library(libname, handle)
239+
if abs_path is None:
240+
raise RuntimeError(f"No expected symbol for {libname=!r}")
241+
return LoadedDL(abs_path, False, handle._handle)
242+
if build_prefix := os.getenv("BUILD_PREFIX"):
243+
for nvidia_conda_target_lib_path in nvidia_conda_target_lib_paths:
244+
build_prefix_target_lib_path = os.path.join(build_prefix, nvidia_conda_target_lib_path)
245+
if os.path.isdir(build_prefix_target_lib_path):
246+
soname = os.path.join(build_prefix_target_lib_path, soname)
247+
try:
248+
handle = _load_lib(libname, soname)
249+
except OSError:
250+
pass
251+
else:
252+
# TODO KEITH: Do we need this abs_path_for_dynamic_library call?
253+
# We're already resolving the absolute path based on the conda environment variables
254+
abs_path = abs_path_for_dynamic_library(libname, handle)
255+
if abs_path is None:
256+
raise RuntimeError(f"No expected symbol for {libname=!r}")
257+
return LoadedDL(abs_path, False, handle._handle)
258+
# Only run if not found in the target lib paths
259+
build_prefix_normal_lib_path = os.path.join(build_prefix, normal_conda_lib_path)
260+
if os.path.isdir(build_prefix_normal_lib_path):
261+
soname = os.path.join(build_prefix_normal_lib_path, soname)
262+
try:
263+
handle = _load_lib(libname, soname)
264+
except OSError:
265+
pass
266+
else:
267+
# TODO KEITH: Do we need this abs_path_for_dynamic_library call?
268+
# We're already resolving the absolute path based on the conda environment variables
269+
abs_path = abs_path_for_dynamic_library(libname, handle)
270+
if abs_path is None:
271+
raise RuntimeError(f"No expected symbol for {libname=!r}")
272+
return LoadedDL(abs_path, False, handle._handle)
273+
elif in_conda_env:
274+
if conda_prefix := os.getenv("CONDA_PREFIX"):
275+
for nvidia_conda_target_lib_path in nvidia_conda_target_lib_paths:
276+
conda_prefix_target_lib_path = os.path.join(conda_prefix, nvidia_conda_target_lib_path)
277+
if os.path.isdir(conda_prefix_target_lib_path):
278+
soname = os.path.join(conda_prefix_target_lib_path, soname)
279+
try:
280+
handle = _load_lib(libname, soname)
281+
except OSError:
282+
pass
283+
else:
284+
# TODO KEITH: Do we need this abs_path_for_dynamic_library call?
285+
# We're already resolving the absolute path based on the conda environment variables
286+
abs_path = abs_path_for_dynamic_library(libname, handle)
287+
if abs_path is None:
288+
raise RuntimeError(f"No expected symbol for {libname=!r}")
289+
return LoadedDL(abs_path, False, handle._handle)
290+
# Only run if not found in the target lib paths
291+
conda_prefix_normal_lib_path = os.path.join(conda_prefix, normal_conda_lib_path)
292+
if os.path.isdir(conda_prefix_normal_lib_path):
293+
soname = os.path.join(conda_prefix_normal_lib_path, soname)
294+
try:
295+
handle = _load_lib(libname, soname)
296+
except OSError:
297+
pass
298+
else:
299+
# TODO KEITH: Do we need this abs_path_for_dynamic_library call?
300+
# We're already resolving the absolute path based on the conda environment variables
301+
abs_path = abs_path_for_dynamic_library(libname, handle)
302+
return None
303+
304+
176305
def _work_around_known_bugs(libname: str, found_path: str) -> None:
177306
if libname == "nvrtc":
178307
# Work around bug/oversight in

cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,64 @@ def load_with_system_search(libname: str) -> Optional[LoadedDL]:
132132
return None
133133

134134

135+
def load_with_conda_search(libname: str) -> Optional[LoadedDL]:
136+
"""Try to load a DLL using conda search paths.
137+
138+
Args:
139+
libname: The name of the library to load
140+
141+
Returns:
142+
A LoadedDL object if successful, None if the library cannot be loaded
143+
"""
144+
in_conda_build = False
145+
in_conda_env = False
146+
if os.getenv("CONDA_BUILD") == "1":
147+
in_conda_build = True
148+
elif os.getenv("CONDA_PREFIX"):
149+
in_conda_env = True
150+
else:
151+
return None
152+
153+
normal_conda_lib_path = os.path.join("Library", "bin", "x64")
154+
if libname == "nvvm":
155+
normal_conda_lib_path = os.path.join("Library", "nvvm", "bin", "x64")
156+
157+
for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()):
158+
if in_conda_build:
159+
if prefix := os.getenv("PREFIX"):
160+
prefix_normal_lib_path = os.path.join(prefix, normal_conda_lib_path)
161+
if os.path.isdir(prefix_normal_lib_path):
162+
dll_name = os.path.join(prefix_normal_lib_path, dll_name)
163+
handle = kernel32.LoadLibraryExW(dll_name, None, 0)
164+
if handle:
165+
# TODO KEITH: Do we need this abs_path_for_dynamic_library call?
166+
# We're already resolving the absolute path based on the conda environment variables
167+
abs_path = abs_path_for_dynamic_library(libname, handle)
168+
return LoadedDL(abs_path, False, ctypes_handle_to_unsigned_int(handle))
169+
if build_prefix := os.getenv("BUILD_PREFIX"):
170+
build_prefix_normal_lib_path = os.path.join(build_prefix, normal_conda_lib_path)
171+
if os.path.isdir(build_prefix_normal_lib_path):
172+
dll_name = os.path.join(build_prefix_normal_lib_path, dll_name)
173+
handle = kernel32.LoadLibraryExW(dll_name, None, 0)
174+
if handle:
175+
# TODO KEITH: Do we need this abs_path_for_dynamic_library call?
176+
# We're already resolving the absolute path based on the conda environment variables
177+
abs_path = abs_path_for_dynamic_library(libname, handle)
178+
return LoadedDL(abs_path, False, ctypes_handle_to_unsigned_int(handle))
179+
elif in_conda_env:
180+
if conda_prefix := os.getenv("CONDA_PREFIX"):
181+
conda_prefix_normal_lib_path = os.path.join(conda_prefix, normal_conda_lib_path)
182+
if os.path.isdir(conda_prefix_normal_lib_path):
183+
dll_name = os.path.join(conda_prefix_normal_lib_path, dll_name)
184+
handle = kernel32.LoadLibraryExW(dll_name, None, 0)
185+
if handle:
186+
# TODO KEITH: Do we need this abs_path_for_dynamic_library call?
187+
# We're already resolving the absolute path based on the conda environment variables
188+
abs_path = abs_path_for_dynamic_library(libname, handle)
189+
return LoadedDL(abs_path, False, ctypes_handle_to_unsigned_int(handle))
190+
return None
191+
192+
135193
def load_with_abs_path(libname: str, found_path: str) -> LoadedDL:
136194
"""Load a dynamic library from the given path.
137195

cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
from cuda.pathfinder._dynamic_libs.load_dl_windows import (
1414
check_if_already_loaded_from_elsewhere,
1515
load_with_abs_path,
16+
load_with_conda_search,
1617
load_with_system_search,
1718
)
1819
else:
1920
from cuda.pathfinder._dynamic_libs.load_dl_linux import (
2021
check_if_already_loaded_from_elsewhere,
2122
load_with_abs_path,
23+
load_with_conda_search,
2224
load_with_system_search,
2325
)
2426

@@ -41,6 +43,9 @@ def _load_lib_no_cache(libname: str) -> LoadedDL:
4143
return loaded
4244

4345
if not have_abs_path:
46+
loaded = load_with_conda_search(libname)
47+
if loaded is not None:
48+
return loaded
4449
loaded = load_with_system_search(libname)
4550
if loaded is not None:
4651
return loaded

0 commit comments

Comments
 (0)