Support gstreamer as a backend of videoio module
[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 UNIX 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 "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_CUDNN)
41       set(CMAKE_MODULE_PATH "${OpenCV_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
42       find_host_package(CUDNN "${MIN_VER_CUDNN}")
43       list(REMOVE_AT CMAKE_MODULE_PATH 0)
44
45       if(CUDNN_FOUND)
46         set(HAVE_CUDNN 1)
47       endif()
48   endif()
49
50   if(WITH_NVCUVID)
51     find_cuda_helper_libs(nvcuvid)
52     if(WIN32)
53       find_cuda_helper_libs(nvcuvenc)
54     endif()
55     if(CUDA_nvcuvid_LIBRARY)
56       set(HAVE_NVCUVID 1)
57     endif()
58     if(CUDA_nvcuvenc_LIBRARY)
59       set(HAVE_NVCUVENC 1)
60     endif()
61   endif()
62
63   message(STATUS "CUDA detected: " ${CUDA_VERSION})
64
65   set(_generations "Fermi" "Kepler" "Maxwell" "Pascal" "Volta" "Turing")
66   if(NOT CMAKE_CROSSCOMPILING)
67     list(APPEND _generations "Auto")
68   endif()
69   set(CUDA_GENERATION "" CACHE STRING "Build CUDA device code only for specific GPU architecture. Leave empty to build for all architectures.")
70   if( CMAKE_VERSION VERSION_GREATER "2.8" )
71     set_property( CACHE CUDA_GENERATION PROPERTY STRINGS "" ${_generations} )
72   endif()
73
74   if(CUDA_GENERATION)
75     if(NOT ";${_generations};" MATCHES ";${CUDA_GENERATION};")
76       string(REPLACE ";" ", " _generations "${_generations}")
77       message(FATAL_ERROR "ERROR: ${_generations} Generations are suppered.")
78     endif()
79     unset(CUDA_ARCH_BIN CACHE)
80     unset(CUDA_ARCH_PTX CACHE)
81   endif()
82
83   SET(DETECT_ARCHS_COMMAND "${CUDA_NVCC_EXECUTABLE}" ${CUDA_NVCC_FLAGS} "${OpenCV_SOURCE_DIR}/cmake/checks/OpenCVDetectCudaArch.cu" "--run")
84   if(WIN32 AND CMAKE_LINKER) #Workaround for VS cl.exe not being in the env. path
85     get_filename_component(host_compiler_bindir ${CMAKE_LINKER} DIRECTORY)
86     SET(DETECT_ARCHS_COMMAND ${DETECT_ARCHS_COMMAND} "-ccbin" "${host_compiler_bindir}")
87   endif()
88
89   set(__cuda_arch_ptx "")
90   if(CUDA_GENERATION STREQUAL "Fermi")
91     set(__cuda_arch_bin "2.0")
92   elseif(CUDA_GENERATION STREQUAL "Kepler")
93     set(__cuda_arch_bin "3.0 3.5 3.7")
94   elseif(CUDA_GENERATION STREQUAL "Maxwell")
95     set(__cuda_arch_bin "5.0 5.2")
96   elseif(CUDA_GENERATION STREQUAL "Pascal")
97     set(__cuda_arch_bin "6.0 6.1")
98   elseif(CUDA_GENERATION STREQUAL "Volta")
99     set(__cuda_arch_bin "7.0")
100   elseif(CUDA_GENERATION STREQUAL "Turing")
101     set(__cuda_arch_bin "7.5")
102   elseif(CUDA_GENERATION STREQUAL "Auto")
103     execute_process( COMMAND ${DETECT_ARCHS_COMMAND}
104                      WORKING_DIRECTORY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/"
105                      RESULT_VARIABLE _nvcc_res OUTPUT_VARIABLE _nvcc_out
106                      ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
107     string(REGEX REPLACE ".*\n" "" _nvcc_out "${_nvcc_out}") #Strip leading warning messages, if any
108     if(NOT _nvcc_res EQUAL 0)
109       message(STATUS "Automatic detection of CUDA generation failed. Going to build for all known architectures.")
110     else()
111       set(__cuda_arch_bin "${_nvcc_out}")
112       string(REPLACE "2.1" "2.1(2.0)" __cuda_arch_bin "${__cuda_arch_bin}")
113     endif()
114   endif()
115
116   if(NOT DEFINED __cuda_arch_bin)
117     if(ARM)
118       set(__cuda_arch_bin "3.2")
119       set(__cuda_arch_ptx "")
120     elseif(AARCH64)
121       execute_process( COMMAND ${DETECT_ARCHS_COMMAND}
122                        WORKING_DIRECTORY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/"
123                        RESULT_VARIABLE _nvcc_res OUTPUT_VARIABLE _nvcc_out
124                        ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
125       string(REGEX REPLACE ".*\n" "" _nvcc_out "${_nvcc_out}") #Strip leading warning messages, if any
126       if(NOT _nvcc_res EQUAL 0)
127         message(STATUS "Automatic detection of CUDA generation failed. Going to build for all known architectures.")
128         set(__cuda_arch_bin "5.3 6.2 7.2")
129       else()
130         set(__cuda_arch_bin "${_nvcc_out}")
131         string(REPLACE "2.1" "2.1(2.0)" __cuda_arch_bin "${__cuda_arch_bin}")
132       endif()
133       set(__cuda_arch_ptx "")
134     else()
135       if(CUDA_VERSION VERSION_LESS "9.0")
136         set(__cuda_arch_bin "2.0 3.0 3.5 3.7 5.0 5.2 6.0 6.1")
137       elseif(CUDA_VERSION VERSION_LESS "10.0")
138         set(__cuda_arch_bin "3.0 3.5 3.7 5.0 5.2 6.0 6.1 7.0")
139       else()
140         set(__cuda_arch_bin "3.0 3.5 3.7 5.0 5.2 6.0 6.1 7.0 7.5")
141       endif()
142     endif()
143   endif()
144
145   set(CUDA_ARCH_BIN ${__cuda_arch_bin} CACHE STRING "Specify 'real' GPU architectures to build binaries for, BIN(PTX) format is supported")
146   set(CUDA_ARCH_PTX ${__cuda_arch_ptx} CACHE STRING "Specify 'virtual' PTX architectures to build PTX intermediate code for")
147
148   string(REGEX REPLACE "\\." "" ARCH_BIN_NO_POINTS "${CUDA_ARCH_BIN}")
149   string(REGEX REPLACE "\\." "" ARCH_PTX_NO_POINTS "${CUDA_ARCH_PTX}")
150
151   # Ckeck if user specified 1.0 compute capability: we don't support it
152   string(REGEX MATCH "1.0" HAS_ARCH_10 "${CUDA_ARCH_BIN} ${CUDA_ARCH_PTX}")
153   set(CUDA_ARCH_BIN_OR_PTX_10 0)
154   if(NOT ${HAS_ARCH_10} STREQUAL "")
155     set(CUDA_ARCH_BIN_OR_PTX_10 1)
156   endif()
157
158   # NVCC flags to be set
159   set(NVCC_FLAGS_EXTRA "")
160
161   # These vars will be passed into the templates
162   set(OPENCV_CUDA_ARCH_BIN "")
163   set(OPENCV_CUDA_ARCH_PTX "")
164   set(OPENCV_CUDA_ARCH_FEATURES "")
165
166   # Tell NVCC to add binaries for the specified GPUs
167   string(REGEX MATCHALL "[0-9()]+" ARCH_LIST "${ARCH_BIN_NO_POINTS}")
168   foreach(ARCH IN LISTS ARCH_LIST)
169     if(ARCH MATCHES "([0-9]+)\\(([0-9]+)\\)")
170       # User explicitly specified PTX for the concrete BIN
171       set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -gencode arch=compute_${CMAKE_MATCH_2},code=sm_${CMAKE_MATCH_1})
172       set(OPENCV_CUDA_ARCH_BIN "${OPENCV_CUDA_ARCH_BIN} ${CMAKE_MATCH_1}")
173       set(OPENCV_CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES} ${CMAKE_MATCH_2}")
174     else()
175       # User didn't explicitly specify PTX for the concrete BIN, we assume PTX=BIN
176       set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -gencode arch=compute_${ARCH},code=sm_${ARCH})
177       set(OPENCV_CUDA_ARCH_BIN "${OPENCV_CUDA_ARCH_BIN} ${ARCH}")
178       set(OPENCV_CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES} ${ARCH}")
179     endif()
180   endforeach()
181   set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -D_FORCE_INLINES)
182
183   # Tell NVCC to add PTX intermediate code for the specified architectures
184   string(REGEX MATCHALL "[0-9]+" ARCH_LIST "${ARCH_PTX_NO_POINTS}")
185   foreach(ARCH IN LISTS ARCH_LIST)
186     set(NVCC_FLAGS_EXTRA ${NVCC_FLAGS_EXTRA} -gencode arch=compute_${ARCH},code=compute_${ARCH})
187     set(OPENCV_CUDA_ARCH_PTX "${OPENCV_CUDA_ARCH_PTX} ${ARCH}")
188     set(OPENCV_CUDA_ARCH_FEATURES "${OPENCV_CUDA_ARCH_FEATURES} ${ARCH}")
189   endforeach()
190
191   # These vars will be processed in other scripts
192   set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} ${NVCC_FLAGS_EXTRA})
193   set(OpenCV_CUDA_CC "${NVCC_FLAGS_EXTRA}")
194
195   if(ANDROID)
196     set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xptxas;-dlcm=ca")
197   endif()
198
199   message(STATUS "CUDA NVCC target flags: ${CUDA_NVCC_FLAGS}")
200
201   OCV_OPTION(CUDA_FAST_MATH "Enable --use_fast_math for CUDA compiler " OFF)
202
203   if(CUDA_FAST_MATH)
204     set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} --use_fast_math)
205   endif()
206
207   mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_VERBOSE_BUILD CUDA_SDK_ROOT_DIR)
208
209   macro(ocv_cuda_filter_options)
210     foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG)
211       set(${var}_backup_in_cuda_compile_ "${${var}}")
212
213       if (CV_CLANG)
214         # we remove -Winconsistent-missing-override and -Qunused-arguments
215         # just in case we are compiling CUDA with gcc but OpenCV with clang
216         string(REPLACE "-Winconsistent-missing-override" "" ${var} "${${var}}")
217         string(REPLACE "-Qunused-arguments" "" ${var} "${${var}}")
218       endif()
219
220       # we remove /EHa as it generates warnings under windows
221       string(REPLACE "/EHa" "" ${var} "${${var}}")
222
223       # we remove -ggdb3 flag as it leads to preprocessor errors when compiling CUDA files (CUDA 4.1)
224       string(REPLACE "-ggdb3" "" ${var} "${${var}}")
225
226       # we remove -Wsign-promo as it generates warnings under linux
227       string(REPLACE "-Wsign-promo" "" ${var} "${${var}}")
228
229       # we remove -Wno-sign-promo as it generates warnings under linux
230       string(REPLACE "-Wno-sign-promo" "" ${var} "${${var}}")
231
232       # we remove -Wno-delete-non-virtual-dtor because it's used for C++ compiler
233       # but NVCC uses C compiler by default
234       string(REPLACE "-Wno-delete-non-virtual-dtor" "" ${var} "${${var}}")
235
236       # we remove -frtti because it's used for C++ compiler
237       # but NVCC uses C compiler by default
238       string(REPLACE "-frtti" "" ${var} "${${var}}")
239
240       string(REPLACE "-fvisibility-inlines-hidden" "" ${var} "${${var}}")
241
242       # cc1: warning: command line option '-Wsuggest-override' is valid for C++/ObjC++ but not for C
243       string(REPLACE "-Wsuggest-override" "" ${var} "${${var}}")
244
245       # issue: #11552 (from OpenCVCompilerOptions.cmake)
246       string(REGEX REPLACE "-Wimplicit-fallthrough(=[0-9]+)? " "" ${var} "${${var}}")
247
248       # removal of custom specified options
249       if(OPENCV_CUDA_NVCC_FILTEROUT_OPTIONS)
250         foreach(__flag ${OPENCV_CUDA_NVCC_FILTEROUT_OPTIONS})
251           string(REPLACE "${__flag}" "" ${var} "${${var}}")
252         endforeach()
253       endif()
254     endforeach()
255   endmacro()
256
257   macro(ocv_cuda_compile VAR)
258     ocv_cuda_filter_options()
259
260     if(BUILD_SHARED_LIBS)
261       set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler -DCVAPI_EXPORTS)
262     endif()
263
264     if(UNIX OR APPLE)
265       set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler -fPIC --std=c++11)
266     endif()
267     if(APPLE)
268       set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler -fno-finite-math-only)
269     endif()
270
271     if(CMAKE_CROSSCOMPILING AND (ARM OR AARCH64))
272       set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xlinker --unresolved-symbols=ignore-in-shared-libs)
273     endif()
274
275     # disabled because of multiple warnings during building nvcc auto generated files
276     if(CV_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.6.0")
277       ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-but-set-variable)
278     endif()
279
280     CUDA_COMPILE(${VAR} ${ARGN})
281
282     foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG)
283       set(${var} "${${var}_backup_in_cuda_compile_}")
284       unset(${var}_backup_in_cuda_compile_)
285     endforeach()
286   endmacro()
287 else()
288   unset(CUDA_ARCH_BIN CACHE)
289   unset(CUDA_ARCH_PTX CACHE)
290 endif()
291
292 if(HAVE_CUDA)
293   set(CUDA_LIBS_PATH "")
294   foreach(p ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
295     get_filename_component(_tmp ${p} PATH)
296     list(APPEND CUDA_LIBS_PATH ${_tmp})
297   endforeach()
298
299   if(HAVE_CUBLAS)
300     foreach(p ${CUDA_cublas_LIBRARY})
301       get_filename_component(_tmp ${p} PATH)
302       list(APPEND CUDA_LIBS_PATH ${_tmp})
303     endforeach()
304   endif()
305
306   if(HAVE_CUDNN)
307     foreach(p ${CUDNN_LIBRARIES})
308       get_filename_component(_tmp ${p} PATH)
309       list(APPEND CUDA_LIBS_PATH ${_tmp})
310     endforeach()
311   endif()
312
313   if(HAVE_CUFFT)
314     foreach(p ${CUDA_cufft_LIBRARY})
315       get_filename_component(_tmp ${p} PATH)
316       list(APPEND CUDA_LIBS_PATH ${_tmp})
317     endforeach()
318   endif()
319
320   list(REMOVE_DUPLICATES CUDA_LIBS_PATH)
321   link_directories(${CUDA_LIBS_PATH})
322
323   set(CUDA_LIBRARIES_ABS ${CUDA_LIBRARIES})
324   ocv_convert_to_lib_name(CUDA_LIBRARIES ${CUDA_LIBRARIES})
325   set(CUDA_npp_LIBRARY_ABS ${CUDA_npp_LIBRARY})
326   ocv_convert_to_lib_name(CUDA_npp_LIBRARY ${CUDA_npp_LIBRARY})
327   if(HAVE_CUBLAS)
328     set(CUDA_cublas_LIBRARY_ABS ${CUDA_cublas_LIBRARY})
329     ocv_convert_to_lib_name(CUDA_cublas_LIBRARY ${CUDA_cublas_LIBRARY})
330   endif()
331   if(HAVE_CUDNN)
332     set(CUDNN_LIBRARIES_ABS ${CUDNN_LIBRARIES})
333     ocv_convert_to_lib_name(CUDNN_LIBRARIES ${CUDNN_LIBRARIES})
334   endif()
335   if(HAVE_CUFFT)
336     set(CUDA_cufft_LIBRARY_ABS ${CUDA_cufft_LIBRARY})
337     ocv_convert_to_lib_name(CUDA_cufft_LIBRARY ${CUDA_cufft_LIBRARY})
338   endif()
339 endif()
340
341
342 # ----------------------------------------------------------------------------
343 # Add CUDA libraries (needed for apps/tools, samples)
344 # ----------------------------------------------------------------------------
345 if(HAVE_CUDA)
346   # details: https://github.com/NVIDIA/nvidia-docker/issues/775
347   if(" ${CUDA_CUDA_LIBRARY}" MATCHES "/stubs/libcuda.so" AND NOT OPENCV_SKIP_CUDA_STUB_WORKAROUND)
348     set(CUDA_STUB_ENABLED_LINK_WORKAROUND 1)
349     if(EXISTS "${CUDA_CUDA_LIBRARY}" AND NOT OPENCV_SKIP_CUDA_STUB_WORKAROUND_RPATH_LINK)
350       set(CUDA_STUB_TARGET_PATH "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/")
351       execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${CUDA_CUDA_LIBRARY}" "${CUDA_STUB_TARGET_PATH}/libcuda.so.1"
352           RESULT_VARIABLE CUDA_STUB_SYMLINK_RESULT)
353       if(NOT CUDA_STUB_SYMLINK_RESULT EQUAL 0)
354         execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CUDA_CUDA_LIBRARY}" "${CUDA_STUB_TARGET_PATH}/libcuda.so.1"
355           RESULT_VARIABLE CUDA_STUB_COPY_RESULT)
356         if(NOT CUDA_STUB_COPY_RESULT EQUAL 0)
357           set(CUDA_STUB_ENABLED_LINK_WORKAROUND 0)
358         endif()
359       endif()
360       if(CUDA_STUB_ENABLED_LINK_WORKAROUND)
361         set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath-link,\"${CUDA_STUB_TARGET_PATH}\"")
362       endif()
363     else()
364       set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--allow-shlib-undefined")
365     endif()
366     if(NOT CUDA_STUB_ENABLED_LINK_WORKAROUND)
367       message(WARNING "CUDA: workaround for stubs/libcuda.so.1 is not applied")
368     endif()
369   endif()
370
371   set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
372   if(HAVE_CUBLAS)
373     set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDA_cublas_LIBRARY})
374   endif()
375   if(HAVE_CUDNN)
376     set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDNN_LIBRARIES})
377   endif()
378   if(HAVE_CUFFT)
379     set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDA_cufft_LIBRARY})
380   endif()
381   foreach(p ${CUDA_LIBS_PATH})
382     if(MSVC AND CMAKE_GENERATOR MATCHES "Ninja|JOM")
383       set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CMAKE_LIBRARY_PATH_FLAG}"${p}")
384     else()
385       set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CMAKE_LIBRARY_PATH_FLAG}${p})
386     endif()
387   endforeach()
388 endif()