FindBLAS.cmake 36 KB
Newer Older
1
2
3
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

4
5
6
7
#[=======================================================================[.rst:
FindBLAS
--------

8
Find Basic Linear Algebra Subprograms (BLAS) library
9

10
This module finds an installed Fortran library that implements the
11
`BLAS linear-algebra interface`_.
12

13
14
At least one of the ``C``, ``CXX``, or ``Fortran`` languages must be enabled.

15
.. _`BLAS linear-algebra interface`: http://www.netlib.org/blas/
16

17
18
Input Variables
^^^^^^^^^^^^^^^
19

20
The following variables may be set to influence this module's behavior:
21

22
23
``BLA_STATIC``
  if ``ON`` use static linkage
24

25
``BLA_VENDOR``
26
27
  Set to one of the :ref:`BLAS/LAPACK Vendors` to search for BLAS only
  from the specified vendor.  If not set, all vendors are considered.
28

29
30
``BLA_F95``
  if ``ON`` tries to find the BLAS95 interfaces
31

32
``BLA_PREFER_PKGCONFIG``
33
34
  .. versionadded:: 3.11

35
  if set ``pkg-config`` will be used to search for a BLAS library first
36
  and if one is found that is preferred
37

38
39
40
41
42
43
44
45
46
47
48
49
50
``BLA_SIZEOF_INTEGER``
  .. versionadded:: 3.22

  Specify the BLAS/LAPACK library integer size:

  ``4``
    Search for a BLAS/LAPACK with 32-bit integer interfaces.
  ``8``
    Search for a BLAS/LAPACK with 64-bit integer interfaces.
  ``ANY``
    Search for any BLAS/LAPACK.
    Most likely, a BLAS/LAPACK with 32-bit integer interfaces will be found.

51
52
53
Imported targets
^^^^^^^^^^^^^^^^

54
This module defines the following :prop_tgt:`IMPORTED` targets:
55
56

``BLAS::BLAS``
57
  .. versionadded:: 3.18
58

59
  The libraries to use for BLAS, if found.
60

61
62
Result Variables
^^^^^^^^^^^^^^^^
63

64
This module defines the following variables:
65

66
67
68
``BLAS_FOUND``
  library implementing the BLAS interface is found
``BLAS_LINKER_FLAGS``
69
  uncached list of required linker flags (excluding ``-l`` and ``-L``).
70
71
72
73
74
75
76
77
``BLAS_LIBRARIES``
  uncached list of libraries (using full path name) to link against
  to use BLAS (may be empty if compiler implicitly links BLAS)
``BLAS95_LIBRARIES``
  uncached list of libraries (using full path name) to link against
  to use BLAS95 interface
``BLAS95_FOUND``
  library implementing the BLAS95 interface is found
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
.. _`BLAS/LAPACK Vendors`:

BLAS/LAPACK Vendors
^^^^^^^^^^^^^^^^^^^

``Generic``
  Generic reference implementation

``ACML``, ``ACML_MP``, ``ACML_GPU``
  AMD Core Math Library

``Apple``, ``NAS``
  Apple BLAS (Accelerate), and Apple NAS (vecLib)

``Arm``, ``Arm_mp``, ``Arm_ilp64``, ``Arm_ilp64_mp``
  .. versionadded:: 3.18

  Arm Performance Libraries

``ATLAS``
  Automatically Tuned Linear Algebra Software

``CXML``, ``DXML``
  Compaq/Digital Extended Math Library

``EML``, ``EML_mt``
  .. versionadded:: 3.20

  Elbrus Math Library

``FLAME``
  .. versionadded:: 3.11

  BLIS Framework

``FlexiBLAS``
  .. versionadded:: 3.19

117
``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``, ``Fujitsu_SSL2SVE``, ``Fujitsu_SSL2BLAMPSVE``
118
119
  .. versionadded:: 3.20

120
  Fujitsu SSL2 serial and parallel blas/lapack with SVE instructions
121

122
123
``Goto``
  GotoBLAS
124

125
126
``IBMESSL``, ``IBMESSL_SMP``

127
  IBM Engineering and Scientific Subroutine Library
128

129
130
``Intel``
  Intel MKL 32 bit and 64 bit obsolete versions
131

132
133
``Intel10_32``
  Intel MKL v10 32 bit, threaded code
134

135
136
``Intel10_64lp``
  Intel MKL v10+ 64 bit, threaded code, lp64 model
137

138
139
``Intel10_64lp_seq``
  Intel MKL v10+ 64 bit, sequential code, lp64 model
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
``Intel10_64ilp``
  .. versionadded:: 3.13

  Intel MKL v10+ 64 bit, threaded code, ilp64 model

``Intel10_64ilp_seq``
  .. versionadded:: 3.13

  Intel MKL v10+ 64 bit, sequential code, ilp64 model

``Intel10_64_dyn``
  .. versionadded:: 3.17

  Intel MKL v10+ 64 bit, single dynamic library

``NVHPC``
  .. versionadded:: 3.21

  NVIDIA HPC SDK

``OpenBLAS``
  .. versionadded:: 3.6

``PhiPACK``
  Portable High Performance ANSI C (PHiPAC)

167
``SCSL``, ``SCSL_mp``
168
169
170
171
172
173
174
175
  Scientific Computing Software Library

``SGIMATH``
  SGI Scientific Mathematical Library

``SunPerf``
  Sun Performance Library

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
.. _`Intel MKL`:

Intel MKL
^^^^^^^^^

To use the Intel MKL implementation of BLAS, a project must enable at least
one of the ``C`` or ``CXX`` languages.  Set ``BLA_VENDOR`` to an Intel MKL
variant either on the command-line as ``-DBLA_VENDOR=Intel10_64lp`` or in
project code:

.. code-block:: cmake

  set(BLA_VENDOR Intel10_64lp)
  find_package(BLAS)

In order to build a project using Intel MKL, and end user must first
establish an Intel MKL environment:

Intel oneAPI
  Source the full Intel environment script:

  .. code-block:: shell

    . /opt/intel/oneapi/setvars.sh

  Or, source the MKL component environment script:

  .. code-block:: shell

    . /opt/intel/oneapi/mkl/latest/env/vars.sh

Intel Classic
  Source the full Intel environment script:

  .. code-block:: shell

    . /opt/intel/bin/compilervars.sh intel64

  Or, source the MKL component environment script:

  .. code-block:: shell

    . /opt/intel/mkl/bin/mklvars.sh intel64

The above environment scripts set the ``MKLROOT`` environment variable
to the top of the MKL installation.  They also add the location of the
runtime libraries to the dynamic library loader environment variable for
your platform (e.g. ``LD_LIBRARY_PATH``).  This is necessary for programs
linked against MKL to run.

.. note::

  As of Intel oneAPI 2021.2, loading only the MKL component does not
  make all of its dependencies available.  In particular, the ``iomp5``
  library must be available separately, or provided by also loading
  the compiler component environment:
232

233
  .. code-block:: shell
234

235
    . /opt/intel/oneapi/compiler/latest/env/vars.sh
236

237
#]=======================================================================]
238

239
240
241
# The approach follows that of the ``autoconf`` macro file, ``acx_blas.m4``
# (distributed at http://ac-archive.sourceforge.net/ac-archive/acx_blas.html).

Alexey Ozeritsky's avatar
Alexey Ozeritsky committed
242
# Check the language being used
243
if(NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED))
Alexey Ozeritsky's avatar
Alexey Ozeritsky committed
244
245
  if(BLAS_FIND_REQUIRED)
    message(FATAL_ERROR "FindBLAS requires Fortran, C, or C++ to be enabled.")
246
  else()
Alexey Ozeritsky's avatar
Alexey Ozeritsky committed
247
248
    message(STATUS "Looking for BLAS... - NOT found (Unsupported languages)")
    return()
249
250
  endif()
endif()
251

252
function(_add_blas_target)
253
  if(BLAS_FOUND AND NOT TARGET BLAS::BLAS)
254
255
256
257
258
259
    add_library(BLAS::BLAS INTERFACE IMPORTED)
    if(BLAS_LIBRARIES)
      set_target_properties(BLAS::BLAS PROPERTIES
        INTERFACE_LINK_LIBRARIES "${BLAS_LIBRARIES}"
      )
    endif()
260
261
262
263
264
    if(BLAS_LINKER_FLAGS)
      set_target_properties(BLAS::BLAS PROPERTIES
        INTERFACE_LINK_OPTIONS "${BLAS_LINKER_FLAGS}"
      )
    endif()
265
266
267
  endif()
endfunction()

268
269
270
271
272
273
274
if(CMAKE_Fortran_COMPILER_LOADED)
  include(${CMAKE_CURRENT_LIST_DIR}/CheckFortranFunctionExists.cmake)
else()
  include(${CMAKE_CURRENT_LIST_DIR}/CheckFunctionExists.cmake)
endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)

275
276
if(BLA_PREFER_PKGCONFIG)
  find_package(PkgConfig)
277
  pkg_check_modules(PKGC_BLAS blas)
278
  if(PKGC_BLAS_FOUND)
279
    set(BLAS_FOUND ${PKGC_BLAS_FOUND})
280
    set(BLAS_LIBRARIES "${PKGC_BLAS_LINK_LIBRARIES}")
281
    _add_blas_target()
282
283
284
285
    return()
  endif()
endif()

286
287
# TODO: move this stuff to a separate module

288
289
290
291
292
293
294
function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs)
  # This function checks for the existence of the combination of libraries
  # given by _list.  If the combination is found, this checks whether can link
  # against that library combination using the name of a routine given by _name
  # using the linker flags given by _flags.  If the combination of libraries is
  # found and passes the link test, ${LIBRARIES} is set to the list of complete
  # library paths that have been found.  Otherwise, ${LIBRARIES} is set to FALSE.
295
296

  set(_libraries_work TRUE)
297
  set(_libraries)
298
  set(_combined_name)
299

300
301
302
303
304
305
306
307
308
309
310
311
312
  if(BLA_STATIC)
    if(WIN32)
      set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
    else()
      set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
    endif()
  else()
    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
      # for ubuntu's libblas3gf and liblapack3gf packages
      set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf)
    endif()
  endif()

313
  set(_extaddlibdir "${_addlibdir}")
314
  if(WIN32)
315
    list(APPEND _extaddlibdir ENV LIB)
316
  elseif(APPLE)
317
    list(APPEND _extaddlibdir ENV DYLD_LIBRARY_PATH)
318
  else()
319
    list(APPEND _extaddlibdir ENV LD_LIBRARY_PATH)
320
  endif()
321
  list(APPEND _extaddlibdir "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}")
322

323
  foreach(_library ${_list})
324
325
    if(_library MATCHES "^-")
      # Respect linker flags as-is (required by MKL)
326
      list(APPEND _libraries "${_library}")
327
    else()
328
      string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}")
329
      string(APPEND _combined_name "_${_lib_var}")
330
      if(NOT "${_deps}" STREQUAL "")
331
        string(APPEND _combined_name "_deps")
332
      endif()
333
      if(_libraries_work)
334
        find_library(${_prefix}_${_lib_var}_LIBRARY
335
          NAMES ${_library}
Sibi Siddharthan's avatar
Sibi Siddharthan committed
336
          NAMES_PER_DIR
337
          PATHS ${_extaddlibdir}
338
339
          PATH_SUFFIXES ${_subdirs}
        )
340
341
342
        mark_as_advanced(${_prefix}_${_lib_var}_LIBRARY)
        list(APPEND _libraries ${${_prefix}_${_lib_var}_LIBRARY})
        set(_libraries_work ${${_prefix}_${_lib_var}_LIBRARY})
343
      endif()
344
345
    endif()
  endforeach()
346

347
348
  foreach(_flag ${_flags})
    string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}")
349
    string(APPEND _combined_name "_${_flag_var}")
350
  endforeach()
351
352
  if(_libraries_work)
    # Test this combination of libraries.
353
    set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${_libraries} ${_deps})
354
    set(CMAKE_REQUIRED_QUIET ${BLAS_FIND_QUIETLY})
355
    if(CMAKE_Fortran_COMPILER_LOADED)
356
357
358
359
360
361
      check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS)
    else()
      check_function_exists("${_name}_" ${_prefix}${_combined_name}_WORKS)
    endif()
    set(CMAKE_REQUIRED_LIBRARIES)
    set(_libraries_work ${${_prefix}${_combined_name}_WORKS})
362
  endif()
363

364
365
  if(_libraries_work)
    if("${_list}" STREQUAL "")
366
      set(_libraries "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
367
    else()
368
      list(APPEND _libraries ${_deps})
369
370
    endif()
  else()
371
    set(_libraries FALSE)
372
  endif()
373
374
  set(${LIBRARIES} "${_libraries}" PARENT_SCOPE)
endfunction()
375
376
377
378

set(BLAS_LINKER_FLAGS)
set(BLAS_LIBRARIES)
set(BLAS95_LIBRARIES)
379
set(_blas_fphsa_req_var BLAS_LIBRARIES)
380
if(NOT $ENV{BLA_VENDOR} STREQUAL "")
381
  set(BLA_VENDOR $ENV{BLA_VENDOR})
382
else()
383
384
  if(NOT BLA_VENDOR)
    set(BLA_VENDOR "All")
385
  endif()
386
endif()
387

388
389
390
391
392
393
394
395
396
397
398
if(NOT BLA_SIZEOF_INTEGER)
  # in the reality we do not know which API of BLAS/LAPACK is masked in library
  set(_blas_sizeof_integer "ANY")
elseif((BLA_SIZEOF_INTEGER STREQUAL "ANY") OR
       (BLA_SIZEOF_INTEGER STREQUAL "4") OR
       (BLA_SIZEOF_INTEGER STREQUAL "8"))
  set(_blas_sizeof_integer ${BLA_SIZEOF_INTEGER})
else()
  message(FATAL_ERROR "BLA_SIZEOF_INTEGER can have only <no value>, ANY, 4, or 8 values")
endif()

399
400
# Implicitly linked BLAS libraries?
if(BLA_VENDOR STREQUAL "All")
401
  if(NOT BLAS_LIBRARIES)
402
    check_blas_libraries(
403
404
405
406
407
408
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
      ""
      ""
409
410
      ""
      ""
411
412
      )
  endif()
413
  if(BLAS_WORKS)
414
415
    # Give a more helpful "found" message
    set(BLAS_WORKS "implicitly linked")
416
417
    set(_blas_fphsa_req_var BLAS_WORKS)
  endif()
418
endif()
419

420
421
422
423
424
425
426
427
428
429
430
# BLAS in the Intel MKL 10+ library?
if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
  if(NOT BLAS_LIBRARIES)
    if(CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED)
      # System-specific settings
      if(WIN32)
        if(BLA_STATIC)
          set(BLAS_mkl_DLL_SUFFIX "")
        else()
          set(BLAS_mkl_DLL_SUFFIX "_dll")
        endif()
431
      else()
432
433
434
435
436
437
438
        if(BLA_STATIC)
          set(BLAS_mkl_START_GROUP "-Wl,--start-group")
          set(BLAS_mkl_END_GROUP "-Wl,--end-group")
        else()
          set(BLAS_mkl_START_GROUP "")
          set(BLAS_mkl_END_GROUP "")
        endif()
439
        # Switch to GNU Fortran support layer if needed (but not on Apple, where MKL does not provide it)
440
        if(CMAKE_Fortran_COMPILER_LOADED AND (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "LCC") AND NOT APPLE)
441
442
            set(BLAS_mkl_INTFACE "gf")
            set(BLAS_mkl_THREADING "gnu")
443
            set(BLAS_mkl_OMP "gomp")
444
445
446
        else()
            set(BLAS_mkl_INTFACE "intel")
            set(BLAS_mkl_THREADING "intel")
447
            set(BLAS_mkl_OMP "iomp5")
448
449
450
        endif()
        set(BLAS_mkl_LM "-lm")
        set(BLAS_mkl_LDL "-ldl")
451
452
      endif()

453
454
455
456
457
458
      if(BLAS_FIND_QUIETLY OR NOT BLAS_FIND_REQUIRED)
        find_package(Threads)
      else()
        find_package(Threads REQUIRED)
      endif()

459
      if(_blas_sizeof_integer EQUAL 8)
460
        set(BLAS_mkl_ILP_MODE "ilp64")
461
      elseif(_blas_sizeof_integer EQUAL 4)
462
        set(BLAS_mkl_ILP_MODE "lp64")
463
464
465
466
467
468
      else()
        if(BLA_VENDOR MATCHES "_64ilp")
          set(BLAS_mkl_ILP_MODE "ilp64")
        else()
          set(BLAS_mkl_ILP_MODE "lp64")
        endif()
469
470
      endif()

471
472
473
      set(BLAS_SEARCH_LIBS "")

      if(BLA_F95)
474
        set(BLAS_mkl_SEARCH_SYMBOL "sgemm_f95")
475
        set(_BLAS_LIBRARIES BLAS95_LIBRARIES)
476
        if(WIN32)
477
478
          # Find the main file (32-bit or 64-bit)
          set(BLAS_SEARCH_LIBS_WIN_MAIN "")
479
          if(BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
480
481
482
            list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
              "mkl_blas95${BLAS_mkl_DLL_SUFFIX} mkl_intel_c${BLAS_mkl_DLL_SUFFIX}")
          endif()
483

484
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp" OR BLA_VENDOR STREQUAL "All")
485
            list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
486
              "mkl_blas95_${BLAS_mkl_ILP_MODE}${BLAS_mkl_DLL_SUFFIX} mkl_intel_${BLAS_mkl_ILP_MODE}${BLAS_mkl_DLL_SUFFIX}")
487
          endif()
488
489
490

          # Add threading/sequential libs
          set(BLAS_SEARCH_LIBS_WIN_THREAD "")
491
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All")
492
493
494
495
496
497
498
            # old version
            list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
              "libguide40 mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
            # mkl >= 10.3
            list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
              "libiomp5md mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
          endif()
499
500
501
502
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All")
            list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
              "mkl_sequential${BLAS_mkl_DLL_SUFFIX}")
          endif()
503
504

          # Cartesian product of the above
505
506
          foreach(MAIN ${BLAS_SEARCH_LIBS_WIN_MAIN})
            foreach(THREAD ${BLAS_SEARCH_LIBS_WIN_THREAD})
507
508
509
510
              list(APPEND BLAS_SEARCH_LIBS
                "${MAIN} ${THREAD} mkl_core${BLAS_mkl_DLL_SUFFIX}")
            endforeach()
          endforeach()
511
512
        else()
          if(BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
513
            # old version
514
            list(APPEND BLAS_SEARCH_LIBS
515
              "mkl_blas95 mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core guide")
516
517

            # mkl >= 10.3
518
            list(APPEND BLAS_SEARCH_LIBS
519
              "${BLAS_mkl_START_GROUP} mkl_blas95 mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}")
520
521
          endif()
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All")
522
523
            # old version
            list(APPEND BLAS_SEARCH_LIBS
524
              "mkl_blas95 mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core guide")
525
526

            # mkl >= 10.3
527
            list(APPEND BLAS_SEARCH_LIBS
528
              "${BLAS_mkl_START_GROUP} mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}")
529
530
          endif()
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All")
531
            list(APPEND BLAS_SEARCH_LIBS
532
              "${BLAS_mkl_START_GROUP} mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_sequential mkl_core ${BLAS_mkl_END_GROUP}")
533
534
535
          endif()
        endif()
      else()
536
        set(BLAS_mkl_SEARCH_SYMBOL sgemm)
537
        set(_BLAS_LIBRARIES BLAS_LIBRARIES)
538
        if(WIN32)
539
540
          # Find the main file (32-bit or 64-bit)
          set(BLAS_SEARCH_LIBS_WIN_MAIN "")
541
          if(BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
542
543
544
            list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
              "mkl_intel_c${BLAS_mkl_DLL_SUFFIX}")
          endif()
545
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp" OR BLA_VENDOR STREQUAL "All")
546
            list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
547
              "mkl_intel_${BLAS_mkl_ILP_MODE}${BLAS_mkl_DLL_SUFFIX}")
548
          endif()
549
550
551

          # Add threading/sequential libs
          set(BLAS_SEARCH_LIBS_WIN_THREAD "")
552
553
554
555
          if(BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
            list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
              "libiomp5md mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
          endif()
556
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All")
557
558
559
560
561
562
563
            # old version
            list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
              "libguide40 mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
            # mkl >= 10.3
            list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
              "libiomp5md mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
          endif()
564
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All")
565
566
567
568
569
            list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
              "mkl_sequential${BLAS_mkl_DLL_SUFFIX}")
          endif()

          # Cartesian product of the above
570
571
          foreach(MAIN ${BLAS_SEARCH_LIBS_WIN_MAIN})
            foreach(THREAD ${BLAS_SEARCH_LIBS_WIN_THREAD})
572
573
574
575
              list(APPEND BLAS_SEARCH_LIBS
                "${MAIN} ${THREAD} mkl_core${BLAS_mkl_DLL_SUFFIX}")
            endforeach()
          endforeach()
576
577
        else()
          if(BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
578
            # old version
579
            list(APPEND BLAS_SEARCH_LIBS
580
              "mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core guide")
581
582

            # mkl >= 10.3
583
            list(APPEND BLAS_SEARCH_LIBS
584
              "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}")
585
586
          endif()
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All")
587
588
            # old version
            list(APPEND BLAS_SEARCH_LIBS
589
              "mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core guide")
590
591

            # mkl >= 10.3
592
            list(APPEND BLAS_SEARCH_LIBS
593
              "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}")
594
595
          endif()
          if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All")
596
            list(APPEND BLAS_SEARCH_LIBS
597
              "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_sequential mkl_core ${BLAS_mkl_END_GROUP}")
598
          endif()
599

600
          #older versions of intel mkl libs
601
          if(BLA_VENDOR STREQUAL "Intel" OR BLA_VENDOR STREQUAL "All")
602
603
604
605
606
607
            list(APPEND BLAS_SEARCH_LIBS
              "mkl")
            list(APPEND BLAS_SEARCH_LIBS
              "mkl_ia32")
            list(APPEND BLAS_SEARCH_LIBS
              "mkl_em64t")
608
609
610
          endif()
        endif()
      endif()
611

612
613
614
615
616
617
      if(BLA_VENDOR MATCHES "^Intel10_64_dyn$" OR BLA_VENDOR STREQUAL "All")
        # mkl >= 10.3 with single dynamic library
        list(APPEND BLAS_SEARCH_LIBS
          "mkl_rt")
      endif()

618
619
620
621
622
      # MKL uses a multitude of partially platform-specific subdirectories:
      if(BLA_VENDOR STREQUAL "Intel10_32")
        set(BLAS_mkl_ARCH_NAME "ia32")
      else()
        set(BLAS_mkl_ARCH_NAME "intel64")
623
      endif()
624
625
626
627
628
629
630
631
      if(WIN32)
        set(BLAS_mkl_OS_NAME "win")
      elseif(APPLE)
        set(BLAS_mkl_OS_NAME "mac")
      else()
        set(BLAS_mkl_OS_NAME "lin")
      endif()
      if(DEFINED ENV{MKLROOT})
632
        file(TO_CMAKE_PATH "$ENV{MKLROOT}" BLAS_mkl_MKLROOT)
633
634
635
636
637
638
        # If MKLROOT points to the subdirectory 'mkl', use the parent directory instead
        # so we can better detect other relevant libraries in 'compiler' or 'tbb':
        get_filename_component(BLAS_mkl_MKLROOT_LAST_DIR "${BLAS_mkl_MKLROOT}" NAME)
        if(BLAS_mkl_MKLROOT_LAST_DIR STREQUAL "mkl")
            get_filename_component(BLAS_mkl_MKLROOT "${BLAS_mkl_MKLROOT}" DIRECTORY)
        endif()
639
      endif()
640
641
      set(BLAS_mkl_LIB_PATH_SUFFIXES
          "compiler/lib" "compiler/lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}"
642
          "compiler/lib/${BLAS_mkl_ARCH_NAME}"
643
          "mkl/lib" "mkl/lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}"
644
          "mkl/lib/${BLAS_mkl_ARCH_NAME}"
645
646
647
          "lib" "lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}"
          "lib/${BLAS_mkl_ARCH_NAME}"
          )
648

649
650
651
      foreach(_search ${BLAS_SEARCH_LIBS})
        string(REPLACE " " ";" _search ${_search})
        if(NOT ${_BLAS_LIBRARIES})
652
          check_blas_libraries(
653
            ${_BLAS_LIBRARIES}
654
655
656
            BLAS
            ${BLAS_mkl_SEARCH_SYMBOL}
            ""
657
            "${_search}"
658
            "${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}"
659
660
            "${BLAS_mkl_MKLROOT}"
            "${BLAS_mkl_LIB_PATH_SUFFIXES}"
661
            )
662
663
664
        endif()
      endforeach()

665
      unset(_search)
666
667
668
669
670
671
672
      unset(BLAS_mkl_ILP_MODE)
      unset(BLAS_mkl_INTFACE)
      unset(BLAS_mkl_THREADING)
      unset(BLAS_mkl_OMP)
      unset(BLAS_mkl_DLL_SUFFIX)
      unset(BLAS_mkl_LM)
      unset(BLAS_mkl_LDL)
673
      unset(BLAS_mkl_MKLROOT)
674
      unset(BLAS_mkl_MKLROOT_LAST_DIR)
675
676
677
      unset(BLAS_mkl_ARCH_NAME)
      unset(BLAS_mkl_OS_NAME)
      unset(BLAS_mkl_LIB_PATH_SUFFIXES)
678
679
680
    endif()
  endif()
endif()
681

682
683
684
685
686
687
688
689
if(BLA_F95)
  find_package_handle_standard_args(BLAS REQUIRED_VARS BLAS95_LIBRARIES)
  set(BLAS95_FOUND ${BLAS_FOUND})
  if(BLAS_FOUND)
    set(BLAS_LIBRARIES "${BLAS95_LIBRARIES}")
  endif()
endif()

690
691
# gotoblas? (http://www.tacc.utexas.edu/tacc-projects/gotoblas2)
if(BLA_VENDOR STREQUAL "Goto" OR BLA_VENDOR STREQUAL "All")
692
  if(NOT BLAS_LIBRARIES)
693
    check_blas_libraries(
694
695
696
697
698
699
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
      "goto2"
      ""
700
701
      ""
      ""
702
703
      )
  endif()
704
endif()
Alexey Ozeritsky's avatar
Alexey Ozeritsky committed
705

706
707
# FlexiBLAS? (http://www.mpi-magdeburg.mpg.de/mpcsc/software/FlexiBLAS/)
if(BLA_VENDOR STREQUAL "FlexiBLAS" OR BLA_VENDOR STREQUAL "All")
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
708
709
  set(_blas_flexiblas_lib "flexiblas")

710
711
712
713
  if(_blas_sizeof_integer EQUAL 8)
    string(APPEND _blas_flexiblas_lib "64")
  endif()

714
715
716
717
718
719
  if(NOT BLAS_LIBRARIES)
    check_blas_libraries(
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
720
      "${_blas_flexiblas_lib}"
721
722
723
724
725
      ""
      ""
      ""
      )
  endif()
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
726
727

  unset(_blas_flexiblas_lib)
728
729
endif()

730
731
# OpenBLAS? (http://www.openblas.net)
if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All")
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
732
733
  set(_blas_openblas_lib "openblas")

734
735
736
737
  if(_blas_sizeof_integer EQUAL 8)
    string(APPEND _blas_openblas_lib "64")
  endif()

738
  if(NOT BLAS_LIBRARIES)
739
    check_blas_libraries(
740
741
742
743
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
744
      "${_blas_openblas_lib}"
745
      ""
746
747
      ""
      ""
748
749
      )
  endif()
750
751
752
753
754
755
  if(NOT BLAS_LIBRARIES AND (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED))
    if(BLAS_FIND_QUIETLY OR NOT BLAS_FIND_REQUIRED)
      find_package(Threads)
    else()
      find_package(Threads REQUIRED)
    endif()
756
757
    set(_threadlibs "${CMAKE_THREAD_LIBS_INIT}")
    if(BLA_STATIC)
758
759
760
761
762
763
764
      if (CMAKE_C_COMPILER_LOADED)
        find_package(OpenMP COMPONENTS C)
        list(PREPEND _threadlibs "${OpenMP_C_LIBRARIES}")
      elseif(CMAKE_CXX_COMPILER_LOADED)
        find_package(OpenMP COMPONENTS CXX)
        list(PREPEND _threadlibs "${OpenMP_CXX_LIBRARIES}")
      endif()
765
    endif()
766
    check_blas_libraries(
767
768
769
770
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
771
      "${_blas_openblas_lib}"
772
      "${_threadlibs}"
773
774
      ""
      ""
775
      )
776
    unset(_threadlibs)
777
  endif()
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
778
779

  unset(_blas_openblas_lib)
780
endif()
781

782
783
784
785
# ArmPL blas library? (https://developer.arm.com/tools-and-software/server-and-hpc/compile/arm-compiler-for-linux/arm-performance-libraries)
if(BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All")

   # Check for 64bit Integer support
786
787
788
789
790
791
792
793
794
795
796
  if(_blas_sizeof_integer EQUAL 8)
    set(_blas_armpl_lib "armpl_ilp64")
  elseif(_blas_sizeof_integer EQUAL 4)
    set(_blas_armpl_lib "armpl_lp64")
  else()
    if(BLA_VENDOR MATCHES "_ilp64")
      set(_blas_armpl_lib "armpl_ilp64")
    else()
      set(_blas_armpl_lib "armpl_lp64")
    endif()
  endif()
797
798
799

   # Check for OpenMP support, VIA BLA_VENDOR of Arm_mp or Arm_ipl64_mp
   if(BLA_VENDOR MATCHES "_mp")
800
     string(APPEND _blas_armpl_lib "_mp")
801
802
803
   endif()

   if(NOT BLAS_LIBRARIES)
804
805
806
807
808
809
810
811
812
813
     check_blas_libraries(
       BLAS_LIBRARIES
       BLAS
       sgemm
       ""
       "${_blas_armpl_lib}"
       ""
       ""
       ""
       )
814
  endif()
815
  unset(_blas_armpl_lib)
816
817
endif()

818
819
# FLAME's blis library? (https://github.com/flame/blis)
if(BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All")
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
820
821
  set(_blas_flame_lib "blis")

822
823
824
825
  if(_blas_sizeof_integer EQUAL 8)
    string(APPEND _blas_flame_lib "64")
  endif()

826
  if(NOT BLAS_LIBRARIES)
827
    check_blas_libraries(
828
829
830
831
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
832
      "${_blas_flame_lib}"
833
      ""
834
835
      ""
      ""
836
837
      )
  endif()
Igor S. Gerasimov's avatar
Igor S. Gerasimov committed
838
839

  unset(_blas_flame_lib)
840
endif()
841

842
843
# BLAS in the ATLAS library? (http://math-atlas.sourceforge.net/)
if(BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All")
844
  if(NOT BLAS_LIBRARIES)
845
    check_blas_libraries(
846
847
848
849
      BLAS_LIBRARIES
      BLAS
      dgemm
      ""
850
      "blas;f77blas;atlas"
851
      ""
852
853
      ""
      ""
854
855
      )
  endif()
856
endif()
857
858

# BLAS in PhiPACK libraries? (requires generic BLAS lib, too)
859
if(BLA_VENDOR STREQUAL "PhiPACK" OR BLA_VENDOR STREQUAL "All")
860
  if(NOT BLAS_LIBRARIES)
861
    check_blas_libraries(
862
863
864
865
866
867
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
      "sgemm;dgemm;blas"
      ""
868
869
      ""
      ""
870
871
      )
  endif()
872
endif()
873
874

# BLAS in Alpha CXML library?
875
if(BLA_VENDOR STREQUAL "CXML" OR BLA_VENDOR STREQUAL "All")
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
  if(_blas_sizeof_integer EQUAL 8)
    if(BLA_VENDOR STREQUAL "CXML")
      message(FATAL_ERROR "CXML does not support Int64 type")
    endif()
  else()
    if(NOT BLAS_LIBRARIES)
      check_blas_libraries(
        BLAS_LIBRARIES
        BLAS
        sgemm
        ""
        "cxml"
        ""
        ""
        ""
        )
    endif()
893
  endif()
894
endif()
895
896

# BLAS in Alpha DXML library? (now called CXML, see above)
897
if(BLA_VENDOR STREQUAL "DXML" OR BLA_VENDOR STREQUAL "All")
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
  if(_blas_sizeof_integer EQUAL 8)
    if(BLA_VENDOR STREQUAL "DXML")
      message(FATAL_ERROR "DXML does not support Int64 type")
    endif()
  else()
    if(NOT BLAS_LIBRARIES)
      check_blas_libraries(
        BLAS_LIBRARIES
        BLAS
        sgemm
        ""
        "dxml"
        ""
        ""
        ""
        )
    endif()
915
  endif()
916
endif()
917
918

# BLAS in Sun Performance library?
919
if(BLA_VENDOR STREQUAL "SunPerf" OR BLA_VENDOR STREQUAL "All")
920
  if(NOT BLAS_LIBRARIES)
921
    check_blas_libraries(
922
923
924
925
926
927
      BLAS_LIBRARIES
      BLAS
      sgemm
      "-xlic_lib=sunperf"
      "sunperf;sunmath"
      ""
928
929
      ""
      ""
930
931
932
933
      )
    if(BLAS_LIBRARIES)
      set(BLAS_LINKER_FLAGS "-xlic_lib=sunperf")
    endif()
934
  endif()
935
endif()
936
937

# BLAS in SCSL library?  (SGI/Cray Scientific Library)
938
939
940
if(BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All")
  set(_blas_scsl_lib "scs")

941
942
943
  if(_blas_sizeof_integer EQUAL 8)
    string(APPEND _blas_scsl_lib "_i8")
  endif()
944
  if(BLA_VENDOR MATCHES "_mp")
945
    string(APPEND _blas_scsl_lib "_mp")
946
947
  endif()

948
  if(NOT BLAS_LIBRARIES)
949
    check_blas_libraries(
950
951
952
953
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
954
      "${_blas_scsl_lib}"
955
      ""
956
957
      ""
      ""
958
959
      )
  endif()
960
961

  unset(_blas_scsl_lib)
962
endif()
963
964

# BLAS in SGIMATH library?
965
if(BLA_VENDOR STREQUAL "SGIMATH" OR BLA_VENDOR STREQUAL "All")
966
  if(NOT BLAS_LIBRARIES)
967
    check_blas_libraries(
968
969
970
971
972
973
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
      "complib.sgimath"
      ""
974
975
      ""
      ""
976
977
      )
  endif()
978
endif()
979

980
# BLAS in IBM ESSL library?
981
982
983
984
if(BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All")
  set(_blas_essl_lib "essl")

  if(BLA_VENDOR MATCHES "_SMP")
985
    string(APPEND _blas_essl_lib "smp")
986
  endif()
987
988
989
990
  if(_blas_sizeof_integer EQUAL 8)
    string(APPEND _blas_essl_lib "6464")
  endif()

991
  if(NOT BLAS_LIBRARIES)
992
    check_blas_libraries(
993
994
995
996
      BLAS_LIBRARIES
      BLAS
      sgemm
      ""
997
      "${_blas_essl_lib}"
998
      ""
999
1000
      ""
      ""
1001
1002
      )
  endif()
1003
1004

  unset(_blas_essl_lib)
1005
endif()
1006

1007
1008
1009
# BLAS in acml library?
if(BLA_VENDOR MATCHES "ACML" OR BLA_VENDOR STREQUAL "All")
  if(((BLA_VENDOR STREQUAL "ACML") AND (NOT BLAS_ACML_LIB_DIRS)) OR
1010
1011
1012
1013
    ((BLA_VENDOR STREQUAL "ACML_MP") AND (NOT BLAS_ACML_MP_LIB_DIRS)) OR
    ((BLA_VENDOR STREQUAL "ACML_GPU") AND (NOT BLAS_ACML_GPU_LIB_DIRS))
    )
  # try to find acml in "standard" paths
1014
1015
  if(WIN32)
    file(GLOB _ACML_ROOT "C:/AMD/acml*/ACML-EULA.txt")
1016
  else()
1017
    file(GLOB _ACML_ROOT "/opt/acml*/ACML-EULA.txt")
1018
  endif()
1019
1020
  if(WIN32)
    file(GLOB _ACML_GPU_ROOT "C:/AMD/acml*/GPGPUexamples")
1021
  else()
1022
    file(GLOB _ACML_GPU_ROOT "/opt/acml*/GPGPUexamples")
1023
1024
1025
  endif()
  list(GET _ACML_ROOT 0 _ACML_ROOT)
  list(GET _ACML_GPU_ROOT 0 _ACML_GPU_ROOT)
1026
1027
  if(_ACML_ROOT)
    get_filename_component(_ACML_ROOT ${_ACML_ROOT} PATH)
1028
    if(_blas_sizeof_integer EQUAL 8)
1029
      set(_ACML_PATH_SUFFIX "_int64")
1030
    else()
1031
      set(_ACML_PATH_SUFFIX "")
1032
    endif()
1033
1034
1035
    if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
      set(_ACML_COMPILER32 "ifort32")
      set(_ACML_COMPILER64 "ifort64")
1036
1037
1038
    elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "IntelLLVM")
      # 32-bit not supported
      set(_ACML_COMPILER64 "ifx")
1039
1040
1041
1042
1043
1044
1045
    elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "SunPro")
      set(_ACML_COMPILER32 "sun32")
      set(_ACML_COMPILER64 "sun64")
    elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "PGI")
      set(_ACML_COMPILER32 "pgi32")
      if(WIN32)
        set(_ACML_COMPILER64 "win64")
1046
      else()
1047
        set(_ACML_COMPILER64 "pgi64")
1048
      endif()
1049
    elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Open64")
1050
1051
      # 32 bit builds not supported on Open64 but for code simplicity
      # We'll just use the same directory twice
1052
1053
1054
1055
1056
      set(_ACML_COMPILER32 "open64_64")
      set(_ACML_COMPILER64 "open64_64")
    elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "NAG")
      set(_ACML_COMPILER32 "nag32")
      set(_ACML_COMPILER64 "nag64")
Alexey Ozeritsky's avatar
Alexey Ozeritsky committed
1057
    else()
1058
1059
      set(_ACML_COMPILER32 "gfortran32")
      set(_ACML_COMPILER64 "gfortran64")
1060
1061
    endif()

1062
    if(BLA_VENDOR STREQUAL "ACML_MP")
1063
1064
      set(_ACML_MP_LIB_DIRS
        "${_ACML_ROOT}/${_ACML_COMPILER32}_mp${_ACML_PATH_SUFFIX}/lib"
1065
        "${_ACML_ROOT}/${_ACML_COMPILER64}_mp${_ACML_PATH_SUFFIX}/lib")
Alexey Ozeritsky's avatar
Alexey Ozeritsky committed
1066
    else()
1067
1068
      set(_ACML_LIB_DIRS
        "${_ACML_ROOT}/${_ACML_COMPILER32}${_ACML_PATH_SUFFIX}/lib"
1069
        "${_ACML_ROOT}/${_ACML_COMPILER64