Skip to content
Draft
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
125 changes: 81 additions & 44 deletions actions/setup_cuda/README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
# setup_cuda

A reusable action to install NVIDIA CUDA Toolkit on Linux runners using the runfile installer.
A reusable action to install NVIDIA CUDA Toolkit on Linux and Windows runners using official installers.

This action provides a consistent way to install CUDA Toolkit across different Linux runners, including both standard
Ubuntu and ARM-based Ubuntu runners. The installation uses NVIDIA's official runfile installers and sets up all
necessary environment variables for C/C++ compilation.
This action provides a consistent way to install CUDA Toolkit across different runners, including Linux (x86_64, ARM64)
and Windows (x86_64). The installation uses NVIDIA's official installers and sets up all necessary environment
variables for C/C++ compilation.

## 🛠️ Prep Work

This action is designed for Linux runners only and requires:
- Ubuntu-based runner (standard x86_64 or ARM64/aarch64)
- Sufficient disk space (CUDA Toolkit requires ~3-4 GB)
- `sudo` access (required for installation)
This action supports the following runners:
- **Linux**: Ubuntu-based runners (x86_64 or ARM64/aarch64) - requires `sudo` access
- **Windows**: Windows Server runners (x86_64)
- **macOS**: Skips gracefully (CUDA not supported on macOS)

Requirements:
- Sufficient disk space (CUDA Toolkit requires ~3-4 GB for local installer, ~100MB for network installer)

> [!NOTE]
> This action installs the CUDA Toolkit only (compiler, libraries, headers) and does not install GPU drivers,
> as they are not needed for compilation and are not available in standard GitHub Actions runners.

> [!TIP]
> To find the correct CUDA version and driver version combination, visit the
> [NVIDIA CUDA Toolkit Downloads](https://developer.nvidia.com/cuda-downloads) page and select your desired version.
> The driver version is part of the runfile name.
> To find the correct CUDA version and driver version combination:
> - **For Linux**: Visit [NVIDIA CUDA Toolkit Downloads](https://developer.nvidia.com/cuda-downloads), select Linux, and note the driver version in the runfile name
> - **For Windows**: Only the CUDA version is needed

## 🚀 Basic Usage

See [action.yml](action.yml)

### CUDA 12.4.1
### Linux - CUDA 13.1.0
```yaml
steps:
- name: Setup CUDA 12.4.1
- name: Setup CUDA 13.1.0
uses: LizardByte/actions/actions/setup_cuda@master
with:
cuda-version: '12.4.1'
driver-version: '550.54.15'
cuda-version: '13.1.0'
driver-version: '590.44.01' # Required for Linux
- name: Verify CUDA Version
run: nvcc --version
```
Expand All @@ -44,23 +47,32 @@ steps:
- name: Setup CUDA
uses: LizardByte/actions/actions/setup_cuda@master
with:
cuda-version: '12.6.2'
driver-version: '560.35.03'
cuda-version: '13.1.0'
driver-version: '590.44.01'
install-path: '/opt/cuda'
```

## 📥 Inputs

| Name | Description | Default | Required |
|----------------|-------------------------------------------------------------------------|-------------------|----------|
| cuda-version | The version of CUDA Toolkit to install (e.g., '12.6.2', '11.8.0') | | `true` |
| driver-version | The driver version in the runfile name (e.g., '560.35.03', '520.61.05') | | `true` |
| install-path | Installation path for CUDA Toolkit | `/usr/local/cuda` | `false` |
| Name | Description | Default | Required |
|----------------|------------------------------------------------------------------------|-------------------|----------|
| cuda-version | The version of CUDA Toolkit to install (e.g., '13.1.0', '12.4.1') | | `true` |
| driver-version | The driver version in the runfile name (Linux only, e.g., '590.44.01') | | `false`* |
| install-path | Installation path for CUDA Toolkit (Linux only) | `/usr/local/cuda` | `false` |

**Required for Linux, not used for Windows (uses network installer).*

> [!NOTE]
> The `driver-version` is the version number included in NVIDIA's runfile name. For example, for the file
> `cuda_12.4.1_550.54.15_linux.run`, the cuda-version is `12.4.1` and the driver-version is `550.54.15`.
> You can find these on the [NVIDIA CUDA Downloads](https://developer.nvidia.com/cuda-downloads) page.
> **Linux**: The `driver-version` is required and must match the driver version in NVIDIA's runfile name.
> - Example: `cuda_13.1.0_590.44.01_linux.run` → driver-version: `590.44.01`
>
> **Windows**: The `driver-version` is not used. Windows uses the network installer which doesn't require specifying a driver version.
> - Network installer: `cuda_13.1.0_windows_network.exe`
>
> **macOS**: The action skips gracefully with a success message (CUDA is not supported on macOS).

> [!TIP]
> Find driver versions on the [NVIDIA CUDA Downloads](https://developer.nvidia.com/cuda-downloads) page by selecting Linux and viewing the runfile name.

## 📤 Outputs

Expand All @@ -72,24 +84,34 @@ steps:

## 📝 Notes

### Supported CUDA Versions
### Supported Platforms & Installers

This action can install **any** CUDA Toolkit version available from NVIDIA, as long as you provide the correct
`cuda-version` and `driver-version` combination. There is no hardcoded list of supported versions.
This action can install **any** CUDA Toolkit version available from NVIDIA.

| Platform | Installer Type | Driver Version |
|----------------|-------------------|----------------|
| Linux x86_64 | Local runfile | ✅ Required |
| Linux ARM64 | Local runfile | ✅ Required |
| Windows x86_64 | Network installer | ❌ Not needed |
| macOS | N/A (skips) | ❌ Not needed |

> [!TIP]
> To find the driver version for any CUDA version:
> 1. Visit [NVIDIA CUDA Toolkit Archive](https://developer.nvidia.com/cuda-toolkit-archive)
> 2. Select your desired CUDA version
> 3. Choose "Linux" → "x86_64" (or "sbsa" for ARM) → "Ubuntu" → "runfile (local)"
> 4. The download link will show the full runfile name, which includes the driver version
> **For Linux**: Find the driver version by visiting [NVIDIA CUDA Toolkit Archive](https://developer.nvidia.com/cuda-toolkit-archive):
> 1. Select your desired CUDA version
> 2. Choose "Linux" → "x86_64" (or "sbsa" for ARM) → "Ubuntu" → "runfile (local)"
> 3. The download link shows the full runfile name with driver version
>
> For example: `cuda_12.4.1_550.54.15_linux.run` means driver version is `550.54.15`
> Example: `cuda_13.1.0_590.44.01_linux.run` means driver version is `590.44.01`

> [!TIP]
> **For Windows**: Only specify the `cuda-version`. The network installer automatically handles driver components.

> [!NOTE]
> The action automatically detects your architecture and downloads the appropriate installer:
> - **x86_64**: Downloads `cuda_X.Y.Z_DDD.DD.DD_linux.run`
> - **aarch64**: Downloads `cuda_X.Y.Z_DDD.DD.DD_linux_sbsa.run` (Server Base System Architecture)
> The action automatically detects your platform and downloads the appropriate installer:
> - **Linux x86_64**: `cuda_X.Y.Z_DDD.DD.DD_linux.run`
> - **Linux aarch64**: `cuda_X.Y.Z_DDD.DD.DD_linux_sbsa.run` (Server Base System Architecture)
> - **Windows**: `cuda_X.Y.Z_windows_network.exe` (network installer)
> - **macOS**: Skips with success message

### Environment Variables

Expand All @@ -100,20 +122,31 @@ This action automatically sets up the following environment variables for subseq
- `CUDA_ROOT` - Same as CUDA_PATH (for compatibility)
- `CMAKE_CUDA_COMPILER` - Path to nvcc compiler
- `PATH` - Updated to include `${CUDA_PATH}/bin`
- `LD_LIBRARY_PATH` - Updated to include `${CUDA_PATH}/lib64`
- `LIBRARY_PATH` - Updated to include `${CUDA_PATH}/lib64`
- `CPATH` - Updated to include `${CUDA_PATH}/include`
- `LD_LIBRARY_PATH` - Updated to include `${CUDA_PATH}/lib64` (Linux only)
- `LIBRARY_PATH` - Updated to include `${CUDA_PATH}/lib64` (Linux only)
- `CPATH` - Updated to include `${CUDA_PATH}/include` (Linux only)

These variables make it easy to compile CUDA code with various build systems (Make, CMake, etc.).

### Installation Details

- **Installation Method**: Official NVIDIA runfile installer
**Linux:**
- **Installation Method**: Official NVIDIA runfile installer (local)
- **Components Installed**: CUDA Toolkit only (compiler, libraries, headers)
- **Components NOT Installed**: GPU drivers, OpenGL libraries (not needed for compilation)
- **Components NOT Installed**: GPU drivers, OpenGL libraries
- **Installation Size**: ~3-4 GB depending on version
- **Installation Time**: ~2-5 minutes depending on runner speed

**Windows:**
- **Installation Method**: Official NVIDIA network installer
- **Components Installed**: CUDA Toolkit only (compiler, libraries, headers)
- **Components NOT Installed**: GPU drivers, Visual Studio integration
- **Download Size**: ~2-100 MB (components downloaded during installation)
- **Installation Time**: ~5-10 minutes (downloads components as needed)

**macOS:**
- Skips gracefully with success message (CUDA not supported)

### CMake Integration

The action sets `CMAKE_CUDA_COMPILER` automatically, so CMake will find the correct nvcc compiler.
Expand All @@ -125,7 +158,11 @@ The action sets `CMAKE_CUDA_COMPILER` automatically, so CMake will find the corr

## ⚠️ Limitations

- **Linux Only**: This action only supports Linux runners (Ubuntu-based)
- **No GPU Execution**: GitHub Actions runners don't have GPUs, so you can compile CUDA code but not run it
- **No Driver Installation**: GPU drivers are not installed (not needed for compilation)
- **Architecture Support**: Only x86_64 and ARM64/aarch64 architectures are supported
- **Platform Support**:
- ✅ Linux x86_64 and ARM64/aarch64 (full support)
- ✅ Windows x86_64 (full support via network installer)
- ⚠️ macOS (skips gracefully - CUDA not supported on macOS)
- **Linux Requirements**: Requires `sudo` access for installation
- **Windows**: Install path not customizable (uses NVIDIA default location)
6 changes: 4 additions & 2 deletions actions/setup_cuda/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ inputs:
driver-version:
description: >
The driver version included in the CUDA installer (e.g., '560.35.03', '520.61.05').
Required for Linux, not used for Windows (uses network installer).
This can be found on NVIDIA's CUDA Toolkit download page.
required: true
required: false
default: ""
install-path:
description: "Installation path for CUDA Toolkit"
description: "Installation path for CUDA Toolkit (Linux only, Windows uses default location)"
required: false
default: "/usr/local/cuda"

Expand Down
6 changes: 6 additions & 0 deletions actions/setup_cuda/ci-matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,11 @@
"cuda-version": "13.1.0",
"driver-version": "590.44.01"
}
},
{
"runs-on": "windows-latest",
"with": {
"cuda-version": "13.1.0"
}
}
]
144 changes: 130 additions & 14 deletions actions/setup_cuda/post-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,111 @@ else
exit 1
fi

# Check for lib directory (Windows uses lib, Linux uses lib64)
if [[ -d "${CUDA_PATH}/lib64" ]]; then
echo "✓ ${CUDA_PATH}/lib64 exists"
elif [[ -d "${CUDA_PATH}/lib" ]]; then
echo "✓ ${CUDA_PATH}/lib exists"
else
echo "✗ ${CUDA_PATH}/lib64 not found"
echo "✗ ${CUDA_PATH}/lib or lib64 not found"
exit 1
fi

# Detect platform (prefer GitHub's RUNNER_OS when available)
RUNNER_OS_NORMALIZED="${RUNNER_OS:-}"
if [[ -z "${RUNNER_OS_NORMALIZED}" ]]; then
case "$(uname -s 2>/dev/null || echo unknown)" in
MINGW*|MSYS*|CYGWIN*) RUNNER_OS_NORMALIZED="Windows" ;;
Darwin*) RUNNER_OS_NORMALIZED="macOS" ;;
Linux*) RUNNER_OS_NORMALIZED="Linux" ;;
*) RUNNER_OS_NORMALIZED="unknown" ;;
esac
fi

# On Windows, nvcc needs the MSVC host compiler (cl.exe). GitHub runners sometimes
# don't have it on PATH inside bash. We'll try to enable it, and if we can't,
# we'll skip the compilation test (but still validate the CUDA install).
maybe_enable_msvc_windows() {
[[ "${RUNNER_OS_NORMALIZED}" == "Windows" ]] || return 0

if command -v cl.exe &>/dev/null; then
return 0
fi

echo ""
echo "MSVC host compiler (cl.exe) not found in PATH. Attempting to enable Visual Studio environment..."

# Try to locate VS installation via vswhere.exe
# Note: Windows env vars may include parentheses, so use printenv instead of ${ProgramFiles(x86)}
local programfiles_x86
programfiles_x86="$(printenv 'ProgramFiles(x86)' 2>/dev/null || true)"
local vswhere_winpath="${programfiles_x86}\\Microsoft Visual Studio\\Installer\\vswhere.exe"
local vswhere=""

# Convert to MSYS path if needed (Git-Bash provides cygpath)
if command -v cygpath &>/dev/null; then
vswhere="$(cygpath -u "$vswhere_winpath" 2>/dev/null || true)"
fi

# Fallback common path if cygpath isn't available
if [[ -z "${vswhere}" ]]; then
vswhere="/c/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe"
fi

if [[ ! -f "${vswhere}" ]]; then
echo "⚠ vswhere.exe not found; cannot auto-enable MSVC environment."
return 0
fi

local vs_install
vs_install="$(${vswhere} -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath 2>/dev/null || true)"

if [[ -z "${vs_install}" ]]; then
echo "⚠ Visual Studio with C++ build tools not found via vswhere.exe."
return 0
fi

# Prefer VsDevCmd.bat (sets a complete dev environment)
local vsdevcmd
vsdevcmd="${vs_install}\\Common7\\Tools\\VsDevCmd.bat"
local vcvars64
vcvars64="${vs_install}\\VC\\Auxiliary\\Build\\vcvars64.bat"

local bat_to_call=""
if [[ -f "${vsdevcmd}" ]]; then
bat_to_call="${vsdevcmd}"
elif [[ -f "${vcvars64}" ]]; then
bat_to_call="${vcvars64}"
else
echo "⚠ Could not find VsDevCmd.bat or vcvars64.bat under: ${vs_install}"
return 0
fi

# Export the environment from cmd.exe into this bash process.
# We parse `set` output lines as KEY=VALUE.
local env_dump
env_dump="$(cmd.exe /c "call \"${bat_to_call}\" -arch=amd64 -host_arch=amd64 >nul 2>&1 && set" 2>nul | tr -d '\r' || true)"

if [[ -z "${env_dump}" ]]; then
echo "⚠ Failed to capture Visual Studio environment."
return 0
fi

while IFS='=' read -r key val; do
# Skip malformed lines
[[ -z "${key}" ]] && continue
export "${key}=${val}"
done <<< "${env_dump}"

if command -v cl.exe &>/dev/null; then
echo "✓ MSVC environment enabled (cl.exe now found)"
else
echo "⚠ MSVC environment attempted but cl.exe still not found"
fi
}

maybe_enable_msvc_windows

# Try to compile a simple CUDA program
echo ""
echo "Testing CUDA compilation..."
Expand All @@ -68,24 +166,42 @@ int main() {
}
EOF

if nvcc -o test_cuda test_cuda.cu; then
echo "✓ CUDA compilation successful"
if ./test_cuda; then
echo "✓ CUDA program execution successful"
# On Windows, nvcc requires MSVC's cl.exe. If it's not available, skip this test.
if [[ "${RUNNER_OS_NORMALIZED}" == "Windows" ]] && ! command -v cl.exe &>/dev/null; then
echo "⚠ Skipping CUDA compilation test on Windows because cl.exe was not found in PATH."
echo " (CUDA toolkit is installed, but MSVC Build Tools are required to compile with nvcc.)"
rm -f test_cuda.cu
else
# Compile only: GitHub runners typically don't have a GPU, so execution is unreliable.
if [[ "${RUNNER_OS_NORMALIZED}" == "Windows" ]]; then
# Object-only compile to validate nvcc + host compiler integration
if nvcc -c test_cuda.cu -o test_cuda.obj; then
echo "✓ CUDA compilation successful"
else
echo "✗ CUDA compilation failed"
rm -f test_cuda.cu test_cuda.obj
exit 1
fi
rm -f test_cuda.cu test_cuda.obj
else
echo "✗ CUDA program execution failed"
if nvcc -o test_cuda test_cuda.cu; then
echo "✓ CUDA compilation successful"
if ./test_cuda; then
echo "✓ CUDA program execution successful"
else
echo "✗ CUDA program execution failed"
rm -f test_cuda test_cuda.cu
exit 1
fi
else
echo "✗ CUDA compilation failed"
rm -f test_cuda.cu
exit 1
fi
rm -f test_cuda test_cuda.cu
exit 1
fi
else
echo "✗ CUDA compilation failed"
rm -f test_cuda.cu
exit 1
fi

# Clean up test files
rm -f test_cuda test_cuda.cu

# Test CMake integration
echo ""
echo "Testing CMake CUDA support..."
Expand Down
Loading
Loading