Skip to content
Open
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
111 changes: 111 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Thank you for your interest in contributing to CUDA Python! Based on the type of

- [Contributing to CUDA Python](#contributing-to-cuda-python)
- [Table of Contents](#table-of-contents)
- [Cloning the repository](#cloning-the-repository)
- [Recommended clone](#recommended-clone)
- [Fixing an existing clone](#fixing-an-existing-clone)
- [Symptoms of a bad clone](#symptoms-of-a-bad-clone)
- [Type stubs for cuda.core](#type-stubs-for-cudacore)
- [Pre-commit](#pre-commit)
- [Signing Your Work](#signing-your-work)
Expand All @@ -34,6 +38,113 @@ Thank you for your interest in contributing to CUDA Python! Based on the type of
- [Code coverage](#code-coverage)


## Cloning the repository

Every package in this repository derives its version from git tags using
[`setuptools-scm`](https://setuptools-scm.readthedocs.io/), so **how you clone
determines whether you can build at all, and whether the version you build is
correct.** Each package matches its own tag prefix:

| Package | Tag pattern |
| --- | --- |
| `cuda-bindings`, `cuda-python` | `v*` (e.g. `v13.3.1`) |
| `cuda-core` | `cuda-core-v*` (e.g. `cuda-core-v1.1.0`) |
| `cuda-pathfinder` | `cuda-pathfinder-v*` (e.g. `cuda-pathfinder-v1.6.0`) |

Each package sets `root = ".."` in its `[tool.setuptools_scm]` table, meaning the
version is read from the *repository root* rather than the package directory. A
working build therefore needs all of the following:

1. **A real git clone.** Source zips and GitHub "Download ZIP" archives have no
git metadata and the build fails outright. (Tarballs produced by
`git archive` do work, thanks to the `.git_archival.txt` substitutions
configured in `.gitattributes`.)
2. **The full repository**, not just the package subdirectory, because the
version lookup walks up to the repository root.
3. **Tags, reaching back at least as far as the most recent tag** matching the
package you are building. `git describe` needs to find that tag; the history
between it and your checkout must be present too.

Each package is tagged on its own cadence, so the distance from `main` back to
the relevant tag differs per package and grows as commits land between releases.
There is no `--depth` value that is safe for all four packages, and any value
that works today will silently stop working later.

This makes a partial `--depth` actively dangerous, because it can succeed for one
package while quietly failing for the others. A `--depth 20` clone taken while
the nearest `cuda-pathfinder-v*` tag was 10 commits back gives:

```text
cuda_pathfinder -> 1.6.1.dev10+g0d22cb4 # correct
cuda_core -> 0.1.dev20+g0d22cb444 # wrong, no error
cuda_bindings -> 0.1.dev20+g0d22cb444 # wrong, no error
```
Comment on lines +68 to +81

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is way too much detail.

Suggested change
Each package is tagged on its own cadence, so the distance from `main` back to
the relevant tag differs per package and grows as commits land between releases.
There is no `--depth` value that is safe for all four packages, and any value
that works today will silently stop working later.
This makes a partial `--depth` actively dangerous, because it can succeed for one
package while quietly failing for the others. A `--depth 20` clone taken while
the nearest `cuda-pathfinder-v*` tag was 10 commits back gives:
```text
cuda_pathfinder -> 1.6.1.dev10+g0d22cb4 # correct
cuda_core -> 0.1.dev20+g0d22cb444 # wrong, no error
cuda_bindings -> 0.1.dev20+g0d22cb444 # wrong, no error
```


### Recommended clone

```console
$ git clone --filter=blob:none https://github.com/NVIDIA/cuda-python.git
```

This is a *treeless* clone: it fetches the complete commit graph and all tags
(which is what `setuptools-scm` needs) while skipping historical file contents
(which it does not). It is substantially faster than a plain clone and is
exactly what CI uses — see the `fetch-depth: 0` plus `filter: blob:none`
checkout settings in `.github/workflows/build-wheel.yml`.

Do **not** use `--depth`, `--shallow-since`, or `--no-tags`.
Comment on lines +83 to +95

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we just recommend the defaults, tbh.

Suggested change
### Recommended clone
```console
$ git clone --filter=blob:none https://github.com/NVIDIA/cuda-python.git
```
This is a *treeless* clone: it fetches the complete commit graph and all tags
(which is what `setuptools-scm` needs) while skipping historical file contents
(which it does not). It is substantially faster than a plain clone and is
exactly what CI uses — see the `fetch-depth: 0` plus `filter: blob:none`
checkout settings in `.github/workflows/build-wheel.yml`.
Do **not** use `--depth`, `--shallow-since`, or `--no-tags`.


### Fixing an existing clone

If you already have a shallow clone:

```console
$ git fetch --unshallow --tags
```

If you are working from a personal fork, your fork's tags stop tracking upstream
the moment new releases are cut, which silently yields a stale version. Fetch
tags from upstream directly:

```console
$ git remote add upstream https://github.com/NVIDIA/cuda-python.git
$ git fetch --tags upstream
```

Keep doing this periodically — a fork that was correct when you created it will
drift.

### Symptoms of a bad clone

Only case 3 below reports an error. The first two fail *silently*, producing a
wrong version that surfaces much later as a confusing dependency-resolution or
version-check failure:

1. **No tags reachable.** The build succeeds and produces a version starting at
`0.1.dev`: a `--depth 1` clone yields `0.1.dev1+g0d22cb444`, a full clone made
with `--no-tags` yields `0.1.dev2114+g0d22cb444`. Installing `cuda-python`
built this way then fails, because its `install_requires` pins
`cuda-bindings` to that same bogus version.
2. **Stale tags** (a fork that has not fetched upstream in a while): you get a
plausible-looking but wrong version, e.g. `13.0.4.dev650+g0d22cb44` when the
real latest tag is `v13.3.1`. Nothing warns you. Note there is no leading
`v` — the tag prefix is stripped by `tag_regex`.
3. **No git metadata** (source zip): the build fails with
`LookupError: setuptools-scm was unable to detect version`.

As a last resort — for example when building inside a container that has no git
history — you can bypass the lookup entirely:

```console
$ SETUPTOOLS_SCM_PRETEND_VERSION_FOR_CUDA_CORE=1.1.0 pip install ./cuda_core
```

The environment variable is suffixed with the distribution name, uppercased with
hyphens replaced by underscores: `..._FOR_CUDA_BINDINGS`, `..._FOR_CUDA_CORE`,
`..._FOR_CUDA_PATHFINDER`, `..._FOR_CUDA_PYTHON`. Use this only when you
genuinely cannot provide tags; it is not a substitute for a correct clone.


## Type stubs for cuda.core

`cuda.core` is a PEP 561-compliant package: it ships a `py.typed` marker and
Expand Down
3 changes: 3 additions & 0 deletions cuda_bindings/docs/source/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,14 @@ Requirements

* CUDA Toolkit headers[^1]
* CUDA Runtime static library[^2]
* A git clone of the repository that includes tags[^3]

[^1]: User projects that ``cimport`` CUDA symbols in Cython must also use CUDA Toolkit (CTK) types as provided by the ``cuda.bindings`` major.minor version. This results in CTK headers becoming a transitive dependency of downstream projects through CUDA Python.

[^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 --filter=blob:none 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. 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:

.. code-block:: console
Expand Down
16 changes: 13 additions & 3 deletions cuda_core/docs/source/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ Development with uv

.. code-block:: console

$ git clone https://github.com/NVIDIA/cuda-python
$ git clone --filter=blob:none https://github.com/NVIDIA/cuda-python.git
$ cd cuda-python/cuda_core
$ uv venv
$ source .venv/bin/activate # On Windows: .venv\Scripts\activate
Expand All @@ -132,7 +132,7 @@ From the repository root:

.. code-block:: console

$ git clone https://github.com/NVIDIA/cuda-python
$ git clone --filter=blob:none https://github.com/NVIDIA/cuda-python.git
$ cd cuda-python
$ pixi run -e cu13 test-core

Expand All @@ -151,8 +151,18 @@ Installing from Source

.. code-block:: console

$ git clone https://github.com/NVIDIA/cuda-python
$ git clone --filter=blob:none https://github.com/NVIDIA/cuda-python.git
$ cd cuda-python/cuda_core
$ pip install .

``cuda-bindings`` 12.x or 13.x is a required dependency.

.. note::

The version is derived from git tags via ``setuptools-scm``, so the clone
must include tags reaching back to at least the latest ``cuda-core-v*`` tag.
Do not use ``--depth`` or ``--no-tags``: 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.
12 changes: 11 additions & 1 deletion cuda_pathfinder/docs/source/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Installing from Source

.. code-block:: console

$ git clone https://github.com/NVIDIA/cuda-python
$ git clone --filter=blob:none https://github.com/NVIDIA/cuda-python.git
$ cd cuda-python/cuda_pathfinder
$ pip install .

Expand All @@ -68,3 +68,13 @@ For an editable install (e.g. when developing ``cuda.pathfinder`` itself):
.. code-block:: console

$ pip install -v -e .

.. note::

The version is derived from git tags via ``setuptools-scm``, so the clone
must include tags reaching back to at least the latest ``cuda-pathfinder-v*``
tag. Do not use ``--depth`` or ``--no-tags``: 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.
Loading