# Locate an LP64 OpenBLAS implementation together with the CBLAS and LAPACKE # C interfaces. LAPACKE may be provided by libopenblas itself or by a separate # liblapacke library. # # Result: # REML_OpenBLAS_FOUND # REML::OpenBLASLAPACKE # # Optional hints/overrides: # OpenBLAS_ROOT # LAPACKE_ROOT # REML_OPENBLAS_LIBRARY # REML_LAPACKE_LIBRARY # REML_CBLAS_INCLUDE_DIR # REML_LAPACKE_INCLUDE_DIR include(CheckCXXSourceCompiles) include(CMakePushCheckState) include(FindPackageHandleStandardArgs) set(_reml_openblas_hints) foreach(_root IN ITEMS "${OpenBLAS_ROOT}" "$ENV{OpenBLAS_ROOT}" "$ENV{OPENBLAS_ROOT}" "$ENV{CONDA_PREFIX}") if(_root) list(APPEND _reml_openblas_hints "${_root}") endif() endforeach() set(_reml_lapacke_hints ${_reml_openblas_hints}) foreach(_root IN ITEMS "${LAPACKE_ROOT}" "$ENV{LAPACKE_ROOT}") if(_root) list(PREPEND _reml_lapacke_hints "${_root}") endif() endforeach() # Prefer package-provided imported targets because they carry static-library # dependencies (Fortran runtime, pthreads, and libm) correctly. find_package(OpenBLAS CONFIG QUIET) if(TARGET OpenBLAS::OpenBLAS) set(_reml_openblas_link OpenBLAS::OpenBLAS) elseif(TARGET OpenBLAS) set(_reml_openblas_link OpenBLAS) endif() if(NOT _reml_openblas_link) find_library(REML_OPENBLAS_LIBRARY NAMES openblas libopenblas HINTS ${_reml_openblas_hints} PATH_SUFFIXES lib lib64 Library/lib ) if(REML_OPENBLAS_LIBRARY) set(_reml_openblas_link "${REML_OPENBLAS_LIBRARY}") endif() endif() find_path(REML_CBLAS_INCLUDE_DIR NAMES cblas.h HINTS ${_reml_openblas_hints} PATH_SUFFIXES include include/openblas Library/include Library/include/openblas ) find_path(REML_LAPACKE_INCLUDE_DIR NAMES lapacke.h HINTS ${_reml_lapacke_hints} PATH_SUFFIXES include include/openblas include/lapacke Library/include Library/include/openblas ) find_package(LAPACKE CONFIG QUIET) if(TARGET LAPACKE::LAPACKE) set(_reml_lapacke_link LAPACKE::LAPACKE) elseif(TARGET LAPACKE) set(_reml_lapacke_link LAPACKE) else() find_library(REML_LAPACKE_LIBRARY NAMES lapacke liblapacke HINTS ${_reml_lapacke_hints} PATH_SUFFIXES lib lib64 Library/lib ) if(REML_LAPACKE_LIBRARY) set(_reml_lapacke_link "${REML_LAPACKE_LIBRARY}") endif() endif() if(_reml_lapacke_link) # Keep the static-link order dependency first, provider second: # liblapacke calls LAPACK symbols supplied by libopenblas. set(_reml_link_items ${_reml_lapacke_link} ${_reml_openblas_link}) else() set(_reml_link_items ${_reml_openblas_link}) endif() unset(REML_OPENBLAS_LINK_OK CACHE) if(REML_CBLAS_INCLUDE_DIR AND REML_LAPACKE_INCLUDE_DIR AND _reml_openblas_link) cmake_push_check_state(RESET) set(CMAKE_REQUIRED_INCLUDES "${REML_CBLAS_INCLUDE_DIR};${REML_LAPACKE_INCLUDE_DIR}") set(CMAKE_REQUIRED_LIBRARIES ${_reml_link_items}) check_cxx_source_compiles([[ #include #include int main() { double a[1] = {1.0}; double b[1] = {1.0}; double c[1] = {0.0}; cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 1, 1, 1, 1.0, a, 1, b, 1, 0.0, c, 1); return LAPACKE_dpotrf(LAPACK_ROW_MAJOR, 'L', 1, a, 1); } ]] REML_OPENBLAS_LINK_OK) cmake_pop_check_state() else() set(REML_OPENBLAS_LINK_OK FALSE) endif() find_package_handle_standard_args(REML_OpenBLAS REQUIRED_VARS REML_CBLAS_INCLUDE_DIR REML_LAPACKE_INCLUDE_DIR _reml_openblas_link REML_OPENBLAS_LINK_OK FAIL_MESSAGE "OpenBLAS with LP64 CBLAS and LAPACKE is required. Set OpenBLAS_ROOT/LAPACKE_ROOT, or the REML_* cache variables listed in cmake/FindREML_OpenBLAS.cmake." ) if(REML_OpenBLAS_FOUND AND NOT TARGET REML::OpenBLASLAPACKE) add_library(REML::OpenBLASLAPACKE INTERFACE IMPORTED) set_property(TARGET REML::OpenBLASLAPACKE PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${REML_CBLAS_INCLUDE_DIR};${REML_LAPACKE_INCLUDE_DIR}") set_property(TARGET REML::OpenBLASLAPACKE PROPERTY INTERFACE_LINK_LIBRARIES "${_reml_link_items}") endif() mark_as_advanced( REML_CBLAS_INCLUDE_DIR REML_LAPACKE_INCLUDE_DIR REML_OPENBLAS_LIBRARY REML_LAPACKE_LIBRARY )