Skip to content

cuda.core: directory-aware C++ build rule and drop the dead top-level copy from the merged wheel - #2799

Open
Andy-Jost wants to merge 3 commits into
NVIDIA:mainfrom
Andy-Jost:ajost/rt-phase1-build-and-wheel-fix
Open

cuda.core: directory-aware C++ build rule and drop the dead top-level copy from the merged wheel#2799
Andy-Jost wants to merge 3 commits into
NVIDIA:mainfrom
Andy-Jost:ajost/rt-phase1-build-and-wheel-fix

Conversation

@Andy-Jost

@Andy-Jost Andy-Jost commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Description

Groundwork for splitting cuda.core._resource_handles into a directory of C++ sources, plus a fix to the merged-wheel layout. No behavior changes.

Build backend. build_hooks.py now compiles every .cpp under cuda/core/_cpp/<stem>/ into the extension for _<stem>.pyx, keeping the legacy single file _cpp/<stem>.cpp as the fallback (tensor_map is unchanged). With no such directory in the tree yet, the sources it produces are exactly today's, so this part is inert on its own. The cuda.core._cpp package-data globs become recursive so headers in nested directories ship, and .gitignore stops hiding .cpp files under cuda/core/_cpp/ so new sources are visible to git.

Merged wheel. ci/tools/merge_cuda_core_wheels.py stops keeping a third, top-level copy of _resource_handles (extension, .pxd, .pyi) and the top-level _cpp/ and _include/ header directories in the merged cu12+cu13 wheel. cuda/core/__init__.py rewrites the package's __path__, __file__, and __spec__ to the versioned subpackage before any import reaches them, so that copy was never used at runtime (about 308 KB uncompressed in the 1.2.0 wheel); the comment defending it referred to an import removed in #1463. The C++ headers advertised in 1.1.1 (#2236) are still shipped under cu12/ and cu13/ and are reached through the package's import path, which resolves to the active one. After the removal the script asserts that the merged wheel's top level holds exactly __init__.py, _version.py, and the versioned trees of its input wheels.

Tests. Three small tests of the source rule in test_build_hooks.py (directory form, legacy single file, no C++, empty directory).

Checklist

  • New or existing tests cover these changes.
  • The documentation is up to date with these changes (no user-facing behavior changes; nothing to document).

🤖 Generated with Claude Code

@github-actions github-actions Bot added CI/CD CI/CD infrastructure cuda.core Everything related to the cuda.core module labels Sep 10, 2026
@Andy-Jost Andy-Jost self-assigned this Sep 10, 2026
@Andy-Jost Andy-Jost added this to the cuda.core 1.3.0 milestone Sep 10, 2026
… copy from the merged wheel

build_hooks.py maps a Cython module to its C++ by name. It now also accepts
a directory: every .cpp under cuda/core/_cpp/<stem>/ compiles into the one
extension for _<stem>.pyx, with the legacy single file _cpp/<stem>.cpp kept
as the fallback (tensor_map is unchanged). With no such directory in the
tree yet, the sources are exactly today's, so this part is inert on its own.
The cuda.core._cpp package-data globs become recursive so headers in nested
directories ship, and .gitignore stops ignoring .cpp files under
cuda/core/_cpp/ so new sources are visible to git.

ci/tools/merge_cuda_core_wheels.py stops retaining a third, top-level copy
of _resource_handles and the top-level _cpp/ and _include/ headers in the
merged cu12+cu13 wheel. cuda/core/__init__.py rewrites __path__ to the
versioned subpackage before any import reaches them, so that copy (about
308 KB uncompressed in the 1.2.0 wheel) was never imported; the comment
defending it referred to an import removed in NVIDIA#1463. A step in
build-wheel.yml now asserts that the merged wheel's top level holds only
__init__.py, _version.py and the two versioned trees.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Andy-Jost
Andy-Jost force-pushed the ajost/rt-phase1-build-and-wheel-fix branch from 2ae8604 to cb5784e Compare September 10, 2026 02:35
@github-actions

Copy link
Copy Markdown
Contributor

@Andy-Jost Andy-Jost added the P0 High priority - Must do! label Sep 10, 2026
@Andy-Jost
Andy-Jost requested review from leofang, mdboom and rwgk and removed request for mdboom September 10, 2026 14:37
Comment thread .github/workflows/build-wheel.yml Outdated
Comment on lines +699 to +718
- name: Check merged cuda.core wheel layout
if: ${{ env.BUILD_CORE == 'true' }}
run: |
# cuda/core/__init__.py rewrites __path__ to the active cuXX/ tree, so
# only the entry points and the two versioned trees belong at the top
# level of cuda/core/; anything else is a dead copy.
python - "${{ env.CUDA_CORE_ARTIFACTS_DIR }}"/cuda_core*.whl <<'EOF'
import os
import sys
import zipfile

prefix = "cuda/core/"
members = zipfile.ZipFile(sys.argv[1]).namelist()
names = {n[len(prefix) :].split("/")[0] for n in members if n.startswith(prefix)}
names.discard("")
expected = {"__init__.py", "_version.py"}
expected |= {f"cu{os.environ[v]}" for v in ("BUILD_CUDA_MAJOR", "BUILD_PREV_CUDA_MAJOR")}
assert names == expected, f"unexpected top-level entries under cuda/core/: {sorted(names ^ expected)}"
print("merged wheel top level:", sorted(names))
EOF

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.

Since we already have a Python script to merge cuda-core wheels, maybe it's simplest to just add this check there? (This on its own isn't terrible, but writ large we have too much logic in our GHA config.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 28b73d2: the check now lives in merge_cuda_core_wheels.py, which derives the kept cuNN directories from its input wheels and raises if anything else remains under cuda/core/. The workflow step is gone, so build-wheel.yml is back to what main has.

Comment thread cuda_core/build_hooks.py Outdated
cuda/core/_cpp/<stem>/, or the single legacy file cuda/core/_cpp/<stem>.cpp.
Example: _tensor_map.pyx compiles _cpp/tensor_map.cpp."""
sources = [f"cuda/core/{mod_name}.pyx"]
cpp_stem = os.path.join("cuda", "core", "_cpp", mod_name.lstrip("_"))

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.

os.path is soft deprecated. We should use pathlib.Path in new code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 28b73d2: _extension_sources uses pathlib.Path.

…e pathlib

Review follow-up. The top-level layout assertion moves from build-wheel.yml
into ci/tools/merge_cuda_core_wheels.py, which now derives the kept cuNN
directories from its input wheels and raises if anything else remains under
cuda/core/ after the removal. _extension_sources uses pathlib.
@Andy-Jost
Andy-Jost requested a review from mdboom September 11, 2026 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI/CD CI/CD infrastructure cuda.core Everything related to the cuda.core module P0 High priority - Must do!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants