From 1f085a6dc4e7fd9d4c86980fce9b232ef7984856 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Tue, 20 Oct 2026 16:18:33 -0400 Subject: [PATCH 1/2] Use tags for blob links from a release --- cuda_bindings/AGENTS.md | 11 ++++--- cuda_bindings/_build_shared.py | 32 +++++++++++++++++-- cuda_bindings/setup.py | 3 +- .../docs/source/10_minutes_to_cuda_core.rst | 3 +- cuda_core/docs/source/conf.py | 4 +++ cuda_core/pyproject.toml | 2 +- cuda_core/setup.py | 3 +- cuda_pathfinder/MANIFEST.in | 5 +++ cuda_pathfinder/_build_shared.py | 1 + cuda_pathfinder/setup.py | 15 +++++++++ 10 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 cuda_pathfinder/MANIFEST.in create mode 120000 cuda_pathfinder/_build_shared.py create mode 100644 cuda_pathfinder/setup.py diff --git a/cuda_bindings/AGENTS.md b/cuda_bindings/AGENTS.md index 389246be5a9..f8e6c7e8e23 100644 --- a/cuda_bindings/AGENTS.md +++ b/cuda_bindings/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/_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/_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/_build_shared.py b/cuda_bindings/_build_shared.py index aedb3f57993..cf75381f726 100644 --- a/cuda_bindings/_build_shared.py +++ b/cuda_bindings/_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/_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/setup.py b/cuda_bindings/setup.py index 1b02b43bace..8cacfed4767 100644 --- a/cuda_bindings/setup.py +++ b/cuda_bindings/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/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 7b8317c9b0b..c92ea458073 100644 --- a/cuda_core/pyproject.toml +++ b/cuda_core/pyproject.toml @@ -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_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..31696363b94 --- /dev/null +++ b/cuda_pathfinder/_build_shared.py @@ -0,0 +1 @@ +../cuda_bindings/_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")}) From 1e23b5201841f95b3710c78fba8e0a3f0d4e0616 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 20 Oct 2026 16:55:21 -0700 Subject: [PATCH 2/2] Clarify version-neutral package names after source-root rename Signed-off-by: Ralf W. Grosse-Kunstleve --- .github/workflows/ci-pixi-source-test.yml | 2 +- .github/workflows/ci.yml | 10 +++++----- cuda_core/AGENTS.md | 2 +- cuda_core/pyproject.toml | 2 +- cuda_core/tests/AGENTS.md | 2 +- .../cuda_python_test_helpers/graphics.py | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) 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_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/pyproject.toml b/cuda_core/pyproject.toml index d4740097b44..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", ] 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_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