find_blas.cmake 15.8 KB
Newer Older
1
2
3
4
5
#
# This is a CMake makefile.  You can find the cmake utility and
# information about it at http://www.cmake.org
#
#
6
# This cmake file tries to find installed BLAS and LAPACK libraries.  
7
# It looks for an installed copy of the Intel MKL library first and then
8
9
# attempts to find some other BLAS and LAPACK libraries if you don't have 
# the Intel MKL.
10
#
11
12
13
14
15
16
17
18
#  blas_found               - True if BLAS is available
#  lapack_found             - True if LAPACK is available
#  found_intel_mkl          - True if the Intel MKL library is available
#  found_intel_mkl_headers  - True if Intel MKL headers are available
#  blas_libraries           - link against these to use BLAS library 
#  lapack_libraries         - link against these to use LAPACK library 
#  mkl_libraries            - link against these to use the MKL library
#  mkl_include_dir          - add to the include path to use the MKL library
Davis King's avatar
Davis King committed
19
#  openmp_libraries         - Set to Intel's OpenMP library if and only if we
20
#                             find the MKL.
21
22
23
24
25

# setting this makes CMake allow normal looking if else statements
SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)

SET(blas_found 0)
26
SET(lapack_found 0)
27
SET(found_intel_mkl 0)
28
SET(found_intel_mkl_headers 0)
29
30
SET(lapack_with_underscore 0)
SET(lapack_without_underscore 0)
31

Davis King's avatar
Cleanup  
Davis King committed
32
message(STATUS "Searching for BLAS and LAPACK")
33

34
if (UNIX OR MINGW)
Davis King's avatar
Davis King committed
35
36
37
   message(STATUS "Searching for BLAS and LAPACK")

   if (BUILDING_MATLAB_MEX_FILE)
Davis King's avatar
merged  
Davis King committed
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
      # # This commented out stuff would link directly to MATLAB's built in
      # BLAS and LAPACK. But it's better to not link to anything and do a
      #find_library(MATLAB_BLAS_LIBRARY mwblas  PATHS ${MATLAB_LIB_FOLDERS} )
      #find_library(MATLAB_LAPACK_LIBRARY mwlapack  PATHS ${MATLAB_LIB_FOLDERS} )
      #if (MATLAB_BLAS_LIBRARY AND MATLAB_LAPACK_LIBRARY)
      #    add_subdirectory(external/cblas)
      #    set(blas_libraries  ${MATLAB_BLAS_LIBRARY} cblas  )
      #    set(lapack_libraries  ${MATLAB_LAPACK_LIBRARY} )
      #    set(blas_found 1)
      #    set(lapack_found 1)
      #    message(STATUS "Found MATLAB's BLAS and LAPACK libraries")
      #endif()

      # We need cblas since MATLAB doesn't provide cblas symbols.
      add_subdirectory(external/cblas)
      set(blas_libraries  cblas  )
      set(blas_found 1)
      set(lapack_found 1)
      message(STATUS "Will link with MATLAB's BLAS and LAPACK at runtime (hopefully!)")


      ## Don't try to link to anything other than MATLAB's own internal blas
      ## and lapack libraries because doing so generally upsets MATLAB.  So
      ## we just end here no matter what.
Davis King's avatar
Davis King committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
      return()
   endif()

   # First, search for libraries via pkg-config, which is the cleanest path
   find_package(PkgConfig)
   pkg_check_modules(BLAS_REFERENCE cblas)
   pkg_check_modules(LAPACK_REFERENCE lapack)
   if (BLAS_REFERENCE_FOUND AND LAPACK_REFERENCE_FOUND)
      set(blas_libraries "${BLAS_REFERENCE_LDFLAGS}")
      set(lapack_libraries "${LAPACK_REFERENCE_LDFLAGS}")
      set(blas_found 1)
      set(lapack_found 1)
      set(REQUIRES_LIBS "${REQUIRES_LIBS} cblas lapack")
      message(STATUS "Found BLAS and LAPACK via pkg-config")
      return()
   endif()

   include(CheckTypeSize)
   check_type_size( "void*" SIZE_OF_VOID_PTR)

   if (SIZE_OF_VOID_PTR EQUAL 8)
      set( mkl_search_path
         /opt/intel/mkl/*/lib/em64t
         /opt/intel/mkl/lib/intel64
         /opt/intel/lib/intel64
         /opt/intel/mkl/lib
         )

      find_library(mkl_intel mkl_intel_lp64 ${mkl_search_path})
      mark_as_advanced(mkl_intel)
   else()
      set( mkl_search_path
         /opt/intel/mkl/*/lib/32
         /opt/intel/mkl/lib/ia32
         /opt/intel/lib/ia32
         )

      find_library(mkl_intel mkl_intel ${mkl_search_path})
      mark_as_advanced(mkl_intel)
   endif()
102
103
104

   include(CheckLibraryExists)

Davis King's avatar
Davis King committed
105
106
107
108
109
110
111
112
   # Get mkl_include_dir
   set(mkl_include_search_path
      /opt/intel/mkl/include
      /opt/intel/include
      )
   find_path(mkl_include_dir mkl_version.h ${mkl_include_search_path})
   mark_as_advanced(mkl_include_dir)

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
   if(NOT DLIB_USE_MKL_SEQUENTIAL)
      # Search for the needed libraries from the MKL.  We will try to link against the mkl_rt
      # file first since this way avoids linking bugs in some cases.
      find_library(mkl_rt mkl_rt ${mkl_search_path})
      find_library(openmp_libraries iomp5 ${mkl_search_path}) 
      mark_as_advanced(mkl_rt  openmp_libraries)
      # if we found the MKL 
      if (mkl_rt)
         set(mkl_libraries  ${mkl_rt} )
         set(blas_libraries  ${mkl_rt} )
         set(lapack_libraries  ${mkl_rt} )
         set(blas_found 1)
         set(lapack_found 1)
         set(found_intel_mkl 1)
         message(STATUS "Found Intel MKL BLAS/LAPACK library")
      endif()
Davis King's avatar
Davis King committed
129
   endif()
130
   
Davis King's avatar
Davis King committed
131
132
133
134
135

   if (NOT found_intel_mkl)
      # Search for the needed libraries from the MKL.  This time try looking for a different
      # set of MKL files and try to link against those.
      find_library(mkl_core mkl_core ${mkl_search_path})
136
137
138
139
140
141
142
143
144
145
146
147
148
149
      set(mkl_libs ${mkl_intel} ${mkl_core})
      mark_as_advanced(mkl_libs mkl_intel mkl_core)
      if (DLIB_USE_MKL_SEQUENTIAL)
         find_library(mkl_sequential mkl_sequential ${mkl_search_path})
         mark_as_advanced(mkl_sequential)
         list(APPEND mkl_libs ${mkl_sequential})
      else()
         find_library(mkl_thread mkl_intel_thread ${mkl_search_path})
         find_library(mkl_iomp iomp5 ${mkl_search_path})
         find_library(mkl_pthread pthread ${mkl_search_path})
         mark_as_advanced(mkl_thread mkl_iomp mkl_pthread)
         list(APPEND mkl_libs ${mkl_thread} ${mkl_iomp} ${mkl_pthread})
      endif()
   
Davis King's avatar
Davis King committed
150
      # If we found the MKL 
151
152
153
154
      if (mkl_intel AND mkl_core AND ((mkl_thread AND mkl_iomp AND mkl_pthread) OR mkl_sequential))
         set(mkl_libraries ${mkl_libs})
         set(blas_libraries ${mkl_libs})
         set(lapack_libraries ${mkl_libs})
Davis King's avatar
Davis King committed
155
156
157
158
159
160
         set(blas_found 1)
         set(lapack_found 1)
         set(found_intel_mkl 1)
         message(STATUS "Found Intel MKL BLAS/LAPACK library")
      endif()
   endif()
161

Davis King's avatar
Davis King committed
162
163
164
   if (found_intel_mkl AND mkl_include_dir)
      set(found_intel_mkl_headers 1)
   endif()
165

166
   # try to find some other LAPACK libraries if we didn't find the MKL
167
   set(extra_paths
Davis King's avatar
Davis King committed
168
169
170
171
172
173
174
175
176
177
178
179
      /usr/lib64
      /usr/lib64/atlas-sse3
      /usr/lib64/atlas-sse2
      /usr/lib64/atlas
      /usr/lib
      /usr/lib/atlas-sse3
      /usr/lib/atlas-sse2
      /usr/lib/atlas
      /usr/lib/openblas-base
      /opt/OpenBLAS/lib
      $ENV{OPENBLAS_HOME}/lib
      )
180
181
182
183

   INCLUDE (CheckFunctionExists)

   if (NOT blas_found)
Davis King's avatar
Davis King committed
184
      find_library(cblas_lib openblas PATHS ${extra_paths})
185
186
187
188
189
190
191
192
193
194
195
      if (cblas_lib)
         set(blas_libraries ${cblas_lib})
         set(blas_found 1)
         message(STATUS "Found OpenBLAS library")
         set(CMAKE_REQUIRED_LIBRARIES ${blas_libraries})
         # If you compiled OpenBLAS with LAPACK in it then it should have the
         # sgetrf_single function in it.  So if we find that function in
         # OpenBLAS then just use OpenBLAS's LAPACK. 
         CHECK_FUNCTION_EXISTS(sgetrf_single OPENBLAS_HAS_LAPACK)
         if (OPENBLAS_HAS_LAPACK)
            message(STATUS "Using OpenBLAS's built in LAPACK")
196
            # set(lapack_libraries gfortran) 
197
198
199
200
201
            set(lapack_found 1)
         endif()
      endif()
      mark_as_advanced( cblas_lib)
   endif()
202

203
204

   if (NOT lapack_found)
205
      find_library(lapack_lib NAMES lapack lapack-3 PATHS ${extra_paths})
206
207
208
209
210
211
      if (lapack_lib)
         set(lapack_libraries ${lapack_lib})
         set(lapack_found 1)
         message(STATUS "Found LAPACK library")
      endif()
      mark_as_advanced( lapack_lib)
212
213
   endif()

Davis King's avatar
Davis King committed
214

215
   # try to find some other BLAS libraries if we didn't find the MKL
Davis King's avatar
Davis King committed
216

217
   if (NOT blas_found)
218
219
      find_library(atlas_lib atlas PATHS ${extra_paths})
      find_library(cblas_lib cblas PATHS ${extra_paths})
220
221
      if (atlas_lib AND cblas_lib)
         set(blas_libraries ${atlas_lib} ${cblas_lib})
222
223
224
         set(blas_found 1)
         message(STATUS "Found ATLAS BLAS library")
      endif()
225
      mark_as_advanced( atlas_lib cblas_lib)
226
227
   endif()

228
229
230
231
232
233
234
235
236
237
238
239
   # CentOS 7 atlas
   if (NOT blas_found)
      find_library(tatlas_lib tatlas PATHS ${extra_paths})
      find_library(satlas_lib satlas PATHS ${extra_paths})
      if (tatlas_lib AND satlas_lib )
         set(blas_libraries ${tatlas_lib} ${satlas_lib})
         set(blas_found 1)
         message(STATUS "Found ATLAS BLAS library")
      endif()
      mark_as_advanced( tatlas_lib satlas_lib)
   endif()

240
241

   if (NOT blas_found)
242
      find_library(cblas_lib cblas PATHS ${extra_paths})
243
244
245
246
247
248
249
250
      if (cblas_lib)
         set(blas_libraries ${cblas_lib})
         set(blas_found 1)
         message(STATUS "Found CBLAS library")
      endif()
      mark_as_advanced( cblas_lib)
   endif()

Davis King's avatar
Davis King committed
251

252
   if (NOT blas_found)
253
      find_library(generic_blas blas PATHS ${extra_paths})
254
255
256
257
258
259
260
261
      if (generic_blas)
         set(blas_libraries ${generic_blas})
         set(blas_found 1)
         message(STATUS "Found BLAS library")
      endif()
      mark_as_advanced( generic_blas)
   endif()

262
263
264
265
266



   # Make sure we really found a CBLAS library.  That is, it needs to expose
   # the proper cblas link symbols.  So here we test if one of them is present
267
268
269
270
   # and assume everything is good if it is. Note that we don't do this check if
   # we found the Intel MKL since for some reason CHECK_FUNCTION_EXISTS doesn't work
   # with it.  But it's fine since the MKL should always have cblas.
   if (blas_found AND NOT found_intel_mkl)
271
272
273
274
275
276
277
278
279
280
      set(CMAKE_REQUIRED_LIBRARIES ${blas_libraries})
      CHECK_FUNCTION_EXISTS(cblas_ddot HAVE_CBLAS)
      if (NOT HAVE_CBLAS)
         message(STATUS "BLAS library does not have cblas symbols, so dlib will not use BLAS or LAPACK")
         set(blas_found 0)
         set(lapack_found 0)
      endif()
   endif()


281

282
elseif(WIN32 AND NOT MINGW)
Davis King's avatar
Davis King committed
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
   message(STATUS "Searching for BLAS and LAPACK")

   include(CheckTypeSize)
   check_type_size( "void*" SIZE_OF_VOID_PTR)
   if (SIZE_OF_VOID_PTR EQUAL 8)
      set( mkl_search_path
         "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries_*/windows/mkl/lib/intel64" 
         "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries_*/windows/compiler/lib/intel64" 
         "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/compiler/lib/intel64" 
         "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/intel64"
         "C:/Program Files (x86)/Intel/Composer XE/mkl/lib/intel64"
         "C:/Program Files (x86)/Intel/Composer XE/compiler/lib/intel64"
         "C:/Program Files/Intel/Composer XE/mkl/lib/intel64"
         "C:/Program Files/Intel/Composer XE/compiler/lib/intel64"
         )
      find_library(mkl_intel  mkl_intel_lp64 ${mkl_search_path})
   else()
      set( mkl_search_path
         "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries_*/windows/mkl/lib/ia32" 
         "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries_*/windows/compiler/lib/ia32"
         "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/ia32" 
         "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/compiler/lib/ia32"
         "C:/Program Files (x86)/Intel/Composer XE/mkl/lib/ia32"
         "C:/Program Files (x86)/Intel/Composer XE/compiler/lib/ia32"
         "C:/Program Files/Intel/Composer XE/mkl/lib/ia32"
         "C:/Program Files/Intel/Composer XE/compiler/lib/ia32"
         )
      find_library(mkl_intel  mkl_intel_c ${mkl_search_path})
   endif()
312

313
   INCLUDE (CheckFunctionExists)
314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
   # Get mkl_include_dir
   set(mkl_include_search_path
      "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries_*/windows/mkl/include"
      "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries_*/windows/compiler/include"
      "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/compiler/include"
      "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/include"
      "C:/Program Files (x86)/Intel/Composer XE/mkl/include"
      "C:/Program Files (x86)/Intel/Composer XE/compiler/include"
      "C:/Program Files/Intel/Composer XE/mkl/include"
      "C:/Program Files/Intel/Composer XE/compiler/include"
      )
   find_path(mkl_include_dir mkl_version.h ${mkl_include_search_path})
   mark_as_advanced(mkl_include_dir)

Davis King's avatar
Davis King committed
329
330
   # Search for the needed libraries from the MKL.  
   find_library(mkl_core mkl_core ${mkl_search_path})
331
332
333
334
335
336
337
338
339
340
341
342
   set(mkl_libs ${mkl_intel} ${mkl_core})
   mark_as_advanced(mkl_libs mkl_intel mkl_core)
   if (DLIB_USE_MKL_SEQUENTIAL)
     find_library(mkl_sequential mkl_sequential ${mkl_search_path})
     mark_as_advanced(mkl_sequential)
     list(APPEND mkl_libs ${mkl_sequential})
   else()
     find_library(mkl_thread mkl_intel_thread ${mkl_search_path})
     find_library(mkl_iomp libiomp5md ${mkl_search_path})
     mark_as_advanced(mkl_thread mkl_iomp)
     list(APPEND mkl_libs ${mkl_thread} ${mkl_iomp})
   endif()
Davis King's avatar
Davis King committed
343
344

   # If we found the MKL 
345
346
347
   if (mkl_intel AND mkl_core AND ((mkl_thread AND mkl_iomp) OR mkl_sequential))
      set(blas_libraries ${mkl_libs})
      set(lapack_libraries ${mkl_libs})
Davis King's avatar
Davis King committed
348
349
      set(blas_found 1)
      set(lapack_found 1)
350
      set(found_intel_mkl 1)
Davis King's avatar
Davis King committed
351
352
353
354
355
356
357
358
359
360
361
362
363
      message(STATUS "Found Intel MKL BLAS/LAPACK library")

      # Make sure the version of the Intel MKL we found is compatible with
      # the compiler we are using.  One way to do this check is to see if we can
      # link to it right now.
      set(CMAKE_REQUIRED_LIBRARIES ${blas_libraries})
      CHECK_FUNCTION_EXISTS(cblas_ddot HAVE_CBLAS)
      if (NOT HAVE_CBLAS)
         message("BLAS library does not have cblas symbols, so dlib will not use BLAS or LAPACK")
         set(blas_found 0)
         set(lapack_found 0)
      endif()
   endif()
364
365
366
367
368

   if (found_intel_mkl AND mkl_include_dir)
      set(found_intel_mkl_headers 1)
   endif()

Davis King's avatar
Cleanup  
Davis King committed
369
endif()
Sean Warren's avatar
Sean Warren committed
370

371

Davis King's avatar
Cleanup  
Davis King committed
372
373
# When all else fails use CMake's built in functions to find BLAS and LAPACK
if (NOT blas_found)
Davis King's avatar
Davis King committed
374
375
376
377
378
379
380
381
382
383
384
385
   find_package(BLAS QUIET)
   if (${BLAS_FOUND})
      set(blas_libraries ${BLAS_LIBRARIES})      
      set(blas_found 1)
      if (NOT lapack_found)
         find_package(LAPACK QUIET)
         if (${LAPACK_FOUND})
            set(lapack_libraries ${LAPACK_LIBRARIES})
            set(lapack_found 1)
         endif()
      endif()
   endif()
Davis King's avatar
Cleanup  
Davis King committed
386
endif()
387

388

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
# If using lapack, determine whether to mangle functions
if (lapack_found)
   include(CheckFunctionExists)
   include(CheckFortranFunctionExists)
   set(CMAKE_REQUIRED_LIBRARIES ${lapack_libraries})

   check_function_exists("sgesv" LAPACK_FOUND_C_UNMANGLED)
   check_function_exists("sgesv_" LAPACK_FOUND_C_MANGLED)
   if (CMAKE_Fortran_COMPILER_LOADED)
      check_fortran_function_exists("sgesv" LAPACK_FOUND_FORTRAN_UNMANGLED)
      check_fortran_function_exists("sgesv_" LAPACK_FOUND_FORTRAN_MANGLED)
   endif ()
   if (LAPACK_FOUND_C_MANGLED OR LAPACK_FOUND_FORTRAN_MANGLED)
      set(lapack_with_underscore 1)
   elseif (LAPACK_FOUND_C_UNMANGLED OR LAPACK_FOUND_FORTRAN_UNMANGLED)
      set(lapack_without_underscore 1)
   endif ()
endif()

408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

if (UNIX OR MINGW)
   if (NOT blas_found)
      message(" *****************************************************************************")
      message(" *** No BLAS library found so using dlib's built in BLAS.  However, if you ***")
      message(" *** install an optimized BLAS such as OpenBLAS or the Intel MKL your code ***")
      message(" *** will run faster.  On Ubuntu you can install OpenBLAS by executing:    ***")
      message(" ***    sudo apt-get install libopenblas-dev liblapack-dev                 ***")
      message(" *** Or you can easily install OpenBLAS from source by downloading the     ***")
      message(" *** source tar file from http://www.openblas.net, extracting it, and      ***")
      message(" *** running:                                                              ***")
      message(" ***    make; sudo make install                                            ***")
      message(" *****************************************************************************")
   endif()
endif()