cmake_minimum_required( VERSION 3.17 ) # Require CMake 3.17+ include( CMakePushCheckState ) include( CheckLibraryExists ) include( CheckSymbolExists ) include( CMakeFindDependencyMacro ) include( FindPackageHandleStandardArgs ) include( ${CMAKE_CURRENT_LIST_DIR}/util/CommonFunctions.cmake ) include( ${CMAKE_CURRENT_LIST_DIR}/util/LAPACKUtilities.cmake ) include( ${CMAKE_CURRENT_LIST_DIR}/LinAlgModulesMacros.cmake ) # SANITY CHECK if( "ilp64" IN_LIST LAPACK_FIND_COMPONENTS AND "lp64" IN_LIST LAPACK_FIND_COMPONENTS ) message( FATAL_ERROR "LAPACK cannot link to both ILP64 and LP64 interfaces" ) endif() # Get list of required / optional components foreach( _comp ${LAPACK_FIND_COMPONENTS} ) if( LAPACK_FIND_REQUIRED_${_comp} ) list( APPEND LAPACK_REQUIRED_COMPONENTS ${_comp} ) else() list( APPEND LAPACK_OPTIONAL_COMPONENTS ${_comp} ) endif() endforeach() emulate_kitware_linalg_modules( LAPACK ) fill_out_prefix( LAPACK ) if( NOT LAPACK_PREFERENCE_LIST ) set( LAPACK_PREFERENCE_LIST "ReferenceLAPACK" "FLAME" ) endif() if( NOT LAPACK_LIBRARIES ) # Find BLAS if( NOT TARGET BLAS::BLAS ) copy_meta_data( LAPACK BLAS ) find_dependency( BLAS COMPONENTS ${LAPACK_REQUIRED_COMPONENTS} OPTIONAL_COMPONENTS ${LAPACK_OPTIONAL_COMPONENTS} ) endif() # Check if BLAS contains a LAPACK linker message( STATUS "LAPACK_LIBRARIES Not Given: Checking for LAPACK in BLAS" ) set( LAPACK_LIBRARIES ${BLAS_LIBRARIES} ) set( LAPACK_INCLUDE_DIRS ${BLAS_INCLUDE_DIRS} ) set( LAPACK_COMPILE_DEFINITIONS ${BLAS_COMPILE_DEFINITIONS} ) # use dpstrf to check for full LAPACK API ... some implementations are incomplete (e.g. older OpenBLAS) # also need to handle several corner cases: # - OpenBLAS needs libgfortran only for some functions, dpstrf is not one of them, so check for dgesvd check_fortran_functions_exist( "dpstrf;dgesvd" LAPACK LAPACK_LIBRARIES BLAS_HAS_LAPACK LAPACK_Fortran_LOWER LAPACK_Fortran_UNDERSCORE ) # If BLAS has a full LAPACK Linker, propagate vars if( BLAS_HAS_LAPACK ) message( STATUS "BLAS Has A Full LAPACK Linker" ) set( LAPACK_VENDOR ${BLAS_VENDOR} ) set( LAPACK_IS_LP64 ${BLAS_IS_LP64} ) set( LAPACK_blacs_FOUND ${BLAS_blacs_FOUND} ) set( LAPACK_scalapack_FOUND ${BLAS_scalapack_FOUND} ) set( LAPACK_sycl_FOUND ${BLAS_sycl_FOUND} ) # Else find LAPACK installation consistent with BLAS else( BLAS_HAS_LAPACK ) # Ensure proper integer size if( BLAS_IS_LP64 AND (NOT "lp64" IN_LIST LAPACK_REQUIRED_COMPONENTS) ) list( APPEND LAPACK_REQUIRED_COMPONENTS "lp64" ) elseif( (NOT BLAS_IS_LP64) AND (NOT "ilp64" IN_LIST LAPACK_REQUIRED_COMPONENTS ) ) list( APPEND LAPACK_REQUIRED_COMPONENTS "ilp64" ) endif() message( STATUS "BLAS Does Not Have A Full LAPACK Linker -- Performing Search" ) foreach( lapack_type ${LAPACK_PREFERENCE_LIST} ) copy_meta_data( LAPACK ${lapack_type} ) find_package( ${lapack_type} COMPONENTS ${LAPACK_REQUIRED_COMPONENTS} OPTIONAL_COMPONENTS ${LAPACK_OPTIONAL_COMPONENTS} ) if( ${lapack_type}_FOUND ) # Propagate Linker / Includes set( LAPACK_VENDOR "${lapack_type}" ) list( PREPEND LAPACK_LIBRARIES ${${lapack_type}_LIBRARIES} ) list( PREPEND LAPACK_COMPILE_DEFINITIONS ${${lapack_type}_COMPILE_DEFINITIONS} ) list( PREPEND LAPACK_INCLUDE_DIR ${${lapack_type}_INCLUDE_DIR} ) # Generic Components #set( LAPACK_headers_FOUND ${${lapack_type}_headers_FOUND} ) set( LAPACK_blacs_FOUND ${${lapack_type}_blacs_FOUND} ) set( LAPACK_scalapack_FOUND ${${lapack_type}_scalapack_FOUND} ) set( LAPACK_sycl_FOUND ${${lapack_type}_sycl_FOUND} ) break() # Break from search loop endif() endforeach() endif( BLAS_HAS_LAPACK ) else() find_linalg_dependencies( LAPACK_LIBRARIES ) endif() # Handle implicit LAPACK linkage if( LAPACK_LIBRARIES MATCHES "[Ii][Mm][Pp][Ll][Ii][Cc][Ii][Tt]" ) unset( LAPACK_LIBRARIES ) endif() # Check for LAPACK Linker if( BLAS_HAS_LAPACK ) set( LAPACK_LINK_OK TRUE ) else() # see notes above the first invocation of check_fortran_functions_exist check_fortran_functions_exist( "dpstrf;dgesvd" LAPACK LAPACK_LIBRARIES LAPACK_LINK_OK LAPACK_Fortran_LOWER LAPACK_Fortran_UNDERSCORE ) endif() # If LAPACK linkage successful, check if it is ILP64/LP64 if( LAPACK_LINK_OK ) set( _dsyev_name "dsyev" ) if( NOT LAPACK_Fortran_LOWER ) string( TOUPPER "${_dsyev_name}" _dsyev_name ) endif() if( LAPACK_Fortran_UNDERSCORE ) set( _dsyev_name "${_dsyev_name}_" ) endif() check_lapack_int( LAPACK_LIBRARIES ${_dsyev_name} LAPACK_IS_LP64 ) if( LAPACK_IS_LP64 ) set( LAPACK_lp64_FOUND TRUE ) set( LAPACK_ilp64_FOUND FALSE ) else() set( LAPACK_lp64_FOUND FALSE ) set( LAPACK_ilp64_FOUND TRUE ) find_dependency( ILP64 ) list( APPEND LAPACK_COMPILE_OPTIONS "${ILP64_COMPILE_OPTIONS}" ) foreach ( lang C CXX Fortran ) if ( DEFINED ILP64_${lang}_COMPILE_OPTIONS ) list( APPEND LAPACK_${lang}_COMPILE_OPTIONS "${ILP64_${lang}_COMPILE_OPTIONS}" ) endif() endforeach() endif() else() # Unset everything for safety unset( LAPACK_LIBRARIES ) unset( LAPACK_COMPILE_DEFINITIONS ) endif() find_package_handle_standard_args( LAPACK REQUIRED_VARS LAPACK_LINK_OK HANDLE_COMPONENTS ) # Cache variables if( LAPACK_FOUND ) set( LAPACK_VENDOR "${LAPACK_VENDOR}" CACHE STRING "LAPACK Vendor" FORCE ) set( LAPACK_IS_LP64 "${LAPACK_IS_LP64}" CACHE STRING "LAPACK LP64 Flag" FORCE ) set( LAPACK_LIBRARIES "${LAPACK_LIBRARIES}" CACHE STRING "LAPACK Libraries" FORCE ) set( LAPACK_COMPILE_DEFINITIONS "${LAPACK_COMPILE_DEFINITIONS}" CACHE STRING "LAPACK Compile Definitions" FORCE ) set( LAPACK_INCLUDE_DIRS "${LAPACK_INCLUDE_DIRS}" CACHE STRING "LAPACK Include Directories" FORCE ) set( LAPACK_COMPILE_OPTIONS "${LAPACK_COMPILE_OPTIONS}" CACHE STRING "LAPACK Compile Options" FORCE ) foreach ( lang C CXX Fortran ) if ( DEFINED LAPACK_${lang}_COMPILE_OPTIONS ) set( LAPACK_${lang}_COMPILE_OPTIONS "${LAPACK_${lang}_COMPILE_OPTIONS}" CACHE STRING "LAPACK Compile Options for Language ${lang}" FORCE ) endif() endforeach() endif() if( LAPACK_FOUND AND NOT TARGET LAPACK::LAPACK ) add_library( LAPACK::LAPACK INTERFACE IMPORTED ) set_target_properties( LAPACK::LAPACK PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LAPACK_INCLUDE_DIRS}" INTERFACE_COMPILE_OPTIONS "${LAPACK_COMPILE_OPTIONS}" INTERFACE_COMPILE_DEFINITIONS "${LAPACK_COMPILE_DEFINITIONS}" INTERFACE_LINK_LIBRARIES "${LAPACK_LIBRARIES}" ) endif()