Skip to content

[FEA] Centralize CUDA environment variable handling and prioritize CUDA_PATH over CUDA_HOME#1519

Closed
rparolin wants to merge 14 commits intoNVIDIA:mainfrom
rparolin:rparolin/env_var_improvements
Closed

[FEA] Centralize CUDA environment variable handling and prioritize CUDA_PATH over CUDA_HOME#1519
rparolin wants to merge 14 commits intoNVIDIA:mainfrom
rparolin:rparolin/env_var_improvements

Conversation

@rparolin
Copy link
Copy Markdown
Collaborator

@rparolin rparolin commented Jan 22, 2026

This PR introduces centralized CUDA environment variable handling across cuda-python packages with improved consistency and better handling of conflicting environment variable configurations.

The previous implicit priority of CUDA_HOME over CUDA_PATH was inconsistent with:

  • NVIDIA's own CUDA Toolkit installers (which set CUDA_PATH by default)
  • CMake's FindCUDAToolkit module (prioritizes CUDA_PATH)

Key Changes

Breaking Change - Environment Variable Priority

Changed the search order priority from CUDA_HOME > CUDA_PATH to CUDA_PATH > CUDA_HOME to align with NVIDIA tooling standards and industry conventions. This affects all packages that query CUDA Toolkit locations (cuda.pathfinder, cuda.core, cuda.bindings).

New Module: cuda.pathfinder._utils.env_var_constants

  • Defines canonical search order CUDA_ENV_VARS_ORDERED = ("CUDA_PATH", "CUDA_HOME")
  • Zero-dependency module safe for bootstrap scenarios
  • Single source of truth for environment variable ordering

Enhanced cuda.pathfinder._utils.env_vars

  • Improved get_cuda_home_or_path() with robust path comparison using os.path.samefile()
  • Handles symlinks, junctions, trailing slashes, and case-insensitivity correctly
  • Warns users when multiple environment variables are set but point to different locations
  • Result is cached for process lifetime for consistent behavior
  • Preserves empty strings when explicitly set

Closes #1433.

@copy-pr-bot
Copy link
Copy Markdown
Contributor

copy-pr-bot bot commented Jan 22, 2026

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@rparolin
Copy link
Copy Markdown
Collaborator Author

/ok to test

@rparolin rparolin marked this pull request as ready for review January 22, 2026 20:12
@copy-pr-bot
Copy link
Copy Markdown
Contributor

copy-pr-bot bot commented Jan 22, 2026

Auto-sync is disabled for ready for review pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@rparolin
Copy link
Copy Markdown
Collaborator Author

/ok to test

@rparolin
Copy link
Copy Markdown
Collaborator Author

/ok to test

@rparolin
Copy link
Copy Markdown
Collaborator Author

/ok to test

@rparolin rparolin closed this Jan 22, 2026
@rparolin rparolin reopened this Jan 22, 2026
@rparolin
Copy link
Copy Markdown
Collaborator Author

/ok to test

@github-actions
Copy link
Copy Markdown

@rparolin
Copy link
Copy Markdown
Collaborator Author

/ok to test

"setuptools_scm[simple]>=8",
"cython>=3.2,<3.3",
"pyclibrary>=0.1.7",
"cuda-pathfinder",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It's already on line 34 below. Having it there seemed to work reliably in all situations?

@rwgk
Copy link
Copy Markdown
Collaborator

rwgk commented Jan 27, 2026

This still uses the old pattern (seems like an easy fix):

  • @functools.cache
    def _get_cuda_paths() -> list[str]:
    CUDA_PATH = os.environ.get("CUDA_PATH", os.environ.get("CUDA_HOME", None))
    if not CUDA_PATH:
    raise RuntimeError("Environment variable CUDA_PATH or CUDA_HOME is not set")
    CUDA_PATH = CUDA_PATH.split(os.pathsep)
    print("CUDA paths:", CUDA_PATH)
    return CUDA_PATH

This

  • # prepare include
    cuda_path = os.environ.get("CUDA_PATH", os.environ.get("CUDA_HOME"))
    if cuda_path is None:
    print("this demo requires a valid CUDA_PATH environment variable set", file=sys.stderr)
    sys.exit(0)
    cuda_include = os.path.join(cuda_path, "include")
    assert os.path.isdir(cuda_include)
    include_path = [cuda_include]
    cccl_include = os.path.join(cuda_include, "cccl")
    if os.path.isdir(cccl_include):
    include_path.insert(0, cccl_include)

should probably be updated to use pathfinder, similar to what I did here a few days ago:

I could take care of that in a separate, small PR. Should I?

from cuda.pathfinder._utils.env_vars import get_cuda_home_or_path

CUDA_HOME = get_cuda_home_or_path()
except ImportError:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think this fallback code is needed. cuda-bindings depends critically on cuda-pathfinder.

Comment on lines +81 to +82
Path to CUDA Toolkit, or None if neither variable is set. Empty strings are
preserved and returned as-is if explicitly set in the environment.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hm, that seems like it could lead to confusing situations. Could we make it so that empty strings are equivalent to to undefined?

@rparolin rparolin added this to the cuda.pathfinder 1.4.0 milestone Feb 18, 2026
@rparolin rparolin closed this Mar 3, 2026
@rwgk rwgk removed this from the cuda.pathfinder 1.4.0 milestone Mar 3, 2026
github-actions bot pushed a commit that referenced this pull request Mar 4, 2026
Removed preview folders for the following PRs:
- PR #1519
- PR #1685
rwgk added a commit to rwgk/cuda-python that referenced this pull request Mar 20, 2026
…d onto main.

Adds cuda.pathfinder._utils.env_var_constants with canonical search order,
enhances get_cuda_home_or_path() with robust path comparison and caching,
and updates documentation across all packages to reflect the new priority.

Co-authored-by: Rob Parolin <rparolin@nvidia.com>
Made-with: Cursor
cpcloud pushed a commit that referenced this pull request Mar 24, 2026
…PATH` over `CUDA_HOME` (#1801)

* Squash-merge of PR #1519 (rparolin/env_var_improvements) rebased onto main.

Adds cuda.pathfinder._utils.env_var_constants with canonical search order,
enhances get_cuda_home_or_path() with robust path comparison and caching,
and updates documentation across all packages to reflect the new priority.

Co-authored-by: Rob Parolin <rparolin@nvidia.com>
Made-with: Cursor

* replace _get_cuda_paths() with _get_cuda_path() using pathfinder

Drop os.pathsep splitting of CUDA_PATH/CUDA_HOME in both build_hooks.py files.
Both functions now delegate to get_cuda_home_or_path() from cuda.pathfinder,
returning a single path.

See #1801 (comment)

Made-with: Cursor

* treat empty env vars as undefined in get_cuda_home_or_path()

See #1801 (comment) for the rationale

Made-with: Cursor

* fix(pathfinder): clear get_cuda_home_or_path cache in test fixtures

Made-with: Cursor

* fix(core): update test_build_hooks for _get_cuda_path rename, drop multi-path test

Made-with: Cursor

* refactor(core): use get_cuda_home_or_path() in test conftest skipif

Made-with: Cursor

* refactor(core): use get_cuda_home_or_path() in examples

Made-with: Cursor

* rename get_cuda_home_or_path -> get_cuda_path_or_home

Safe: currently an internal-only API (not yet public).
Made-with: Cursor

* make get_cuda_path_or_home a public API, privatize CUDA_ENV_VARS_ORDERED

Export get_cuda_path_or_home from cuda.pathfinder.__init__. External
consumers now import from cuda.pathfinder directly. Rename constant
to _CUDA_PATH_ENV_VARS_ORDERED and remove all public references to it.

Made-with: Cursor

* docs(pathfinder): manually edit 1.5.0 release notes, fix RST formatting (Cursor)

Made-with: Cursor

* Add 1.5.0, 1.4.3, 1.4.2 in cuda_pathfinder/docs/nv-versions.json

* docs: clarify that CUDA_PATH/CUDA_HOME priority comes from pathfinder

Pathfinder 1.5.0 release notes no longer claim cross-package consistency
(that depends on future bindings/core releases). cuda_bindings env var
docs now defer to pathfinder release notes for migration guidance.

Made-with: Cursor

* fix oversights that slipped in when manually editing cuda_pathfinder/docs/nv-versions.json before

Discovered via independent review from GPT-5.4 Extra High

* fix(pathfinder): change found_via from "CUDA_HOME" to "CUDA_PATH"

Aligns the provenance label with the new CUDA_PATH-first priority.
The label signals the highest-priority env var name, not necessarily
which variable supplied the value.

Discovered via independent review from GPT-5.4 Extra High

Made-with: Cursor

* fix(build): don't import cuda.pathfinder in build_hooks.py

The build backends run in an isolated venv created by pyproject-build.
Although cuda-pathfinder is listed in build-system.requires and gets
installed, the cuda namespace package from backend-path=["."] shadows
the installed cuda-pathfinder, making `from cuda.pathfinder import ...`
fail with ModuleNotFoundError. This broke all CI wheel builds.

Revert _get_cuda_path() to use os.environ.get() directly with
CUDA_PATH > CUDA_HOME priority, and remove cuda-pathfinder from
build-system.requires (it was not there on main; our PR added it).

Made-with: Cursor

* Update pathfinder descriptor catalogs for cusparseLt release 0.9.0

* Slightly enhance comment in _get_cuda_path()

* Add PR #1806 to 1.5.0-notes.rst

* Systematically rename find_in_cuda_home → find_in_cuda_path

* add _cuda_headers_available() guard to conftest files

Add a helper that skips tests when no CUDA path is set, but
asserts that the include/ subdirectory exists when one is — surfacing
stale or incomplete toolkit roots at collection time instead of
letting them fail later in compilation.

Applied in both the root conftest.py and cuda_core/tests/conftest.py.

Made-with: Cursor

---------

Co-authored-by: Rob Parolin <rparolin@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEA]: Improve handling of CUDA_HOME and CUDA_PATH in build across projects

3 participants