Skip to content

Commit 3505cf1

Browse files
kkraus14cursoragent
andcommitted
Switch to uv build frontend and add top-level uv workspace
- Add root pyproject.toml as virtual uv workspace covering cuda_bindings, cuda_core, cuda_pathfinder, cuda_python, and cuda_python_test_helpers. - Declare workspace-level cu12/cu13 conflicts so uv lock can resolve the mutually-exclusive cuda-toolkit version requirements. - Add [tool.cibuildwheel] build-frontend = "build[uv]" to cuda_bindings and cuda_core. - Add [tool.uv.sources] workspace references to cuda_bindings and cuda_core so transitive workspace deps resolve during lock. - Add cuda-pathfinder to cuda_core build-system.requires so uv sees the transitive build dependency chain. - Make cuda_python dependencies static in pyproject.toml. - Replace pip with uv across all CI workflows (build-wheel, test-wheel-linux, test-wheel-windows, build-docs, coverage) and ci/tools/run-tests. - Install uv via astral-sh/setup-uv@v5 in every workflow. - Use uv build --wheel, uv pip install, and uv sync --only-group for dependency group installation. - Exclude uv.lock from SPDX and large-file pre-commit checks. - Generate uv.lock for the workspace. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 0921933 commit 3505cf1

File tree

13 files changed

+3468
-56
lines changed

13 files changed

+3468
-56
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ cuda_core/cuda/core/_cpp/*.hpp -binary text diff
1616
*.svg binary
1717
# SCM syntax highlighting & preventing 3-way merges
1818
pixi.lock merge=binary linguist-language=YAML linguist-generated=true
19+
uv.lock merge=binary linguist-language=TOML linguist-generated=true

.github/workflows/build-docs.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1+
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

@@ -77,6 +77,9 @@ jobs:
7777
conda config --show-sources
7878
conda config --show
7979
80+
- name: Install uv
81+
uses: astral-sh/setup-uv@v5
82+
8083
# WAR: Building the doc currently requires CTK installed (NVIDIA/cuda-python#326,327)
8184
- name: Set up mini CTK
8285
uses: ./.github/actions/fetch_ctk
@@ -181,18 +184,18 @@ jobs:
181184
- name: Install all packages
182185
run: |
183186
pushd cuda_pathfinder
184-
pip install *.whl
187+
uv pip install *.whl
185188
popd
186189
187190
pushd "${CUDA_BINDINGS_ARTIFACTS_DIR}"
188-
pip install *.whl
191+
uv pip install *.whl
189192
popd
190193
191194
pushd "${CUDA_CORE_ARTIFACTS_DIR}"
192-
pip install *.whl
195+
uv pip install *.whl
193196
popd
194197
195-
pip install cuda_python*.whl
198+
uv pip install cuda_python*.whl
196199
197200
# This step sets the PR_NUMBER/BUILD_LATEST/BUILD_PREVIEW env vars.
198201
- name: Get PR number

.github/workflows/build-wheel.yml

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,18 @@ jobs:
106106
run: |
107107
env
108108
109+
- name: Install uv
110+
uses: astral-sh/setup-uv@v5
111+
109112
- name: Install twine
110113
run: |
111-
pip install twine
114+
uv pip install twine
112115
113116
# To keep the build workflow simple, all matrix jobs will build a wheel for later use within this workflow.
114117
- name: Build and check cuda.pathfinder wheel
115118
run: |
116119
pushd cuda_pathfinder
117-
pip wheel -v --no-deps .
120+
uv build --wheel
118121
popd
119122
120123
- name: List the cuda.pathfinder artifacts directory
@@ -124,22 +127,22 @@ jobs:
124127
else
125128
export CHOWN="sudo chown"
126129
fi
127-
$CHOWN -R $(whoami) cuda_pathfinder/*.whl
128-
ls -lahR cuda_pathfinder
130+
$CHOWN -R $(whoami) cuda_pathfinder/dist/*.whl
131+
ls -lahR cuda_pathfinder/dist
129132
130133
# We only need/want a single pure python wheel, pick linux-64 index 0.
131134
# This is what we will use for testing & releasing.
132135
- name: Check cuda.pathfinder wheel
133136
if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }}
134137
run: |
135-
twine check --strict cuda_pathfinder/*.whl
138+
twine check --strict cuda_pathfinder/dist/*.whl
136139
137140
- name: Upload cuda.pathfinder build artifacts
138141
if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }}
139142
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
140143
with:
141144
name: cuda-pathfinder-wheel
142-
path: cuda_pathfinder/*.whl
145+
path: cuda_pathfinder/dist/*.whl
143146
if-no-files-found: error
144147

145148
- name: Set up mini CTK
@@ -267,8 +270,8 @@ jobs:
267270
if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }}
268271
run: |
269272
pushd cuda_python
270-
pip wheel -v --no-deps .
271-
twine check --strict *.whl
273+
uv build --wheel
274+
twine check --strict dist/*.whl
272275
popd
273276
274277
- name: List the cuda-python artifacts directory
@@ -279,15 +282,15 @@ jobs:
279282
else
280283
export CHOWN="sudo chown"
281284
fi
282-
$CHOWN -R $(whoami) cuda_python/*.whl
283-
ls -lahR cuda_python
285+
$CHOWN -R $(whoami) cuda_python/dist/*.whl
286+
ls -lahR cuda_python/dist
284287
285288
- name: Upload cuda-python build artifacts
286289
if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }}
287290
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
288291
with:
289292
name: cuda-python-wheel
290-
path: cuda_python/*.whl
293+
path: cuda_python/dist/*.whl
291294
if-no-files-found: error
292295

293296
- name: Set up Python
@@ -312,11 +315,12 @@ jobs:
312315
313316
- name: Install cuda.pathfinder (required for next step)
314317
run: |
315-
pip install cuda_pathfinder/*.whl
318+
uv pip install cuda_pathfinder/dist/*.whl
316319
317320
- name: Build cuda.bindings Cython tests
318321
run: |
319-
pip install ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}/*.whl --group ./cuda_bindings/pyproject.toml:test
322+
uv pip install ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}/*.whl
323+
uv pip install "pytest>=6.2.4" "pytest-benchmark>=3.4.1" pytest-randomly pytest-repeat "pyglet>=2.1.9" "numpy>=1.21.1" "cython>=3.2,<3.3" "setuptools>=77.0.0"
320324
pushd ${{ env.CUDA_BINDINGS_CYTHON_TESTS_DIR }}
321325
bash build_tests.sh
322326
popd
@@ -330,7 +334,8 @@ jobs:
330334

331335
- name: Build cuda.core Cython tests
332336
run: |
333-
pip install ${{ env.CUDA_CORE_ARTIFACTS_DIR }}/"cu${BUILD_CUDA_MAJOR}"/*.whl --group ./cuda_core/pyproject.toml:test
337+
uv pip install ${{ env.CUDA_CORE_ARTIFACTS_DIR }}/"cu${BUILD_CUDA_MAJOR}"/*.whl
338+
uv pip install "pytest>=6.2.4" pytest-randomly pytest-repeat "cython>=3.2,<3.3" setuptools
334339
pushd ${{ env.CUDA_CORE_CYTHON_TESTS_DIR }}
335340
bash build_tests.sh
336341
popd
@@ -444,7 +449,7 @@ jobs:
444449
445450
- name: Merge cuda.core wheels
446451
run: |
447-
pip install wheel
452+
uv pip install wheel
448453
python ci/tools/merge_cuda_core_wheels.py \
449454
"${{ env.CUDA_CORE_ARTIFACTS_DIR }}"/cu"${BUILD_CUDA_MAJOR}"/cuda_core*.whl \
450455
"${{ env.CUDA_CORE_ARTIFACTS_DIR }}"/cu"${BUILD_PREV_CUDA_MAJOR}"/cuda_core*.whl \

.github/workflows/coverage.yml

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

@@ -82,6 +82,9 @@ jobs:
8282
# we use self-hosted runners on which setup-python behaves weirdly...
8383
AGENT_TOOLSDIRECTORY: "/opt/hostedtoolcache"
8484

85+
- name: Install uv
86+
uses: astral-sh/setup-uv@v5
87+
8588
- name: Set up mini CTK
8689
if: ${{ env.LOCAL_CTK == '1' }}
8790
uses: ./.github/actions/fetch_ctk
@@ -92,29 +95,29 @@ jobs:
9295

9396
- name: Create venv
9497
run: |
95-
python -m venv .venv
98+
uv venv .venv
9699
97100
- name: Build cuda-pathfinder
98101
run: |
99-
.venv/bin/pip install -v ./cuda_pathfinder
102+
uv pip install --python .venv/bin/python -v ./cuda_pathfinder
100103
101104
- name: Build cuda-python-test-helpers
102105
run: |
103-
.venv/bin/pip install -v ./cuda_python_test_helpers
106+
uv pip install --python .venv/bin/python -v ./cuda_python_test_helpers
104107
105108
- name: Build cuda-bindings
106109
run: |
107-
cd cuda_bindings
108-
../.venv/bin/pip install -v . --group test
110+
uv pip install --python .venv/bin/python -v ./cuda_bindings
111+
cd cuda_bindings && uv sync --python ../.venv/bin/python --package cuda-bindings --only-group test --no-install-project && cd ..
109112
110113
- name: Build cuda-core
111114
run: |
112-
cd cuda_core
113-
../.venv/bin/pip install -v . --group test
115+
uv pip install --python .venv/bin/python -v ./cuda_core
116+
cd cuda_core && uv sync --python ../.venv/bin/python --package cuda-core --only-group "test-cu$(cut -d. -f1 <<< $CUDA_VER)" --no-install-project && cd ..
114117
115118
- name: Install coverage tools
116119
run: |
117-
.venv/bin/pip install coverage pytest-cov
120+
uv pip install --python .venv/bin/python coverage pytest-cov
118121
119122
- name: Set cuda package install root
120123
run: |

.github/workflows/test-wheel-linux.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ jobs:
224224
# we use self-hosted runners on which setup-python behaves weirdly (Python include can't be found)...
225225
AGENT_TOOLSDIRECTORY: "/opt/hostedtoolcache"
226226

227+
- name: Install uv
228+
uses: astral-sh/setup-uv@v5
229+
227230
- name: Set up mini CTK
228231
if: ${{ matrix.LOCAL_CTK == '1' }}
229232
uses: ./.github/actions/fetch_ctk
@@ -279,17 +282,18 @@ jobs:
279282
- name: Ensure cuda-python installable
280283
run: |
281284
if [[ "${{ matrix.LOCAL_CTK }}" == 1 ]]; then
282-
pip install --only-binary=:all: cuda_python*.whl
285+
uv pip install cuda_python*.whl
283286
else
284-
pip install --only-binary=:all: $(ls cuda_python*.whl)[all]
287+
uv pip install $(ls cuda_python*.whl)[all]
285288
fi
286289
287290
- name: Install cuda.pathfinder extra wheels for testing
288291
run: |
289292
set -euo pipefail
290293
pushd cuda_pathfinder
291-
pip install --only-binary=:all: -v ./*.whl --group "test-cu${TEST_CUDA_MAJOR}"
292-
pip list
294+
uv pip install -v ./*.whl
295+
uv sync --package cuda-pathfinder --only-group "test-cu${TEST_CUDA_MAJOR}" --no-install-project
296+
uv pip list
293297
popd
294298
295299
- name: Run cuda.pathfinder tests with all_must_work

.github/workflows/test-wheel-windows.yml

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ jobs:
208208
with:
209209
python-version: ${{ matrix.PY_VER }}
210210

211+
- name: Install uv
212+
uses: astral-sh/setup-uv@v5
213+
211214
- name: Set up mini CTK
212215
if: ${{ matrix.LOCAL_CTK == '1' }}
213216
uses: ./.github/actions/fetch_ctk
@@ -254,19 +257,21 @@ jobs:
254257
run: run-tests core
255258

256259
- name: Ensure cuda-python installable
260+
shell: bash --noprofile --norc -xeuo pipefail {0}
257261
run: |
258-
if ('${{ matrix.LOCAL_CTK }}' -eq '1') {
259-
pip install --only-binary=:all: (Get-ChildItem -Filter cuda_python*.whl).FullName
260-
} else {
261-
pip install --only-binary=:all: "$((Get-ChildItem -Filter cuda_python*.whl).FullName)[all]"
262-
}
262+
if [[ "${{ matrix.LOCAL_CTK }}" == 1 ]]; then
263+
uv pip install cuda_python*.whl
264+
else
265+
uv pip install $(ls cuda_python*.whl)[all]
266+
fi
263267
264268
- name: Install cuda.pathfinder extra wheels for testing
265269
shell: bash --noprofile --norc -xeuo pipefail {0}
266270
run: |
267271
pushd cuda_pathfinder
268-
pip install --only-binary=:all: -v ./*.whl --group "test-cu${TEST_CUDA_MAJOR}"
269-
pip list
272+
uv pip install -v ./*.whl
273+
uv sync --package cuda-pathfinder --only-group "test-cu${TEST_CUDA_MAJOR}" --no-install-project
274+
uv pip list
270275
popd
271276
272277
- name: Run cuda.pathfinder tests with all_must_work

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ repos:
2929
language: python
3030
additional_dependencies:
3131
- https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl
32-
exclude: '.*pixi\.lock'
32+
exclude: '.*pixi\.lock|uv\.lock'
3333
args: ["--fix"]
3434

3535
- id: no-markdown-in-docs-source
@@ -46,7 +46,7 @@ repos:
4646
rev: "3e8a8703264a2f4a69428a0aa4dcb512790b2c8c" # frozen: v6.0.0
4747
hooks:
4848
- id: check-added-large-files
49-
exclude: cuda_bindings/cuda/bindings/nvml.pyx
49+
exclude: 'cuda_bindings/cuda/bindings/nvml\.pyx|uv\.lock'
5050
- id: check-case-conflict
5151
- id: check-docstring-first
5252
- id: check-merge-conflict

ci/tools/run-tests

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env bash
22

3-
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

@@ -24,7 +24,8 @@ test_module=${1}
2424
# (it is a direct dependency of bindings, and a transitive dependency of core)
2525
pushd ./cuda_pathfinder
2626
echo "Installing pathfinder wheel"
27-
pip install ./*.whl --group test
27+
uv pip install ./*.whl
28+
uv sync --package cuda-pathfinder --only-group test --no-install-project
2829
popd
2930

3031
if [[ "${test_module}" == "pathfinder" ]]; then
@@ -41,10 +42,11 @@ elif [[ "${test_module}" == "bindings" ]]; then
4142
echo "Installing bindings wheel"
4243
pushd ./cuda_bindings
4344
if [[ "${LOCAL_CTK}" == 1 ]]; then
44-
pip install "${CUDA_BINDINGS_ARTIFACTS_DIR}"/*.whl --group test
45+
uv pip install "${CUDA_BINDINGS_ARTIFACTS_DIR}"/*.whl
4546
else
46-
pip install $(ls "${CUDA_BINDINGS_ARTIFACTS_DIR}"/*.whl)[all] --group test
47+
uv pip install $(ls "${CUDA_BINDINGS_ARTIFACTS_DIR}"/*.whl)[all]
4748
fi
49+
uv sync --package cuda-bindings --only-group test --no-install-project
4850
echo "Running bindings tests"
4951
${SANITIZER_CMD} pytest -rxXs -v --durations=0 tests/
5052
if [[ "${SKIP_CYTHON_TEST}" == 0 ]]; then
@@ -57,9 +59,9 @@ elif [[ "${test_module}" == "core" ]]; then
5759
if [[ "${SKIP_CUDA_BINDINGS_TEST}" == 1 ]]; then
5860
echo "Installing bindings wheel"
5961
if [[ "${LOCAL_CTK}" == 1 ]]; then
60-
pip install "${CUDA_BINDINGS_ARTIFACTS_DIR}"/*.whl
62+
uv pip install "${CUDA_BINDINGS_ARTIFACTS_DIR}"/*.whl
6163
else
62-
pip install $(ls "${CUDA_BINDINGS_ARTIFACTS_DIR}"/*.whl)[all]
64+
uv pip install $(ls "${CUDA_BINDINGS_ARTIFACTS_DIR}"/*.whl)[all]
6365
fi
6466
fi
6567
TEST_CUDA_MAJOR="$(cut -d '.' -f 1 <<< ${CUDA_VER})"
@@ -74,10 +76,11 @@ elif [[ "${test_module}" == "core" ]]; then
7476
if [[ "${LOCAL_CTK}" == 1 ]]; then
7577
# We already installed cuda-bindings, and all CTK components exist locally,
7678
# so just install the test dependencies.
77-
pip install "${CUDA_CORE_ARTIFACTS_DIR}"/*.whl --group "test-cu${TEST_CUDA_MAJOR}${FREE_THREADING}"
79+
uv pip install "${CUDA_CORE_ARTIFACTS_DIR}"/*.whl
7880
else
79-
pip install $(ls "${CUDA_CORE_ARTIFACTS_DIR}"/*.whl)["cu${TEST_CUDA_MAJOR}"] --group "test-cu${TEST_CUDA_MAJOR}${FREE_THREADING}"
81+
uv pip install $(ls "${CUDA_CORE_ARTIFACTS_DIR}"/*.whl)["cu${TEST_CUDA_MAJOR}"]
8082
fi
83+
uv sync --package cuda-core --only-group "test-cu${TEST_CUDA_MAJOR}${FREE_THREADING}" --no-install-project
8184
echo "Running core tests"
8285
${SANITIZER_CMD} pytest -rxXs -v --durations=0 tests/
8386
# Currently our CI always installs the latest bindings (from either major version).

cuda_bindings/pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,11 @@ include-package-data = false
6767
[tool.setuptools.dynamic]
6868
readme = { file = ["DESCRIPTION.rst"], content-type = "text/x-rst" }
6969

70+
[tool.uv.sources]
71+
cuda-pathfinder = { workspace = true }
72+
7073
[tool.cibuildwheel]
74+
build-frontend = "build[uv]"
7175
skip = "*-musllinux_*"
7276
enable = "cpython-freethreading"
7377
build-verbosity = 1

cuda_core/pyproject.toml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
requires = [
77
"setuptools>=80",
88
"setuptools-scm[simple]>=8",
9-
"Cython>=3.2,<3.3"
9+
"Cython>=3.2,<3.3",
10+
# cuda-pathfinder is a transitive build dependency via cuda-bindings (which
11+
# is dynamically added by the build backend). Listing it here as a direct
12+
# requirement lets uv's workspace resolver see it during lock.
13+
"cuda-pathfinder",
1014
]
1115
build-backend = "build_hooks"
1216
backend-path = ["."]
@@ -90,7 +94,15 @@ version_file = "cuda/core/_version.py"
9094
tag_regex = "^cuda-core-(?P<version>v\\d+\\.\\d+\\.\\d+)"
9195
git_describe_command = ["git", "describe", "--dirty", "--tags", "--long", "--match", "cuda-core-v*[0-9]*"]
9296

97+
[tool.uv]
98+
conflicts = [[{ extra = "cu12" }, { extra = "cu13" }]]
99+
100+
[tool.uv.sources]
101+
cuda-bindings = { workspace = true }
102+
cuda-pathfinder = { workspace = true }
103+
93104
[tool.cibuildwheel]
105+
build-frontend = "build[uv]"
94106
skip = "*-musllinux_*"
95107
enable = "cpython-freethreading"
96108
build-verbosity = 1

0 commit comments

Comments
 (0)