Coverage for cuda/pathfinder/_static_libs/find_bitcode_lib.py: 100.00%
79 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-03 02:41 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-03 02:41 +0000
1# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2# SPDX-License-Identifier: Apache-2.0
4import functools
5import os
6from dataclasses import dataclass
7from pathlib import Path
8from typing import NoReturn, TypedDict
10from cuda.pathfinder._utils.env_vars import get_cuda_path_or_home
11from cuda.pathfinder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages
12from cuda.pathfinder._utils.platform_aware import IS_WINDOWS
15class BitcodeLibNotFoundError(RuntimeError):
16 """Raised when a bitcode library cannot be found."""
19@dataclass(frozen=True)
20class LocatedBitcodeLib:
21 """Information about a located bitcode library."""
23 name: str
24 abs_path: str
25 filename: str
26 found_via: str
29class _BitcodeLibInfo(TypedDict):
30 """Bitcode-library metadata with ordered alternatives searched first-to-last."""
32 filename: str
33 rel_path: str
34 site_packages_dirs: tuple[str, ...]
35 available_on_windows: bool
38_SUPPORTED_BITCODE_LIBS_INFO: dict[str, _BitcodeLibInfo] = {
39 "device": {
40 "filename": "libdevice.10.bc",
41 "rel_path": "nvvm/libdevice",
42 "site_packages_dirs": (
43 "nvidia/cu13/nvvm/libdevice",
44 "nvidia/cuda_nvcc/nvvm/libdevice",
45 ),
46 "available_on_windows": True,
47 },
48 "nccl_device": {
49 "filename": "libnccl_device.bc",
50 "rel_path": "lib",
51 "site_packages_dirs": ("nvidia/nccl/lib",),
52 "available_on_windows": False,
53 },
54 "nvshmem_device": {
55 "filename": "libnvshmem_device.bc",
56 "rel_path": "lib",
57 "site_packages_dirs": ("nvidia/nvshmem/lib",),
58 "available_on_windows": False,
59 },
60}
62# Public API: just the supported library names
63SUPPORTED_BITCODE_LIBS: tuple[str, ...] = tuple(
64 sorted(
65 name for name, info in _SUPPORTED_BITCODE_LIBS_INFO.items() if not IS_WINDOWS or info["available_on_windows"]
66 )
67)
70def _no_such_file_in_dir(directory: Path, filename: str, error_messages: list[str], attachments: list[str]) -> None:
71 error_messages.append(f"No such file: {directory / filename}") 1aef
72 if directory.is_dir(): 1aef
73 attachments.append(f' listdir("{directory}"):') 1a
74 for node in sorted(node_path.name for node_path in directory.iterdir()): 1a
75 attachments.append(f" {node}") 1a
76 else:
77 attachments.append(f' Directory does not exist: "{directory}"') 1ef
80class _FindBitcodeLib:
81 def __init__(self, name: str) -> None:
82 if name not in _SUPPORTED_BITCODE_LIBS_INFO: # Updated reference 1jaghefbcd
83 raise ValueError(f"Unknown bitcode library: '{name}'. Supported: {', '.join(SUPPORTED_BITCODE_LIBS)}") 1j
84 self.name: str = name 1aghefbcd
85 self.config: _BitcodeLibInfo = _SUPPORTED_BITCODE_LIBS_INFO[name] # Updated reference 1aghefbcd
86 self.filename: str = self.config["filename"] 1aghefbcd
87 self.rel_path: str = self.config["rel_path"] 1aghefbcd
88 self.site_packages_dirs: tuple[str, ...] = self.config["site_packages_dirs"] 1aghefbcd
89 self.error_messages: list[str] = [] 1aghefbcd
90 self.attachments: list[str] = [] 1aghefbcd
92 def try_site_packages(self) -> Path | None:
93 for rel_dir in self.site_packages_dirs: 1aghefbcd
94 sub_dir = tuple(rel_dir.split("/")) 1aghefbcd
95 for abs_dir in find_sub_dirs_all_sitepackages(sub_dir): 1aghefbcd
96 file_path = Path(abs_dir, self.filename) 1bcd
97 if file_path.is_file(): 1bcd
98 return file_path 1bcd
99 return None 1aghefbcd
101 def try_with_conda_prefix(self) -> Path | None:
102 conda_prefix = os.environ.get("CONDA_PREFIX") 1aghefbcd
103 if not conda_prefix: 1aghefbcd
104 return None 1aghef
106 anchor = Path(conda_prefix, "Library") if IS_WINDOWS else Path(conda_prefix) 1bcd
107 file_path = anchor / self.rel_path / self.filename 1bcd
108 if file_path.is_file(): 1bcd
109 return file_path 1bcd
110 return None 1bcd
112 def try_with_cuda_home(self) -> Path | None:
113 cuda_home = get_cuda_path_or_home() 1aghefbcd
114 if cuda_home is None: 1aghefbcd
115 self.error_messages.append("CUDA_HOME/CUDA_PATH not set") 1g
116 return None 1g
118 anchor = Path(cuda_home) 1ahefbcd
119 file_path = anchor / self.rel_path / self.filename 1ahefbcd
120 if file_path.is_file(): 1ahefbcd
121 return file_path 1hbcd
123 _no_such_file_in_dir( 1aef
124 anchor / self.rel_path,
125 self.filename,
126 self.error_messages,
127 self.attachments,
128 )
129 return None 1aef
131 def raise_not_found_error(self) -> NoReturn:
132 err = ", ".join(self.error_messages) if self.error_messages else "No search paths available" 1agef
133 att = "\n".join(self.attachments) if self.attachments else "" 1agef
134 raise BitcodeLibNotFoundError(f'Failure finding "{self.filename}": {err}\n{att}') 1agef
137def locate_bitcode_lib(name: str) -> LocatedBitcodeLib:
138 """Locate a bitcode library by name.
140 Raises:
141 ValueError: If ``name`` is not a supported bitcode library.
142 BitcodeLibNotFoundError: If the bitcode library cannot be found.
143 """
144 finder = _FindBitcodeLib(name) 1jaghefbcd
146 abs_path = finder.try_site_packages() 1aghefbcd
147 if abs_path is not None: 1aghefbcd
148 return LocatedBitcodeLib( 1bcd
149 name=name,
150 abs_path=str(abs_path),
151 filename=finder.filename,
152 found_via="site-packages",
153 )
155 abs_path = finder.try_with_conda_prefix() 1aghefbcd
156 if abs_path is not None: 1aghefbcd
157 return LocatedBitcodeLib( 1bcd
158 name=name,
159 abs_path=str(abs_path),
160 filename=finder.filename,
161 found_via="conda",
162 )
164 abs_path = finder.try_with_cuda_home() 1aghefbcd
165 if abs_path is not None: 1aghefbcd
166 return LocatedBitcodeLib( 1hbcd
167 name=name,
168 abs_path=str(abs_path),
169 filename=finder.filename,
170 found_via="CUDA_PATH",
171 )
173 finder.raise_not_found_error() 1agef
176@functools.cache
177def find_bitcode_lib(name: str) -> str:
178 """Find the absolute path to a bitcode library.
180 Raises:
181 ValueError: If ``name`` is not a supported bitcode library.
182 BitcodeLibNotFoundError: If the bitcode library cannot be found.
183 """
184 return locate_bitcode_lib(name).abs_path 1agh