diff --git a/.github/workflows/ci-pixi-source-test.yml b/.github/workflows/ci-pixi-source-test.yml index 1ec8b5d8bd1..a09f2e2756f 100644 --- a/.github/workflows/ci-pixi-source-test.yml +++ b/.github/workflows/ci-pixi-source-test.yml @@ -131,7 +131,7 @@ jobs: # The round trip (not just cu13 -> cu12) is what catches the second half: # coming back to cu13 must not silently reuse the cu12 extension. # - # cuda_core only: cuda_bindings_13 cannot be source-built in its cu12 + # cuda_core only: cuda-bindings cannot be source-built in its cu12 # environment at all, for reasons unrelated to stale artifacts. build-identity-roundtrip: name: "cu13 -> cu12 -> cu13 round trip (linux-64, CPU)" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46cde16b3d5..174f560e245 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,13 +122,13 @@ jobs: # # Dependency graph (verified in pyproject.toml files): # cuda_pathfinder -> (no internal deps) - # cuda_bindings_13 -> cuda_pathfinder - # cuda_core -> cuda_pathfinder, cuda_bindings_13 - # cuda_python -> cuda_pathfinder, cuda_bindings_13, cuda_core (meta package) + # cuda_bindings -> cuda_pathfinder + # cuda_core -> cuda_pathfinder, cuda_bindings + # cuda_python -> cuda_pathfinder, cuda_bindings, cuda_core (meta package) # # A change to cuda_pathfinder (or shared infra) forces a rebuild of every - # downstream module. A change to cuda_bindings_13 forces rebuild of cuda_core. - # A change to cuda_core alone skips rebuilding/retesting cuda_bindings_13 and + # downstream module. A change to cuda_bindings forces rebuild of cuda_core. + # A change to cuda_core alone skips rebuilding/retesting cuda_bindings and # cuda_pathfinder, but still retests the downstream cuda-python metapackage. # Shared build/orchestration changes run the full pipeline; test-only CI # infrastructure runs every test suite without rebuilding package wheels. diff --git a/cuda_bindings_13/AGENTS.md b/cuda_bindings_13/AGENTS.md index 327e08bf656..6985c3aa988 100644 --- a/cuda_bindings_13/AGENTS.md +++ b/cuda_bindings_13/AGENTS.md @@ -19,11 +19,12 @@ subpackage in the `cuda-python` monorepo. - **Platform internals**: `cuda/bindings/_internal/` contains platform-specific implementation files and support code. - **Build backend**: `build_hooks.py` drives extension configuration and - Cythonization. Logic shared with `cuda_core` (toolchain selection, the - compiler flag set, the Cython cache helpers and the rebuild stamps) lives - in `_build_shared.py`. `cuda_bindings_13/_build_shared.py` is canonical; - `cuda_core/_build_shared.py` must be either a symlink to it or a byte-for-byte - identical copy. + Cythonization. Logic shared with `cuda_core` and `cuda_pathfinder` + (toolchain selection, the compiler flag set, the Cython cache helpers, the + rebuild stamps and the release-tag pinning of README links) lives in + `_build_shared.py`. `cuda_bindings_13/_build_shared.py` is canonical; + the `cuda_core` and `cuda_pathfinder` copies must each be either a symlink to + it or a byte-for-byte identical copy. ## Generated-source workflow diff --git a/cuda_bindings_13/_build_shared.py b/cuda_bindings_13/_build_shared.py index a6ff54c1f25..8a4faf06686 100644 --- a/cuda_bindings_13/_build_shared.py +++ b/cuda_bindings_13/_build_shared.py @@ -1,10 +1,11 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -"""Build helpers shared by the cuda-bindings and cuda-core PEP 517 backends. +"""Build helpers shared by the cuda-bindings, cuda-core and cuda-pathfinder builds. ``cuda_bindings_13/_build_shared.py`` is canonical. ``cuda_core/_build_shared.py`` -is either a symlink to it or a byte-for-byte identical copy. Both backends load +and ``cuda_pathfinder/_build_shared.py`` are each either a symlink to it or a +byte-for-byte identical copy. Both backends load the helper through their package-local path, keeping ``Path(__file__)``-relative state package-local. @@ -30,6 +31,7 @@ import functools import hashlib import os +import re import shlex import shutil import sys @@ -509,3 +511,29 @@ def record_build_key(stamp, key): """ stamp.parent.mkdir(parents=True, exist_ok=True) stamp.write_text(key + "\n", encoding="utf-8") + + +_SOURCE_LINK_RE = re.compile(r"(https://github\.com/NVIDIA/cuda-python/(?:blob|tree))/main/") + + +def make_egg_info_command(tag_prefix): + """Return an ``egg_info`` command that pins README source links to the release tag. + + DESCRIPTION.rst links to ``main`` so that it renders correctly in the + repository. In a release build, the command pins those links to the tag + that produced the wheel (``tag_prefix`` followed by the version), so that + they survive later repository changes. Development builds keep ``main``. + """ + from packaging.version import Version + from setuptools.command.egg_info import egg_info + + class ReleaseLinksEggInfo(egg_info): + def run(self): + metadata = self.distribution.metadata + version = Version(self.distribution.get_version()) + if not (version.is_devrelease or version.local): + tag = f"{tag_prefix}{version}" + metadata.long_description = _SOURCE_LINK_RE.sub(rf"\1/{tag}/", metadata.long_description) + super().run() + + return ReleaseLinksEggInfo diff --git a/cuda_bindings_13/setup.py b/cuda_bindings_13/setup.py index 1b02b43bace..8cacfed4767 100644 --- a/cuda_bindings_13/setup.py +++ b/cuda_bindings_13/setup.py @@ -11,7 +11,7 @@ from setuptools.command.build_ext import build_ext as _build_ext from setuptools.command.build_py import build_py as _build_py -from _build_shared import drop_empty_venv_include_dir +from _build_shared import drop_empty_venv_include_dir, make_egg_info_command if os.environ.get("PARALLEL_LEVEL") is not None: warn( @@ -65,6 +65,7 @@ def finalize_options(self): cmdclass={ "build_ext": build_ext, "build_py": build_py, + "egg_info": make_egg_info_command("v"), }, zip_safe=False, ) diff --git a/cuda_core/AGENTS.md b/cuda_core/AGENTS.md index e0722b9fcc4..63c6ce8dafa 100644 --- a/cuda_core/AGENTS.md +++ b/cuda_core/AGENTS.md @@ -23,7 +23,7 @@ This file describes `cuda_core`, the high-level Pythonic CUDA subpackage in the one `_cpp/.cpp` or as a directory `_cpp//` whose sources all compile into the `_` extension (`_cpp/rt/` for `_rt`). - **Build backend**: `build_hooks.py` handles Cython extension setup and build - dependency wiring. Logic shared with `cuda_bindings_13` (toolchain selection, + dependency wiring. Logic shared with `cuda-bindings` (toolchain selection, the compiler flag set, the Cython cache helpers and the rebuild stamps) lives in `_build_shared.py`. `cuda_bindings_13/_build_shared.py` is canonical; `cuda_core/_build_shared.py` must be either a symlink to it or a byte-for-byte diff --git a/cuda_core/docs/source/10_minutes_to_cuda_core.rst b/cuda_core/docs/source/10_minutes_to_cuda_core.rst index 33bc5214f6b..5df24494ffd 100644 --- a/cuda_core/docs/source/10_minutes_to_cuda_core.rst +++ b/cuda_core/docs/source/10_minutes_to_cuda_core.rst @@ -316,8 +316,7 @@ for a complete capture-and-replay example with a measured speedup. Beyond the stream capture shown here, ``cuda.core`` also provides an explicit graph interface (the :mod:`cuda.core.graph` module) for building, inspecting, and modifying graphs directly, including graphs first produced by capture. The -project's `graph tests -`_ have +project's :repo-tree:`graph tests ` have many usage examples. diff --git a/cuda_core/docs/source/conf.py b/cuda_core/docs/source/conf.py index 453e75f96d4..fa5b344bcf6 100644 --- a/cuda_core/docs/source/conf.py +++ b/cuda_core/docs/source/conf.py @@ -148,6 +148,10 @@ def _html_baseurl(): copybutton_exclude = ".linenos, .gp" extlinks = { + "repo-tree": ( + f"https://github.com/NVIDIA/cuda-python/tree/{GITHUB_EXAMPLES_REF}/%s", + "%s", + ), # Historical release notes use this role to link into pre-migration tags. "cuda-core-example": ( f"https://github.com/NVIDIA/cuda-python/blob/{GITHUB_EXAMPLES_REF}/cuda_core/examples/%s", diff --git a/cuda_core/pyproject.toml b/cuda_core/pyproject.toml index f6954701050..e850dadacfe 100644 --- a/cuda_core/pyproject.toml +++ b/cuda_core/pyproject.toml @@ -79,7 +79,7 @@ test = [ "psutil==7.2.2; sys_platform != 'win32' or python_version < '3.15'", "packaging>=24", "docutils==0.23", - # Required by tests/test_graphics.py; pinned to match cuda_bindings_13. + # Required by tests/test_graphics.py; pinned to match cuda-bindings. "pyglet==2.1.14", "cffi==2.1.1", ] @@ -103,7 +103,7 @@ conflicts = [ [project.urls] homepage = "https://nvidia.github.io/cuda-python/" documentation = "https://nvidia.github.io/cuda-python/cuda-core/" -repository = "https://github.com/NVIDIA/cuda-python/tree/main/cuda_core" +repository = "https://github.com/NVIDIA/cuda-python" issues = "https://github.com/NVIDIA/cuda-python/issues/" [tool.setuptools.packages.find] diff --git a/cuda_core/setup.py b/cuda_core/setup.py index 1e6c4f9508d..795c80546aa 100644 --- a/cuda_core/setup.py +++ b/cuda_core/setup.py @@ -13,7 +13,7 @@ from setuptools.command.build_ext import build_ext as _build_ext from setuptools.command.build_py import build_py as _build_py -from _build_shared import drop_empty_venv_include_dir +from _build_shared import drop_empty_venv_include_dir, make_egg_info_command nthreads = int(os.environ.get("CUDA_PYTHON_PARALLEL_LEVEL", os.cpu_count() // 2)) coverage_mode = bool(int(os.environ.get("CUDA_PYTHON_COVERAGE", "0"))) @@ -160,6 +160,7 @@ def finalize_options(self): cmdclass={ "build_ext": build_ext, "build_py": build_py, + "egg_info": make_egg_info_command("cuda-core-v"), }, zip_safe=False, ) diff --git a/cuda_core/tests/AGENTS.md b/cuda_core/tests/AGENTS.md index 6e51ed61ecb..8bf0a6c7162 100644 --- a/cuda_core/tests/AGENTS.md +++ b/cuda_core/tests/AGENTS.md @@ -109,7 +109,7 @@ Follow these rules when adding or moving shared test code: before adding a new helper; consolidate duplicates across packages into `cuda_python_test_helpers` (both `cuda_core` and - `cuda_bindings_13` test environments already depend on it). + `cuda-bindings` test environments already depend on it). - Fixtures in a nested `conftest.py` are available to tests in its directory and descendants; fixtures from applicable parent `conftest.py` files remain available. diff --git a/cuda_pathfinder/MANIFEST.in b/cuda_pathfinder/MANIFEST.in new file mode 100644 index 00000000000..ebfa7352318 --- /dev/null +++ b/cuda_pathfinder/MANIFEST.in @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# package-local shared build helper, imported by setup.py +include _build_shared.py diff --git a/cuda_pathfinder/_build_shared.py b/cuda_pathfinder/_build_shared.py new file mode 120000 index 00000000000..e4ab5964749 --- /dev/null +++ b/cuda_pathfinder/_build_shared.py @@ -0,0 +1 @@ +../cuda_bindings_13/_build_shared.py \ No newline at end of file diff --git a/cuda_pathfinder/setup.py b/cuda_pathfinder/setup.py new file mode 100644 index 00000000000..90f1296de6f --- /dev/null +++ b/cuda_pathfinder/setup.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +import sys +from pathlib import Path + +from setuptools import setup + +# setuptools.build_meta does not put the package directory on sys.path. +sys.path.insert(0, str(Path(__file__).resolve().parent)) + +from _build_shared import make_egg_info_command + +setup(cmdclass={"egg_info": make_egg_info_command("cuda-pathfinder-v")}) diff --git a/cuda_python_test_helpers/cuda_python_test_helpers/graphics.py b/cuda_python_test_helpers/cuda_python_test_helpers/graphics.py index 8b8a80fb1a5..96561e8b244 100644 --- a/cuda_python_test_helpers/cuda_python_test_helpers/graphics.py +++ b/cuda_python_test_helpers/cuda_python_test_helpers/graphics.py @@ -4,7 +4,7 @@ """Shared GL helpers for graphics interop tests. -Both ``cuda_core`` and ``cuda_bindings_13`` graphics tests need to skip +Both ``cuda_core`` and ``cuda_bindings`` graphics tests need to skip when the GL backend cannot be made current, and that decision must not hide real bugs in the tests' own GL allocation code. This module owns the shared predicate so the two test suites stay in sync. @@ -135,7 +135,7 @@ def tcc_skip_reason() -> str | None: OpenGL support, so CUDA-GL interop is unavailable on a TCC device. The check queries the currently-selected device via the CUDA runtime API (``cuda.bindings``) rather than ``cuda.core``, so both the ``cuda_core`` - and ``cuda_bindings_13`` graphics tests can share it without the latter + and ``cuda_bindings`` graphics tests can share it without the latter taking a ``cuda.core`` dependency. Runtime query failures (e.g. no CUDA device) propagate rather than being