From ba7ba5ceeb61940c4bddaf32e82fc0fc58bd59fc Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sun, 21 Dec 2025 11:17:55 -0500 Subject: [PATCH 1/2] feat(setup_cuda): add windows support --- actions/setup_cuda/README.md | 125 +++++++----- actions/setup_cuda/action.yml | 6 +- actions/setup_cuda/ci-matrix.json | 6 + actions/setup_cuda/post-ci.sh | 5 +- actions/setup_cuda/pre-ci.sh | 20 ++ actions/setup_cuda/setup_cuda.sh | 308 ++++++++++++++++++++++-------- 6 files changed, 344 insertions(+), 126 deletions(-) diff --git a/actions/setup_cuda/README.md b/actions/setup_cuda/README.md index a4060f7..c1ec6d7 100644 --- a/actions/setup_cuda/README.md +++ b/actions/setup_cuda/README.md @@ -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 ``` @@ -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 @@ -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 @@ -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. @@ -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) diff --git a/actions/setup_cuda/action.yml b/actions/setup_cuda/action.yml index 98967a2..5b7788e 100644 --- a/actions/setup_cuda/action.yml +++ b/actions/setup_cuda/action.yml @@ -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" diff --git a/actions/setup_cuda/ci-matrix.json b/actions/setup_cuda/ci-matrix.json index fb07261..6a63c92 100644 --- a/actions/setup_cuda/ci-matrix.json +++ b/actions/setup_cuda/ci-matrix.json @@ -12,5 +12,11 @@ "cuda-version": "13.1.0", "driver-version": "590.44.01" } + }, + { + "runs-on": "windows-latest", + "with": { + "cuda-version": "13.1.0" + } } ] diff --git a/actions/setup_cuda/post-ci.sh b/actions/setup_cuda/post-ci.sh index 6db9d8d..a2740b5 100644 --- a/actions/setup_cuda/post-ci.sh +++ b/actions/setup_cuda/post-ci.sh @@ -43,10 +43,13 @@ 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 diff --git a/actions/setup_cuda/pre-ci.sh b/actions/setup_cuda/pre-ci.sh index f133095..307d920 100644 --- a/actions/setup_cuda/pre-ci.sh +++ b/actions/setup_cuda/pre-ci.sh @@ -5,6 +5,26 @@ set -euo pipefail echo "Pre-CI: Freeing up disk space for CUDA installation..." echo "" +# Detect OS +OS_TYPE=$(uname -s) + +# Skip on macOS +if [[ "$OS_TYPE" == "Darwin" ]]; then + echo "macOS detected - skipping cleanup (CUDA not supported on macOS)" + echo "Pre-CI setup complete!" + exit 0 +fi + +# Skip on Windows +if [[ "$OS_TYPE" == MINGW* ]] || [[ "$OS_TYPE" == MSYS* ]] || [[ "$OS_TYPE" == CYGWIN* ]]; then + echo "Windows detected - skipping cleanup (Windows runners have sufficient space)" + echo "Pre-CI setup complete!" + exit 0 +fi + +echo "Linux detected - running cleanup script..." +echo "" + # Determine which branch/ref to use for downloading the cleanup script # If we're running in the LizardByte/actions repository itself, use the current commit SHA # Otherwise, use master branch diff --git a/actions/setup_cuda/setup_cuda.sh b/actions/setup_cuda/setup_cuda.sh index 8dd9f18..ae74841 100644 --- a/actions/setup_cuda/setup_cuda.sh +++ b/actions/setup_cuda/setup_cuda.sh @@ -10,10 +10,37 @@ BLUE='\033[0;34m' CYAN='\033[0;36m' RESET='\033[0m' +# OS type constants +readonly OS_LINUX="linux" +readonly OS_WINDOWS="windows" +readonly OS_MACOS="macos" + # Default values CUDA_VERSION="" DRIVER_VERSION="" -INSTALL_PATH="/usr/local/cuda" +INSTALL_PATH="" +OS_TYPE="" + +# Detect OS +detect_os() { + case "$(uname -s)" in + Linux*) + echo "$OS_LINUX" + ;; + Darwin*) + echo "$OS_MACOS" + ;; + MINGW*|MSYS*|CYGWIN*) + echo "$OS_WINDOWS" + ;; + *) + echo -e "${RED}Error: Unsupported OS: $(uname -s)${RESET}" >&2 + exit 1 + ;; + esac + + return 0 +} # Function to detect architecture detect_architecture() { @@ -36,17 +63,21 @@ detect_architecture() { return 0 } -# Function to get the runfile name for a specific version and architecture -get_runfile_name() { +# Function to get the installer name for a specific version and architecture +get_installer_name() { local version="$1" local driver_version="$2" local arch="$3" + local os_type="$4" - # NVIDIA naming convention for runfiles - # For x86_64: cuda___linux.run - # For aarch64: cuda___linux_sbsa.run + # NVIDIA naming convention for installers + # Linux x86_64: cuda___linux.run + # Linux aarch64: cuda___linux_sbsa.run + # Windows: cuda__windows_network.exe (network installer, no driver version) - if [[ "$arch" == "x86_64" ]]; then + if [[ "$os_type" == "$OS_WINDOWS" ]]; then + echo "cuda_${version}_windows_network.exe" + elif [[ "$arch" == "x86_64" ]]; then echo "cuda_${version}_${driver_version}_linux.run" elif [[ "$arch" == "aarch64" ]]; then echo "cuda_${version}_${driver_version}_linux_sbsa.run" @@ -61,10 +92,15 @@ get_runfile_name() { # Function to get download URL get_download_url() { local version="$1" - local runfile="$2" + local installer="$2" + local os_type="$3" - # NVIDIA's standard URL pattern - echo "https://developer.download.nvidia.com/compute/cuda/${version}/local_installers/${runfile}" + # NVIDIA's URL pattern differs for Windows network installer + if [[ "$os_type" == "$OS_WINDOWS" ]]; then + echo "https://developer.download.nvidia.com/compute/cuda/${version}/network_installers/${installer}" + else + echo "https://developer.download.nvidia.com/compute/cuda/${version}/local_installers/${installer}" + fi return 0 } @@ -74,27 +110,31 @@ install_cuda() { local version="$1" local driver_version="$2" local install_path="$3" + local os_type="$4" local arch - local runfile + local installer local download_url arch=$(detect_architecture) echo -e "${BLUE}Detected architecture: ${CYAN}${arch}${RESET}" + echo -e "${BLUE}Operating system: ${CYAN}${os_type}${RESET}" - runfile=$(get_runfile_name "$version" "$driver_version" "$arch") - download_url=$(get_download_url "$version" "$runfile") + installer=$(get_installer_name "$version" "$driver_version" "$arch" "$os_type") + download_url=$(get_download_url "$version" "$installer" "$os_type") - echo -e "${BLUE}Installing CUDA Toolkit ${CYAN}${version}${BLUE} for ${CYAN}${arch}${RESET}" - echo -e "${CYAN}Driver version: ${driver_version}${RESET}" + echo -e "${BLUE}Installing CUDA Toolkit ${CYAN}${version}${BLUE} for ${CYAN}${os_type}/${arch}${RESET}" + if [[ "$os_type" != "$OS_WINDOWS" ]]; then + echo -e "${CYAN}Driver version: ${driver_version}${RESET}" + fi echo -e "${CYAN}Download URL: ${download_url}${RESET}" - # Download the runfile + # Download the installer echo -e "${BLUE}Downloading CUDA installer...${RESET}" local tmp_dir tmp_dir=$(mktemp -d) - local runfile_path="${tmp_dir}/${runfile}" + local installer_path="${tmp_dir}/${installer}" - if ! curl -fsSL -o "$runfile_path" "$download_url"; then + if ! curl -fsSL -o "$installer_path" "$download_url"; then echo -e "${RED}Error: Failed to download CUDA installer${RESET}" >&2 echo -e "${YELLOW}URL: ${download_url}${RESET}" >&2 rm -rf "$tmp_dir" @@ -103,22 +143,36 @@ install_cuda() { echo -e "${GREEN}Download complete${RESET}" - # Make the runfile executable - chmod +x "$runfile_path" - - # Install CUDA toolkit (without driver, since we don't have GPU in CI) - echo -e "${BLUE}Installing CUDA Toolkit to ${CYAN}${install_path}${RESET}" - echo -e "${YELLOW}Note: Installing toolkit only (no driver)${RESET}" + if [[ "$os_type" == "$OS_WINDOWS" ]]; then + # Windows installation using network installer + echo -e "${BLUE}Installing CUDA Toolkit (network installer)${RESET}" + echo -e "${YELLOW}Note: Installing toolkit only (no driver, no visual studio integration)${RESET}" - # Run the installer silently - # --silent: silent installation - # --toolkit: install toolkit only - # --toolkitpath: specify installation path - # --no-opengl-libs: don't install OpenGL libraries (not needed for compilation) - if ! sudo "$runfile_path" --silent --toolkit --toolkitpath="$install_path" --no-opengl-libs; then - echo -e "${RED}Error: CUDA installation failed${RESET}" >&2 - rm -rf "$tmp_dir" - exit 1 + # Run the network installer silently + # -s: silent mode + if ! "$installer_path" -s; then + echo -e "${RED}Error: CUDA installation failed${RESET}" >&2 + rm -rf "$tmp_dir" + exit 1 + fi + else + # Linux installation + # Make the runfile executable + chmod +x "$installer_path" + + echo -e "${BLUE}Installing CUDA Toolkit to ${CYAN}${install_path}${RESET}" + echo -e "${YELLOW}Note: Installing toolkit only (no driver)${RESET}" + + # Run the installer silently + # --silent: silent installation + # --toolkit: install toolkit only + # --toolkitpath: specify installation path + # --no-opengl-libs: don't install OpenGL libraries (not needed for compilation) + if ! sudo "$installer_path" --silent --toolkit --toolkitpath="$install_path" --no-opengl-libs; then + echo -e "${RED}Error: CUDA installation failed${RESET}" >&2 + rm -rf "$tmp_dir" + exit 1 + fi fi echo -e "${GREEN}CUDA Toolkit installation complete${RESET}" @@ -127,9 +181,22 @@ install_cuda() { rm -rf "$tmp_dir" # Verify installation - if [[ -f "${install_path}/bin/nvcc" ]]; then - echo -e "${GREEN}CUDA compiler (nvcc) found at ${install_path}/bin/nvcc${RESET}" - "${install_path}/bin/nvcc" --version + local nvcc_path + if [[ "$os_type" == "$OS_WINDOWS" ]]; then + # Windows: CUDA installs to C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v + # Find the nvcc.exe + nvcc_path=$(find "/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA" -name "nvcc.exe" 2>/dev/null | head -1 || true) + if [[ -z "$nvcc_path" ]]; then + # Try Program Files (x86) + nvcc_path=$(find "/c/Program Files (x86)/NVIDIA GPU Computing Toolkit/CUDA" -name "nvcc.exe" 2>/dev/null | head -1 || true) + fi + else + nvcc_path="${install_path}/bin/nvcc" + fi + + if [[ -f "$nvcc_path" ]]; then + echo -e "${GREEN}CUDA compiler (nvcc) found at ${nvcc_path}${RESET}" + "$nvcc_path" --version || true else echo -e "${RED}Error: CUDA compiler not found after installation${RESET}" >&2 exit 1 @@ -142,43 +209,105 @@ install_cuda() { setup_environment() { local install_path="$1" local version="$2" + local os_type="$3" echo -e "${BLUE}Setting up environment variables...${RESET}" - # Add CUDA to PATH - echo "${install_path}/bin" >> "${GITHUB_PATH}" - - # Set environment variables for GitHub Actions - if [[ -n "${GITHUB_ENV:-}" ]]; then - { - echo "CUDA_PATH=${install_path}" - echo "CUDA_HOME=${install_path}" - echo "CUDA_ROOT=${install_path}" - echo "LD_LIBRARY_PATH=${install_path}/lib64:\${LD_LIBRARY_PATH:-}" - echo "LIBRARY_PATH=${install_path}/lib64:\${LIBRARY_PATH:-}" - echo "CPATH=${install_path}/include:\${CPATH:-}" - echo "CMAKE_CUDA_COMPILER=${install_path}/bin/nvcc" - } >> "${GITHUB_ENV}" - fi + if [[ "$os_type" == "$OS_WINDOWS" ]]; then + # Windows: Find CUDA installation + local cuda_base="/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA" + if [[ ! -d "$cuda_base" ]]; then + cuda_base="/c/Program Files (x86)/NVIDIA GPU Computing Toolkit/CUDA" + fi - # Set outputs for GitHub Actions - if [[ -n "${GITHUB_OUTPUT:-}" ]]; then - { - echo "cuda-version=${version}" - echo "cuda-path=${install_path}" - echo "nvcc-path=${install_path}/bin/nvcc" - } >> "${GITHUB_OUTPUT}" - fi + # Find the version directory + local cuda_version_dir + cuda_version_dir=$(find "$cuda_base" -maxdepth 1 -type d -name "v*" | sort -V | tail -1) - echo -e "${GREEN}Environment variables configured:${RESET}" - echo -e " ${CYAN}CUDA_PATH=${install_path}${RESET}" - echo -e " ${CYAN}CUDA_HOME=${install_path}${RESET}" - echo -e " ${CYAN}CUDA_ROOT=${install_path}${RESET}" - echo -e " ${CYAN}CMAKE_CUDA_COMPILER=${install_path}/bin/nvcc${RESET}" - echo -e " ${CYAN}PATH includes ${install_path}/bin${RESET}" - echo -e " ${CYAN}LD_LIBRARY_PATH includes ${install_path}/lib64${RESET}" - echo -e " ${CYAN}LIBRARY_PATH includes ${install_path}/lib64${RESET}" - echo -e " ${CYAN}CPATH includes ${install_path}/include${RESET}" + if [[ -z "$cuda_version_dir" ]]; then + echo -e "${RED}Error: Could not find CUDA installation directory${RESET}" >&2 + exit 1 + fi + + local nvcc_path="${cuda_version_dir}/bin/nvcc.exe" + + # Convert paths to Windows format for outputs + local win_cuda_path + local win_nvcc_path + if command -v cygpath &>/dev/null; then + win_cuda_path=$(cygpath -w "$cuda_version_dir") + win_nvcc_path=$(cygpath -w "$nvcc_path") + else + # Fallback: convert /c/path to C:\path + win_cuda_path=$(echo "$cuda_version_dir" | sed 's|^/\([a-z]\)/|\U\1:/|' | sed 's|/|\\|g') + win_nvcc_path=$(echo "$nvcc_path" | sed 's|^/\([a-z]\)/|\U\1:/|' | sed 's|/|\\|g') + fi + + # Add CUDA to PATH (use Unix-style for bash) + echo "${cuda_version_dir}/bin" >> "${GITHUB_PATH}" + + # Set environment variables for GitHub Actions (use Windows-style paths) + if [[ -n "${GITHUB_ENV:-}" ]]; then + { + echo "CUDA_PATH=${win_cuda_path}" + echo "CUDA_HOME=${win_cuda_path}" + echo "CUDA_ROOT=${win_cuda_path}" + echo "CUDA_PATH_V${version//./_}=${win_cuda_path}" + echo "CMAKE_CUDA_COMPILER=${win_nvcc_path}" + } >> "${GITHUB_ENV}" + fi + + # Set outputs for GitHub Actions (use Windows-style paths) + if [[ -n "${GITHUB_OUTPUT:-}" ]]; then + { + echo "cuda-version=${version}" + echo "cuda-path=${win_cuda_path}" + echo "nvcc-path=${win_nvcc_path}" + } >> "${GITHUB_OUTPUT}" + fi + + echo -e "${GREEN}Environment variables configured:${RESET}" + echo -e " ${CYAN}CUDA_PATH=${win_cuda_path}${RESET}" + echo -e " ${CYAN}CUDA_HOME=${win_cuda_path}${RESET}" + echo -e " ${CYAN}CMAKE_CUDA_COMPILER=${win_nvcc_path}${RESET}" + echo -e " ${CYAN}PATH includes ${cuda_version_dir}/bin${RESET}" + else + # Linux: Use provided install path + # Add CUDA to PATH + echo "${install_path}/bin" >> "${GITHUB_PATH}" + + # Set environment variables for GitHub Actions + if [[ -n "${GITHUB_ENV:-}" ]]; then + { + echo "CUDA_PATH=${install_path}" + echo "CUDA_HOME=${install_path}" + echo "CUDA_ROOT=${install_path}" + echo "LD_LIBRARY_PATH=${install_path}/lib64:\${LD_LIBRARY_PATH:-}" + echo "LIBRARY_PATH=${install_path}/lib64:\${LIBRARY_PATH:-}" + echo "CPATH=${install_path}/include:\${CPATH:-}" + echo "CMAKE_CUDA_COMPILER=${install_path}/bin/nvcc" + } >> "${GITHUB_ENV}" + fi + + # Set outputs for GitHub Actions + if [[ -n "${GITHUB_OUTPUT:-}" ]]; then + { + echo "cuda-version=${version}" + echo "cuda-path=${install_path}" + echo "nvcc-path=${install_path}/bin/nvcc" + } >> "${GITHUB_OUTPUT}" + fi + + echo -e "${GREEN}Environment variables configured:${RESET}" + echo -e " ${CYAN}CUDA_PATH=${install_path}${RESET}" + echo -e " ${CYAN}CUDA_HOME=${install_path}${RESET}" + echo -e " ${CYAN}CUDA_ROOT=${install_path}${RESET}" + echo -e " ${CYAN}CMAKE_CUDA_COMPILER=${install_path}/bin/nvcc${RESET}" + echo -e " ${CYAN}PATH includes ${install_path}/bin${RESET}" + echo -e " ${CYAN}LD_LIBRARY_PATH includes ${install_path}/lib64${RESET}" + echo -e " ${CYAN}LIBRARY_PATH includes ${install_path}/lib64${RESET}" + echo -e " ${CYAN}CPATH includes ${install_path}/include${RESET}" + fi return 0 } @@ -212,31 +341,52 @@ if [[ -z "$CUDA_VERSION" ]]; then exit 1 fi -if [[ -z "$DRIVER_VERSION" ]]; then - echo -e "${RED}Error: --driver-version is required${RESET}" >&2 +# Detect OS +OS_TYPE=$(detect_os) + +# Skip on macOS +if [[ "$OS_TYPE" == "$OS_MACOS" ]]; then + echo -e "${YELLOW}macOS detected - CUDA Toolkit installation not supported on macOS${RESET}" + echo -e "${YELLOW}Skipping CUDA installation...${RESET}" + echo "" + echo -e "${GREEN}=== CUDA Toolkit Setup Skipped (macOS) ===${RESET}" + exit 0 +fi + +# Validate driver-version is provided for Linux (not needed for Windows network installer) +if [[ "$OS_TYPE" == "$OS_LINUX" ]] && [[ -z "$DRIVER_VERSION" ]]; then + echo -e "${RED}Error: --driver-version is required for Linux${RESET}" >&2 echo -e "${YELLOW}Example: --driver-version=550.54.15${RESET}" >&2 echo -e "${YELLOW}Find the correct driver version at: https://developer.nvidia.com/cuda-downloads${RESET}" >&2 exit 1 fi +# Set default install path if not provided +if [[ -z "$INSTALL_PATH" ]]; then + if [[ "$OS_TYPE" == "$OS_WINDOWS" ]]; then + # Windows default is handled by the installer itself + INSTALL_PATH="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v${CUDA_VERSION}" + else + # Linux default + INSTALL_PATH="/usr/local/cuda" + fi +fi + # Main execution echo -e "${BLUE}=== CUDA Toolkit Setup ===${RESET}" +echo -e "${CYAN}Operating System: ${OS_TYPE}${RESET}" echo -e "${CYAN}CUDA Version: ${CUDA_VERSION}${RESET}" -echo -e "${CYAN}Driver Version: ${DRIVER_VERSION}${RESET}" +if [[ "$OS_TYPE" == "$OS_LINUX" ]]; then + echo -e "${CYAN}Driver Version: ${DRIVER_VERSION}${RESET}" +fi echo -e "${CYAN}Install Path: ${INSTALL_PATH}${RESET}" echo "" -# Check if running on Linux -if [[ "$(uname -s)" != "Linux" ]]; then - echo -e "${RED}Error: This action only supports Linux runners${RESET}" >&2 - exit 1 -fi - # Install CUDA -install_cuda "$CUDA_VERSION" "$DRIVER_VERSION" "$INSTALL_PATH" +install_cuda "$CUDA_VERSION" "$DRIVER_VERSION" "$INSTALL_PATH" "$OS_TYPE" # Setup environment -setup_environment "$INSTALL_PATH" "$CUDA_VERSION" +setup_environment "$INSTALL_PATH" "$CUDA_VERSION" "$OS_TYPE" echo "" echo -e "${GREEN}=== CUDA Toolkit Setup Complete ===${RESET}" From e7143da8ddfd0a1dd14ce5b1d0fdf64e3f3f2d60 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sun, 21 Dec 2025 12:14:49 -0500 Subject: [PATCH 2/2] Improve CUDA post-CI script for Windows compatibility Enhances the post-CI script to better detect the platform and handle CUDA compilation on Windows. Adds logic to enable the MSVC environment if cl.exe is not found, and conditionally skips the CUDA compilation test if the required compiler is unavailable. Also adjusts the compilation test to use object-only compilation on Windows and improves cleanup and messaging. --- actions/setup_cuda/post-ci.sh | 139 ++++++++++++++++++++++++++++++---- 1 file changed, 126 insertions(+), 13 deletions(-) diff --git a/actions/setup_cuda/post-ci.sh b/actions/setup_cuda/post-ci.sh index a2740b5..26e79bc 100644 --- a/actions/setup_cuda/post-ci.sh +++ b/actions/setup_cuda/post-ci.sh @@ -53,6 +53,101 @@ else 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..." @@ -71,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..."