mirror of
https://github.com/cp2k/cp2k.git
synced 2026-07-21 14:35:15 -04:00
455 lines
15 KiB
CMake
455 lines
15 KiB
CMake
#!-------------------------------------------------------------------------------------------------!
|
|
#! CP2K: A general program to perform molecular dynamics simulations !
|
|
#! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
|
|
#! !
|
|
#! SPDX-License-Identifier: GPL-2.0-or-later !
|
|
#!-------------------------------------------------------------------------------------------------!
|
|
|
|
#
|
|
# CMake recipes https://github.com/eth-cscs/cmake-recipes
|
|
#
|
|
# Copyright (c) 2018-2019, ETH Zurich BSD 3-Clause License. All rights reserved.
|
|
#
|
|
# Author: Teodor Nikolov (teodor.nikolov22@gmail.com)
|
|
#
|
|
#[=======================================================================[.rst:
|
|
FindMKL
|
|
-------
|
|
|
|
The following conventions are used:
|
|
|
|
intel / INTEL - Bindings for everything except GNU Fortran
|
|
gf / GF - GNU Fortran bindings
|
|
seq / SEQ - sequential MKL
|
|
omp / OMP - threaded MKL with OpenMP back end
|
|
tbb / TBB - threaded MKL with TBB back end
|
|
32bit / 32BIT - MKL 32 bit integer interface (used most often)
|
|
64bit / 64BIT - MKL 64 bit integer interface
|
|
mpich / MPICH - MPICH / IntelMPI BLACS back end
|
|
ompi / OMPI - OpenMPI BLACS back end
|
|
st / ST - static libraries
|
|
dyn / DYN - dynamic libraries
|
|
|
|
The module attempts to define a target for each MKL configuration. The
|
|
configuration will not be available if there are missing library files or a
|
|
missing dependency.
|
|
|
|
MKL Link line advisor:
|
|
https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor
|
|
|
|
Note: Mixing GCC and Intel OpenMP backends is a bad idea.
|
|
|
|
Search variables
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
``MKLROOT``
|
|
Environment variable set to MKL's root directory
|
|
|
|
``MKL_ROOT``
|
|
CMake variable set to MKL's root directory
|
|
|
|
Example usage
|
|
^^^^^^^^^^^^^
|
|
|
|
To Find MKL:
|
|
|
|
find_package(MKL REQUIRED)
|
|
|
|
To check if target is available:
|
|
|
|
if (TARGET MKL::scalapack_mpich_intel_32bit_omp_dyn)
|
|
...
|
|
endif()
|
|
|
|
To link to an available target (see list below):
|
|
|
|
target_link_libraries(... MKL::scalapack_mpich_intel_32bit_omp_dyn)
|
|
|
|
Note: dependencies are handled for you (MPI, OpenMP, ...)
|
|
|
|
the target MKL::blas, MKL::MKL, MKL::lapack also include all necessary libraries
|
|
for linking.
|
|
MKL::MKL is also used by the cmake module provided by intel.
|
|
|
|
MKL::scalapack_link gives all libraries needed for scalapack.
|
|
|
|
Imported targets
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
MKL (BLAS, LAPACK, FFT) targets:
|
|
|
|
MKL::[gf|intel]_[32bit|64bit]_[seq|omp|tbb]_[st|dyn] e.g.
|
|
|
|
MKL::mkl_intel_32bit_omp_dyn
|
|
|
|
BLACS targets:
|
|
|
|
MKL::blacs_[mpich|ompi]_[gf|intel]_[32bit|64bit]_[seq|omp|tbb]_[st|dyn] e.g.
|
|
|
|
MKL::blacs_intel_mpich_32bit_seq_st
|
|
|
|
|
|
ScaLAPACK targets:
|
|
|
|
MKL::scalapack_[mpich|ompi]_[gf|intel]_[32bit|64bit]_[seq|omp|tbb]_[st|dyn] e.g.
|
|
|
|
MKL::scalapack_mpich_intel_64bit_omp_dyn
|
|
|
|
Result variables
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
MKL_FOUND
|
|
|
|
Not supported
|
|
^^^^^^^^^^^^^
|
|
|
|
- F95 interfaces
|
|
|
|
#]=======================================================================]
|
|
|
|
# Copyright (c) 2022- ETH Zurich
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
|
# list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
# this list of conditions and the following disclaimer in the documentation
|
|
# and/or other materials provided with the distribution.
|
|
# 3. Neither the name of the copyright holder nor the names of its contributors
|
|
# may be used to endorse or promote products derived from this software
|
|
# without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
include(FindPackageHandleStandardArgs)
|
|
|
|
if(NOT
|
|
(CMAKE_C_COMPILER_LOADED
|
|
OR CMAKE_CXX_COMPILER_LOADED
|
|
OR CMAKE_Fortran_COMPILER_LOADED))
|
|
message(FATAL_ERROR "FindMKL requires Fortran, C, or C++ to be enabled.")
|
|
endif()
|
|
|
|
# Dependencies
|
|
#
|
|
find_package(Threads)
|
|
find_package(MPI COMPONENTS CXX C Fortran)
|
|
find_package(OpenMP COMPONENTS CXX C Fortran)
|
|
|
|
# If MKL_ROOT is not set, set it via the env variable MKLROOT.
|
|
#
|
|
if(NOT DEFINED MKL_ROOT)
|
|
set(MKL_ROOT
|
|
$ENV{MKLROOT}
|
|
CACHE PATH "MKL's root directory.")
|
|
endif()
|
|
|
|
# Determine MKL's library folder
|
|
#
|
|
set(_mkl_libpath_suffix "intel64")
|
|
if(CMAKE_SIZEOF_VOID_P EQUAL 4) # 32 bit
|
|
set(_mkl_libpath_suffix "ia32")
|
|
endif()
|
|
|
|
if(WIN32)
|
|
list(APPEND _mkl_libpath_suffix_list ${_mkl_libpath_suffix})
|
|
string(APPEND _mkl_libpath_suffix "_win")
|
|
list(APPEND _mkl_libpath_suffix_list ${_mkl_libpath_suffix})
|
|
set(_mkl_libname_prefix "")
|
|
set(_mkl_shared_lib "_dll.lib")
|
|
set(_mkl_static_lib ".lib")
|
|
elseif(APPLE)
|
|
list(APPEND _mkl_libpath_suffix_list ${_mkl_libpath_suffix})
|
|
string(APPEND _mkl_libpath_suffix "_mac")
|
|
list(APPEND _mkl_libpath_suffix_list ${_mkl_libpath_suffix})
|
|
set(_mkl_libname_prefix "lib")
|
|
set(_mkl_shared_lib ".dylib")
|
|
set(_mkl_static_lib ".a")
|
|
else() # LINUX
|
|
list(APPEND _mkl_libpath_suffix_list ${_mkl_libpath_suffix})
|
|
string(APPEND _mkl_libpath_suffix "_lin")
|
|
list(APPEND _mkl_libpath_suffix_list ${_mkl_libpath_suffix})
|
|
set(_mkl_libname_prefix "lib")
|
|
set(_mkl_shared_lib ".so")
|
|
set(_mkl_static_lib ".a")
|
|
endif()
|
|
set(_mkl_search_paths "${MKL_ROOT}" "${MKL_ROOT}/lib" "${MKL_ROOT}/mkl/lib"
|
|
"${MKL_ROOT}/compiler/lib")
|
|
|
|
# Functions: finds both static and shared MKL libraries
|
|
#
|
|
function(__mkl_find_library _varname _libname)
|
|
find_library(
|
|
${_varname}_DYN
|
|
NAMES ${_mkl_libname_prefix}${_libname}${_mkl_shared_lib}
|
|
HINTS ${_mkl_search_paths}
|
|
PATH_SUFFIXES ${_mkl_libpath_suffix_list})
|
|
mark_as_advanced(${_varname}_DYN)
|
|
find_library(
|
|
${_varname}_ST
|
|
NAMES ${_mkl_libname_prefix}${_libname}${_mkl_static_lib}
|
|
HINTS ${_mkl_search_paths}
|
|
PATH_SUFFIXES ${_mkl_libpath_suffix_list})
|
|
mark_as_advanced(${_varname}_ST)
|
|
endfunction()
|
|
|
|
# Find MKL headers
|
|
#
|
|
find_path(CP2K_MKL_INCLUDE_DIRS mkl.h HINTS ${MKL_ROOT}/include
|
|
${MKL_ROOT}/mkl/include)
|
|
mark_as_advanced(CP2K_MKL_INCLUDE_DIRS)
|
|
|
|
# Group flags for static libraries on Linux (GNU, PGI, ICC -> same linker)
|
|
#
|
|
if(UNIX AND NOT APPLE)
|
|
set(_mkl_linker_pre_flags_ST "-Wl,--start-group")
|
|
set(_mkl_linker_post_flags_ST "-Wl,--end-group")
|
|
endif()
|
|
|
|
# Core MKL
|
|
#
|
|
__mkl_find_library(MKL_CORE_LIB mkl_core)
|
|
|
|
# Interface
|
|
#
|
|
__mkl_find_library(MKL_INTERFACE_INTEL_32BIT_LIB mkl_intel_lp64)
|
|
__mkl_find_library(MKL_INTERFACE_INTEL_64BIT_LIB mkl_intel_ilp64)
|
|
if(NOT APPLE
|
|
AND CMAKE_Fortran_COMPILER_LOADED
|
|
AND CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
|
__mkl_find_library(MKL_INTERFACE_GF_32BIT_LIB mkl_gf_lp64)
|
|
__mkl_find_library(MKL_INTERFACE_GF_64BIT_LIB mkl_gf_ilp64)
|
|
endif()
|
|
|
|
# Threading
|
|
#
|
|
__mkl_find_library(MKL_SEQ_LIB mkl_sequential)
|
|
if(NOT APPLE
|
|
AND (CMAKE_C_COMPILER_ID STREQUAL "GNU"
|
|
OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
|
|
OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU"))
|
|
__mkl_find_library(MKL_OMP_LIB mkl_gnu_thread)
|
|
else()
|
|
__mkl_find_library(MKL_OMP_LIB mkl_intel_thread)
|
|
endif()
|
|
__mkl_find_library(MKL_TBB_LIB mkl_tbb_thread)
|
|
|
|
# BLACS
|
|
#
|
|
if(APPLE)
|
|
__mkl_find_library(MKL_BLACS_MPICH_32BIT_LIB mkl_blacs_mpich_lp64)
|
|
__mkl_find_library(MKL_BLACS_MPICH_64BIT_LIB mkl_blacs_mpich_ilp64)
|
|
else()
|
|
__mkl_find_library(MKL_BLACS_MPICH_32BIT_LIB mkl_blacs_intelmpi_lp64)
|
|
__mkl_find_library(MKL_BLACS_MPICH_64BIT_LIB mkl_blacs_intelmpi_ilp64)
|
|
endif()
|
|
__mkl_find_library(MKL_BLACS_OMPI_32BIT_LIB mkl_blacs_openmpi_lp64)
|
|
__mkl_find_library(MKL_BLACS_OMPI_64BIT_LIB mkl_blacs_openmpi_ilp64)
|
|
|
|
# ScaLAPACK
|
|
#
|
|
__mkl_find_library(MKL_SCALAPACK_32BIT_LIB mkl_scalapack_lp64)
|
|
__mkl_find_library(MKL_SCALAPACK_64BIT_LIB mkl_scalapack_ilp64)
|
|
|
|
# Check if core libs were found
|
|
#
|
|
find_package_handle_standard_args(MKL REQUIRED_VARS CP2K_MKL_INCLUDE_DIRS
|
|
Threads_FOUND)
|
|
|
|
# Sequential has no threading dependency. There is currently no TBB module
|
|
# shipped with CMake. The dependency is not accounted for. (FIXME)
|
|
#
|
|
set(_mkl_dep_found_SEQ TRUE)
|
|
set(_mkl_dep_found_TBB TRUE)
|
|
if(TARGET OpenMP::OpenMP_CXX)
|
|
set(_mkl_dep_OMP ${OpenMP_CXX_LIBRARIES})
|
|
set(_mkl_dep_found_OMP TRUE)
|
|
endif()
|
|
|
|
# Define all blas, blacs and scalapack
|
|
#
|
|
foreach(_libtype "ST" "DYN")
|
|
set(_mkl_core_lib ${MKL_CORE_LIB_${_libtype}})
|
|
foreach(_bits "32BIT" "64BIT")
|
|
set(_mkl_scalapack_lib ${MKL_SCALAPACK_${_bits}_LIB_${_libtype}})
|
|
foreach(_iface "INTEL" "GF")
|
|
set(_mkl_interface_lib
|
|
${MKL_INTERFACE_${_iface}_${_bits}_LIB_${_libtype}})
|
|
foreach(_threading "SEQ" "OMP" "TBB")
|
|
set(_mkl_threading_lib ${MKL_${_threading}_LIB_${_libtype}})
|
|
|
|
string(TOLOWER "${_iface}_${_bits}_${_threading}_${_libtype}"
|
|
_tgt_config)
|
|
set(_mkl_tgt cp2k::BLAS::MKL::${_tgt_config})
|
|
|
|
if(MKL_FOUND
|
|
AND _mkl_interface_lib
|
|
AND _mkl_threading_lib
|
|
AND _mkl_core_lib
|
|
AND _mkl_dep_found_${_threading}
|
|
AND NOT TARGET ${_mkl_tgt})
|
|
set(_mkl_libs
|
|
"${_mkl_linker_pre_flags_${_threading}}"
|
|
"${_mkl_interface_lib}"
|
|
"${_mkl_threading_lib}"
|
|
"${_mkl_core_lib}"
|
|
"${_mkl_linker_post_flags_${_threading}}"
|
|
"${_mkl_dep_${_threading}}"
|
|
"Threads::Threads")
|
|
add_library(${_mkl_tgt} INTERFACE IMPORTED)
|
|
set_target_properties(
|
|
${_mkl_tgt}
|
|
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CP2K_MKL_INCLUDE_DIRS}"
|
|
INTERFACE_LINK_LIBRARIES "${_mkl_libs}")
|
|
endif()
|
|
|
|
foreach(_mpi_impl "MPICH" "OMPI")
|
|
set(_mkl_blacs_lib ${MKL_BLACS_${_mpi_impl}_${_bits}_LIB_${_libtype}})
|
|
|
|
string(
|
|
TOLOWER "${_mpi_impl}_${_iface}_${_bits}_${_threading}_${_libtype}"
|
|
_tgt_config)
|
|
|
|
if(_mkl_blacs_lib
|
|
AND TARGET ${_mkl_tgt}
|
|
AND TARGET MPI::MPI_CXX
|
|
AND NOT TARGET cp2k::BLAS::MKL::blacs_${_tgt_config})
|
|
set(_blacs_libs
|
|
"${_mkl_linker_pre_flags_${_libtype}}"
|
|
"${_mkl_interface_lib}"
|
|
"${_mkl_threading_lib}"
|
|
"${_mkl_core_lib}"
|
|
"${_mkl_blacs_lib}"
|
|
"${_mkl_linker_post_flags_${_libtype}}"
|
|
"MPI::MPI_CXX"
|
|
"${_mkl_dep_${_threading}}"
|
|
"Threads::Threads")
|
|
add_library(cp2k::BLAS::MKL::blacs_${_tgt_config} INTERFACE
|
|
IMPORTED)
|
|
set_target_properties(
|
|
cp2k::BLAS::MKL::blacs_${_tgt_config}
|
|
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
|
"${CP2K_MKL_INCLUDE_DIRS}" INTERFACE_LINK_LIBRARIES
|
|
"${_mkl_blacs_lib}")
|
|
endif()
|
|
|
|
if(_mkl_scalapack_lib AND NOT TARGET
|
|
cp2k::BLAS::MKL::scalapack_${_tgt_config})
|
|
set(_scalapack_libs "${_mkl_scalapack_lib}")
|
|
if(TARGET cp2k::BLAS::MKL::blacs_${_tgt_config})
|
|
list(APPEND _scalapack_libs cp2k::BLAS::MKL::blacs_${_tgt_config})
|
|
endif()
|
|
add_library(cp2k::BLAS::MKL::scalapack_${_tgt_config} INTERFACE
|
|
IMPORTED)
|
|
set_target_properties(
|
|
cp2k::BLAS::MKL::scalapack_${_tgt_config}
|
|
PROPERTIES INTERFACE_LINK_LIBRARIES "${_scalapack_libs}")
|
|
endif()
|
|
endforeach()
|
|
endforeach()
|
|
endforeach()
|
|
endforeach()
|
|
endforeach()
|
|
|
|
if(MKL_FOUND)
|
|
# BLAS in the Intel MKL 10+ library?
|
|
|
|
# the findMKL package finds all possible combination and define target for
|
|
# each of them we just need to find which compiler we use, mpi etc...
|
|
|
|
if(CMAKE_Fortran_COMPILER_LOADED
|
|
AND CMAKE_Fortran_COMPILER_ID STREQUAL "GNU"
|
|
AND NOT APPLE)
|
|
set(BLAS_mkl_INTFACE "gf")
|
|
else()
|
|
set(BLAS_mkl_INTFACE "intel")
|
|
endif()
|
|
|
|
if(CP2K_BLAS_THREADING STREQUAL "sequential")
|
|
set(BLAS_mkl_thread__ "seq")
|
|
elseif(CP2K_BLAS_THREADING MATCHES
|
|
"^(thread|gnu-thread|intel-thread|openmp)$")
|
|
set(BLAS_mkl_thread__ "omp")
|
|
elseif(CP2K_BLAS_THREADING STREQUAL "tbb-thread")
|
|
set(BLAS_mkl_thread__ "tbb")
|
|
endif()
|
|
|
|
if(CP2K_BLAS_INTERFACE MATCHES "64bits")
|
|
set(BLAS_mkl_ILP_MODE "64bit")
|
|
else()
|
|
set(BLAS_mkl_ILP_MODE "32bit")
|
|
endif()
|
|
|
|
get_target_property(
|
|
MKL_BLAS_INCLUDE_DIRS
|
|
cp2k::BLAS::MKL::${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE}_${BLAS_mkl_thread__}_dyn
|
|
INTERFACE_INCLUDE_DIRECTORIES)
|
|
get_target_property(
|
|
MKL_BLAS_LIBRARIES
|
|
cp2k::BLAS::MKL::${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE}_${BLAS_mkl_thread__}_dyn
|
|
INTERFACE_LINK_LIBRARIES)
|
|
if(NOT TARGET cp2k::BLAS::MKL::blas)
|
|
add_library(cp2k::BLAS::MKL::MKL INTERFACE IMPORTED)
|
|
add_library(cp2k::BLAS::MKL::blas ALIAS cp2k::BLAS::MKL::MKL)
|
|
# create a empty lapack
|
|
add_library(cp2k::BLAS::MKL::lapack INTERFACE IMPORTED)
|
|
endif()
|
|
set_target_properties(
|
|
cp2k::BLAS::MKL::MKL
|
|
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CP2K_MKL_INCLUDE_DIRS}"
|
|
INTERFACE_LINK_LIBRARIES "${MKL_BLAS_LIBRARIES}")
|
|
|
|
if("${MPI_Fortran_LIBRARY_VERSION_STRING}" MATCHES "Open MPI")
|
|
set(__mkl_mpi_ver_ "ompi")
|
|
else()
|
|
set(__mkl_mpi_ver_ "mpich")
|
|
endif()
|
|
|
|
get_target_property(
|
|
__mkl_scalapack_inc
|
|
cp2k::BLAS::MKL::scalapack_${__mkl_mpi_ver_}_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE}_${BLAS_mkl_thread__}_dyn
|
|
INTERFACE_INCLUDE_DIRECTORIES)
|
|
get_target_property(
|
|
__mkl_scalapack_lib
|
|
cp2k::BLAS::MKL::scalapack_${__mkl_mpi_ver_}_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE}_${BLAS_mkl_thread__}_dyn
|
|
INTERFACE_LINK_LIBRARIES)
|
|
get_target_property(
|
|
__mkl_blacs_inc
|
|
cp2k::BLAS::MKL::blacs_${__mkl_mpi_ver_}_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE}_${BLAS_mkl_thread__}_dyn
|
|
INTERFACE_INCLUDE_DIRECTORIES)
|
|
get_target_property(
|
|
__mkl_blacs_lib
|
|
cp2k::BLAS::MKL::blacs_${__mkl_mpi_ver_}_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE}_${BLAS_mkl_thread__}_dyn
|
|
INTERFACE_LINK_LIBRARIES)
|
|
if(NOT TARGET cp2k::BLAS::MKL::scalapack_link)
|
|
add_library(cp2k::BLAS::MKL::scalapack_link INTERFACE IMPORTED)
|
|
set_target_properties(
|
|
cp2k::BLAS::MKL::scalapack_link
|
|
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${__mkl_scalapack_inc}"
|
|
INTERFACE_LINK_LIBRARIES
|
|
"${__mkl_scalapack_lib};${__mkl_blacs_lib}")
|
|
endif()
|
|
unset(BLAS_mkl_ILP_MODE)
|
|
unset(BLAS_mkl_INTFACE)
|
|
unset(BLAS_mkl_thread__)
|
|
unset(BLAS_mkl_OMP)
|
|
unset(BLAS_mkl_OS_NAME)
|
|
unset(__mkl_blacs_lib)
|
|
unset(__mkl_blacs_inc)
|
|
unset(__mkl_scalapack_lib)
|
|
unset(__mkl_scalapack_inc)
|
|
set(CP2K_BLAS_VENDOR "MKL")
|
|
mark_as_advanced(CP2K_BLAS_VENDOR)
|
|
mark_as_advanced(CP2K_MKL_FOUND)
|
|
endif()
|