forked from wullm/monofonic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FindFFTW3.cmake
258 lines (227 loc) · 8.15 KB
/
FindFFTW3.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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
167
168
169
170
171
172
173
174
175
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# - Try to find FFTW
#
# By default, it will look only for the serial libraries with single, double,
# and long double precision. Any combination of precision (SINGLE, DOUBLE,
# LONGDOUBLE) and library type (SERIAL, [THREADS|OPENMP], MPI) is possible by
# using the COMPONENTS keyword. For example,
#
# find_package(FFTW3 COMPONENTS SINGLE DOUBLE OPENMP MPI)
#
# Once done this will define
# FFTW3_FOUND - System has FFTW3
# FFTW3_INCLUDE_DIRS - The FFTW3 include directories
# FFTW3_LIBRARIES - The libraries needed to use FFTW3
# FFTW3_DEFINITIONS - Compiler switches required for using FFTW3
# FFTW3_$KIND_$PARALLEL_FOUND- Set if FFTW3 exists in KIND precision format for PARALLEL mode.
# where KIND can be: SINGLE, DOUBLE, LONGDOUBLE
# and PARALLEL: SERIAL, OPENMP, MPI, THREADS.
# FFTW3_$KIND_$PARALLEL_LIBRARY - The libraries needed to use.
# FFTW3_INCLUDE_DIR_PARALLEL - The FFTW3 include directories for parallels mode.
cmake_policy(SET CMP0054 NEW)
if(FFTW3_FOUND)
return()
endif()
if(FFTW3_INCLUDE_DIR AND FFTW3_LIBRARIES)
set(FFTW3_FOUND TRUE)
foreach(component ${FFTW3_FIND_COMPONENTS})
if("${FFTW3_${component}_LIBRARY}" STREQUAL "")
set(FFTW3_${component}_LIBRARY "${FFTW3_LIBRARIES}")
endif()
endforeach()
return()
endif()
macro(find_specific_libraries KIND PARALLEL)
list(APPEND FFTW3_FIND_COMPONENTS ${KIND}_${PARALLEL})
if(NOT (${PARALLEL} STREQUAL "SERIAL") AND NOT ${PARALLEL}_FOUND)
message(FATAL_ERROR "Please, find ${PARALLEL} libraries before FFTW")
endif()
find_library(
FFTW3_${KIND}_${PARALLEL}_LIBRARY
NAMES fftw3${SUFFIX_${KIND}}${SUFFIX_${PARALLEL}}${SUFFIX_FINAL}
HINTS ${HINT_DIRS}
)
if(FFTW3_${KIND}_${PARALLEL}_LIBRARY MATCHES fftw3)
list(APPEND FFTW3_LIBRARIES ${FFTW3_${KIND}_${PARALLEL}_LIBRARY})
set(FFTW3_${KIND}_${PARALLEL}_FOUND TRUE)
STRING(TOLOWER "${KIND}" kind)
STRING(TOLOWER "${PARALLEL}" parallel)
if(FFTW3_${kind}_${parallel}_LIBRARY MATCHES "\\.a$")
add_library(fftw3::${kind}::${parallel} STATIC IMPORTED GLOBAL)
else()
add_library(fftw3::${kind}::${parallel} SHARED IMPORTED GLOBAL)
endif()
# MPI Has a different included library than the others
# FFTW3_INCLUDE_DIR_PARALLEL will change depending of which on is used.
set(FFTW3_INCLUDE_DIR_PARALLEL ${FFTW3_INCLUDE_DIR} )
if(PARALLEL STREQUAL "MPI")
set(FFTW3_INCLUDE_DIR_PARALLEL ${FFTW3_${PARALLEL}_INCLUDE_DIR})
endif()
set_target_properties(fftw3::${kind}::${parallel} PROPERTIES
IMPORTED_LOCATION "${FFTW3_${KIND}_${PARALLEL}_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR_PARALLEL}")
# adding target properties to the different cases
## MPI
if(PARALLEL STREQUAL "MPI")
if(MPI_C_LIBRARIES)
set_target_properties(fftw3::${kind}::mpi PROPERTIES
IMPORTED_LOCATION "${FFTW3_${KIND}_${PARALLEL}_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR_PARALLEL}"
IMPORTED_LINK_INTERFACE_LIBRARIES "${MPI_C_LIBRARIES}")
endif()
endif()
## OpenMP
if(PARALLEL STREQUAL "OPENMP")
if(OPENMP_C_FLAGS)
set_target_properties(fftw3::${kind}::${parallel} PROPERTIES
IMPORTED_LOCATION "${FFTW3_${KIND}_${PARALLEL}_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR_PARALLEL}"
INTERFACE_COMPILE_OPTIONS "${OPENMP_C_FLAGS}")
endif()
endif()
## THREADS
if(PARALLEL STREQUAL "THREADS")
if(CMAKE_THREAD_LIBS_INIT) # TODO: this is not running
set_target_properties(fftw3::${kind}::${parallel} PROPERTIES
IMPORTED_LOCATION "${FFTW3_${KIND}_${PARALLEL}_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR_PARALLEL}"
INTERFACE_COMPILE_OPTIONS "${CMAKE_THREAD_LIBS_INIT}")
endif()
endif()
endif()
endmacro()
if(NOT FFTW3_FIND_COMPONENTS)
set(FFTW3_FIND_COMPONENTS SINGLE DOUBLE LONGDOUBLE SERIAL)
endif()
string(TOUPPER "${FFTW3_FIND_COMPONENTS}" FFTW3_FIND_COMPONENTS)
list(FIND FFTW3_FIND_COMPONENTS SINGLE LOOK_FOR_SINGLE)
list(FIND FFTW3_FIND_COMPONENTS DOUBLE LOOK_FOR_DOUBLE)
list(FIND FFTW3_FIND_COMPONENTS LONGDOUBLE LOOK_FOR_LONGDOUBLE)
list(FIND FFTW3_FIND_COMPONENTS THREADS LOOK_FOR_THREADS)
list(FIND FFTW3_FIND_COMPONENTS OPENMP LOOK_FOR_OPENMP)
list(FIND FFTW3_FIND_COMPONENTS MPI LOOK_FOR_MPI)
list(FIND FFTW3_FIND_COMPONENTS SERIAL LOOK_FOR_SERIAL)
# FIXME - This may fail in computers wihtout serial
# Default serial to obtain version number
set(LOOK_FOR_SERIAL 1)
# set serial as default if none parallel component has been set
if((LOOK_FOR_THREADS LESS 0) AND (LOOK_FOR_MPI LESS 0) AND
(LOOK_FOR_OPENMP LESS 0))
set(LOOK_FOR_SERIAL 1)
endif()
if(MPI_C_FOUND)
set(MPI_FOUND ${MPI_C_FOUND})
endif()
unset(FFTW3_FIND_COMPONENTS)
if(WIN32)
set(HINT_DIRS ${FFTW3_DIRECTORY} $ENV{FFTW3_DIRECTORY})
else()
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules(PC_FFTW QUIET fftw3)
set(FFTW3_DEFINITIONS ${PC_FFTW_CFLAGS_OTHER})
endif()
set(HINT_DIRS
${PC_FFTW_INCLUDEDIR}
${PC_FFTW_INCLUDE_DIRS}
${FFTW3_INCLUDE_DIR}
$ENV{FFTW3_INCLUDE_DIR}
)
endif()
find_path(FFTW3_INCLUDE_DIR
NAMES fftw3.h
HINTS ${HINT_DIRS})
if (LOOK_FOR_MPI) # Probably is going to be the same as fftw3.h
find_path(FFTW3_MPI_INCLUDE_DIR
NAMES fftw3-mpi.h
HINTS ${HINT_DIRS})
endif()
function(find_version OUTVAR LIBRARY SUFFIX)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/fftw${SUFFIX}/main.c
# TODO: do we need to add include for mpi headers?
"#include <fftw3.h>
#include <stdio.h>
int main(int nargs, char const *argv[]) {
printf(\"%s\", fftw${SUFFIX}_version);
return 0;
}"
)
if(NOT CMAKE_CROSSCOMPILING)
try_run(RUN_RESULT COMPILE_RESULT
"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/fftw${SUFFIX}/"
"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/fftw${SUFFIX}/main.c"
CMAKE_FLAGS
-DLINK_LIBRARIES=${LIBRARY}
-DINCLUDE_DIRECTORIES=${FFTW3_INCLUDE_DIR}
RUN_OUTPUT_VARIABLE OUTPUT
COMPILE_OUTPUT_VARIABLE COUTPUT
)
endif()
if(RUN_RESULT EQUAL 0)
string(REGEX REPLACE
".*([0-9]+\\.[0-9]+\\.[0-9]+).*"
"\\1" VERSION_STRING "${OUTPUT}"
)
set(${OUTVAR} ${VERSION_STRING} PARENT_SCOPE)
endif()
endfunction()
set(SUFFIX_DOUBLE "")
set(SUFFIX_SINGLE "f")
set(SUFFIX_LONGDOUBLE "l")
set(SUFFIX_SERIAL "")
set(SUFFIX_OPENMP "_omp")
set(SUFFIX_MPI "_mpi")
set(SUFFIX_THREADS "_threads")
set(SUFFIX_FINAL "")
if(WIN32)
set(SUFFIX_FINAL "-3")
else()
set(HINT_DIRS
${PC_FFTW_LIBDIR}
${PC_FFTW_LIBRARY_DIRS}
$ENV{FFTW3_LIBRARY_DIR}
${FFTW3_LIBRARY_DIR} )
endif(WIN32)
unset(FFTW3_LIBRARIES)
set(FFTW3_INCLUDE_DIRS ${FFTW3_INCLUDE_DIR} ) # TODO what's for?
set(FFTW3_FLAGS_C "")
foreach(KIND SINGLE DOUBLE LONGDOUBLE)
if(LOOK_FOR_${KIND} LESS 0)
continue()
endif()
foreach(PARALLEL SERIAL MPI OPENMP THREADS)
if(LOOK_FOR_${PARALLEL} LESS 0)
continue()
endif()
find_specific_libraries(${KIND} ${PARALLEL})
endforeach()
endforeach()
if(FFTW3_INCLUDE_DIR)
list(GET FFTW3_FIND_COMPONENTS 0 smallerrun)
string(REPLACE "_" ";" RUNLIST ${smallerrun})
list(GET RUNLIST 0 KIND)
list(GET RUNLIST 1 PARALLEL)
unset(smallerrun)
unset(RUNLIST)
# suffix is quoted so it pass empty in the case of double as it's empty
find_version(FFTW3_VERSION_STRING ${FFTW3_${KIND}_${PARALLEL}_LIBRARY}
"${SUFFIX_${KIND}}")
endif()
# FIXME: fails if use REQUIRED.
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set FFTW3_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(FFTW3
REQUIRED_VARS FFTW3_LIBRARIES FFTW3_INCLUDE_DIR
VERSION_VAR FFTW3_VERSION_STRING
HANDLE_COMPONENTS
)
if(FFTW3_FOUND)
foreach(component ${FFTW3_FIND_COMPONENTS})
if(NOT TARGET FFTW3::FFTW3_${component})
add_library(FFTW3::FFTW3_${component} UNKNOWN IMPORTED)
set_target_properties(FFTW3::FFTW3_${component} PROPERTIES
IMPORTED_LOCATION "${FFTW3_${component}_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES ${FFTW3_INCLUDE_DIR})
endif()
endforeach()
endif()