Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ repos:
language: python
files: '^cuda_core/tests/.*\.py$'

- id: check-build-shared-sync
name: Check _build_shared.py copies are identical
language: system
pass_filenames: false
files: '^(cuda_bindings|cuda_core)/_build_shared\.py$'
entry: bash -c
args:
- 'git diff --no-index --exit-code -- cuda_bindings/_build_shared.py cuda_core/_build_shared.py || { echo "ERROR: cuda_bindings/_build_shared.py and cuda_core/_build_shared.py must be byte-identical. Copy one onto the other and commit both." >&2; exit 1; }'
- "_" # fake script name, because bash considers $0 (the first argument) to be the script name

- id: no-markdown-in-docs-source
name: Prevent markdown files in docs/source directories
entry: bash -c
Expand Down
48 changes: 23 additions & 25 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ Thank you for your interest in contributing to CUDA Python! Based on the type of

## Cloning the repository

> **Windows contributors (not WSL):** configure Git for symlinks *before*
> cloning, or the shared PEP 517 build-hook file lands as a text stub instead
> of a working symlink. See [Enabling git symlinks](#enabling-git-symlinks)
> under Development on Windows.
> **Windows contributors (not WSL):** source builds and tests work with
> `core.symlinks=false`. Git symlink support is optional and only affects the
> remaining documentation and metadata links (`CLAUDE.md`,
> `cuda_python/README.md`, and `.git_archival.txt`). See
> [Enabling git symlinks](#enabling-git-symlinks) if you want those links materialized.

Every package in this repository derives its version from git tags using
[`setuptools-scm`](https://setuptools-scm.readthedocs.io/), so **how you clone
Expand Down Expand Up @@ -137,18 +138,18 @@ genuinely cannot provide tags; it is not a substitute for a correct clone.

## Development on Windows

This section collects the Windows-specific setup a contributor needs when
working outside of WSL. WSL contributors can follow the Linux flow in the rest
of this document.
This section collects Windows-specific guidance for contributors working
outside of WSL. WSL contributors can follow the Linux flow in the rest of this
document.

### Enabling git symlinks

The `cuda_core` PEP 517 backend shares source-of-truth helper files with
`cuda_bindings` via symbolic links. Git materializes symlinks by default on
Linux and macOS, but on Windows it needs to be configured before cloning,
otherwise the "symlinks" land in your working tree as plain text files that
contain the target path — enough to look right in `git status`, but not enough
to actually build.
The repository still contains documentation and metadata symlinks, including
`CLAUDE.md`, `cuda_python/README.md`, and the per-package `.git_archival.txt`
files. With `core.symlinks=false`, Git checks them out as plain text files
containing the target path. This does not affect source builds or tests.

If you want these links materialized as symlinks:

1. **[Activate Developer Mode](https://learn.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development#activate-developer-mode)**
so Git can create symlinks without Administrator privileges.
Expand All @@ -162,22 +163,19 @@ to actually build.

Then clone as usual (see [Cloning the repository](#cloning-the-repository)).

If you already cloned without these settings, note that `git clone` probes
symlink support at clone time and writes `core.symlinks=false` into the
repo-local config when the probe fails. Repo-local config overrides
`--global`, so you must clear it *inside the existing clone* — the global
setting alone won't take effect:
If you already cloned with `core.symlinks=false`, the repository-local
setting overrides the global setting. Enable it locally, then rematerialize
all tracked symlinks. For example:

```console
$ git config core.symlinks true # no --global — clears the repo-local override
$ git rm --cached cuda_core/_build_shared.py
$ git checkout HEAD -- cuda_core/_build_shared.py
$ git config core.symlinks true
$ git rm --cached cuda_python/README.md
$ git checkout HEAD -- cuda_python/README.md
```

In practice, deleting the checkout and re-cloning after the two steps at
the top of this section (Developer Mode + `git config --global core.symlinks
true`) is usually simpler and less error-prone than repairing an existing
clone in place.
Repeat the last two commands for every other tracked symlink. Re-cloning after
enabling Developer Mode and setting the global option is simpler if you want
all links restored.

### Pre-commit lychee workaround

Expand Down
5 changes: 3 additions & 2 deletions cuda_bindings/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ subpackage in the `cuda-python` monorepo.
- **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_core/_build_shared.py` is a symlink to this
file, so an edit here changes both packages.
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.

## Generated-source workflow

Expand Down
2 changes: 1 addition & 1 deletion cuda_bindings/MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ recursive-include cuda/ *.pyx *.pxd *.pxi *.pyx.in *.pxd.in *.pxi.in *.h
# to the payload, causing file copying to the build environment failed
exclude cuda/bindings cuda?bindings
exclude cuda/bindings/_bindings cuda?bindings?_bindings
# canonical shared PEP 517 helper (cuda_core/_build_shared.py symlinks to the cuda_bindings copy)
# package-local shared PEP 517 helper
include _build_shared.py
13 changes: 6 additions & 7 deletions cuda_bindings/_build_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

"""Build helpers shared by the cuda-bindings and cuda-core PEP 517 backends.

This is the single source of truth. ``cuda_core/_build_shared.py`` is a symlink
to this file. Python does not dereference symlinks in ``__file__``, so any
``Path(__file__)``-relative location in here resolves under whichever package
loads it.
``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
the helper through their package-local path, keeping ``Path(__file__)``-relative
state package-local.

PEP 517 build isolation gives each backend its own ``build_hooks.py`` but not a
shared import path. Both packages declare ``backend-path = ["."]``, which puts
Expand Down Expand Up @@ -385,9 +385,8 @@ def _stable_cython_alias(target: Path, alias: Path):
unstable across runs. This context manager creates a fixed, worktree-
relative symlink so Cython sees a stable lexical path.

The symlink is created in the *package directory* (the directory containing
this file, which is the package's own copy through the symlink), not in
the cwd, to keep aliases package-local and avoid cross-package races.
The symlink is created in the package directory containing this file, not
in the cwd, to keep aliases package-local and avoid cross-package races.

alias must not already exist as a real file or directory; if it is a
symlink (including a dangling one) it is atomically replaced.
Expand Down
2 changes: 1 addition & 1 deletion cuda_bindings/docs/source/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Requirements

[^2]: The CUDA Runtime static library (``libcudart_static.a`` on Linux, ``cudart_static.lib`` on Windows) is part of the CUDA Toolkit. If using conda packages, it is contained in the ``cuda-cudart-static`` package.

[^3]: The version is derived from git tags via ``setuptools-scm``, so the clone must include tags reaching back to at least the latest ``v*`` tag. Clone with ``git clone https://github.com/NVIDIA/cuda-python.git``; do not use ``--depth`` or ``--no-tags``, since a shallow clone builds without error but produces a bogus version such as ``0.1.dev1+g0d22cb444``. See `Cloning the repository <https://github.com/NVIDIA/cuda-python/blob/main/CONTRIBUTING.md>`_ for details and recovery steps. Windows contributors building outside of WSL should also see `Development on Windows <https://github.com/NVIDIA/cuda-python/blob/main/CONTRIBUTING.md#development-on-windows>`_ for the git-symlink configuration that must be set *before* cloning.
[^3]: The version is derived from git tags via ``setuptools-scm``, so the clone must include tags reaching back to at least the latest ``v*`` tag. Clone with ``git clone https://github.com/NVIDIA/cuda-python.git``; do not use ``--depth`` or ``--no-tags``, since a shallow clone builds without error but produces a bogus version such as ``0.1.dev1+g0d22cb444``. See `Cloning the repository <https://github.com/NVIDIA/cuda-python/blob/main/CONTRIBUTING.md>`_ for details and recovery steps.

Source builds require that the provided CUDA headers are of the same major.minor version as the ``cuda.bindings`` you're trying to build. Despite this requirement, note that the minor version compatibility is still maintained. The build checks the header before it compiles anything. A mismatch stops the build with a message that names the ``cuda.h`` it found and the version this source tree needs. Use the ``CUDA_PATH`` (or ``CUDA_HOME``) environment variable to specify the location of your headers. If both are set, ``CUDA_PATH`` takes precedence. For example, if your headers are located in ``/usr/local/cuda/include``, then you should set ``CUDA_PATH`` with:

Expand Down
5 changes: 3 additions & 2 deletions cuda_core/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ This file describes `cuda_core`, the high-level Pythonic CUDA subpackage in the
- **Build backend**: `build_hooks.py` handles Cython extension setup and build
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`, a symlink to `cuda_bindings/_build_shared.py`; an edit through either path changes both
packages.
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.

## Build and version coupling

Expand Down
2 changes: 1 addition & 1 deletion cuda_core/MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ recursive-include cuda/core/_cpp *.cpp *.h *.hpp
recursive-include cuda/core/_include *.h *.hpp
include cuda/core/py.typed
include NOTICE
# canonical shared PEP 517 helper (cuda_core/_build_shared.py symlinks to the cuda_bindings copy)
# package-local shared PEP 517 helper
include _build_shared.py
1 change: 0 additions & 1 deletion cuda_core/_build_shared.py

This file was deleted.

Loading
Loading