OpenCVFindLAPACK.cmake 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  2. set(_apple_device_min_target_os_version "13.3")
  3. elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  4. set(_apple_device_min_target_os_version "16.4")
  5. elseif(CMAKE_SYSTEM_NAME STREQUAL "watchOS")
  6. set(_apple_device_min_target_os_version "9.4")
  7. elseif(CMAKE_SYSTEM_NAME STREQUAL "tvOS")
  8. set(_apple_device_min_target_os_version "16.4")
  9. elseif(CMAKE_SYSTEM_NAME STREQUAL "visionOS")
  10. set(_apple_device_min_target_os_version "1.0")
  11. endif()
  12. if(DEFINED _apple_device_min_target_os_version AND
  13. ("${CMAKE_OSX_DEPLOYMENT_TARGET}" VERSION_GREATER "${_apple_device_min_target_os_version}" OR
  14. "${CMAKE_OSX_DEPLOYMENT_TARGET}" VERSION_EQUAL "${_apple_device_min_target_os_version}"))
  15. set(_apple_device_has_required_min_os_version ON)
  16. else()
  17. set(_apple_device_has_required_min_os_version OFF)
  18. endif()
  19. OCV_OPTION(OPENCV_OSX_USE_ACCELERATE_NEW_LAPACK "Use new BLAS/LAPACK interfaces from Accelerate framework on Apple platform" _apple_device_has_required_min_os_version
  20. VISIBLE_IF APPLE)
  21. macro(_find_header_file_in_dirs VAR NAME)
  22. unset(${VAR})
  23. unset(${VAR} CACHE)
  24. if(" ${ARGN}" STREQUAL " ")
  25. check_include_file("${NAME}" HAVE_${VAR})
  26. if(HAVE_${VAR})
  27. set(${VAR} "${NAME}") # fallback
  28. else()
  29. set(${VAR} "")
  30. endif()
  31. else()
  32. find_path(${VAR} "${NAME}" ${ARGN} NO_DEFAULT_PATH)
  33. if(${VAR})
  34. set(${VAR} "${${VAR}}/${NAME}")
  35. unset(${VAR} CACHE)
  36. else()
  37. unset(${VAR} CACHE)
  38. set(${VAR} "")
  39. endif()
  40. endif()
  41. endmacro()
  42. macro(ocv_lapack_check)
  43. cmake_parse_arguments(LAPACK "" "IMPL;CBLAS_H;LAPACKE_H" "INCLUDE_DIR;LIBRARIES" ${ARGN})
  44. ocv_debug_message("LAPACK_IMPL=${LAPACK_IMPL}")
  45. ocv_debug_message("LAPACK_CBLAS_H=${LAPACK_CBLAS_H}")
  46. ocv_debug_message("LAPACK_LAPACKE_H=${LAPACK_LAPACKE_H}")
  47. ocv_debug_message("LAPACK_INCLUDE_DIR=${LAPACK_INCLUDE_DIR}")
  48. ocv_debug_message("LAPACK_LIBRARIES=${LAPACK_LIBRARIES}")
  49. string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" _lapack_impl "${LAPACK_IMPL}")
  50. message(STATUS "LAPACK(${LAPACK_IMPL}): LAPACK_LIBRARIES: ${LAPACK_LIBRARIES}")
  51. _find_header_file_in_dirs(OPENCV_CBLAS_H_PATH_${_lapack_impl} "${LAPACK_CBLAS_H}" "${LAPACK_INCLUDE_DIR}")
  52. _find_header_file_in_dirs(OPENCV_LAPACKE_H_PATH_${_lapack_impl} "${LAPACK_LAPACKE_H}" "${LAPACK_INCLUDE_DIR}")
  53. if(NOT OPENCV_CBLAS_H_PATH_${_lapack_impl} OR NOT OPENCV_LAPACKE_H_PATH_${_lapack_impl})
  54. message(WARNING "LAPACK(${LAPACK_IMPL}): CBLAS/LAPACK headers are not found in '${LAPACK_INCLUDE_DIR}'")
  55. unset(LAPACK_LIBRARIES)
  56. else()
  57. # adding proxy opencv_lapack.h header
  58. set(CBLAS_H_PROXY_PATH ${CMAKE_BINARY_DIR}/opencv_lapack.h)
  59. set(_lapack_add_extern_c NOT (APPLE OR OPENCV_SKIP_LAPACK_EXTERN_C) OR OPENCV_FORCE_LAPACK_EXTERN_C)
  60. set(_lapack_content "// This file is auto-generated\n")
  61. if(${_lapack_add_extern_c})
  62. list(APPEND _lapack_content "extern \"C\" {")
  63. endif()
  64. if(NOT OPENCV_SKIP_LAPACK_MSVC_FIX)
  65. list(APPEND _lapack_content "
  66. #ifdef _MSC_VER
  67. #include <complex.h>
  68. #define lapack_complex_float _Fcomplex
  69. #define lapack_complex_double _Dcomplex
  70. #endif
  71. ")
  72. endif()
  73. list(APPEND _lapack_content "#include \"${OPENCV_CBLAS_H_PATH_${_lapack_impl}}\"")
  74. if(NOT "${OPENCV_CBLAS_H_PATH_${_lapack_impl}}" STREQUAL "${OPENCV_LAPACKE_H_PATH_${_lapack_impl}}")
  75. list(APPEND _lapack_content "#include \"${OPENCV_LAPACKE_H_PATH_${_lapack_impl}}\"")
  76. endif()
  77. list(APPEND _lapack_content "
  78. #if defined(LAPACK_GLOBAL) || defined(LAPACK_NAME)
  79. /*
  80. * Using netlib's reference LAPACK implementation version >= 3.4.0 (first with C interface).
  81. * Use LAPACK_xxxx to transparently (via predefined lapack macros) deal with pre and post 3.9.1 versions.
  82. * LAPACK 3.9.1 introduces LAPACK_FORTRAN_STRLEN_END and modifies (through preprocessing) the declarations of the following functions used in opencv
  83. * sposv_, dposv_, spotrf_, dpotrf_, sgesdd_, dgesdd_, sgels_, dgels_
  84. * which end up with an extra parameter.
  85. * So we also need to preprocess the function calls in opencv coding by prefixing them with LAPACK_.
  86. * The good news is the preprocessing works fine whatever netlib's LAPACK version.
  87. */
  88. #define OCV_LAPACK_FUNC(f) LAPACK_##f
  89. #else
  90. /* Using other LAPACK implementations so fall back to opencv's assumption until now */
  91. #define OCV_LAPACK_FUNC(f) f##_
  92. #endif
  93. ")
  94. if(${_lapack_add_extern_c})
  95. list(APPEND _lapack_content "}")
  96. endif()
  97. string(REPLACE ";" "\n" _lapack_content "${_lapack_content}")
  98. ocv_update_file("${CBLAS_H_PROXY_PATH}" "${_lapack_content}")
  99. if(CMAKE_GENERATOR MATCHES "Visual Studio" # MSBuild
  100. AND LAPACK_IMPL STREQUAL "MKL"
  101. AND ";${LAPACK_LIBRARIES};" MATCHES ";tbb;" AND TARGET tbb
  102. AND DEFINED TBB_INTERFACE_VERSION AND NOT (TBB_INTERFACE_VERSION LESS 12000) # oneTBB/oneAPI workaround
  103. )
  104. # workaround DEFAULTLIB:tbb12.lib issue
  105. get_target_property(_tbb_lib tbb IMPORTED_LOCATION)
  106. if(NOT _tbb_lib)
  107. get_target_property(_tbb_lib tbb IMPORTED_LOCATION_RELEASE)
  108. endif()
  109. if(_tbb_lib AND NOT OPENCV_SKIP_WORKAROUND_MKL_LINK_DIRECTORIES_TBB)
  110. # MSBuild drops content of 'LIB' environment variable,
  111. # so pass TBB library directory through `link_directories()`
  112. get_filename_component(_tbb_lib_dir "${_tbb_lib}" DIRECTORY)
  113. message(STATUS "MKL: adding '${_tbb_lib_dir}' to link directories (workaround DEFAULTLIB issue)")
  114. link_directories("${_tbb_lib_dir}")
  115. elseif(NOT OPENCV_SKIP_WORKAROUND_MKL_DEFAULTLIB)
  116. # We may have tbb.lib for 'tbb' target, but not 'tbb12.lib'
  117. ocv_update(OPENCV_MKL_IGNORE_DEFAULTLIB_TBB "tbb12.lib")
  118. set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:${OPENCV_MKL_IGNORE_DEFAULTLIB_TBB}")
  119. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:${OPENCV_MKL_IGNORE_DEFAULTLIB_TBB}")
  120. endif()
  121. endif()
  122. # TODO add cache for try_compile() inputs/results
  123. get_property(__link_directories DIRECTORY PROPERTY LINK_DIRECTORIES)
  124. if(LAPACK_LINK_LIBRARIES)
  125. list(APPEND __link_directories ${LAPACK_LINK_LIBRARIES})
  126. endif()
  127. set(LAPACK_TRY_COMPILE_DEF "")
  128. if(LAPACK_IMPL STREQUAL "LAPACK/Apple" AND OPENCV_OSX_USE_ACCELERATE_NEW_LAPACK)
  129. message(STATUS "LAPACK(${LAPACK_IMPL}): Accelerate New LAPACK is enabled.")
  130. set(LAPACK_TRY_COMPILE_DEF "-DACCELERATE_NEW_LAPACK")
  131. add_compile_definitions(ACCELERATE_NEW_LAPACK)
  132. add_compile_definitions(ACCELERATE_LAPACK_ILP64)
  133. endif()
  134. try_compile(__VALID_LAPACK
  135. "${OpenCV_BINARY_DIR}"
  136. "${OpenCV_SOURCE_DIR}/cmake/checks/lapack_check.cpp"
  137. CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${LAPACK_INCLUDE_DIR}\;${CMAKE_BINARY_DIR}"
  138. "-DLINK_DIRECTORIES:STRING=${__link_directories}"
  139. COMPILE_DEFINITIONS ${LAPACK_TRY_COMPILE_DEF}
  140. LINK_LIBRARIES ${LAPACK_LIBRARIES}
  141. OUTPUT_VARIABLE TRY_OUT
  142. )
  143. if(NOT __VALID_LAPACK)
  144. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  145. "\nLAPACK(${LAPACK_IMPL}) check FAILED:\n"
  146. " LAPACK_INCLUDE_DIR: '${LAPACK_INCLUDE_DIR}'\n"
  147. " LAPACK_LIBRARIES: '${LAPACK_LIBRARIES}'\n"
  148. " LAPACK_LINK_LIBRARIES: '${__link_directories}'\n"
  149. " Output:\n${TRY_OUT}\n\n")
  150. message(STATUS "LAPACK(${LAPACK_IMPL}): Can't build LAPACK check code. This LAPACK version is not supported.")
  151. unset(LAPACK_LIBRARIES)
  152. else()
  153. message(STATUS "LAPACK(${LAPACK_IMPL}): Support is enabled.")
  154. ocv_include_directories(${LAPACK_INCLUDE_DIR})
  155. set(HAVE_LAPACK 1)
  156. endif()
  157. endif()
  158. endmacro()
  159. if(WITH_LAPACK)
  160. ocv_update(LAPACK_IMPL "Unknown")
  161. if(NOT OPENCV_LAPACK_FIND_PACKAGE_ONLY)
  162. if(NOT LAPACK_LIBRARIES AND NOT OPENCV_LAPACK_DISABLE_MKL)
  163. include(cmake/OpenCVFindMKL.cmake)
  164. if(HAVE_MKL)
  165. ocv_lapack_check(IMPL "MKL"
  166. CBLAS_H "mkl_cblas.h"
  167. LAPACKE_H "mkl_lapack.h"
  168. INCLUDE_DIR "${MKL_INCLUDE_DIRS}"
  169. LIBRARIES "${MKL_LIBRARIES}")
  170. endif()
  171. endif()
  172. if(NOT LAPACK_LIBRARIES)
  173. include(cmake/OpenCVFindOpenBLAS.cmake)
  174. if(OpenBLAS_FOUND)
  175. ocv_lapack_check(IMPL "OpenBLAS"
  176. CBLAS_H "cblas.h"
  177. LAPACKE_H "lapacke.h"
  178. INCLUDE_DIR "${OpenBLAS_INCLUDE_DIRS}"
  179. LIBRARIES "${OpenBLAS_LIBRARY};${OpenBLAS_LIBRARIES}")
  180. endif()
  181. endif()
  182. if(NOT LAPACK_LIBRARIES AND UNIX)
  183. include(cmake/OpenCVFindAtlas.cmake)
  184. if(ATLAS_FOUND)
  185. ocv_lapack_check(IMPL "Atlas"
  186. CBLAS_H "cblas.h"
  187. LAPACKE_H "lapacke.h"
  188. INCLUDE_DIR "${Atlas_INCLUDE_DIR}"
  189. LIBRARIES "${Atlas_LIBRARIES}")
  190. endif()
  191. endif()
  192. endif()
  193. if(NOT LAPACK_LIBRARIES)
  194. if(WIN32 AND NOT OPENCV_LAPACK_SHARED_LIBS)
  195. set(BLA_STATIC 1)
  196. endif()
  197. find_package(LAPACK)
  198. if(LAPACK_FOUND)
  199. if(NOT DEFINED LAPACKE_INCLUDE_DIR)
  200. find_path(LAPACKE_INCLUDE_DIR "lapacke.h")
  201. endif()
  202. if(NOT DEFINED MKL_LAPACKE_INCLUDE_DIR)
  203. find_path(MKL_LAPACKE_INCLUDE_DIR "mkl_lapack.h")
  204. endif()
  205. if(MKL_LAPACKE_INCLUDE_DIR AND NOT OPENCV_LAPACK_DISABLE_MKL)
  206. ocv_lapack_check(IMPL "LAPACK/MKL"
  207. CBLAS_H "mkl_cblas.h"
  208. LAPACKE_H "mkl_lapack.h"
  209. INCLUDE_DIR "${MKL_LAPACKE_INCLUDE_DIR}"
  210. LIBRARIES "${LAPACK_LIBRARIES}")
  211. endif()
  212. if(NOT HAVE_LAPACK)
  213. if(NOT DEFINED CBLAS_INCLUDE_DIR)
  214. find_path(CBLAS_INCLUDE_DIR "cblas.h")
  215. endif()
  216. if(CBLAS_INCLUDE_DIR AND LAPACKE_INCLUDE_DIR)
  217. ocv_lapack_check(IMPL "LAPACK/Generic"
  218. CBLAS_H "cblas.h"
  219. LAPACKE_H "lapacke.h"
  220. INCLUDE_DIR "${CBLAS_INCLUDE_DIR}" "${LAPACKE_INCLUDE_DIR}"
  221. LIBRARIES "${LAPACK_LIBRARIES}")
  222. elseif(APPLE)
  223. ocv_lapack_check(IMPL "LAPACK/Apple"
  224. CBLAS_H "Accelerate/Accelerate.h"
  225. LAPACKE_H "Accelerate/Accelerate.h")
  226. endif()
  227. endif()
  228. endif()
  229. if(NOT HAVE_LAPACK)
  230. unset(LAPACK_LIBRARIES)
  231. unset(LAPACK_LIBRARIES CACHE)
  232. endif()
  233. endif()
  234. if(NOT LAPACK_LIBRARIES AND APPLE AND NOT OPENCV_LAPACK_FIND_PACKAGE_ONLY)
  235. ocv_lapack_check(IMPL "Apple"
  236. CBLAS_H "Accelerate/Accelerate.h"
  237. LAPACKE_H "Accelerate/Accelerate.h"
  238. LIBRARIES "-framework Accelerate")
  239. endif()
  240. if(NOT HAVE_LAPACK AND LAPACK_LIBRARIES AND LAPACK_CBLAS_H AND LAPACK_LAPACKE_H)
  241. ocv_lapack_check(IMPL "Unknown"
  242. CBLAS_H ${LAPACK_CBLAS_H}
  243. LAPACKE_H ${LAPACK_LAPACKE_H}
  244. LIBRARIES "${LAPACK_LIBRARIES}")
  245. endif()
  246. set(LAPACK_INCLUDE_DIR ${LAPACK_INCLUDE_DIR} CACHE PATH "Path to BLAS include dir" FORCE)
  247. set(LAPACK_CBLAS_H ${LAPACK_CBLAS_H} CACHE STRING "Alternative name of cblas.h" FORCE)
  248. set(LAPACK_LAPACKE_H ${LAPACK_LAPACKE_H} CACHE STRING "Alternative name of lapacke.h" FORCE)
  249. set(LAPACK_LIBRARIES ${LAPACK_LIBRARIES} CACHE STRING "Names of BLAS & LAPACK binaries (.so, .dll, .a, .lib)" FORCE)
  250. set(LAPACK_IMPL ${LAPACK_IMPL} CACHE STRING "Lapack implementation id" FORCE)
  251. endif()