1 # Helper macro for the function below. We treat BLAS and LAPACK the same
2 # way, so there's no reason to duplicate the logic for them
4 # MESSSAGE_TEXT variable is accumulated while checks for these
5 # libraries fail, but the message is only emitted if we are forced to
6 # fall back on the internal version.
9 # name "BLAS" or "LAPACK"
10 # function_in_library the name of a function to use in a linking test of that library
11 macro(manage_linear_algebra_library name function_in_library)
12 set(_library_was_found 0)
13 set(_find_quietly FALSE)
14 set(_user_var_changed FALSE)
15 if(NOT DEFINED GMX_EXTERNAL_${name} OR
16 (GMX_EXTERNAL_${name} AND NOT "${GMX_${name}_USER}" STREQUAL "${GMX_${name}_USER_PREV}"))
17 set(_user_var_changed TRUE)
19 if(DEFINED GMX_EXTERNAL_${name} AND NOT _user_var_changed)
20 set(_find_quietly TRUE)
23 # We could consider printing status messages at the beginning and
24 # end, which would require caching whether the previous provider
25 # was user/MKL/external/internal. It's possible (we do it for
26 # FFT), but the number of times the user changes these is pretty
27 # low, so let's solve that one in master branch when we have
28 # better CMake gear to support it.
29 if(GMX_EXTERNAL_${name} OR NOT DEFINED GMX_EXTERNAL_${name})
30 set(GMX_${name}_USER_PREV ${GMX_${name}_USER} CACHE INTERNAL
31 "Previous value of GMX_${name}_USER (to detect changes)" FORCE)
33 # Check for user-specified libraries if external libraries have
34 # been specified (which is the default).
36 set(_libraries_to_link ${GMX_${name}_USER})
37 set(_library_was_found 1)
40 set(CMAKE_REQUIRED_LIBRARIES ${GMX_${name}_USER})
42 unset(_${name}_user_works CACHE)
44 message(STATUS "Checking that user ${name} library ${GMX_${name}_USER} works")
45 check_function_exists(${function_in_library} _${name}_user_works)
46 if(NOT _${name}_user_works)
47 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.")
51 message(STATUS "MKL and GMX_${name}_USER were both specified. Using the latter for ${name}.")
56 if(NOT _library_was_found AND HAVE_LIBMKL)
57 set(CMAKE_REQUIRED_LIBRARIES ${FFT_LINKER_FLAGS} ${FFT_LIBRARIES})
58 # This may also not work correctly if the user changes
59 # MKL_LIBRARIES after the first run. However,
60 # MKL_LIBRARIES is only needed for icc version < 11, or
61 # for trying to use MKL with a non-Intel compiler, and we
62 # can live with that for now.
63 check_function_exists(${function_in_library} _${name}_mkl_works)
64 if(_${name}_mkl_works)
65 # If we ever need to compile with MKL linear algebra and
66 # not with FFT supplied by MKL, uncomment the next line
67 # (and probably tweak other things).
68 # list(APPEND LINEAR_ALGEBRA_LIBRARIES ${FFT_LINKER_FLAGS} ${FFT_LIBRARIES})
69 set(_library_was_found 1)
71 set(_message_text "Intel's MKL was specified, and it should provide ${name}, but it does not. ")
75 # If detection of ${name} has never run, or none of the preceding
76 # detection succeeded, try to detect ${name} in the CMake
77 # detection paths, etc.
78 if (NOT _library_was_found)
79 set(${name}_FIND_QUIETLY _find_quietly)
80 # Note that this finds all kinds of system libraries,
81 # including Apple's Accelerate Framework (and perhaps MKL for
85 set(_libraries_to_link ${${name}_LIBRARIES})
86 set(_library_was_found 1)
90 if (NOT _library_was_found AND NOT _find_quietly)
91 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.")
95 # Default behaviour is to try to use an external library, but fall
96 # back on the internal one if none is found.
97 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)")
98 mark_as_advanced(GMX_EXTERNAL_${name})
99 # Default behaviour is to use a library found on the system or in
100 # GROMACS. The user must actively set GMX_${name}_USER if they
101 # want to specify a library.
102 set(GMX_${name}_USER "" CACHE BOOL "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)")
103 mark_as_advanced(GMX_${name}_USER)
105 if(GMX_EXTERNAL_${name})
106 if (NOT _library_was_found)
107 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.")
109 # Actually trigger linking.
110 list(APPEND LINEAR_ALGEBRA_LIBRARIES ${_libraries_to_link})
112 # Triggering the compilation of the internal version of the library is handled elsewhere.
116 # The default behaviour is to try to detect an "external" BLAS and/or
117 # LAPACK, perhaps provided by a vendor, use those if found, and
118 # otherwise fall back on the GROMACS internal implementations of
119 # these. If the libraries are not in a standard location, the user can
120 # indicate a search path with CMAKE_PREFIX_PATH.
122 # However, if we are using icc+mkl (so a build command that includes
123 # -mkl), then it is probably painful to try to link some other BLAS or
124 # LAPACK. In that case, we use the BLAS & LAPACK provided by MKL. In
125 # principle, we could offer a more configurable behaviour if/when
126 # there is need to (say) use vendor BLAS with MKL for FFTs.
128 # If the vendor BLAS and/or LAPACK have abnormal library names, then
129 # the default searching procedure will fail (e.g. Redmine #771). The
130 # GMX_(BLAS|LAPACK)_USER variables can be used to indicate the correct
131 # libraries. If these do not work, a warning is emitted and we try to
132 # use them anyway, assuming the user knows what they are doing.
135 # GMX_EXTERNAL_BLAS user input about whether to detect BLAS
136 # GMX_EXTERNAL_LAPACK user input about whether to detect LAPACK
137 # HAVE_LIBMKL true if the build will link to MKL
138 # FFT_LINKER_FLAGS used iff HAVE_MKL
139 # FFT_LIBRARIES used iff HAVE_MKL
140 # GMX_BLAS_USER user input for BLAS libraries to use
141 # GMX_LAPACK_USER user input for LAPACK libraries to use
143 # This function sets the following cache variables:
144 # GMX_EXTERNAL_BLAS according to whether external BLAS is being used
145 # GMX_EXTERNAL_LAPACK according to whether external LAPACK is being used
146 # GMX_BLAS_USER off = use a system library;
147 # any other value = full path to the library to use
148 # GMX_LAPACK_USER off = use a system library;
149 # any other value = full path to the library to use
151 # This function sets the following variables in its parent scope:
152 # LINEAR_ALGEBRA_LIBRARIES will be set as required to add libraries required for linear algebra
154 function(gmxManageLinearAlgebraLibraries)
155 include(CheckFunctionExists)
156 # Probably not necessary to unset, but let's be clear about usage.
157 unset(LINEAR_ALGEBRA_LIBRARIES)
159 manage_linear_algebra_library(BLAS dgemm_)
160 set(BLAS_FIND_QUIETLY ON)
161 manage_linear_algebra_library(LAPACK cheev_)
163 # Propagate the new local value to the parent scope
164 set(LINEAR_ALGEBRA_LIBRARIES "${LINEAR_ALGEBRA_LIBRARIES}" PARENT_SCOPE)
167 gmxManageLinearAlgebraLibraries()