Skip to content

Commit 9829655

Browse files
committed
Update
[ghstack-poisoned]
1 parent a19256c commit 9829655

3 files changed

Lines changed: 73 additions & 17 deletions

File tree

.ci/scripts/wheel/test_cpp_sdk.py

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -130,20 +130,56 @@
130130
# environment or the separate nvidia packages. None is reachable from an ldd process,
131131
# and a wheel must not carry an absolute path to a build machine's copy just to
132132
# 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")"
141171
)
142172

173+
_SONAME_SUFFIX = re.compile(r"\.so(?:\.\d+)*$")
174+
143175

144176
def _provided_externally(name: str) -> bool:
145177
"""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))
147183

148184

149185
# The component library each target is expected to expose. Keyed by the library base
@@ -317,9 +353,7 @@ def test_shipped_libraries_load() -> None:
317353
# __cudaRegisterFatBinary for every compiled .cu file.
318354
and not (
319355
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)
323357
)
324358
]
325359
if undefined:

extension/cuda/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ target_compile_definitions(
3232
extension_cuda PRIVATE EXECUTORCH_EXTENSION_CUDA_BUILDING
3333
)
3434

35+
if(EXECUTORCH_BUILD_SHARED)
36+
# A namespaced, versioned name, matching the other libraries the wheel ships. The CUDA
37+
# delegate carries a real symbol reference to this library, so its DT_NEEDED entry
38+
# survives even under --as-needed. A generic name like libextension_cuda.so could be
39+
# satisfied by an unrelated library that happens to be loaded first, which would bind a
40+
# different caller-stream implementation into the delegate.
41+
set_target_properties(
42+
extension_cuda
43+
PROPERTIES OUTPUT_NAME executorch_extension_cuda
44+
VERSION "${PROJECT_VERSION}"
45+
SOVERSION "${PROJECT_VERSION_MAJOR}"
46+
)
47+
endif()
48+
3549
install(
3650
TARGETS extension_cuda
3751
EXPORT ExecuTorchTargets

setup.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,11 +1310,19 @@ def run(self): # noqa C901
13101310
# whenever CUDA is on, so gating on the shared runtime as well
13111311
# would drop it from a CUDA wheel built with a static runtime.
13121312
BuiltFile(
1313-
src_dir="%CMAKE_CACHE_DIR%/extension/cuda/%BUILD_TYPE%/",
1314-
src_name="extension_cuda",
1315-
dst="executorch/lib/",
1316-
is_dynamic_lib=True,
1317-
dependent_cmake_flags=["EXECUTORCH_BUILD_CUDA"],
1313+
src_dir="%CMAKE_CACHE_DIR%/extension/cuda/",
1314+
src_name=(
1315+
"libexecutorch_extension_cuda.so."
1316+
f"{get_runtime_soname_major()}.*"
1317+
),
1318+
dst=(
1319+
"executorch/lib/libexecutorch_extension_cuda.so."
1320+
f"{get_runtime_soname_major()}"
1321+
),
1322+
dependent_cmake_flags=[
1323+
"EXECUTORCH_BUILD_SHARED",
1324+
"EXECUTORCH_BUILD_CUDA",
1325+
],
13181326
),
13191327
# Install the prebuilt pybindings extension wrapper for the runtime,
13201328
# portable kernels, and a selection of backends. This lets users

0 commit comments

Comments
 (0)