cuda.cmake 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. # ---[ cuda
  2. # Poor man's include guard
  3. if(TARGET torch::cudart)
  4. return()
  5. endif()
  6. # sccache is only supported in CMake master and not in the newest official
  7. # release (3.11.3) yet. Hence we need our own Modules_CUDA_fix to enable sccache.
  8. list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../Modules_CUDA_fix)
  9. # We don't want to statically link cudart, because we rely on it's dynamic linkage in
  10. # python (follow along torch/cuda/__init__.py and usage of cudaGetErrorName).
  11. # Technically, we can link cudart here statically, and link libtorch_python.so
  12. # to a dynamic libcudart.so, but that's just wasteful.
  13. # However, on Windows, if this one gets switched off, the error "cuda: unknown error"
  14. # will be raised when running the following code:
  15. # >>> import torch
  16. # >>> torch.cuda.is_available()
  17. # >>> torch.cuda.current_device()
  18. # More details can be found in the following links.
  19. # https://github.com/pytorch/pytorch/issues/20635
  20. # https://github.com/pytorch/pytorch/issues/17108
  21. if(NOT MSVC)
  22. set(CUDA_USE_STATIC_CUDA_RUNTIME OFF CACHE INTERNAL "")
  23. endif()
  24. # Find CUDA.
  25. find_package(CUDA)
  26. if(NOT CUDA_FOUND)
  27. message(WARNING
  28. "Caffe2: CUDA cannot be found. Depending on whether you are building "
  29. "Caffe2 or a Caffe2 dependent library, the next warning / error will "
  30. "give you more info.")
  31. set(CAFFE2_USE_CUDA OFF)
  32. return()
  33. endif()
  34. # Enable CUDA language support
  35. set(CUDAToolkit_ROOT "${CUDA_TOOLKIT_ROOT_DIR}")
  36. # Pass clang as host compiler, which according to the docs
  37. # Must be done before CUDA language is enabled, see mast be done before
  38. # see https://cmake.org/cmake/help/v3.15/variable/CMAKE_CUDA_HOST_COMPILER.html
  39. if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
  40. set(CMAKE_CUDA_HOST_COMPILER "${CMAKE_C_COMPILER}")
  41. endif()
  42. enable_language(CUDA)
  43. set(CMAKE_CUDA_STANDARD ${CMAKE_CXX_STANDARD})
  44. set(CMAKE_CUDA_STANDARD_REQUIRED ON)
  45. message(STATUS "Caffe2: CUDA detected: " ${CUDA_VERSION})
  46. message(STATUS "Caffe2: CUDA nvcc is: " ${CUDA_NVCC_EXECUTABLE})
  47. message(STATUS "Caffe2: CUDA toolkit directory: " ${CUDA_TOOLKIT_ROOT_DIR})
  48. if(CUDA_VERSION VERSION_LESS 11.0)
  49. message(FATAL_ERROR "PyTorch requires CUDA 11.0 or above.")
  50. endif()
  51. if(CUDA_FOUND)
  52. # Sometimes, we may mismatch nvcc with the CUDA headers we are
  53. # compiling with, e.g., if a ccache nvcc is fed to us by CUDA_NVCC_EXECUTABLE
  54. # but the PATH is not consistent with CUDA_HOME. It's better safe
  55. # than sorry: make sure everything is consistent.
  56. if(MSVC AND CMAKE_GENERATOR MATCHES "Visual Studio")
  57. # When using Visual Studio, it attempts to lock the whole binary dir when
  58. # `try_run` is called, which will cause the build to fail.
  59. string(RANDOM BUILD_SUFFIX)
  60. set(PROJECT_RANDOM_BINARY_DIR "${PROJECT_BINARY_DIR}/${BUILD_SUFFIX}")
  61. else()
  62. set(PROJECT_RANDOM_BINARY_DIR "${PROJECT_BINARY_DIR}")
  63. endif()
  64. set(file "${PROJECT_BINARY_DIR}/detect_cuda_version.cc")
  65. file(WRITE ${file} ""
  66. "#include <cuda.h>\n"
  67. "#include <cstdio>\n"
  68. "int main() {\n"
  69. " printf(\"%d.%d\", CUDA_VERSION / 1000, (CUDA_VERSION / 10) % 100);\n"
  70. " return 0;\n"
  71. "}\n"
  72. )
  73. if(NOT CMAKE_CROSSCOMPILING)
  74. try_run(run_result compile_result ${PROJECT_RANDOM_BINARY_DIR} ${file}
  75. CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CUDA_INCLUDE_DIRS}"
  76. LINK_LIBRARIES ${CUDA_LIBRARIES}
  77. RUN_OUTPUT_VARIABLE cuda_version_from_header
  78. COMPILE_OUTPUT_VARIABLE output_var
  79. )
  80. if(NOT compile_result)
  81. message(FATAL_ERROR "Caffe2: Couldn't determine version from header: " ${output_var})
  82. endif()
  83. message(STATUS "Caffe2: Header version is: " ${cuda_version_from_header})
  84. if(NOT cuda_version_from_header STREQUAL ${CUDA_VERSION_STRING})
  85. # Force CUDA to be processed for again next time
  86. # TODO: I'm not sure if this counts as an implementation detail of
  87. # FindCUDA
  88. set(${cuda_version_from_findcuda} ${CUDA_VERSION_STRING})
  89. unset(CUDA_TOOLKIT_ROOT_DIR_INTERNAL CACHE)
  90. # Not strictly necessary, but for good luck.
  91. unset(CUDA_VERSION CACHE)
  92. # Error out
  93. message(FATAL_ERROR "FindCUDA says CUDA version is ${cuda_version_from_findcuda} (usually determined by nvcc), "
  94. "but the CUDA headers say the version is ${cuda_version_from_header}. This often occurs "
  95. "when you set both CUDA_HOME and CUDA_NVCC_EXECUTABLE to "
  96. "non-standard locations, without also setting PATH to point to the correct nvcc. "
  97. "Perhaps, try re-running this command again with PATH=${CUDA_TOOLKIT_ROOT_DIR}/bin:$PATH. "
  98. "See above log messages for more diagnostics, and see https://github.com/pytorch/pytorch/issues/8092 for more details.")
  99. endif()
  100. endif()
  101. endif()
  102. # Optionally, find TensorRT
  103. if(CAFFE2_USE_TENSORRT)
  104. find_path(TENSORRT_INCLUDE_DIR NvInfer.h
  105. HINTS ${TENSORRT_ROOT} ${CUDA_TOOLKIT_ROOT_DIR}
  106. PATH_SUFFIXES include)
  107. find_library(TENSORRT_LIBRARY nvinfer
  108. HINTS ${TENSORRT_ROOT} ${CUDA_TOOLKIT_ROOT_DIR}
  109. PATH_SUFFIXES lib lib64 lib/x64)
  110. find_package_handle_standard_args(
  111. TENSORRT DEFAULT_MSG TENSORRT_INCLUDE_DIR TENSORRT_LIBRARY)
  112. if(TENSORRT_FOUND)
  113. execute_process(COMMAND /bin/sh -c "[ -r \"${TENSORRT_INCLUDE_DIR}/NvInferVersion.h\" ] && awk '/^\#define NV_TENSORRT_MAJOR/ {print $3}' \"${TENSORRT_INCLUDE_DIR}/NvInferVersion.h\"" OUTPUT_VARIABLE TENSORRT_VERSION_MAJOR)
  114. execute_process(COMMAND /bin/sh -c "[ -r \"${TENSORRT_INCLUDE_DIR}/NvInferVersion.h\" ] && awk '/^\#define NV_TENSORRT_MINOR/ {print $3}' \"${TENSORRT_INCLUDE_DIR}/NvInferVersion.h\"" OUTPUT_VARIABLE TENSORRT_VERSION_MINOR)
  115. if(TENSORRT_VERSION_MAJOR)
  116. string(STRIP ${TENSORRT_VERSION_MAJOR} TENSORRT_VERSION_MAJOR)
  117. string(STRIP ${TENSORRT_VERSION_MINOR} TENSORRT_VERSION_MINOR)
  118. set(TENSORRT_VERSION "${TENSORRT_VERSION_MAJOR}.${TENSORRT_VERSION_MINOR}")
  119. #CAFFE2_USE_TRT is set in Dependencies
  120. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTENSORRT_VERSION_MAJOR=${TENSORRT_VERSION_MAJOR}")
  121. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTENSORRT_VERSION_MINOR=${TENSORRT_VERSION_MINOR}")
  122. else()
  123. message(WARNING "Caffe2: Cannot find ${TENSORRT_INCLUDE_DIR}/NvInferVersion.h. Assuming TRT 5.0 which is no longer supported. Turning the option off.")
  124. set(CAFFE2_USE_TENSORRT OFF)
  125. endif()
  126. else()
  127. message(WARNING
  128. "Caffe2: Cannot find TensorRT library. Turning the option off.")
  129. set(CAFFE2_USE_TENSORRT OFF)
  130. endif()
  131. endif()
  132. # ---[ CUDA libraries wrapper
  133. # find libcuda.so and lbnvrtc.so
  134. # For libcuda.so, we will find it under lib, lib64, and then the
  135. # stubs folder, in case we are building on a system that does not
  136. # have cuda driver installed. On windows, we also search under the
  137. # folder lib/x64.
  138. find_library(CUDA_CUDA_LIB cuda
  139. PATHS ${CUDA_TOOLKIT_ROOT_DIR}
  140. PATH_SUFFIXES lib lib64 lib/stubs lib64/stubs lib/x64)
  141. find_library(CUDA_NVRTC_LIB nvrtc
  142. PATHS ${CUDA_TOOLKIT_ROOT_DIR}
  143. PATH_SUFFIXES lib lib64 lib/x64)
  144. if(CUDA_NVRTC_LIB AND NOT CUDA_NVRTC_SHORTHASH)
  145. if("${PYTHON_EXECUTABLE}" STREQUAL "")
  146. set(_python_exe "python")
  147. else()
  148. set(_python_exe "${PYTHON_EXECUTABLE}")
  149. endif()
  150. execute_process(
  151. COMMAND "${_python_exe}" -c
  152. "import hashlib;hash=hashlib.sha256();hash.update(open('${CUDA_NVRTC_LIB}','rb').read());print(hash.hexdigest()[:8])"
  153. RESULT_VARIABLE _retval
  154. OUTPUT_VARIABLE CUDA_NVRTC_SHORTHASH)
  155. if(NOT _retval EQUAL 0)
  156. message(WARNING "Failed to compute shorthash for libnvrtc.so")
  157. set(CUDA_NVRTC_SHORTHASH "XXXXXXXX")
  158. else()
  159. string(STRIP "${CUDA_NVRTC_SHORTHASH}" CUDA_NVRTC_SHORTHASH)
  160. message(STATUS "${CUDA_NVRTC_LIB} shorthash is ${CUDA_NVRTC_SHORTHASH}")
  161. endif()
  162. endif()
  163. # Create new style imported libraries.
  164. # Several of these libraries have a hardcoded path if CAFFE2_STATIC_LINK_CUDA
  165. # is set. This path is where sane CUDA installations have their static
  166. # libraries installed. This flag should only be used for binary builds, so
  167. # end-users should never have this flag set.
  168. # cuda
  169. add_library(caffe2::cuda UNKNOWN IMPORTED)
  170. set_property(
  171. TARGET caffe2::cuda PROPERTY IMPORTED_LOCATION
  172. ${CUDA_CUDA_LIB})
  173. set_property(
  174. TARGET caffe2::cuda PROPERTY INTERFACE_INCLUDE_DIRECTORIES
  175. ${CUDA_INCLUDE_DIRS})
  176. # cudart. CUDA_LIBRARIES is actually a list, so we will make an interface
  177. # library.
  178. add_library(torch::cudart INTERFACE IMPORTED)
  179. if(CAFFE2_STATIC_LINK_CUDA)
  180. set_property(
  181. TARGET torch::cudart PROPERTY INTERFACE_LINK_LIBRARIES
  182. "${CUDA_cudart_static_LIBRARY}")
  183. if(NOT WIN32)
  184. set_property(
  185. TARGET torch::cudart APPEND PROPERTY INTERFACE_LINK_LIBRARIES
  186. rt dl)
  187. endif()
  188. else()
  189. set_property(
  190. TARGET torch::cudart PROPERTY INTERFACE_LINK_LIBRARIES
  191. ${CUDA_LIBRARIES})
  192. endif()
  193. set_property(
  194. TARGET torch::cudart PROPERTY INTERFACE_INCLUDE_DIRECTORIES
  195. ${CUDA_INCLUDE_DIRS})
  196. # nvToolsExt
  197. add_library(torch::nvtoolsext INTERFACE IMPORTED)
  198. if(MSVC)
  199. if(NOT NVTOOLEXT_HOME)
  200. set(NVTOOLEXT_HOME "C:/Program Files/NVIDIA Corporation/NvToolsExt")
  201. endif()
  202. if(DEFINED ENV{NVTOOLSEXT_PATH})
  203. set(NVTOOLEXT_HOME $ENV{NVTOOLSEXT_PATH})
  204. file(TO_CMAKE_PATH ${NVTOOLEXT_HOME} NVTOOLEXT_HOME)
  205. endif()
  206. set_target_properties(
  207. torch::nvtoolsext PROPERTIES
  208. INTERFACE_LINK_LIBRARIES ${NVTOOLEXT_HOME}/lib/x64/nvToolsExt64_1.lib
  209. INTERFACE_INCLUDE_DIRECTORIES ${NVTOOLEXT_HOME}/include)
  210. elseif(APPLE)
  211. set_property(
  212. TARGET torch::nvtoolsext PROPERTY INTERFACE_LINK_LIBRARIES
  213. ${CUDA_TOOLKIT_ROOT_DIR}/lib/libnvrtc.dylib
  214. ${CUDA_TOOLKIT_ROOT_DIR}/lib/libnvToolsExt.dylib)
  215. else()
  216. find_library(LIBNVTOOLSEXT libnvToolsExt.so PATHS ${CUDA_TOOLKIT_ROOT_DIR}/lib64/)
  217. set_property(
  218. TARGET torch::nvtoolsext PROPERTY INTERFACE_LINK_LIBRARIES
  219. ${LIBNVTOOLSEXT})
  220. endif()
  221. # cublas. CUDA_CUBLAS_LIBRARIES is actually a list, so we will make an
  222. # interface library similar to cudart.
  223. add_library(caffe2::cublas INTERFACE IMPORTED)
  224. if(CAFFE2_STATIC_LINK_CUDA AND NOT WIN32)
  225. set_property(
  226. TARGET caffe2::cublas PROPERTY INTERFACE_LINK_LIBRARIES
  227. ${CUDA_CUBLAS_LIBRARIES})
  228. # Add explicit dependency to cudart_static to fix
  229. # libcublasLt_static.a.o): undefined reference to symbol 'cudaStreamWaitEvent'
  230. # error adding symbols: DSO missing from command line
  231. set_property(
  232. TARGET caffe2::cublas APPEND PROPERTY INTERFACE_LINK_LIBRARIES
  233. "${CUDA_cudart_static_LIBRARY}" rt dl)
  234. else()
  235. set_property(
  236. TARGET caffe2::cublas PROPERTY INTERFACE_LINK_LIBRARIES
  237. ${CUDA_CUBLAS_LIBRARIES})
  238. endif()
  239. set_property(
  240. TARGET caffe2::cublas PROPERTY INTERFACE_INCLUDE_DIRECTORIES
  241. ${CUDA_INCLUDE_DIRS})
  242. # cudnn interface
  243. # static linking is handled by USE_STATIC_CUDNN environment variable
  244. if(CAFFE2_USE_CUDNN)
  245. if(USE_STATIC_CUDNN)
  246. set(CUDNN_STATIC ON CACHE BOOL "")
  247. else()
  248. set(CUDNN_STATIC OFF CACHE BOOL "")
  249. endif()
  250. find_package(CUDNN)
  251. if(NOT CUDNN_FOUND)
  252. message(WARNING
  253. "Cannot find cuDNN library. Turning the option off")
  254. set(CAFFE2_USE_CUDNN OFF)
  255. else()
  256. if(CUDNN_VERSION VERSION_LESS "8.0.0")
  257. message(FATAL_ERROR "PyTorch requires cuDNN 8 and above.")
  258. endif()
  259. endif()
  260. add_library(torch::cudnn INTERFACE IMPORTED)
  261. target_include_directories(torch::cudnn INTERFACE ${CUDNN_INCLUDE_PATH})
  262. if(CUDNN_STATIC AND NOT WIN32)
  263. target_link_options(torch::cudnn INTERFACE
  264. "-Wl,--exclude-libs,libcudnn_static.a")
  265. else()
  266. target_link_libraries(torch::cudnn INTERFACE ${CUDNN_LIBRARY_PATH})
  267. endif()
  268. else()
  269. message(STATUS "USE_CUDNN is set to 0. Compiling without cuDNN support")
  270. endif()
  271. # curand
  272. add_library(caffe2::curand UNKNOWN IMPORTED)
  273. if(CAFFE2_STATIC_LINK_CUDA AND NOT WIN32)
  274. set_property(
  275. TARGET caffe2::curand PROPERTY IMPORTED_LOCATION
  276. "${CUDA_TOOLKIT_ROOT_DIR}/lib64/libcurand_static.a")
  277. set_property(
  278. TARGET caffe2::curand PROPERTY INTERFACE_LINK_LIBRARIES
  279. "${CUDA_TOOLKIT_ROOT_DIR}/lib64/libculibos.a" dl)
  280. else()
  281. set_property(
  282. TARGET caffe2::curand PROPERTY IMPORTED_LOCATION
  283. ${CUDA_curand_LIBRARY})
  284. endif()
  285. set_property(
  286. TARGET caffe2::curand PROPERTY INTERFACE_INCLUDE_DIRECTORIES
  287. ${CUDA_INCLUDE_DIRS})
  288. # cufft. CUDA_CUFFT_LIBRARIES is actually a list, so we will make an
  289. # interface library similar to cudart.
  290. add_library(caffe2::cufft INTERFACE IMPORTED)
  291. if(CAFFE2_STATIC_LINK_CUDA AND NOT WIN32)
  292. set_property(
  293. TARGET caffe2::cufft PROPERTY INTERFACE_LINK_LIBRARIES
  294. "${CUDA_TOOLKIT_ROOT_DIR}/lib64/libcufft_static_nocallback.a"
  295. "${CUDA_TOOLKIT_ROOT_DIR}/lib64/libculibos.a" dl)
  296. else()
  297. set_property(
  298. TARGET caffe2::cufft PROPERTY INTERFACE_LINK_LIBRARIES
  299. ${CUDA_CUFFT_LIBRARIES})
  300. endif()
  301. set_property(
  302. TARGET caffe2::cufft PROPERTY INTERFACE_INCLUDE_DIRECTORIES
  303. ${CUDA_INCLUDE_DIRS})
  304. # TensorRT
  305. if(CAFFE2_USE_TENSORRT)
  306. add_library(caffe2::tensorrt UNKNOWN IMPORTED)
  307. set_property(
  308. TARGET caffe2::tensorrt PROPERTY IMPORTED_LOCATION
  309. ${TENSORRT_LIBRARY})
  310. set_property(
  311. TARGET caffe2::tensorrt PROPERTY INTERFACE_INCLUDE_DIRECTORIES
  312. ${TENSORRT_INCLUDE_DIR})
  313. endif()
  314. # nvrtc
  315. add_library(caffe2::nvrtc UNKNOWN IMPORTED)
  316. set_property(
  317. TARGET caffe2::nvrtc PROPERTY IMPORTED_LOCATION
  318. ${CUDA_NVRTC_LIB})
  319. set_property(
  320. TARGET caffe2::nvrtc PROPERTY INTERFACE_INCLUDE_DIRECTORIES
  321. ${CUDA_INCLUDE_DIRS})
  322. # Add onnx namepsace definition to nvcc
  323. if(ONNX_NAMESPACE)
  324. list(APPEND CUDA_NVCC_FLAGS "-DONNX_NAMESPACE=${ONNX_NAMESPACE}")
  325. else()
  326. list(APPEND CUDA_NVCC_FLAGS "-DONNX_NAMESPACE=onnx_c2")
  327. endif()
  328. # Don't activate VC env again for Ninja generators with MSVC on Windows if CUDAHOSTCXX is not defined
  329. # by adding --use-local-env.
  330. if(MSVC AND CMAKE_GENERATOR STREQUAL "Ninja" AND NOT DEFINED ENV{CUDAHOSTCXX})
  331. list(APPEND CUDA_NVCC_FLAGS "--use-local-env")
  332. endif()
  333. # setting nvcc arch flags
  334. torch_cuda_get_nvcc_gencode_flag(NVCC_FLAGS_EXTRA)
  335. # CMake 3.18 adds integrated support for architecture selection, but we can't rely on it
  336. set(CMAKE_CUDA_ARCHITECTURES OFF)
  337. list(APPEND CUDA_NVCC_FLAGS ${NVCC_FLAGS_EXTRA})
  338. message(STATUS "Added CUDA NVCC flags for: ${NVCC_FLAGS_EXTRA}")
  339. # disable some nvcc diagnostic that appears in boost, glog, glags, opencv, etc.
  340. foreach(diag cc_clobber_ignored integer_sign_change useless_using_declaration
  341. set_but_not_used field_without_dll_interface
  342. base_class_has_different_dll_interface
  343. dll_interface_conflict_none_assumed
  344. dll_interface_conflict_dllexport_assumed
  345. implicit_return_from_non_void_function
  346. unsigned_compare_with_zero
  347. declared_but_not_referenced
  348. bad_friend_decl)
  349. list(APPEND SUPPRESS_WARNING_FLAGS --diag_suppress=${diag})
  350. endforeach()
  351. string(REPLACE ";" "," SUPPRESS_WARNING_FLAGS "${SUPPRESS_WARNING_FLAGS}")
  352. list(APPEND CUDA_NVCC_FLAGS -Xcudafe ${SUPPRESS_WARNING_FLAGS})
  353. set(CUDA_PROPAGATE_HOST_FLAGS_BLOCKLIST "-Werror")
  354. if(MSVC)
  355. list(APPEND CUDA_NVCC_FLAGS "--Werror" "cross-execution-space-call")
  356. list(APPEND CUDA_NVCC_FLAGS "--no-host-device-move-forward")
  357. endif()
  358. # Debug and Release symbol support
  359. if(MSVC)
  360. if(${CAFFE2_USE_MSVC_STATIC_RUNTIME})
  361. string(APPEND CMAKE_CUDA_FLAGS_DEBUG " -Xcompiler /MTd")
  362. string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL " -Xcompiler /MT")
  363. string(APPEND CMAKE_CUDA_FLAGS_RELEASE " -Xcompiler /MT")
  364. string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO " -Xcompiler /MT")
  365. else()
  366. string(APPEND CMAKE_CUDA_FLAGS_DEBUG " -Xcompiler /MDd")
  367. string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL " -Xcompiler /MD")
  368. string(APPEND CMAKE_CUDA_FLAGS_RELEASE " -Xcompiler /MD")
  369. string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO " -Xcompiler /MD")
  370. endif()
  371. if(CUDA_NVCC_FLAGS MATCHES "Zi")
  372. list(APPEND CUDA_NVCC_FLAGS "-Xcompiler" "-FS")
  373. endif()
  374. elseif(CUDA_DEVICE_DEBUG)
  375. list(APPEND CUDA_NVCC_FLAGS "-g" "-G") # -G enables device code debugging symbols
  376. endif()
  377. # Set expt-relaxed-constexpr to suppress Eigen warnings
  378. list(APPEND CUDA_NVCC_FLAGS "--expt-relaxed-constexpr")
  379. # Set expt-extended-lambda to support lambda on device
  380. list(APPEND CUDA_NVCC_FLAGS "--expt-extended-lambda")
  381. foreach(FLAG ${CUDA_NVCC_FLAGS})
  382. string(FIND "${FLAG}" " " flag_space_position)
  383. if(NOT flag_space_position EQUAL -1)
  384. message(FATAL_ERROR "Found spaces in CUDA_NVCC_FLAGS entry '${FLAG}'")
  385. endif()
  386. string(APPEND CMAKE_CUDA_FLAGS " ${FLAG}")
  387. endforeach()