-
Notifications
You must be signed in to change notification settings - Fork 93
/
FindMATLAB.cmake
342 lines (302 loc) · 14 KB
/
FindMATLAB.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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# - this module looks for Matlab
# Defines:
# MATLAB_INCLUDE_DIR: include path for mex.h, engine.h
# MATLAB_LIBRARIES: required libraries: libmex, etc
# MATLAB_MEX_LIBRARY: path to libmex.lib
# MATLAB_MX_LIBRARY: path to libmx.lib
# MATLAB_MAT_LIBRARY: path to libmat.lib
# MATLAB_ENG_LIBRARY: path to libeng.lib
# MATLAB_ROOT: path to Matlab's root directory
# MATLAB_MEX_EXE: path to mex program
# MATLAB_MEX_EXT: mex extension
# MATLAB_CFLAGS, MATLAB_CLINKER_FLAGS, MATLAB_CLIBS (and same for CXX and Fortran)
#
# Note: You cannot use MATLAB_CLIBS etc to set "target_link_libraries" as that gets confused
# by the flag that specifies where the matlab libraries are (at least on Windows for Visual Studio).
# This variable also contains system libraries etc so it's probably not a good idea to use it in
# your CMake file. You should probably use
#
# include_directories(${MATLAB_INCLUDE_DIR})
# add_definitions(${MATLAB_CXXFLAGS})
# target_link_libraries(yourmexfile ${MATLAB_LIBRARIES} )
#
# Reason for MATLAB_CXXFLAGS: on linux, mex files need to be compiled with -fPIC, but that means all
# linked libraries need to be compiled with -fPIC as well.
# This is a derivative work of file FindMatlab.cmake released with
# CMake v2.8, because the original seems to be a bit outdated
#
# This file uses ideas from Gerardus (Author: Ramon Casero <rcasero@...>, Tom Doel)
# and a post by Kent Williams
# http://www.cmake.org/pipermail/cmake/2013-December/056593.html
#
# Heavily modified by Kris Thielemans for WIN32 and recent versions of matlab
#=============================================================================
# Copyright 2005-2009 Kitware, Inc.
# Copyright 2014 University College London
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file 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 CMake, substitute the full
# License text for the above reference.)
# If MATLAB_ROOT was defined in the environment, use it.
if (NOT MATLAB_ROOT AND NOT $ENV{MATLAB_ROOT} STREQUAL "")
set(MATLAB_ROOT $ENV{MATLAB_ROOT} CACHE PATH "set this if CMake does not find it automatically")
file(TO_CMAKE_PATH "${MATLAB_ROOT}" MATLAB_ROOT)
endif()
if (NOT MATLAB_ROOT)
# get path to the Matlab executable
find_program(MATLAB_EXE_PATH matlab
PATHS /usr/local/bin)
if (MATLAB_EXE_PATH)
# found it, so let's find its absolute path and go one level up to find MATLAB_ROOT
message(STATUS "MATLAB executable found: ${MATLAB_EXE_PATH}")
# remove symbolic links
get_filename_component(MATLAB_EXE_PATH "${MATLAB_EXE_PATH}" REALPATH )
# find directory of executable
get_filename_component(my_MATLAB_ROOT "${MATLAB_EXE_PATH}" PATH )
# find root dir
get_filename_component(my_MATLAB_ROOT "${my_MATLAB_ROOT}" PATH )
# store it in the cache
set(MATLAB_ROOT "${my_MATLAB_ROOT}" CACHE PATH "Location of MATLAB files")
else()
# First set MATLAB_ROOT to an empty string but as a cached variable
# this avoids CMake creating a local variable with the same name
set(MATLAB_ROOT "" CACHE PATH "Location of MATLAB files")
# now go and look in more places
if(WIN32)
# Search for a version of Matlab available, starting from the most modern one to older versions
# we didn't really check if these version numbers exist...
foreach(MATVER "13.3" "13.2" "13.1" "13.0" "12.3" "12.2" "12.1" "12.0" "11.3" "11.2" "11.1" "11.0" "10.3" "10.2" "10.1" "10.0" "9.3" "9.2" "9.1" "9.0" "8.5" "8.4" "8.3" "8.2" "8.1" "8.0" "7.16" "7.15" "7.14" "7.13" "7.12" "7.11" "7.10" "7.9" "7.8" "7.7" "7.6" "7.5" "7.4")
if((NOT DEFINED MATLAB_ROOT)
OR ("${MATLAB_ROOT}" STREQUAL "")
OR ("${MATLAB_ROOT}" STREQUAL "/registry"))
get_filename_component(MATLAB_ROOT "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${MATVER};MATLABROOT]" ABSOLUTE)
endif()
endforeach()
if("${MATLAB_ROOT}" STREQUAL "/registry")
set(MATLAB_ROOT "")
endif()
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # Check if this is a Mac
# we look in the applications folder
# Search for a version of Matlab available, starting from the most modern one to older versions
foreach(MATVER "2018b" "2018a" "2017b" "2017a" "2016b" "2016a" "2015b" "2015a" "R2014b" "R2014a" "R2013b" "R2013a" "R2012b" "R2012a" "R2011b" "R2011a" "R2010b" "R2010a" "R2009b" "R2009a" "R2008b")
if((NOT DEFINED MATLAB_ROOT) OR ("${MATLAB_ROOT}" STREQUAL ""))
if(EXISTS /Applications/MATLAB_${MATVER}.app)
set(MATLAB_ROOT /Applications/MATLAB_${MATVER}.app)
endif()
endif()
endforeach()
else()
# could go and look in some other default places for other OSses
endif()
endif()
endif()
if ("${MATLAB_ROOT}" STREQUAL "")
message(STATUS "MATLAB not found. Set MATLAB_ROOT")
# TODO should really skip rest of configuration as it will all fail anyway.
else()
message(STATUS "MATLAB_ROOT set to ${MATLAB_ROOT}")
endif()
# Find out where MATLAB libraries are
IF (NOT MATLAB_LIBRARIES_DIR)
if (WIN32 OR CYGWIN)
# Directory name depending on whether the Windows architecture is 32
# bit or 64 bit
if(CMAKE_SIZEOF_VOID_P MATCHES "4")
set(WINDIR "win32")
elseif(CMAKE_SIZEOF_VOID_P MATCHES "8")
set(WINDIR "win64")
else()
message(WARNING
"CMAKE_SIZEOF_VOID_P (${CMAKE_SIZEOF_VOID_P}) doesn't indicate a valid platform. Guessing 64-bit.")
set(WINDIR "win64")
endif()
message(STATUS "Looking for MATLAB libraries for platform ${WINDIR}")
# Folder where the MEX libraries are, depending on the Windows compiler
if(${CMAKE_GENERATOR} MATCHES "Visual Studio 6")
set(myMATLAB_LIBRARIES_DIR "${MATLAB_ROOT}/extern/lib/${WINDIR}/microsoft/msvc60")
elseif(${CMAKE_GENERATOR} MATCHES "Visual Studio 7")
# Assume people are generally using Visual Studio 7.1,
# if using 7.0 need to link to: ../extern/lib/${WINDIR}/microsoft/msvc70
set(myMATLAB_LIBRARIES_DIR "${MATLAB_ROOT}/extern/lib/${WINDIR}/microsoft/msvc71")
# set(myMATLAB_LIBRARIES_DIR "${MATLAB_ROOT}/extern/lib/${WINDIR}/microsoft/msvc70")
elseif(${CMAKE_GENERATOR} MATCHES "Borland")
# Assume people are generally using Borland 5.4,
# if using 7.0 need to link to: ../extern/lib/${WINDIR}/microsoft/msvc70
set(myMATLAB_LIBRARIES_DIR "${MATLAB_ROOT}/extern/lib/${WINDIR}/microsoft/bcc54")
# set(myMATLAB_LIBRARIES_DIR "${MATLAB_ROOT}/extern/lib/${WINDIR}/microsoft/bcc50")
# set(myMATLAB_LIBRARIES_DIR "${MATLAB_ROOT}/extern/lib/${WINDIR}/microsoft/bcc51")
else()
# We try our luck with the microsoft directory
set(myMATLAB_LIBRARIES_DIR "${MATLAB_ROOT}/extern/lib/${WINDIR}/microsoft/")
endif()
else(WIN32 OR CYGWIN)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LIBRARY_EXTENSION .dylib)
else()
set(LIBRARY_EXTENSION .so)
endif()
# There seems to be no way to let cmake do a search in subdirectories, so use "find"
execute_process(
COMMAND find "${MATLAB_ROOT}/bin" -name libmex${LIBRARY_EXTENSION}
COMMAND xargs echo -n
OUTPUT_VARIABLE mex_lib
)
if (mex_lib)
# find directory of executable
get_filename_component(myMATLAB_LIBRARIES_DIR ${mex_lib} PATH )
endif()
endif(WIN32 OR CYGWIN)
if (NOT myMATLAB_LIBRARIES_DIR)
set(myMATLAB_LIBRARIES_DIR ${MATLAB_ROOT})
endif()
set(MATLAB_LIBRARIES_DIR "${myMATLAB_LIBRARIES_DIR}" CACHE PATH "Location of MATLAB library files")
endif() # MATLAB_LIBRARIES_DIR
message(STATUS "Will look for MATLAB libraries in ${MATLAB_LIBRARIES_DIR}")
if (WIN32 OR CYGWIN)
set(BATEXT .bat)
set(LIBPREFIX lib)
endif()
# This is common to all platforms:
# Get paths to the Matlab MEX libraries
find_library(MATLAB_MEX_LIBRARY
${LIBPREFIX}mex
HINTS "${MATLAB_LIBRARIES_DIR}"
)
find_library(MATLAB_MX_LIBRARY
${LIBPREFIX}mx
HINTS "${MATLAB_LIBRARIES_DIR}"
)
find_library(MATLAB_MAT_LIBRARY
${LIBPREFIX}mat
HINTS "${MATLAB_LIBRARIES_DIR}"
)
find_library(MATLAB_ENG_LIBRARY
${LIBPREFIX}eng
HINTS "${MATLAB_LIBRARIES_DIR}"
)
# Get path to the include directory
find_path(MATLAB_INCLUDE_DIR
"mex.h"
HINTS "${MATLAB_ROOT}/extern/include" "${MATLAB_ROOT}/include"
)
find_program( MATLAB_MEX_PATH mex${BATEXT}
HINTS ${MATLAB_ROOT}/bin
DOC "The mex program path"
)
find_program( MATLAB_MEXEXT_PATH mexext${BATEXT}
HINTS ${MATLAB_ROOT}/bin
DOC "The mexext program path"
)
# find mex extension
execute_process(
COMMAND ${MATLAB_MEXEXT_PATH}
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE MATLAB_MEX_EXT
)
set(MATLAB_LIBRARIES
${MATLAB_MEX_LIBRARY} ${MATLAB_MX_LIBRARY} ${MATLAB_ENG_LIBRARY}
CACHE PATH "Libraries to link mex files"
)
######################### find flags using "mex -v"
# This is based on Kent Williams's post at
# http://www.cmake.org/pipermail/cmake/2013-December/056593.html
# mex -v outputs all the settings used for building MEX files, so
# we can use it to grab the important variables needed
# This sets MATLAB_CFLAGS, MATLAB_CLINKER_FLAGS, MATLAB_CLIBS (and same for CXX and Fortran)
macro(MATLAB_GETFLAGS FILENAME)
execute_process(COMMAND ${MATLAB_MEX_PATH} -v -n ${FILENAME}
OUTPUT_VARIABLE mexOut
ERROR_VARIABLE mexErr)
# parse mex output line by line by turning file into CMake list of lines
string(REGEX REPLACE "\r?\n" ";" _mexOut "${mexOut}")
foreach(line ${_mexOut})
if("${line}" MATCHES "[\t ]+DEFINES *:") # on Linux
string(REGEX REPLACE "[\t ]+DEFINES *: *" "" mexDefines "${line}")
elseif("${line}" MATCHES "[\t ]+COMPDEFINES *:") # on Windows
string(REGEX REPLACE "[\t ]+COMPDEFINES *: *" "" mexDefines "${line}")
elseif("${line}" MATCHES "[\t ]+LINKFLAGS *:")
string(REGEX REPLACE "[\t ]+LINKFLAGS *: *" "" mexLdFlags "${line}")
# get rid of /implib statement used on some older windows-matlab versions (refers to temp file)
string(REGEX REPLACE "/implib:\".*\"" "" mexLdFlags "${mexLdFlags}")
elseif("${line}" MATCHES "[\t ]+LINKLIBS *:")
string(REGEX REPLACE "[\t ]+LINKLIBS *: *" "" mexLdLibs "${line}")
elseif("${line}" MATCHES "[\t ]+LINKEXPORT *:")
string(REGEX REPLACE "[\t ]+LINKEXPORT *: *" "" mexLdExport "${line}")
elseif("${line}" MATCHES "[\t ]+CXXFLAGS *[:=]")
string(REGEX REPLACE "[\t ]+CXXFLAGS *[:=] *" "" mexCxxFlags "${line}")
#message(STATUS "mexcxx ${mexCxxFlags}")
elseif("${line}" MATCHES "[\t ]+CFLAGS *[:=]")
string(REGEX REPLACE "[\t ]+CFLAGS *[:=] *" "" mexCFlags "${line}")
elseif("${line}" MATCHES "[\t ]+FFLAGS *[:=]")
string(REGEX REPLACE "[\t ]+FFLAGS *[:=] *" "" mexFFlags "${line}")
# pre-2014a flags
elseif("${line}" MATCHES "[\t ]+CXXLIBS *[:=]")
string(REGEX REPLACE "[\t ]+CXXLIBS *[:=] *" "" mexCxxLibs "${line}")
elseif("${line}" MATCHES "[\t ]+CLIBS *[:=]")
string(REGEX REPLACE "[\t ]+CLIBS *[:=] *" "" mexCLibs "${line}")
elseif("${line}" MATCHES "[\t ]+FLIBS *[:=]")
string(REGEX REPLACE "[\t ]+FLIBS *[:=] *" "" mexFLibs "${line}")
elseif("${line}" MATCHES "[\t ]+LDFLAGS *[:=]")
string(REGEX REPLACE "[\t ]+LDFLAGS *[:=] *" "" mexLdFlags "${line}")
elseif("${line}" MATCHES "[\t ]+LDCXXFLAGS *[:=]")
string(REGEX REPLACE "[\t ]+LDCXXFLAGS *[:=] *" "" mexLdCxxFlags "${line}")
elseif("${line}" MATCHES "[\t ]+LDCFLAGS *[:=]")
string(REGEX REPLACE "[\t ]+LDCFLAGS *[:=] *" "" mexLdCFlags "${line}")
elseif("${line}" MATCHES "[\t ]+LDFLAGS *[:=]")
string(REGEX REPLACE "[\t ]+LDFLAGS *[:=] *" "" mexLdFFlags "${line}")
endif()
endforeach()
endmacro()
# Since 2014a or so, mex can only be used for one type of source and no longer
# reports all flags. We therefore need to run mex with different file types.
#### C
MATLAB_GETFLAGS(${PROJECT_SOURCE_DIR}/src/cmake/FindMATLAB_mextest.c)
set(MATLAB_CFLAGS "${mexDefines} ${mexCFlags}" CACHE STRING "Flags to compile C MATLAB Mex files (or libraries that link with them)")
set(MATLAB_CLINKER_FLAGS "${mexLdFlags} ${mexLdCFlags} ${mexLdExport}" CACHE STRING "Flags to link MATLAB C Mex files")
set(MATLAB_CLIBS "${mexLdLibs} ${mexCLibs}" CACHE STRING "Flags with libraries to link MATLAB C Mex files")
#### C++
MATLAB_GETFLAGS(${PROJECT_SOURCE_DIR}/src/cmake/FindMATLAB_mextest.cxx)
set(MATLAB_CXXFLAGS "${mexDefines} ${mexCxxFlags}" CACHE STRING "Flags to compile C++ MATLAB Mex files (or libraries that link with them)")
set(MATLAB_CXXLINKER_FLAGS "${mexLdFlags} ${mexLdCxxFlags} ${mexLdExport}" CACHE STRING "Flags to link MATLAB C++ Mex files")
set(MATLAB_CXXLIBS "${mexLdLibs} ${mexCxxLibs}" CACHE STRING "Flags with libraries to link MATLAB C++ Mex files")
#### Fortran
MATLAB_GETFLAGS(${PROJECT_SOURCE_DIR}/src/cmake/FindMATLAB_mextest.f)
set(MATLAB_FFLAGS "${mexDefines} ${mexFFlags}" CACHE STRING "Flags to compile Fortran MATLAB Mex files (or libraries that link with them)")
set(MATLAB_FLINKER_FLAGS "${mexLdFlags} ${mexLdFFlags} ${mexLdExport}" CACHE STRING "Flags to link MATLAB Fortran Mex files")
set(MATLAB_FLIBS "${mexLdLibs} ${mexFLibs}" CACHE STRING "Flags with libraries to link MATLAB Fortran Mex files")
# handle the QUIETLY and REQUIRED arguments and set MATLAB_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MATLAB "MATLAB not found. If you do have it, set missing variables (e.g. via MATLAB_ROOT) and reconfigure"
MATLAB_ROOT MATLAB_INCLUDE_DIR MATLAB_LIBRARIES
MATLAB_MEX_PATH
MATLAB_MEXEXT_PATH
MATLAB_MEX_EXT
)
mark_as_advanced(
MATLAB_EXE_PATH
MATLAB_LIBRARIES
MATLAB_MEX_LIBRARY
MATLAB_MX_LIBRARY
MATLAB_ENG_LIBRARY
MATLAB_INCLUDE_DIR
MATLAB_FOUND
MATLAB_MAT_LIBRARY
MATLAB_MEX_PATH
MATLAB_MEXEXT_PATH
MATLAB_MEX_EXT
MATLAB_CFLAGS
MATLAB_CXXFLAGS
MATLAB_FFLAGS
MATLAB_CLINKER_FLAGS
MATLAB_CXXLINKER_FLAGS
MATLAB_FLINKER_FLAGS
MATLAB_CLIBS
MATLAB_CXXLIBS
MATLAB_FLIBS
)