From f3fbf3a6b1ad034aefc6847151880fde5525ad8e Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Wed, 29 Jan 2025 17:40:56 -0600 Subject: [PATCH 1/8] Rewrite of cuda_cccl build system Transition from using setuptools to using scikit-build-core, so that CMakeLists.txt is used to ensure that include is the same as in the cuda toolkit. Added test folder to test that the package works correctly. --- python/new_cuda_cccl/.gitignore | 4 ++ python/new_cuda_cccl/CMakeLists.txt | 31 +++++++++ python/new_cuda_cccl/LICENSE | 1 + python/new_cuda_cccl/README.md | 3 + python/new_cuda_cccl/cuda/__init__.py | 0 python/new_cuda_cccl/cuda/cccl/__init__.py | 8 +++ python/new_cuda_cccl/cuda/cccl/_version.py | 7 +++ .../cuda/cccl/include/__init__.py | 1 + .../new_cuda_cccl/cuda/cccl/include_paths.py | 63 +++++++++++++++++++ python/new_cuda_cccl/pyproject.toml | 46 ++++++++++++++ python/new_cuda_cccl/test/test_cuda_cccl.py | 21 +++++++ 11 files changed, 185 insertions(+) create mode 100644 python/new_cuda_cccl/.gitignore create mode 100644 python/new_cuda_cccl/CMakeLists.txt create mode 120000 python/new_cuda_cccl/LICENSE create mode 100644 python/new_cuda_cccl/README.md create mode 100644 python/new_cuda_cccl/cuda/__init__.py create mode 100644 python/new_cuda_cccl/cuda/cccl/__init__.py create mode 100644 python/new_cuda_cccl/cuda/cccl/_version.py create mode 100644 python/new_cuda_cccl/cuda/cccl/include/__init__.py create mode 100644 python/new_cuda_cccl/cuda/cccl/include_paths.py create mode 100644 python/new_cuda_cccl/pyproject.toml create mode 100644 python/new_cuda_cccl/test/test_cuda_cccl.py diff --git a/python/new_cuda_cccl/.gitignore b/python/new_cuda_cccl/.gitignore new file mode 100644 index 00000000000..0ae14ff5c8f --- /dev/null +++ b/python/new_cuda_cccl/.gitignore @@ -0,0 +1,4 @@ +build +dist +*egg-info +*~ diff --git a/python/new_cuda_cccl/CMakeLists.txt b/python/new_cuda_cccl/CMakeLists.txt new file mode 100644 index 00000000000..be1e5d62d2d --- /dev/null +++ b/python/new_cuda_cccl/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.21...3.31 FATAL_ERROR) + +# include_guard(GLOBAL) + +project( + CCCL_HEADERS + VERSION ${SKBUILD_PROJECT_VERSION} + LANGUAGES C CXX + DESCRIPTION "Headers of NVIDIA CUDA Core Compute Libraries" +) + +add_subdirectory(../.. _parent_cccl) + +find_package(CUB REQUIRED) +find_package(Thrust REQUIRED) +find_package(libcudacxx REQUIRED) + +set(_dest_incl_dir cuda/cccl/include) + +install( + DIRECTORY ${CUB_SOURCE_DIR}/cub + DESTINATION ${_dest_incl_dir} +) +install( + DIRECTORY ${Thrust_SOURCE_DIR}/thrust + DESTINATION ${_dest_incl_dir} +) +install( + DIRECTORY ${libcudacxx_SOURCE_DIR}/include + DESTINATION ${_dest_incl_dir} +) diff --git a/python/new_cuda_cccl/LICENSE b/python/new_cuda_cccl/LICENSE new file mode 120000 index 00000000000..30cff7403da --- /dev/null +++ b/python/new_cuda_cccl/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/python/new_cuda_cccl/README.md b/python/new_cuda_cccl/README.md new file mode 100644 index 00000000000..37f020b6df6 --- /dev/null +++ b/python/new_cuda_cccl/README.md @@ -0,0 +1,3 @@ +## Note + +This package is currently FOR INTERNAL USE ONLY and not meant to be used/installed explicitly. diff --git a/python/new_cuda_cccl/cuda/__init__.py b/python/new_cuda_cccl/cuda/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/new_cuda_cccl/cuda/cccl/__init__.py b/python/new_cuda_cccl/cuda/cccl/__init__.py new file mode 100644 index 00000000000..5288f071942 --- /dev/null +++ b/python/new_cuda_cccl/cuda/cccl/__init__.py @@ -0,0 +1,8 @@ +# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. +# +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +from cuda.cccl._version import __version__ +from cuda.cccl.include_paths import get_include_paths + +__all__ = ["__version__", "get_include_paths"] diff --git a/python/new_cuda_cccl/cuda/cccl/_version.py b/python/new_cuda_cccl/cuda/cccl/_version.py new file mode 100644 index 00000000000..ec7c29a266e --- /dev/null +++ b/python/new_cuda_cccl/cuda/cccl/_version.py @@ -0,0 +1,7 @@ +# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. +# +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This file is generated by ci/update_version.sh +# Do not edit this file manually. +__version__ = "2.8.0" diff --git a/python/new_cuda_cccl/cuda/cccl/include/__init__.py b/python/new_cuda_cccl/cuda/cccl/include/__init__.py new file mode 100644 index 00000000000..bb7b160deb3 --- /dev/null +++ b/python/new_cuda_cccl/cuda/cccl/include/__init__.py @@ -0,0 +1 @@ +# Intentionally empty diff --git a/python/new_cuda_cccl/cuda/cccl/include_paths.py b/python/new_cuda_cccl/cuda/cccl/include_paths.py new file mode 100644 index 00000000000..ba626f3a5e7 --- /dev/null +++ b/python/new_cuda_cccl/cuda/cccl/include_paths.py @@ -0,0 +1,63 @@ +# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. +# +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +import os +import shutil +from dataclasses import dataclass +from functools import lru_cache +from pathlib import Path +from typing import Optional + + +def _get_cuda_path() -> Optional[Path]: + cuda_path = os.environ.get("CUDA_PATH") + if cuda_path: + cuda_path = Path(cuda_path) + if cuda_path.exists(): + return cuda_path + + nvcc_path = shutil.which("nvcc") + if nvcc_path: + return Path(nvcc_path).parent.parent + + default_path = Path("/usr/local/cuda") + if default_path.exists(): + return default_path + + return None + + +@dataclass +class IncludePaths: + cuda: Optional[Path] + libcudacxx: Optional[Path] + cub: Optional[Path] + thrust: Optional[Path] + + def as_tuple(self): + # Note: higher-level ... lower-level order: + return (self.thrust, self.cub, self.libcudacxx, self.cuda) + + +@lru_cache() +def get_include_paths() -> IncludePaths: + # TODO: once docs env supports Python >= 3.9, we + # can move this to a module-level import. + from importlib.resources import as_file, files + + cuda_incl = None + cuda_path = _get_cuda_path() + if cuda_path is not None: + cuda_incl = cuda_path / "include" + + with as_file(files("cuda.cccl.include")) as f: + cccl_incl = Path(f) + assert cccl_incl.exists() + + return IncludePaths( + cuda=cuda_incl, + libcudacxx=cccl_incl, + cub=cccl_incl, + thrust=cccl_incl, + ) diff --git a/python/new_cuda_cccl/pyproject.toml b/python/new_cuda_cccl/pyproject.toml new file mode 100644 index 00000000000..084bdf6a3c2 --- /dev/null +++ b/python/new_cuda_cccl/pyproject.toml @@ -0,0 +1,46 @@ +# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. +# +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +[build-system] +requires = ["scikit-build-core>=0.10", "setuptools"] +build-backend = "scikit_build_core.build" + +[project] +name = "cuda-cccl" +description = "Experimental Package with CCCL headers to support JIT compilation" +authors = [{ name = "NVIDIA Corporation" }] +classifiers = [ + "Programming Language :: Python :: 3 :: Only", + "Environment :: GPU :: NVIDIA CUDA", + "License :: OSI Approved :: Apache Software License", +] +license-files = ["LICENSE"] +requires-python = ">=3.9" +version = "3.0.0" +# dynamic = ["version", "readme"] + +[project.urls] +Homepage = "https://github.com/NVIDIA/cccl" + +[tool.scikit-build] +minimum-version = "build-system.requires" +build-dir = "build/{wheel_tag}" + +[tool.scikit-build.cmake] +version = ">=3.21" +args = [] +build-type = "Release" +source-dir = "." + +[tool.scikit-build.ninja] +version = ">=1.11" +make-fallback = true + +[tool.scikit-build.wheel] +py-api = "py3" +platlib = "" + +[tool.scikit-build.wheel.packages] +"cuda" = "cuda" +"cuda/cccl" = "cuda/cccl" diff --git a/python/new_cuda_cccl/test/test_cuda_cccl.py b/python/new_cuda_cccl/test/test_cuda_cccl.py new file mode 100644 index 00000000000..4a907041cca --- /dev/null +++ b/python/new_cuda_cccl/test/test_cuda_cccl.py @@ -0,0 +1,21 @@ +import cuda.cccl as c4l + + +def test_headers(): + inc_paths = c4l.get_include_paths() + assert hasattr(inc_paths, "cuda") + assert hasattr(inc_paths, "cub") + assert hasattr(inc_paths, "libcudacxx") + assert hasattr(inc_paths, "thrust") + tpl = inc_paths.as_tuple() + assert len(tpl) == 4 + thrust_, cub_, cudacxx_, cuda_ = tpl + assert cuda_ == inc_paths.cuda + assert cub_ == inc_paths.cub + assert cudacxx_ == inc_paths.libcudacxx + assert thrust_ == inc_paths.thrust + + +def test_version(): + v = c4l.__version__ + assert isinstance(v, str) From c000604db92df054a2c274f32e22be5275ea251f Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Wed, 29 Jan 2025 18:30:38 -0600 Subject: [PATCH 2/8] Make project.version metadata dynamic Use suggestion by Bradley to use scikit-build-core regex facility to extract version value from "_version.py" --- python/new_cuda_cccl/pyproject.toml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/new_cuda_cccl/pyproject.toml b/python/new_cuda_cccl/pyproject.toml index 084bdf6a3c2..71b87d50c1a 100644 --- a/python/new_cuda_cccl/pyproject.toml +++ b/python/new_cuda_cccl/pyproject.toml @@ -8,6 +8,7 @@ build-backend = "scikit_build_core.build" [project] name = "cuda-cccl" +dynamic = ["version"] description = "Experimental Package with CCCL headers to support JIT compilation" authors = [{ name = "NVIDIA Corporation" }] classifiers = [ @@ -17,8 +18,7 @@ classifiers = [ ] license-files = ["LICENSE"] requires-python = ">=3.9" -version = "3.0.0" -# dynamic = ["version", "readme"] +readme = { file = "README.md", content-type = "text/markdown" } [project.urls] Homepage = "https://github.com/NVIDIA/cccl" @@ -44,3 +44,8 @@ platlib = "" [tool.scikit-build.wheel.packages] "cuda" = "cuda" "cuda/cccl" = "cuda/cccl" + +[tool.scikit-build.metadata.version] +provider = "scikit_build_core.metadata.regex" +input = "cuda/cccl/_version.py" +# use default regex From b2be8564040c45761b0a4e24d9344551790a844b Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Wed, 29 Jan 2025 18:33:25 -0600 Subject: [PATCH 3/8] Delete existing cuda_cccl --- python/cuda_cccl/.gitignore | 2 - python/cuda_cccl/README.md | 3 - python/cuda_cccl/cuda/cccl/__init__.py | 8 --- python/cuda_cccl/cuda/cccl/_version.py | 7 --- python/cuda_cccl/cuda/cccl/include_paths.py | 63 --------------------- python/cuda_cccl/pyproject.toml | 29 ---------- python/cuda_cccl/setup.py | 51 ----------------- 7 files changed, 163 deletions(-) delete mode 100644 python/cuda_cccl/.gitignore delete mode 100644 python/cuda_cccl/README.md delete mode 100644 python/cuda_cccl/cuda/cccl/__init__.py delete mode 100644 python/cuda_cccl/cuda/cccl/_version.py delete mode 100644 python/cuda_cccl/cuda/cccl/include_paths.py delete mode 100644 python/cuda_cccl/pyproject.toml delete mode 100644 python/cuda_cccl/setup.py diff --git a/python/cuda_cccl/.gitignore b/python/cuda_cccl/.gitignore deleted file mode 100644 index 24ec757199f..00000000000 --- a/python/cuda_cccl/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -cuda/cccl/include -*egg-info diff --git a/python/cuda_cccl/README.md b/python/cuda_cccl/README.md deleted file mode 100644 index 37f020b6df6..00000000000 --- a/python/cuda_cccl/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Note - -This package is currently FOR INTERNAL USE ONLY and not meant to be used/installed explicitly. diff --git a/python/cuda_cccl/cuda/cccl/__init__.py b/python/cuda_cccl/cuda/cccl/__init__.py deleted file mode 100644 index 5288f071942..00000000000 --- a/python/cuda_cccl/cuda/cccl/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. -# -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -from cuda.cccl._version import __version__ -from cuda.cccl.include_paths import get_include_paths - -__all__ = ["__version__", "get_include_paths"] diff --git a/python/cuda_cccl/cuda/cccl/_version.py b/python/cuda_cccl/cuda/cccl/_version.py deleted file mode 100644 index ec7c29a266e..00000000000 --- a/python/cuda_cccl/cuda/cccl/_version.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. -# -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -# This file is generated by ci/update_version.sh -# Do not edit this file manually. -__version__ = "2.8.0" diff --git a/python/cuda_cccl/cuda/cccl/include_paths.py b/python/cuda_cccl/cuda/cccl/include_paths.py deleted file mode 100644 index da8246b9195..00000000000 --- a/python/cuda_cccl/cuda/cccl/include_paths.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. -# -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -import os -import shutil -from dataclasses import dataclass -from functools import lru_cache -from pathlib import Path -from typing import Optional - - -def _get_cuda_path() -> Optional[Path]: - cuda_path = os.environ.get("CUDA_PATH") - if cuda_path: - cuda_path = Path(cuda_path) - if cuda_path.exists(): - return cuda_path - - nvcc_path = shutil.which("nvcc") - if nvcc_path: - return Path(nvcc_path).parent.parent - - default_path = Path("/usr/local/cuda") - if default_path.exists(): - return default_path - - return None - - -@dataclass -class IncludePaths: - cuda: Optional[Path] - libcudacxx: Optional[Path] - cub: Optional[Path] - thrust: Optional[Path] - - def as_tuple(self): - # Note: higher-level ... lower-level order: - return (self.thrust, self.cub, self.libcudacxx, self.cuda) - - -@lru_cache() -def get_include_paths() -> IncludePaths: - # TODO: once docs env supports Python >= 3.9, we - # can move this to a module-level import. - from importlib.resources import as_file, files - - cuda_incl = None - cuda_path = _get_cuda_path() - if cuda_path is not None: - cuda_incl = cuda_path / "include" - - with as_file(files("cuda.cccl.include")) as f: - cccl_incl = Path(f) - assert cccl_incl.exists() - - return IncludePaths( - cuda=cuda_incl, - libcudacxx=cccl_incl / "libcudacxx", - cub=cccl_incl, - thrust=cccl_incl, - ) diff --git a/python/cuda_cccl/pyproject.toml b/python/cuda_cccl/pyproject.toml deleted file mode 100644 index ada06301a4c..00000000000 --- a/python/cuda_cccl/pyproject.toml +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. -# -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -[build-system] -requires = ["setuptools>=61.0.0"] -build-backend = "setuptools.build_meta" - -[project] -name = "cuda-cccl" -description = "Experimental Package with CCCL headers to support JIT compilation" -authors = [{ name = "NVIDIA Corporation" }] -classifiers = [ - "Programming Language :: Python :: 3 :: Only", - "Environment :: GPU :: NVIDIA CUDA", - "License :: OSI Approved :: Apache Software License", -] -requires-python = ">=3.9" -dynamic = ["version", "readme"] - -[project.urls] -Homepage = "https://github.com/NVIDIA/cccl" - -[tool.setuptools.dynamic] -version = { attr = "cuda.cccl._version.__version__" } -readme = { file = ["README.md"], content-type = "text/markdown" } - -[tool.setuptools.package-data] -cuda = ["cccl/include/**/*"] diff --git a/python/cuda_cccl/setup.py b/python/cuda_cccl/setup.py deleted file mode 100644 index f6e5e3fa033..00000000000 --- a/python/cuda_cccl/setup.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. -# -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -import shutil -from pathlib import Path - -from setuptools import setup -from setuptools.command.build_py import build_py - -PROJECT_PATH = Path(__file__).resolve().parent -CCCL_PATH = PROJECT_PATH.parents[1] - - -class CustomBuildPy(build_py): - """Copy CCCL headers BEFORE super().run() - - Note that the CCCL headers cannot be referenced directly: - setuptools (and pyproject.toml) does not support relative paths that - reference files outside the package directory (like ../../). - This is a restriction designed to avoid inadvertently packaging files - that are outside the source tree. - """ - - def run(self): - cccl_headers = [ - ("cub", "cub"), - ("libcudacxx", "include"), - ("thrust", "thrust"), - ] - - inc_path = PROJECT_PATH / "cuda" / "cccl" / "include" - inc_path.mkdir(parents=True, exist_ok=True) - - for proj_dir, header_dir in cccl_headers: - src_path = CCCL_PATH / proj_dir / header_dir - dst_path = inc_path / proj_dir - if dst_path.exists(): - shutil.rmtree(dst_path) - shutil.copytree(src_path, dst_path) - - init_py_path = inc_path / "__init__.py" - init_py_path.write_text("# Intentionally empty.\n") - - super().run() - - -setup( - license_files=["../../LICENSE"], - cmdclass={"build_py": CustomBuildPy}, -) From dd191f7ddb860ba3fa0fc5d4e2b0ec05c2bd74dd Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Wed, 29 Jan 2025 18:34:08 -0600 Subject: [PATCH 4/8] Rename new_cuda_cccl to cuda_cccl to become ready to open a PR --- python/{new_cuda_cccl => cuda_cccl}/.gitignore | 0 python/{new_cuda_cccl => cuda_cccl}/CMakeLists.txt | 0 python/{new_cuda_cccl => cuda_cccl}/LICENSE | 0 python/{new_cuda_cccl => cuda_cccl}/README.md | 0 python/{new_cuda_cccl => cuda_cccl}/cuda/__init__.py | 0 python/{new_cuda_cccl => cuda_cccl}/cuda/cccl/__init__.py | 0 python/{new_cuda_cccl => cuda_cccl}/cuda/cccl/_version.py | 0 python/{new_cuda_cccl => cuda_cccl}/cuda/cccl/include/__init__.py | 0 python/{new_cuda_cccl => cuda_cccl}/cuda/cccl/include_paths.py | 0 python/{new_cuda_cccl => cuda_cccl}/pyproject.toml | 0 python/{new_cuda_cccl => cuda_cccl}/test/test_cuda_cccl.py | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename python/{new_cuda_cccl => cuda_cccl}/.gitignore (100%) rename python/{new_cuda_cccl => cuda_cccl}/CMakeLists.txt (100%) rename python/{new_cuda_cccl => cuda_cccl}/LICENSE (100%) rename python/{new_cuda_cccl => cuda_cccl}/README.md (100%) rename python/{new_cuda_cccl => cuda_cccl}/cuda/__init__.py (100%) rename python/{new_cuda_cccl => cuda_cccl}/cuda/cccl/__init__.py (100%) rename python/{new_cuda_cccl => cuda_cccl}/cuda/cccl/_version.py (100%) rename python/{new_cuda_cccl => cuda_cccl}/cuda/cccl/include/__init__.py (100%) rename python/{new_cuda_cccl => cuda_cccl}/cuda/cccl/include_paths.py (100%) rename python/{new_cuda_cccl => cuda_cccl}/pyproject.toml (100%) rename python/{new_cuda_cccl => cuda_cccl}/test/test_cuda_cccl.py (100%) diff --git a/python/new_cuda_cccl/.gitignore b/python/cuda_cccl/.gitignore similarity index 100% rename from python/new_cuda_cccl/.gitignore rename to python/cuda_cccl/.gitignore diff --git a/python/new_cuda_cccl/CMakeLists.txt b/python/cuda_cccl/CMakeLists.txt similarity index 100% rename from python/new_cuda_cccl/CMakeLists.txt rename to python/cuda_cccl/CMakeLists.txt diff --git a/python/new_cuda_cccl/LICENSE b/python/cuda_cccl/LICENSE similarity index 100% rename from python/new_cuda_cccl/LICENSE rename to python/cuda_cccl/LICENSE diff --git a/python/new_cuda_cccl/README.md b/python/cuda_cccl/README.md similarity index 100% rename from python/new_cuda_cccl/README.md rename to python/cuda_cccl/README.md diff --git a/python/new_cuda_cccl/cuda/__init__.py b/python/cuda_cccl/cuda/__init__.py similarity index 100% rename from python/new_cuda_cccl/cuda/__init__.py rename to python/cuda_cccl/cuda/__init__.py diff --git a/python/new_cuda_cccl/cuda/cccl/__init__.py b/python/cuda_cccl/cuda/cccl/__init__.py similarity index 100% rename from python/new_cuda_cccl/cuda/cccl/__init__.py rename to python/cuda_cccl/cuda/cccl/__init__.py diff --git a/python/new_cuda_cccl/cuda/cccl/_version.py b/python/cuda_cccl/cuda/cccl/_version.py similarity index 100% rename from python/new_cuda_cccl/cuda/cccl/_version.py rename to python/cuda_cccl/cuda/cccl/_version.py diff --git a/python/new_cuda_cccl/cuda/cccl/include/__init__.py b/python/cuda_cccl/cuda/cccl/include/__init__.py similarity index 100% rename from python/new_cuda_cccl/cuda/cccl/include/__init__.py rename to python/cuda_cccl/cuda/cccl/include/__init__.py diff --git a/python/new_cuda_cccl/cuda/cccl/include_paths.py b/python/cuda_cccl/cuda/cccl/include_paths.py similarity index 100% rename from python/new_cuda_cccl/cuda/cccl/include_paths.py rename to python/cuda_cccl/cuda/cccl/include_paths.py diff --git a/python/new_cuda_cccl/pyproject.toml b/python/cuda_cccl/pyproject.toml similarity index 100% rename from python/new_cuda_cccl/pyproject.toml rename to python/cuda_cccl/pyproject.toml diff --git a/python/new_cuda_cccl/test/test_cuda_cccl.py b/python/cuda_cccl/test/test_cuda_cccl.py similarity index 100% rename from python/new_cuda_cccl/test/test_cuda_cccl.py rename to python/cuda_cccl/test/test_cuda_cccl.py From a00a02f56e6b4b2f96f035eae60891e90b0871b2 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:31:01 -0600 Subject: [PATCH 5/8] Fix build break --- python/cuda_cccl/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/cuda_cccl/CMakeLists.txt b/python/cuda_cccl/CMakeLists.txt index be1e5d62d2d..92311564aa3 100644 --- a/python/cuda_cccl/CMakeLists.txt +++ b/python/cuda_cccl/CMakeLists.txt @@ -17,15 +17,19 @@ find_package(libcudacxx REQUIRED) set(_dest_incl_dir cuda/cccl/include) +# No end slash: create ${_dest_inc_dir}/cub install( DIRECTORY ${CUB_SOURCE_DIR}/cub DESTINATION ${_dest_incl_dir} ) +# No end slash: create ${_dest_inc_dir}/thrust install( DIRECTORY ${Thrust_SOURCE_DIR}/thrust DESTINATION ${_dest_incl_dir} ) +# Slash at the end: copy content of +# include/ into ${_dest_inc_dir}/ install( - DIRECTORY ${libcudacxx_SOURCE_DIR}/include + DIRECTORY ${libcudacxx_SOURCE_DIR}/include/ DESTINATION ${_dest_incl_dir} ) From 792fd5dd5540a74f5d2dec59d3789c84c70ca75a Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Thu, 30 Jan 2025 12:56:01 -0600 Subject: [PATCH 6/8] Expand tests for cuda_cccl 1. Use pytest fixture to reuse computed inc_paths 2. Split long test into smaller individual tests with descriptive names 3. Add tests to check that directories contain expected marker files (versions) 4. Avoid using c4l in favor of cccl --- python/cuda_cccl/test/test_cuda_cccl.py | 54 ++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/python/cuda_cccl/test/test_cuda_cccl.py b/python/cuda_cccl/test/test_cuda_cccl.py index 4a907041cca..cf673b3c89c 100644 --- a/python/cuda_cccl/test/test_cuda_cccl.py +++ b/python/cuda_cccl/test/test_cuda_cccl.py @@ -1,14 +1,37 @@ -import cuda.cccl as c4l +import pytest +from cuda import cccl -def test_headers(): - inc_paths = c4l.get_include_paths() +def test_version(): + v = cccl.__version__ + assert isinstance(v, str) + + +@pytest.fixture +def inc_paths(): + return cccl.get_include_paths() + + +def test_headers_has_cuda(inc_paths): assert hasattr(inc_paths, "cuda") + + +def test_headers_has_cub(inc_paths): assert hasattr(inc_paths, "cub") + + +def test_headers_has_cudacxx(inc_paths): assert hasattr(inc_paths, "libcudacxx") + + +def test_headers_has_thrust(inc_paths): assert hasattr(inc_paths, "thrust") + + +def test_headers_as_tuple(inc_paths): tpl = inc_paths.as_tuple() assert len(tpl) == 4 + thrust_, cub_, cudacxx_, cuda_ = tpl assert cuda_ == inc_paths.cuda assert cub_ == inc_paths.cub @@ -16,6 +39,25 @@ def test_headers(): assert thrust_ == inc_paths.thrust -def test_version(): - v = c4l.__version__ - assert isinstance(v, str) +def test_cub_version(inc_paths): + cub_dir = inc_paths.cub / "cub" + cub_version = cub_dir / "version.cuh" + assert cub_version.exists() + + +def test_thrust_version(inc_paths): + thrust_dir = inc_paths.thrust / "thrust" + thrust_version = thrust_dir / "version.h" + assert thrust_version.exists() + + +def test_cudacxx_version(inc_paths): + cudacxx_dir = inc_paths.libcudacxx / "cuda" + cudacxx_version = cudacxx_dir / "version" + assert cudacxx_version.exists() + + +def test_nv_target(inc_paths): + nv_dir = inc_paths.libcudacxx / "nv" + nv_target = nv_dir / "target" + assert nv_target.exists() From d392111f0bc4c387c298978eb6cba4e863c068f4 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Fri, 31 Jan 2025 11:45:58 -0600 Subject: [PATCH 7/8] Change cuda_parallel over to use scikit-build-core --- python/cuda_cccl/pyproject.toml | 2 +- python/cuda_parallel/CMakeLists.txt | 24 +++++++++++++ python/cuda_parallel/LICENSE | 1 + python/cuda_parallel/{setup.py => _setup.py} | 0 .../cuda/parallel/experimental/cccl/.gitkeep} | 0 python/cuda_parallel/pyproject.toml | 36 +++++++++++++++---- 6 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 python/cuda_parallel/CMakeLists.txt create mode 120000 python/cuda_parallel/LICENSE rename python/cuda_parallel/{setup.py => _setup.py} (100%) rename python/{cuda_cccl/cuda/__init__.py => cuda_parallel/cuda/parallel/experimental/cccl/.gitkeep} (100%) diff --git a/python/cuda_cccl/pyproject.toml b/python/cuda_cccl/pyproject.toml index 71b87d50c1a..f0e49b4e38c 100644 --- a/python/cuda_cccl/pyproject.toml +++ b/python/cuda_cccl/pyproject.toml @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception [build-system] -requires = ["scikit-build-core>=0.10", "setuptools"] +requires = ["scikit-build-core>=0.10"] build-backend = "scikit_build_core.build" [project] diff --git a/python/cuda_parallel/CMakeLists.txt b/python/cuda_parallel/CMakeLists.txt new file mode 100644 index 00000000000..c42f4119e8e --- /dev/null +++ b/python/cuda_parallel/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.21) + +project( + cuda_parallel +# VERSION ${SKBUILD_PROJECT_VERSION} + DESCRIPTION "Python package cuda_parallel" + LANGUAGES CUDA CXX +) + +set(_cccl_root ../..) + +include(${_cccl_root}/cmake/AppendOptionIfAvailable.cmake) +include(${_cccl_root}/cmake/CCCLConfigureTarget.cmake) +include(${_cccl_root}/cmake/CCCLBuildCompilerTargets.cmake) +cccl_build_compiler_targets() + +set(CCCL_ENABLE_C ON) +set(CCCL_C_PARALLEL_LIBRARY_OUTPUT_DIRECTORY ${SKBUILD_PROJECT_NAME}) +add_subdirectory(${_cccl_root} _parent_cccl) + +install( + TARGETS cccl.c.parallel + DESTINATION cuda/parallel/experimental/cccl +) diff --git a/python/cuda_parallel/LICENSE b/python/cuda_parallel/LICENSE new file mode 120000 index 00000000000..30cff7403da --- /dev/null +++ b/python/cuda_parallel/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/python/cuda_parallel/setup.py b/python/cuda_parallel/_setup.py similarity index 100% rename from python/cuda_parallel/setup.py rename to python/cuda_parallel/_setup.py diff --git a/python/cuda_cccl/cuda/__init__.py b/python/cuda_parallel/cuda/parallel/experimental/cccl/.gitkeep similarity index 100% rename from python/cuda_cccl/cuda/__init__.py rename to python/cuda_parallel/cuda/parallel/experimental/cccl/.gitkeep diff --git a/python/cuda_parallel/pyproject.toml b/python/cuda_parallel/pyproject.toml index e7d2b9f0081..c32f85e1ab8 100644 --- a/python/cuda_parallel/pyproject.toml +++ b/python/cuda_parallel/pyproject.toml @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception [build-system] -requires = ["setuptools>=61.0.0"] -build-backend = "setuptools.build_meta" +requires = ["scikit-build-core>=0.10"] +build-backend = "scikit_build_core.build" [project] name = "cuda-parallel" @@ -17,7 +17,8 @@ classifiers = [ ] requires-python = ">=3.9" dependencies = ["cuda-cccl", "numba>=0.60.0", "cuda-python==12.*"] -dynamic = ["version", "readme"] +dynamic = ["version"] +readme = { file = "README.md", content-type = "text/markdown" } [project.optional-dependencies] test = ["pytest", "pytest-xdist", "cupy-cuda12x", "typing_extensions"] @@ -25,9 +26,32 @@ test = ["pytest", "pytest-xdist", "cupy-cuda12x", "typing_extensions"] [project.urls] Homepage = "https://developer.nvidia.com/" -[tool.setuptools.dynamic] -version = { attr = "cuda.parallel._version.__version__" } -readme = { file = ["README.md"], content-type = "text/markdown" } +[tool.scikit-build] +minimum-version = "build-system.requires" +build-dir = "build/{wheel_tag}" + +[tool.scikit-build.cmake] +version = ">=3.21" +args = [] +build-type = "Release" +source-dir = "." + +[tool.scikit-build.ninja] +version = ">=1.11" +make-fallback = true + +[tool.scikit-build.wheel] +py-api = "py3" + +[tool.scikit-build.wheel.packages] +"cuda" = "cuda" +"cuda/parallel" = "cuda/parallel" +"cuda/parallel/experimental" = "cuda/parallel/experimental" + +[tool.scikit-build.metadata.version] +provider = "scikit_build_core.metadata.regex" +input = "cuda/parallel/_version.py" +# use default regex [tool.mypy] python_version = "3.10" From 8e7684139b4dd5cd9fb6d85f15d0a146efaf5465 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Fri, 31 Jan 2025 12:05:11 -0600 Subject: [PATCH 8/8] Delete unused _setup.py --- python/cuda_parallel/_setup.py | 49 ---------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 python/cuda_parallel/_setup.py diff --git a/python/cuda_parallel/_setup.py b/python/cuda_parallel/_setup.py deleted file mode 100644 index c5c9fcd3c32..00000000000 --- a/python/cuda_parallel/_setup.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. -# -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -import subprocess -from pathlib import Path - -from setuptools import Extension, setup -from setuptools.command.build_ext import build_ext - -CCCL_PYTHON_PATH = Path(__file__).resolve().parents[1] -CCCL_PATH = CCCL_PYTHON_PATH.parent - - -class CMakeExtension(Extension): - def __init__(self, name): - super().__init__(name, sources=[]) - - -class BuildCMakeExtension(build_ext): - def run(self): - for ext in self.extensions: - self.build_extension(ext) - - def build_extension(self, ext): - extdir = Path(self.get_ext_fullpath(ext.name)).resolve().parent - cmake_args = [ - "-DCCCL_ENABLE_C=YES", - f"-DCCCL_C_PARALLEL_LIBRARY_OUTPUT_DIRECTORY={extdir}", - "-DCMAKE_BUILD_TYPE=Release", - ] - - build_temp_path = Path(self.build_temp) - build_temp_path.mkdir(parents=True, exist_ok=True) - - subprocess.check_call(["cmake", CCCL_PATH] + cmake_args, cwd=build_temp_path) - subprocess.check_call( - ["cmake", "--build", ".", "--target", "cccl.c.parallel"], - cwd=build_temp_path, - ) - - -setup( - license_files=["../../LICENSE"], - cmdclass={ - "build_ext": BuildCMakeExtension, - }, - ext_modules=[CMakeExtension("cuda.parallel.experimental.cccl.c")], -)