FindCBLAS.cmake 14.3 KB
Newer Older
1 2 3 4 5
###
#
# @copyright (c) 2009-2014 The University of Tennessee and The University
#                          of Tennessee Research Foundation.
#                          All rights reserved.
6
# @copyright (c) 2012-2016 Inria. All rights reserved.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# @copyright (c) 2012-2014 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria, Univ. Bordeaux. All rights reserved.
#
###
#
# - Find CBLAS include dirs and libraries
# Use this module by invoking find_package with the form:
#  find_package(CBLAS
#               [REQUIRED] # Fail with error if cblas is not found
#               [COMPONENTS <comp1> <comp2> ...] # dependencies
#              )
#
#  CBLAS depends on the following libraries:
#   - BLAS
#
# This module finds headers and cblas library.
# Results are reported in variables:
#  CBLAS_FOUND            - True if headers and requested libraries were found
24
#  CBLAS_LINKER_FLAGS     - list of required linker flags (excluding -l and -L)
25 26 27 28 29 30
#  CBLAS_INCLUDE_DIRS     - cblas include directories
#  CBLAS_LIBRARY_DIRS     - Link directories for cblas libraries
#  CBLAS_LIBRARIES        - cblas component libraries to be linked
#  CBLAS_INCLUDE_DIRS_DEP - cblas + dependencies include directories
#  CBLAS_LIBRARY_DIRS_DEP - cblas + dependencies link directories
#  CBLAS_LIBRARIES_DEP    - cblas libraries + dependencies
31
#  CBLAS_HAS_ZGEMM3M      - True if cblas contains zgemm3m fast complex mat-mat product
32 33 34 35 36 37
#
# The user can give specific paths where to find the libraries adding cmake
# options at configure (ex: cmake path/to/project -DCBLAS_DIR=path/to/cblas):
#  CBLAS_DIR              - Where to find the base directory of cblas
#  CBLAS_INCDIR           - Where to find the header files
#  CBLAS_LIBDIR           - Where to find the library files
38 39
# The module can also look for the following environment variables if paths
# are not given as cmake variable: CBLAS_DIR, CBLAS_INCDIR, CBLAS_LIBDIR
40 41 42 43 44 45 46
#
# CBLAS could be directly embedded in BLAS library (ex: Intel MKL) so that
# we test a cblas function with the blas libraries found and set CBLAS
# variables to BLAS ones if test is successful. To skip this feature and
# look for a stand alone cblas, please add the following in your
# CMakeLists.txt before to call find_package(CBLAS):
# set(CBLAS_STANDALONE TRUE)
47 48 49 50 51 52 53
###
# We handle different modes to find the dependency
#
# - Detection if already installed on the system
#   - CBLAS libraries can be detected from different ways
#     Here is the order of precedence:
#     1) we look in cmake variable CBLAS_LIBDIR or CBLAS_DIR (we guess the libdirs) if defined
54
#     2) we look in environment variable CBLAS_LIBDIR or CBLAS_DIR (we guess the libdirs) if defined
55 56 57 58 59
#     3) we look in common environnment variables depending on the system (INCLUDE, C_INCLUDE_PATH, CPATH - LIB, DYLD_LIBRARY_PATH, LD_LIBRARY_PATH)
#     4) we look in common system paths depending on the system, see for example paths contained in the following cmake variables:
#       - CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES, CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
#       - CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES, CMAKE_C_IMPLICIT_LINK_DIRECTORIES
#
60 61 62 63 64 65

#=============================================================================
# Copyright 2012-2013 Inria
# Copyright 2012-2013 Emmanuel Agullo
# Copyright 2012-2013 Mathieu Faverge
# Copyright 2012      Cedric Castagnede
66
# Copyright 2013-2016 Florent Pruvost
67 68 69 70 71 72 73 74 75 76 77 78 79
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file MORSE-Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of Morse, substitute the full
#  License text for the above reference.)


if (NOT CBLAS_FOUND)
PRUVOST Florent's avatar
PRUVOST Florent committed
80 81 82 83
  set(CBLAS_DIR "" CACHE PATH "Installation directory of CBLAS library")
  if (NOT CBLAS_FIND_QUIETLY)
    message(STATUS "A cache variable, namely CBLAS_DIR, has been set to specify the install directory of CBLAS")
  endif()
84 85 86 87 88
endif()


# CBLAS depends on BLAS anyway, try to find it
if (NOT BLAS_FOUND)
PRUVOST Florent's avatar
PRUVOST Florent committed
89 90 91 92 93
  if(CBLAS_FIND_REQUIRED)
    find_package(BLASEXT REQUIRED)
  else()
    find_package(BLASEXT)
  endif()
94 95 96 97 98 99
endif()


# find CBLAS
if (BLAS_FOUND)

PRUVOST Florent's avatar
PRUVOST Florent committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
  if (NOT CBLAS_STANDALONE)
    # check if a cblas function exists in the BLAS lib
    # this can be the case with libs such as MKL, ACML
    include(CheckFunctionExists)
    set(CMAKE_REQUIRED_LIBRARIES "${BLAS_LINKER_FLAGS};${BLAS_LIBRARIES}")
    set(CMAKE_REQUIRED_FLAGS "${BLAS_COMPILER_FLAGS}")
    unset(CBLAS_WORKS CACHE)
    check_function_exists(cblas_dscal CBLAS_WORKS)
    check_function_exists(cblas_zgemm3m CBLAS_ZGEMM3M_FOUND)
    mark_as_advanced(CBLAS_WORKS)
    set(CMAKE_REQUIRED_LIBRARIES)

    if(CBLAS_WORKS)

      # Check for faster complex GEMM routine
      # (only C/Z, no S/D version)
      if ( CBLAS_ZGEMM3M_FOUND )
117
        add_definitions(-DCBLAS_HAS_ZGEMM3M -DCBLAS_HAS_CGEMM3M)
PRUVOST Florent's avatar
PRUVOST Florent committed
118 119 120
      endif()

      if(NOT CBLAS_FIND_QUIETLY)
121
        message(STATUS "Looking for cblas: test with blas succeeds")
PRUVOST Florent's avatar
PRUVOST Florent committed
122 123 124
      endif()
      # test succeeds: CBLAS is in BLAS
      set(CBLAS_LIBRARIES "${BLAS_LIBRARIES}")
125
      set(CBLAS_LIBRARIES_DEP "${BLAS_LIBRARIES}")
PRUVOST Florent's avatar
PRUVOST Florent committed
126
      if (BLAS_LIBRARY_DIRS)
127
        set(CBLAS_LIBRARY_DIRS "${BLAS_LIBRARY_DIRS}")
PRUVOST Florent's avatar
PRUVOST Florent committed
128 129
      endif()
      if(BLAS_INCLUDE_DIRS)
130 131
        set(CBLAS_INCLUDE_DIRS "${BLAS_INCLUDE_DIRS}")
        set(CBLAS_INCLUDE_DIRS_DEP "${BLAS_INCLUDE_DIRS_DEP}")
PRUVOST Florent's avatar
PRUVOST Florent committed
132 133
      endif()
      if (BLAS_LINKER_FLAGS)
134
        set(CBLAS_LINKER_FLAGS "${BLAS_LINKER_FLAGS}")
PRUVOST Florent's avatar
PRUVOST Florent committed
135 136 137
      endif()
    endif()
  endif (NOT CBLAS_STANDALONE)
138

PRUVOST Florent's avatar
PRUVOST Florent committed
139
  if (CBLAS_STANDALONE OR NOT CBLAS_WORKS)
140

PRUVOST Florent's avatar
PRUVOST Florent committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    if(NOT CBLAS_WORKS AND NOT CBLAS_FIND_QUIETLY)
      message(STATUS "Looking for cblas : test with blas fails")
    endif()
    # test fails: try to find CBLAS lib exterior to BLAS

    # Try to find CBLAS lib
    #######################

    # Looking for include
    # -------------------

    # Add system include paths to search include
    # ------------------------------------------
    unset(_inc_env)
    set(ENV_CBLAS_DIR "$ENV{CBLAS_DIR}")
    set(ENV_CBLAS_INCDIR "$ENV{CBLAS_INCDIR}")
    if(ENV_CBLAS_INCDIR)
      list(APPEND _inc_env "${ENV_CBLAS_INCDIR}")
    elseif(ENV_CBLAS_DIR)
      list(APPEND _inc_env "${ENV_CBLAS_DIR}")
      list(APPEND _inc_env "${ENV_CBLAS_DIR}/include")
      list(APPEND _inc_env "${ENV_CBLAS_DIR}/include/cblas")
    else()
      if(WIN32)
165 166
        string(REPLACE ":" ";" _path_env "$ENV{INCLUDE}")
        list(APPEND _inc_env "${_path_env}")
PRUVOST Florent's avatar
PRUVOST Florent committed
167
      else()
168 169 170 171 172 173 174 175
        string(REPLACE ":" ";" _path_env "$ENV{INCLUDE}")
        list(APPEND _inc_env "${_path_env}")
        string(REPLACE ":" ";" _path_env "$ENV{C_INCLUDE_PATH}")
        list(APPEND _inc_env "${_path_env}")
        string(REPLACE ":" ";" _path_env "$ENV{CPATH}")
        list(APPEND _inc_env "${_path_env}")
        string(REPLACE ":" ";" _path_env "$ENV{INCLUDE_PATH}")
        list(APPEND _inc_env "${_path_env}")
PRUVOST Florent's avatar
PRUVOST Florent committed
176 177 178 179 180 181 182 183 184 185 186 187 188
      endif()
    endif()
    list(APPEND _inc_env "${CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES}")
    list(APPEND _inc_env "${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}")
    list(REMOVE_DUPLICATES _inc_env)


    # Try to find the cblas header in the given paths
    # -------------------------------------------------
    # call cmake macro to find the header path
    if(CBLAS_INCDIR)
      set(CBLAS_cblas.h_DIRS "CBLAS_cblas.h_DIRS-NOTFOUND")
      find_path(CBLAS_cblas.h_DIRS
189 190
        NAMES cblas.h
        HINTS ${CBLAS_INCDIR})
PRUVOST Florent's avatar
PRUVOST Florent committed
191 192
    else()
      if(CBLAS_DIR)
193 194 195 196 197
        set(CBLAS_cblas.h_DIRS "CBLAS_cblas.h_DIRS-NOTFOUND")
        find_path(CBLAS_cblas.h_DIRS
          NAMES cblas.h
          HINTS ${CBLAS_DIR}
          PATH_SUFFIXES "include" "include/cblas")
PRUVOST Florent's avatar
PRUVOST Florent committed
198
      else()
199 200 201 202 203
        set(CBLAS_cblas.h_DIRS "CBLAS_cblas.h_DIRS-NOTFOUND")
        find_path(CBLAS_cblas.h_DIRS
          NAMES cblas.h
          HINTS ${_inc_env}
          PATH_SUFFIXES "cblas")
PRUVOST Florent's avatar
PRUVOST Florent committed
204 205 206 207 208 209 210 211 212 213 214
      endif()
    endif()
    mark_as_advanced(CBLAS_cblas.h_DIRS)

    # If found, add path to cmake variable
    # ------------------------------------
    if (CBLAS_cblas.h_DIRS)
      set(CBLAS_INCLUDE_DIRS "${CBLAS_cblas.h_DIRS}")
    else ()
      set(CBLAS_INCLUDE_DIRS "CBLAS_INCLUDE_DIRS-NOTFOUND")
      if(NOT CBLAS_FIND_QUIETLY)
215
        message(STATUS "Looking for cblas -- cblas.h not found")
PRUVOST Florent's avatar
PRUVOST Florent committed
216
      endif()
217 218 219
    endif()


PRUVOST Florent's avatar
PRUVOST Florent committed
220 221 222 223 224 225 226 227 228 229 230 231 232 233
    # Looking for lib
    # ---------------

    # Add system library paths to search lib
    # --------------------------------------
    unset(_lib_env)
    set(ENV_CBLAS_LIBDIR "$ENV{CBLAS_LIBDIR}")
    if(ENV_CBLAS_LIBDIR)
      list(APPEND _lib_env "${ENV_CBLAS_LIBDIR}")
    elseif(ENV_CBLAS_DIR)
      list(APPEND _lib_env "${ENV_CBLAS_DIR}")
      list(APPEND _lib_env "${ENV_CBLAS_DIR}/lib")
    else()
      if(WIN32)
234
        string(REPLACE ":" ";" _lib_env "$ENV{LIB}")
PRUVOST Florent's avatar
PRUVOST Florent committed
235
      else()
236 237 238 239 240 241 242
        if(APPLE)
          string(REPLACE ":" ";" _lib_env "$ENV{DYLD_LIBRARY_PATH}")
        else()
          string(REPLACE ":" ";" _lib_env "$ENV{LD_LIBRARY_PATH}")
        endif()
        list(APPEND _lib_env "${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES}")
        list(APPEND _lib_env "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}")
PRUVOST Florent's avatar
PRUVOST Florent committed
243 244 245 246 247 248 249 250 251 252 253
      endif()
    endif()
    list(REMOVE_DUPLICATES _lib_env)

    # Try to find the cblas lib in the given paths
    # ----------------------------------------------

    # call cmake macro to find the lib path
    if(CBLAS_LIBDIR)
      set(CBLAS_cblas_LIBRARY "CBLAS_cblas_LIBRARY-NOTFOUND")
      find_library(CBLAS_cblas_LIBRARY
254 255
        NAMES cblas
        HINTS ${CBLAS_LIBDIR})
256
    else()
PRUVOST Florent's avatar
PRUVOST Florent committed
257
      if(CBLAS_DIR)
258 259 260 261 262
        set(CBLAS_cblas_LIBRARY "CBLAS_cblas_LIBRARY-NOTFOUND")
        find_library(CBLAS_cblas_LIBRARY
          NAMES cblas
          HINTS ${CBLAS_DIR}
          PATH_SUFFIXES lib lib32 lib64)
PRUVOST Florent's avatar
PRUVOST Florent committed
263
      else()
264 265 266 267
        set(CBLAS_cblas_LIBRARY "CBLAS_cblas_LIBRARY-NOTFOUND")
        find_library(CBLAS_cblas_LIBRARY
          NAMES cblas
          HINTS ${_lib_env})
PRUVOST Florent's avatar
PRUVOST Florent committed
268
      endif()
269
    endif()
PRUVOST Florent's avatar
PRUVOST Florent committed
270 271 272 273 274 275 276 277 278 279 280 281 282
    mark_as_advanced(CBLAS_cblas_LIBRARY)

    # If found, add path to cmake variable
    # ------------------------------------
    if (CBLAS_cblas_LIBRARY)
      get_filename_component(cblas_lib_path "${CBLAS_cblas_LIBRARY}" PATH)
      # set cmake variables
      set(CBLAS_LIBRARIES    "${CBLAS_cblas_LIBRARY}")
      set(CBLAS_LIBRARY_DIRS "${cblas_lib_path}")
    else ()
      set(CBLAS_LIBRARIES    "CBLAS_LIBRARIES-NOTFOUND")
      set(CBLAS_LIBRARY_DIRS "CBLAS_LIBRARY_DIRS-NOTFOUND")
      if (NOT CBLAS_FIND_QUIETLY)
283
        message(STATUS "Looking for cblas -- lib cblas not found")
PRUVOST Florent's avatar
PRUVOST Florent committed
284 285 286 287 288 289 290 291 292 293 294 295 296
      endif()
    endif ()

    # check a function to validate the find
    if(CBLAS_LIBRARIES)

      set(REQUIRED_INCDIRS)
      set(REQUIRED_LDFLAGS)
      set(REQUIRED_LIBDIRS)
      set(REQUIRED_LIBS)

      # CBLAS
      if (CBLAS_INCLUDE_DIRS)
297
        set(REQUIRED_INCDIRS "${CBLAS_INCLUDE_DIRS}")
PRUVOST Florent's avatar
PRUVOST Florent committed
298 299
      endif()
      if (CBLAS_LIBRARY_DIRS)
300
        set(REQUIRED_LIBDIRS "${CBLAS_LIBRARY_DIRS}")
PRUVOST Florent's avatar
PRUVOST Florent committed
301 302 303 304
      endif()
      set(REQUIRED_LIBS "${CBLAS_LIBRARIES}")
      # BLAS
      if (BLAS_INCLUDE_DIRS)
305
        list(APPEND REQUIRED_INCDIRS "${BLAS_INCLUDE_DIRS}")
PRUVOST Florent's avatar
PRUVOST Florent committed
306 307
      endif()
      if (BLAS_LIBRARY_DIRS)
308
        list(APPEND REQUIRED_LIBDIRS "${BLAS_LIBRARY_DIRS}")
PRUVOST Florent's avatar
PRUVOST Florent committed
309 310 311
      endif()
      list(APPEND REQUIRED_LIBS "${BLAS_LIBRARIES}")
      if (BLAS_LINKER_FLAGS)
312
        list(APPEND REQUIRED_LDFLAGS "${BLAS_LINKER_FLAGS}")
PRUVOST Florent's avatar
PRUVOST Florent committed
313 314 315 316 317 318 319
      endif()

      # set required libraries for link
      set(CMAKE_REQUIRED_INCLUDES "${REQUIRED_INCDIRS}")
      set(CMAKE_REQUIRED_LIBRARIES)
      list(APPEND CMAKE_REQUIRED_LIBRARIES "${REQUIRED_LDFLAGS}")
      foreach(lib_dir ${REQUIRED_LIBDIRS})
320
        list(APPEND CMAKE_REQUIRED_LIBRARIES "-L${lib_dir}")
PRUVOST Florent's avatar
PRUVOST Florent committed
321 322 323 324 325 326 327 328 329 330 331 332
      endforeach()
      list(APPEND CMAKE_REQUIRED_LIBRARIES "${REQUIRED_LIBS}")
      string(REGEX REPLACE "^ -" "-" CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")

      # test link
      unset(CBLAS_WORKS CACHE)
      include(CheckFunctionExists)
      check_function_exists(cblas_dscal CBLAS_WORKS)
      mark_as_advanced(CBLAS_WORKS)

      if(CBLAS_WORKS)

333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
        # Check for faster complex GEMM routine
        # (only C/Z, no S/D version)
        check_function_exists(cblas_zgemm3m CBLAS_ZGEMM3M_FOUND)
        if ( CBLAS_ZGEMM3M_FOUND )
          add_definitions(-DCBLAS_HAS_ZGEMM3M -DCBLAS_HAS_CGEMM3M)
        endif()

        # save link with dependencies
        set(CBLAS_LIBRARIES_DEP "${REQUIRED_LIBS}")
        set(CBLAS_LIBRARY_DIRS_DEP "${REQUIRED_LIBDIRS}")
        set(CBLAS_INCLUDE_DIRS_DEP "${REQUIRED_INCDIRS}")
        set(CBLAS_LINKER_FLAGS "${REQUIRED_LDFLAGS}")
        list(REMOVE_DUPLICATES CBLAS_LIBRARY_DIRS_DEP)
        list(REMOVE_DUPLICATES CBLAS_INCLUDE_DIRS_DEP)
        list(REMOVE_DUPLICATES CBLAS_LINKER_FLAGS)
PRUVOST Florent's avatar
PRUVOST Florent committed
348
      else()
349 350 351 352 353 354
        if(NOT CBLAS_FIND_QUIETLY)
          message(STATUS "Looking for cblas : test of cblas_dscal with cblas and blas libraries fails")
          message(STATUS "CMAKE_REQUIRED_LIBRARIES: ${CMAKE_REQUIRED_LIBRARIES}")
          message(STATUS "CMAKE_REQUIRED_INCLUDES: ${CMAKE_REQUIRED_INCLUDES}")
          message(STATUS "Check in CMakeFiles/CMakeError.log to figure out why it fails")
        endif()
PRUVOST Florent's avatar
PRUVOST Florent committed
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
      endif()
      set(CMAKE_REQUIRED_INCLUDES)
      set(CMAKE_REQUIRED_FLAGS)
      set(CMAKE_REQUIRED_LIBRARIES)
    endif(CBLAS_LIBRARIES)

  endif (CBLAS_STANDALONE OR NOT CBLAS_WORKS)

else(BLAS_FOUND)

  if (NOT CBLAS_FIND_QUIETLY)
    message(STATUS "CBLAS requires BLAS but BLAS has not been found."
      "Please look for BLAS first.")
  endif()

endif(BLAS_FOUND)

if (CBLAS_LIBRARIES)
  list(GET CBLAS_LIBRARIES 0 first_lib)
  get_filename_component(first_lib_path "${first_lib}" PATH)
375 376 377
  if (NOT CBLAS_LIBRARY_DIRS)
    set(CBLAS_LIBRARY_DIRS "${first_lib_path}")
  endif()
PRUVOST Florent's avatar
PRUVOST Florent committed
378 379 380 381 382 383
  if (${first_lib_path} MATCHES "(/lib(32|64)?$)|(/lib/intel64$|/lib/ia32$)")
    string(REGEX REPLACE "(/lib(32|64)?$)|(/lib/intel64$|/lib/ia32$)" "" not_cached_dir "${first_lib_path}")
    set(CBLAS_DIR_FOUND "${not_cached_dir}" CACHE PATH "Installation directory of CBLAS library" FORCE)
  else()
    set(CBLAS_DIR_FOUND "${first_lib_path}" CACHE PATH "Installation directory of CBLAS library" FORCE)
  endif()
384
endif()
385 386
mark_as_advanced(CBLAS_DIR)
mark_as_advanced(CBLAS_DIR_FOUND)
387 388 389 390 391

# check that CBLAS has been found
# -------------------------------
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CBLAS DEFAULT_MSG
PRUVOST Florent's avatar
PRUVOST Florent committed
392 393
  CBLAS_LIBRARIES
  CBLAS_WORKS)