diff options
author | Cris Luengo <cris.l.luengo@gmail.com> | 2018-10-22 05:59:31 (GMT) |
---|---|---|
committer | Cris Luengo <cris.l.luengo@gmail.com> | 2018-10-24 05:50:17 (GMT) |
commit | d7e19032d52f9d1529a27bb1061da33524b69060 (patch) | |
tree | 482fd23a7f88b88a04a8480a73776216f7989657 /Modules/FindMatlab.cmake | |
parent | 518553d9537be7e6c245090e52ba989df5686e19 (diff) | |
download | CMake-d7e19032d52f9d1529a27bb1061da33524b69060.zip CMake-d7e19032d52f9d1529a27bb1061da33524b69060.tar.gz CMake-d7e19032d52f9d1529a27bb1061da33524b69060.tar.bz2 |
FindMatlab: `matlab_add_mex` has new options `R2017b` and `R2018a`.
- These options are equivalent to `mex` command options `-R2017b` and `-R2018a`.
- `R2017b` is the default, and selects the compatability API.
- `R2018a` is the alternative, and selects the new complex-interleaved API.
- For versions of MATLAB before R2018a, these options are ignored.
- `matlab_add_mex` now works correctly with newer MATLABs.
Diffstat (limited to 'Modules/FindMatlab.cmake')
-rw-r--r-- | Modules/FindMatlab.cmake | 157 |
1 files changed, 87 insertions, 70 deletions
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 1e29702..0f0fd8d 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -884,6 +884,7 @@ endfunction() [OUTPUT_NAME output_name] [DOCUMENTATION file.txt] [LINK_TO target1 target2 ...] + [R2017b | R2018a] [...] ) @@ -904,6 +905,12 @@ endfunction() the same folder without any processing, with the same name as the final mex file, and with extension `.m`. In that case, typing ``help <name>`` in Matlab prints the documentation contained in this file. + ``R2017b`` or ``R2018a`` may be given to specify the version of the C API + to use: ``R2017b`` specifies the traditional (separate complex) C API, + and corresponds to the ``-R2017b`` flag for the `mex` command. ``R2018a`` + specifies the new interleaved complex C API, and corresponds to the + ``-R2018a`` flag for the `mex` command. Ignored if MATLAB version prior + to R2018a. Defaults to ``R2017b``. ``MODULE`` or ``SHARED`` may be given to specify the type of library to be created. ``EXECUTABLE`` may be given to create an executable instead of a library. If no type is given explicitly, the type is ``SHARED``. @@ -933,7 +940,7 @@ function(matlab_add_mex) endif() - set(options EXECUTABLE MODULE SHARED) + set(options EXECUTABLE MODULE SHARED R2017b R2018a) set(oneValueArgs NAME DOCUMENTATION OUTPUT_NAME) set(multiValueArgs LINK_TO SRC) @@ -948,9 +955,25 @@ function(matlab_add_mex) set(${prefix}_OUTPUT_NAME ${${prefix}_NAME}) endif() + if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file + # TODO: check the file extensions in ${${prefix}_SRC} to see if they're C or C++ files + # Currently, the C and C++ versions of the version files are identical, so this doesn't matter. + set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/c_mexapi_version.c") + #set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp") + endif() + + if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") # For 9.4 (R2018a) and newer, add API macro + if(${${prefix}_R2018a}) + set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2018a") + else() + set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2017b") + endif() + endif() + if(${prefix}_EXECUTABLE) add_executable(${${prefix}_NAME} ${${prefix}_SRC} + ${MEX_VERSION_FILE} ${${prefix}_DOCUMENTATION} ${${prefix}_UNPARSED_ARGUMENTS}) else() @@ -963,31 +986,25 @@ function(matlab_add_mex) add_library(${${prefix}_NAME} ${type} ${${prefix}_SRC} + ${MEX_VERSION_FILE} ${${prefix}_DOCUMENTATION} ${${prefix}_UNPARSED_ARGUMENTS}) endif() target_include_directories(${${prefix}_NAME} PRIVATE ${Matlab_INCLUDE_DIRS}) - if(DEFINED Matlab_MX_LIBRARY) - target_link_libraries(${${prefix}_NAME} ${Matlab_MX_LIBRARY}) - endif() - - if(DEFINED Matlab_ENGINE_LIBRARY) - target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY}) - endif() - - if(DEFINED Matlab_DATAARRAY_LIBRARY) - target_link_libraries(${${prefix}_NAME} ${Matlab_DATAARRAY_LIBRARY}) + if(Matlab_HAS_CPP_API) + target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY} ${Matlab_DATAARRAY_LIBRARY}) endif() - target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${${prefix}_LINK_TO}) + target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${${prefix}_LINK_TO}) set_target_properties(${${prefix}_NAME} PROPERTIES PREFIX "" OUTPUT_NAME ${${prefix}_OUTPUT_NAME} SUFFIX ".${Matlab_MEX_EXTENSION}") + target_compile_definitions(${${prefix}_NAME} PRIVATE ${MEX_API_MACRO} MATLAB_MEX_FILE) # documentation if(NOT ${${prefix}_DOCUMENTATION} STREQUAL "") @@ -1001,82 +1018,82 @@ function(matlab_add_mex) endif() # documentation # entry point in the mex file + taking care of visibility and symbol clashes. - if (MSVC) - get_target_property( - _previous_link_flags - ${${prefix}_NAME} - LINK_FLAGS) - if(NOT _previous_link_flags) - set(_previous_link_flags) - endif() + if(WIN32) - set_target_properties(${${prefix}_NAME} - PROPERTIES - LINK_FLAGS "${_previous_link_flags} /EXPORT:mexFunction") - endif() + if (MSVC) + + set(_link_flags "${_link_flags} /EXPORT:${mexFunction}") + if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, export version + set(_link_flags "${_link_flags} /EXPORT:${mexfilerequiredapiversion}") + endif() + + if(Matlab_HAS_CPP_API) + set(_link_flags "${_link_flags} /EXPORT:${mexCreateMexFunction} /EXPORT:${mexDestroyMexFunction} /EXPORT:${mexFunctionAdapter}") + #TODO: Is this necessary? + endif() + + set_property(TARGET ${${prefix}_NAME} APPEND PROPERTY LINK_FLAGS ${_link_flags}) + + endif() # TODO: what if there's a different compiler on Windows? - if(WIN32) set_target_properties(${${prefix}_NAME} PROPERTIES DEFINE_SYMBOL "DLL_EXPORT_SYM=__declspec(dllexport)") + else() - if(HAS_MINUS_PTHREAD AND NOT APPLE) - # Apparently, compiling with -pthread generated the proper link flags - # and some defines at compilation - target_compile_options(${${prefix}_NAME} PRIVATE "-pthread") + if(${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For versions prior to 9.1 (R2016b) + set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/mexFunction.map) + else() # For 9.1 (R2016b) and newer + set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/c_exportsmexfileversion.map) endif() + if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.5") # For 9.5 (R2018b) (and newer?) + target_compile_options(${${prefix}_NAME} PRIVATE "-fvisibility=default") + # This one is weird, it might be a bug in <mex.h> for R2018b. When compiling with + # -fvisibility=hidden, the symbol `mexFunction` cannot be exported. Reading the + # source code for <mex.h>, it seems that the preprocessor macro `MW_NEEDS_VERSION_H` + # needs to be defined for `__attribute__ ((visibility("default")))` to be added + # in front of the declaration of `mexFunction`. In previous versions of MATLAB this + # was not the case, there `DLL_EXPORT_SYM` needed to be defined. + # Adding `-fvisibility=hidden` to the `mex` command causes the build to fail. + # TODO: Check that this is still necessary in R2019a when it comes out. + endif() - # if we do not do that, the symbols linked from eg. boost remain weak and - # then clash with the ones defined in the matlab process. So by default - # the symbols are hidden. - # This also means that for shared libraries (like MEX), the entry point - # should be explicitly declared with default visibility, otherwise Matlab - # cannot find the entry point. - # Note that this is particularly meaningful if the MEX wrapper itself - # contains symbols that are clashing with Matlab (that are compiled in the - # MEX file). In order to propagate the visibility options to the libraries - # to which the MEX file is linked against, the -Wl,--exclude-libs,ALL - # option should also be specified. + if(APPLE) - set_target_properties(${${prefix}_NAME} - PROPERTIES - CXX_VISIBILITY_PRESET "hidden" - C_VISIBILITY_PRESET "hidden" - VISIBILITY_INLINES_HIDDEN ON - ) + if(Matlab_HAS_CPP_API) + list(APPEND _ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/cppMexFunction.map) # This one doesn't exist on Linux + set(_link_flags "${_link_flags} -Wl,-U,_mexCreateMexFunction -Wl,-U,_mexDestroyMexFunction -Wl,-U,_mexFunctionAdapter") + # On MacOS, the MEX command adds the above, without it the link breaks + # because we indiscriminately use "cppMexFunction.map" even for C API MEX-files. + endif() - # get_target_property( - # _previous_link_flags - # ${${prefix}_NAME} - # LINK_FLAGS) - # if(NOT _previous_link_flags) - # set(_previous_link_flags) - # endif() - - # if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - # set_target_properties(${${prefix}_NAME} - # PROPERTIES - # LINK_FLAGS "${_previous_link_flags} -Wl,--exclude-libs,ALL" - # # -Wl,--version-script=${_FindMatlab_SELF_DIR}/MatlabLinuxVisibility.map" - # ) - # elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - # # in this case, all other symbols become hidden. - # set_target_properties(${${prefix}_NAME} - # PROPERTIES - # LINK_FLAGS "${_previous_link_flags} -Wl,-exported_symbol,_mexFunction" - # #-Wl,-exported_symbols_list,${_FindMatlab_SELF_DIR}/MatlabOSXVisilibity.map" - # ) - # endif() + set(_export_flag_name -exported_symbols_list) + else() # Linux + if(HAS_MINUS_PTHREAD) + # Apparently, compiling with -pthread generated the proper link flags + # and some defines at compilation + target_compile_options(${${prefix}_NAME} PRIVATE "-pthread") + endif() + + set(_link_flags "${_link_flags} -Wl,--as-needed") + + set(_export_flag_name --version-script) + + endif() + + foreach(_file ${_ver_map_files}) + set(_link_flags "${_link_flags} -Wl,${_export_flag_name},${_file}") + endforeach() set_target_properties(${${prefix}_NAME} PROPERTIES DEFINE_SYMBOL "DLL_EXPORT_SYM=__attribute__ ((visibility (\"default\")))" - ) - + LINK_FLAGS "${_link_flags}" + ) # The `mex` command doesn't add this define. Is it necessary? endif() |