cuda.cmake 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. if (HAVE_CUDA)
  2. if(${CMAKE_VERSION} VERSION_LESS "3.17.0")
  3. message(FATAL_ERROR "Build with CUDA requires at least cmake 3.17.0")
  4. endif()
  5. enable_language(CUDA)
  6. include(global_flags)
  7. include(common)
  8. function(quote_if_contains_spaces OutVar Var)
  9. if (Var MATCHES ".*[ ].*")
  10. set(${OutVar} "\"${Var}\"" PARENT_SCOPE)
  11. else()
  12. set(${OutVar} ${Var} PARENT_SCOPE)
  13. endif()
  14. endfunction()
  15. function(get_cuda_flags_from_cxx_flags OutCudaFlags CxxFlags)
  16. # OutCudaFlags is an output string
  17. # CxxFlags is a string
  18. set(skipList
  19. -gline-tables-only
  20. # clang coverage
  21. -fprofile-instr-generate
  22. -fcoverage-mapping
  23. /Zc:inline # disable unreferenced functions (kernel registrators) remove
  24. -Wno-c++17-extensions
  25. -flto
  26. -faligned-allocation
  27. -fsized-deallocation
  28. # While it might be reasonable to compile host part of .cu sources with these optimizations enabled,
  29. # nvcc passes these options down towards cicc which lacks x86_64 extensions support.
  30. -msse2
  31. -msse3
  32. -mssse3
  33. -msse4.1
  34. -msse4.2
  35. )
  36. set(skipPrefixRegexp
  37. "(-fsanitize=|-fsanitize-coverage=|-fsanitize-blacklist=|--system-header-prefix|(/|-)std(:|=)c\\+\\+).*"
  38. )
  39. string(FIND "${CMAKE_CUDA_HOST_COMPILER}" clang hostCompilerIsClangPos)
  40. string(COMPARE NOTEQUAL ${hostCompilerIsClangPos} -1 isHostCompilerClang)
  41. function(separate_arguments_with_special_symbols Output Src)
  42. string(REPLACE ";" "$<SEMICOLON>" LocalOutput "${Src}")
  43. separate_arguments(LocalOutput NATIVE_COMMAND ${LocalOutput})
  44. set(${Output} ${LocalOutput} PARENT_SCOPE)
  45. endfunction()
  46. separate_arguments_with_special_symbols(Separated_CxxFlags "${CxxFlags}")
  47. if (MSVC)
  48. set(flagPrefixSymbol "/")
  49. else()
  50. set(flagPrefixSymbol "-")
  51. endif()
  52. set(localCudaCommonFlags "") # non host compiler options
  53. set(localCudaCompilerOptions "")
  54. while (Separated_CxxFlags)
  55. list(POP_FRONT Separated_CxxFlags cxxFlag)
  56. if ((cxxFlag IN_LIST skipList) OR (cxxFlag MATCHES ${skipPrefixRegexp}))
  57. continue()
  58. endif()
  59. if ((cxxFlag STREQUAL -fopenmp=libomp) AND (NOT isHostCompilerClang))
  60. list(APPEND localCudaCompilerOptions -fopenmp)
  61. continue()
  62. endif()
  63. if ((NOT isHostCompilerClang) AND (cxxFlag MATCHES "^\-\-target=.*"))
  64. continue()
  65. endif()
  66. if (cxxFlag MATCHES "^${flagPrefixSymbol}(D[^ ]+)=(.+)")
  67. set(key ${CMAKE_MATCH_1})
  68. quote_if_contains_spaces(safeValue "${CMAKE_MATCH_2}")
  69. list(APPEND localCudaCommonFlags "-${key}=${safeValue}")
  70. continue()
  71. endif()
  72. if (cxxFlag MATCHES "^${flagPrefixSymbol}([DI])(.*)")
  73. set(key ${CMAKE_MATCH_1})
  74. if (CMAKE_MATCH_2)
  75. set(value ${CMAKE_MATCH_2})
  76. set(sep "")
  77. else()
  78. list(POP_FRONT Separated_CxxFlags value)
  79. set(sep " ")
  80. endif()
  81. quote_if_contains_spaces(safeValue "${value}")
  82. list(APPEND localCudaCommonFlags "-${key}${sep}${safeValue}")
  83. continue()
  84. endif()
  85. list(APPEND localCudaCompilerOptions ${cxxFlag})
  86. endwhile()
  87. if (isHostCompilerClang)
  88. # nvcc concatenates the sources for clang, and clang reports unused
  89. # things from .h files as if they they were defined in a .cpp file.
  90. list(APPEND localCudaCommonFlags -Wno-unused-function -Wno-unused-parameter)
  91. if (CMAKE_CXX_COMPILER_TARGET)
  92. list(APPEND localCudaCompilerOptions "--target=${CMAKE_CXX_COMPILER_TARGET}")
  93. endif()
  94. endif()
  95. if (CMAKE_SYSROOT)
  96. list(APPEND localCudaCompilerOptions "--sysroot=${CMAKE_SYSROOT}")
  97. endif()
  98. list(JOIN localCudaCommonFlags " " joinedLocalCudaCommonFlags)
  99. string(REPLACE "$<SEMICOLON>" ";" joinedLocalCudaCommonFlags "${joinedLocalCudaCommonFlags}")
  100. list(JOIN localCudaCompilerOptions , joinedLocalCudaCompilerOptions)
  101. set(${OutCudaFlags} "${joinedLocalCudaCommonFlags} --compiler-options ${joinedLocalCudaCompilerOptions}" PARENT_SCOPE)
  102. endfunction()
  103. get_cuda_flags_from_cxx_flags(CMAKE_CUDA_FLAGS "${CMAKE_CXX_FLAGS}")
  104. string(APPEND CMAKE_CUDA_FLAGS
  105. # Allow __host__, __device__ annotations in lambda declaration.
  106. " --expt-extended-lambda"
  107. # Allow host code to invoke __device__ constexpr functions and vice versa
  108. " --expt-relaxed-constexpr"
  109. )
  110. set(NVCC_STD_VER 14)
  111. if(MSVC)
  112. set(NVCC_STD "/std:c++${NVCC_STD_VER}")
  113. else()
  114. set(NVCC_STD "-std=c++${NVCC_STD_VER}")
  115. endif()
  116. string(APPEND CMAKE_CUDA_FLAGS " --compiler-options ${NVCC_STD}")
  117. string(APPEND CMAKE_CUDA_FLAGS " -DTHRUST_IGNORE_CUB_VERSION_CHECK")
  118. if(MSVC)
  119. # default CMake flags differ from our configuration
  120. set(CMAKE_CUDA_FLAGS_DEBUG "-D_DEBUG --compiler-options /Z7,/Ob0,/Od")
  121. set(CMAKE_CUDA_FLAGS_MINSIZEREL "-DNDEBUG --compiler-options /O1,/Ob1")
  122. set(CMAKE_CUDA_FLAGS_RELEASE "-DNDEBUG --compiler-options /Ox,/Ob2,/Oi")
  123. set(CMAKE_CUDA_FLAGS_RELWITHDEBINFO "-DNDEBUG --compiler-options /Z7,/Ox,/Ob1")
  124. endif()
  125. # use versions from contrib, standard libraries from CUDA distibution are incompatible with MSVC and libcxx
  126. set(CUDA_EXTRA_INCLUDE_DIRECTORIES
  127. ${CMAKE_SOURCE_DIR}/contrib/libs/nvidia/thrust
  128. ${CMAKE_SOURCE_DIR}/contrib/libs/nvidia/cub
  129. )
  130. find_package(CUDAToolkit REQUIRED)
  131. if(${CMAKE_CUDA_COMPILER_VERSION} VERSION_GREATER_EQUAL "11.2")
  132. string(APPEND CMAKE_CUDA_FLAGS " --threads 0")
  133. endif()
  134. message(VERBOSE "CMAKE_CUDA_FLAGS = \"${CMAKE_CUDA_FLAGS}\"")
  135. enable_language(CUDA)
  136. function(target_cuda_flags Tgt)
  137. set_property(TARGET ${Tgt} APPEND PROPERTY
  138. CUDA_FLAGS ${ARGN}
  139. )
  140. endfunction()
  141. function(target_cuda_cflags Tgt)
  142. if (NOT ("${ARGN}" STREQUAL ""))
  143. string(JOIN "," OPTIONS ${ARGN})
  144. set_property(TARGET ${Tgt} APPEND PROPERTY
  145. CUDA_FLAGS --compiler-options ${OPTIONS}
  146. )
  147. endif()
  148. endfunction()
  149. function(target_cuda_sources Tgt Scope)
  150. # add include directories on per-CMakeLists file level because some non-CUDA source files may want to include calls to CUDA libs
  151. include_directories(${CUDA_EXTRA_INCLUDE_DIRECTORIES})
  152. set_source_files_properties(${ARGN} PROPERTIES
  153. COMPILE_OPTIONS "$<JOIN:$<TARGET_GENEX_EVAL:${Tgt},$<TARGET_PROPERTY:${Tgt},CUDA_FLAGS>>,;>"
  154. )
  155. target_sources(${Tgt} ${Scope} ${ARGN})
  156. endfunction()
  157. endif()