From 2b44c0b6493726c465152e1db82cd8e65944d0db Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 23 Dec 2016 14:50:33 +0300 Subject: [PATCH] cmake: fix lapack - added compile check with multiple tries for different configurations - restored find_package(LAPACK) - avoided modification of OPENCV_LINKER_LIBS --- cmake/OpenCVFindLAPACK.cmake | 213 +++++++++++++++++++++++----------- cmake/checks/lapack_check.cpp | 14 +++ modules/core/CMakeLists.txt | 2 +- 3 files changed, 162 insertions(+), 67 deletions(-) create mode 100644 cmake/checks/lapack_check.cpp diff --git a/cmake/OpenCVFindLAPACK.cmake b/cmake/OpenCVFindLAPACK.cmake index dfacf24328..0bee1b4c90 100644 --- a/cmake/OpenCVFindLAPACK.cmake +++ b/cmake/OpenCVFindLAPACK.cmake @@ -1,78 +1,159 @@ -macro(_find_file_in_dirs VAR NAME DIRS) - find_path(${VAR} ${NAME} ${DIRS} NO_DEFAULT_PATH) - set(${VAR} ${${VAR}}/${NAME}) - unset(${VAR} CACHE) +macro(_find_header_file_in_dirs VAR NAME) + unset(${VAR}) + unset(${VAR} CACHE) + if(" ${ARGN}" STREQUAL " ") + check_include_file("${NAME}" HAVE_${VAR}) + if(HAVE_${VAR}) + set(${VAR} "${NAME}") # fallback + else() + set(${VAR} "") + endif() + else() + find_path(${VAR} "${NAME}" ${ARGN} NO_DEFAULT_PATH) + if(${VAR}) + set(${VAR} "${${VAR}}/${NAME}") + unset(${VAR} CACHE) + else() + unset(${VAR} CACHE) + set(${VAR} "") + endif() + endif() +endmacro() + +macro(ocv_lapack_check) + string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" _lapack_impl "${LAPACK_IMPL}") + message(STATUS "LAPACK(${LAPACK_IMPL}): LAPACK_LIBRARIES: ${LAPACK_LIBRARIES}") + _find_header_file_in_dirs(OPENCV_CBLAS_H_PATH_${_lapack_impl} "${LAPACK_CBLAS_H}" "${LAPACK_INCLUDE_DIR}") + _find_header_file_in_dirs(OPENCV_LAPACKE_H_PATH_${_lapack_impl} "${LAPACK_LAPACKE_H}" "${LAPACK_INCLUDE_DIR}") + if(NOT OPENCV_CBLAS_H_PATH_${_lapack_impl} OR NOT OPENCV_LAPACKE_H_PATH_${_lapack_impl}) + message(WARNING "LAPACK(${LAPACK_IMPL}): CBLAS/LAPACK headers are not found in '${LAPACK_INCLUDE_DIR}'") + unset(LAPACK_LIBRARIES) + else() + # adding proxy opencv_lapack.h header + set(CBLAS_H_PROXY_PATH ${CMAKE_BINARY_DIR}/opencv_lapack.h) + set(_lapack_include_str "\#include \"${OPENCV_CBLAS_H_PATH_${_lapack_impl}}\"") + if(NOT "${OPENCV_CBLAS_H_PATH_${_lapack_impl}}" STREQUAL "${OPENCV_LAPACKE_H_PATH_${_lapack_impl}}") + set(_lapack_include_str "${_lapack_include_str}\n#include \"${OPENCV_LAPACKE_H_PATH_${_lapack_impl}}\"") + endif() + # update file contents (if required) + set(__content_str "") + if(EXISTS "${CBLAS_H_PROXY_PATH}") + file(READ "${CBLAS_H_PROXY_PATH}" __content_str) + endif() + if(NOT " ${__content_str}" STREQUAL " ${_lapack_include_str}") + file(WRITE "${CBLAS_H_PROXY_PATH}" "${_lapack_include_str}") + endif() + + try_compile(__VALID_LAPACK + "${OpenCV_BINARY_DIR}" + "${OpenCV_SOURCE_DIR}/cmake/checks/lapack_check.cpp" + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${LAPACK_INCLUDE_DIR}\;${CMAKE_BINARY_DIR}" + "-DLINK_DIRECTORIES:STRING=${LAPACK_LINK_LIBRARIES}" + "-DLINK_LIBRARIES:STRING=${LAPACK_LIBRARIES}" + OUTPUT_VARIABLE TRY_OUT + ) + if(NOT __VALID_LAPACK) + #message(FATAL_ERROR "LAPACK: check build log:\n${TRY_OUT}") + message(STATUS "LAPACK(${LAPACK_IMPL}): Can't build LAPACK check code. This LAPACK version is not supported.") + unset(LAPACK_LIBRARIES) + else() + message(STATUS "LAPACK(${LAPACK_IMPL}): Support is enabled.") + ocv_include_directories(${LAPACK_INCLUDE_DIR}) + set(HAVE_LAPACK 1) + endif() + endif() endmacro() if(WITH_LAPACK) - ocv_update(LAPACK_IMPL "Unknown") - if(NOT LAPACK_LIBRARIES) - include(cmake/OpenCVFindMKL.cmake) - if(HAVE_MKL) - set(LAPACK_INCLUDE_DIR ${MKL_INCLUDE_DIRS}) - set(LAPACK_LIBRARIES ${MKL_LIBRARIES} ) - set(LAPACK_CBLAS_H "mkl_cblas.h" ) - set(LAPACK_LAPACKE_H "mkl_lapack.h" ) - set(LAPACK_IMPL "MKL") - endif() + ocv_update(LAPACK_IMPL "Unknown") + if(NOT OPENCV_LAPACK_FIND_PACKAGE_ONLY) + if(NOT LAPACK_LIBRARIES AND NOT OPENCV_LAPACK_DISABLE_MKL) + include(cmake/OpenCVFindMKL.cmake) + if(HAVE_MKL) + set(LAPACK_INCLUDE_DIR ${MKL_INCLUDE_DIRS}) + set(LAPACK_LIBRARIES ${MKL_LIBRARIES}) + set(LAPACK_CBLAS_H "mkl_cblas.h") + set(LAPACK_LAPACKE_H "mkl_lapack.h") + set(LAPACK_IMPL "MKL") + ocv_lapack_check() + endif() endif() if(NOT LAPACK_LIBRARIES) - include(cmake/OpenCVFindOpenBLAS.cmake) - if(OpenBLAS_FOUND) - set(LAPACK_INCLUDE_DIR ${OpenBLAS_INCLUDE_DIR} ) - set(LAPACK_LIBRARIES ${OpenBLAS_LIB} ) - set(LAPACK_CBLAS_H "cblas.h" ) - set(LAPACK_LAPACKE_H "lapacke.h" ) - set(LAPACK_IMPL "OpenBLAS") - endif() + include(cmake/OpenCVFindOpenBLAS.cmake) + if(OpenBLAS_FOUND) + set(LAPACK_INCLUDE_DIR ${OpenBLAS_INCLUDE_DIR}) + set(LAPACK_LIBRARIES ${OpenBLAS_LIB}) + set(LAPACK_CBLAS_H "cblas.h") + set(LAPACK_LAPACKE_H "lapacke.h") + set(LAPACK_IMPL "OpenBLAS") + ocv_lapack_check() + endif() endif() if(NOT LAPACK_LIBRARIES AND UNIX) - include(cmake/OpenCVFindAtlas.cmake) - if(ATLAS_FOUND) - set(LAPACK_INCLUDE_DIR ${Atlas_INCLUDE_DIR}) - set(LAPACK_LIBRARIES ${Atlas_LIBRARIES} ) - set(LAPACK_CBLAS_H "cblas.h" ) - set(LAPACK_LAPACKE_H "lapacke.h" ) - set(LAPACK_IMPL "Atlas") - endif() + include(cmake/OpenCVFindAtlas.cmake) + if(ATLAS_FOUND) + set(LAPACK_INCLUDE_DIR ${Atlas_INCLUDE_DIR}) + set(LAPACK_LIBRARIES ${Atlas_LIBRARIES}) + set(LAPACK_CBLAS_H "cblas.h") + set(LAPACK_LAPACKE_H "lapacke.h") + set(LAPACK_IMPL "Atlas") + ocv_lapack_check() + endif() endif() + endif() - if(NOT LAPACK_LIBRARIES AND APPLE) - set(LAPACK_INCLUDE_DIR "Accelerate") - set(LAPACK_LIBRARIES "-framework Accelerate") - set(LAPACK_CBLAS_H "cblas.h" ) - set(LAPACK_LAPACKE_H "lapacke.h" ) - set(LAPACK_IMPL "Apple") + if(NOT LAPACK_LIBRARIES) + if(WIN32 AND NOT OPENCV_LAPACK_SHARED_LIBS) + set(BLA_STATIC 1) endif() - - set(LAPACK_INCLUDE_DIR ${LAPACK_INCLUDE_DIR} CACHE PATH "Path to BLAS include dir" FORCE) - set(LAPACK_CBLAS_H ${LAPACK_CBLAS_H} CACHE STRING "Alternative name of cblas.h" FORCE) - set(LAPACK_LAPACKE_H ${LAPACK_LAPACKE_H} CACHE STRING "Alternative name of lapacke.h" FORCE) - set(LAPACK_LIBRARIES ${LAPACK_LIBRARIES} CACHE STRING "Names of BLAS & LAPACK binaries (.so, .dll, .a, .lib)" FORCE) - set(LAPACK_IMPL ${LAPACK_IMPL} CACHE STRING "Lapack implementation id" FORCE) - - if(LAPACK_LIBRARIES) #adding proxy cblas.h header - message(STATUS "LAPACK_IMPL: ${LAPACK_IMPL}, LAPACK_LIBRARIES: ${LAPACK_LIBRARIES}") - if("${LAPACK_IMPL}" STREQUAL "Apple") - set(CBLAS_H_PATH "Accelerate/Accelerate.h") - set(LAPACKE_H_PATH "Accelerate/Accelerate.h") - else() - _find_file_in_dirs(CBLAS_H_PATH "${LAPACK_CBLAS_H}" "${LAPACK_INCLUDE_DIR}") - _find_file_in_dirs(LAPACKE_H_PATH "${LAPACK_LAPACKE_H}" "${LAPACK_INCLUDE_DIR}") - endif() - if(NOT CBLAS_H_PATH OR NOT LAPACKE_H_PATH) - message(WARNING "CBLAS/LAPACK headers are not found in '${LAPACK_INCLUDE_DIR}'") - endif() - ocv_include_directories(${LAPACK_INCLUDE_DIR}) - list(APPEND OPENCV_LINKER_LIBS ${LAPACK_LIBRARIES}) - set(HAVE_LAPACK 1) - - set(CBLAS_H_PROXY_PATH ${CMAKE_BINARY_DIR}/opencv_lapack.h) - set(_include_str "\#include \"${CBLAS_H_PATH}\"") - if("${CBLAS_H_PATH}" STREQUAL "${LAPACKE_H_PATH}") - else() - set(_include_str "${_include_str}\n\#include \"${LAPACKE_H_PATH}\"") - endif() - file(WRITE ${CBLAS_H_PROXY_PATH} ${_include_str}) + find_package(LAPACK) + if(LAPACK_FOUND) + if(NOT DEFINED LAPACKE_INCLUDE_DIR) + find_path(LAPACKE_INCLUDE_DIR "lapacke.h") + endif() + if(NOT DEFINED MKL_LAPACKE_INCLUDE_DIR) + find_path(MKL_LAPACKE_INCLUDE_DIR "mkl_lapack.h") + endif() + if(MKL_LAPACKE_INCLUDE_DIR AND NOT OPENCV_LAPACK_DISABLE_MKL) + set(LAPACK_INCLUDE_DIR ${MKL_LAPACKE_INCLUDE_DIR}) + set(LAPACK_CBLAS_H "mkl_cblas.h") + set(LAPACK_LAPACKE_H "mkl_lapack.h") + set(LAPACK_IMPL "LAPACK/MKL") + ocv_lapack_check() + endif() + if(LAPACKE_INCLUDE_DIR AND NOT HAVE_LAPACK) + set(LAPACK_INCLUDE_DIR ${LAPACKE_INCLUDE_DIR}) + set(LAPACK_CBLAS_H "cblas.h") + set(LAPACK_LAPACKE_H "lapacke.h") + set(LAPACK_IMPL "LAPACK/Generic") + ocv_lapack_check() + elseif(APPLE) + set(LAPACK_CBLAS_H "Accelerate/Accelerate.h") + set(LAPACK_LAPACKE_H "Accelerate/Accelerate.h") + set(LAPACK_IMPL "LAPACK/Apple") + ocv_lapack_check() + else() + unset(LAPACK_LIBRARIES CACHE) + endif() endif() + endif() + + if(NOT LAPACK_LIBRARIES AND APPLE AND NOT OPENCV_LAPACK_FIND_PACKAGE_ONLY) + set(LAPACK_INCLUDE_DIR "") + set(LAPACK_LIBRARIES "-framework Accelerate") + set(LAPACK_CBLAS_H "Accelerate/Accelerate.h") + set(LAPACK_LAPACKE_H "Accelerate/Accelerate.h") + set(LAPACK_IMPL "Apple") + ocv_lapack_check() + endif() + + if(NOT HAVE_LAPACK AND LAPACK_LIBRARIES) + ocv_lapack_check() + endif() + + set(LAPACK_INCLUDE_DIR ${LAPACK_INCLUDE_DIR} CACHE PATH "Path to BLAS include dir" FORCE) + set(LAPACK_CBLAS_H ${LAPACK_CBLAS_H} CACHE STRING "Alternative name of cblas.h" FORCE) + set(LAPACK_LAPACKE_H ${LAPACK_LAPACKE_H} CACHE STRING "Alternative name of lapacke.h" FORCE) + set(LAPACK_LIBRARIES ${LAPACK_LIBRARIES} CACHE STRING "Names of BLAS & LAPACK binaries (.so, .dll, .a, .lib)" FORCE) + set(LAPACK_IMPL ${LAPACK_IMPL} CACHE STRING "Lapack implementation id" FORCE) endif() diff --git a/cmake/checks/lapack_check.cpp b/cmake/checks/lapack_check.cpp new file mode 100644 index 0000000000..0457c44d68 --- /dev/null +++ b/cmake/checks/lapack_check.cpp @@ -0,0 +1,14 @@ +#include "opencv_lapack.h" + +static char* check_fn1 = (char*)sgesv_; +static char* check_fn2 = (char*)sposv_; +static char* check_fn3 = (char*)spotrf_; +static char* check_fn4 = (char*)sgesdd_; + +int main(int argc, char* argv[]) +{ + (void)argv; + if(argc > 1000) + return check_fn1[0] + check_fn2[0] + check_fn3[0] + check_fn4[0]; + return 0; +} diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index 0485a08ad3..41da825457 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -1,7 +1,7 @@ set(the_description "The Core Functionality") ocv_add_module(core "${OPENCV_HAL_LINKER_LIBS}" - PRIVATE_REQUIRED ${ZLIB_LIBRARIES} "${OPENCL_LIBRARIES}" "${VA_LIBRARIES}" + PRIVATE_REQUIRED ${ZLIB_LIBRARIES} "${OPENCL_LIBRARIES}" "${VA_LIBRARIES}" "${LAPACK_LIBRARIES}" OPTIONAL opencv_cudev WRAP java python)