diff --git a/CMakeLists.txt b/CMakeLists.txt index 01b39bb..fcd44bb 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 2c30414..718e22f 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 10a7089..789f4af 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 7c8a4b9..536e966 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 d151c13..2f89f4c 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 9e54660..d6cc441 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 c4e4eb7..506de5a 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 e3d7d33..21faa30 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 "") +# 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()