1# This module looks for mex, the MATLAB compiler.
2# The following variables are defined when the script completes:
3#   MATLAB_MEX: location of mex compiler
4#   MATLAB_ROOT: root of MATLAB installation
5#   MATLABMEX_FOUND: 0 if not found, 1 if found
6
7SET(MATLABMEX_FOUND 0)
8SET(MATLABMCC_FOUND 0)
9
10IF(WIN32)
11  # Win32 is Untested
12  # Taken from the older FindMatlab.cmake script as well as
13  # the modifications by Ramon Casero and Tom Doel for Gerardus.
14
15  # Search for a version of Matlab available, starting from the most modern one
16  # to older versions.
17  FOREACH(MATVER "7.20" "7.19" "7.18" "7.17" "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")
18    IF((NOT DEFINED MATLAB_ROOT)
19        OR ("${MATLAB_ROOT}" STREQUAL "")
20        OR ("${MATLAB_ROOT}" STREQUAL "/registry"))
21      GET_FILENAME_COMPONENT(MATLAB_ROOT
22        "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${MATVER};MATLABROOT]"
23        ABSOLUTE)
24      SET(MATLAB_VERSION ${MATVER})
25    ENDIF((NOT DEFINED MATLAB_ROOT)
26      OR ("${MATLAB_ROOT}" STREQUAL "")
27      OR ("${MATLAB_ROOT}" STREQUAL "/registry"))
28  ENDFOREACH(MATVER)
29
30  FIND_PROGRAM(MATLAB_MEX
31          mex
32          ${MATLAB_ROOT}/bin
33          )
34  FIND_PROGRAM(MATLAB_MCC
35          mex
36          ${MATLAB_ROOT}/bin
37          )
38ELSE(WIN32)
39  # Check if this is a Mac.
40  IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
41    # Mac is untested
42    # Taken from the older FindMatlab.cmake script as
43    # well as the modifications by Ramon Casero and Tom Doel for Gerardus.
44
45   SET(LIBRARY_EXTENSION .dylib)
46
47    # If this is a Mac and the attempts to find MATLAB_ROOT have so far failed,~
48    # we look in the applications folder
49    IF((NOT DEFINED MATLAB_ROOT) OR ("${MATLAB_ROOT}" STREQUAL ""))
50
51    # Search for a version of Matlab available, starting from the most modern
52    # one to older versions
53      FOREACH(MATVER "2016b" "2014b" "R2013b" "R2013a" "R2012b" "R2012a" "R2011b" "R2011a" "R2010b" "R2010a" "R2009b" "R2009a" "R2008b")
54        IF((NOT DEFINED MATLAB_ROOT) OR ("${MATLAB_ROOT}" STREQUAL ""))
55          IF(EXISTS /Applications/MATLAB_${MATVER}.app)
56            SET(MATLAB_ROOT /Applications/MATLAB_${MATVER}.app)
57
58          ENDIF(EXISTS /Applications/MATLAB_${MATVER}.app)
59        ENDIF((NOT DEFINED MATLAB_ROOT) OR ("${MATLAB_ROOT}" STREQUAL ""))
60      ENDFOREACH(MATVER)
61
62    ENDIF((NOT DEFINED MATLAB_ROOT) OR ("${MATLAB_ROOT}" STREQUAL ""))
63
64    FIND_PROGRAM(MATLAB_MEX
65            mex
66            PATHS
67            ${MATLAB_ROOT}/bin
68            )
69    FIND_PROGRAM(MATLAB_MCC
70            mcc
71            PATHS
72            ${MATLAB_ROOT}/bin
73            )
74
75  ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
76    # On a Linux system.  The goal is to find MATLAB_ROOT.
77    SET(LIBRARY_EXTENSION .so)
78
79    FIND_PROGRAM(MATLAB_MEX
80            mex
81            PATHS
82            ${MATLAB_ROOT}/bin
83            /prog/matlab/R2016B/bin # Statoil location
84            /prog/matlab/R2014B/bin # Statoil location
85            /opt/matlab/bin
86            /usr/local/matlab/bin
87            $ENV{HOME}/matlab/bin
88            # Now all the versions
89            /opt/matlab/[rR]20[0-9][0-9][abAB]/bin
90            /usr/local/matlab/[rR]20[0-9][0-9][abAB]/bin
91            /opt/matlab-[rR]20[0-9][0-9][abAB]/bin
92            /opt/matlab_[rR]20[0-9][0-9][abAB]/bin
93            /usr/local/matlab-[rR]20[0-9][0-9][abAB]/bin
94            /usr/local/matlab_[rR]20[0-9][0-9][abAB]/bin
95            $ENV{HOME}/matlab/[rR]20[0-9][0-9][abAB]/bin
96            $ENV{HOME}/matlab-[rR]20[0-9][0-9][abAB]/bin
97            $ENV{HOME}/matlab_[rR]20[0-9][0-9][abAB]/bin
98            )
99
100    GET_FILENAME_COMPONENT(MATLAB_MEX "${MATLAB_MEX}" REALPATH)
101    GET_FILENAME_COMPONENT(MATLAB_BIN_ROOT "${MATLAB_MEX}" PATH)
102    # Strip ./bin/.
103    GET_FILENAME_COMPONENT(MATLAB_ROOT "${MATLAB_BIN_ROOT}" PATH)
104
105    FIND_PROGRAM(MATLAB_MCC
106            mcc
107            PATHS
108            ${MATLAB_ROOT}/bin
109            )
110
111    FIND_PROGRAM(MATLAB_MEXEXT
112            mexext
113            PATHS
114            ${MATLAB_ROOT}/bin
115            )
116
117    GET_FILENAME_COMPONENT(MATLAB_MCC "${MATLAB_MCC}" REALPATH)
118    GET_FILENAME_COMPONENT(MATLAB_MEXEXT "${MATLAB_MEXEXT}" REALPATH)
119  ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
120ENDIF(WIN32)
121
122IF(NOT EXISTS "${MATLAB_MEX}" AND "${MatlabMex_FIND_REQUIRED}")
123  MESSAGE(FATAL_ERROR "Could not find MATLAB mex compiler; try specifying MATLAB_ROOT.")
124ELSE(NOT EXISTS "${MATLAB_MEX}" AND "${MatlabMex_FIND_REQUIRED}")
125  IF(EXISTS "${MATLAB_MEX}")
126    MESSAGE(STATUS "Found MATLAB mex compiler: ${MATLAB_MEX}")
127    MESSAGE(STATUS "MATLAB root: ${MATLAB_ROOT}")
128    SET(MATLABMEX_FOUND 1)
129  ENDIF(EXISTS "${MATLAB_MEX}")
130ENDIF(NOT EXISTS "${MATLAB_MEX}" AND "${MatlabMex_FIND_REQUIRED}")
131
132IF(NOT EXISTS "${MATLAB_MCC}" AND "${MatlabMcc_FIND_REQUIRED}")
133  MESSAGE(FATAL_ERROR "Could not find MATLAB mcc compiler; try specifying MATLAB_ROOT.")
134ELSE(NOT EXISTS "${MATLAB_MCC}" AND "${MatlabMcc_FIND_REQUIRED}")
135  IF(EXISTS "${MATLAB_MCC}")
136    MESSAGE(STATUS "Found MATLAB mcc compiler: ${MATLAB_MCC}")
137    SET(MATLABMCC_FOUND 1)
138  ENDIF(EXISTS "${MATLAB_MCC}")
139ENDIF(NOT EXISTS "${MATLAB_MCC}" AND "${MatlabMcc_FIND_REQUIRED}")
140
141MARK_AS_ADVANCED(
142  MATLABMEX_FOUND
143)
144
145SET(MATLAB_ROOT ${MATLAB_ROOT} CACHE FILEPATH "Path to a matlab installation")
146
147EXECUTE_PROCESS(COMMAND ${MATLAB_MEXEXT} OUTPUT_VARIABLE MEXEXT OUTPUT_STRIP_TRAILING_WHITESPACE)
148
149macro(mexo MEX_OBJECT)
150    set(MEX_CFLAGS -fPIC  -std=c99 -Werror)
151    set(MEX_LDFLAGS)
152
153    get_property(dirs DIRECTORY . PROPERTY INCLUDE_DIRECTORIES)
154    foreach(dir ${dirs})
155        set(MEX_CFLAGS ${MEX_CFLAGS} -I${dir})
156    endforeach()
157
158    set(MEX_LDFLAGS -shared)
159
160    set(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/${MEX_OBJECT}.c)
161    set(HEADER ${CMAKE_CURRENT_SOURCE_DIR}/${MEX_OBJECT}.h)
162    set(OBJECT ${CMAKE_CURRENT_BINARY_DIR}/${MEX_OBJECT}.o)
163
164    add_custom_command(OUTPUT ${OBJECT}
165            COMMAND
166            ${MATLAB_MEX}
167            -c
168            CC="${CMAKE_C_COMPILER}"
169            LD="${CMAKE_CXX_COMPILER}"
170            CFLAGS="${MEX_CFLAGS}"
171            LDFLAGS="${MEX_LDFLAGS}"
172            -outdir ${CMAKE_CURRENT_BINARY_DIR}
173            ${SOURCE}
174            DEPENDS
175            ${SOURCE}
176            ${HEADER}
177            )
178
179    add_custom_target(${MEX_OBJECT} ALL DEPENDS ${OBJECT})
180endmacro()
181
182macro(mex MEX_NAME )
183    set(DEP ${ARG2})
184    set(MEX_CFLAGS -fPIC  -std=c99 -Werror)
185    set(MEX_LDFLAGS)
186
187    get_property(dirs DIRECTORY . PROPERTY INCLUDE_DIRECTORIES)
188    foreach(dir ${dirs})
189        set(MEX_CFLAGS ${MEX_CFLAGS} -I${dir})
190    endforeach()
191
192    set(MEX_LDFLAGS -shared)
193
194    set(MEX_SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${MEX_NAME}.c)
195    set(MEX_RESULT_FILE ${CMAKE_CURRENT_BINARY_DIR}/${MEX_NAME}.${MEXEXT})
196    add_custom_command(OUTPUT ${MEX_RESULT_FILE}
197            COMMAND
198            ${MATLAB_MEX}
199            CC="${CMAKE_C_COMPILER}"
200            CXX="${CMAKE_CXX_COMPILER}"
201            LD="${CMAKE_CXX_COMPILER}"
202            CFLAGS="${MEX_CFLAGS}"
203            LDFLAGS="${MEX_LDFLAGS}"
204            ${OBJECT}
205            $<TARGET_FILE:segyio>
206            -outdir ${CMAKE_CURRENT_BINARY_DIR}
207            ${MEX_SOURCE_FILE}
208            DEPENDS
209            ${MEX_SOURCE_FILE}
210            segyio
211            segyutil.o
212            )
213
214    add_custom_target(${MEX_NAME} ALL DEPENDS ${MEX_RESULT_FILE} segyutil.o)
215
216    set(${MEX_NAME}_TARGET ${MEX_NAME} PARENT_SCOPE)
217    set(${MEX_NAME}_FILE ${MEX_RESULT_FILE} PARENT_SCOPE)
218
219endmacro()
220
221
222# this isn't meant to be run directly; use matlab_add_test or
223# matlab_add_example instead
224function(matlab_test TYPE TESTNAME MCC_SOURCE_FILE)
225    configure_file(${MCC_SOURCE_FILE} ${MCC_SOURCE_FILE} COPYONLY)
226
227    add_test(NAME ${TESTNAME}
228            COMMAND ${MATLAB_ROOT}/bin/matlab -nodisplay -nosplash -nodesktop -r
229            "addpath('../mex'), try, run('${MCC_SOURCE_FILE}'), exit(0), catch, exit(-1), end;" < /dev/null
230            )
231endfunction()
232
233function(add_matlab_test TESTNAME MCC_SOURCE_FILE)
234    matlab_test(tests ${TESTNAME} ${MCC_SOURCE_FILE})
235endfunction()
236
237# add_matlab_example takes an arbitrary number of arguments which it will
238# forward to the example program
239function(add_matlab_example TESTNAME MCC_SOURCE_FILE)
240    matlab_test(examples ${TESTNAME} ${MCC_SOURCE_FILE})
241endfunction()
242