1include(helpers)
2
3include(CheckSymbolExists)
4
5# The threading library is not needed for igraph itself, but might be needed
6# for tests
7include(FindThreads)
8
9macro(find_dependencies)
10  # Declare the list of dependencies that _may_ be vendored and those that may not
11  set(VENDORABLE_DEPENDENCIES BLAS CXSparse GLPK LAPACK ARPACK GMP)
12  set(NONVENDORABLE_DEPENDENCIES GLPK OpenMP)
13
14  # Declare configuration options for dependencies
15  tristate(IGRAPH_USE_INTERNAL_GMP "Compile igraph with internal Mini-GMP" AUTO)
16  tristate(IGRAPH_USE_INTERNAL_ARPACK "Compile igraph with internal ARPACK" AUTO)
17  tristate(IGRAPH_USE_INTERNAL_BLAS "Compile igraph with internal BLAS" AUTO)
18  tristate(IGRAPH_USE_INTERNAL_CXSPARSE "Compile igraph with internal CXSparse" AUTO)
19  tristate(IGRAPH_USE_INTERNAL_GLPK "Compile igraph with internal GLPK" AUTO)
20  tristate(IGRAPH_USE_INTERNAL_LAPACK "Compile igraph with internal LAPACK" AUTO)
21
22  # Declare dependencies
23  set(REQUIRED_DEPENDENCIES "")
24  set(OPTIONAL_DEPENDENCIES FLEX BISON OpenMP)
25  set(VENDORED_DEPENDENCIES "")
26
27  # Extend dependencies depending on whether we will be using the vendored
28  # copies or not
29  foreach(DEPENDENCY ${VENDORABLE_DEPENDENCIES})
30    string(TOUPPER "${DEPENDENCY}" LIBNAME_UPPER)
31
32    if(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER} STREQUAL "AUTO")
33      find_package(${DEPENDENCY})
34      if(${LIBNAME_UPPER}_FOUND)
35        set(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER} OFF)
36      else()
37        set(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER} ON)
38      endif()
39    endif()
40
41    if(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER})
42      list(APPEND VENDORED_DEPENDENCIES ${DEPENDENCY})
43    else()
44      list(APPEND REQUIRED_DEPENDENCIES ${DEPENDENCY})
45    endif()
46  endforeach()
47
48  # For nonvendorable dependencies, figure out whether we should attempt to
49  # link to them based on the value of the IGRAPH_..._SUPPORT option
50  foreach(DEPENDENCY ${NONVENDORABLE_DEPENDENCIES})
51    string(TOUPPER "${DEPENDENCY}" LIBNAME_UPPER)
52
53    if(IGRAPH_${LIBNAME_UPPER}_SUPPORT STREQUAL "AUTO")
54      find_package(${DEPENDENCY})
55      if(${LIBNAME_UPPER}_FOUND)
56        set(IGRAPH_${LIBNAME_UPPER}_SUPPORT ON)
57      else()
58        set(IGRAPH_${LIBNAME_UPPER}_SUPPORT OFF)
59      endif()
60    endif()
61  endforeach()
62
63  # GraphML support is treated separately because the library name is different
64  if(IGRAPH_GRAPHML_SUPPORT STREQUAL "AUTO")
65    find_package(LibXml2)
66    if(LibXml2_FOUND)
67      set(IGRAPH_GRAPHML_SUPPORT ON)
68    else()
69      set(IGRAPH_GRAPHML_SUPPORT OFF)
70    endif()
71  endif()
72
73  if(NOT IGRAPH_GLPK_SUPPORT)
74    if(IGRAPH_USE_INTERNAL_GLPK)
75      list(REMOVE_ITEM VENDORED_DEPENDENCIES GLPK)
76    else()
77      list(REMOVE_ITEM REQUIRED_DEPENDENCIES GLPK)
78    endif()
79  endif()
80
81  if(IGRAPH_GRAPHML_SUPPORT)
82    list(APPEND REQUIRED_DEPENDENCIES LibXml2)
83  endif()
84
85  # Find dependencies
86  foreach(DEPENDENCY ${REQUIRED_DEPENDENCIES} ${OPTIONAL_DEPENDENCIES})
87    list(FIND REQUIRED_DEPENDENCIES "${DEPENDENCY}" INDEX)
88    set(NEED_THIS_DEPENDENCY NO)
89
90    if(INDEX GREATER_EQUAL 0)
91      # This is a required dependency, search for it unconditionally. Do
92      # not use REQUIRED; we will report errors in a single batch at the end
93      # of the configuration process
94      set(NEED_THIS_DEPENDENCY YES)
95    else()
96      # This is an optional dependency, search for it only if the user did not
97      # turn it off explicitly
98      string(TOUPPER "${DEPENDENCY}" LIBNAME_UPPER)
99      if(NOT DEFINED IGRAPH_${LIBNAME_UPPER}_SUPPORT)
100        set(NEED_THIS_DEPENDENCY YES)
101      elseif(IGRAPH_${LIBNAME_UPPER}_SUPPORT)
102        set(NEED_THIS_DEPENDENCY YES)
103      endif()
104    endif()
105
106    if(NEED_THIS_DEPENDENCY AND NOT DEFINED ${DEPENDENCY}_FOUND)
107      find_package(${DEPENDENCY})
108    endif()
109  endforeach()
110
111  # Override libraries of vendored dependencies even if they were somehow
112  # detected above
113  foreach(DEPENDENCY ${VENDORED_DEPENDENCIES})
114    string(TOUPPER "${DEPENDENCY}" LIBNAME_UPPER)
115    string(TOLOWER "${DEPENDENCY}" LIBNAME_LOWER)
116    if(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER})
117      set(${LIBNAME_UPPER}_LIBRARIES "")
118      set(${LIBNAME_UPPER}_FOUND 1)
119      set(${LIBNAME_UPPER}_IS_VENDORED 1)
120      set(INTERNAL_${LIBNAME_UPPER} 1)
121    endif()
122  endforeach()
123
124  # Export some aliases that will be used in config.h
125  set(HAVE_GLPK ${GLPK_FOUND})
126  set(HAVE_GMP ${GMP_FOUND})
127  set(HAVE_LIBXML ${LIBXML2_FOUND})
128
129  # Check whether we need to link to the math library
130  if(NOT DEFINED CACHE{NEED_LINKING_AGAINST_LIBM})
131    set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
132    set(CMAKE_REQUIRED_QUIET ON)
133    check_symbol_exists(sinh "math.h" SINH_FUNCTION_EXISTS)
134    if(NOT SINH_FUNCTION_EXISTS)
135      unset(SINH_FUNCTION_EXISTS CACHE)
136      set(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES})
137      list(APPEND CMAKE_REQUIRED_LIBRARIES m)
138      check_symbol_exists(sinh "math.h" SINH_FUNCTION_EXISTS)
139      if(SINH_FUNCTION_EXISTS)
140        set(NEED_LINKING_AGAINST_LIBM True CACHE BOOL "" FORCE)
141      else()
142        message(FATAL_ERROR "Failed to figure out how to link to the math library on this platform")
143      endif()
144      set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_SAVE})
145    endif()
146    unset(SINH_FUNCTION_EXISTS CACHE)
147	set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE})
148  endif()
149
150  if(NEED_LINKING_AGAINST_LIBM)
151    find_library(MATH_LIBRARY m)
152  endif()
153
154  mark_as_advanced(MATH_LIBRARY)
155  mark_as_advanced(NEED_LINKING_AGAINST_LIBM)
156endmacro()
157