1###
2#
3# @copyright (c) 2009-2014 The University of Tennessee and The University
4#                          of Tennessee Research Foundation.
5#                          All rights reserved.
6# @copyright (c) 2012-2016 Inria. All rights reserved.
7# @copyright (c) 2012-2014 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria, Univ. Bordeaux. All rights reserved.
8#
9###
10#
11# - Find BLAS EXTENDED for MORSE projects: find include dirs and libraries
12#
13# This module allows to find BLAS libraries by calling the official FindBLAS module
14# and handles the creation of different library lists whether the user wishes to link
15# with a sequential BLAS or a multihreaded (BLAS_SEQ_LIBRARIES and BLAS_PAR_LIBRARIES).
16# BLAS is detected with a FindBLAS call then if the BLAS vendor is Intel10_64lp, ACML
17# or IBMESSLMT then the module attempts to find the corresponding multithreaded libraries.
18#
19# The following variables have been added to manage links with sequential or multithreaded
20# versions:
21#  BLAS_INCLUDE_DIRS  - BLAS include directories
22#  BLAS_LIBRARY_DIRS  - Link directories for BLAS libraries
23#  BLAS_SEQ_LIBRARIES - BLAS component libraries to be linked (sequential)
24#  BLAS_PAR_LIBRARIES - BLAS component libraries to be linked (multithreaded)
25
26#=============================================================================
27# Copyright 2012-2013 Inria
28# Copyright 2012-2013 Emmanuel Agullo
29# Copyright 2012-2013 Mathieu Faverge
30# Copyright 2012      Cedric Castagnede
31# Copyright 2013-2016 Florent Pruvost
32#
33# Distributed under the OSI-approved BSD License (the "License");
34# see accompanying file MORSE-Copyright.txt for details.
35#
36# This software is distributed WITHOUT ANY WARRANTY; without even the
37# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
38# See the License for more information.
39#=============================================================================
40# (To distribute this file outside of Morse, substitute the full
41#  License text for the above reference.)
42
43# macro to factorize this call
44macro(find_package_blas)
45  if(BLASEXT_FIND_REQUIRED)
46    if(BLASEXT_FIND_QUIETLY)
47      find_package(BLAS REQUIRED QUIET)
48    else()
49      find_package(BLAS REQUIRED)
50    endif()
51  else()
52    if(BLASEXT_FIND_QUIETLY)
53      find_package(BLAS QUIET)
54    else()
55      find_package(BLAS)
56    endif()
57  endif()
58endmacro()
59
60# add a cache variable to let the user specify the BLAS vendor
61set(BLA_VENDOR "" CACHE STRING "list of possible BLAS vendor:
62    Open, Eigen, Goto, ATLAS PhiPACK, CXML, DXML, SunPerf, SCSL, SGIMATH, IBMESSL, IBMESSLMT,
63    Intel10_32 (intel mkl v10 32 bit),
64    Intel10_64lp (intel mkl v10 64 bit, lp thread model, lp64 model),
65    Intel10_64lp_seq (intel mkl v10 64 bit, sequential code, lp64 model),
66    Intel( older versions of mkl 32 and 64 bit),
67    ACML, ACML_MP, ACML_GPU, Apple, NAS, Generic")
68
69if(NOT BLASEXT_FIND_QUIETLY)
70  message(STATUS "In FindBLASEXT")
71  message(STATUS "If you want to force the use of one specific library, "
72    "\n   please specify the BLAS vendor by setting -DBLA_VENDOR=blas_vendor_name"
73    "\n   at cmake configure.")
74  message(STATUS "List of possible BLAS vendor: Goto, ATLAS PhiPACK, CXML, "
75    "\n   DXML, SunPerf, SCSL, SGIMATH, IBMESSL, IBMESSLMT, Intel10_32 (intel mkl v10 32 bit),"
76    "\n   Intel10_64lp (intel mkl v10 64 bit, lp thread model, lp64 model),"
77    "\n   Intel10_64lp_seq (intel mkl v10 64 bit, sequential code, lp64 model),"
78    "\n   Intel( older versions of mkl 32 and 64 bit),"
79    "\n   ACML, ACML_MP, ACML_GPU, Apple, NAS, Generic")
80endif()
81
82if (NOT BLAS_FOUND)
83  # First try to detect two cases:
84  # 1: only SEQ libs are handled
85  # 2: both SEQ and PAR libs are handled
86  find_package_blas()
87endif ()
88
89# detect the cases where SEQ and PAR libs are handled
90if(BLA_VENDOR STREQUAL "All" AND
91    (BLAS_mkl_core_LIBRARY OR BLAS_mkl_core_dll_LIBRARY)
92    )
93  set(BLA_VENDOR "Intel")
94  if(BLAS_mkl_intel_LIBRARY)
95    set(BLA_VENDOR "Intel10_32")
96  endif()
97  if(BLAS_mkl_intel_lp64_LIBRARY)
98    set(BLA_VENDOR "Intel10_64lp")
99  endif()
100  if(NOT BLASEXT_FIND_QUIETLY)
101    message(STATUS "A BLAS library has been found (${BLAS_LIBRARIES}) but we"
102      "\n   have also potentially detected some multithreaded BLAS libraries from the MKL."
103      "\n   We try to find both libraries lists (Sequential/Multithreaded).")
104  endif()
105  set(BLAS_FOUND "")
106elseif(BLA_VENDOR STREQUAL "All" AND BLAS_acml_LIBRARY)
107  set(BLA_VENDOR "ACML")
108  if(NOT BLASEXT_FIND_QUIETLY)
109    message(STATUS "A BLAS library has been found (${BLAS_LIBRARIES}) but we"
110      "\n   have also potentially detected some multithreaded BLAS libraries from the ACML."
111      "\n   We try to find both libraries lists (Sequential/Multithreaded).")
112  endif()
113  set(BLAS_FOUND "")
114elseif(BLA_VENDOR STREQUAL "All" AND BLAS_essl_LIBRARY)
115  set(BLA_VENDOR "IBMESSL")
116  if(NOT BLASEXT_FIND_QUIETLY)
117    message(STATUS "A BLAS library has been found (${BLAS_LIBRARIES}) but we"
118      "\n   have also potentially detected some multithreaded BLAS libraries from the ESSL."
119      "\n   We try to find both libraries lists (Sequential/Multithreaded).")
120  endif()
121  set(BLAS_FOUND "")
122endif()
123
124# Intel case
125if(BLA_VENDOR MATCHES "Intel*")
126
127  ###
128  # look for include path if the BLAS vendor is Intel
129  ###
130
131  # gather system include paths
132  unset(_inc_env)
133  if(WIN32)
134    string(REPLACE ":" ";" _inc_env "$ENV{INCLUDE}")
135  else()
136    string(REPLACE ":" ";" _path_env "$ENV{INCLUDE}")
137    list(APPEND _inc_env "${_path_env}")
138    string(REPLACE ":" ";" _path_env "$ENV{C_INCLUDE_PATH}")
139    list(APPEND _inc_env "${_path_env}")
140    string(REPLACE ":" ";" _path_env "$ENV{CPATH}")
141    list(APPEND _inc_env "${_path_env}")
142    string(REPLACE ":" ";" _path_env "$ENV{INCLUDE_PATH}")
143    list(APPEND _inc_env "${_path_env}")
144  endif()
145  list(APPEND _inc_env "${CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES}")
146  list(APPEND _inc_env "${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}")
147  set(ENV_MKLROOT "$ENV{MKLROOT}")
148  if (ENV_MKLROOT)
149    list(APPEND _inc_env "${ENV_MKLROOT}/include")
150  endif()
151  list(REMOVE_DUPLICATES _inc_env)
152
153  # find mkl.h inside known include paths
154  set(BLAS_mkl.h_INCLUDE_DIRS "BLAS_mkl.h_INCLUDE_DIRS-NOTFOUND")
155  if(BLAS_INCDIR)
156    set(BLAS_mkl.h_INCLUDE_DIRS "BLAS_mkl.h_INCLUDE_DIRS-NOTFOUND")
157    find_path(BLAS_mkl.h_INCLUDE_DIRS
158      NAMES mkl.h
159      HINTS ${BLAS_INCDIR})
160  else()
161    if(BLAS_DIR)
162      set(BLAS_mkl.h_INCLUDE_DIRS "BLAS_mkl.h_INCLUDE_DIRS-NOTFOUND")
163      find_path(BLAS_mkl.h_INCLUDE_DIRS
164	NAMES mkl.h
165	HINTS ${BLAS_DIR}
166	PATH_SUFFIXES include)
167    else()
168      set(BLAS_mkl.h_INCLUDE_DIRS "BLAS_mkl.h_INCLUDE_DIRS-NOTFOUND")
169      find_path(BLAS_mkl.h_INCLUDE_DIRS
170	NAMES mkl.h
171	HINTS ${_inc_env})
172    endif()
173  endif()
174  mark_as_advanced(BLAS_mkl.h_INCLUDE_DIRS)
175  ## Print status if not found
176  ## -------------------------
177  #if (NOT BLAS_mkl.h_INCLUDE_DIRS AND MORSE_VERBOSE)
178  #    Print_Find_Header_Status(blas mkl.h)
179  #endif ()
180  set(BLAS_INCLUDE_DIRS "")
181  if(BLAS_mkl.h_INCLUDE_DIRS)
182    list(APPEND BLAS_INCLUDE_DIRS "${BLAS_mkl.h_INCLUDE_DIRS}" )
183  endif()
184
185  ###
186  # look for libs
187  ###
188  # if Intel 10 64 bit -> look for sequential and multithreaded versions
189  if(BLA_VENDOR MATCHES "Intel10_64lp*")
190
191    ## look for the sequential version
192    set(BLA_VENDOR "Intel10_64lp_seq")
193    if(NOT BLASEXT_FIND_QUIETLY)
194      message(STATUS "Look for the sequential version Intel10_64lp_seq")
195    endif()
196    find_package_blas()
197    if(BLAS_FOUND)
198      set(BLAS_SEQ_LIBRARIES "${BLAS_LIBRARIES}")
199    else()
200      set(BLAS_SEQ_LIBRARIES "${BLAS_SEQ_LIBRARIES-NOTFOUND}")
201    endif()
202
203    ## look for the multithreaded version
204    set(BLA_VENDOR "Intel10_64lp")
205    if(NOT BLASEXT_FIND_QUIETLY)
206      message(STATUS "Look for the multithreaded version Intel10_64lp")
207    endif()
208    find_package_blas()
209    if(BLAS_FOUND)
210      set(BLAS_PAR_LIBRARIES "${BLAS_LIBRARIES}")
211    else()
212      set(BLAS_PAR_LIBRARIES "${BLAS_PAR_LIBRARIES-NOTFOUND}")
213    endif()
214
215  else()
216
217    if(BLAS_FOUND)
218      set(BLAS_SEQ_LIBRARIES "${BLAS_LIBRARIES}")
219    else()
220      set(BLAS_SEQ_LIBRARIES "${BLAS_SEQ_LIBRARIES-NOTFOUND}")
221    endif()
222
223  endif()
224
225  # ACML case
226elseif(BLA_VENDOR MATCHES "ACML*")
227
228  ## look for the sequential version
229  set(BLA_VENDOR "ACML")
230  find_package_blas()
231  if(BLAS_FOUND)
232    set(BLAS_SEQ_LIBRARIES "${BLAS_LIBRARIES}")
233  else()
234    set(BLAS_SEQ_LIBRARIES "${BLAS_SEQ_LIBRARIES-NOTFOUND}")
235  endif()
236
237  ## look for the multithreaded version
238  set(BLA_VENDOR "ACML_MP")
239  find_package_blas()
240  if(BLAS_FOUND)
241    set(BLAS_PAR_LIBRARIES "${BLAS_LIBRARIES}")
242  else()
243    set(BLAS_PAR_LIBRARIES "${BLAS_PAR_LIBRARIES-NOTFOUND}")
244  endif()
245
246  # IBMESSL case
247elseif(BLA_VENDOR MATCHES "IBMESSL*")
248
249  ## look for the sequential version
250  set(BLA_VENDOR "IBMESSL")
251  find_package_blas()
252  if(BLAS_FOUND)
253    set(BLAS_SEQ_LIBRARIES "${BLAS_LIBRARIES}")
254  else()
255    set(BLAS_SEQ_LIBRARIES "${BLAS_SEQ_LIBRARIES-NOTFOUND}")
256  endif()
257
258  ## look for the multithreaded version
259  set(BLA_VENDOR "IBMESSLMT")
260  find_package_blas()
261  if(BLAS_FOUND)
262    set(BLAS_PAR_LIBRARIES "${BLAS_LIBRARIES}")
263  else()
264    set(BLAS_PAR_LIBRARIES "${BLAS_PAR_LIBRARIES-NOTFOUND}")
265  endif()
266
267else()
268
269  if(BLAS_FOUND)
270    # define the SEQ libs as the BLAS_LIBRARIES
271    set(BLAS_SEQ_LIBRARIES "${BLAS_LIBRARIES}")
272  else()
273    set(BLAS_SEQ_LIBRARIES "${BLAS_SEQ_LIBRARIES-NOTFOUND}")
274  endif()
275  set(BLAS_PAR_LIBRARIES "${BLAS_PAR_LIBRARIES-NOTFOUND}")
276
277endif()
278
279
280if(BLAS_SEQ_LIBRARIES)
281  set(BLAS_LIBRARIES "${BLAS_SEQ_LIBRARIES}")
282endif()
283
284# extract libs paths
285# remark: because it is not given by find_package(BLAS)
286set(BLAS_LIBRARY_DIRS "")
287string(REPLACE " " ";" BLAS_LIBRARIES "${BLAS_LIBRARIES}")
288foreach(blas_lib ${BLAS_LIBRARIES})
289  if (EXISTS "${blas_lib}")
290    get_filename_component(a_blas_lib_dir "${blas_lib}" PATH)
291    list(APPEND BLAS_LIBRARY_DIRS "${a_blas_lib_dir}" )
292  else()
293    string(REPLACE "-L" "" blas_lib "${blas_lib}")
294    if (EXISTS "${blas_lib}")
295      list(APPEND BLAS_LIBRARY_DIRS "${blas_lib}" )
296    else()
297      get_filename_component(a_blas_lib_dir "${blas_lib}" PATH)
298      if (EXISTS "${a_blas_lib_dir}")
299	list(APPEND BLAS_LIBRARY_DIRS "${a_blas_lib_dir}" )
300      endif()
301    endif()
302  endif()
303endforeach()
304if (BLAS_LIBRARY_DIRS)
305  list(REMOVE_DUPLICATES BLAS_LIBRARY_DIRS)
306endif ()
307
308# check that BLAS has been found
309# ---------------------------------
310include(FindPackageHandleStandardArgs)
311if(BLA_VENDOR MATCHES "Intel*")
312  if(BLA_VENDOR MATCHES "Intel10_64lp*")
313    if(NOT BLASEXT_FIND_QUIETLY)
314      message(STATUS "BLAS found is Intel MKL:"
315	"\n   we manage two lists of libs, one sequential and one parallel if found"
316	"\n   (see BLAS_SEQ_LIBRARIES and BLAS_PAR_LIBRARIES)")
317      message(STATUS "BLAS sequential libraries stored in BLAS_SEQ_LIBRARIES")
318    endif()
319    find_package_handle_standard_args(BLAS DEFAULT_MSG
320      BLAS_SEQ_LIBRARIES
321      BLAS_LIBRARY_DIRS
322      BLAS_INCLUDE_DIRS)
323    if(BLAS_PAR_LIBRARIES)
324      if(NOT BLASEXT_FIND_QUIETLY)
325	message(STATUS "BLAS parallel libraries stored in BLAS_PAR_LIBRARIES")
326      endif()
327      find_package_handle_standard_args(BLAS DEFAULT_MSG
328	BLAS_PAR_LIBRARIES)
329    endif()
330  else()
331    if(NOT BLASEXT_FIND_QUIETLY)
332      message(STATUS "BLAS sequential libraries stored in BLAS_SEQ_LIBRARIES")
333    endif()
334    find_package_handle_standard_args(BLAS DEFAULT_MSG
335      BLAS_SEQ_LIBRARIES
336      BLAS_LIBRARY_DIRS
337      BLAS_INCLUDE_DIRS)
338  endif()
339elseif(BLA_VENDOR MATCHES "ACML*")
340  if(NOT BLASEXT_FIND_QUIETLY)
341    message(STATUS "BLAS found is ACML:"
342      "\n   we manage two lists of libs, one sequential and one parallel if found"
343      "\n   (see BLAS_SEQ_LIBRARIES and BLAS_PAR_LIBRARIES)")
344    message(STATUS "BLAS sequential libraries stored in BLAS_SEQ_LIBRARIES")
345  endif()
346  find_package_handle_standard_args(BLAS DEFAULT_MSG
347    BLAS_SEQ_LIBRARIES
348    BLAS_LIBRARY_DIRS)
349  if(BLAS_PAR_LIBRARIES)
350    if(NOT BLASEXT_FIND_QUIETLY)
351      message(STATUS "BLAS parallel libraries stored in BLAS_PAR_LIBRARIES")
352    endif()
353    find_package_handle_standard_args(BLAS DEFAULT_MSG
354      BLAS_PAR_LIBRARIES)
355  endif()
356elseif(BLA_VENDOR MATCHES "IBMESSL*")
357  if(NOT BLASEXT_FIND_QUIETLY)
358    message(STATUS "BLAS found is ESSL:"
359      "\n   we manage two lists of libs, one sequential and one parallel if found"
360      "\n   (see BLAS_SEQ_LIBRARIES and BLAS_PAR_LIBRARIES)")
361    message(STATUS "BLAS sequential libraries stored in BLAS_SEQ_LIBRARIES")
362  endif()
363  find_package_handle_standard_args(BLAS DEFAULT_MSG
364    BLAS_SEQ_LIBRARIES
365    BLAS_LIBRARY_DIRS)
366  if(BLAS_PAR_LIBRARIES)
367    if(NOT BLASEXT_FIND_QUIETLY)
368      message(STATUS "BLAS parallel libraries stored in BLAS_PAR_LIBRARIES")
369    endif()
370    find_package_handle_standard_args(BLAS DEFAULT_MSG
371      BLAS_PAR_LIBRARIES)
372  endif()
373else()
374  if(NOT BLASEXT_FIND_QUIETLY)
375    message(STATUS "BLAS sequential libraries stored in BLAS_SEQ_LIBRARIES")
376  endif()
377  find_package_handle_standard_args(BLAS DEFAULT_MSG
378    BLAS_SEQ_LIBRARIES
379    BLAS_LIBRARY_DIRS)
380endif()
381