bcbc8bab5704a984046d0db6713d9ec591d946c3
[alexxy/gromacs.git] / cmake / gmxManageLinearAlgebraLibraries.cmake
1 #
2 # This file is part of the GROMACS molecular simulation package.
3 #
4 # Copyright (c) 2013, 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.
8 #
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.
13 #
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.
18 #
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.
23 #
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.
31 #
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.
34
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
37 #
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.
41 #
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)
47
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)
69
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()
80
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()
86
87         if(NOT _library_was_found AND HAVE_LIBMKL)
88             set(CMAKE_REQUIRED_LIBRARIES ${FFT_LINKER_FLAGS} ${FFT_LIBRARIES})
89             # This may also not work correctly if the user changes
90             # MKL_LIBRARIES after the first run. However,
91             # MKL_LIBRARIES is only needed for icc version < 11, or
92             # for trying to use MKL with a non-Intel compiler, and we
93             # can live with that for now.
94             check_function_exists(${function_in_library} _${name}_mkl_works)
95             if(_${name}_mkl_works)
96                 # If we ever need to compile with MKL linear algebra and
97                 # not with FFT supplied by MKL, uncomment the next line
98                 # (and probably tweak other things).
99 #                list(APPEND LINEAR_ALGEBRA_LIBRARIES ${FFT_LINKER_FLAGS} ${FFT_LIBRARIES})
100                 set(_library_was_found 1)
101             else()
102                 set(_message_text "Intel's MKL was specified, and it should provide ${name}, but it does not. ")
103             endif()
104         endif()
105
106         # If detection of ${name} has never run, or none of the preceding
107         # detection succeeded, try to detect ${name} in the CMake
108         # detection paths, etc.
109         if (NOT _library_was_found)
110             set(${name}_FIND_QUIETLY ${_find_quietly})
111             # Note that this finds all kinds of system libraries,
112             # including Apple's Accelerate Framework (and perhaps MKL for
113             # icc < 11).
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()
120
121         if (NOT _library_was_found AND NOT _find_quietly)
122             message("${_message_text}A ${name} library was not found by CMake in the paths available to it. Falling back on the GROMACS internal version of the ${name} library instead. This is fine for normal usage.")
123         endif()
124     endif()
125
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)
138
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()
149
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.
155 #
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.
161 #
162 # If the vendor BLAS and/or LAPACK have abnormal library names, then
163 # the default searching procedure will fail (e.g. Redmine #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.
167
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
176 #
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
184 #
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
187 #
188 function(gmxManageLinearAlgebraLibraries)
189     include(CheckFunctionExists)
190     # Probably not necessary to unset, but let's be clear about usage.
191     unset(LINEAR_ALGEBRA_LIBRARIES)
192
193     manage_linear_algebra_library(BLAS dgemm_)
194     set(BLAS_FIND_QUIETLY ON)
195     manage_linear_algebra_library(LAPACK cheev_)
196
197     # Propagate the new local value to the parent scope
198     set(LINEAR_ALGEBRA_LIBRARIES "${LINEAR_ALGEBRA_LIBRARIES}" PARENT_SCOPE)
199 endfunction()
200
201 gmxManageLinearAlgebraLibraries()