Make check_nvvm_compiler_options return False when nvvm is unavailable - #2541
Open
LeSingh1 wants to merge 1 commit into
Open
Make check_nvvm_compiler_options return False when nvvm is unavailable#2541LeSingh1 wants to merge 1 commit into
LeSingh1 wants to merge 1 commit into
Conversation
Contributor
check_nvvm_compiler_options() has two guards meant to answer "options not
supported" instead of failing when nvvm is missing. Neither one works.
1. The optional import.
try:
from cuda.bindings import nvvm
except ModuleNotFoundError as exc:
if exc.name == "nvvm":
return False
raise
`from <pkg> import <sub>` never raises ModuleNotFoundError for a missing
submodule: importlib swallows it in _handle_fromlist() and the IMPORT_FROM
opcode raises a plain ImportError. And ModuleNotFoundError.name is always
the fully qualified name, so even where one is raised it is
"cuda.bindings.nvvm", never "nvvm". In a tree where the nvvm extension has
not been built, the public API therefore raises
ImportError: cannot import name 'nvvm' from 'cuda.bindings'
Import via importlib.import_module(), which does raise
ModuleNotFoundError with name == "cuda.bindings.nvvm", and compare against
that. This mirrors cuda.pathfinder._optional_cuda_import, which already
uses the fully qualified name for the same "is the target module itself
missing, or one of its dependencies?" distinction. A missing dependency
still propagates, unchanged.
2. The libNVVM probe.
if _inspect_function_pointer("__nvvmCreateProgram") == 0:
return False
A zero pointer only covers "libNVVM is loaded but does not export the
symbol". _inspect_function_pointer() loads libNVVM lazily, so when it is
not installed at all the call raises DynamicLibNotFoundError instead of
returning 0. tests/test_utils.py already knows this: its
_is_libnvvm_available() helper wraps the identical call in
`except DynamicLibNotFoundError`. Catch it here too.
This is what test_check_nvvm_compiler_options_no_libnvvm asserts, and that
test errors out on a machine without libNVVM today. It is on the
always-skipped list in NVIDIA#2077, which is why nobody has seen it fail.
Adds three tests that simulate both conditions without needing an unbuilt
tree or a machine without libNVVM, so they run in CI.
LeSingh1
force-pushed
the
nvvm-optional-import
branch
from
August 9, 2026 01:42
85580d8 to
a8ebc34
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
check_nvvm_compiler_options()has two guards meant to answer "options not supported"rather than fail when nvvm is unavailable. Neither one works.
1. The optional import is not optional
Unreachable, for two independent reasons:
from <pkg> import <sub>does not raiseModuleNotFoundErrorwhen the submoduleis missing.
importlib._bootstrap._handle_fromlist()swallows it and theIMPORT_FROMopcode raises a plain
ImportError— a different exception type, so the handler neverruns.
ModuleNotFoundError.nameis always the fully qualified name. Even where one israised it is
"cuda.bindings.nvvm", never"nvvm".Reproduced in a source tree where the nvvm extension has not been built:
Fix: import through
importlib.import_module("cuda.bindings.nvvm"), which does raiseModuleNotFoundErrorwithname == "cuda.bindings.nvvm", and compare against the fullyqualified name. Same shape as
cuda.pathfinder._optional_cuda_import(), which alreadydraws the "is the target module itself missing, or one of its dependencies?" distinction
this way. The re-raise for a missing dependency is preserved — that half of the original
intent was already correct.
2. The libNVVM probe only covers half the failure
A zero pointer means "libNVVM is loaded but does not export the symbol".
_inspect_function_pointer()loads libNVVM lazily(
_inspect_function_pointers()→_check_or_init_nvvm()→load_library()→load_nvidia_dynamic_lib("nvvm")), so when libNVVM is not installed at all the callraises
DynamicLibNotFoundErrorinstead of returning 0.tests/test_utils.pyalready knows this — its_is_libnvvm_available()helper wraps theidentical call in
except DynamicLibNotFoundError. Butcheck_nvvm_compiler_options()does not, so it propagates the exception.
This is exactly what the existing
test_check_nvvm_compiler_options_no_libnvvmasserts:On a machine without libNVVM that test errors instead of passing. It is on the
always-skipped list in #2077, which is why it has never been seen to fail. I did not touch
that test — this PR makes the code satisfy it.
Fix: catch
DynamicLibNotFoundErroraround the probe and returnFalse.Tests
Three added to
cuda_bindings/tests/test_utils.py. All three simulate the failureconditions, so they run in CI on a normal machine with everything built — no GPU, no
unbuilt tree, no libNVVM-less host required:
test_check_nvvm_compiler_options_without_the_nvvm_binding— hidescuda.bindings.nvvmbehind a
sys.meta_pathfinder (plus the parent-package attribute and thesys.modulesentry, which both short-circuit the import system). Fails on
main.test_check_nvvm_compiler_options_without_libnvvm— substitutes an_inspect_function_pointerthat raisesDynamicLibNotFoundError, i.e. the realno-libNVVM condition. Fails on
main.test_check_nvvm_compiler_options_does_not_mask_a_missing_dependency— passes onmaintoo, on purpose: it pins down that widening the guards did not start swallowing real
problems.
Verified against
upstream/main: the first two fail, the third passes; all three pass withthe change.
ruff checkandruff format --checkclean.