Add Windows support

This commit is contained in:
Marco Franzreb Salgado
2026-05-07 00:31:36 -07:00
parent f392725015
commit dd1ffc94e8
8 changed files with 105 additions and 46 deletions

View File

@@ -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})

View File

@@ -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}"

View File

@@ -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)

View File

@@ -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
$<$<COMPILE_LANGUAGE:CUDA>:FMT_UNICODE=0>
)
endif()
endif()
target_compile_options(nvbench.build_interface INTERFACE
$<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:-Xcudafe=--display_error_number>
$<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:-Wno-deprecated-gpu-targets>
$<$<AND:$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>,$<CXX_COMPILER_ID:MSVC>>:-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)
$<$<AND:$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>,$<CXX_COMPILER_ID:MSVC>>:-Xcudafe=--diag_suppress=27>
$<$<AND:$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>,$<CXX_COMPILER_ID:MSVC>>:-Xcudafe=--diag_suppress=128>
$<$<AND:$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>,$<CXX_COMPILER_ID:MSVC>>:-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"
)

View File

@@ -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

View File

@@ -24,6 +24,7 @@
#include <fmt/format.h>
#include <algorithm>
#include <iterator>
#include <string_view>
#include "test_asserts.cuh"

View File

@@ -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()

View File

@@ -10,45 +10,53 @@ enable_testing()
add_test(NAME test_bench COMMAND "$<TARGET_FILE:test_bench>" --timeout 1)
add_test(NAME nvbench_ctl COMMAND "$<TARGET_FILE:nvbench::ctl>")
# Setup LD_LIBRARY_PATH for testing
if (UNIX)
set(ctl_lib_path "")
set(cupti_lib_path "")
# 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()
# 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
)
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()
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()
# 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()