OpenCVDetectCUDA.cmake 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. if((WIN32 AND NOT MSVC) OR OPENCV_CMAKE_FORCE_CUDA)
  2. message(STATUS "CUDA compilation is disabled (due to only Visual Studio compiler supported on your platform).")
  3. return()
  4. endif()
  5. if((NOT UNIX AND CV_CLANG) OR OPENCV_CMAKE_FORCE_CUDA)
  6. message(STATUS "CUDA compilation is disabled (due to Clang unsupported on your platform).")
  7. return()
  8. endif()
  9. #set(OPENCV_CMAKE_CUDA_DEBUG 1)
  10. if(((NOT CMAKE_VERSION VERSION_LESS "3.9.0") # requires https://gitlab.kitware.com/cmake/cmake/merge_requests/663
  11. OR OPENCV_CUDA_FORCE_EXTERNAL_CMAKE_MODULE)
  12. AND NOT OPENCV_CUDA_FORCE_BUILTIN_CMAKE_MODULE)
  13. ocv_update(CUDA_LINK_LIBRARIES_KEYWORD "PRIVATE")
  14. find_host_package(CUDA "${MIN_VER_CUDA}" QUIET)
  15. else()
  16. # Use OpenCV's patched "FindCUDA" module
  17. set(CMAKE_MODULE_PATH "${OpenCV_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
  18. if(ANDROID)
  19. set(CUDA_TARGET_OS_VARIANT "Android")
  20. endif()
  21. find_host_package(CUDA "${MIN_VER_CUDA}" QUIET)
  22. list(REMOVE_AT CMAKE_MODULE_PATH 0)
  23. endif()
  24. if(CUDA_FOUND)
  25. set(HAVE_CUDA 1)
  26. if(NOT CUDA_VERSION VERSION_LESS 11.0)
  27. # CUDA 11.0 removes nppicom
  28. ocv_list_filterout(CUDA_nppi_LIBRARY "nppicom")
  29. ocv_list_filterout(CUDA_npp_LIBRARY "nppicom")
  30. endif()
  31. if(WITH_CUFFT)
  32. set(HAVE_CUFFT 1)
  33. endif()
  34. if(WITH_CUBLAS)
  35. set(HAVE_CUBLAS 1)
  36. endif()
  37. if(WITH_CUDNN)
  38. set(CMAKE_MODULE_PATH "${OpenCV_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
  39. find_host_package(CUDNN "${MIN_VER_CUDNN}")
  40. list(REMOVE_AT CMAKE_MODULE_PATH 0)
  41. if(CUDNN_FOUND)
  42. set(HAVE_CUDNN 1)
  43. endif()
  44. endif()
  45. if(WITH_NVCUVID)
  46. macro(ocv_cuda_SEARCH_NVCUVID_HEADER _filename _result)
  47. # place header file under CUDA_TOOLKIT_TARGET_DIR or CUDA_TOOLKIT_ROOT_DIR
  48. find_path(_header_result
  49. ${_filename}
  50. PATHS "${CUDA_TOOLKIT_TARGET_DIR}" "${CUDA_TOOLKIT_ROOT_DIR}"
  51. ENV CUDA_PATH
  52. ENV CUDA_INC_PATH
  53. PATH_SUFFIXES include
  54. NO_DEFAULT_PATH
  55. )
  56. if("x${_header_result}" STREQUAL "x_header_result-NOTFOUND")
  57. set(${_result} 0)
  58. else()
  59. set(${_result} 1)
  60. endif()
  61. unset(_header_result CACHE)
  62. endmacro()
  63. ocv_cuda_SEARCH_NVCUVID_HEADER("nvcuvid.h" HAVE_NVCUVID_HEADER)
  64. ocv_cuda_SEARCH_NVCUVID_HEADER("dynlink_nvcuvid.h" HAVE_DYNLINK_NVCUVID_HEADER)
  65. find_cuda_helper_libs(nvcuvid)
  66. if(WIN32)
  67. find_cuda_helper_libs(nvcuvenc)
  68. endif()
  69. if(CUDA_nvcuvid_LIBRARY AND (${HAVE_NVCUVID_HEADER} OR ${HAVE_DYNLINK_NVCUVID_HEADER}))
  70. # make sure to have both header and library before enabling
  71. set(HAVE_NVCUVID 1)
  72. endif()
  73. if(CUDA_nvcuvenc_LIBRARY)
  74. set(HAVE_NVCUVENC 1)
  75. endif()
  76. endif()
  77. message(STATUS "CUDA detected: " ${CUDA_VERSION})
  78. OCV_OPTION(CUDA_ENABLE_DEPRECATED_GENERATION "Enable deprecated generations in the list" OFF)
  79. set(_generations "Maxwell" "Pascal" "Volta" "Turing" "Ampere")
  80. if(CUDA_ENABLE_DEPRECATED_GENERATION)
  81. set(_generations "Fermi" "${_generations}")
  82. set(_generations "Kepler" "${_generations}")
  83. endif()
  84. set(_arch_fermi "2.0")
  85. set(_arch_kepler "3.0;3.5;3.7")
  86. set(_arch_maxwell "5.0;5.2")
  87. set(_arch_pascal "6.0;6.1")
  88. set(_arch_volta "7.0")
  89. set(_arch_turing "7.5")
  90. set(_arch_ampere "8.0;8.6")
  91. if(NOT CMAKE_CROSSCOMPILING)
  92. list(APPEND _generations "Auto")
  93. endif()
  94. set(CUDA_GENERATION "" CACHE STRING "Build CUDA device code only for specific GPU architecture. Leave empty to build for all architectures.")
  95. if( CMAKE_VERSION VERSION_GREATER "2.8" )
  96. set_property( CACHE CUDA_GENERATION PROPERTY STRINGS "" ${_generations} )
  97. endif()
  98. if(CUDA_GENERATION)
  99. if(NOT ";${_generations};" MATCHES ";${CUDA_GENERATION};")
  100. string(REPLACE ";" ", " _generations "${_generations}")
  101. message(FATAL_ERROR "ERROR: ${_generations} Generations are supported.")
  102. endif()
  103. unset(CUDA_ARCH_BIN CACHE)
  104. unset(CUDA_ARCH_PTX CACHE)
  105. endif()
  106. if(OPENCV_CUDA_DETECTION_NVCC_FLAGS MATCHES "-ccbin")
  107. # already specified by user
  108. elseif(CUDA_HOST_COMPILER AND EXISTS "${CUDA_HOST_COMPILER}")
  109. get_filename_component(c_compiler_realpath "${CMAKE_C_COMPILER}" REALPATH)
  110. # C compiler doesn't work with --run option, forcing C++ compiler instead
  111. if(CUDA_HOST_COMPILER STREQUAL c_compiler_realpath OR CUDA_HOST_COMPILER STREQUAL CMAKE_C_COMPILER)
  112. if(DEFINED CMAKE_CXX_COMPILER)
  113. get_filename_component(cxx_compiler_realpath "${CMAKE_CXX_COMPILER}" REALPATH)
  114. LIST(APPEND OPENCV_CUDA_DETECTION_NVCC_FLAGS -ccbin "${cxx_compiler_realpath}")
  115. else()
  116. message(STATUS "CUDA: CMAKE_CXX_COMPILER is not available. You may need to specify CUDA_HOST_COMPILER.")
  117. endif()
  118. else()
  119. LIST(APPEND OPENCV_CUDA_DETECTION_NVCC_FLAGS -ccbin "${CUDA_HOST_COMPILER}")
  120. endif()
  121. elseif(WIN32 AND CMAKE_LINKER) # Workaround for VS cl.exe not being in the env. path
  122. get_filename_component(host_compiler_bindir ${CMAKE_LINKER} DIRECTORY)
  123. LIST(APPEND OPENCV_CUDA_DETECTION_NVCC_FLAGS -ccbin "${host_compiler_bindir}")
  124. else()
  125. if(CUDA_HOST_COMPILER)
  126. message(STATUS "CUDA: CUDA_HOST_COMPILER='${CUDA_HOST_COMPILER}' is not valid, autodetection may not work. Specify OPENCV_CUDA_DETECTION_NVCC_FLAGS with -ccbin option for fix that")
  127. endif()
  128. endif()
  129. macro(ocv_filter_available_architecture result_list)
  130. set(__cache_key_check "${ARGN} : ${CUDA_NVCC_EXECUTABLE} ${OPENCV_CUDA_DETECTION_NVCC_FLAGS}")
  131. if(DEFINED OPENCV_CACHE_CUDA_SUPPORTED_CC AND OPENCV_CACHE_CUDA_SUPPORTED_CC_check STREQUAL __cache_key_check)
  132. set(${result_list} "${OPENCV_CACHE_CUDA_SUPPORTED_CC}")
  133. else()
  134. set(CC_LIST ${ARGN})
  135. foreach(target_arch ${CC_LIST})
  136. string(REPLACE "." "" target_arch_short "${target_arch}")
  137. set(NVCC_OPTION "-gencode;arch=compute_${target_arch_short},code=sm_${target_arch_short}")
  138. set(_cmd "${CUDA_NVCC_EXECUTABLE}" ${OPENCV_CUDA_DETECTION_NVCC_FLAGS} ${NVCC_OPTION} "${OpenCV_SOURCE_DIR}/cmake/checks/OpenCVDetectCudaArch.cu" --compile)
  139. execute_process(
  140. COMMAND ${_cmd}
  141. WORKING_DIRECTORY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/"
  142. RESULT_VARIABLE _nvcc_res
  143. OUTPUT_VARIABLE _nvcc_out
  144. ERROR_VARIABLE _nvcc_err
  145. #ERROR_QUIET
  146. OUTPUT_STRIP_TRAILING_WHITESPACE
  147. )
  148. if(OPENCV_CMAKE_CUDA_DEBUG)
  149. message(WARNING "COMMAND: ${_cmd}")
  150. message(STATUS "Result: ${_nvcc_res}")
  151. message(STATUS "Out: ${_nvcc_out}")
  152. message(STATUS "Err: ${_nvcc_err}")
  153. endif()
  154. if(_nvcc_res EQUAL 0)
  155. LIST(APPEND ${result_list} "${target_arch}")
  156. endif()
  157. endforeach()
  158. string(STRIP "${${result_list}}" ${result_list})
  159. if(" ${${result_list}}" STREQUAL " ")
  160. message(WARNING "CUDA: Autodetection arch list is empty. Please enable OPENCV_CMAKE_CUDA_DEBUG=1 and check/specify OPENCV_CUDA_DETECTION_NVCC_FLAGS variable")
  161. endif()
  162. # cache detected values
  163. set(OPENCV_CACHE_CUDA_SUPPORTED_CC ${${result_list}} CACHE INTERNAL "")
  164. set(OPENCV_CACHE_CUDA_SUPPORTED_CC_check "${__cache_key_check}" CACHE INTERNAL "")
  165. endif()
  166. endmacro()
  167. macro(ocv_detect_native_cuda_arch status output)
  168. set(OPENCV_CUDA_DETECT_ARCHS_COMMAND "${CUDA_NVCC_EXECUTABLE}" ${OPENCV_CUDA_DETECTION_NVCC_FLAGS} "${OpenCV_SOURCE_DIR}/cmake/checks/OpenCVDetectCudaArch.cu" "--run")
  169. set(__cache_key_check "${OPENCV_CUDA_DETECT_ARCHS_COMMAND}")
  170. if(DEFINED OPENCV_CACHE_CUDA_ACTIVE_CC AND OPENCV_CACHE_CUDA_ACTIVE_CC_check STREQUAL __cache_key_check)
  171. set(${output} "${OPENCV_CACHE_CUDA_ACTIVE_CC}")
  172. set(${status} 0)
  173. else()
  174. execute_process(
  175. COMMAND ${OPENCV_CUDA_DETECT_ARCHS_COMMAND}
  176. WORKING_DIRECTORY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/"
  177. RESULT_VARIABLE ${status}
  178. OUTPUT_VARIABLE _nvcc_out
  179. ERROR_VARIABLE _nvcc_err
  180. ERROR_QUIET
  181. OUTPUT_STRIP_TRAILING_WHITESPACE
  182. )
  183. if(OPENCV_CMAKE_CUDA_DEBUG)
  184. message(WARNING "COMMAND: ${OPENCV_CUDA_DETECT_ARCHS_COMMAND}")
  185. message(STATUS "Result: ${${status}}")
  186. message(STATUS "Out: ${_nvcc_out}")
  187. message(STATUS "Err: ${_nvcc_err}")
  188. endif()
  189. string(REGEX REPLACE ".*\n" "" ${output} "${_nvcc_out}") #Strip leading warning messages, if any
  190. if(${status} EQUAL 0)
  191. # cache detected values
  192. set(OPENCV_CACHE_CUDA_ACTIVE_CC ${${output}} CACHE INTERNAL "")
  193. set(OPENCV_CACHE_CUDA_ACTIVE_CC_check "${__cache_key_check}" CACHE INTERNAL "")
  194. endif()
  195. endif()
  196. endmacro()
  197. set(__cuda_arch_ptx "")
  198. if(CUDA_GENERATION STREQUAL "Fermi")
  199. set(__cuda_arch_bin ${_arch_fermi})
  200. elseif(CUDA_GENERATION STREQUAL "Kepler")
  201. set(__cuda_arch_bin ${_arch_kepler})
  202. elseif(CUDA_GENERATION STREQUAL "Maxwell")
  203. set(__cuda_arch_bin ${_arch_maxwell})
  204. elseif(CUDA_GENERATION STREQUAL "Pascal")
  205. set(__cuda_arch_bin ${_arch_pascal})
  206. elseif(CUDA_GENERATION STREQUAL "Volta")
  207. set(__cuda_arch_bin ${_arch_volta})
  208. elseif(CUDA_GENERATION STREQUAL "Turing")
  209. set(__cuda_arch_bin ${_arch_turing})
  210. elseif(CUDA_GENERATION STREQUAL "Ampere")
  211. set(__cuda_arch_bin ${_arch_ampere})
  212. elseif(CUDA_GENERATION STREQUAL "Auto")
  213. ocv_detect_native_cuda_arch(_nvcc_res _nvcc_out)
  214. if(NOT _nvcc_res EQUAL 0)
  215. message(STATUS "Automatic detection of CUDA generation failed. Going to build for all known architectures.")
  216. else()
  217. string(REGEX MATCHALL "[0-9]+\\.[0-9]" __cuda_arch_bin "${_nvcc_out}")
  218. endif()
  219. elseif(CUDA_ARCH_BIN)
  220. message(STATUS "CUDA: Using CUDA_ARCH_BIN=${CUDA_ARCH_BIN}")
  221. set(__cuda_arch_bin ${CUDA_ARCH_BIN})
  222. endif()
  223. if(NOT DEFINED __cuda_arch_bin)
  224. if(ARM)
  225. set(__cuda_arch_bin "3.2")
  226. set(__cuda_arch_ptx "")
  227. elseif(AARCH64)
  228. if(NOT CMAKE_CROSSCOMPILING)
  229. ocv_detect_native_cuda_arch(_nvcc_res _nvcc_out)
  230. else()
  231. set(_nvcc_res -1) # emulate error, see below
  232. endif()
  233. if(NOT _nvcc_res EQUAL 0)
  234. message(STATUS "Automatic detection of CUDA generation failed. Going to build for all known architectures.")
  235. # TX1 (5.3) TX2 (6.2) Xavier (7.2) V100 (7.0)
  236. ocv_filter_available_architecture(__cuda_arch_bin
  237. 5.3
  238. 6.2
  239. 7.2
  240. 7.0
  241. )
  242. else()
  243. set(__cuda_arch_bin "${_nvcc_out}")
  244. endif()
  245. set(__cuda_arch_ptx "")
  246. else()
  247. ocv_filter_available_architecture(__cuda_arch_bin
  248. ${_arch_fermi}
  249. ${_arch_kepler}
  250. ${_arch_maxwell}
  251. ${_arch_pascal}
  252. ${_arch_volta}
  253. ${_arch_turing}
  254. ${_arch_ampere}
  255. )
  256. endif()
  257. endif()
  258. set(CUDA_ARCH_BIN ${__cuda_arch_bin} CACHE STRING "Specify 'real' GPU architectures to build binaries for, BIN(PTX) format is supported")
  259. set(CUDA_ARCH_PTX ${__cuda_arch_ptx} CACHE STRING "Specify 'virtual' PTX architectures to build PTX intermediate code for")
  260. string(REGEX REPLACE "\\." "" ARCH_BIN_NO_POINTS "${CUDA_ARCH_BIN}")
  261. string(REGEX REPLACE "\\." "" ARCH_PTX_NO_POINTS "${CUDA_ARCH_PTX}")
  262. # Check if user specified 1.0/2.1 compute capability: we don't support it
  263. macro(ocv_wipeout_deprecated_cc target_cc)
  264. if(" ${CUDA_ARCH_BIN} ${CUDA_ARCH_PTX}" MATCHES " ${target_cc}")
  265. message(SEND_ERROR "CUDA: ${target_cc} compute capability is not supported - exclude it from ARCH/PTX list and re-run CMake")
  266. endif()
  267. endmacro()
  268. ocv_wipeout_deprecated_cc("1.0")
  269. ocv_wipeout_deprecated_cc("2.1")
  270. # NVCC flags to be set
  271. set(NVCC_FLAGS_EXTRA "")
  272. # These vars will be passed into the templates
  273. set(OPENCV_CUDA_ARCH_BIN "")
  274. set(OPENCV_CUDA_ARCH_PTX "")
  275. set(OPENCV_CUDA_ARCH_FEATURES "")
  276. # Tell NVCC to add binaries for the specified GPUs
  277. string(REGEX MATCHALL "[0-9()]+" ARCH_LIST "${ARCH_BIN_NO_POINTS}")
  278. foreach(ARCH IN LISTS ARCH_LIST)
  279. if(ARCH MATCHES "([0-9]+)\\(([0-9]+)\\)")
  280. # User explicitly specified PTX for the concrete BIN
  281. set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -gencode arch=compute_${CMAKE_MATCH_2},code=sm_${CMAKE_MATCH_1})
  282. set(OPENCV_CUDA_ARCH_BIN "${OPENCV_CUDA_ARCH_BIN} ${CMAKE_MATCH_1}")
  283. set(OPENCV_CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES} ${CMAKE_MATCH_2}")
  284. else()
  285. # User didn't explicitly specify PTX for the concrete BIN, we assume PTX=BIN
  286. set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -gencode arch=compute_${ARCH},code=sm_${ARCH})
  287. set(OPENCV_CUDA_ARCH_BIN "${OPENCV_CUDA_ARCH_BIN} ${ARCH}")
  288. set(OPENCV_CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES} ${ARCH}")
  289. endif()
  290. endforeach()
  291. set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -D_FORCE_INLINES)
  292. # Tell NVCC to add PTX intermediate code for the specified architectures
  293. string(REGEX MATCHALL "[0-9]+" ARCH_LIST "${ARCH_PTX_NO_POINTS}")
  294. foreach(ARCH IN LISTS ARCH_LIST)
  295. set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -gencode arch=compute_${ARCH},code=compute_${ARCH})
  296. set(OPENCV_CUDA_ARCH_PTX "${OPENCV_CUDA_ARCH_PTX} ${ARCH}")
  297. set(OPENCV_CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES} ${ARCH}")
  298. endforeach()
  299. # These vars will be processed in other scripts
  300. set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} ${NVCC_FLAGS_EXTRA})
  301. set(OpenCV_CUDA_CC "${NVCC_FLAGS_EXTRA}")
  302. if(ANDROID)
  303. set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xptxas;-dlcm=ca")
  304. endif()
  305. message(STATUS "CUDA NVCC target flags: ${CUDA_NVCC_FLAGS}")
  306. OCV_OPTION(CUDA_FAST_MATH "Enable --use_fast_math for CUDA compiler " OFF)
  307. if(CUDA_FAST_MATH)
  308. set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} --use_fast_math)
  309. endif()
  310. mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_VERBOSE_BUILD CUDA_SDK_ROOT_DIR)
  311. macro(ocv_cuda_filter_options)
  312. foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG)
  313. set(${var}_backup_in_cuda_compile_ "${${var}}")
  314. if (CV_CLANG)
  315. # we remove -Winconsistent-missing-override and -Qunused-arguments
  316. # just in case we are compiling CUDA with gcc but OpenCV with clang
  317. string(REPLACE "-Winconsistent-missing-override" "" ${var} "${${var}}")
  318. string(REPLACE "-Qunused-arguments" "" ${var} "${${var}}")
  319. endif()
  320. # we remove /EHa as it generates warnings under windows
  321. string(REPLACE "/EHa" "" ${var} "${${var}}")
  322. # we remove -ggdb3 flag as it leads to preprocessor errors when compiling CUDA files (CUDA 4.1)
  323. string(REPLACE "-ggdb3" "" ${var} "${${var}}")
  324. # we remove -Wsign-promo as it generates warnings under linux
  325. string(REPLACE "-Wsign-promo" "" ${var} "${${var}}")
  326. # we remove -Wno-sign-promo as it generates warnings under linux
  327. string(REPLACE "-Wno-sign-promo" "" ${var} "${${var}}")
  328. # we remove -Wno-delete-non-virtual-dtor because it's used for C++ compiler
  329. # but NVCC uses C compiler by default
  330. string(REPLACE "-Wno-delete-non-virtual-dtor" "" ${var} "${${var}}")
  331. # we remove -frtti because it's used for C++ compiler
  332. # but NVCC uses C compiler by default
  333. string(REPLACE "-frtti" "" ${var} "${${var}}")
  334. string(REPLACE "-fvisibility-inlines-hidden" "" ${var} "${${var}}")
  335. # cc1: warning: command line option '-Wsuggest-override' is valid for C++/ObjC++ but not for C
  336. string(REPLACE "-Wsuggest-override" "" ${var} "${${var}}")
  337. # issue: #11552 (from OpenCVCompilerOptions.cmake)
  338. string(REGEX REPLACE "-Wimplicit-fallthrough(=[0-9]+)? " "" ${var} "${${var}}")
  339. # removal of custom specified options
  340. if(OPENCV_CUDA_NVCC_FILTEROUT_OPTIONS)
  341. foreach(__flag ${OPENCV_CUDA_NVCC_FILTEROUT_OPTIONS})
  342. string(REPLACE "${__flag}" "" ${var} "${${var}}")
  343. endforeach()
  344. endif()
  345. endforeach()
  346. endmacro()
  347. macro(ocv_cuda_compile VAR)
  348. ocv_cuda_filter_options()
  349. if(BUILD_SHARED_LIBS)
  350. set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler -DCVAPI_EXPORTS)
  351. endif()
  352. if(UNIX OR APPLE)
  353. set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler -fPIC)
  354. if(NOT " ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_DEBUG} ${CUDA_NVCC_FLAGS}" MATCHES "-std=")
  355. if(CUDA_VERSION VERSION_LESS "11.0")
  356. list(APPEND CUDA_NVCC_FLAGS "--std=c++11")
  357. else()
  358. list(APPEND CUDA_NVCC_FLAGS "--std=c++14")
  359. endif()
  360. endif()
  361. endif()
  362. if(APPLE)
  363. set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler -fno-finite-math-only)
  364. endif()
  365. if(CMAKE_CROSSCOMPILING AND (ARM OR AARCH64))
  366. set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xlinker --unresolved-symbols=ignore-in-shared-libs)
  367. endif()
  368. # disabled because of multiple warnings during building nvcc auto generated files
  369. if(CV_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.6.0")
  370. ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-but-set-variable)
  371. endif()
  372. CUDA_COMPILE(${VAR} ${ARGN})
  373. foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG)
  374. set(${var} "${${var}_backup_in_cuda_compile_}")
  375. unset(${var}_backup_in_cuda_compile_)
  376. endforeach()
  377. endmacro()
  378. else()
  379. unset(CUDA_ARCH_BIN CACHE)
  380. unset(CUDA_ARCH_PTX CACHE)
  381. endif()
  382. if(HAVE_CUDA)
  383. set(CUDA_LIBS_PATH "")
  384. foreach(p ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
  385. get_filename_component(_tmp ${p} PATH)
  386. list(APPEND CUDA_LIBS_PATH ${_tmp})
  387. endforeach()
  388. if(HAVE_CUBLAS)
  389. foreach(p ${CUDA_cublas_LIBRARY})
  390. get_filename_component(_tmp ${p} PATH)
  391. list(APPEND CUDA_LIBS_PATH ${_tmp})
  392. endforeach()
  393. endif()
  394. if(HAVE_CUDNN)
  395. foreach(p ${CUDNN_LIBRARIES})
  396. get_filename_component(_tmp ${p} PATH)
  397. list(APPEND CUDA_LIBS_PATH ${_tmp})
  398. endforeach()
  399. endif()
  400. if(HAVE_CUFFT)
  401. foreach(p ${CUDA_cufft_LIBRARY})
  402. get_filename_component(_tmp ${p} PATH)
  403. list(APPEND CUDA_LIBS_PATH ${_tmp})
  404. endforeach()
  405. endif()
  406. list(REMOVE_DUPLICATES CUDA_LIBS_PATH)
  407. link_directories(${CUDA_LIBS_PATH})
  408. set(CUDA_LIBRARIES_ABS ${CUDA_LIBRARIES})
  409. ocv_convert_to_lib_name(CUDA_LIBRARIES ${CUDA_LIBRARIES})
  410. set(CUDA_npp_LIBRARY_ABS ${CUDA_npp_LIBRARY})
  411. ocv_convert_to_lib_name(CUDA_npp_LIBRARY ${CUDA_npp_LIBRARY})
  412. if(HAVE_CUBLAS)
  413. set(CUDA_cublas_LIBRARY_ABS ${CUDA_cublas_LIBRARY})
  414. ocv_convert_to_lib_name(CUDA_cublas_LIBRARY ${CUDA_cublas_LIBRARY})
  415. endif()
  416. if(HAVE_CUDNN)
  417. set(CUDNN_LIBRARIES_ABS ${CUDNN_LIBRARIES})
  418. ocv_convert_to_lib_name(CUDNN_LIBRARIES ${CUDNN_LIBRARIES})
  419. endif()
  420. if(HAVE_CUFFT)
  421. set(CUDA_cufft_LIBRARY_ABS ${CUDA_cufft_LIBRARY})
  422. ocv_convert_to_lib_name(CUDA_cufft_LIBRARY ${CUDA_cufft_LIBRARY})
  423. endif()
  424. if(CMAKE_GENERATOR MATCHES "Visual Studio"
  425. AND NOT OPENCV_SKIP_CUDA_CMAKE_SUPPRESS_REGENERATION
  426. )
  427. message(STATUS "CUDA: MSVS generator is detected. Disabling CMake re-run checks (CMAKE_SUPPRESS_REGENERATION=ON). You need to run CMake manually if updates are required.")
  428. set(CMAKE_SUPPRESS_REGENERATION ON)
  429. endif()
  430. endif()
  431. # ----------------------------------------------------------------------------
  432. # Add CUDA libraries (needed for apps/tools, samples)
  433. # ----------------------------------------------------------------------------
  434. if(HAVE_CUDA)
  435. # details: https://github.com/NVIDIA/nvidia-docker/issues/775
  436. if(" ${CUDA_CUDA_LIBRARY}" MATCHES "/stubs/libcuda.so" AND NOT OPENCV_SKIP_CUDA_STUB_WORKAROUND)
  437. set(CUDA_STUB_ENABLED_LINK_WORKAROUND 1)
  438. if(EXISTS "${CUDA_CUDA_LIBRARY}" AND NOT OPENCV_SKIP_CUDA_STUB_WORKAROUND_RPATH_LINK)
  439. set(CUDA_STUB_TARGET_PATH "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/")
  440. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${CUDA_CUDA_LIBRARY}" "${CUDA_STUB_TARGET_PATH}/libcuda.so.1"
  441. RESULT_VARIABLE CUDA_STUB_SYMLINK_RESULT)
  442. if(NOT CUDA_STUB_SYMLINK_RESULT EQUAL 0)
  443. execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CUDA_CUDA_LIBRARY}" "${CUDA_STUB_TARGET_PATH}/libcuda.so.1"
  444. RESULT_VARIABLE CUDA_STUB_COPY_RESULT)
  445. if(NOT CUDA_STUB_COPY_RESULT EQUAL 0)
  446. set(CUDA_STUB_ENABLED_LINK_WORKAROUND 0)
  447. endif()
  448. endif()
  449. if(CUDA_STUB_ENABLED_LINK_WORKAROUND)
  450. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath-link,\"${CUDA_STUB_TARGET_PATH}\"")
  451. endif()
  452. else()
  453. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--allow-shlib-undefined")
  454. endif()
  455. if(NOT CUDA_STUB_ENABLED_LINK_WORKAROUND)
  456. message(WARNING "CUDA: workaround for stubs/libcuda.so.1 is not applied")
  457. endif()
  458. endif()
  459. set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
  460. if(HAVE_CUBLAS)
  461. set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDA_cublas_LIBRARY})
  462. endif()
  463. if(HAVE_CUDNN)
  464. set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDNN_LIBRARIES})
  465. endif()
  466. if(HAVE_CUFFT)
  467. set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDA_cufft_LIBRARY})
  468. endif()
  469. foreach(p ${CUDA_LIBS_PATH})
  470. if(MSVC AND CMAKE_GENERATOR MATCHES "Ninja|JOM")
  471. set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CMAKE_LIBRARY_PATH_FLAG}"${p}")
  472. else()
  473. set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CMAKE_LIBRARY_PATH_FLAG}${p})
  474. endif()
  475. endforeach()
  476. endif()