From 7a1b3aaf2e90a3f0a06712514ad6e10f840f6a95 Mon Sep 17 00:00:00 2001 From: Zachary Ferguson Date: Sat, 12 Sep 2026 18:13:13 -0400 Subject: [PATCH 1/5] Enable Windows CUDA CI --- .github/workflows/cuda.yml | 75 +++++++++++++++++++++++++++++++++----- CMakeLists.txt | 4 +- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/.github/workflows/cuda.yml b/.github/workflows/cuda.yml index a777807b0..9c317eb66 100644 --- a/.github/workflows/cuda.yml +++ b/.github/workflows/cuda.yml @@ -22,31 +22,72 @@ env: jobs: Build: - name: CUDA (${{ matrix.config }}) - runs-on: ubuntu-latest + name: ${{ matrix.name }} CUDA (${{ matrix.config }}) + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: + os: [ubuntu-latest, windows-latest] config: - Debug - - Release + # - Release # cannot run multiple cuda-toolkit jobs in parallel + include: + - os: ubuntu-latest + name: Linux + cuda_subpackages: '["nvcc"]' + - os: windows-latest + name: Windows + # Windows splits the toolkit into finer components than Linux and an + # invalid component name aborts the whole install, so name exactly + # what the build needs (per the Windows installer subpackage list): + # nvcc - compiler front-end (nvcc, cudafe++, ptxas, nvlink) + # nvvm - device compiler backend (cicc); nvcc alone omits it + # cudart - cuda_runtime.h + runtime library + # crt - crt/host_config.h + # thrust - Thrust, and the CUB/libcudacxx headers it bundles + # ("cccl"/"cub" are not valid Windows installer subpackage names.) + cuda_subpackages: '["nvcc", "nvvm", "cudart", "crt", "thrust"]' steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 10 - - name: Dependencies + - name: Dependencies (Linux) + if: runner.os == 'Linux' run: | sudo apt-get install ccache echo 'CACHE_PATH=~/.cache/ccache' >> "$GITHUB_ENV" - - name: cuda-toolkit - uses: Jimver/cuda-toolkit@v0.2.30 + - name: Dependencies (Windows) + if: runner.os == 'Windows' + run: | + choco install ccache + "CACHE_PATH=${env:LOCALAPPDATA}\ccache" | Out-File -FilePath $env:GITHUB_ENV -Append + + - name: Install Ninja + if: runner.os == 'Windows' + uses: seanmiddleditch/gha-setup-ninja@master + + # Install CUDA before msvc-dev-cmd so the toolkit's bin dir lands on PATH + # before msvc-dev-cmd snapshots PATH into GITHUB_ENV for later steps. + # (check_language(CUDA) still does not reliably autodetect nvcc on this + # runner even with it on PATH, so the Windows configure also passes + # -DCMAKE_CUDA_COMPILER explicitly.) + - name: Install CUDA Toolkit + uses: Jimver/cuda-toolkit@v0.2.35 + id: cuda-toolkit with: - sub-packages: '["nvcc"]' + cuda: '13.2.0' + sub-packages: ${{ matrix.cuda_subpackages }} method: 'network' + - name: Setup MSVC (Windows) + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v2 id: cpu-cores @@ -56,7 +97,7 @@ jobs: uses: actions/cache@v5 with: path: ${{ env.CACHE_PATH }} - key: ${{ runner.os }}-${{ matrix.config }}-cache + key: ${{ runner.os }}-${{ matrix.config }}-CUDA-cache - name: Prepare ccache run: | @@ -64,7 +105,8 @@ jobs: ccache -V && ccache --show-config ccache --show-stats && ccache --zero-stats - - name: Configure + - name: Configure (Linux) + if: runner.os == 'Linux' run: | mkdir -p build cd build @@ -76,6 +118,21 @@ jobs: -DIPC_TOOLKIT_BUILD_PYTHON=ON \ -DCMAKE_BUILD_TYPE=${{ matrix.config }} + - name: Configure (Windows) + if: runner.os == 'Windows' + shell: cmd + run: | + cmake -G Ninja ^ + -DIPC_TOOLKIT_WITH_CUDA=ON ^ + -DCMAKE_CUDA_ARCHITECTURES=75 ^ + -DSCALABLE_CCD_CUDA_ARCHITECTURES=75 ^ + -DIPC_TOOLKIT_BUILD_TESTS=ON ^ + -DIPC_TOOLKIT_BUILD_PYTHON=ON ^ + -DCMAKE_CUDA_COMPILER="%CUDA_PATH%\bin\nvcc.exe" ^ + -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ + -B build ^ + -S . + - name: Build run: | cmake --build build -j ${{ steps.cpu-cores.outputs.count }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 68fd32051..4ba292f3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,8 +207,8 @@ add_subdirectory("${IPC_TOOLKIT_SOURCE_DIR}") # Public include directory for IPC Toolkit target_include_directories(ipc_toolkit PUBLIC - "${IPC_TOOLKIT_INCLUDE_DIR}" # public headers - "${PROJECT_BINARY_DIR}/include" # generated config.hpp + "${IPC_TOOLKIT_INCLUDE_DIR}" # public headers + $ # generated config.hpp ) # Folder name for IDE From 10e2b2b8bbb1b42893b8f0f5e42e38fb15b231d8 Mon Sep 17 00:00:00 2001 From: Zachary Ferguson Date: Wed, 14 Oct 2026 16:08:16 -0400 Subject: [PATCH 2/5] Fix Windows CUDA CI masking failures and ccache - Run build and ccache steps under bash so failures aren't masked by pwsh - Gate the x86-64-v3 check to Linux - Drop /Zi from Windows Debug flags so ccache can cache compiles - Remove the deprecated gha-setup-ninja action Co-Authored-By: Claude Opus 5.5 --- .github/workflows/continuous.yml | 5 ----- .github/workflows/cuda.yml | 15 +++++++++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/continuous.yml b/.github/workflows/continuous.yml index 42e65f3c1..efcfcde4e 100644 --- a/.github/workflows/continuous.yml +++ b/.github/workflows/continuous.yml @@ -59,11 +59,6 @@ jobs: choco install ccache "CACHE_PATH=${env:LOCALAPPDATA}\ccache" | Out-File -FilePath $env:GITHUB_ENV -Append - # Install Ninja (only needed on Windows) - - name: Install Ninja - if: runner.os == 'Windows' - uses: seanmiddleditch/gha-setup-ninja@master - - name: Setup MSVC (Windows) if: runner.os == 'Windows' uses: ilammy/msvc-dev-cmd@v1 diff --git a/.github/workflows/cuda.yml b/.github/workflows/cuda.yml index b8b094b0d..6c2c14545 100644 --- a/.github/workflows/cuda.yml +++ b/.github/workflows/cuda.yml @@ -65,10 +65,6 @@ jobs: choco install ccache "CACHE_PATH=${env:LOCALAPPDATA}\ccache" | Out-File -FilePath $env:GITHUB_ENV -Append - - name: Install Ninja - if: runner.os == 'Windows' - uses: seanmiddleditch/gha-setup-ninja@master - # Install CUDA before msvc-dev-cmd so the toolkit's bin dir lands on PATH # before msvc-dev-cmd snapshots PATH into GITHUB_ENV for later steps. # (check_language(CUDA) still does not reliably autodetect nvcc on this @@ -95,6 +91,7 @@ jobs: # On Linux, explicitly build for x86-64-v3 instead of -march=native. This # avoids issues with ccache restoring from a runner with a different ISA. - name: Check x86-64-v3 support + if: runner.os == 'Linux' run: | for f in avx2 bmi1 bmi2 f16c fma abm movbe xsave; do grep -qw "$f" /proc/cpuinfo || { echo "::error::Runner CPU lacks $f, which x86-64-v3 requires"; exit 1; } @@ -112,6 +109,7 @@ jobs: key: cuda-${{ runner.os }}-${{ matrix.config }}-cache - name: Prepare ccache + shell: bash run: | ccache --max-size=1.0G ccache -V && ccache --show-config @@ -139,12 +137,17 @@ jobs: -DIPC_TOOLKIT_BUILD_PYTHON=ON \ -DCMAKE_BUILD_TYPE=${{ matrix.config }} + # MSVC's default Debug flags include /Zi, which ccache cannot cache, so we + # drop it the same way the Linux configure drops -g. - name: Configure (Windows) if: runner.os == 'Windows' shell: cmd run: | cmake -G Ninja ^ -DIPC_TOOLKIT_WITH_CUDA=ON ^ + -DCMAKE_C_FLAGS_DEBUG="/Od /Ob0 /RTC1" ^ + -DCMAKE_CXX_FLAGS_DEBUG="/Od /Ob0 /RTC1" ^ + -DCMAKE_CUDA_FLAGS_DEBUG= ^ -DCMAKE_CUDA_ARCHITECTURES=75 ^ -DSCALABLE_CCD_CUDA_ARCHITECTURES=75 ^ -DIPC_TOOLKIT_BUILD_TESTS=ON ^ @@ -154,7 +157,11 @@ jobs: -B build ^ -S . + # Use bash on every runner. Windows' default pwsh reports only the last + # native command's exit code, so a failed build followed by a successful + # `ccache --show-stats` would pass the step. - name: Build + shell: bash run: | cmake --build build -j ${{ steps.cpu-cores.outputs.count }} ccache --show-stats From ea4c9ef7d30b552333cb17f7640ef0ca733dadf1 Mon Sep 17 00:00:00 2001 From: Zachary Ferguson Date: Wed, 14 Oct 2026 16:10:40 -0400 Subject: [PATCH 3/5] Revert unneeded BUILD_INTERFACE include change --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8120922cc..7f6c06c5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -229,8 +229,8 @@ add_subdirectory("${IPC_TOOLKIT_SOURCE_DIR}") # Public include directory for IPC Toolkit target_include_directories(ipc_toolkit PUBLIC - "${IPC_TOOLKIT_INCLUDE_DIR}" # public headers - $ # generated config.hpp + "${IPC_TOOLKIT_INCLUDE_DIR}" # public headers + "${PROJECT_BINARY_DIR}/include" # generated config.hpp ) # Folder name for IDE From ea06f44372a7a8ab1c5b1cf95258795a24e359a6 Mon Sep 17 00:00:00 2001 From: Zachary Ferguson Date: Wed, 14 Oct 2026 16:34:29 -0400 Subject: [PATCH 4/5] Suppress fmt front-end warnings on MSVC-host nvcc Co-Authored-By: Claude Opus 5.5 --- cmake/ipc_toolkit/ipc_toolkit_warnings.cmake | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmake/ipc_toolkit/ipc_toolkit_warnings.cmake b/cmake/ipc_toolkit/ipc_toolkit_warnings.cmake index ff799263b..5c3d9ca3c 100644 --- a/cmake/ipc_toolkit/ipc_toolkit_warnings.cmake +++ b/cmake/ipc_toolkit/ipc_toolkit_warnings.cmake @@ -245,4 +245,13 @@ if(IPC_TOOLKIT_WITH_CUDA) target_compile_options(ipc_toolkit_warnings INTERFACE "$<$,$>:SHELL:-Werror all-warnings>" "$<$,$>:SHELL:-Werror cross-execution-space-call>") + + # With an MSVC host, the front end flags two warnings inside spdlog's bundled + # fmt (#128 "loop is not reachable" and #2417 "constexpr constructor calls + # non-constexpr function"), even though it is an -isystem include. Under + # all-warnings these fail the build, and we can't fix third-party code, so we + # suppress them for MSVC hosts only. This is safe because the Linux build + # still turns both into errors, so our own code stays covered. + target_compile_options(ipc_toolkit_warnings INTERFACE + "$<$,$,$>:-diag-suppress=128,2417>") endif() From f7e4c07799300182917377931cc3a55f1fe4d3cd Mon Sep 17 00:00:00 2001 From: Zachary Ferguson Date: Wed, 14 Oct 2026 16:45:28 -0400 Subject: [PATCH 5/5] Forward MSVC warning suppressions to nvcc host Co-Authored-By: Claude Opus 5.5 --- cmake/ipc_toolkit/ipc_toolkit_warnings.cmake | 27 ++++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/cmake/ipc_toolkit/ipc_toolkit_warnings.cmake b/cmake/ipc_toolkit/ipc_toolkit_warnings.cmake index 5c3d9ca3c..b95e87f10 100644 --- a/cmake/ipc_toolkit/ipc_toolkit_warnings.cmake +++ b/cmake/ipc_toolkit/ipc_toolkit_warnings.cmake @@ -9,14 +9,10 @@ endif() # Flags above don't make sense for MSVC if(MSVC) - set(IPC_TOOLKIT_WARNING_FLAGS - /W4 # High warning level (MSVC equivalent of -Wall -Wextra; /Wall is - # unusably noisy, enabling off-by-default warnings like C4711/C4710/ - # C4514/C4820/C5045) - /MP # Multi-processor compilation - # Silence /W4 warnings that have no counterpart in our GCC/Clang flag set - # (-Wall -Wextra -Wpedantic, with -Wconversion intentionally off), so the - # MSVC output matches the other compilers: + # Silence /W4 warnings that have no counterpart in our GCC/Clang flag set + # (-Wall -Wextra -Wpedantic, with -Wconversion intentionally off), so the + # MSVC output matches the other compilers. The CUDA host pass reuses these. + set(IPC_TOOLKIT_MSVC_DISABLED_WARNINGS /wd4250 # 'inherits via dominance' (benign; from virtual inheritance) /wd4244 # conversion, possible loss of data (GCC: -Wconversion, off) /wd4267 # size_t -> smaller conversion (GCC: -Wconversion, off) @@ -27,6 +23,13 @@ if(MSVC) # params they use) are compiled out, and the collision-stencil # virtual overrides legitimately ignore some params. ) + set(IPC_TOOLKIT_WARNING_FLAGS + /W4 # High warning level (MSVC equivalent of -Wall -Wextra; /Wall is + # unusably noisy, enabling off-by-default warnings like C4711/C4710/ + # C4514/C4820/C5045) + /MP # Multi-processor compilation + ${IPC_TOOLKIT_MSVC_DISABLED_WARNINGS} + ) else() set(IPC_TOOLKIT_WARNING_FLAGS -Wall @@ -226,6 +229,14 @@ if(IPC_TOOLKIT_WITH_CUDA AND NOT MSVC) ) ipc_toolkit_filter_nvcc_flags(IPC_TOOLKIT_NVCC_HOST_WARNING_FLAGS) target_compile_options(ipc_toolkit_warnings INTERFACE ${IPC_TOOLKIT_NVCC_HOST_WARNING_FLAGS}) +elseif(IPC_TOOLKIT_WITH_CUDA) + # With an MSVC host, we only forward the disabled warnings. nvcc's + # `-Werror all-warnings` (below) also makes the host compiler treat its + # warnings as errors, so without these the host pass fails on things the C++ + # build already silences, like C4068 for our `#pragma GCC` directives. + set(IPC_TOOLKIT_NVCC_HOST_WARNING_FLAGS ${IPC_TOOLKIT_MSVC_DISABLED_WARNINGS}) + ipc_toolkit_filter_nvcc_flags(IPC_TOOLKIT_NVCC_HOST_WARNING_FLAGS) + target_compile_options(ipc_toolkit_warnings INTERFACE ${IPC_TOOLKIT_NVCC_HOST_WARNING_FLAGS}) endif() # The device pass has no -Wall; nvcc's own diagnostics are few, and these are