diff --git a/include/fmt/core.h b/include/fmt/core.h index 2dc6ed552bbb..7abaf657fec0 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -132,8 +132,9 @@ # endif # endif #endif -// Workaround broken [[deprecated]] in the Intel compiler. -#ifdef __INTEL_COMPILER + +// Workaround broken [[deprecated]] in the Intel compiler and NVCC +#if defined(__INTEL_COMPILER) || defined(__NVCC__) || defined(__CUDACC__) # define FMT_DEPRECATED_ALIAS #else # define FMT_DEPRECATED_ALIAS FMT_DEPRECATED diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e399096f2d05..338c9af79ccd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -225,3 +225,13 @@ if (FMT_PEDANTIC AND NOT WIN32) "-DPEDANTIC_COMPILE_FLAGS=${PEDANTIC_COMPILE_FLAGS}" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") endif () + +# +# Activate CUDA related tests if we can find CUDA from CMake. This is optional. +# For version selection, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#cpp14-language-features +# +find_package(CUDA 9.0) +if(CUDA_FOUND) + add_subdirectory(cuda-test) + add_test(NAME cuda-test COMMAND fmt-in-cuda-test) +endif() diff --git a/test/cuda-test/CMakeLists.txt b/test/cuda-test/CMakeLists.txt new file mode 100644 index 000000000000..bb7ac973d336 --- /dev/null +++ b/test/cuda-test/CMakeLists.txt @@ -0,0 +1,105 @@ + +# +# We can find some usecases which follows the guide of CMake. +# The way replaces 'find_package(CUDA)' to 'enable_language(CUDA)'. +# And let the CMake built-in functions to use NVCC. +# +# See: https://cmake.org/cmake/help/latest/module/FindCUDA.html#replacement +# +# However, such CMake versions are pretty high (3.10 or later). +# And we can't sure most of the CUDA projects are using those latest +# because the latest C++ standard for NVCC is C++ 14 at this moment. +# +# In conclusion, +# this test should follow the version of the Root CMakeLists.txt +# and rely on 'find_package(CUDA)'. +# + +# +# This part is for future update +# +# cmake_minimum_required(VERSION 3.10) +# project(fmt-cuda-test LANGUAGES CXX CUDA) # see 'enable_language(CUDA)' +# + +# Follow the Root CMakeLists.txt +cmake_minimum_required(VERSION 3.1) + +# We already knows the packages. This part shows example. +# find_package(CUDA 9.0 REQUIRED) +# find_package(FMT 6.0 REQUIRED) + +# +# Update these when NVCC becomes ready for C++ 17 features +# https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#cpp14-language-features +# +set(CMAKE_CUDA_STANDARD 14) +set(CMAKE_CUDA_STANDARD_REQUIRED 14) + +# +# https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html +# +list(APPEND CUDA_NVCC_FLAGS "-std=c++14") +if(MSVC) + # this is the solution of pytorch + # https://github.com/pytorch/pytorch/pull/7118 + list(APPEND CUDA_NVCC_FLAGS "-Xcompiler" "/std:c++14") + list(APPEND CUDA_NVCC_FLAGS "-Xcompiler" "/Zc:__cplusplus") + # for the reason of this -Xcompiler options, see below ... +endif() + +# +# In this test, we will assume that +# the user is going to compile CUDA source codes with some libraries. +# Of course, it's 'fmt' in this case. +# +# In addition to that, +# this test will invoke both C++ Host compiler and NVCC by providing +# another (non-CUDA) C++ source code +# +cuda_add_executable(fmt-in-cuda-test + cuda-cpp14.cu + cpp14.cc +) + +target_compile_features(fmt-in-cuda-test +PRIVATE + cxx_std_14 # just make sure of the property +) + +get_target_property(IN_USE_CUDA_STANDARD + fmt-in-cuda-test CUDA_STANDARD +) +message(STATUS "cuda_standard: ${IN_USE_CUDA_STANDARD}") + +get_target_property(IN_USE_CUDA_STANDARD_REQUIRED + fmt-in-cuda-test CUDA_STANDARD_REQUIRED +) +message(STATUS "cuda_standard_required: ${IN_USE_CUDA_STANDARD_REQUIRED}") + +# +# https://cmake.org/cmake/help/latest/module/FindCUDA.html +# +# From the document, you can see "The default is to use no keyword" +# +target_link_libraries(fmt-in-cuda-test +# PUBLIC + fmt::fmt +) + +if(MSVC) + # + # This part is for (non-CUDA) C++ code. + # MSVC can define incorrect '__cplusplus' macro. + # Fix for the issue is to use additional compiler flag. + # + # See Also: + # https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ + # https://github.com/Microsoft/vscode-cpptools/issues/2595 + # + target_compile_options(fmt-in-cuda-test + PRIVATE + /Zc:__cplusplus + /permissive- + ) +endif() diff --git a/test/cuda-test/cpp14.cc b/test/cuda-test/cpp14.cc new file mode 100644 index 000000000000..629a0e64f2a4 --- /dev/null +++ b/test/cuda-test/cpp14.cc @@ -0,0 +1,14 @@ + +#include + +// +// The purpose of this part is to ensure NVCC's host compiler also supports +// the standard version. See 'cuda-cpp14.cu'. +// +// https://en.cppreference.com/w/cpp/preprocessor/replace#Predefined_macros +// +static_assert(__cplusplus >= 201402L, "expect C++ 2014 for host compiler"); + +auto make_message_cpp() -> std::string { + return fmt::format("host compiler \t: __cplusplus == {}", __cplusplus); +} diff --git a/test/cuda-test/cuda-cpp14.cu b/test/cuda-test/cuda-cpp14.cu new file mode 100644 index 000000000000..0fafd524211d --- /dev/null +++ b/test/cuda-test/cuda-cpp14.cu @@ -0,0 +1,47 @@ + +// +// Direct NVCC command line example: +// +// nvcc.exe ./cuda-cpp14.cu -x cu -I"../include" -l"fmtd" -L"../build/Debug" \ +// -std=c++14 -Xcompiler /std:c++14 -Xcompiler /Zc:__cplusplus +// + +// +// Ensure that we are using the latest C++ standard for NVCC +// The version is C++14 +// +// https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#c-cplusplus-language-support +// https://en.cppreference.com/w/cpp/preprocessor/replace#Predefined_macros +// +static_assert(__cplusplus >= 201402L, "expect C++ 2014 for nvcc"); + +// +// https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#nvcc-identification-macro +// +// __NVCC__ is for NVCC compiler +// __CUDACC__ is for CUDA(.cu) source code +// +// Since we don't know the actual case in this header, checking both macro +// will prevent possible pitfalls ... +// +// --- this check is moved into the --- +// +// #if defined(__NVCC__) || defined(__CUDACC__) +// # define FMT_DEPRECATED // suppress [[deprecated]] attribute +// #endif +#include + +#include +#include + +extern auto make_message_cpp() -> std::string; +extern auto make_message_cuda() -> std::string; + +int main(int, char*[]) { + std::cout << make_message_cuda() << std::endl; + std::cout << make_message_cpp() << std::endl; +} + +auto make_message_cuda() -> std::string { + return fmt::format("nvcc compiler \t: __cplusplus == {}", __cplusplus); +}