Skip to content

Commit 4586d79

Browse files
feat(actions): add setup cuda action (#94)
1 parent 28cbc37 commit 4586d79

7 files changed

Lines changed: 630 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This is a monorepo containing a collection of GitHub Actions maintained by Lizar
1919
| [release_create](actions/release_create#readme) | Create a new release | composite | bash, javascript |
2020
| [release_homebrew](actions/release_homebrew#readme) | Validate and update Homebrew formula | composite | bash, python |
2121
| [release_setup](actions/release_setup#readme) | Prepare a release | docker | python |
22+
| [setup_cuda](actions/setup_cuda#readme) | Set up NVIDIA CUDA Toolkit on Linux runners | composite | bash |
2223
| [setup_python](actions/setup_python#readme) | Set up Python environment | composite | bash |
2324

2425
## Contributions

actions/setup_cuda/README.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# setup_cuda
2+
3+
A reusable action to install NVIDIA CUDA Toolkit on Linux runners using the runfile installer.
4+
5+
This action provides a consistent way to install CUDA Toolkit across different Linux runners, including both standard
6+
Ubuntu and ARM-based Ubuntu runners. The installation uses NVIDIA's official runfile installers and sets up all
7+
necessary environment variables for C/C++ compilation.
8+
9+
## 🛠️ Prep Work
10+
11+
This action is designed for Linux runners only and requires:
12+
- Ubuntu-based runner (standard x86_64 or ARM64/aarch64)
13+
- Sufficient disk space (CUDA Toolkit requires ~3-4 GB)
14+
- `sudo` access (required for installation)
15+
16+
> [!NOTE]
17+
> This action installs the CUDA Toolkit only (compiler, libraries, headers) and does not install GPU drivers,
18+
> as they are not needed for compilation and are not available in standard GitHub Actions runners.
19+
20+
> [!TIP]
21+
> To find the correct CUDA version and driver version combination, visit the
22+
> [NVIDIA CUDA Toolkit Downloads](https://developer.nvidia.com/cuda-downloads) page and select your desired version.
23+
> The driver version is part of the runfile name.
24+
25+
## 🚀 Basic Usage
26+
27+
See [action.yml](action.yml)
28+
29+
### CUDA 12.4.1
30+
```yaml
31+
steps:
32+
- name: Setup CUDA 12.4.1
33+
uses: LizardByte/actions/actions/setup_cuda@master
34+
with:
35+
cuda-version: '12.4.1'
36+
driver-version: '550.54.15'
37+
- name: Verify CUDA Version
38+
run: nvcc --version
39+
```
40+
41+
### Custom Installation Path
42+
```yaml
43+
steps:
44+
- name: Setup CUDA
45+
uses: LizardByte/actions/actions/setup_cuda@master
46+
with:
47+
cuda-version: '12.6.2'
48+
driver-version: '560.35.03'
49+
install-path: '/opt/cuda'
50+
```
51+
52+
## 📥 Inputs
53+
54+
| Name | Description | Default | Required |
55+
|----------------|-------------------------------------------------------------------------|-------------------|----------|
56+
| cuda-version | The version of CUDA Toolkit to install (e.g., '12.6.2', '11.8.0') | | `true` |
57+
| driver-version | The driver version in the runfile name (e.g., '560.35.03', '520.61.05') | | `true` |
58+
| install-path | Installation path for CUDA Toolkit | `/usr/local/cuda` | `false` |
59+
60+
> [!NOTE]
61+
> The `driver-version` is the version number included in NVIDIA's runfile name. For example, for the file
62+
> `cuda_12.4.1_550.54.15_linux.run`, the cuda-version is `12.4.1` and the driver-version is `550.54.15`.
63+
> You can find these on the [NVIDIA CUDA Downloads](https://developer.nvidia.com/cuda-downloads) page.
64+
65+
## 📤 Outputs
66+
67+
| Name | Description |
68+
|--------------|----------------------------------------|
69+
| cuda-version | The version of CUDA that was installed |
70+
| cuda-path | The installation path of CUDA Toolkit |
71+
| nvcc-path | The path to the nvcc compiler |
72+
73+
## 📝 Notes
74+
75+
### Supported CUDA Versions
76+
77+
This action can install **any** CUDA Toolkit version available from NVIDIA, as long as you provide the correct
78+
`cuda-version` and `driver-version` combination. There is no hardcoded list of supported versions.
79+
80+
> [!TIP]
81+
> To find the driver version for any CUDA version:
82+
> 1. Visit [NVIDIA CUDA Toolkit Archive](https://developer.nvidia.com/cuda-toolkit-archive)
83+
> 2. Select your desired CUDA version
84+
> 3. Choose "Linux" → "x86_64" (or "sbsa" for ARM) → "Ubuntu" → "runfile (local)"
85+
> 4. The download link will show the full runfile name, which includes the driver version
86+
>
87+
> For example: `cuda_12.4.1_550.54.15_linux.run` means driver version is `550.54.15`
88+
89+
> [!NOTE]
90+
> The action automatically detects your architecture and downloads the appropriate installer:
91+
> - **x86_64**: Downloads `cuda_X.Y.Z_DDD.DD.DD_linux.run`
92+
> - **aarch64**: Downloads `cuda_X.Y.Z_DDD.DD.DD_linux_sbsa.run` (Server Base System Architecture)
93+
94+
### Environment Variables
95+
96+
This action automatically sets up the following environment variables for subsequent steps:
97+
98+
- `CUDA_PATH` - Path to CUDA installation (e.g., `/usr/local/cuda`)
99+
- `CUDA_HOME` - Same as CUDA_PATH (for compatibility)
100+
- `CUDA_ROOT` - Same as CUDA_PATH (for compatibility)
101+
- `CMAKE_CUDA_COMPILER` - Path to nvcc compiler
102+
- `PATH` - Updated to include `${CUDA_PATH}/bin`
103+
- `LD_LIBRARY_PATH` - Updated to include `${CUDA_PATH}/lib64`
104+
- `LIBRARY_PATH` - Updated to include `${CUDA_PATH}/lib64`
105+
- `CPATH` - Updated to include `${CUDA_PATH}/include`
106+
107+
These variables make it easy to compile CUDA code with various build systems (Make, CMake, etc.).
108+
109+
### Installation Details
110+
111+
- **Installation Method**: Official NVIDIA runfile installer
112+
- **Components Installed**: CUDA Toolkit only (compiler, libraries, headers)
113+
- **Components NOT Installed**: GPU drivers, OpenGL libraries (not needed for compilation)
114+
- **Installation Size**: ~3-4 GB depending on version
115+
- **Installation Time**: ~2-5 minutes depending on runner speed
116+
117+
### CMake Integration
118+
119+
The action sets `CMAKE_CUDA_COMPILER` automatically, so CMake will find the correct nvcc compiler.
120+
121+
## 🔗 See Also
122+
123+
- [more_space](../more_space) - Free up disk space if needed before CUDA installation
124+
- [monitor_space](../monitor_space) - Monitor disk space usage during CUDA installation
125+
126+
## ⚠️ Limitations
127+
128+
- **Linux Only**: This action only supports Linux runners (Ubuntu-based)
129+
- **No GPU Execution**: GitHub Actions runners don't have GPUs, so you can compile CUDA code but not run it
130+
- **No Driver Installation**: GPU drivers are not installed (not needed for compilation)
131+
- **Architecture Support**: Only x86_64 and ARM64/aarch64 architectures are supported

actions/setup_cuda/action.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
name: "Setup CUDA Toolkit"
3+
description: "A reusable action to install NVIDIA CUDA Toolkit on Linux runners using runfile installer."
4+
author: "LizardByte"
5+
6+
branding:
7+
icon: cpu
8+
color: green
9+
10+
inputs:
11+
cuda-version:
12+
description: The version of CUDA Toolkit to install (e.g., '12.6.2', '11.8.0').
13+
required: true
14+
driver-version:
15+
description: >
16+
The driver version included in the CUDA installer (e.g., '560.35.03', '520.61.05').
17+
This can be found on NVIDIA's CUDA Toolkit download page.
18+
required: true
19+
install-path:
20+
description: "Installation path for CUDA Toolkit"
21+
required: false
22+
default: "/usr/local/cuda"
23+
24+
outputs:
25+
cuda-version:
26+
description: "The version of CUDA that was installed"
27+
value: ${{ steps.setup.outputs.cuda-version }}
28+
cuda-path:
29+
description: "The installation path of CUDA Toolkit"
30+
value: ${{ steps.setup.outputs.cuda-path }}
31+
nvcc-path:
32+
description: "The path to the nvcc compiler"
33+
value: ${{ steps.setup.outputs.nvcc-path }}
34+
35+
runs:
36+
using: "composite"
37+
steps:
38+
- name: Make script executable
39+
shell: bash
40+
run: chmod +x "${GITHUB_ACTION_PATH}/setup_cuda.sh"
41+
42+
- name: Setup CUDA Toolkit
43+
env:
44+
INPUT_CUDA_VERSION: ${{ inputs.cuda-version }}
45+
INPUT_DRIVER_VERSION: ${{ inputs.driver-version }}
46+
INPUT_INSTALL_PATH: ${{ inputs.install-path }}
47+
id: setup
48+
shell: bash
49+
run: |
50+
"${GITHUB_ACTION_PATH}/setup_cuda.sh" \
51+
--cuda-version="${INPUT_CUDA_VERSION}" \
52+
--driver-version="${INPUT_DRIVER_VERSION}" \
53+
--install-path="${INPUT_INSTALL_PATH}"

actions/setup_cuda/ci-matrix.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"runs-on": "ubuntu-24.04-arm",
4+
"with": {
5+
"cuda-version": "13.1.0",
6+
"driver-version": "590.44.01"
7+
}
8+
},
9+
{
10+
"runs-on": "ubuntu-latest",
11+
"with": {
12+
"cuda-version": "13.1.0",
13+
"driver-version": "590.44.01"
14+
}
15+
}
16+
]

actions/setup_cuda/post-ci.sh

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
echo "Verifying CUDA installation..."
6+
7+
# Check if nvcc is available
8+
if command -v nvcc &>/dev/null; then
9+
echo "✓ nvcc found in PATH"
10+
nvcc --version
11+
else
12+
echo "✗ nvcc not found in PATH"
13+
exit 1
14+
fi
15+
16+
# Check environment variables
17+
echo ""
18+
echo "Environment variables:"
19+
echo " CUDA_PATH=${CUDA_PATH:-not set}"
20+
echo " CUDA_HOME=${CUDA_HOME:-not set}"
21+
echo " CMAKE_CUDA_COMPILER=${CMAKE_CUDA_COMPILER:-not set}"
22+
23+
# Verify CUDA_PATH is set
24+
if [[ -z "${CUDA_PATH:-}" ]]; then
25+
echo "✗ CUDA_PATH not set"
26+
exit 1
27+
fi
28+
29+
# Check if CUDA directories exist
30+
echo ""
31+
echo "CUDA installation structure:"
32+
if [[ -d "${CUDA_PATH}/bin" ]]; then
33+
echo "${CUDA_PATH}/bin exists"
34+
else
35+
echo "${CUDA_PATH}/bin not found"
36+
exit 1
37+
fi
38+
39+
if [[ -d "${CUDA_PATH}/include" ]]; then
40+
echo "${CUDA_PATH}/include exists"
41+
else
42+
echo "${CUDA_PATH}/include not found"
43+
exit 1
44+
fi
45+
46+
if [[ -d "${CUDA_PATH}/lib64" ]]; then
47+
echo "${CUDA_PATH}/lib64 exists"
48+
else
49+
echo "${CUDA_PATH}/lib64 not found"
50+
exit 1
51+
fi
52+
53+
# Try to compile a simple CUDA program
54+
echo ""
55+
echo "Testing CUDA compilation..."
56+
57+
cat > test_cuda.cu << 'EOF'
58+
#include <stdio.h>
59+
60+
__global__ void hello_cuda() {
61+
printf("Hello from CUDA!\n");
62+
}
63+
64+
int main() {
65+
printf("CUDA compilation test\n");
66+
printf("This program was compiled successfully with nvcc\n");
67+
return 0;
68+
}
69+
EOF
70+
71+
if nvcc -o test_cuda test_cuda.cu; then
72+
echo "✓ CUDA compilation successful"
73+
if ./test_cuda; then
74+
echo "✓ CUDA program execution successful"
75+
else
76+
echo "✗ CUDA program execution failed"
77+
rm -f test_cuda test_cuda.cu
78+
exit 1
79+
fi
80+
else
81+
echo "✗ CUDA compilation failed"
82+
rm -f test_cuda.cu
83+
exit 1
84+
fi
85+
86+
# Clean up test files
87+
rm -f test_cuda test_cuda.cu
88+
89+
# Test CMake integration
90+
echo ""
91+
echo "Testing CMake CUDA support..."
92+
93+
if command -v cmake &>/dev/null; then
94+
cat > test_cuda_cmake.cu << 'EOF'
95+
#include <stdio.h>
96+
97+
int main() {
98+
printf("CMake CUDA test\n");
99+
return 0;
100+
}
101+
EOF
102+
103+
cat > CMakeLists.txt << 'EOF'
104+
cmake_minimum_required(VERSION 3.18)
105+
project(CUDATest CUDA)
106+
107+
add_executable(test_cmake test_cuda_cmake.cu)
108+
EOF
109+
110+
mkdir -p build_test
111+
if cmake -B build_test -S . &>/dev/null && cmake --build build_test &>/dev/null; then
112+
echo "✓ CMake CUDA configuration successful"
113+
if ./build_test/test_cmake; then
114+
echo "✓ CMake CUDA build successful"
115+
fi
116+
else
117+
echo "✗ CMake CUDA configuration failed (this may be expected if CMake is not available)"
118+
fi
119+
120+
# Clean up CMake test files
121+
rm -rf build_test test_cuda_cmake.cu CMakeLists.txt
122+
else
123+
echo "⚠ CMake not available, skipping CMake test"
124+
fi
125+
126+
echo ""
127+
echo "Post-CI verification complete!"

actions/setup_cuda/pre-ci.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
echo "Pre-CI: Freeing up disk space for CUDA installation..."
6+
echo ""
7+
8+
# Determine which branch/ref to use for downloading the cleanup script
9+
# If we're running in the LizardByte/actions repository itself, use the current commit SHA
10+
# Otherwise, use master branch
11+
if [[ "${GITHUB_REPOSITORY:-}" == "LizardByte/actions" ]]; then
12+
# Running in the actions repo - use the current commit SHA
13+
# GITHUB_SHA is reliable for both PRs and branches
14+
CLEANUP_REF="${GITHUB_SHA:-master}"
15+
echo "Detected LizardByte/actions repository, using commit: ${CLEANUP_REF}"
16+
else
17+
# Running in a different repository - use master
18+
CLEANUP_REF="master"
19+
fi
20+
21+
# Download the cleanup script from more_space action
22+
# Using the raw GitHub URL to get the script from the same repository
23+
CLEANUP_SCRIPT_URL="https://raw.githubusercontent.com/LizardByte/actions/${CLEANUP_REF}/actions/more_space/cleanup.sh"
24+
CLEANUP_SCRIPT="/tmp/cleanup_more_space.sh"
25+
26+
echo "Downloading cleanup script from more_space action..."
27+
if curl -fsSL -o "${CLEANUP_SCRIPT}" "${CLEANUP_SCRIPT_URL}"; then
28+
echo "✓ Downloaded cleanup script"
29+
else
30+
echo "✗ Failed to download cleanup script, trying wget..."
31+
if wget -q -O "${CLEANUP_SCRIPT}" "${CLEANUP_SCRIPT_URL}"; then
32+
echo "✓ Downloaded cleanup script with wget"
33+
else
34+
echo "✗ Failed to download cleanup script"
35+
exit 1
36+
fi
37+
fi
38+
39+
# Make the script executable
40+
chmod +x "${CLEANUP_SCRIPT}"
41+
42+
# Run the cleanup script with options suitable for CUDA installation
43+
# Clean most things but keep JVM which might be needed for tests
44+
bash "${CLEANUP_SCRIPT}" \
45+
--remove-android=true \
46+
--remove-codeql=true \
47+
--remove-docker-images=true \
48+
--remove-docs-linux=true \
49+
--remove-dotnet=true \
50+
--remove-haskell=true \
51+
--remove-jvm=false \
52+
--remove-swift=true \
53+
--remove-tool-cache=true
54+
55+
# Clean up the downloaded script
56+
rm -f "${CLEANUP_SCRIPT}"
57+
58+
echo ""
59+
echo "Pre-CI cleanup complete!"
60+
echo ""

0 commit comments

Comments
 (0)