|
130 | 130 | # environment or the separate nvidia packages. None is reachable from an ldd process, |
131 | 131 | # and a wheel must not carry an absolute path to a build machine's copy just to |
132 | 132 | # satisfy a check. Anything the wheel itself ships still has to resolve. |
133 | | -_EXTERNAL_LIBRARY_PREFIXES = ( |
134 | | - "libpython", |
135 | | - "libtorch", |
136 | | - "libc10", |
137 | | - "libcuda", |
138 | | - "libcurand", |
139 | | - "libcublas", |
140 | | - "libnvinfer", |
| 133 | +# Base names of the libraries the wheel expects from outside itself: the interpreter, |
| 134 | +# PyTorch, and the CUDA runtime. Matched as whole names rather than as prefixes, because a |
| 135 | +# prefix test also excuses unrelated libraries that merely start the same way, such as |
| 136 | +# libtorchcodec_core.so or libcudagraph_helper.so. |
| 137 | +_EXTERNAL_LIBRARY_NAMES = frozenset( |
| 138 | + { |
| 139 | + "libpython3", |
| 140 | + "libtorch", |
| 141 | + "libtorch_cpu", |
| 142 | + "libtorch_cuda", |
| 143 | + "libtorch_python", |
| 144 | + "libtorch_global_deps", |
| 145 | + "libc10", |
| 146 | + "libc10_cuda", |
| 147 | + "libcuda", |
| 148 | + "libcudart", |
| 149 | + "libcurand", |
| 150 | + "libcublas", |
| 151 | + "libcublasLt", |
| 152 | + "libcudnn", |
| 153 | + "libcufft", |
| 154 | + "libcusparse", |
| 155 | + "libcusolver", |
| 156 | + "libnvinfer", |
| 157 | + "libnvinfer_plugin", |
| 158 | + "libnvrtc", |
| 159 | + "libnccl", |
| 160 | + } |
| 161 | +) |
| 162 | + |
| 163 | +# The CUDA entry points, spelled the way the CUDA APIs are: a known family followed by an |
| 164 | +# uppercase letter. A bare "cu" prefix would also suppress ordinary names such as |
| 165 | +# custom_double_out, so a library genuinely missing one would pass unnoticed. |
| 166 | +_CUDA_SYMBOL = re.compile( |
| 167 | + r"undefined symbol:\s+_*(?:" |
| 168 | + r"cuda[A-Z]|cu[A-Z]|curand[A-Z]|cublas[A-Z]|cudnn[A-Z]" |
| 169 | + r"|cusparse[A-Z]|cusolver[A-Z]|cufft[A-Z]|nvrtc[A-Z]|nccl[A-Z]" |
| 170 | + r")" |
141 | 171 | ) |
142 | 172 |
|
| 173 | +_SONAME_SUFFIX = re.compile(r"\.so(?:\.\d+)*$") |
| 174 | + |
143 | 175 |
|
144 | 176 | def _provided_externally(name: str) -> bool: |
145 | 177 | """Whether a shared library is expected to come from outside the wheel.""" |
146 | | - return name.startswith(_EXTERNAL_LIBRARY_PREFIXES) |
| 178 | + base = _SONAME_SUFFIX.sub("", name) |
| 179 | + if base in _EXTERNAL_LIBRARY_NAMES: |
| 180 | + return True |
| 181 | + # Version-suffixed interpreter names such as libpython3.12. |
| 182 | + return bool(re.fullmatch(r"libpython3(?:\.\d+)?", base)) |
147 | 183 |
|
148 | 184 |
|
149 | 185 | # The component library each target is expected to expose. Keyed by the library base |
@@ -317,9 +353,7 @@ def test_shipped_libraries_load() -> None: |
317 | 353 | # __cudaRegisterFatBinary for every compiled .cu file. |
318 | 354 | and not ( |
319 | 355 | skip_undefined |
320 | | - and re.search( |
321 | | - r"undefined symbol:\s+_*(cu|cuda|curand|cublas|cudnn)", line |
322 | | - ) |
| 356 | + and re.search(_CUDA_SYMBOL, line) |
323 | 357 | ) |
324 | 358 | ] |
325 | 359 | if undefined: |
|
0 commit comments