Skip to content

fix: resolve CCCL headers from the CUDA 13 include path - #496

Open
janickm wants to merge 2 commits into
bazel-contrib:mainfrom
janickm:dev/janickm/cccl-headers-include-path
Open

fix: resolve CCCL headers from the CUDA 13 include path#496
janickm wants to merge 2 commits into
bazel-contrib:mainfrom
janickm:dev/janickm/cccl-headers-include-path

Conversation

@janickm

@janickm janickm commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Fixes #489.

Problem

cccl_headers is generated from the generic <component>_headers in BUILD.dctk_comp, which always sets includes to <component>/include. CUDA 13 moved the CCCL headers one level deeper, into include/cccl/, so that path resolves <cccl/thrust/...> but not <thrust/...>:

fatal error: thrust/complex.h: No such file or directory

The per-library targets in BUILD.cccl already handle the move, but cccl_headers is not generated from that fragment. It also reaches cuda_headers, which aggregates every component's headers target, so both fail the same way.

Fix

Per your suggestion in the issue: BUILD.cccl now declares cccl_headers itself, using the same if_cuda_toolkit_version_ge as the neighbouring thrust/cub/libcudacxx targets, and the generic target in BUILD.dctk_comp is suppressed for that component. The two fragments are concatenated into one BUILD file, so only one of them may declare it — the suppression is required, not cosmetic. It follows the shape of _component_owns_cuda_repo_alias from #488.

Keeping the version knowledge in the fragment that already has it avoids teaching the generic template about CCCL's layout.

One wrinkle worth flagging: the new target is confined to deliverable repos via if_local_cuda_toolkit. A local toolkit expands BUILD.cccl into @cuda itself, where %{component_name} is cuda and BUILD.lctk_cuda already declares cuda_headers — without the guard, toolchain_root fails with a duplicate cuda_headers.

Verification

Non-cccl component repos generate byte-identical BUILD files, and exactly one cccl_headers is declared:

Toolkit cccl_headers resolves to
CUDA 13.0.2 cccl/include/cccl
CUDA 12.8.1 cccl/include

The new integration case builds a kernel including <thrust/complex.h> through both cccl_headers and the cuda_headers aggregate. It declares a single CUDA version, so CUDA_REDIST_VERSION_OVERRIDE sweeps it across the versions in the matrix and covers both layouts. I confirmed it fails on unpatched main and passes here.

The targets pass nvcc's own -std=c++17, not an -Xcompiler host flag: thrust refuses to compile below C++17, some CI hosts default lower, and a host-only flag leaves nvcc compiling the CCCL headers as C++14 (which fails on MSVC with "inline specifier allowed on function declarations only").

Full matrix green on a branch in my fork — all 10 Test Example Build jobs including the three Windows ones, plus Test Utilities and pre-commit. Also ran bazel test //tests/... (82 pass), the examples including //rdc:all, and test_all.sh.

Separate, not fixed here

While testing this across two declared versions I hit a different instance of the max-version problem: every component repo loads @cuda//:defs.bzl, whose ctk_version is stamped from the maximum declared version, so if_cuda_toolkit_version_ge returns the wrong answer inside a non-maximum component repo. On current main, @cuda_cccl_..._12_8_1//:thrust already resolves cccl/include/cccl when 13.x is also declared.

That is pre-existing and affects thrust, cub and libcudacxx equally, and it cannot be fixed in the fragments, since if_cuda_toolkit_version_ge is a load-time function reading a stamped constant. It needs each component repo to know its own version, which the version attribute already carries. I kept it out of this PR and will file it separately unless you would rather it were folded in.

`cccl_headers` comes from the generic `<component>_headers` in BUILD.dctk_comp, which
always sets `includes` to `<component>/include`. CUDA 13 moved the CCCL headers one level
deeper, into `include/cccl/`, so that path resolves `<cccl/thrust/...>` but not
`<thrust/...>`:

  fatal error: thrust/complex.h: No such file or directory

The per-library targets in BUILD.cccl already handle the move, but `cccl_headers` is not
generated from that fragment. It also reaches `cuda_headers`, which aggregates every
component's headers target, so both fail the same way.

BUILD.cccl now declares `cccl_headers` itself, with the same
`if_cuda_toolkit_version_ge` the neighbouring targets use, and BUILD.dctk_comp's generic
target is suppressed for that component: the two fragments are concatenated into one BUILD
file, so only one of them may declare it. Keeping the version knowledge in the fragment
that already has it avoids teaching the generic template about CCCL's layout.

The new target is confined to deliverable repos. A local toolkit expands BUILD.cccl into
`@cuda` itself, where the component name is "cuda" and BUILD.lctk_cuda already declares
`cuda_headers`.

Fixes bazel-contrib#489
Builds a kernel including `<thrust/complex.h>` against `cccl_headers` and against the
`cuda_headers` aggregate that wraps it. Without the preceding commit both fail on a CUDA 13
toolkit with "thrust/complex.h: No such file or directory".

One declared version, so CUDA_REDIST_VERSION_OVERRIDE sweeps the case across the CUDA
versions in the matrix and covers both header layouts. Declaring two versions here would
instead exercise the multi-version toolkit, where `if_cuda_toolkit_version_ge` reads the
maximum declared version rather than the selected one -- a separate problem, and not what
this is testing.

The targets pass nvcc's own `-std=c++17`, rather than an `-Xcompiler` host flag, because
thrust refuses to compile below it and some CI hosts default to an older standard. It has
to be nvcc's flag so that it governs the device dialect too; a host-only flag leaves nvcc
compiling the CCCL headers as C++14.
@cloudhan

Copy link
Copy Markdown
Collaborator

I will delay this after #501

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.

cccl_headers uses the pre-CUDA-13 include path, so <thrust/...> does not resolve on CUDA 13

2 participants