Home | History | Annotate | Download | only in cmake
      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 PTSCOTCH include dirs and libraries
     12 # Use this module by invoking find_package with the form:
     13 #  find_package(PTSCOTCH
     14 #               [REQUIRED]             # Fail with error if ptscotch is not found
     15 #               [COMPONENTS <comp1> <comp2> ...] # dependencies
     16 #              )
     17 #
     18 #  PTSCOTCH depends on the following libraries:
     19 #   - Threads
     20 #   - MPI
     21 #
     22 #  COMPONENTS can be some of the following:
     23 #   - ESMUMPS: to activate detection of PT-Scotch with the esmumps interface
     24 #
     25 # This module finds headers and ptscotch library.
     26 # Results are reported in variables:
     27 #  PTSCOTCH_FOUND            - True if headers and requested libraries were found
     28 #  PTSCOTCH_LINKER_FLAGS     - list of required linker flags (excluding -l and -L)
     29 #  PTSCOTCH_INCLUDE_DIRS     - ptscotch include directories
     30 #  PTSCOTCH_LIBRARY_DIRS     - Link directories for ptscotch libraries
     31 #  PTSCOTCH_LIBRARIES        - ptscotch component libraries to be linked
     32 #  PTSCOTCH_INCLUDE_DIRS_DEP - ptscotch + dependencies include directories
     33 #  PTSCOTCH_LIBRARY_DIRS_DEP - ptscotch + dependencies link directories
     34 #  PTSCOTCH_LIBRARIES_DEP    - ptscotch libraries + dependencies
     35 #  PTSCOTCH_INTSIZE          - Number of octets occupied by a SCOTCH_Num
     36 #
     37 # The user can give specific paths where to find the libraries adding cmake
     38 # options at configure (ex: cmake path/to/project -DPTSCOTCH=path/to/ptscotch):
     39 #  PTSCOTCH_DIR              - Where to find the base directory of ptscotch
     40 #  PTSCOTCH_INCDIR           - Where to find the header files
     41 #  PTSCOTCH_LIBDIR           - Where to find the library files
     42 # The module can also look for the following environment variables if paths
     43 # are not given as cmake variable: PTSCOTCH_DIR, PTSCOTCH_INCDIR, PTSCOTCH_LIBDIR
     44 
     45 #=============================================================================
     46 # Copyright 2012-2013 Inria
     47 # Copyright 2012-2013 Emmanuel Agullo
     48 # Copyright 2012-2013 Mathieu Faverge
     49 # Copyright 2012      Cedric Castagnede
     50 # Copyright 2013-2016 Florent Pruvost
     51 #
     52 # Distributed under the OSI-approved BSD License (the "License");
     53 # see accompanying file MORSE-Copyright.txt for details.
     54 #
     55 # This software is distributed WITHOUT ANY WARRANTY; without even the
     56 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     57 # See the License for more information.
     58 #=============================================================================
     59 # (To distribute this file outside of Morse, substitute the full
     60 #  License text for the above reference.)
     61 
     62 if (NOT PTSCOTCH_FOUND)
     63   set(PTSCOTCH_DIR "" CACHE PATH "Installation directory of PTSCOTCH library")
     64   if (NOT PTSCOTCH_FIND_QUIETLY)
     65     message(STATUS "A cache variable, namely PTSCOTCH_DIR, has been set to specify the install directory of PTSCOTCH")
     66   endif()
     67 endif()
     68 
     69 # Set the version to find
     70 set(PTSCOTCH_LOOK_FOR_ESMUMPS OFF)
     71 
     72 if( PTSCOTCH_FIND_COMPONENTS )
     73   foreach( component ${PTSCOTCH_FIND_COMPONENTS} )
     74     if (${component} STREQUAL "ESMUMPS")
     75       # means we look for esmumps library
     76       set(PTSCOTCH_LOOK_FOR_ESMUMPS ON)
     77     endif()
     78   endforeach()
     79 endif()
     80 
     81 # PTSCOTCH depends on Threads, try to find it
     82 if (NOT THREADS_FOUND)
     83   if (PTSCOTCH_FIND_REQUIRED)
     84     find_package(Threads REQUIRED)
     85   else()
     86     find_package(Threads)
     87   endif()
     88 endif()
     89 
     90 # PTSCOTCH depends on MPI, try to find it
     91 if (NOT MPI_FOUND)
     92   if (PTSCOTCH_FIND_REQUIRED)
     93     find_package(MPI REQUIRED)
     94   else()
     95     find_package(MPI)
     96   endif()
     97 endif()
     98 
     99 # Looking for include
    100 # -------------------
    101 
    102 # Add system include paths to search include
    103 # ------------------------------------------
    104 unset(_inc_env)
    105 set(ENV_PTSCOTCH_DIR "$ENV{PTSCOTCH_DIR}")
    106 set(ENV_PTSCOTCH_INCDIR "$ENV{PTSCOTCH_INCDIR}")
    107 if(ENV_PTSCOTCH_INCDIR)
    108   list(APPEND _inc_env "${ENV_PTSCOTCH_INCDIR}")
    109 elseif(ENV_PTSCOTCH_DIR)
    110   list(APPEND _inc_env "${ENV_PTSCOTCH_DIR}")
    111   list(APPEND _inc_env "${ENV_PTSCOTCH_DIR}/include")
    112   list(APPEND _inc_env "${ENV_PTSCOTCH_DIR}/include/ptscotch")
    113 else()
    114   if(WIN32)
    115     string(REPLACE ":" ";" _inc_env "$ENV{INCLUDE}")
    116   else()
    117     string(REPLACE ":" ";" _path_env "$ENV{INCLUDE}")
    118     list(APPEND _inc_env "${_path_env}")
    119     string(REPLACE ":" ";" _path_env "$ENV{C_INCLUDE_PATH}")
    120     list(APPEND _inc_env "${_path_env}")
    121     string(REPLACE ":" ";" _path_env "$ENV{CPATH}")
    122     list(APPEND _inc_env "${_path_env}")
    123     string(REPLACE ":" ";" _path_env "$ENV{INCLUDE_PATH}")
    124     list(APPEND _inc_env "${_path_env}")
    125   endif()
    126 endif()
    127 list(APPEND _inc_env "${CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES}")
    128 list(APPEND _inc_env "${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}")
    129 list(REMOVE_DUPLICATES _inc_env)
    130 
    131 
    132 # Try to find the ptscotch header in the given paths
    133 # -------------------------------------------------
    134 
    135 set(PTSCOTCH_hdrs_to_find "ptscotch.h;scotch.h")
    136 
    137 # call cmake macro to find the header path
    138 if(PTSCOTCH_INCDIR)
    139   foreach(ptscotch_hdr ${PTSCOTCH_hdrs_to_find})
    140     set(PTSCOTCH_${ptscotch_hdr}_DIRS "PTSCOTCH_${ptscotch_hdr}_DIRS-NOTFOUND")
    141     find_path(PTSCOTCH_${ptscotch_hdr}_DIRS
    142       NAMES ${ptscotch_hdr}
    143       HINTS ${PTSCOTCH_INCDIR})
    144     mark_as_advanced(PTSCOTCH_${ptscotch_hdr}_DIRS)
    145   endforeach()
    146 else()
    147   if(PTSCOTCH_DIR)
    148     foreach(ptscotch_hdr ${PTSCOTCH_hdrs_to_find})
    149       set(PTSCOTCH_${ptscotch_hdr}_DIRS "PTSCOTCH_${ptscotch_hdr}_DIRS-NOTFOUND")
    150       find_path(PTSCOTCH_${ptscotch_hdr}_DIRS
    151 	NAMES ${ptscotch_hdr}
    152 	HINTS ${PTSCOTCH_DIR}
    153 	PATH_SUFFIXES "include" "include/scotch")
    154       mark_as_advanced(PTSCOTCH_${ptscotch_hdr}_DIRS)
    155     endforeach()
    156   else()
    157     foreach(ptscotch_hdr ${PTSCOTCH_hdrs_to_find})
    158       set(PTSCOTCH_${ptscotch_hdr}_DIRS "PTSCOTCH_${ptscotch_hdr}_DIRS-NOTFOUND")
    159       find_path(PTSCOTCH_${ptscotch_hdr}_DIRS
    160 	NAMES ${ptscotch_hdr}
    161 	HINTS ${_inc_env}
    162 	PATH_SUFFIXES "scotch")
    163       mark_as_advanced(PTSCOTCH_${ptscotch_hdr}_DIRS)
    164     endforeach()
    165   endif()
    166 endif()
    167 
    168 # If found, add path to cmake variable
    169 # ------------------------------------
    170 foreach(ptscotch_hdr ${PTSCOTCH_hdrs_to_find})
    171   if (PTSCOTCH_${ptscotch_hdr}_DIRS)
    172     list(APPEND PTSCOTCH_INCLUDE_DIRS "${PTSCOTCH_${ptscotch_hdr}_DIRS}")
    173   else ()
    174     set(PTSCOTCH_INCLUDE_DIRS "PTSCOTCH_INCLUDE_DIRS-NOTFOUND")
    175     if (NOT PTSCOTCH_FIND_QUIETLY)
    176       message(STATUS "Looking for ptscotch -- ${ptscotch_hdr} not found")
    177     endif()
    178   endif()
    179 endforeach()
    180 list(REMOVE_DUPLICATES PTSCOTCH_INCLUDE_DIRS)
    181 
    182 # Looking for lib
    183 # ---------------
    184 
    185 # Add system library paths to search lib
    186 # --------------------------------------
    187 unset(_lib_env)
    188 set(ENV_PTSCOTCH_LIBDIR "$ENV{PTSCOTCH_LIBDIR}")
    189 if(ENV_PTSCOTCH_LIBDIR)
    190   list(APPEND _lib_env "${ENV_PTSCOTCH_LIBDIR}")
    191 elseif(ENV_PTSCOTCH_DIR)
    192   list(APPEND _lib_env "${ENV_PTSCOTCH_DIR}")
    193   list(APPEND _lib_env "${ENV_PTSCOTCH_DIR}/lib")
    194 else()
    195   if(WIN32)
    196     string(REPLACE ":" ";" _lib_env "$ENV{LIB}")
    197   else()
    198     if(APPLE)
    199       string(REPLACE ":" ";" _lib_env "$ENV{DYLD_LIBRARY_PATH}")
    200     else()
    201       string(REPLACE ":" ";" _lib_env "$ENV{LD_LIBRARY_PATH}")
    202     endif()
    203     list(APPEND _lib_env "${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES}")
    204     list(APPEND _lib_env "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}")
    205   endif()
    206 endif()
    207 list(REMOVE_DUPLICATES _lib_env)
    208 
    209 # Try to find the ptscotch lib in the given paths
    210 # ----------------------------------------------
    211 
    212 set(PTSCOTCH_libs_to_find "ptscotch;ptscotcherr")
    213 if (PTSCOTCH_LOOK_FOR_ESMUMPS)
    214   list(INSERT PTSCOTCH_libs_to_find 0 "ptesmumps")
    215   list(APPEND PTSCOTCH_libs_to_find   "esmumps"  )
    216 endif()
    217 list(APPEND PTSCOTCH_libs_to_find "scotch;scotcherr")
    218 
    219 # call cmake macro to find the lib path
    220 if(PTSCOTCH_LIBDIR)
    221   foreach(ptscotch_lib ${PTSCOTCH_libs_to_find})
    222     set(PTSCOTCH_${ptscotch_lib}_LIBRARY "PTSCOTCH_${ptscotch_lib}_LIBRARY-NOTFOUND")
    223     find_library(PTSCOTCH_${ptscotch_lib}_LIBRARY
    224       NAMES ${ptscotch_lib}
    225       HINTS ${PTSCOTCH_LIBDIR})
    226   endforeach()
    227 else()
    228   if(PTSCOTCH_DIR)
    229     foreach(ptscotch_lib ${PTSCOTCH_libs_to_find})
    230       set(PTSCOTCH_${ptscotch_lib}_LIBRARY "PTSCOTCH_${ptscotch_lib}_LIBRARY-NOTFOUND")
    231       find_library(PTSCOTCH_${ptscotch_lib}_LIBRARY
    232 	NAMES ${ptscotch_lib}
    233 	HINTS ${PTSCOTCH_DIR}
    234 	PATH_SUFFIXES lib lib32 lib64)
    235     endforeach()
    236   else()
    237     foreach(ptscotch_lib ${PTSCOTCH_libs_to_find})
    238       set(PTSCOTCH_${ptscotch_lib}_LIBRARY "PTSCOTCH_${ptscotch_lib}_LIBRARY-NOTFOUND")
    239       find_library(PTSCOTCH_${ptscotch_lib}_LIBRARY
    240 	NAMES ${ptscotch_lib}
    241 	HINTS ${_lib_env})
    242     endforeach()
    243   endif()
    244 endif()
    245 
    246 set(PTSCOTCH_LIBRARIES "")
    247 set(PTSCOTCH_LIBRARY_DIRS "")
    248 # If found, add path to cmake variable
    249 # ------------------------------------
    250 foreach(ptscotch_lib ${PTSCOTCH_libs_to_find})
    251 
    252   if (PTSCOTCH_${ptscotch_lib}_LIBRARY)
    253     get_filename_component(${ptscotch_lib}_lib_path "${PTSCOTCH_${ptscotch_lib}_LIBRARY}" PATH)
    254     # set cmake variables
    255     list(APPEND PTSCOTCH_LIBRARIES "${PTSCOTCH_${ptscotch_lib}_LIBRARY}")
    256     list(APPEND PTSCOTCH_LIBRARY_DIRS "${${ptscotch_lib}_lib_path}")
    257   else ()
    258     list(APPEND PTSCOTCH_LIBRARIES "${PTSCOTCH_${ptscotch_lib}_LIBRARY}")
    259     if (NOT PTSCOTCH_FIND_QUIETLY)
    260       message(STATUS "Looking for ptscotch -- lib ${ptscotch_lib} not found")
    261     endif()
    262   endif ()
    263 
    264   mark_as_advanced(PTSCOTCH_${ptscotch_lib}_LIBRARY)
    265 
    266 endforeach()
    267 list(REMOVE_DUPLICATES PTSCOTCH_LIBRARY_DIRS)
    268 
    269 # check a function to validate the find
    270 if(PTSCOTCH_LIBRARIES)
    271 
    272   set(REQUIRED_LDFLAGS)
    273   set(REQUIRED_INCDIRS)
    274   set(REQUIRED_LIBDIRS)
    275   set(REQUIRED_LIBS)
    276 
    277   # PTSCOTCH
    278   if (PTSCOTCH_INCLUDE_DIRS)
    279     set(REQUIRED_INCDIRS  "${PTSCOTCH_INCLUDE_DIRS}")
    280   endif()
    281   if (PTSCOTCH_LIBRARY_DIRS)
    282     set(REQUIRED_LIBDIRS "${PTSCOTCH_LIBRARY_DIRS}")
    283   endif()
    284   set(REQUIRED_LIBS "${PTSCOTCH_LIBRARIES}")
    285   # MPI
    286   if (MPI_FOUND)
    287     if (MPI_C_INCLUDE_PATH)
    288       list(APPEND CMAKE_REQUIRED_INCLUDES "${MPI_C_INCLUDE_PATH}")
    289     endif()
    290     if (MPI_C_LINK_FLAGS)
    291       if (${MPI_C_LINK_FLAGS} MATCHES "  -")
    292 	string(REGEX REPLACE " -" "-" MPI_C_LINK_FLAGS ${MPI_C_LINK_FLAGS})
    293       endif()
    294       list(APPEND REQUIRED_LDFLAGS "${MPI_C_LINK_FLAGS}")
    295     endif()
    296     list(APPEND REQUIRED_LIBS "${MPI_C_LIBRARIES}")
    297   endif()
    298   # THREADS
    299   if(CMAKE_THREAD_LIBS_INIT)
    300     list(APPEND REQUIRED_LIBS "${CMAKE_THREAD_LIBS_INIT}")
    301   endif()
    302   set(Z_LIBRARY "Z_LIBRARY-NOTFOUND")
    303   find_library(Z_LIBRARY NAMES z)
    304   mark_as_advanced(Z_LIBRARY)
    305   if(Z_LIBRARY)
    306     list(APPEND REQUIRED_LIBS "-lz")
    307   endif()
    308   set(M_LIBRARY "M_LIBRARY-NOTFOUND")
    309   find_library(M_LIBRARY NAMES m)
    310   mark_as_advanced(M_LIBRARY)
    311   if(M_LIBRARY)
    312     list(APPEND REQUIRED_LIBS "-lm")
    313   endif()
    314   set(RT_LIBRARY "RT_LIBRARY-NOTFOUND")
    315   find_library(RT_LIBRARY NAMES rt)
    316   mark_as_advanced(RT_LIBRARY)
    317   if(RT_LIBRARY)
    318     list(APPEND REQUIRED_LIBS "-lrt")
    319   endif()
    320 
    321   # set required libraries for link
    322   set(CMAKE_REQUIRED_INCLUDES "${REQUIRED_INCDIRS}")
    323   set(CMAKE_REQUIRED_LIBRARIES)
    324   list(APPEND CMAKE_REQUIRED_LIBRARIES "${REQUIRED_LDFLAGS}")
    325   foreach(lib_dir ${REQUIRED_LIBDIRS})
    326     list(APPEND CMAKE_REQUIRED_LIBRARIES "-L${lib_dir}")
    327   endforeach()
    328   list(APPEND CMAKE_REQUIRED_LIBRARIES "${REQUIRED_LIBS}")
    329   list(APPEND CMAKE_REQUIRED_FLAGS "${REQUIRED_FLAGS}")
    330   string(REGEX REPLACE "^ -" "-" CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
    331 
    332   # test link
    333   unset(PTSCOTCH_WORKS CACHE)
    334   include(CheckFunctionExists)
    335   check_function_exists(SCOTCH_dgraphInit PTSCOTCH_WORKS)
    336   mark_as_advanced(PTSCOTCH_WORKS)
    337 
    338   if(PTSCOTCH_WORKS)
    339     # save link with dependencies
    340     set(PTSCOTCH_LIBRARIES_DEP "${REQUIRED_LIBS}")
    341     set(PTSCOTCH_LIBRARY_DIRS_DEP "${REQUIRED_LIBDIRS}")
    342     set(PTSCOTCH_INCLUDE_DIRS_DEP "${REQUIRED_INCDIRS}")
    343     set(PTSCOTCH_LINKER_FLAGS "${REQUIRED_LDFLAGS}")
    344     list(REMOVE_DUPLICATES PTSCOTCH_LIBRARY_DIRS_DEP)
    345     list(REMOVE_DUPLICATES PTSCOTCH_INCLUDE_DIRS_DEP)
    346     list(REMOVE_DUPLICATES PTSCOTCH_LINKER_FLAGS)
    347   else()
    348     if(NOT PTSCOTCH_FIND_QUIETLY)
    349       message(STATUS "Looking for PTSCOTCH : test of SCOTCH_dgraphInit with PTSCOTCH library fails")
    350       message(STATUS "CMAKE_REQUIRED_LIBRARIES: ${CMAKE_REQUIRED_LIBRARIES}")
    351       message(STATUS "CMAKE_REQUIRED_INCLUDES: ${CMAKE_REQUIRED_INCLUDES}")
    352       message(STATUS "Check in CMakeFiles/CMakeError.log to figure out why it fails")
    353     endif()
    354   endif()
    355   set(CMAKE_REQUIRED_INCLUDES)
    356   set(CMAKE_REQUIRED_FLAGS)
    357   set(CMAKE_REQUIRED_LIBRARIES)
    358 endif(PTSCOTCH_LIBRARIES)
    359 
    360 if (PTSCOTCH_LIBRARIES)
    361   list(GET PTSCOTCH_LIBRARIES 0 first_lib)
    362   get_filename_component(first_lib_path "${first_lib}" PATH)
    363   if (${first_lib_path} MATCHES "/lib(32|64)?$")
    364     string(REGEX REPLACE "/lib(32|64)?$" "" not_cached_dir "${first_lib_path}")
    365     set(PTSCOTCH_DIR_FOUND "${not_cached_dir}" CACHE PATH "Installation directory of PTSCOTCH library" FORCE)
    366   else()
    367     set(PTSCOTCH_DIR_FOUND "${first_lib_path}" CACHE PATH "Installation directory of PTSCOTCH library" FORCE)
    368   endif()
    369 endif()
    370 mark_as_advanced(PTSCOTCH_DIR)
    371 mark_as_advanced(PTSCOTCH_DIR_FOUND)
    372 
    373 # Check the size of SCOTCH_Num
    374 # ---------------------------------
    375 set(CMAKE_REQUIRED_INCLUDES ${PTSCOTCH_INCLUDE_DIRS})
    376 
    377 include(CheckCSourceRuns)
    378 #stdio.h and stdint.h should be included by scotch.h directly
    379 set(PTSCOTCH_C_TEST_SCOTCH_Num_4 "
    380 #include <stdio.h>
    381 #include <stdint.h>
    382 #include <ptscotch.h>
    383 int main(int argc, char **argv) {
    384   if (sizeof(SCOTCH_Num) == 4)
    385     return 0;
    386   else
    387     return 1;
    388 }
    389 ")
    390 
    391 set(PTSCOTCH_C_TEST_SCOTCH_Num_8 "
    392 #include <stdio.h>
    393 #include <stdint.h>
    394 #include <ptscotch.h>
    395 int main(int argc, char **argv) {
    396   if (sizeof(SCOTCH_Num) == 8)
    397     return 0;
    398   else
    399     return 1;
    400 }
    401 ")
    402 check_c_source_runs("${PTSCOTCH_C_TEST_SCOTCH_Num_4}" PTSCOTCH_Num_4)
    403 if(NOT PTSCOTCH_Num_4)
    404   check_c_source_runs("${PTSCOTCH_C_TEST_SCOTCH_Num_8}" PTSCOTCH_Num_8)
    405   if(NOT PTSCOTCH_Num_8)
    406     set(PTSCOTCH_INTSIZE -1)
    407   else()
    408     set(PTSCOTCH_INTSIZE 8)
    409   endif()
    410 else()
    411   set(PTSCOTCH_INTSIZE 4)
    412 endif()
    413 set(CMAKE_REQUIRED_INCLUDES "")
    414 
    415 # check that PTSCOTCH has been found
    416 # ---------------------------------
    417 include(FindPackageHandleStandardArgs)
    418 find_package_handle_standard_args(PTSCOTCH DEFAULT_MSG
    419   PTSCOTCH_LIBRARIES
    420   PTSCOTCH_WORKS)
    421 #
    422 # TODO: Add possibility to check for specific functions in the library
    423 #
    424