Merge remote-tracking branch 'upstream/3.4' into merge-3.4
[platform/upstream/opencv.git] / cmake / OpenCVDetectCUDA.cmake
1 if(WIN32 AND NOT MSVC)
2   message(STATUS "CUDA compilation is disabled (due to only Visual Studio compiler supported on your platform).")
3   return()
4 endif()
5
6 if(NOT APPLE AND CV_CLANG)
7   message(STATUS "CUDA compilation is disabled (due to Clang unsupported on your platform).")
8   return()
9 endif()
10
11
12 if(((NOT CMAKE_VERSION VERSION_LESS "3.9.0")  # requires https://gitlab.kitware.com/cmake/cmake/merge_requests/663
13       OR OPENCV_CUDA_FORCE_EXTERNAL_CMAKE_MODULE)
14     AND NOT OPENCV_CUDA_FORCE_BUILTIN_CMAKE_MODULE)
15   ocv_update(CUDA_LINK_LIBRARIES_KEYWORD "LINK_PRIVATE")
16   find_host_package(CUDA "${MIN_VER_CUDA}" QUIET)
17 else()
18   # Use OpenCV's patched "FindCUDA" module
19   set(CMAKE_MODULE_PATH "${OpenCV_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
20
21   if(ANDROID)
22     set(CUDA_TARGET_OS_VARIANT "Android")
23   endif()
24   find_host_package(CUDA "${MIN_VER_CUDA}" QUIET)
25
26   list(REMOVE_AT CMAKE_MODULE_PATH 0)
27 endif()
28
29 if(CUDA_FOUND)
30   set(HAVE_CUDA 1)
31
32   if(WITH_CUFFT)
33     set(HAVE_CUFFT 1)
34   endif()
35
36   if(WITH_CUBLAS)
37     set(HAVE_CUBLAS 1)
38   endif()
39
40   if(WITH_NVCUVID)
41     find_cuda_helper_libs(nvcuvid)
42     if(WIN32)
43       find_cuda_helper_libs(nvcuvenc)
44     endif()
45     if(CUDA_nvcuvid_LIBRARY)
46       set(HAVE_NVCUVID 1)
47     endif()
48     if(CUDA_nvcuvenc_LIBRARY)
49       set(HAVE_NVCUVENC 1)
50     endif()
51   endif()
52
53   message(STATUS "CUDA detected: " ${CUDA_VERSION})
54
55   set(_generations "Fermi" "Kepler" "Maxwell" "Pascal" "Volta")
56   if(NOT CMAKE_CROSSCOMPILING)
57     list(APPEND _generations "Auto")
58   endif()
59   set(CUDA_GENERATION "" CACHE STRING "Build CUDA device code only for specific GPU architecture. Leave empty to build for all architectures.")
60   if( CMAKE_VERSION VERSION_GREATER "2.8" )
61     set_property( CACHE CUDA_GENERATION PROPERTY STRINGS "" ${_generations} )
62   endif()
63
64   if(CUDA_GENERATION)
65     if(NOT ";${_generations};" MATCHES ";${CUDA_GENERATION};")
66       string(REPLACE ";" ", " _generations "${_generations}")
67       message(FATAL_ERROR "ERROR: ${_generations} Generations are suppered.")
68     endif()
69     unset(CUDA_ARCH_BIN CACHE)
70     unset(CUDA_ARCH_PTX CACHE)
71   endif()
72
73   set(__cuda_arch_ptx "")
74   if(CUDA_GENERATION STREQUAL "Fermi")
75     set(__cuda_arch_bin "2.0")
76   elseif(CUDA_GENERATION STREQUAL "Kepler")
77     set(__cuda_arch_bin "3.0 3.5 3.7")
78   elseif(CUDA_GENERATION STREQUAL "Maxwell")
79     set(__cuda_arch_bin "5.0 5.2")
80   elseif(CUDA_GENERATION STREQUAL "Pascal")
81     set(__cuda_arch_bin "6.0 6.1")
82   elseif(CUDA_GENERATION STREQUAL "Volta")
83     set(__cuda_arch_bin "7.0")
84   elseif(CUDA_GENERATION STREQUAL "Auto")
85     execute_process( COMMAND "${CUDA_NVCC_EXECUTABLE}" ${CUDA_NVCC_FLAGS} "${OpenCV_SOURCE_DIR}/cmake/checks/OpenCVDetectCudaArch.cu" "--run"
86                      WORKING_DIRECTORY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/"
87                      RESULT_VARIABLE _nvcc_res OUTPUT_VARIABLE _nvcc_out
88                      ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
89     if(NOT _nvcc_res EQUAL 0)
90       message(STATUS "Automatic detection of CUDA generation failed. Going to build for all known architectures.")
91     else()
92       set(__cuda_arch_bin "${_nvcc_out}")
93       string(REPLACE "2.1" "2.1(2.0)" __cuda_arch_bin "${__cuda_arch_bin}")
94     endif()
95   endif()
96
97   if(NOT DEFINED __cuda_arch_bin)
98     if(ARM)
99       set(__cuda_arch_bin "3.2")
100       set(__cuda_arch_ptx "")
101     elseif(AARCH64)
102       execute_process( COMMAND "${CUDA_NVCC_EXECUTABLE}" ${CUDA_NVCC_FLAGS} "${OpenCV_SOURCE_DIR}/cmake/checks/OpenCVDetectCudaArch.cu" "--run"
103                        WORKING_DIRECTORY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/"
104                        RESULT_VARIABLE _nvcc_res OUTPUT_VARIABLE _nvcc_out
105                        ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
106       if(NOT _nvcc_res EQUAL 0)
107         message(STATUS "Automatic detection of CUDA generation failed. Going to build for all known architectures.")
108         set(__cuda_arch_bin "5.3 6.2 7.0")
109       else()
110         set(__cuda_arch_bin "${_nvcc_out}")
111         string(REPLACE "2.1" "2.1(2.0)" __cuda_arch_bin "${__cuda_arch_bin}")
112       endif()
113       set(__cuda_arch_ptx "")
114     else()
115       if(${CUDA_VERSION} VERSION_LESS "9.0")
116         set(__cuda_arch_bin "2.0 3.0 3.5 3.7 5.0 5.2 6.0 6.1")
117       else()
118         set(__cuda_arch_bin "3.0 3.5 3.7 5.0 5.2 6.0 6.1 7.0")
119       endif()
120     endif()
121   endif()
122
123   set(CUDA_ARCH_BIN ${__cuda_arch_bin} CACHE STRING "Specify 'real' GPU architectures to build binaries for, BIN(PTX) format is supported")
124   set(CUDA_ARCH_PTX ${__cuda_arch_ptx} CACHE STRING "Specify 'virtual' PTX architectures to build PTX intermediate code for")
125
126   string(REGEX REPLACE "\\." "" ARCH_BIN_NO_POINTS "${CUDA_ARCH_BIN}")
127   string(REGEX REPLACE "\\." "" ARCH_PTX_NO_POINTS "${CUDA_ARCH_PTX}")
128
129   # Ckeck if user specified 1.0 compute capability: we don't support it
130   string(REGEX MATCH "1.0" HAS_ARCH_10 "${CUDA_ARCH_BIN} ${CUDA_ARCH_PTX}")
131   set(CUDA_ARCH_BIN_OR_PTX_10 0)
132   if(NOT ${HAS_ARCH_10} STREQUAL "")
133     set(CUDA_ARCH_BIN_OR_PTX_10 1)
134   endif()
135
136   # NVCC flags to be set
137   set(NVCC_FLAGS_EXTRA "")
138
139   # These vars will be passed into the templates
140   set(OPENCV_CUDA_ARCH_BIN "")
141   set(OPENCV_CUDA_ARCH_PTX "")
142   set(OPENCV_CUDA_ARCH_FEATURES "")
143
144   # Tell NVCC to add binaries for the specified GPUs
145   string(REGEX MATCHALL "[0-9()]+" ARCH_LIST "${ARCH_BIN_NO_POINTS}")
146   foreach(ARCH IN LISTS ARCH_LIST)
147     if(ARCH MATCHES "([0-9]+)\\(([0-9]+)\\)")
148       # User explicitly specified PTX for the concrete BIN
149       set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -gencode arch=compute_${CMAKE_MATCH_2},code=sm_${CMAKE_MATCH_1})
150       set(OPENCV_CUDA_ARCH_BIN "${OPENCV_CUDA_ARCH_BIN} ${CMAKE_MATCH_1}")
151       set(OPENCV_CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES} ${CMAKE_MATCH_2}")
152     else()
153       # User didn't explicitly specify PTX for the concrete BIN, we assume PTX=BIN
154       set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -gencode arch=compute_${ARCH},code=sm_${ARCH})
155       set(OPENCV_CUDA_ARCH_BIN "${OPENCV_CUDA_ARCH_BIN} ${ARCH}")
156       set(OPENCV_CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES} ${ARCH}")
157     endif()
158   endforeach()
159   set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -D_FORCE_INLINES)
160
161   # Tell NVCC to add PTX intermediate code for the specified architectures
162   string(REGEX MATCHALL "[0-9]+" ARCH_LIST "${ARCH_PTX_NO_POINTS}")
163   foreach(ARCH IN LISTS ARCH_LIST)
164     set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -gencode arch=compute_${ARCH},code=compute_${ARCH})
165     set(OPENCV_CUDA_ARCH_PTX "${OPENCV_CUDA_ARCH_PTX} ${ARCH}")
166     set(OPENCV_CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES} ${ARCH}")
167   endforeach()
168
169   # These vars will be processed in other scripts
170   set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} ${NVCC_FLAGS_EXTRA})
171   set(OpenCV_CUDA_CC "${NVCC_FLAGS_EXTRA}")
172
173   if(ANDROID)
174     set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xptxas;-dlcm=ca")
175   endif()
176
177   message(STATUS "CUDA NVCC target flags: ${CUDA_NVCC_FLAGS}")
178
179   OCV_OPTION(CUDA_FAST_MATH "Enable --use_fast_math for CUDA compiler " OFF)
180
181   if(CUDA_FAST_MATH)
182     set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} --use_fast_math)
183   endif()
184
185   mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_VERBOSE_BUILD CUDA_SDK_ROOT_DIR)
186
187   macro(ocv_cuda_filter_options)
188     foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG)
189       set(${var}_backup_in_cuda_compile_ "${${var}}")
190
191       # we remove /EHa as it generates warnings under windows
192       string(REPLACE "/EHa" "" ${var} "${${var}}")
193
194       # we remove -ggdb3 flag as it leads to preprocessor errors when compiling CUDA files (CUDA 4.1)
195       string(REPLACE "-ggdb3" "" ${var} "${${var}}")
196
197       # we remove -Wsign-promo as it generates warnings under linux
198       string(REPLACE "-Wsign-promo" "" ${var} "${${var}}")
199
200       # we remove -Wno-sign-promo as it generates warnings under linux
201       string(REPLACE "-Wno-sign-promo" "" ${var} "${${var}}")
202
203       # we remove -Wno-delete-non-virtual-dtor because it's used for C++ compiler
204       # but NVCC uses C compiler by default
205       string(REPLACE "-Wno-delete-non-virtual-dtor" "" ${var} "${${var}}")
206
207       # we remove -frtti because it's used for C++ compiler
208       # but NVCC uses C compiler by default
209       string(REPLACE "-frtti" "" ${var} "${${var}}")
210
211       string(REPLACE "-fvisibility-inlines-hidden" "" ${var} "${${var}}")
212
213       # cc1: warning: command line option '-Wsuggest-override' is valid for C++/ObjC++ but not for C
214       string(REPLACE "-Wsuggest-override" "" ${var} "${${var}}")
215
216       # issue: #11552 (from OpenCVCompilerOptions.cmake)
217       string(REGEX REPLACE "-Wimplicit-fallthrough(=[0-9]+)? " "" ${var} "${${var}}")
218
219       # removal of custom specified options
220       if(OPENCV_CUDA_NVCC_FILTEROUT_OPTIONS)
221         foreach(__flag ${OPENCV_CUDA_NVCC_FILTEROUT_OPTIONS})
222           string(REPLACE "${__flag}" "" ${var} "${${var}}")
223         endforeach()
224       endif()
225     endforeach()
226   endmacro()
227
228   macro(ocv_cuda_compile VAR)
229     ocv_cuda_filter_options()
230
231     if(BUILD_SHARED_LIBS)
232       set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler -DCVAPI_EXPORTS)
233     endif()
234
235     if(UNIX OR APPLE)
236       set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler -fPIC --std=c++11)
237     endif()
238     if(APPLE)
239       set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler -fno-finite-math-only)
240     endif()
241
242     if(CMAKE_CROSSCOMPILING AND (ARM OR AARCH64))
243       set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xlinker --unresolved-symbols=ignore-in-shared-libs)
244     endif()
245
246     # disabled because of multiple warnings during building nvcc auto generated files
247     if(CV_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.6.0")
248       ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-but-set-variable)
249     endif()
250
251     CUDA_COMPILE(${VAR} ${ARGN})
252
253     foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG)
254       set(${var} "${${var}_backup_in_cuda_compile_}")
255       unset(${var}_backup_in_cuda_compile_)
256     endforeach()
257   endmacro()
258 else()
259   unset(CUDA_ARCH_BIN CACHE)
260   unset(CUDA_ARCH_PTX CACHE)
261 endif()
262
263 if(HAVE_CUDA)
264   set(CUDA_LIBS_PATH "")
265   foreach(p ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
266     get_filename_component(_tmp ${p} PATH)
267     list(APPEND CUDA_LIBS_PATH ${_tmp})
268   endforeach()
269
270   if(HAVE_CUBLAS)
271     foreach(p ${CUDA_cublas_LIBRARY})
272       get_filename_component(_tmp ${p} PATH)
273       list(APPEND CUDA_LIBS_PATH ${_tmp})
274     endforeach()
275   endif()
276
277   if(HAVE_CUFFT)
278     foreach(p ${CUDA_cufft_LIBRARY})
279       get_filename_component(_tmp ${p} PATH)
280       list(APPEND CUDA_LIBS_PATH ${_tmp})
281     endforeach()
282   endif()
283
284   list(REMOVE_DUPLICATES CUDA_LIBS_PATH)
285   link_directories(${CUDA_LIBS_PATH})
286
287   set(CUDA_LIBRARIES_ABS ${CUDA_LIBRARIES})
288   ocv_convert_to_lib_name(CUDA_LIBRARIES ${CUDA_LIBRARIES})
289   set(CUDA_npp_LIBRARY_ABS ${CUDA_npp_LIBRARY})
290   ocv_convert_to_lib_name(CUDA_npp_LIBRARY ${CUDA_npp_LIBRARY})
291   if(HAVE_CUBLAS)
292     set(CUDA_cublas_LIBRARY_ABS ${CUDA_cublas_LIBRARY})
293     ocv_convert_to_lib_name(CUDA_cublas_LIBRARY ${CUDA_cublas_LIBRARY})
294   endif()
295
296   if(HAVE_CUFFT)
297     set(CUDA_cufft_LIBRARY_ABS ${CUDA_cufft_LIBRARY})
298     ocv_convert_to_lib_name(CUDA_cufft_LIBRARY ${CUDA_cufft_LIBRARY})
299   endif()
300 endif()