Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cuda12.6/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: cuda12.6
Title: CUDA 12.6 Toolkit Libraries
Version: 1.0.5
Version: 1.0.6
Authors@R:
person("Daniel", "Falbel", , "daniel@posit.co", role = c("aut", "cre"))
Description: Provides CUDA 12.6 native libraries (runtime, cuBLAS, cuDNN, cuFFT,
Expand Down
2 changes: 1 addition & 1 deletion cuda12.6/configure
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ if ! command -v unzip > /dev/null 2>&1; then
exit 1
fi

PLATFORM=$(detect_platform)
PLATFORM=$(detect_platform) || exit 1
TMPDIR=$(mktemp -d)
trap "rm -rf '$TMPDIR'" EXIT

Expand Down
2 changes: 1 addition & 1 deletion cuda12.6/inst/cuda-version.env
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CUDA_MINOR="12.6"
CUDA_MAJOR="12"
TOOLKIT_VERSION="12.6.3"
PKG_VERSION="1.0.5"
PKG_VERSION="1.0.6"
CUDNN_VERSION="9.5.0.50"
NCCL_VERSION="2.23.4"
NVSHMEM_VERSION="3.1.7"
2 changes: 1 addition & 1 deletion cuda12.8/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: cuda12.8
Title: CUDA 12.8 Toolkit Libraries
Version: 1.0.6
Version: 1.0.7
Authors@R:
person("Daniel", "Falbel", , "daniel@posit.co", role = c("aut", "cre"))
Description: Provides CUDA 12.8 native libraries (runtime, cuBLAS, cuDNN, cuFFT,
Expand Down
2 changes: 1 addition & 1 deletion cuda12.8/configure
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ if ! command -v unzip > /dev/null 2>&1; then
exit 1
fi

PLATFORM=$(detect_platform)
PLATFORM=$(detect_platform) || exit 1
TMPDIR=$(mktemp -d)
trap "rm -rf '$TMPDIR'" EXIT

Expand Down
2 changes: 1 addition & 1 deletion cuda12.8/inst/cuda-version.env
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CUDA_MINOR="12.8"
CUDA_MAJOR="12"
TOOLKIT_VERSION="12.8.1"
PKG_VERSION="1.0.6"
PKG_VERSION="1.0.7"
CUDNN_VERSION="9.8.0.87"
NCCL_VERSION="2.29.7"
NVSHMEM_VERSION="3.4.5"
15 changes: 15 additions & 0 deletions cuda13.0/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Package: cuda13.0
Title: CUDA 13.0 Toolkit Libraries
Version: 1.0.0
Authors@R:
person("Daniel", "Falbel", , "daniel@posit.co", role = c("aut", "cre"))
Description: Provides CUDA 13.0 native libraries (runtime, cuBLAS, cuDNN, cuFFT,
cuSOLVER, cuSPARSE, CUPTI, NVRTC, NvJitLink, NCCL, NVSHMEM, and NVCC) by
downloading pre-built binaries from PyPI at install time. Intended to be used
as a dependency by packages that require CUDA 13.0.
License: MIT + file LICENSE
URL: https://github.com/mlverse/cudatoolkit
BugReports: https://github.com/mlverse/cudatoolkit/issues
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
2 changes: 2 additions & 0 deletions cuda13.0/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
YEAR: 2026
COPYRIGHT HOLDER: Daniel Falbel
7 changes: 7 additions & 0 deletions cuda13.0/NAMESPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Generated by roxygen2: do not edit by hand

export(all_lib_paths)
export(bin_path)
export(cuda_path)
export(include_path)
export(lib_path)
70 changes: 70 additions & 0 deletions cuda13.0/R/paths.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Read component -> wheel_subdir mapping from installed components.tsv
.read_components <- function() {
tsv <- system.file("components.tsv", package = packageName(), mustWork = TRUE)
df <- read.delim(tsv, stringsAsFactors = FALSE)
setNames(df$wheel_subdir, df$component)
}

# Lazily cached component map
.component_subdir_env <- new.env(parent = emptyenv())

.component_subdir <- function(component) {
if (is.null(.component_subdir_env$map)) {
.component_subdir_env$map <- .read_components()
}
subdir <- .component_subdir_env$map[[component]]
if (is.null(subdir)) {
stop(sprintf("Unknown component: '%s'. Available: %s",
component, paste(names(.component_subdir_env$map), collapse = ", ")))
}
subdir
}

#' Path to a CUDA component installation
#'
#' @param component Component name (e.g., "runtime", "cublas", "cudnn").
#' @return A character string with the path to the installed component files.
#' @export
cuda_path <- function(component) {
system.file(file.path("nvidia", .component_subdir(component)),
package = packageName(), mustWork = TRUE)
}

#' Path to the shared library directory
#'
#' All CUDA component libraries are installed into a single shared directory.
#'
#' @return A character string with the path to the lib directory.
#' @export
lib_path <- function() {
system.file("lib", package = packageName(), mustWork = TRUE)
}

#' Path to a CUDA component's headers
#'
#' @param component Component name (e.g., "runtime", "cublas", "cudnn").
#' @return A character string with the path to the include directory.
#' @export
include_path <- function(component) {
file.path(cuda_path(component), "include")
}

#' Path to a CUDA component's binaries
#'
#' @param component Component name (e.g., "nvcc").
#' @return A character string with the path to the bin directory.
#' @export
bin_path <- function(component) {
file.path(cuda_path(component), "bin")
}

#' Path to the shared library directory
#'
#' Alias for \code{\link{lib_path}}. All CUDA component libraries are in a
#' single directory, so this simply returns that path.
#'
#' @return A character vector of length one with the library path.
#' @export
all_lib_paths <- function() {
lib_path()
}
222 changes: 222 additions & 0 deletions cuda13.0/configure
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
#!/bin/sh

# Downloads CUDA toolkit components from PyPI during package installation.
# Component names and pinned versions are read from inst/components.tsv
# (generated at build time by CI).
#
# Environment variables:
# CUDA_COMPONENTS Comma-separated list of components to install.
# Default: all components. Example: "runtime,cublas,cudnn"
# Use @version to override a component's pinned version:
# "runtime,cublas,cudnn@9.10.0.56"
# CUDA_PLATFORM Override platform detection (linux-x64, linux-arm64, windows-x64).

detect_platform() {
if [ -n "$CUDA_PLATFORM" ]; then
case "$CUDA_PLATFORM" in
linux-x64) echo "x86_64" ;;
linux-arm64) echo "aarch64" ;;
windows-x64) echo "win_amd64" ;;
*)
echo "ERROR: Unknown CUDA_PLATFORM: $CUDA_PLATFORM" >&2
exit 1
;;
esac
return
fi

os=$(uname -s)
arch=$(uname -m)

case "$os" in
Linux)
case "$arch" in
x86_64) echo "x86_64" ;;
aarch64) echo "aarch64" ;;
*)
echo "ERROR: Unsupported Linux architecture: $arch" >&2
exit 1
;;
esac
;;
MINGW*|MSYS*|CYGWIN*|Windows_NT)
echo "win_amd64"
;;
*)
echo "ERROR: Unsupported OS: $os" >&2
exit 1
;;
esac
}

is_windows() {
case "$PLATFORM" in
win_amd64) return 0 ;;
*) return 1 ;;
esac
}

download_file() {
url="$1"; dest="$2"
if command -v curl > /dev/null 2>&1; then
curl -sL -o "$dest" "$url"
elif command -v wget > /dev/null 2>&1; then
wget -q -O "$dest" "$url"
else
echo "ERROR: Neither curl nor wget found." >&2
exit 1
fi
}

if ! command -v unzip > /dev/null 2>&1; then
echo "ERROR: unzip not found. Please install unzip." >&2
exit 1
fi

PLATFORM=$(detect_platform) || exit 1
TMPDIR=$(mktemp -d)
trap "rm -rf '$TMPDIR'" EXIT

# Parse CUDA_COMPONENTS filter and version overrides
SELECTED_COMPONENTS="${CUDA_COMPONENTS:-}"

is_selected() {
comp="$1"
# If no filter set, install all
[ -z "$SELECTED_COMPONENTS" ] && return 0
# Check if component (with or without @version) is in the comma-separated list
echo ",$SELECTED_COMPONENTS," | grep -q ",${comp}," || echo ",$SELECTED_COMPONENTS," | grep -q ",${comp}@"
}

# Get version override for a component, or empty if not overridden
get_version_override() {
comp="$1"
[ -z "$SELECTED_COMPONENTS" ] && return
override=$(echo ",$SELECTED_COMPONENTS," | grep -o ",${comp}@[^,]*," | sed "s/,//g;s/${comp}@//")
echo "$override"
}

echo "=== CUDA Toolkit ==="
echo "* Platform: ${PLATFORM}"
if [ -n "$SELECTED_COMPONENTS" ]; then
echo "* Components: ${SELECTED_COMPONENTS}"
fi
echo ""

# Shared lib directory for all components
mkdir -p inst/lib

# Read components.tsv (skip header) and install each component
tail -n +2 inst/components.tsv | while IFS=" " read -r component pypi_package version wheel_subdir extract linux_only; do
[ -z "$component" ] && continue

# Skip components not in the selection
if ! is_selected "$component"; then
echo "* Skipping ${component} (not selected)"
continue
fi

# Skip linux-only components on Windows
if [ "$linux_only" = "yes" ] && is_windows; then
echo "* Skipping ${component} (Linux-only)"
continue
fi

# Check for version override
ver_override=$(get_version_override "$component")
if [ -n "$ver_override" ]; then
version="$ver_override"
echo "* Installing ${component} ${version} (overridden)..."
else
echo "* Installing ${component} ${version}..."
fi

# Fetch PyPI simple index for this package
INDEX_FILE="${TMPDIR}/index_${pypi_package}.html"
download_file "https://pypi.org/simple/${pypi_package}/" "$INDEX_FILE"

# Find matching wheel URL
WHEEL_URL=$(grep -o "href=\"[^\"]*${pypi_package}-${version}[^\"]*${PLATFORM}[^\"]*\"" "$INDEX_FILE" | head -1 | sed 's/href="//;s/"//')

if [ -z "$WHEEL_URL" ]; then
echo " ERROR: Could not find wheel for ${pypi_package}==${version} on ${PLATFORM}" >&2
exit 1
fi

WHEEL_URL=$(echo "$WHEEL_URL" | sed 's/#.*//')
WHEEL_NAME=$(basename "$WHEEL_URL")
WHEEL_PATH="${TMPDIR}/${WHEEL_NAME}"

echo " Downloading ${WHEEL_NAME}..."
download_file "$WHEEL_URL" "$WHEEL_PATH"

if [ ! -f "$WHEEL_PATH" ]; then
echo " ERROR: Download failed." >&2
exit 1
fi

# Extract requested directories from the wheel
for dir in $(echo "$extract" | tr ',' ' '); do
unzip -q -o "$WHEEL_PATH" "nvidia/${wheel_subdir}/${dir}/*" -d inst/
done

# Move shared libraries into the unified lib directory
if [ -d "inst/nvidia/${wheel_subdir}/lib" ]; then
mv inst/nvidia/${wheel_subdir}/lib/* inst/lib/ 2>/dev/null || true
rmdir inst/nvidia/${wheel_subdir}/lib 2>/dev/null || true
fi

# Ensure binaries are executable (for nvcc/ptxas)
if echo "$extract" | grep -q "bin"; then
chmod +x inst/nvidia/${wheel_subdir}/bin/* 2>/dev/null || true
fi

rm -f "$WHEEL_PATH"
echo " Done."
done

# Patch RUNPATH on Linux so each .so resolves dependencies from its own
# directory first, preventing LD_LIBRARY_PATH from pulling in wrong versions
# (e.g. conda's older cuDNN).
get_patchelf() {
command -v patchelf > /dev/null 2>&1 && { echo "patchelf"; return 0; }

# Download patchelf from PyPI wheel (static binary, no Python needed)
PATCHELF_VERSION="0.17.2.2"
case "$(uname -m)" in
x86_64)
PATCHELF_URL="https://files.pythonhosted.org/packages/f2/f9/e070956e350ccdfdf059251836f757ad91ac0c01b0ba3e033ea7188d8d42/patchelf-0.17.2.2-py3-none-manylinux1_x86_64.manylinux_2_5_x86_64.musllinux_1_1_x86_64.whl"
;;
aarch64)
PATCHELF_URL="https://files.pythonhosted.org/packages/56/0d/dc3ac6c6e9e9d0d3e40bee1abe95a07034f83627319e60a7dc9abdbfafee/patchelf-0.17.2.2-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.musllinux_1_1_aarch64.whl"
;;
*) return 1 ;;
esac

PATCHELF_DIR="${TMPDIR}/patchelf"
PATCHELF_WHL="${PATCHELF_DIR}/patchelf.whl"
mkdir -p "$PATCHELF_DIR"
download_file "$PATCHELF_URL" "$PATCHELF_WHL"
unzip -q -o "$PATCHELF_WHL" "patchelf-${PATCHELF_VERSION}.data/scripts/patchelf" -d "$PATCHELF_DIR" || return 1
chmod +x "${PATCHELF_DIR}/patchelf-${PATCHELF_VERSION}.data/scripts/patchelf"
echo "${PATCHELF_DIR}/patchelf-${PATCHELF_VERSION}.data/scripts/patchelf"
}

if ! is_windows; then
PATCHELF_BIN=$(get_patchelf)
if [ -n "$PATCHELF_BIN" ]; then
echo "* Patching RPATH with \$ORIGIN (--force-rpath so it takes precedence over LD_LIBRARY_PATH)..."
for so in inst/lib/*.so*; do
[ -f "$so" ] || continue
"$PATCHELF_BIN" --force-rpath --add-rpath '$ORIGIN' "$so" 2>/dev/null || true
done
echo " Done."
else
echo "* WARNING: Could not obtain patchelf, skipping RUNPATH patching."
echo " Install patchelf for reliable CUDA library loading when"
echo " LD_LIBRARY_PATH contains other CUDA installations."
fi
fi

echo ""
echo "=== All components installed successfully ==="
13 changes: 13 additions & 0 deletions cuda13.0/inst/components.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
component pypi_package version wheel_subdir extract linux_only
runtime nvidia_cuda_runtime 13.0.96 cu13 lib,include no
cublas nvidia_cublas 13.1.0.3 cu13 lib,include no
cupti nvidia_cuda_cupti 13.0.85 cu13 lib,include no
nvrtc nvidia_cuda_nvrtc 13.0.88 cu13 lib,include no
cufft nvidia_cufft 12.0.0.61 cu13 lib,include no
cusolver nvidia_cusolver 12.0.4.66 cu13 lib,include no
cusparse nvidia_cusparse 12.6.3.3 cu13 lib,include no
nvjitlink nvidia_nvjitlink 13.0.88 cu13 lib,include no
nvcc nvidia_cuda_nvcc 13.0.88 cu13 bin,include,nvvm no
cudnn nvidia_cudnn_cu13 9.14.0 cudnn lib,include no
nccl nvidia_nccl_cu13 2.27.7 nccl lib,include yes
nvshmem nvidia_nvshmem_cu13 3.4.5 nvshmem lib,include yes
7 changes: 7 additions & 0 deletions cuda13.0/inst/cuda-version.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CUDA_MINOR="13.0"
CUDA_MAJOR="13"
TOOLKIT_VERSION="13.0.2"
PKG_VERSION="1.0.0"
CUDNN_VERSION="9.14.0"
NCCL_VERSION="2.27.7"
NVSHMEM_VERSION="3.4.5"
Loading
Loading