feat(cccl): integrate missing CCCL directories — python/, ci/, .agent/, docs/, test/

Sparse-checkout from NVIDIA/cccl main branch to complete cccl_upstream:

Added:
- python/cuda_cccl/ (226 files) — Python bindings for device-level algorithms
  Critical for muh toolchain: cuda.compute.reduce_into, scan, radix_sort, etc.
  Includes 204 .py files with full test coverage for all 27 algorithms
- ci/ (163 files) — Build/test infrastructure
  build_cub.sh, test_cub.sh, build_and_test_targets.sh, matrix.yaml
  Directly maps to our [INFRA-CI] and [INFRA-BUILD] items
- .agent/skills/ (7 files) — NVIDIA's own agent skills for CCCL
  cccl-style/SKILL.md, cccl-test/SKILL.md, sass-diff/SKILL.md
- docs/ (491 files) — Official CCCL documentation
  CI references, CMake guides, Python compute docs, libcudacxx PTX docs
- test/ (12 files) — Top-level integration tests (cuda_smoke, stdpar)
- Root configs: .clang-format, .clang-tidy, CONTRIBUTING.md, pyproject.toml
- CLAUDE.md symlink → AGENTS.md (NVIDIA's standard)

cccl_upstream now mirrors full NVIDIA/cccl structure:
  Before: 42M (cub + thrust + libcudacxx + cudax + c + examples + benchmarks)
  After:  53M (+python +ci +docs +.agent +test +configs)

This completes the CCCL base needed for:
- [muh-bench] items: ci/util/build_and_test_targets.sh for targeted builds
- [CCCL-verify] items: python/cuda_cccl/tests/ as reference implementations
- [CCCL-test] items: ci/test_cub.sh, ci/test_thrust.sh
- Agent workflow: .agent/skills/ for consistent style and test patterns
This commit is contained in:
muh-bot
2026-08-07 02:34:33 +00:00
parent 3f97dca7ad
commit 2a7ca101d7
908 changed files with 121615 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Remove-Module -Name build_common -ErrorAction SilentlyContinue
Import-Module $PSScriptRoot/build_common.psm1 -ArgumentList @(20, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "cccl-c-parallel"
$LOCAL_CMAKE_OPTIONS = ""
configure_and_build_preset "CCCL C Parallel" $PRESET $LOCAL_CMAKE_OPTIONS
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,28 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Remove-Module -Name build_common -ErrorAction SilentlyContinue
Import-Module $PSScriptRoot/build_common.psm1 -ArgumentList @(20, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "cccl-c-parallel-v2"
$LOCAL_CMAKE_OPTIONS = ""
configure_and_build_preset "CCCL C Parallel" $PRESET $LOCAL_CMAKE_OPTIONS
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,233 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(17, 20)]
[int]$CXX_STANDARD = 17,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
# We need the full path to cl because otherwise cmake will replace CMAKE_CXX_COMPILER with the full path
# and keep CMAKE_CUDA_HOST_COMPILER at "cl" which breaks our cmake script
$script:HOST_COMPILER = (Get-Command "cl").source -replace '\\','/'
$script:PARALLEL_LEVEL = $env:NUMBER_OF_PROCESSORS
Write-Host "=== Docker Container Resource Info ==="
Write-Host "Number of Processors: $script:PARALLEL_LEVEL"
Get-WmiObject Win32_OperatingSystem | ForEach-Object {
Write-Host ("Memory: total={0:N1} GB, free={1:N1} GB" -f ($_.TotalVisibleMemorySize / 1MB), ($_.FreePhysicalMemory / 1MB))
}
Write-Host "======================================"
# Extract the CL version for export to build scripts:
$script:CL_VERSION_STRING = & cl.exe /?
if ($script:CL_VERSION_STRING -match "Version (\d+\.\d+)\.\d+") {
$CL_VERSION = [version]$matches[1]
Write-Host "Detected cl.exe version: $CL_VERSION"
}
$script:GLOBAL_CMAKE_OPTIONS = $CMAKE_OPTIONS
if ($CUDA_ARCH) {
$script:GLOBAL_CMAKE_OPTIONS += ' "-DCMAKE_CUDA_ARCHITECTURES={0}"' -f $CUDA_ARCH
}
# Default to pedantic mode in CI (GitHub Actions)
if ($env:GITHUB_ACTIONS) {
$script:GLOBAL_CMAKE_OPTIONS += ' "-DCCCL_ENABLE_WERROR=ON" "-DCCCL_ENABLE_PRAGMA_SYSTEM_HEADER=OFF"'
} else {
$script:GLOBAL_CMAKE_OPTIONS += ' "-DCCCL_ENABLE_WERROR=OFF" "-DCCCL_ENABLE_PRAGMA_SYSTEM_HEADER=ON"'
}
if (-not $env:CCCL_BUILD_INFIX) {
$env:CCCL_BUILD_INFIX = ""
}
# Presets will be configured in this directory:
$BUILD_DIR = "../build/$env:CCCL_BUILD_INFIX"
If(!(test-path -PathType container "../build")) {
New-Item -ItemType Directory -Path "../build"
}
# The most recent build will always be symlinked to cccl/build/latest
New-Item -ItemType Directory -Path "$BUILD_DIR" -Force
# Convert to an absolute path:
$BUILD_DIR = (Get-Item -Path "$BUILD_DIR").FullName
# Prepare environment for CMake:
$env:CMAKE_BUILD_PARALLEL_LEVEL = $PARALLEL_LEVEL
$env:CTEST_PARALLEL_LEVEL = 1
$env:CUDAHOSTCXX = $script:HOST_COMPILER
$env:CXX = $script:HOST_COMPILER
Write-Host "========================================"
Write-Host "Begin build"
Write-Host "pwd=$pwd"
Write-Host "BUILD_DIR=$BUILD_DIR"
Write-Host "CXX_STANDARD=$CXX_STANDARD"
Write-Host "CXX=$env:CXX"
Write-Host "CUDACXX=$env:CUDACXX"
Write-Host "CUDAHOSTCXX=$env:CUDAHOSTCXX"
Write-Host "TBB_ROOT=$env:TBB_ROOT"
Write-Host "NVCC_VERSION=$NVCC_VERSION"
Write-Host "CMAKE_BUILD_PARALLEL_LEVEL=$env:CMAKE_BUILD_PARALLEL_LEVEL"
Write-Host "CTEST_PARALLEL_LEVEL=$env:CTEST_PARALLEL_LEVEL"
Write-Host "CCCL_BUILD_INFIX=$env:CCCL_BUILD_INFIX"
Write-Host "GLOBAL_CMAKE_OPTIONS=$script:GLOBAL_CMAKE_OPTIONS"
Write-Host "Current commit is:"
Write-Host "$(git log -1 --format=short)"
Write-Host "========================================"
cmake --version
ctest --version
function configure_preset {
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$BUILD_NAME,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$PRESET,
[Parameter(Mandatory = $false)]
[string]$LOCAL_CMAKE_OPTIONS = ""
)
$step = "$BUILD_NAME (configure)"
# CMake must be invoked in the same directory as the presets file:
pushd ".."
# Echo and execute command to stdout:
$configure_command = "cmake --preset $PRESET --log-level VERBOSE"
if ($LOCAL_CMAKE_OPTIONS) {
$configure_command += " $LOCAL_CMAKE_OPTIONS"
}
if ($script:GLOBAL_CMAKE_OPTIONS) {
$configure_command += " $script:GLOBAL_CMAKE_OPTIONS"
}
Write-Host $configure_command
Invoke-Expression $configure_command
$test_result = $LastExitCode
If ($test_result -ne 0) {
throw "$step Failed"
}
popd
Write-Host "$step complete."
}
function build_preset {
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$BUILD_NAME,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$PRESET
)
$step = "$BUILD_NAME (build)"
# CMake must be invoked in the same directory as the presets file:
pushd ".."
sccache -z >$null
cmake --build --preset $PRESET -v
$test_result = $LastExitCode
$preset_dir = "${BUILD_DIR}/${PRESET}"
$sccache_json = "${preset_dir}/sccache_stats.json"
sccache --show-adv-stats
sccache --show-adv-stats --stats-format=json > "${sccache_json}"
echo "$step complete"
If ($test_result -ne 0) {
throw "$step Failed"
}
popd
}
function test_preset {
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$BUILD_NAME,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$PRESET
)
$step = "$BUILD_NAME (test)"
# CTest must be invoked in the same directory as the presets file:
pushd ".."
sccache -z >$null
ctest --preset $PRESET
$test_result = $LastExitCode
sccache --show-adv-stats
echo "$step complete"
If ($test_result -ne 0) {
throw "$step Failed"
}
popd
}
function configure_and_build_preset {
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$BUILD_NAME,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$PRESET,
[Parameter(Mandatory = $false)]
[string]$LOCAL_CMAKE_OPTIONS = ""
)
configure_preset $BUILD_NAME $PRESET $LOCAL_CMAKE_OPTIONS
build_preset $BUILD_NAME $PRESET
}
function Invoke-Checked {
<#
.SYNOPSIS
Runs a script block and throws if the last native command in it exits
non-zero. $ErrorActionPreference = "Stop" does not make native commands
(python/pip/pytest/...) throw, so their $LASTEXITCODE must be checked
explicitly; this wraps that boilerplate into one call.
.EXAMPLE
Invoke-Checked { & $python -m pip install pytest } "pip install failed"
#>
param(
[Parameter(Mandatory, Position = 0)][scriptblock]$ScriptBlock,
[Parameter(Position = 1)][string]$ErrorMessage = "Native command failed"
)
& $ScriptBlock
if ($LASTEXITCODE -ne 0) {
throw "$ErrorMessage (exit code $LASTEXITCODE)"
}
}
Export-ModuleMember -Function configure_preset, build_preset, test_preset, configure_and_build_preset, Invoke-Checked
Export-ModuleMember -Variable BUILD_DIR, CL_VERSION

View File

@@ -0,0 +1,246 @@
function Get-Python {
<#
.SYNOPSIS
Returns the path of the Python interpreter satisfying the supplied
version, installing it via uv if necessary.
.PARAMETER Version
A string in the form 'M.m' (e.g., '3.10', '3.13') or a free-threaded
version such as '3.14t'.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory, Position = 0)]
[ValidatePattern('^\d+\.\d+t?$')]
[string]$Version
)
# Install uv if not present. uv downloads pre-built CPython binaries --
# no compilation, no build dependencies, no pyenv-win required.
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
Write-Host "Installing uv..."
Invoke-RestMethod https://astral.sh/uv/install.ps1 | Invoke-Expression
# uv installs to $HOME\.local\bin on Windows
$uvBin = Join-Path $HOME '.local\bin'
$Env:PATH = $uvBin + ";" + $Env:PATH
}
Write-Host "Creating Python $Version venv via uv..."
$venvDir = Join-Path $HOME '.cccl-venv'
& uv venv --seed --python $Version $venvDir
if ($LASTEXITCODE -ne 0) {
throw [System.InvalidOperationException]::new(
"Failed to create Python $Version venv via uv."
)
}
$exe = Join-Path $venvDir 'Scripts\python.exe'
if (-not (Test-Path $exe)) {
throw [System.InvalidOperationException]::new(
"Could not find python.exe in venv at $exe"
)
}
Write-Host "Python $Version at: $exe"
# Add venv Scripts dir to PATH so bare `python` and `pip` work.
$scriptsDir = Join-Path $venvDir 'Scripts'
$Env:PATH = $scriptsDir + ";" + $Env:PATH
return $exe
}
function Get-RepoRoot {
return (Resolve-Path "$PSScriptRoot/../..")
}
function Get-CudaMajor {
<#
.SYNOPSIS
Gets the CUDA major version for this container instance (e.g. '12' or
'13'). Defaults to '13' if no match can be found.
#>
if ($env:CUDA_PATH) {
$nvcc = Join-Path $env:CUDA_PATH "bin/nvcc.exe"
if (Test-Path $nvcc) {
$out = & $nvcc --version 2>&1
$text = ($out -join "`n")
if ($text -match 'release\s+(\d+)\.') { return $Matches[1] }
}
# Fallback: parse major from CUDA_PATH like ...\v13.0 or ...\CUDA\13
$pathMatch = [regex]::Match($env:CUDA_PATH, 'v?(\d+)(?:\.\d+)?')
if ($pathMatch.Success) { return $pathMatch.Groups[1].Value }
}
return '13'
}
function Get-CudaVersion {
<#
.SYNOPSIS
Gets the CUDA major.minor version for this container instance (e.g.
'12.9' or '13.0'). Defaults to '13.0' if no match can be found.
#>
if ($env:CUDA_PATH) {
$nvcc = Join-Path $env:CUDA_PATH "bin/nvcc.exe"
if (Test-Path $nvcc) {
$out = & $nvcc --version 2>&1
$text = ($out -join "`n")
if ($text -match 'release\s+(\d+\.\d+)') { return $Matches[1] }
}
# Fallback: parse major.minor from CUDA_PATH like ...\v13.0
$pathMatch = [regex]::Match($env:CUDA_PATH, 'v?(\d+\.\d+)')
if ($pathMatch.Success) { return $pathMatch.Groups[1].Value }
}
return '13.0'
}
function Get-CtkTestMode {
<#
.SYNOPSIS
Validates and normalizes a CTK test mode passed as -Mode (forwarded from
the -ctk-mode arg): 'pinned' (default; empty means pinned), 'latest', or
'sysctk'. Throws on any other value (fail loud on a typo'd mode). Returns
the lowercased mode.
#>
param([string]$Mode = "")
if ([string]::IsNullOrEmpty($Mode)) { return "pinned" }
$Mode = $Mode.ToLowerInvariant()
if (-not ($Mode -in @("pinned", "latest", "sysctk"))) {
throw "Invalid ctk mode '$Mode' (expected pinned|latest|sysctk)"
}
return $Mode
}
function Set-CtkPin {
<#
.SYNOPSIS
Configures cuda-toolkit pinning for this lane per the -Mode arg (see
Get-CtkTestMode): 'pinned' (default) pins cuda-toolkit to the container's
CTK major.minor via PIP_CONSTRAINT; 'latest' and 'sysctk' leave it
unpinned ('sysctk' installs no cuda-toolkit wheel at all -- the
system-provided toolkit is used).
#>
param([string]$Mode = "")
if ((Get-CtkTestMode $Mode) -eq "pinned") {
$cudaVersion = Get-CudaVersion
$env:PIP_CONSTRAINT = Join-Path ([System.IO.Path]::GetTempPath()) "ctk-constraint.txt"
"cuda-toolkit==$cudaVersion.*" | Out-File -FilePath $env:PIP_CONSTRAINT -Encoding ascii
} else {
# latest / sysctk: no pin. Clear any inherited constraint so it cannot
# affect the resolve.
Remove-Item Env:\PIP_CONSTRAINT -ErrorAction SilentlyContinue
}
}
function Get-CtkExtraFlavor {
<#
.SYNOPSIS
Returns the pip-extra toolkit "flavor" for the given -Mode: 'sysctk' when
the mode is sysctk (rely on the system-provided CUDA toolkit) or 'cu'
otherwise (pip-installed toolkit). Combine with the CUDA major, e.g.
"minimal-$(Get-CtkExtraFlavor $CtkMode)$cudaMajor".
#>
param([string]$Mode = "")
if ((Get-CtkTestMode $Mode) -eq "sysctk") { return "sysctk" }
return "cu"
}
function Convert-ToUnixPath {
Param([Parameter(Mandatory = $true)][string]$p)
return ($p -replace "\\", "/")
}
function Get-CudaCcclWheel {
<#
.SYNOPSIS
Returns the path of the cuda-cccl wheel artifact to use in the context
of a GitHub Actions CI test script.
#>
Param()
$repoRoot = Get-RepoRoot
if ($env:GITHUB_ACTIONS) {
Push-Location $repoRoot
try {
$wheelArtifactName = (& bash -lc "ci/util/workflow/get_wheel_artifact_name.sh").Trim()
if (-not $wheelArtifactName) { throw 'Failed to resolve wheel artifact name' }
$repoRootPosix = Convert-ToUnixPath $repoRoot
# Ensure output from downloader goes to console, not function return pipeline
$null = (& bash -lc "ci/util/artifacts/download.sh $wheelArtifactName $repoRootPosix" 2>&1 | Out-Host)
if ($LASTEXITCODE -ne 0) { throw "Failed to download wheel artifact '$wheelArtifactName'" }
}
finally { Pop-Location }
}
$wheelhouse = Join-Path $repoRoot 'wheelhouse'
$wheelPath = Get-OnePathMatch -Path $wheelhouse -Pattern '^cuda_cccl-.*\.whl' -File
return $wheelPath
}
function Get-OnePathMatch {
<#
.SYNOPSIS
Returns a single path (file or directory) match for a given pattern,
throwing an error if there were no matches or more than one match.
#>
[CmdletBinding(DefaultParameterSetName = 'FileSet')]
param(
[Parameter(Mandatory)]
[string] $Path,
[Parameter(Mandatory)]
[string] $Pattern,
[Parameter(Mandatory, ParameterSetName = 'FileSet')]
[switch] $File,
[Parameter(Mandatory, ParameterSetName = 'DirSet')]
[switch] $Directory,
[switch] $Recurse
)
if (-not (Test-Path -LiteralPath $Path -PathType Container)) {
throw "Path not found or not a directory: $Path"
}
$gciArgs = @{
LiteralPath = $Path
ErrorAction = 'SilentlyContinue'
}
if ($Recurse) { $gciArgs['Recurse'] = $true }
if ($PSCmdlet.ParameterSetName -eq 'FileSet') {
$gciArgs['File'] = $true
}
else {
$gciArgs['Directory'] = $true
}
$pathMatches = @(
Get-ChildItem @gciArgs |
Where-Object { $_.Name -match $Pattern } |
Select-Object -ExpandProperty FullName
)
if ($pathMatches.Count -ne 1) {
$kind = if ($PSCmdlet.ParameterSetName -eq 'FileSet') { 'file' }
else { 'directory' }
$indented = ($pathMatches | ForEach-Object { " $_" }) -join "`n"
$msg = @"
Expected exactly one $kind name matching regex:
$Pattern
under:
$Path
Found:
$($pathMatches.Count)
$indented
"@
throw $msg
}
return $pathMatches[0]
}
Export-ModuleMember -Function Get-Python, Get-CudaMajor, Set-CtkPin, Get-CtkExtraFlavor, Convert-ToUnixPath, Get-RepoRoot, Get-CudaCcclWheel, Get-OnePathMatch

View File

@@ -0,0 +1,72 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(17, 20)]
[int]$CXX_STANDARD = 17,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = "",
[Parameter(Mandatory = $false)]
[Alias("no-lid")]
[switch]$NO_LID_SWITCH = $false,
[Parameter(Mandatory = $false)]
[Alias("lid0")]
[switch]$LID0_SWITCH = $false,
[Parameter(Mandatory = $false)]
[Alias("lid1")]
[switch]$LID1_SWITCH = $false,
[Parameter(Mandatory = $false)]
[Alias("lid2")]
[switch]$LID2_SWITCH = $false
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Import-Module $PSScriptRoot/build_common.psm1 -ArgumentList @($CXX_STANDARD, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "cub"
$artifactTags = @()
if ($NO_LID_SWITCH) {
$artifactTags += "no_lid"
$PRESET = "cub-nolid"
} elseif ($LID0_SWITCH) {
$artifactTags += "lid_0"
$PRESET = "cub-lid0"
} elseif ($LID1_SWITCH) {
$artifactTags += "lid_1"
$PRESET = "cub-lid1"
} elseif ($LID2_SWITCH) {
$artifactTags += "lid_2"
$PRESET = "cub-lid2"
}
$LOCAL_CMAKE_OPTIONS = "-DCMAKE_CXX_STANDARD=$CXX_STANDARD -DCMAKE_CUDA_STANDARD=$CXX_STANDARD"
if ($CL_VERSION -lt [version]"19.20") {
$LOCAL_CMAKE_OPTIONS = "$LOCAL_CMAKE_OPTIONS -DCCCL_IGNORE_DEPRECATED_COMPILER=ON"
}
configure_and_build_preset "CUB" $PRESET $LOCAL_CMAKE_OPTIONS
if ($env:GITHUB_ACTIONS) {
Write-Host "Packaging test artifacts..."
if ($artifactTags.Count -gt 0) {
& bash "./upload_cub_test_artifacts.sh" @artifactTags
} else {
& bash "./upload_cub_test_artifacts.sh"
}
}
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,422 @@
<#
.SYNOPSIS
Build Python cuda-cccl wheels on Windows.
.DESCRIPTION
This script is the Windows analog to the Linux ../build_cuda_cccl_python.sh
script. It is responsible for building CUDA 12.x and CUDA 13.x wheels that
are then merged together into a singular cuda-cccl wheel.
A single CUDA 12.9 builder image (i.e. Docker devcontainer) is used to
build each distinct Python/MSVC combo. Much like the Linux approach, this
script detects when launched via the outer 12.9 instance, builds a `cu12`
wheel, then dispatches a inner Docker instance (Docker-out-of-Docker) to
execute this script with `-OnlyCudaMajor 13 -SkipUpload` parameters, which
yields a `cu13` build.
Upon completion of the `cu13` build, the outer 12.9 container merges both
`cu12` and `cu13` wheels into a single cuda-cccl wheel, and uploads that
via the standard CCCL CI artifact upload mechanisms.
.PARAMETER PyVersion
**Required.** The Python version to use for building the wheel, expressed
as `<major>.<minor>` (e.g. `3.11`) or a free-threaded version such as
`3.14t`.
.PARAMETER OnlyCudaMajor
Optional. Restricts the build to a single CUDA major version (`12` or `13`).
When set, only that version is built and the *merge* step is skipped.
.PARAMETER Cuda13Image
Optional. The Docker image name used for a nested build of the CUDA 13
wheel when the outer container defaults to CUDA 12.9. The default value
matches the RAPIDS dev-container image that contains the required
toolchain: `rapidsai/devcontainers:26.06-cuda13.0-cl14.44-windows2022`.
.PARAMETER SkipUpload
When set, prevents the final wheel(s) from being uploaded as a GitHub
Actions artifact even when the script detects it is running inside an
Action.
.EXAMPLE
# Build a single cuda-cccl wheel for Python 3.13 (consisting of both CUDA
# 12 and 13 versions), and, if in CI, upload the resulting wheel as an
# artifact.
.\build_cuda_cccl_python.ps1 -PyVersion 3.11
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true)]
[Alias("py-version")]
[ValidatePattern("^\d+\.\d+t?$")]
[string]$PyVersion,
[Parameter(Mandatory = $false)]
[ValidateSet('12', '13')]
[string]$OnlyCudaMajor,
[Parameter(Mandatory = $false)]
[string]$Cuda13Image = "rapidsai/devcontainers:26.06-cuda13.0-cl14.44-windows2022",
[Parameter(Mandatory = $false)]
[switch]$SkipUpload
)
$ErrorActionPreference = "Stop"
# Import shared helpers.
Import-Module "$PSScriptRoot/build_common.psm1"
Import-Module "$PSScriptRoot/build_common_python.psm1" -Force
# Resolve repo root from this script's location.
$RepoRoot = Resolve-Path "$PSScriptRoot/../.."
Write-Host "Repo root: $RepoRoot"
# Get the full path to the python.exe for the version we need.
Write-Host "Looking for Python version $PyVersion..."
$PythonExe = Get-Python -Version $PyVersion
Write-Host "Using Python: $PythonExe"
& $PythonExe -m pip --version
# Ensure MSVC is available.
$clPath = (Get-Command cl).Source
if (-not $clPath) {
throw "cl.exe not found in PATH. Run from a Developer PowerShell prompt."
}
Write-Host "Found cl.exe at: $clPath"
function Resolve-CudaPathForMajor {
Param(
[Parameter(Mandatory = $true)]
[ValidateSet('12', '13')]
[string]$Major
)
$candidates = @()
Get-ChildItem Env: |
Where-Object { $_.Name -match "^CUDA_PATH_V${Major}_(\d+)$" } |
ForEach-Object {
$minor = [int]([regex]::Match(
$_.Name,
"^CUDA_PATH_V${Major}_(\d+)$"
).Groups[1].Value)
$candidates += [PSCustomObject]@{
Minor = $minor;
Path = $_.Value
}
}
if ($candidates.Count -gt 0) {
return ($candidates | Sort-Object -Property Minor -Descending |
Select-Object -First 1).Path
}
if ($env:CUDA_PATH) {
$maybe = $env:CUDA_PATH
$nvcc = Join-Path $maybe 'bin/nvcc.exe'
if (Test-Path $nvcc) {
$out = & $nvcc --version 2>&1
$text = ($out -join "`n")
if ($text -match 'release\s+(\d+)\.') {
if ($Matches[1] -eq $Major) {
return $maybe
}
}
}
}
return $null
}
# If $OnlyCudaMajor is present, it means we're being launched from a
# nested Docker container build (12.x launched a 13.x build via DooD).
if ($OnlyCudaMajor) {
$CudaMajorsToBuild = @($OnlyCudaMajor)
}
else {
$CudaMajorsToBuild = @('12', '13')
}
$DoMerge = -not [bool]$OnlyCudaMajor
# Base pip/CMake options
$pipBaseConfigArgs = @(
'-C', 'cmake.define.CMAKE_C_COMPILER=cl.exe',
'-C', 'cmake.define.CMAKE_CXX_COMPILER=cl.exe'
)
$env:CMAKE_GENERATOR = "Ninja"
# Ensure wheelhouse directories exist.
$Wheelhouse = Join-Path $RepoRoot "wheelhouse"
New-Item -ItemType Directory -Path $Wheelhouse -Force | Out-Null
${null} = New-Item -ItemType Directory -Path (Join-Path $RepoRoot 'wheelhouse_cu12') -Force
${null} = New-Item -ItemType Directory -Path (Join-Path $RepoRoot 'wheelhouse_cu13') -Force
function Invoke-Cuda13NestedBuild {
<#
.SYNOPSIS
Run the nested Docker build for CUDA 13 when we are already inside a
CUDA 12 builder image.
.DESCRIPTION
This routine launches a Docker devcontainer CUDA 13 build for the given
Python version by way of Docker-out-of-Docker (DooD) facilities.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory)] [string] $Cuda13Image,
[Parameter(Mandatory)] [string] $PyVersion,
[ValidateNotNullOrEmpty()] [string] $HostWorkspace = $env:HOST_WORKSPACE,
[ValidateNotNullOrEmpty()] [string] $ContainerWorkspace = $env:CONTAINER_WORKSPACE
)
# Validate required environment variables.
if (-not $HostWorkspace) {
throw "HOST_WORKSPACE env var is not set; required for DooD " +
"nested docker mounts on Windows."
}
if (-not $ContainerWorkspace) {
throw "CONTAINER_WORKSPACE env var is not set; required for " +
"DooD nested docker mounts on Windows."
}
# Validate Docker CLI availability.
if (-not (Get-Command docker -ErrorAction SilentlyContinue)) {
throw "docker CLI not found in the devcontainer image (required for DooD)."
}
Write-Host "Checking DooD connectivity..."
$dockerVersionOutput = & docker version 2>&1
$dockerExitCode = $LASTEXITCODE
$dockerVersionOutput | Out-Host
if ($dockerExitCode -ne 0) {
throw "DooD connectivity check failed (exit code $dockerExitCode). See Docker output above."
}
Write-Host "DooD appears to be working, continuing..."
# Detect outer-container resources so we can set sensible limits.
$os = Get-WmiObject -Class Win32_OperatingSystem
$totalGB = [math]::Floor($os.TotalVisibleMemorySize / 1MB) # KB -> GB
$procCount = [Environment]::ProcessorCount
# Leave a little head-room so the outer container doesn't starve
$memLimitGB = [math]::Max(2, [int]([math]::Floor($totalGB * 0.9)))
$cpuCount = [math]::Max(2, $procCount)
Write-Host "Launching nested Docker for CUDA 13 build using image: $Cuda13Image"
$targetFile = Join-Path $ContainerWorkspace 'ci\windows\build_cuda_cccl_python.ps1'
$dockerArgs = @(
'run', '--rm', '-i',
'--cpu-count', "$cpuCount",
'--memory', "${memLimitGB}g",
'--workdir', $ContainerWorkspace,
'--mount', "type=bind,source=$HostWorkspace,target=$ContainerWorkspace",
'--env', "py_version=$PyVersion",
'--env', "GITHUB_ACTIONS=$($env:GITHUB_ACTIONS)",
'--env', "GITHUB_RUN_ID=$($env:GITHUB_RUN_ID)",
'--env', "JOB_ID=$($env:JOB_ID)",
$Cuda13Image,
'PowerShell.exe', '-NoLogo', '-NoProfile', '-ExecutionPolicy', 'Bypass',
'-File', $targetFile,
'-py-version', $PyVersion,
'-OnlyCudaMajor', '13',
'-SkipUpload'
)
Write-Host ("About to invoke: docker " + ($dockerArgs -join ' '))
Invoke-Checked { & docker @dockerArgs } 'Nested CUDA 13 wheel build failed'
}
function Build-CudaCcclWheel {
<#
.SYNOPSIS
Perform the regular wheel build for a given CUDA major version.
.DESCRIPTION
This routine is used to build both CUDA 12 and CUDA 13 based wheels,
and is called from normal "outer" Docker containers, as well as the
"inner" nested ones.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory)] [ValidateSet('12', '13')] [string] $Major,
[Parameter(Mandatory)] [string] $RepoRoot,
[Parameter(Mandatory)] [string] $PythonExe,
[Parameter(Mandatory)] [string[]] $PipBaseConfigArgs
)
# Resolve CUDA toolkit location for the requested major version.
$CudaPathForMajor = Resolve-CudaPathForMajor -Major $Major
if (-not $CudaPathForMajor) {
throw "CUDA Toolkit $Major not found. Ensure CUDA_PATH_V${Major}_* " +
"is set or matching toolkit is installed."
}
$NvccForMajor = Join-Path $CudaPathForMajor 'bin/nvcc.exe'
if (-not (Test-Path $NvccForMajor)) {
throw "nvcc not found at $NvccForMajor"
}
# Convert Windows paths to Unix-style for CMake
$NvccUnix = Convert-ToUnixPath $NvccForMajor
$CudaUnix = Convert-ToUnixPath $CudaPathForMajor
# Build the pip configuration arguments that inject the CUDA toolchain.
$pipConfigArgs = $PipBaseConfigArgs + @(
'-C', "cmake.define.CMAKE_CUDA_COMPILER=$NvccUnix",
'-C', "cmake.define.CUDAToolkit_ROOT=$CudaUnix"
)
$extra = "cu$Major"
# Use separate output directories for 12 vs 13.
$outDir = Join-Path $RepoRoot "wheelhouse_$extra"
Write-Host "Building cuda-cccl wheel for CUDA $Major at $CudaPathForMajor..."
# Run pip wheel to build the wheel.
$pythonArgs = @(
'-m', 'pip', 'wheel',
'-w', $outDir,
".[${extra}]",
'-v'
) + $pipConfigArgs
Write-Host ("python " + ($pythonArgs -join ' '))
Invoke-Checked { & $PythonExe @pythonArgs } "Wheel build failed for CUDA $Major"
# Normalise the wheel filename (append .cu12/.cu13) and prune duplicates.
$builtWheel = Get-OnePathMatch -Path $outDir `
-Pattern '^cuda_cccl-.*\.whl' `
-File
if (-not $builtWheel) {
throw "Failed to locate built wheel in $outDir for CUDA $Major"
}
$builtName = [System.IO.Path]::GetFileName($builtWheel)
if ($builtName -notmatch ".cu$Major\.whl$") {
$newName = ([System.IO.Path]::GetFileNameWithoutExtension($builtName)) `
+ ".cu$Major.whl"
Write-Host "Renaming wheel to: $newName"
Rename-Item -Path $builtWheel -NewName $newName -Force
}
# Remove any stray wheels that lack the .cuXX suffix.
Get-ChildItem -Path $outDir -Filter 'cuda_cccl-*.whl' |
Where-Object { $_.Name -notmatch "\.cu$Major\.whl$" } |
ForEach-Object {
Write-Host "Removing duplicate wheel: $($_.FullName)"
Remove-Item -Force $_.FullName
}
}
# Main build entry code.
Push-Location (Join-Path $RepoRoot 'python/cuda_cccl')
try {
foreach ($major in $CudaMajorsToBuild) {
# Nested Docker build for CUDA 13 for when we are currently inside a
# CUDA 12 image.
if (-not $OnlyCudaMajor -and $major -eq '13' -and $Cuda13Image) {
Invoke-Cuda13NestedBuild `
-Cuda13Image $Cuda13Image `
-PyVersion $PyVersion
continue
}
# Perform a normal build for the current major version. This may
# be invoked from either an "outer" or inner "nested" image.
Build-CudaCcclWheel `
-Major $major `
-RepoRoot $RepoRoot `
-PythonExe $PythonExe `
-PipBaseConfigArgs $pipBaseConfigArgs
}
}
finally {
Pop-Location
}
# Merge the two major-version wheels (if both were built). This will fail if
# either wheel can't be found. This only runs on the outer (non-nested)
# container image.
if ($DoMerge) {
$Cu12Wheel = Get-OnePathMatch `
-Path (Join-Path $RepoRoot 'wheelhouse_cu12') `
-Pattern '^cuda_cccl-.*\.cu12\.whl' `
-File
$Cu13Wheel = Get-OnePathMatch `
-Path (Join-Path $RepoRoot 'wheelhouse_cu13') `
-Pattern '^cuda_cccl-.*\.cu13\.whl' `
-File
Write-Host "Found CUDA 12 wheel: $Cu12Wheel"
Write-Host "Found CUDA 13 wheel: $Cu13Wheel"
Write-Host 'Merging CUDA wheels...'
Invoke-Checked { & $PythonExe -m pip install wheel | Write-Host } 'Failed to install wheel for merging'
$WheelhouseMerged = Join-Path $RepoRoot 'wheelhouse_merged'
${null} = New-Item -ItemType Directory -Path $WheelhouseMerged -Force
$mergePy = Join-Path $RepoRoot 'python/cuda_cccl/merge_cuda_wheels.py'
Invoke-Checked { & $PythonExe $mergePy $Cu12Wheel $Cu13Wheel --output-dir $WheelhouseMerged } 'Merging wheels failed'
# Clean up the per-major directories and move the merged wheel into the
# final location.
Get-ChildItem $Wheelhouse -Filter '*.whl' |
ForEach-Object {
Remove-Item -Force $_.FullName
}
$MergedWheel = Get-OnePathMatch `
-Path $WheelhouseMerged `
-Pattern '^cuda_cccl-.*\.whl' `
-File
Move-Item -Force $MergedWheel $Wheelhouse
Remove-Item $WheelhouseMerged -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item (Join-Path $RepoRoot 'wheelhouse_cu12') `
-Recurse -Force -ErrorAction SilentlyContinue
Remove-Item (Join-Path $RepoRoot 'wheelhouse_cu13') `
-Recurse -Force -ErrorAction SilentlyContinue
Write-Host 'Final wheels in wheelhouse:'
Get-ChildItem $Wheelhouse -Filter '*.whl' |
ForEach-Object {
Write-Host " - $($_.Name)"
}
}
# If it turns out we need delvewheel, we'd handle it here, after the merging
# of wheels. The two DLLs that seem like they might be problematic are
# msvc140p.dll, and dbghelp.dll. The former comes from llvmlite, upon which
# we depend. Dbghelp.dll ships in C:\Windows\System32, but that will often
# be a much older version compared to the one used by Visual Studio. We only
# use one symbol from Dbghelp.dll: UnDecorateSymbolName, which is used by
# nvrtc. If we encounter weird issues with c.parallel jit compilation and
# nvrtc in the wild on Windows, an out-of-date Dbghelp.dll could possibly be
# the culprit.
#
# For now, though, it doesn't appear to be necessary.
# Optionally upload the wheel artifact.
if ($env:GITHUB_ACTIONS -and -not $SkipUpload) {
Push-Location $RepoRoot
try {
Write-Host 'GITHUB_ACTIONS detected; uploading wheel artifact'
$wheelArtifactName = (& bash -lc "ci/util/workflow/get_wheel_artifact_name.sh").Trim()
if (-not $wheelArtifactName) {
throw 'Failed to resolve wheel artifact name'
}
Write-Host "Wheel artifact name: $wheelArtifactName"
$uploadCmd = "ci/util/artifacts/upload.sh $wheelArtifactName 'wheelhouse/.*'"
Invoke-Checked { & bash -lc $uploadCmd } 'Wheel artifact upload failed'
}
finally {
Pop-Location
}
}

View File

@@ -0,0 +1,31 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(20)]
[int]$CXX_STANDARD = 20,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Remove-Module -Name build_common -ErrorAction SilentlyContinue
Import-Module $PSScriptRoot/build_common.psm1 -ArgumentList @($CXX_STANDARD, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "cudax"
$LOCAL_CMAKE_OPTIONS = "-DCMAKE_CXX_STANDARD=$CXX_STANDARD -DCMAKE_CUDA_STANDARD=$CXX_STANDARD"
configure_and_build_preset "CUDA Experimental" $PRESET $LOCAL_CMAKE_OPTIONS
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,48 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(17, 20)]
[int]$CXX_STANDARD = 17,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Import-Module $PSScriptRoot/build_common.psm1 -ArgumentList @($CXX_STANDARD, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "libcudacxx"
$LOCAL_CMAKE_OPTIONS = "-DCMAKE_CXX_STANDARD=$CXX_STANDARD -DCMAKE_CUDA_STANDARD=$CXX_STANDARD"
$uploadTestArtifacts = $false
if ($env:GITHUB_ACTIONS) {
& bash "./util/workflow/has_consumers.sh"
$uploadTestArtifacts = $LASTEXITCODE -eq 0
if ($uploadTestArtifacts) {
$env:LIT_OPTS = "$env:LIT_OPTS -Dtest_executable_mode=build".Trim()
}
}
configure_and_build_preset "libcudacxx" $PRESET $LOCAL_CMAKE_OPTIONS
if ($uploadTestArtifacts) {
Write-Host "Packaging test artifacts..."
Invoke-Checked {
& bash "./upload_libcudacxx_test_artifacts.sh"
} "Packaging test artifacts failed"
}
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,37 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(17, 20)]
[int]$CXX_STANDARD = 17,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Import-Module $PSScriptRoot/build_common.psm1 -ArgumentList @($CXX_STANDARD, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "thrust"
$LOCAL_CMAKE_OPTIONS = "-DCMAKE_CXX_STANDARD=$CXX_STANDARD -DCMAKE_CUDA_STANDARD=$CXX_STANDARD"
configure_and_build_preset "Thrust" $PRESET $LOCAL_CMAKE_OPTIONS
if ($env:GITHUB_ACTIONS) {
Write-Host "Packaging test artifacts..."
& bash "./upload_thrust_test_artifacts.sh"
}
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,41 @@
Param(
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$PassthroughArgs
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
if ($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
if ($null -eq $PassthroughArgs) {
$PassthroughArgs = @()
}
Import-Module "$PSScriptRoot/build_common.psm1"
$ciDirWindows = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$repoDirWindows = (Resolve-Path (Join-Path $ciDirWindows "..")).Path
$ciDir = $ciDirWindows -replace "\\", "/"
$repoDir = $repoDirWindows -replace "\\", "/"
$utilScript = "$ciDir/util/git_bisect.sh"
$argString = if ($PassthroughArgs.Count -gt 0) { " " + ($PassthroughArgs -join " ") } else { "" }
$bashCommand = "cd $repoDir; $utilScript$argString"
Write-Host $bashCommand -ForegroundColor Blue
& bash -lc $bashCommand
$exitCode = $LASTEXITCODE
if ($CURRENT_PATH -ne "ci") {
popd
}
if ($exitCode -ne 0) {
exit $exitCode
}

View File

@@ -0,0 +1,41 @@
Param(
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$PassthroughArgs
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
if ($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
if ($null -eq $PassthroughArgs) {
$PassthroughArgs = @()
}
Import-Module "$PSScriptRoot/build_common.psm1"
$ciDirWindows = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$repoDirWindows = (Resolve-Path (Join-Path $ciDirWindows "..")).Path
$ciDir = $ciDirWindows -replace "\\", "/"
$repoDir = $repoDirWindows -replace "\\", "/"
$utilScript = "$ciDir/util/build_and_test_targets.sh"
$argString = if ($PassthroughArgs.Count -gt 0) { " " + ($PassthroughArgs -join " ") } else { "" }
$bashCommand = "cd $repoDir; $utilScript$argString"
Write-Host $bashCommand -ForegroundColor Blue
& bash -lc $bashCommand
$exitCode = $LASTEXITCODE
if ($CURRENT_PATH -ne "ci") {
popd
}
if ($exitCode -ne 0) {
exit $exitCode
}

View File

@@ -0,0 +1,41 @@
Param(
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$PassthroughArgs
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
if ($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
if ($null -eq $PassthroughArgs) {
$PassthroughArgs = @()
}
Import-Module "$PSScriptRoot/build_common.psm1"
$ciDirWindows = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$repoDirWindows = (Resolve-Path (Join-Path $ciDirWindows "..")).Path
$ciDir = $ciDirWindows -replace "\\", "/"
$repoDir = $repoDirWindows -replace "\\", "/"
$utilScript = "$ciDir/util/git_bisect.sh"
$argString = if ($PassthroughArgs.Count -gt 0) { " " + ($PassthroughArgs -join " ") } else { "" }
$bashCommand = "cd $repoDir; $utilScript$argString"
Write-Host $bashCommand -ForegroundColor Blue
& bash -lc $bashCommand
$exitCode = $LASTEXITCODE
if ($CURRENT_PATH -ne "ci") {
popd
}
if ($exitCode -ne 0) {
exit $exitCode
}

View File

@@ -0,0 +1,41 @@
Param(
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$PassthroughArgs
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
if ($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
if ($null -eq $PassthroughArgs) {
$PassthroughArgs = @()
}
Import-Module "$PSScriptRoot/build_common.psm1"
$ciDirWindows = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$repoDirWindows = (Resolve-Path (Join-Path $ciDirWindows "..")).Path
$ciDir = $ciDirWindows -replace "\\", "/"
$repoDir = $repoDirWindows -replace "\\", "/"
$utilScript = "$ciDir/util/build_and_test_targets.sh"
$argString = if ($PassthroughArgs.Count -gt 0) { " " + ($PassthroughArgs -join " ") } else { "" }
$bashCommand = "cd $repoDir; $utilScript$argString"
Write-Host $bashCommand -ForegroundColor Blue
& bash -lc $bashCommand
$exitCode = $LASTEXITCODE
if ($CURRENT_PATH -ne "ci") {
popd
}
if ($exitCode -ne 0) {
exit $exitCode
}

View File

@@ -0,0 +1,31 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
# Build first
$buildCmd = "$PSScriptRoot/build_cccl_c_parallel.ps1 -arch '$CUDA_ARCH' -cmake-options '$CMAKE_OPTIONS'"
Write-Host "Running: $buildCmd"
Invoke-Expression $buildCmd
Remove-Module -Name build_common -ErrorAction SilentlyContinue
Import-Module -Name "$PSScriptRoot/build_common.psm1" -ArgumentList @(20, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "cccl-c-parallel"
test_preset "CCCL C Parallel" "$PRESET"
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,30 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Remove-Module -Name build_common -ErrorAction SilentlyContinue
Import-Module -Name "$PSScriptRoot/build_common.psm1" -ArgumentList @(20, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "cccl-c-parallel-v2"
$LOCAL_CMAKE_OPTIONS = ""
configure_and_build_preset "CCCL C Parallel v2 (HostJIT)" $PRESET $LOCAL_CMAKE_OPTIONS
test_preset "CCCL C Parallel v2 (HostJIT)" "$PRESET"
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,73 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(17, 20)]
[int]$CXX_STANDARD = 17,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("no-lid")]
[switch]$NO_LID_SWITCH = $false,
[Parameter(Mandatory = $false)]
[Alias("lid0")]
[switch]$LID0_SWITCH = $false,
[Parameter(Mandatory = $false)]
[Alias("lid1")]
[switch]$LID1_SWITCH = $false,
[Parameter(Mandatory = $false)]
[Alias("lid2")]
[switch]$LID2_SWITCH = $false,
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Import-Module -Name "$PSScriptRoot/build_common.psm1" -ArgumentList @($CXX_STANDARD, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "cub"
$artifactTag = ""
$variantArg = ""
if ($NO_LID_SWITCH) {
$artifactTag = "no_lid"
$PRESET = "cub-nolid"
$variantArg = "-no-lid"
} elseif ($LID0_SWITCH) {
$artifactTag = "lid_0"
$PRESET = "cub-lid0"
$variantArg = "-lid0"
} elseif ($LID1_SWITCH) {
$artifactTag = "lid_1"
$PRESET = "cub-lid1"
$variantArg = "-lid1"
} elseif ($LID2_SWITCH) {
$artifactTag = "lid_2"
$PRESET = "cub-lid2"
$variantArg = "-lid2"
}
if ($env:GITHUB_ACTIONS -and $artifactTag) {
$producerId = (& bash "./util/workflow/get_producer_id.sh").Trim()
$artifactName = "z_cub-test-artifacts-$env:DEVCONTAINER_NAME-$producerId-$artifactTag"
Write-Host "Unpacking artifact '$artifactName'"
& bash "./util/artifacts/download_packed.sh" "$artifactName" "../"
} else {
$buildCmd = "$PSScriptRoot/build_cub.ps1 -std $CXX_STANDARD -arch '$CUDA_ARCH' -cmake-options '$CMAKE_OPTIONS' $variantArg"
Write-Host "Running: $buildCmd"
Invoke-Expression $buildCmd
}
test_preset "CUB ($PRESET)" "$PRESET"
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,50 @@
Param(
[Parameter(Mandatory = $true)]
[Alias("py-version")]
[ValidatePattern("^\d+\.\d+t?$")]
[string]$PyVersion,
[Alias("ctk-mode")]
[string]$CtkMode = ""
)
$ErrorActionPreference = "Stop"
# Import shared helpers
Import-Module "$PSScriptRoot/build_common.psm1"
Import-Module "$PSScriptRoot/build_common_python.psm1"
$python = Get-Python -Version $PyVersion
$cudaMajor = Get-CudaMajor
$ctkFlavor = Get-CtkExtraFlavor $CtkMode
# Pin cuda-toolkit to the container's CTK minor (-ctk-mode latest
# opts out). See build_common_python.psm1.
Set-CtkPin $CtkMode
$repoRoot = Get-RepoRoot
${wheelPath} = Get-CudaCcclWheel
# pytest-benchmark is for the host-benchmark smoke test below.
Invoke-Checked { & $python -m pip install -U pip pytest pytest-xdist pytest-benchmark } "Failed to install pytest / pytest-xdist / pytest-benchmark"
# CuPy is required by the cuda.compute examples and is not part of the test extras
Invoke-Checked { & $python -m pip install "${wheelPath}[test-$ctkFlavor$cudaMajor]" "cupy-cuda${cudaMajor}x" } "Failed to install cuda_cccl test extra / cupy"
Push-Location (Join-Path $repoRoot "python/cuda_cccl/tests")
try {
Invoke-Checked { & $python -m pytest -n 6 test_examples.py } "examples tests failed"
}
finally { Pop-Location }
# Smoke-test the host-overhead benchmark harness: run every benchmark case
# exactly once (pass/fail only, no timing) so harness rot fails CI here instead
# of silently surviving until someone runs the perf suite. --benchmark-disable
# makes pytest-benchmark invoke each benchmarked callable a single time. This
# lane already installs cupy + numba (for the examples), which the benchmark
# suite also needs, so only pytest-benchmark is added above.
Push-Location (Join-Path $repoRoot "python/cuda_cccl/benchmarks/compute/host")
try {
Invoke-Checked { & $python -m pytest -v --benchmark-disable . } "host benchmark smoke test failed"
}
finally { Pop-Location }

View File

@@ -0,0 +1,36 @@
Param(
[Parameter(Mandatory = $true)]
[Alias("py-version")]
[ValidatePattern("^\d+\.\d+t?$")]
[string]$PyVersion,
[Alias("ctk-mode")]
[string]$CtkMode = ""
)
$ErrorActionPreference = "Stop"
# Import shared helpers
Import-Module "$PSScriptRoot/build_common.psm1"
Import-Module "$PSScriptRoot/build_common_python.psm1"
$python = Get-Python -Version $PyVersion
$cudaMajor = Get-CudaMajor
$ctkFlavor = Get-CtkExtraFlavor $CtkMode
# Pin cuda-toolkit to the container's CTK minor (-ctk-mode latest
# opts out). See build_common_python.psm1.
Set-CtkPin $CtkMode
$repoRoot = Get-RepoRoot
${wheelPath} = Get-CudaCcclWheel
Invoke-Checked { & $python -m pip install -U pip pytest pytest-xdist } "Failed to install pytest / pytest-xdist"
Invoke-Checked { & $python -m pip install "${wheelPath}[test-$ctkFlavor$cudaMajor]" } "Failed to install cuda_cccl test extra"
Push-Location (Join-Path $repoRoot "python/cuda_cccl/tests")
try {
Invoke-Checked { & $python -m pytest -n auto -v headers/ } "headers tests failed"
}
finally { Pop-Location }

View File

@@ -0,0 +1,79 @@
Param(
[Parameter(Mandatory = $true)]
[Alias("py-version")]
[ValidatePattern("^\d+\.\d+t?$")]
[string]$PyVersion,
[Alias("ctk-mode")]
[string]$CtkMode = ""
)
$ErrorActionPreference = "Stop"
# Import shared helpers
Import-Module "$PSScriptRoot/build_common.psm1"
Import-Module "$PSScriptRoot/build_common_python.psm1"
$python = Get-Python -Version $PyVersion
$cudaMajor = Get-CudaMajor
$ctkFlavor = Get-CtkExtraFlavor $CtkMode
# Pin cuda-toolkit to the container's CTK minor (-ctk-mode latest
# opts out). See build_common_python.psm1.
Set-CtkPin $CtkMode
$repoRoot = Get-RepoRoot
$wheelPath = Get-CudaCcclWheel
# Install cuda_cccl with the minimal CUDA extra. This intentionally avoids the
# full cu* extras because those pull in numba/numba-cuda.
Invoke-Checked { & $python -m pip install -U pip pytest pytest-xdist } "Failed to install pytest / pytest-xdist"
Invoke-Checked { & $python -m pip install "$wheelPath[minimal-$ctkFlavor$cudaMajor]" } "Failed to install cuda_cccl minimal extra"
Push-Location (Join-Path $repoRoot "python/cuda_cccl/tests")
try {
Invoke-Checked { & $python -m pytest -n 6 -v compute/test_no_numba.py } "test_no_numba.py failed"
if ($PyVersion -eq "3.14t") {
# Select only tests that support the minimal extra so pytest does not
# collect tests that import numba-cuda and re-enable the GIL. These tests
# provide their own worker threads, so keep pytest itself in a single
# process. The serialization node-ids are module-skipped on the v2
# backend today and will start running there automatically once v2 gains
# serialization support.
Invoke-Checked {
& $python -m pytest -n 0 -v `
compute/test_free_threading_stress.py `
compute/test_multi_cc_serialization.py::test_aot_build_result_load_failure_is_shared_and_retryable `
compute/test_multi_cc_serialization.py::test_aot_serialization_waits_for_canonical_first_load
} "free-threading stress / serialization tests failed"
# Broad thread-safety sweep (pytest-run-parallel): re-run the numba-free
# functional suite with each test executed concurrently across threads
# (barrier-synchronized start), stressing the process-wide build cache,
# single-flight coordination, and the Cython bindings from many threads at
# once. Complements test_free_threading_stress.py above, which targets
# specific shared-object scenarios by hand. -n 0 so the threads share one
# interpreter.
#
# --parallel-threads=2 matches CuPy's free-threading CI (the closest GPU
# precedent); a small fixed count bounds GPU-memory pressure from
# concurrent kernels and stays reproducible across runners, unlike =auto
# (the runner's logical-core count).
#
# pytest-run-parallel is only used by this sweep, so install it on the
# 3.14t path rather than for every minimal (e.g. non-free-threaded 3.14)
# run.
Invoke-Checked { & $python -m pip install pytest-run-parallel } "Failed to install pytest-run-parallel"
# Fail fast if the interpreter is not actually GIL-free (wrong build /
# PYTHON_GIL=1): pytest-run-parallel does NOT catch a GIL that is enabled
# from the start -- it would run threads GIL-serialized and pass
# vacuously. (A GIL *re-enabled mid-run* by a non-free-threaded import IS
# caught by the plugin, which is why we do not pass --ignore-gil-enabled.)
Invoke-Checked { & $python -c "import sys; assert not sys._is_gil_enabled(), 'GIL is enabled; parallel sweep has no signal'" } "interpreter is not GIL-free; parallel sweep has no signal"
Invoke-Checked { & $python -m pytest -n 0 -v --parallel-threads=2 compute/test_no_numba.py } "parallel-threads sweep failed"
}
}
finally { Pop-Location }

View File

@@ -0,0 +1,37 @@
Param(
[Parameter(Mandatory = $true)]
[Alias("py-version")]
[ValidatePattern("^\d+\.\d+t?$")]
[string]$PyVersion,
[Alias("ctk-mode")]
[string]$CtkMode = ""
)
$ErrorActionPreference = "Stop"
# Import shared helpers
Import-Module "$PSScriptRoot/build_common.psm1"
Import-Module "$PSScriptRoot/build_common_python.psm1"
$python = Get-Python -Version $PyVersion
$cudaMajor = Get-CudaMajor
$ctkFlavor = Get-CtkExtraFlavor $CtkMode
# Pin cuda-toolkit to the container's CTK minor (-ctk-mode latest
# opts out). See build_common_python.psm1.
Set-CtkPin $CtkMode
$repoRoot = Get-RepoRoot
$wheelPath = Get-CudaCcclWheel
Invoke-Checked { & $python -m pip install -U pip pytest pytest-xdist } "Failed to install pytest / pytest-xdist"
Invoke-Checked { & $python -m pip install "$wheelPath[test-$ctkFlavor$cudaMajor]" } "Failed to install cuda_cccl test extra"
Push-Location (Join-Path $repoRoot "python/cuda_cccl/tests")
try {
Invoke-Checked { & $python -m pytest -n 6 -v compute/ -m "not large and not free_threading" } "compute tests (not large) failed"
Invoke-Checked { & $python -m pytest -n 0 -v compute/ -m "large and not free_threading" } "compute tests (large) failed"
}
finally { Pop-Location }

View File

@@ -0,0 +1,35 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(20)]
[int]$CXX_STANDARD = 20,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
# Build first
$buildCmd = "$PSScriptRoot/build_cudax.ps1 -std $CXX_STANDARD -arch '$CUDA_ARCH' -cmake-options '$CMAKE_OPTIONS'"
Write-Host "Running: $buildCmd"
Invoke-Expression $buildCmd
Import-Module -Name "$PSScriptRoot/build_common.psm1" -ArgumentList @($CXX_STANDARD, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "cudax"
test_preset "CUDA Experimental" "$PRESET"
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,53 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(17, 20)]
[int]$CXX_STANDARD = 17,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Import-Module -Name "$PSScriptRoot/build_common.psm1" -ArgumentList @($CXX_STANDARD, $CUDA_ARCH, $CMAKE_OPTIONS)
if ($env:GITHUB_ACTIONS) {
$producerId = & bash "./util/workflow/get_producer_id.sh"
if ($LASTEXITCODE -ne 0) {
throw "Finding the producer job failed (exit code $LASTEXITCODE)"
}
$producerId = "$producerId".Trim()
$artifactName = "z_libcudacxx-test-artifacts-$env:DEVCONTAINER_NAME-$producerId"
Write-Host "Unpacking artifact '$artifactName'"
Invoke-Checked {
& bash "./util/artifacts/download_packed.sh" "$artifactName" "../"
} "Downloading test artifacts failed"
} else {
$buildCmd = "$PSScriptRoot/build_libcudacxx.ps1 -std $CXX_STANDARD -arch '$CUDA_ARCH' -cmake-options '$CMAKE_OPTIONS'"
Write-Host "Running: $buildCmd"
Invoke-Expression $buildCmd
}
if ($env:GITHUB_ACTIONS) {
test_preset "libcudacxx (CTest)" "libcudacxx-ctest"
$env:LIT_OPTS = "$env:LIT_OPTS -Dtest_executable_mode=replay".Trim()
test_preset "libcudacxx (lit replay)" "libcudacxx-lit"
} else {
test_preset "libcudacxx (CTest)" "libcudacxx-ctest-cpp${CXX_STANDARD}"
test_preset "libcudacxx (lit)" "libcudacxx-lit-cpp${CXX_STANDARD}"
}
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,37 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(17, 20)]
[int]$CXX_STANDARD = 17,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
Import-Module $PSScriptRoot/build_common.psm1 -ArgumentList @($CXX_STANDARD, $CUDA_ARCH, $CMAKE_OPTIONS)
$PRESET = "packaging"
$LOCAL_CMAKE_OPTIONS = ""
if ($env:GITHUB_SHA) {
$LOCAL_CMAKE_OPTIONS = '"-DCCCL_EXAMPLE_CPM_TAG={0}"' -f $env:GITHUB_SHA
}
configure_preset "Packaging" $PRESET $LOCAL_CMAKE_OPTIONS
test_preset "Packaging" $PRESET
If($CURRENT_PATH -ne "ci") {
popd
}

View File

@@ -0,0 +1,62 @@
Param(
[Parameter(Mandatory = $false)]
[Alias("std")]
[ValidateNotNullOrEmpty()]
[ValidateSet(17, 20)]
[int]$CXX_STANDARD = 17,
[Parameter(Mandatory = $false)]
[Alias("arch")]
[string]$CUDA_ARCH = "",
[Parameter(Mandatory = $false)]
[Alias("cpu-only")]
[switch]$CPU_ONLY = $false,
[Parameter(Mandatory = $false)]
[Alias("gpu-only")]
[switch]$GPU_ONLY = $false,
[Parameter(Mandatory = $false)]
[Alias("cmake-options")]
[string]$CMAKE_OPTIONS = ""
)
$ErrorActionPreference = "Stop"
$CURRENT_PATH = Split-Path $pwd -leaf
If($CURRENT_PATH -ne "ci") {
Write-Host "Moving to ci folder"
pushd "$PSScriptRoot/.."
}
if ($CPU_ONLY) {
$artifactTag = "test_cpu"
$presets = @("thrust-cpu")
} elseif ($GPU_ONLY) {
$artifactTag = "test_gpu"
$presets = @("thrust-gpu")
} else {
if ($env:GITHUB_ACTIONS) {
throw "Error: test_thrust.ps1 requires -cpu-only or -gpu-only in CI"
}
$artifactTag = ""
$presets = @("thrust-cpu", "thrust-gpu")
}
if ($env:GITHUB_ACTIONS -and $artifactTag) {
$producerId = (& bash "./util/workflow/get_producer_id.sh").Trim()
$artifactName = "z_thrust-test-artifacts-$env:DEVCONTAINER_NAME-$producerId-$artifactTag"
Write-Host "Unpacking artifact '$artifactName'"
& bash "./util/artifacts/download_packed.sh" "$artifactName" "../"
} else {
$cmd = "$PSScriptRoot/build_thrust.ps1 -std $CXX_STANDARD -arch '$CUDA_ARCH' -cmake-options '$CMAKE_OPTIONS'"
Write-Host "Running: $cmd"
Invoke-Expression $cmd
}
Import-Module -Name "$PSScriptRoot/build_common.psm1" -ArgumentList @($CXX_STANDARD, $CUDA_ARCH, $CMAKE_OPTIONS)
foreach ($preset in $presets) {
test_preset "Thrust ($preset)" $preset
}
If($CURRENT_PATH -ne "ci") {
popd
}