From 23b445ad35e125096b43bf78affa090310e658ae Mon Sep 17 00:00:00 2001 From: Marco Franzreb Salgado Date: Thu, 7 May 2026 00:31:36 -0700 Subject: [PATCH 01/21] Add Windows support --- CMakeLists.txt | 3 + ci/build_common.sh | 22 ++++--- cmake/NVBenchCUPTI.cmake | 14 +++-- cmake/NVBenchConfigTarget.cmake | 18 +++++- nvbench/config.cuh.in | 4 ++ testing/axes_metadata.cu | 1 + testing/cmake/CMakeLists.txt | 15 +++++ testing/cmake/test_export/CMakeLists.txt | 74 +++++++++++++----------- 8 files changed, 105 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 01b39bbe..fcd44bb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,9 @@ if (${CUDAToolkit_VERSION} VERSION_LESS 11.3) endif() option(BUILD_SHARED_LIBS "Build NVBench as a shared library" ON) +if (WIN32 AND BUILD_SHARED_LIBS) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +endif() option(NVBench_ENABLE_NVML "Build with NVML support from the Cuda Toolkit." ON) option(NVBench_ENABLE_CUPTI "Build NVBench with CUPTI." ${cupti_default}) diff --git a/ci/build_common.sh b/ci/build_common.sh index 2c30414a..718e22fa 100755 --- a/ci/build_common.sh +++ b/ci/build_common.sh @@ -12,6 +12,7 @@ CUDA_COMPILER=${CUDACXX:-nvcc} # $CUDACXX if set, otherwise `nvcc` CUDA_ARCHS= # Empty, use presets by default. GLOBAL_CMAKE_OPTIONS=() DISABLE_CUB_BENCHMARKS= # Enable to force-disable building CUB benchmarks. +HOST_OS="linux" # "linux" or "windows" # Check if the correct number of arguments has been provided function usage { @@ -21,6 +22,7 @@ function usage { echo echo "Options:" echo " -v/--verbose: enable shell echo for debugging" + echo " -os: Target OS, \"linux\" or \"windows\" (Defaults to linux)" echo " -cuda: CUDA compiler (Defaults to \$CUDACXX if set, otherwise nvcc)" echo " -cxx: Host compiler (Defaults to \$CXX if set, otherwise g++)" echo " -std: CUDA/C++ standard (Defaults to 17)" @@ -32,6 +34,7 @@ function usage { echo " $ PARALLEL_LEVEL=8 $0 -cxx g++-9" echo " $ $0 -cxx clang++-8" echo " $ $0 -cxx g++-8 -std 20 -arch 80-real -v -cuda /usr/local/bin/nvcc" + echo " $ $0 -os windows -cxx cl.exe -arch native" echo " $ $0 -cmake-options \"-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-Wfatal-errors\"" exit 1 } @@ -44,6 +47,7 @@ args=("$@") while [ "${#args[@]}" -ne 0 ]; do case "${args[0]}" in -v | --verbose) VERBOSE=1; args=("${args[@]:1}");; + -os) HOST_OS="${args[1]}"; args=("${args[@]:2}");; -cxx) HOST_COMPILER="${args[1]}"; args=("${args[@]:2}");; -std) CXX_STANDARD="${args[1]}"; args=("${args[@]:2}");; -cuda) CUDA_COMPILER="${args[1]}"; args=("${args[@]:2}");; @@ -66,8 +70,8 @@ while [ "${#args[@]}" -ne 0 ]; do done # Convert to full paths: -HOST_COMPILER=$(which ${HOST_COMPILER}) -CUDA_COMPILER=$(which ${CUDA_COMPILER}) +HOST_COMPILER=$(which "${HOST_COMPILER}") +CUDA_COMPILER=$(which "${CUDA_COMPILER}") if [[ -n "${CUDA_ARCHS}" ]]; then GLOBAL_CMAKE_OPTIONS+=("-DCMAKE_CUDA_ARCHITECTURES=${CUDA_ARCHS}") @@ -91,11 +95,15 @@ BUILD_DIR="../build/${CCCL_BUILD_INFIX}" # The most recent build will always be symlinked to cccl/build/latest mkdir -p $BUILD_DIR -rm -f ../build/latest -ln -sf $BUILD_DIR ../build/latest - -# Now that BUILD_DIR exists, use readlink to canonicalize the path: -BUILD_DIR=$(readlink -f "${BUILD_DIR}") +if [[ "${HOST_OS}" == "windows" ]]; then + # Git Bash on Windows cannot create directory symlinks without elevated privileges + BUILD_DIR=$(cd "${BUILD_DIR}" && pwd) +else + rm -f ../build/latest + ln -sf $BUILD_DIR ../build/latest + # Now that BUILD_DIR exists, use readlink to canonicalize the path: + BUILD_DIR=$(readlink -f "${BUILD_DIR}") +fi # Prepare environment for CMake: export CMAKE_BUILD_PARALLEL_LEVEL="${PARALLEL_LEVEL}" diff --git a/cmake/NVBenchCUPTI.cmake b/cmake/NVBenchCUPTI.cmake index 10a70893..789f4af1 100644 --- a/cmake/NVBenchCUPTI.cmake +++ b/cmake/NVBenchCUPTI.cmake @@ -23,14 +23,20 @@ function(nvbench_add_cupti_dep dep_name) add_library(nvbench::${dep_name_lower} SHARED IMPORTED) find_library(NVBench_${dep_name_upper}_LIBRARY ${dep_name_lower} REQUIRED - DOC "The full path to lib${dep_name_lower}.so from the CUDA Toolkit." + DOC "The import library for ${dep_name_lower} from the CUDA Toolkit." HINTS "${nvbench_cupti_root}/lib64" ) mark_as_advanced(NVBench_${dep_name_upper}_LIBRARY) - set_target_properties(nvbench::${dep_name_lower} PROPERTIES - IMPORTED_LOCATION "${NVBench_${dep_name_upper}_LIBRARY}" - ) + if (WIN32) + set_target_properties(nvbench::${dep_name_lower} PROPERTIES + IMPORTED_IMPLIB "${NVBench_${dep_name_upper}_LIBRARY}" + ) + else() + set_target_properties(nvbench::${dep_name_lower} PROPERTIES + IMPORTED_LOCATION "${NVBench_${dep_name_upper}_LIBRARY}" + ) + endif() endfunction() nvbench_add_cupti_dep(cupti) diff --git a/cmake/NVBenchConfigTarget.cmake b/cmake/NVBenchConfigTarget.cmake index 7c8a4b93..536e9663 100644 --- a/cmake/NVBenchConfigTarget.cmake +++ b/cmake/NVBenchConfigTarget.cmake @@ -91,11 +91,25 @@ endif() if (CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") # fmtlib uses llvm's _BitInt internally, which is not available when compiling through nvcc: target_compile_definitions(nvbench.build_interface INTERFACE "FMT_USE_BITINT=0") + if (MSVC) + # cudafe cannot evaluate fmtlib's UTF-8 literal check even when /utf-8 is passed to the host compiler: + target_compile_definitions(nvbench.build_interface INTERFACE + $<$:FMT_UNICODE=0> + ) + endif() endif() target_compile_options(nvbench.build_interface INTERFACE $<$:-Xcudafe=--display_error_number> $<$:-Wno-deprecated-gpu-targets> + $<$,$>:-Xcompiler=/utf-8> + # Suppress cudafe diagnostics triggered by fmtlib headers when compiled through MSVC+nvcc: + # 27: character value is out of range (char32_t sentinel values in lookup tables) + # 128: loop is not reachable (dead code in constexpr string comparison) + # 2417: constexpr constructor calls non-constexpr function (bigint default ctor) + $<$,$>:-Xcudafe=--diag_suppress=27> + $<$,$>:-Xcudafe=--diag_suppress=128> + $<$,$>:-Xcudafe=--diag_suppress=2417> ) if (NVBench_ENABLE_WERROR) target_compile_options(nvbench.build_interface INTERFACE @@ -115,8 +129,8 @@ function(nvbench_config_target target_name) # the library path, other times they're in a subdirectory that isn't added to # the library path... # To simplify installed nvbench usage, add the CUPTI libraries path to the - # installed nvbench rpath: - if (NVBench_ENABLE_CUPTI AND nvbench_cupti_root) + # installed nvbench rpath (Unix only; Windows uses PATH for DLL lookup): + if (NVBench_ENABLE_CUPTI AND nvbench_cupti_root AND NOT WIN32) set_target_properties(${target_name} PROPERTIES INSTALL_RPATH "${nvbench_cupti_root}/lib64" ) diff --git a/nvbench/config.cuh.in b/nvbench/config.cuh.in index d151c130..2f89f4cc 100644 --- a/nvbench/config.cuh.in +++ b/nvbench/config.cuh.in @@ -24,7 +24,11 @@ // Defined if NVBench has been built with CUPTI support. #cmakedefine NVBENCH_HAS_CUPTI +#if defined(_MSVC_LANG) +#define NVBENCH_CPLUSPLUS _MSVC_LANG +#else #define NVBENCH_CPLUSPLUS __cplusplus +#endif // Detect current dialect: #if NVBENCH_CPLUSPLUS < 201703L diff --git a/testing/axes_metadata.cu b/testing/axes_metadata.cu index 9e546602..d6cc441d 100644 --- a/testing/axes_metadata.cu +++ b/testing/axes_metadata.cu @@ -24,6 +24,7 @@ #include #include +#include #include #include "test_asserts.cuh" diff --git a/testing/cmake/CMakeLists.txt b/testing/cmake/CMakeLists.txt index c4e4eb77..506de5a7 100644 --- a/testing/cmake/CMakeLists.txt +++ b/testing/cmake/CMakeLists.txt @@ -9,6 +9,14 @@ set(cmake_opts -D "CMAKE_CUDA_FLAGS=${CMAKE_CUDA_FLAGS}" -D "CMAKE_CUDA_ARCHITECTURES=${arches}" ) +if (WIN32) + list(APPEND cmake_opts + -D "CMAKE_CUDA_HOST_COMPILER=${CMAKE_CXX_COMPILER}" + -D "CMAKE_LINKER=${CMAKE_LINKER}" + -D "CMAKE_RC_COMPILER=${CMAKE_RC_COMPILER}" + -D "CMAKE_MT=${CMAKE_MT}" + ) +endif() # Temporary installation prefix for tests against installed nvbench: set(tmp_install_prefix "${CMAKE_CURRENT_BINARY_DIR}/test_nvbench_install") @@ -32,6 +40,13 @@ function(nvbench_add_compile_test full_test_name_var subdir test_id) ${ARGN} --test-command "${CMAKE_CTEST_COMMAND}" --output-on-failure ) + if (WIN32 AND NVBench_ENABLE_CUPTI AND nvbench_cupti_root) + cmake_path(NATIVE_PATH nvbench_cupti_root cupti_native) + cmake_path(NATIVE_PATH NVBench_EXECUTABLE_OUTPUT_DIR bin_native) + set_tests_properties(${test_name} PROPERTIES + ENVIRONMENT "PATH=${bin_native}\\;${cupti_native}\\lib64\\;$ENV{PATH}" + ) + endif() set(${full_test_name_var} ${test_name} PARENT_SCOPE) endfunction() diff --git a/testing/cmake/test_export/CMakeLists.txt b/testing/cmake/test_export/CMakeLists.txt index e3d7d33c..21faa30a 100644 --- a/testing/cmake/test_export/CMakeLists.txt +++ b/testing/cmake/test_export/CMakeLists.txt @@ -10,45 +10,53 @@ enable_testing() add_test(NAME test_bench COMMAND "$" --timeout 1) add_test(NAME nvbench_ctl COMMAND "$") -# Setup LD_LIBRARY_PATH for testing -if (UNIX) - set(ctl_lib_path "") - set(cupti_lib_path "") - - # Need to find installed libnvbench.so for installed nvbench-ctl. - # Not needed for build_tree test because of RUNPATH. - if (TEST_TYPE STREQUAL "INSTALL_TREE") - get_property(nvbench_config TARGET nvbench::nvbench - PROPERTY IMPORTED_CONFIGURATIONS - ) - - list(LENGTH nvbench_config num_configs) - if (num_configs GREATER 1) - message(WARNING - "Multiple IMPORTED_CONFIGURATIONS for nvbench::nvbench. " - "Picking the first one. This may cause issues." - ) - list(GET nvbench_config 0 nvbench_config) - endif() +# Setup runtime library paths for testing. +# Unix uses LD_LIBRARY_PATH; Windows uses PATH for DLL lookup. +get_property(nvbench_config TARGET nvbench::nvbench + PROPERTY IMPORTED_CONFIGURATIONS +) +list(LENGTH nvbench_config num_configs) +if (num_configs GREATER 1) + message(WARNING + "Multiple IMPORTED_CONFIGURATIONS for nvbench::nvbench. " + "Picking the first one. This may cause issues." + ) + list(GET nvbench_config 0 nvbench_config) +endif() - get_property(ctl_lib_path TARGET nvbench::nvbench - PROPERTY IMPORTED_LOCATION_${nvbench_config} - ) - cmake_path(GET ctl_lib_path PARENT_PATH ctl_lib_path) - endif() +set(nvbench_lib_dir "") +# On Unix the build tree uses RUNPATH so only the install tree needs the path. +# On Windows there is no RUNPATH so we always need the DLL directory. +if (WIN32 OR TEST_TYPE STREQUAL "INSTALL_TREE") + get_property(nvbench_lib TARGET nvbench::nvbench + PROPERTY IMPORTED_LOCATION_${nvbench_config} + ) + cmake_path(GET nvbench_lib PARENT_PATH nvbench_lib_dir) +endif() - # Need to add the CUPTI path to LD_LIBRARY_PATH to make sure CUPTI libraries - # are found at runtime: - if (TARGET nvbench::cupti) - get_property(cupti_lib_path TARGET nvbench::cupti PROPERTY IMPORTED_LOCATION) - cmake_path(GET cupti_lib_path PARENT_PATH cupti_lib_path) +set(cupti_lib_dir "") +if (TARGET nvbench::cupti) + if (WIN32) + get_property(cupti_lib TARGET nvbench::cupti PROPERTY IMPORTED_IMPLIB) + else() + get_property(cupti_lib TARGET nvbench::cupti PROPERTY IMPORTED_LOCATION) endif() + cmake_path(GET cupti_lib PARENT_PATH cupti_lib_dir) +endif() +if (WIN32) + set(lib_dirs "${nvbench_lib_dir}\\;${cupti_lib_dir}") set_property(TEST test_bench PROPERTY - ENVIRONMENT "LD_LIBRARY_PATH=${cupti_lib_path}" + ENVIRONMENT "PATH=${lib_dirs}\\;$ENV{PATH}" ) set_property(TEST nvbench_ctl PROPERTY - ENVIRONMENT "LD_LIBRARY_PATH=${ctl_lib_path}:${cupti_lib_path}" + ENVIRONMENT "PATH=${lib_dirs}\\;$ENV{PATH}" + ) +else() + set_property(TEST test_bench PROPERTY + ENVIRONMENT "LD_LIBRARY_PATH=${cupti_lib_dir}" + ) + set_property(TEST nvbench_ctl PROPERTY + ENVIRONMENT "LD_LIBRARY_PATH=${nvbench_lib_dir}:${cupti_lib_dir}" ) - endif() From 787e435e6d5201905e798a23ab067e680d94f3b1 Mon Sep 17 00:00:00 2001 From: Marco Franzreb Salgado Date: Wed, 13 May 2026 10:38:55 -0700 Subject: [PATCH 02/21] Windows support: revert CI specific changes --- ci/build_common.sh | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/ci/build_common.sh b/ci/build_common.sh index 718e22fa..2c30414a 100755 --- a/ci/build_common.sh +++ b/ci/build_common.sh @@ -12,7 +12,6 @@ CUDA_COMPILER=${CUDACXX:-nvcc} # $CUDACXX if set, otherwise `nvcc` CUDA_ARCHS= # Empty, use presets by default. GLOBAL_CMAKE_OPTIONS=() DISABLE_CUB_BENCHMARKS= # Enable to force-disable building CUB benchmarks. -HOST_OS="linux" # "linux" or "windows" # Check if the correct number of arguments has been provided function usage { @@ -22,7 +21,6 @@ function usage { echo echo "Options:" echo " -v/--verbose: enable shell echo for debugging" - echo " -os: Target OS, \"linux\" or \"windows\" (Defaults to linux)" echo " -cuda: CUDA compiler (Defaults to \$CUDACXX if set, otherwise nvcc)" echo " -cxx: Host compiler (Defaults to \$CXX if set, otherwise g++)" echo " -std: CUDA/C++ standard (Defaults to 17)" @@ -34,7 +32,6 @@ function usage { echo " $ PARALLEL_LEVEL=8 $0 -cxx g++-9" echo " $ $0 -cxx clang++-8" echo " $ $0 -cxx g++-8 -std 20 -arch 80-real -v -cuda /usr/local/bin/nvcc" - echo " $ $0 -os windows -cxx cl.exe -arch native" echo " $ $0 -cmake-options \"-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-Wfatal-errors\"" exit 1 } @@ -47,7 +44,6 @@ args=("$@") while [ "${#args[@]}" -ne 0 ]; do case "${args[0]}" in -v | --verbose) VERBOSE=1; args=("${args[@]:1}");; - -os) HOST_OS="${args[1]}"; args=("${args[@]:2}");; -cxx) HOST_COMPILER="${args[1]}"; args=("${args[@]:2}");; -std) CXX_STANDARD="${args[1]}"; args=("${args[@]:2}");; -cuda) CUDA_COMPILER="${args[1]}"; args=("${args[@]:2}");; @@ -70,8 +66,8 @@ while [ "${#args[@]}" -ne 0 ]; do done # Convert to full paths: -HOST_COMPILER=$(which "${HOST_COMPILER}") -CUDA_COMPILER=$(which "${CUDA_COMPILER}") +HOST_COMPILER=$(which ${HOST_COMPILER}) +CUDA_COMPILER=$(which ${CUDA_COMPILER}) if [[ -n "${CUDA_ARCHS}" ]]; then GLOBAL_CMAKE_OPTIONS+=("-DCMAKE_CUDA_ARCHITECTURES=${CUDA_ARCHS}") @@ -95,15 +91,11 @@ BUILD_DIR="../build/${CCCL_BUILD_INFIX}" # The most recent build will always be symlinked to cccl/build/latest mkdir -p $BUILD_DIR -if [[ "${HOST_OS}" == "windows" ]]; then - # Git Bash on Windows cannot create directory symlinks without elevated privileges - BUILD_DIR=$(cd "${BUILD_DIR}" && pwd) -else - rm -f ../build/latest - ln -sf $BUILD_DIR ../build/latest - # Now that BUILD_DIR exists, use readlink to canonicalize the path: - BUILD_DIR=$(readlink -f "${BUILD_DIR}") -fi +rm -f ../build/latest +ln -sf $BUILD_DIR ../build/latest + +# Now that BUILD_DIR exists, use readlink to canonicalize the path: +BUILD_DIR=$(readlink -f "${BUILD_DIR}") # Prepare environment for CMake: export CMAKE_BUILD_PARALLEL_LEVEL="${PARALLEL_LEVEL}" From 78b674bf2e125e3c34f65ab221c0001adfd96535 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Fri, 15 May 2026 15:27:37 -0500 Subject: [PATCH 03/21] Re- Enable NVBench Windows build job Remove gate that disables Windows NVBench build job in pr.yaml --- .github/workflows/pr.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7ea85397..40427264 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -79,8 +79,6 @@ jobs: nvbench-windows: name: NVBench Windows CUDA${{ matrix.config.cuda }} ${{ matrix.config.host }} C++${{ matrix.config.std }} - # TODO: Re-enable after https://github.com/NVIDIA/nvbench/pull/354 fixes the Windows build. - if: false permissions: id-token: write contents: read From 460e14f9b7d250685ad5bda30b94ca96f4cfe0b3 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sat, 16 May 2026 08:43:08 -0500 Subject: [PATCH 04/21] Install CUDA Profiler API into toolkit --- .github/workflows/build-windows.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 777d2665..4676bfed 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -119,6 +119,7 @@ jobs: - name: Build NVBench env: + NVBENCH_WINDOWS_CUDA: ${{ inputs.cuda }} NVBENCH_WINDOWS_STD: ${{ inputs.std }} NVBENCH_WINDOWS_ARCH: ${{ inputs.arch }} run: | @@ -131,6 +132,7 @@ jobs: @" `$ErrorActionPreference = 'Stop' git config --global --add safe.directory '$containerRepo' + & '$containerRepo/ci/windows/install_cuda_profiler_api.ps1' -cudaVersion '$env:NVBENCH_WINDOWS_CUDA' & '$containerRepo/ci/windows/build_nvbench.ps1' -std '$env:NVBENCH_WINDOWS_STD' -arch '$env:NVBENCH_WINDOWS_ARCH' exit `$LASTEXITCODE "@ | Set-Content -Path $script -Encoding UTF8 From c6cd09756858407a7d1f7a5e32d8e5e1ccf2c95f Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sat, 16 May 2026 09:02:26 -0500 Subject: [PATCH 05/21] Add intall_cuda_profiler_api.ps1 --- ci/windows/install_cuda_profiler_api.ps1 | 61 ++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 ci/windows/install_cuda_profiler_api.ps1 diff --git a/ci/windows/install_cuda_profiler_api.ps1 b/ci/windows/install_cuda_profiler_api.ps1 new file mode 100644 index 00000000..005631e4 --- /dev/null +++ b/ci/windows/install_cuda_profiler_api.ps1 @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +Param( + [Parameter(Mandatory = $false)] + [Alias("cudaVersion")] + [string]$CUDA_VERSION = "" +) + +$ErrorActionPreference = "Stop" + +if (-not $CUDA_VERSION) { + if ($env:CUDA_PATH -and ($env:CUDA_PATH -match "v(?\d+\.\d+)$")) { + $CUDA_VERSION = $Matches.version + } else { + throw "Could not determine CUDA version. Provide -cudaVersion or set CUDA_PATH." + } +} + +$version = [Version]$CUDA_VERSION +$major = $version.Major +$minor = $version.Minor +$build = $version.Build + +if ($build -lt 0) { + $build = 0 +} + +$mmbVersionTag = "${major}.${minor}.${build}" +$mmVersionTag = "${major}.${minor}" +$cudaRoot = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$mmVersionTag" +$profilerHeader = "$cudaRoot\include\cuda_profiler_api.h" + +if (Test-Path $profilerHeader) { + Write-Host "CUDA Profiler API is already installed: $profilerHeader" + return +} + +$component = "cuda_profiler_api_$mmVersionTag" +$cudaMajorUri = "${mmbVersionTag}/network_installers/cuda_${mmbVersionTag}_windows_network.exe" +$cudaVersionUrl = "https://developer.download.nvidia.com/compute/cuda/$cudaMajorUri" +$installer = Join-Path $env:TEMP "cuda_${mmbVersionTag}_windows_network.exe" + +Write-Host "Installing CUDA component: $component" +Write-Host "Downloading CUDA network installer: $cudaVersionUrl" +Invoke-WebRequest -Uri $cudaVersionUrl -OutFile $installer -UseBasicParsing + +try { + $process = Start-Process -Wait -PassThru -FilePath $installer -ArgumentList @("-s", $component) + if ($process.ExitCode -ne 0) { + throw "CUDA network installer failed with exit code $($process.ExitCode)." + } +} finally { + Remove-Item $installer -ErrorAction SilentlyContinue +} + +if (-not (Test-Path $profilerHeader)) { + throw "CUDA Profiler API installation completed, but header was not found: $profilerHeader" +} + +Write-Host "CUDA Profiler API installed: $profilerHeader" From f8c0554f0e6aa3641cfd4509c2ba3aa017fa0c0a Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sat, 16 May 2026 16:51:14 -0500 Subject: [PATCH 06/21] Inform MSVC that static library export main Attempt to fix "LINK : fatal error LNK1561: entry point must be defined" when building benchmarks which need main function provided by static library libnvbench_main after #350 --- nvbench/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nvbench/CMakeLists.txt b/nvbench/CMakeLists.txt index 7466dcd7..27cb62bf 100644 --- a/nvbench/CMakeLists.txt +++ b/nvbench/CMakeLists.txt @@ -134,6 +134,10 @@ nvbench_config_target(nvbench.main) target_compile_definitions(nvbench.main PRIVATE NVBENCH_NO_IMPLICIT_SYSTEM_HEADER) # Propagate `nvbench` to consumers but keep NVBench's own build warning-visible. target_link_libraries(nvbench.main PUBLIC nvbench) +if (MSVC) + # inform MSVC that library provides main + target_link_options(nvbench.main INTERFACE "/INCLUDE:main") +endif() # Ensure CUDA/CUPTI/NVML include dirs are visible for nvbench.main's build. target_link_libraries(nvbench.main PRIVATE ${ctk_libraries}) # Add NVBench's headers privately so the main library itself sees warnings. From f402b57e50918f2bfeb2f5e66e83f23d9438b753 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 06:21:08 -0500 Subject: [PATCH 07/21] Review feedback to PowerShell script --- ci/windows/install_cuda_profiler_api.ps1 | 27 +++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/ci/windows/install_cuda_profiler_api.ps1 b/ci/windows/install_cuda_profiler_api.ps1 index 005631e4..dc133ff7 100644 --- a/ci/windows/install_cuda_profiler_api.ps1 +++ b/ci/windows/install_cuda_profiler_api.ps1 @@ -9,6 +9,26 @@ Param( $ErrorActionPreference = "Stop" +function Assert-NvidiaAuthenticodeSignature { + Param( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string]$Path + ) + + $signature = Get-AuthenticodeSignature -FilePath $Path + if ($signature.Status -ne "Valid") { + throw "Invalid Authenticode signature for '$Path': $($signature.Status) $($signature.StatusMessage)" + } + + $subject = $signature.SignerCertificate.Subject + if ($subject -notmatch "NVIDIA") { + throw "Unexpected signer for '$Path': $subject" + } + + Write-Host "Validated Authenticode signature for '$Path': $subject" +} + if (-not $CUDA_VERSION) { if ($env:CUDA_PATH -and ($env:CUDA_PATH -match "v(?\d+\.\d+)$")) { $CUDA_VERSION = $Matches.version @@ -28,7 +48,11 @@ if ($build -lt 0) { $mmbVersionTag = "${major}.${minor}.${build}" $mmVersionTag = "${major}.${minor}" -$cudaRoot = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$mmVersionTag" +$cudaRoot = if ($env:CUDA_PATH) { + $env:CUDA_PATH +} else { + "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$mmVersionTag" +} $profilerHeader = "$cudaRoot\include\cuda_profiler_api.h" if (Test-Path $profilerHeader) { @@ -44,6 +68,7 @@ $installer = Join-Path $env:TEMP "cuda_${mmbVersionTag}_windows_network.exe" Write-Host "Installing CUDA component: $component" Write-Host "Downloading CUDA network installer: $cudaVersionUrl" Invoke-WebRequest -Uri $cudaVersionUrl -OutFile $installer -UseBasicParsing +Assert-NvidiaAuthenticodeSignature -Path $installer try { $process = Start-Process -Wait -PassThru -FilePath $installer -ArgumentList @("-s", $component) From 71eacdc9701f2f924a83554d1fac13ab9827b283 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 06:22:37 -0500 Subject: [PATCH 08/21] Fix how CMAKE_CUDA_HOST_COMPILER is set in call to cmake --- testing/cmake/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/testing/cmake/CMakeLists.txt b/testing/cmake/CMakeLists.txt index 506de5a7..2c8d174b 100644 --- a/testing/cmake/CMakeLists.txt +++ b/testing/cmake/CMakeLists.txt @@ -10,8 +10,12 @@ set(cmake_opts -D "CMAKE_CUDA_ARCHITECTURES=${arches}" ) if (WIN32) + set(cuda_host_compiler "${CMAKE_CUDA_HOST_COMPILER}") + if (NOT cuda_host_compiler) + set(cuda_host_compiler "${CMAKE_CXX_COMPILER}") + endif() list(APPEND cmake_opts - -D "CMAKE_CUDA_HOST_COMPILER=${CMAKE_CXX_COMPILER}" + -D "CMAKE_CUDA_HOST_COMPILER=${cuda_host_compiler}" -D "CMAKE_LINKER=${CMAKE_LINKER}" -D "CMAKE_RC_COMPILER=${CMAKE_RC_COMPILER}" -D "CMAKE_MT=${CMAKE_MT}" From cc209bb103845a5155be43b4ddb125231d4b5f75 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 06:23:28 -0500 Subject: [PATCH 09/21] Filter out empty directories LD_LIBRARY_PATH/PATH Act on review feedback regarding corner cases when testing may dependent on the directory it is performed from --- testing/cmake/test_export/CMakeLists.txt | 28 +++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/testing/cmake/test_export/CMakeLists.txt b/testing/cmake/test_export/CMakeLists.txt index 21faa30a..f8b03b4b 100644 --- a/testing/cmake/test_export/CMakeLists.txt +++ b/testing/cmake/test_export/CMakeLists.txt @@ -44,19 +44,37 @@ if (TARGET nvbench::cupti) cmake_path(GET cupti_lib PARENT_PATH cupti_lib_dir) endif() +function(join_nonempty_paths out_var separator) + set(paths "") + foreach(path IN LISTS ARGN) + if (path) + list(APPEND paths "${path}") + endif() + endforeach() + list(JOIN paths "${separator}" joined_paths) + set(${out_var} "${joined_paths}" PARENT_SCOPE) +endfunction() + if (WIN32) - set(lib_dirs "${nvbench_lib_dir}\\;${cupti_lib_dir}") + join_nonempty_paths(lib_dirs "\\;" "${nvbench_lib_dir}" "${cupti_lib_dir}") + if (lib_dirs) + set(path_env "PATH=${lib_dirs}\\;$ENV{PATH}") + else() + set(path_env "PATH=$ENV{PATH}") + endif() set_property(TEST test_bench PROPERTY - ENVIRONMENT "PATH=${lib_dirs}\\;$ENV{PATH}" + ENVIRONMENT "${path_env}" ) set_property(TEST nvbench_ctl PROPERTY - ENVIRONMENT "PATH=${lib_dirs}\\;$ENV{PATH}" + ENVIRONMENT "${path_env}" ) else() + join_nonempty_paths(cupti_ld_library_path ":" "${cupti_lib_dir}") + join_nonempty_paths(nvbench_ld_library_path ":" "${nvbench_lib_dir}" "${cupti_lib_dir}") set_property(TEST test_bench PROPERTY - ENVIRONMENT "LD_LIBRARY_PATH=${cupti_lib_dir}" + ENVIRONMENT "LD_LIBRARY_PATH=${cupti_ld_library_path}" ) set_property(TEST nvbench_ctl PROPERTY - ENVIRONMENT "LD_LIBRARY_PATH=${nvbench_lib_dir}:${cupti_lib_dir}" + ENVIRONMENT "LD_LIBRARY_PATH=${nvbench_ld_library_path}" ) endif() From d980c2a7cfcb508fec39f0f1a2b8e9c262067cb3 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 06:50:58 -0500 Subject: [PATCH 10/21] Check that cudaVersion and :CUDA_PATH are consistent --- ci/windows/install_cuda_profiler_api.ps1 | 34 +++++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/ci/windows/install_cuda_profiler_api.ps1 b/ci/windows/install_cuda_profiler_api.ps1 index dc133ff7..b518a85e 100644 --- a/ci/windows/install_cuda_profiler_api.ps1 +++ b/ci/windows/install_cuda_profiler_api.ps1 @@ -9,6 +9,19 @@ Param( $ErrorActionPreference = "Stop" +function Get-CudaVersionFromPath { + Param( + [Parameter(Mandatory = $false)] + [string]$Path = "" + ) + + if ($Path -and $Path -match "v(?\d+\.\d+)[\\/]?$") { + return $Matches.version + } + + return "" +} + function Assert-NvidiaAuthenticodeSignature { Param( [Parameter(Mandatory = $true)] @@ -30,10 +43,9 @@ function Assert-NvidiaAuthenticodeSignature { } if (-not $CUDA_VERSION) { - if ($env:CUDA_PATH -and ($env:CUDA_PATH -match "v(?\d+\.\d+)$")) { - $CUDA_VERSION = $Matches.version - } else { - throw "Could not determine CUDA version. Provide -cudaVersion or set CUDA_PATH." + $CUDA_VERSION = Get-CudaVersionFromPath -Path $env:CUDA_PATH + if (-not $CUDA_VERSION) { + throw "Could not determine CUDA version. Provide -cudaVersion or set CUDA_PATH to a path ending in v.." } } @@ -48,10 +60,18 @@ if ($build -lt 0) { $mmbVersionTag = "${major}.${minor}.${build}" $mmVersionTag = "${major}.${minor}" -$cudaRoot = if ($env:CUDA_PATH) { - $env:CUDA_PATH + +if ($env:CUDA_PATH) { + $cudaPathVersion = Get-CudaVersionFromPath -Path $env:CUDA_PATH + if (-not $cudaPathVersion) { + throw "CUDA_PATH is set but does not end in v.: $env:CUDA_PATH" + } + if ($cudaPathVersion -ne $mmVersionTag) { + throw "CUDA_PATH points to CUDA $cudaPathVersion, but CUDA $mmVersionTag was requested." + } + $cudaRoot = $env:CUDA_PATH } else { - "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$mmVersionTag" + $cudaRoot = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$mmVersionTag" } $profilerHeader = "$cudaRoot\include\cuda_profiler_api.h" From 6c44ec695869cef474285f8347b874a4a860515f Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 06:51:30 -0500 Subject: [PATCH 11/21] Do not overwrite ENVIRONMENT property with empty values --- testing/cmake/test_export/CMakeLists.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/testing/cmake/test_export/CMakeLists.txt b/testing/cmake/test_export/CMakeLists.txt index f8b03b4b..78c9eb73 100644 --- a/testing/cmake/test_export/CMakeLists.txt +++ b/testing/cmake/test_export/CMakeLists.txt @@ -71,10 +71,14 @@ if (WIN32) else() join_nonempty_paths(cupti_ld_library_path ":" "${cupti_lib_dir}") join_nonempty_paths(nvbench_ld_library_path ":" "${nvbench_lib_dir}" "${cupti_lib_dir}") - set_property(TEST test_bench PROPERTY - ENVIRONMENT "LD_LIBRARY_PATH=${cupti_ld_library_path}" - ) - set_property(TEST nvbench_ctl PROPERTY - ENVIRONMENT "LD_LIBRARY_PATH=${nvbench_ld_library_path}" - ) + if (cupti_ld_library_path) + set_property(TEST test_bench PROPERTY + ENVIRONMENT "LD_LIBRARY_PATH=${cupti_ld_library_path}" + ) + endif() + if (nvbench_ld_library_path) + set_property(TEST nvbench_ctl PROPERTY + ENVIRONMENT "LD_LIBRARY_PATH=${nvbench_ld_library_path}" + ) + endif() endif() From 7f2a6dc1129986c1a08c4819cb7e4151ea64c871 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 07:15:04 -0500 Subject: [PATCH 12/21] Implement retry logic in downloading of CUDA Profiler API --- ci/windows/install_cuda_profiler_api.ps1 | 34 +++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/ci/windows/install_cuda_profiler_api.ps1 b/ci/windows/install_cuda_profiler_api.ps1 index b518a85e..6a88ac3d 100644 --- a/ci/windows/install_cuda_profiler_api.ps1 +++ b/ci/windows/install_cuda_profiler_api.ps1 @@ -42,6 +42,38 @@ function Assert-NvidiaAuthenticodeSignature { Write-Host "Validated Authenticode signature for '$Path': $subject" } +function Invoke-WebRequestWithRetry { + Param( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string]$Uri, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string]$OutFile, + + [Parameter(Mandatory = $false)] + [ValidateRange(1, 10)] + [int]$MaxAttempts = 3 + ) + + for ($attempt = 1; $attempt -le $MaxAttempts; $attempt++) { + try { + Remove-Item $OutFile -ErrorAction SilentlyContinue + Invoke-WebRequest -Uri $Uri -OutFile $OutFile -UseBasicParsing + return + } catch { + if ($attempt -eq $MaxAttempts) { + throw + } + + $delaySeconds = 5 * $attempt + Write-Warning "Download failed on attempt $attempt of $MaxAttempts. Retrying in $delaySeconds seconds. $_" + Start-Sleep -Seconds $delaySeconds + } + } +} + if (-not $CUDA_VERSION) { $CUDA_VERSION = Get-CudaVersionFromPath -Path $env:CUDA_PATH if (-not $CUDA_VERSION) { @@ -87,7 +119,7 @@ $installer = Join-Path $env:TEMP "cuda_${mmbVersionTag}_windows_network.exe" Write-Host "Installing CUDA component: $component" Write-Host "Downloading CUDA network installer: $cudaVersionUrl" -Invoke-WebRequest -Uri $cudaVersionUrl -OutFile $installer -UseBasicParsing +Invoke-WebRequestWithRetry -Uri $cudaVersionUrl -OutFile $installer Assert-NvidiaAuthenticodeSignature -Path $installer try { From 287d041d15bfa35f2cef4bbd372c7c68bd575d01 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 07:30:43 -0500 Subject: [PATCH 13/21] Strengthen publisher verification of downloaded artifact --- ci/windows/install_cuda_profiler_api.ps1 | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ci/windows/install_cuda_profiler_api.ps1 b/ci/windows/install_cuda_profiler_api.ps1 index 6a88ac3d..8ce13ff5 100644 --- a/ci/windows/install_cuda_profiler_api.ps1 +++ b/ci/windows/install_cuda_profiler_api.ps1 @@ -34,12 +34,16 @@ function Assert-NvidiaAuthenticodeSignature { throw "Invalid Authenticode signature for '$Path': $($signature.Status) $($signature.StatusMessage)" } - $subject = $signature.SignerCertificate.Subject - if ($subject -notmatch "NVIDIA") { - throw "Unexpected signer for '$Path': $subject" + $expectedPublisher = "NVIDIA Corporation" + $publisher = $signature.SignerCertificate.GetNameInfo( + [System.Security.Cryptography.X509Certificates.X509NameType]::SimpleName, + $false + ) + if ($publisher -ne $expectedPublisher) { + throw "Unexpected signer for '$Path': $publisher" } - Write-Host "Validated Authenticode signature for '$Path': $subject" + Write-Host "Validated Authenticode signature for '$Path': $publisher" } function Invoke-WebRequestWithRetry { From 9f8bf81ac1762687f1850cba56f95ef0370e1b70 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 07:40:42 -0500 Subject: [PATCH 14/21] Prepend new folders to LD_LIBRARY_PATH, do not overwrite --- testing/cmake/test_export/CMakeLists.txt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/testing/cmake/test_export/CMakeLists.txt b/testing/cmake/test_export/CMakeLists.txt index 78c9eb73..27fd5088 100644 --- a/testing/cmake/test_export/CMakeLists.txt +++ b/testing/cmake/test_export/CMakeLists.txt @@ -55,6 +55,14 @@ function(join_nonempty_paths out_var separator) set(${out_var} "${joined_paths}" PARENT_SCOPE) endfunction() +function(prepend_runtime_path out_var path_var separator env_var) + if (DEFINED ENV{${env_var}} AND NOT "$ENV{${env_var}}" STREQUAL "") + set(${out_var} "${${path_var}}${separator}$ENV{${env_var}}" PARENT_SCOPE) + else() + set(${out_var} "${${path_var}}" PARENT_SCOPE) + endif() +endfunction() + if (WIN32) join_nonempty_paths(lib_dirs "\\;" "${nvbench_lib_dir}" "${cupti_lib_dir}") if (lib_dirs) @@ -72,13 +80,15 @@ else() join_nonempty_paths(cupti_ld_library_path ":" "${cupti_lib_dir}") join_nonempty_paths(nvbench_ld_library_path ":" "${nvbench_lib_dir}" "${cupti_lib_dir}") if (cupti_ld_library_path) + prepend_runtime_path(test_bench_ld_library_path cupti_ld_library_path ":" LD_LIBRARY_PATH) set_property(TEST test_bench PROPERTY - ENVIRONMENT "LD_LIBRARY_PATH=${cupti_ld_library_path}" + ENVIRONMENT "LD_LIBRARY_PATH=${test_bench_ld_library_path}" ) endif() if (nvbench_ld_library_path) + prepend_runtime_path(nvbench_ctl_ld_library_path nvbench_ld_library_path ":" LD_LIBRARY_PATH) set_property(TEST nvbench_ctl PROPERTY - ENVIRONMENT "LD_LIBRARY_PATH=${nvbench_ld_library_path}" + ENVIRONMENT "LD_LIBRARY_PATH=${nvbench_ctl_ld_library_path}" ) endif() endif() From adabe4afa55117de52709268c48aa4ae53b3b3b9 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 07:42:36 -0500 Subject: [PATCH 15/21] Implement timeout, fail on 40x HTTP response code 4xx responses now fail immediately, and the installer is bounded to 15 minutes before being killed and reported as a timeout. --- ci/windows/install_cuda_profiler_api.ps1 | 41 +++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/ci/windows/install_cuda_profiler_api.ps1 b/ci/windows/install_cuda_profiler_api.ps1 index 8ce13ff5..6ae738d7 100644 --- a/ci/windows/install_cuda_profiler_api.ps1 +++ b/ci/windows/install_cuda_profiler_api.ps1 @@ -46,6 +46,30 @@ function Assert-NvidiaAuthenticodeSignature { Write-Host "Validated Authenticode signature for '$Path': $publisher" } +function Get-HttpStatusCodeFromError { + Param( + [Parameter(Mandatory = $true)] + $ErrorRecord + ) + + $responseProperty = $ErrorRecord.Exception.PSObject.Properties["Response"] + if (-not $responseProperty) { + return $null + } + + $response = $responseProperty.Value + if ($null -eq $response) { + return $null + } + + $statusCodeProperty = $response.PSObject.Properties["StatusCode"] + if (-not $statusCodeProperty) { + return $null + } + + return [int]$statusCodeProperty.Value +} + function Invoke-WebRequestWithRetry { Param( [Parameter(Mandatory = $true)] @@ -67,6 +91,11 @@ function Invoke-WebRequestWithRetry { Invoke-WebRequest -Uri $Uri -OutFile $OutFile -UseBasicParsing return } catch { + $statusCode = Get-HttpStatusCodeFromError -ErrorRecord $_ + if ($statusCode -ge 400 -and $statusCode -lt 500) { + throw "Download failed with non-retryable HTTP status $statusCode from '$Uri'. $_" + } + if ($attempt -eq $MaxAttempts) { throw } @@ -126,12 +155,22 @@ Write-Host "Downloading CUDA network installer: $cudaVersionUrl" Invoke-WebRequestWithRetry -Uri $cudaVersionUrl -OutFile $installer Assert-NvidiaAuthenticodeSignature -Path $installer +$installerTimeoutSeconds = 900 +$process = $null try { - $process = Start-Process -Wait -PassThru -FilePath $installer -ArgumentList @("-s", $component) + $process = Start-Process -PassThru -FilePath $installer -ArgumentList @("-s", $component) + if (-not $process.WaitForExit($installerTimeoutSeconds * 1000)) { + Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue + throw "CUDA network installer timed out after $installerTimeoutSeconds seconds." + } + if ($process.ExitCode -ne 0) { throw "CUDA network installer failed with exit code $($process.ExitCode)." } } finally { + if ($process) { + $process.Dispose() + } Remove-Item $installer -ErrorAction SilentlyContinue } From a5b3e97129de7988248c26a4c9eaca34be506edf Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 11:53:50 -0500 Subject: [PATCH 16/21] USE ENVIRONMENT_MODIFICATION property, not ENVIRONMENT --- testing/cmake/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/testing/cmake/CMakeLists.txt b/testing/cmake/CMakeLists.txt index 2c8d174b..9c78fa0a 100644 --- a/testing/cmake/CMakeLists.txt +++ b/testing/cmake/CMakeLists.txt @@ -45,10 +45,11 @@ function(nvbench_add_compile_test full_test_name_var subdir test_id) --test-command "${CMAKE_CTEST_COMMAND}" --output-on-failure ) if (WIN32 AND NVBench_ENABLE_CUPTI AND nvbench_cupti_root) - cmake_path(NATIVE_PATH nvbench_cupti_root cupti_native) - cmake_path(NATIVE_PATH NVBench_EXECUTABLE_OUTPUT_DIR bin_native) + set(cupti_lib_dir "${nvbench_cupti_root}/lib64") set_tests_properties(${test_name} PROPERTIES - ENVIRONMENT "PATH=${bin_native}\\;${cupti_native}\\lib64\\;$ENV{PATH}" + ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$" + "PATH=path_list_prepend:$" ) endif() set(${full_test_name_var} ${test_name} PARENT_SCOPE) From c6347b5e9d7c15fbfcb8f935efb1efa69a07112b Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 11:56:04 -0500 Subject: [PATCH 17/21] escape environment modification values --- testing/cmake/test_export/CMakeLists.txt | 25 +++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/testing/cmake/test_export/CMakeLists.txt b/testing/cmake/test_export/CMakeLists.txt index 27fd5088..f9e3c324 100644 --- a/testing/cmake/test_export/CMakeLists.txt +++ b/testing/cmake/test_export/CMakeLists.txt @@ -64,18 +64,21 @@ function(prepend_runtime_path out_var path_var separator env_var) endfunction() if (WIN32) - join_nonempty_paths(lib_dirs "\\;" "${nvbench_lib_dir}" "${cupti_lib_dir}") - if (lib_dirs) - set(path_env "PATH=${lib_dirs}\\;$ENV{PATH}") - else() - set(path_env "PATH=$ENV{PATH}") + set(path_modifications "") + if (cupti_lib_dir) + list(APPEND path_modifications "PATH=path_list_prepend:$") + endif() + if (nvbench_lib_dir) + list(APPEND path_modifications "PATH=path_list_prepend:$") + endif() + if (path_modifications) + set_property(TEST test_bench PROPERTY + ENVIRONMENT_MODIFICATION ${path_modifications} + ) + set_property(TEST nvbench_ctl PROPERTY + ENVIRONMENT_MODIFICATION ${path_modifications} + ) endif() - set_property(TEST test_bench PROPERTY - ENVIRONMENT "${path_env}" - ) - set_property(TEST nvbench_ctl PROPERTY - ENVIRONMENT "${path_env}" - ) else() join_nonempty_paths(cupti_ld_library_path ":" "${cupti_lib_dir}") join_nonempty_paths(nvbench_ld_library_path ":" "${nvbench_lib_dir}" "${cupti_lib_dir}") From 919468f40f5561cbac5d2626a9dc5aa684dd57b6 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 14:43:13 -0500 Subject: [PATCH 18/21] Fix cmake script error breaking the build --- testing/cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/cmake/CMakeLists.txt b/testing/cmake/CMakeLists.txt index 9c78fa0a..676f9952 100644 --- a/testing/cmake/CMakeLists.txt +++ b/testing/cmake/CMakeLists.txt @@ -46,7 +46,7 @@ function(nvbench_add_compile_test full_test_name_var subdir test_id) ) if (WIN32 AND NVBench_ENABLE_CUPTI AND nvbench_cupti_root) set(cupti_lib_dir "${nvbench_cupti_root}/lib64") - set_tests_properties(${test_name} PROPERTIES + set_property(TEST ${test_name} PROPERTY ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$" "PATH=path_list_prepend:$" From 177c7b054887c465e56a6313023f62395df17af2 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 14:46:40 -0500 Subject: [PATCH 19/21] Added recommented timeout to Invoke-WebRequest --- ci/windows/install_cuda_profiler_api.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/windows/install_cuda_profiler_api.ps1 b/ci/windows/install_cuda_profiler_api.ps1 index 6ae738d7..c0a2fec8 100644 --- a/ci/windows/install_cuda_profiler_api.ps1 +++ b/ci/windows/install_cuda_profiler_api.ps1 @@ -88,7 +88,7 @@ function Invoke-WebRequestWithRetry { for ($attempt = 1; $attempt -le $MaxAttempts; $attempt++) { try { Remove-Item $OutFile -ErrorAction SilentlyContinue - Invoke-WebRequest -Uri $Uri -OutFile $OutFile -UseBasicParsing + Invoke-WebRequest -Uri $Uri -OutFile $OutFile -UseBasicParsing -TimeoutSec 300 return } catch { $statusCode = Get-HttpStatusCodeFromError -ErrorRecord $_ From f83429a734845e902e1baf6791eddde6f7db3c80 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 15:56:12 -0500 Subject: [PATCH 20/21] Set cmake_minimum_required version to 3.30.4, consistent with main project --- testing/cmake/test_export/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/cmake/test_export/CMakeLists.txt b/testing/cmake/test_export/CMakeLists.txt index f9e3c324..15e2206f 100644 --- a/testing/cmake/test_export/CMakeLists.txt +++ b/testing/cmake/test_export/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.20.1) +cmake_minimum_required(VERSION 3.30.4) project(NVBenchTestExport CUDA CXX) message(STATUS "NVBench_DIR=${NVBench_DIR}") From ccfa1b5802f18bf147be226edf3086f35470d154 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Sun, 17 May 2026 15:59:25 -0500 Subject: [PATCH 21/21] Pass NVBENCH environment variables through docker for Windows build --- .github/workflows/build-windows.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 4676bfed..b0cdb653 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -132,8 +132,8 @@ jobs: @" `$ErrorActionPreference = 'Stop' git config --global --add safe.directory '$containerRepo' - & '$containerRepo/ci/windows/install_cuda_profiler_api.ps1' -cudaVersion '$env:NVBENCH_WINDOWS_CUDA' - & '$containerRepo/ci/windows/build_nvbench.ps1' -std '$env:NVBENCH_WINDOWS_STD' -arch '$env:NVBENCH_WINDOWS_ARCH' + & '$containerRepo/ci/windows/install_cuda_profiler_api.ps1' -cudaVersion "`$env:NVBENCH_WINDOWS_CUDA" + & '$containerRepo/ci/windows/build_nvbench.ps1' -std "`$env:NVBENCH_WINDOWS_STD" -arch "`$env:NVBENCH_WINDOWS_ARCH" exit `$LASTEXITCODE "@ | Set-Content -Path $script -Encoding UTF8 @@ -154,6 +154,9 @@ jobs: "--env", "GITHUB_REPOSITORY=$env:GITHUB_REPOSITORY", "--env", "GITHUB_RUN_ID=$env:GITHUB_RUN_ID", "--env", "GITHUB_SHA=$env:GITHUB_SHA", + "--env", "NVBENCH_WINDOWS_ARCH=$env:NVBENCH_WINDOWS_ARCH", + "--env", "NVBENCH_WINDOWS_CUDA=$env:NVBENCH_WINDOWS_CUDA", + "--env", "NVBENCH_WINDOWS_STD=$env:NVBENCH_WINDOWS_STD", "--env", "SCCACHE_BUCKET=$env:SCCACHE_BUCKET", "--env", "SCCACHE_IDLE_TIMEOUT=$env:SCCACHE_IDLE_TIMEOUT", "--env", "SCCACHE_REGION=$env:SCCACHE_REGION",