diff --git a/kernels/src/kernels/cli/__init__.py b/kernels/src/kernels/cli/__init__.py index 679627fb..8b484088 100644 --- a/kernels/src/kernels/cli/__init__.py +++ b/kernels/src/kernels/cli/__init__.py @@ -65,7 +65,8 @@ def main(): versions_parser.set_defaults(func=kernel_versions) upload_parser = subparsers.add_parser( - "upload", help="(Deprecated) Upload kernels to the Hub. Use `kernel-builder upload` instead." + "upload", + help="(Deprecated) Upload kernels to the Hub. Use `kernel-builder upload` instead.", ) upload_parser.add_argument( "kernel_dir", diff --git a/kernels/src/kernels/utils.py b/kernels/src/kernels/utils.py index fbe4dbce..d4926a35 100644 --- a/kernels/src/kernels/utils.py +++ b/kernels/src/kernels/utils.py @@ -25,6 +25,7 @@ from kernels.status import resolve_status from kernels.variants import ( Variant, + describe_system_variant, get_variants, get_variants_local, resolve_variant, @@ -138,8 +139,9 @@ def install_kernel( variant = resolve_variant(variants, backend) if variant is None: + requested = describe_system_variant(backend) raise FileNotFoundError( - f"Cannot find a build variant for this system in {repo_id} (revision: {revision}). Available variants: {', '.join([variant.variant_str for variant in variants])}" + f"Cannot find a build variant for this system in {repo_id} (revision: {revision}). Requested variant: {requested}. Available variants: {', '.join([variant.variant_str for variant in variants])}" ) allow_patterns = [f"build/{variant.variant_str}/*"] @@ -407,8 +409,9 @@ def load_kernel( variant = resolve_variant(variants, backend) if variant is None: + requested = describe_system_variant(backend) raise FileNotFoundError( - f"Cannot find a build variant for this system in {repo_id} (revision: {locked_sha}). Available variants: {', '.join([variant.variant_str for variant in variants])}" + f"Cannot find a build variant for this system in {repo_id} (revision: {locked_sha}). Requested variant: {requested}. Available variants: {', '.join([variant.variant_str for variant in variants])}" ) allow_patterns = [f"build/{variant.variant_str}/*"] diff --git a/kernels/src/kernels/variants.py b/kernels/src/kernels/variants.py index 8bfdddb8..9ef9068a 100644 --- a/kernels/src/kernels/variants.py +++ b/kernels/src/kernels/variants.py @@ -198,11 +198,8 @@ def resolve_variant( return resolved[0] if resolved else None -def resolve_variants( - variants: list[Variant], backend: str | None = None -) -> list[Variant]: - """Return the matching variants for the current system, sorted - by decreasing order of preference.""" +def _get_system_info(backend: str | None = None): + """Gather system information used for variant resolution.""" selected_backend = _select_backend(backend) cpu = platform.machine() @@ -232,6 +229,59 @@ def resolve_variants( tvm_ffi_version = parse(tvm_ffi.__version__) tvm_ffi_version = Version(f"{tvm_ffi_version.major}.{tvm_ffi_version.minor}") + return selected_backend, cpu, os, torch_version, torch_cxx11_abi, tvm_ffi_version + + +def describe_system_variant(backend: str | None = None) -> str: + """Return a human-readable description of the variant the current system requires.""" + selected_backend, cpu, os, torch_version, torch_cxx11_abi, tvm_ffi_version = ( + _get_system_info(backend) + ) + return _describe_system_variant( + selected_backend=selected_backend, + cpu=cpu, + os=os, + torch_version=torch_version, + torch_cxx11_abi=torch_cxx11_abi, + tvm_ffi_version=tvm_ffi_version, + ) + + +def _describe_system_variant( + selected_backend: Backend, + cpu: str, + os: str, + torch_version: Version | None, + torch_cxx11_abi: bool | None, + tvm_ffi_version: Version | None, +) -> str: + """Return a human-readable description of the requested variant given explicit system parameters.""" + parts = [] + + if torch_version is not None: + parts.append(f"torch{torch_version.major}{torch_version.minor}") + + if tvm_ffi_version is not None: + parts.append(f"tvm-ffi{tvm_ffi_version.major}{tvm_ffi_version.minor}") + + if torch_cxx11_abi is not None: + parts.append("cxx11" if torch_cxx11_abi else "cxx98") + + parts.append(selected_backend.variant_str) + parts.append(f"{cpu}-{os}") + + return "-".join(parts) + + +def resolve_variants( + variants: list[Variant], backend: str | None = None +) -> list[Variant]: + """Return the matching variants for the current system, sorted + by decreasing order of preference.""" + selected_backend, cpu, os, torch_version, torch_cxx11_abi, tvm_ffi_version = ( + _get_system_info(backend) + ) + return _resolve_variant_for_system( variants=variants, selected_backend=selected_backend, diff --git a/kernels/tests/test_variants.py b/kernels/tests/test_variants.py index b0d17616..bffd8e0e 100644 --- a/kernels/tests/test_variants.py +++ b/kernels/tests/test_variants.py @@ -3,7 +3,12 @@ from packaging.version import Version from kernels.backends import CPU, CUDA, ROCm -from kernels.variants import Variant, _resolve_variant_for_system, get_variants +from kernels.variants import ( + Variant, + _describe_system_variant, + _resolve_variant_for_system, + get_variants, +) VARIANT_STRINGS = [ "torch25-cxx98-cu118-aarch64-linux", @@ -359,3 +364,37 @@ def test_resolve_cuda_no_different_major_no_noarch(): tvm_ffi_version=None, ) assert result == [] + + +def test_error_message_includes_requested_variant(): + # Simulate a no-match scenario: ROCm 7.0 system with torch 2.9, but only + # CUDA variants available. + variants = RESOLVE_VARIANTS_NO_NOARCH + selected_backend = ROCm(Version("7.0")) + result = _resolve_variant_for_system( + variants=variants, + selected_backend=selected_backend, + cpu="x86_64", + os="linux", + torch_version=Version("2.9"), + torch_cxx11_abi=True, + tvm_ffi_version=None, + ) + assert result == [] + + # Build the error message the same way utils.py does. + requested = _describe_system_variant( + selected_backend=selected_backend, + cpu="x86_64", + os="linux", + torch_version=Version("2.9"), + torch_cxx11_abi=True, + tvm_ffi_version=None, + ) + error_msg = ( + f"Cannot find a build variant for this system in test/repo (revision: abc123). " + f"Requested variant: {requested}. " + f"Available variants: {', '.join([v.variant_str for v in variants])}" + ) + assert "Requested variant: torch29-cxx11-rocm70-x86_64-linux" in error_msg + assert "Available variants:" in error_msg