2 # This file is part of the GROMACS molecular simulation package.
4 # Copyright (c) 2013,2014,2016,2020, by the GROMACS development team, led by
5 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 # and including many others, as listed in the AUTHORS file in the
7 # top-level source directory and at http://www.gromacs.org.
9 # GROMACS is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public License
11 # as published by the Free Software Foundation; either version 2.1
12 # of the License, or (at your option) any later version.
14 # GROMACS is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 # Lesser General Public License for more details.
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with GROMACS; if not, see
21 # http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 # If you want to redistribute modifications to GROMACS, please
25 # consider that scientific software is very special. Version
26 # control is crucial - bugs must be traceable. We will be happy to
27 # consider code for inclusion in the official distribution, but
28 # derived work must not be called official GROMACS. Details are found
29 # in the README & COPYING files - if they are missing, get the
30 # official version at http://www.gromacs.org.
32 # To help us fund GROMACS development, we humbly ask that you cite
33 # the research papers on the package. Check out http://www.gromacs.org.
35 # Helper macro for the function below. We treat BLAS and LAPACK the same
36 # way, so there's no reason to duplicate the logic for them
38 # MESSSAGE_TEXT variable is accumulated while checks for these
39 # libraries fail, but the message is only emitted if we are forced to
40 # fall back on the internal version.
42 # Arguments should be:
43 # name "BLAS" or "LAPACK"
44 # function_in_library the name of a function to use in a linking test of that library
45 macro(manage_linear_algebra_library name function_in_library)
46 set(_library_was_found 0)
48 # We could consider printing status messages at the beginning and
49 # end, which would require caching whether the previous provider
50 # was user/MKL/external/internal. It's possible (we do it for
51 # FFT), but the number of times the user changes these is pretty
52 # low, so let's solve that one in master branch when we have
53 # better CMake gear to support it.
54 if(GMX_EXTERNAL_${name} OR NOT DEFINED GMX_EXTERNAL_${name})
55 set(_find_quietly FALSE)
56 gmx_check_if_changed(_user_var_changed GMX_${name}_USER)
57 if (NOT DEFINED GMX_EXTERNAL_${name})
58 set(_user_var_changed TRUE)
60 if(DEFINED GMX_EXTERNAL_${name} AND NOT _user_var_changed)
61 set(_find_quietly TRUE)
64 # Check for user-specified libraries if external libraries have
65 # been specified (which is the default).
67 set(_libraries_to_link ${GMX_${name}_USER})
68 set(_library_was_found 1)
71 set(CMAKE_REQUIRED_LIBRARIES ${GMX_${name}_USER})
73 unset(_${name}_user_works CACHE)
75 message(STATUS "Checking that user ${name} library ${GMX_${name}_USER} works")
76 check_function_exists(${function_in_library} _${name}_user_works)
77 if(NOT _${name}_user_works)
78 message(WARNING "GMX_${name}_USER library ${GMX_${name}_USER} was specified, but it may not provide ${name}. We are proceeding by assuming you know what you are doing and that linking F77-style to this library will work.")
82 message(STATUS "MKL and GMX_${name}_USER were both specified. Using the latter for ${name}.")
87 if(NOT _library_was_found AND HAVE_LIBMKL)
88 set(CMAKE_REQUIRED_LIBRARIES "${FFT_LIBRARIES}")
89 set(CMAKE_REQUIRED_FLAGS "${FFT_LINKER_FLAGS}")
90 # This may also not work correctly if the user changes
91 # MKL_LIBRARIES after the first run. However,
92 # MKL_LIBRARIES is only needed
93 # for trying to use MKL with a non-Intel compiler, and we
94 # can live with that for now.
95 check_function_exists(${function_in_library} _${name}_mkl_works)
96 if(_${name}_mkl_works)
97 # If we ever need to compile with MKL linear algebra and
98 # not with FFT supplied by MKL, uncomment the next line
99 # (and probably tweak other things).
100 # list(APPEND LINEAR_ALGEBRA_LIBRARIES ${FFT_LINKER_FLAGS} ${FFT_LIBRARIES})
101 set(_library_was_found 1)
103 set(_message_text "Intel's MKL was specified, and it should provide ${name}, but it does not. ")
107 # If detection of ${name} has never run, or none of the preceding
108 # detection succeeded, try to detect ${name} in the CMake
109 # detection paths, etc.
110 if (NOT _library_was_found)
111 set(${name}_FIND_QUIETLY ${_find_quietly})
112 # Note that this finds all kinds of system libraries,
113 # including Apple's Accelerate Framework
114 find_package(${name})
116 set(_libraries_to_link ${${name}_LIBRARIES})
117 set(_library_was_found 1)
121 if (NOT _library_was_found AND NOT _find_quietly)
122 message(STATUS "${_message_text}Using GROMACS built-in ${name}.")
126 # Default behaviour is to try to use an external library, but fall
127 # back on the internal one if none is found.
128 set(GMX_EXTERNAL_${name} ${_library_was_found} CACHE BOOL "Use a ${name} library that is external to GROMACS if possible (ON), or the internal GROMACS one (OFF)")
129 mark_as_advanced(GMX_EXTERNAL_${name})
130 # Default behaviour is to use a library found on the system or in
131 # GROMACS. The user must actively set GMX_${name}_USER if they
132 # want to specify a library.
133 gmx_dependent_cache_variable(
135 "Use a ${name} library found on the system (OFF), or a ${name} library supplied by the user (any other value, which is a full path to that ${name} library)"
136 FILEPATH "" GMX_EXTERNAL_${name})
137 mark_as_advanced(GMX_${name}_USER)
139 if(GMX_EXTERNAL_${name})
140 if (NOT _library_was_found)
141 message(FATAL_ERROR "You have set GMX_EXTERNAL_${name}=ON to instruct GROMACS to use an external ${name} library, but no external library could be detected.")
143 # Actually trigger linking.
144 list(APPEND LINEAR_ALGEBRA_LIBRARIES ${_libraries_to_link})
146 # Triggering the compilation of the internal version of the library is handled elsewhere.
150 # The default behaviour is to try to detect an "external" BLAS and/or
151 # LAPACK, perhaps provided by a vendor, use those if found, and
152 # otherwise fall back on the GROMACS internal implementations of
153 # these. If the libraries are not in a standard location, the user can
154 # indicate a search path with CMAKE_PREFIX_PATH.
156 # However, if we are using icc+mkl (so a build command that includes
157 # -mkl), then it is probably painful to try to link some other BLAS or
158 # LAPACK. In that case, we use the BLAS & LAPACK provided by MKL. In
159 # principle, we could offer a more configurable behaviour if/when
160 # there is need to (say) use vendor BLAS with MKL for FFTs.
162 # If the vendor BLAS and/or LAPACK have abnormal library names, then
163 # the default searching procedure will fail (e.g. Issue #771). The
164 # GMX_(BLAS|LAPACK)_USER variables can be used to indicate the correct
165 # libraries. If these do not work, a warning is emitted and we try to
166 # use them anyway, assuming the user knows what they are doing.
169 # GMX_EXTERNAL_BLAS user input about whether to detect BLAS
170 # GMX_EXTERNAL_LAPACK user input about whether to detect LAPACK
171 # HAVE_LIBMKL true if the build will link to MKL
172 # FFT_LINKER_FLAGS used iff HAVE_MKL
173 # FFT_LIBRARIES used iff HAVE_MKL
174 # GMX_BLAS_USER user input for BLAS libraries to use
175 # GMX_LAPACK_USER user input for LAPACK libraries to use
177 # This function sets the following cache variables:
178 # GMX_EXTERNAL_BLAS according to whether external BLAS is being used
179 # GMX_EXTERNAL_LAPACK according to whether external LAPACK is being used
180 # GMX_BLAS_USER off = use a system library;
181 # any other value = full path to the library to use
182 # GMX_LAPACK_USER off = use a system library;
183 # any other value = full path to the library to use
185 # This function sets the following variables in its parent scope:
186 # LINEAR_ALGEBRA_LIBRARIES will be set as required to add libraries required for linear algebra
188 function(gmxManageLinearAlgebraLibraries)
189 include(CheckFunctionExists)
190 # Probably not necessary to unset, but let's be clear about usage.
191 unset(LINEAR_ALGEBRA_LIBRARIES)
193 manage_linear_algebra_library(BLAS dgemm_)
194 set(BLAS_FIND_QUIETLY ON)
195 manage_linear_algebra_library(LAPACK cheev_)
197 # Propagate the new local value to the parent scope
198 set(LINEAR_ALGEBRA_LIBRARIES "${LINEAR_ALGEBRA_LIBRARIES}" PARENT_SCOPE)
201 gmxManageLinearAlgebraLibraries()