|
6 | 6 | # - https://peps.python.org/pep-0517/ |
7 | 7 | # - https://setuptools.pypa.io/en/latest/build_meta.html#dynamic-build-dependencies-and-other-build-meta-tweaks |
8 | 8 | # Specifically, there are 5 APIs required to create a proper build backend, see below. |
9 | | -# For now it's mostly a pass-through to setuptools, except that we need to determine |
10 | | -# some dependencies at build time. |
11 | 9 | # |
12 | 10 | # TODO: also implement PEP-660 API hooks |
13 | 11 |
|
| 12 | +import functools |
| 13 | +import glob |
14 | 14 | import os |
15 | 15 | import re |
16 | 16 | import subprocess # nosec: B404 |
17 | 17 |
|
| 18 | +from Cython.Build import cythonize |
| 19 | +from setuptools import Extension |
18 | 20 | from setuptools import build_meta as _build_meta |
19 | 21 |
|
20 | 22 | prepare_metadata_for_build_wheel = _build_meta.prepare_metadata_for_build_wheel |
21 | | -build_wheel = _build_meta.build_wheel |
22 | 23 | build_sdist = _build_meta.build_sdist |
23 | 24 | get_requires_for_build_sdist = _build_meta.get_requires_for_build_sdist |
24 | 25 |
|
25 | 26 |
|
| 27 | +@functools.cache |
26 | 28 | def _get_proper_cuda_bindings_major_version() -> str: |
27 | 29 | # for local development (with/without build isolation) |
28 | 30 | try: |
@@ -51,8 +53,40 @@ def _get_proper_cuda_bindings_major_version() -> str: |
51 | 53 | return "13" |
52 | 54 |
|
53 | 55 |
|
54 | | -# Note: this function returns a list of *build-time* dependencies, so it's not affected |
55 | | -# by "--no-deps" based on the PEP-517 design. |
| 56 | +# used later by setup() |
| 57 | +_extensions = None |
| 58 | + |
| 59 | + |
| 60 | +def build_wheel(wheel_directory, config_settings=None, metadata_directory=None): |
| 61 | + # Customizing this hook is needed because we must defer cythonization until cuda-bindings, |
| 62 | + # now a required build-time dependency that's dynamically installed via the other hook below, |
| 63 | + # is installed. Otherwise, cimport any cuda.bindings modules would fail! |
| 64 | + |
| 65 | + # It seems setuptools' wildcard support has problems for namespace packages, |
| 66 | + # so we explicitly spell out all Extension instances. |
| 67 | + root_module = "cuda.core.experimental" |
| 68 | + root_path = f"{os.path.sep}".join(root_module.split(".")) + os.path.sep |
| 69 | + ext_files = glob.glob(f"{root_path}/**/*.pyx", recursive=True) |
| 70 | + |
| 71 | + def strip_prefix_suffix(filename): |
| 72 | + return filename[len(root_path) : -4] |
| 73 | + |
| 74 | + module_names = (strip_prefix_suffix(f) for f in ext_files) |
| 75 | + ext_modules = tuple( |
| 76 | + Extension( |
| 77 | + f"cuda.core.experimental.{mod.replace(os.path.sep, '.')}", |
| 78 | + sources=[f"cuda/core/experimental/{mod}.pyx"], |
| 79 | + language="c++", |
| 80 | + ) |
| 81 | + for mod in module_names |
| 82 | + ) |
| 83 | + |
| 84 | + global _extensions |
| 85 | + _extensions = cythonize(ext_modules, verbose=True, language_level=3, compiler_directives={"embedsignature": True}) |
| 86 | + |
| 87 | + return _build_meta.build_wheel(wheel_directory, config_settings, metadata_directory) |
| 88 | + |
| 89 | + |
56 | 90 | def get_requires_for_build_wheel(config_settings=None): |
57 | 91 | cuda_major = _get_proper_cuda_bindings_major_version() |
58 | 92 | cuda_bindings_require = [f"cuda-bindings=={cuda_major}.*"] |
|
0 commit comments