Skip to content

cuda.cccl: Fix header discovery under pip build isolation#9293

Open
caugonnet wants to merge 3 commits into
NVIDIA:mainfrom
caugonnet:cuda-cccl-build-isolation-paths
Open

cuda.cccl: Fix header discovery under pip build isolation#9293
caugonnet wants to merge 3 commits into
NVIDIA:mainfrom
caugonnet:cuda-cccl-build-isolation-paths

Conversation

@caugonnet

Copy link
Copy Markdown
Contributor

Summary

cuda.cccl.headers.get_include_paths() falls back to scanning candidate roots when the primary importlib.resources lookup does not contain the probe header. That fallback scanned only sys.path.

Under pip build isolation, pip strips the active venv's site-packages from sys.path even though cuda-cccl is still installed there, so discovery failed with Unable to locate CCCL include directory.. sys.prefix still points at the venv, so the directory is recoverable via site.getsitepackages().

This centralizes the candidate-root scan in a new iter_site_roots() helper that also consults the interpreter site directories (guarding getsitepackages/getusersitepackages for virtualenv setups that lack them, and de-duplicating roots).

This is a generic fix in the shared header-discovery module, so it benefits every consumer of get_include_paths()cuda.compute (_cpp_compile.py, _cccl_interop.py) and cuda.coop._experimental (_nvrtc.py) — not just one package. It was originally found and fixed while packaging cuda.stf, but is intentionally extracted here as a standalone, easy-to-review change.

Changes

  • Add iter_site_roots() scanning sys.path + site.getsitepackages() / site.getusersitepackages(), with defensive guards and de-duplication.
  • Use it in the get_include_paths() fallback instead of a sys.path-only scan.
  • Add regression tests for the build-isolation scenario, root de-duplication, and the missing-getsitepackages fallback.

Test plan

  • pytest python/cuda_cccl/tests/headers/test_include_paths_build_isolation.py (3 passed)
  • pre-commit run --files ... (ruff, ruff-format, mypy, codespell all pass)
  • CI on cuda.cccl / cuda.compute / cuda.coop Python jobs

cuda.cccl.headers.get_include_paths() falls back to scanning candidate
roots when the primary importlib.resources lookup does not contain the
probe header. That fallback scanned only sys.path.

Under pip build isolation, pip strips the active venv's site-packages
from sys.path even though cuda-cccl remains installed there, so the
scan failed with "Unable to locate CCCL include directory." sys.prefix
still points at the venv, so the directory is recoverable via
site.getsitepackages().

Centralize the candidate-root scan in iter_site_roots(), which adds the
interpreter site directories (guarding getsitepackages/getusersitepackages
for virtualenv setups that lack them and de-duplicating roots). This fixes
discovery for every consumer of get_include_paths() (cuda.compute,
cuda.coop._experimental, cuda.stf), not just one package.

Add regression tests covering the build-isolation scenario, root
de-duplication, and the missing-getsitepackages fallback.
@caugonnet caugonnet requested a review from a team as a code owner June 8, 2026 08:58
@github-project-automation github-project-automation Bot moved this to Todo in CCCL Jun 8, 2026
@copy-pr-bot

copy-pr-bot Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Review in CCCL Jun 8, 2026
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b6c1914b-5936-428f-8d27-88bb7e0aa722

📥 Commits

Reviewing files that changed from the base of the PR and between 2e2c39f and 8d07b74.

📒 Files selected for processing (2)
  • python/cuda_cccl/cuda/cccl/headers/include_paths.py
  • python/cuda_cccl/tests/headers/test_include_paths_build_isolation.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • python/cuda_cccl/cuda/cccl/headers/include_paths.py
  • python/cuda_cccl/tests/headers/test_include_paths_build_isolation.py

Note: CodeRabbit is enabled on this repository as a convenience for maintainers
and contributors. Use your best judgment when considering its review comments and
suggestions — a suggested change may be inadequate, unnecessary, or safe to ignore.
Contributors are not expected to address every comment. Human reviews are what
ultimately matter for merging.

Summary

Fix header discovery failures in cuda.cccl.headers.get_include_paths() that occur under pip build isolation. pip strips the active venv's site-packages from sys.path even though cuda-cccl remains installed there; the previous fallback scanned only sys.path and could not find the shipped include directory, raising "Unable to locate CCCL include directory." This PR centralizes candidate-root discovery to include interpreter site directories so discovery succeeds in build-isolation environments.

Changes

python/cuda_cccl/cuda/cccl/headers/include_paths.py

  • Added iter_site_roots(): yields deduplicated, resolved candidate roots from sys.path plus interpreter site directories (site.getsitepackages() and site.getusersitepackages()), with defensive handling when those functions are missing and skipping None entries returned by user-site functions.
  • get_include_paths(): replaced the sys.path-only fallback probe with iteration over iter_site_roots() to locate the cuda.cccl headers under each candidate root; preserves existing probe-file check and error behavior.
  • Lines changed: +36 / -2.

python/cuda_cccl/tests/headers/test_include_paths_build_isolation.py (new)

  • Added regression tests for iter_site_roots() covering:
    1. site-packages discovered via site.getsitepackages() when absent from sys.path (build-isolation scenario).
    2. sys.path entries are still scanned.
    3. deduplication when a root appears in both sys.path and site dirs.
    4. tolerating None from getsitepackages()/getusersitepackages() and defensively handling missing getsitepackages().
  • Lines changed: +95 / -0.

Commit/behavior notes

  • Defensive handling added to skip None entries from getsitepackages()/getusersitepackages() (they can return None when user site is disabled), avoiding TypeError from Path(...).resolve().

Tests

  • Local test run: new tests passed (4 tests in the new file).
  • Pre-commit checks: ruff, ruff-format, mypy, codespell passed.
  • CI pipeline runs for cuda.cccl and dependent projects are pending.

suggestion:

Walkthrough

The PR adds iter_site_roots() to enumerate resolved roots from sys.path and interpreter site-package functions (with defensive fallbacks), and updates get_include_paths() to probe CCCL headers under those roots. Regression tests exercise discovery, deduplication, and missing-site-function scenarios.

Changes

Site-root discovery and integration

Layer / File(s) Summary
Site-root discovery implementation
python/cuda_cccl/cuda/cccl/headers/include_paths.py
iter_site_roots() scans sys.path and site directories via site.getsitepackages() and site.getusersitepackages(), resolves and deduplicates paths, tolerates missing/None returns, and get_include_paths() now probes CCCL headers using these candidate roots.
Build isolation regression tests
python/cuda_cccl/tests/headers/test_include_paths_build_isolation.py
Tests simulate pip build-isolation and assert iter_site_roots() includes interpreter site roots when absent from sys.path, deduplicates identical roots, tolerates None from user-site, and handles a missing site.getsitepackages() without raising.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
python/cuda_cccl/tests/headers/test_include_paths_build_isolation.py (1)

62-78: ⚡ Quick win

suggestion: test validates no crash when getsitepackages is missing but doesn't verify getusersitepackages is still discovered. Add assertion:

     roots = list(iter_site_roots())
 
     assert Path("/some/path").resolve() in roots
+    assert Path("/home/user/.local/lib/python3.x/site-packages").resolve() in roots

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: dade963a-f05c-444e-85da-81017b465846

📥 Commits

Reviewing files that changed from the base of the PR and between a4ca799 and 2e2c39f.

📒 Files selected for processing (2)
  • python/cuda_cccl/cuda/cccl/headers/include_paths.py
  • python/cuda_cccl/tests/headers/test_include_paths_build_isolation.py

Comment thread python/cuda_cccl/cuda/cccl/headers/include_paths.py
Comment on lines +38 to +39
for sp in [*sys.path, *site_dirs]:
root = Path(sp).resolve()

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

important: sys.path can contain non-string entries (zipimporter objects, custom path hooks per PEP 302). Path(sp).resolve() will raise TypeError on these. Filter or wrap in a try-except to skip invalid entries:

     for sp in [*sys.path, *site_dirs]:
+        try:
-        root = Path(sp).resolve()
+            root = Path(sp).resolve()
+        except (TypeError, ValueError):
+            continue
         if root in seen:

getsitepackages()/getusersitepackages() can return None when user site
is disabled (e.g. `python -s` or PYTHONNOUSERSITE), which would make
Path(...).resolve() raise TypeError. Skip None entries and cover the
case in tests.
@caugonnet caugonnet mentioned this pull request Jun 8, 2026
2 tasks
@caugonnet

Copy link
Copy Markdown
Contributor Author

/ok to test 5314adc

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🥳 CI Workflow Results

🟩 Finished in 1h 23m: Pass: 100%/48 | Total: 13h 52m | Max: 52m 40s

See results here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

1 participant