Merge branch 'origin/release-2020' into merge-2020-into-2021
[gromacs.git] / cmake / gmxManageLinearAlgebraLibraries.cmake
blobbb5a5e61655e5ff2bd9227cb92f633914353f5fc
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)
59         endif()
60         if(DEFINED GMX_EXTERNAL_${name} AND NOT _user_var_changed)
61             set(_find_quietly TRUE)
62         endif()
63         set(_message_text)
64         # Check for user-specified libraries if external libraries have
65         # been specified (which is the default).
66         if(GMX_${name}_USER)
67             set(_libraries_to_link ${GMX_${name}_USER})
68             set(_library_was_found 1)
70             if(NOT _find_quietly)
71                 set(CMAKE_REQUIRED_LIBRARIES ${GMX_${name}_USER})
72                 if(_user_var_changed)
73                     unset(_${name}_user_works CACHE)
74                 endif()
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.")
79                 endif()
81                 if(HAVE_LIBMKL)
82                     message(STATUS "MKL and GMX_${name}_USER were both specified. Using the latter for ${name}.")
83                 endif()
84             endif()
85         endif()
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)
102             else()
103                 set(_message_text "Intel's MKL was specified, and it should provide ${name}, but it does not. ")
104             endif()
105         endif()
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})
115             if (${name}_FOUND)
116                 set(_libraries_to_link ${${name}_LIBRARIES})
117                 set(_library_was_found 1)
118             endif()
119         endif()
121         if (NOT _library_was_found AND NOT _find_quietly)
122             message(STATUS "${_message_text}Using GROMACS built-in ${name}.")
123         endif()
124     endif()
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(
134         GMX_${name}_USER
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.")
142         endif()
143         # Actually trigger linking.
144         list(APPEND LINEAR_ALGEBRA_LIBRARIES ${_libraries_to_link})
145     else()
146         # Triggering the compilation of the internal version of the library is handled elsewhere.
147     endif()
148 endmacro()
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.
168 # Inputs:
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)
199 endfunction()
201 gmxManageLinearAlgebraLibraries()