diff options
author | Brad King <brad.king@kitware.com> | 2018-10-30 14:55:43 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2018-10-30 14:55:52 (GMT) |
commit | b8f5eca5e2cff99ec0eeba645e3ccf5ac40d9825 (patch) | |
tree | f13d96cedbe5b1ed0e3d0be19737f92bbef65e62 | |
parent | 9330afea04d8e5c8f5c867af43a95fef0ad08d35 (diff) | |
parent | 42731e94bea0839842fc66cef27af71e12d753e1 (diff) | |
download | CMake-b8f5eca5e2cff99ec0eeba645e3ccf5ac40d9825.zip CMake-b8f5eca5e2cff99ec0eeba645e3ccf5ac40d9825.tar.gz CMake-b8f5eca5e2cff99ec0eeba645e3ccf5ac40d9825.tar.bz2 |
Merge topic 'FindMatlab-2018a-API'
42731e94be FindMatlab: Fix linker command under Windows.
ee73e733e4 FindMatlab: Fix compilation error in one specific test configuration.
160499296c FindMatlab: added unit tests for new functionality.
ee7e97a7d3 FindMatlab: add change log item.
d7e19032d5 FindMatlab: `matlab_add_mex` has new options `R2017b` and `R2018a`.
518553d953 FindMatlab: Always find core libraries.
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !2508
-rw-r--r-- | Help/release/dev/FindMatlab-2018a-API.rst | 7 | ||||
-rw-r--r-- | Modules/FindMatlab.cmake | 243 | ||||
-rw-r--r-- | Tests/CMakeLists.txt | 9 | ||||
-rw-r--r-- | Tests/FindMatlab/basic_checks/CMakeLists.txt | 5 | ||||
-rw-r--r-- | Tests/FindMatlab/cmake_matlab_unit_tests4.m | 28 | ||||
-rw-r--r-- | Tests/FindMatlab/cmake_matlab_unit_tests5.m | 20 | ||||
-rw-r--r-- | Tests/FindMatlab/components_checks/CMakeLists.txt | 4 | ||||
-rw-r--r-- | Tests/FindMatlab/failure_reports/CMakeLists.txt | 5 | ||||
-rw-r--r-- | Tests/FindMatlab/matlab_wrapper2.cpp | 22 | ||||
-rw-r--r-- | Tests/FindMatlab/matlab_wrapper3.cpp | 29 | ||||
-rw-r--r-- | Tests/FindMatlab/r2018a_check/CMakeLists.txt | 84 |
11 files changed, 328 insertions, 128 deletions
diff --git a/Help/release/dev/FindMatlab-2018a-API.rst b/Help/release/dev/FindMatlab-2018a-API.rst new file mode 100644 index 0000000..1063411 --- /dev/null +++ b/Help/release/dev/FindMatlab-2018a-API.rst @@ -0,0 +1,7 @@ +FindMatlab-2018a-API +-------------------- + +* The :module:`FindMatlab` module gained new options ``R2017b`` and + ``R2018a`` to specify the MEX API version to use; these options + mirror the new options to the ``mex`` command in MATLAB R2018a. + The option ``MX_LIBRARY`` is no longer needed. diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 8ba88b0..8544653 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -19,10 +19,8 @@ can also be used: The module supports the following components: -* ``MX_LIBRARY``, ``ENG_LIBRARY`` and ``MAT_LIBRARY``: respectively the ``MX``, - ``ENG`` and ``MAT`` libraries of Matlab -* ``ENGINE_LIBRARY``, ``DATAARRAY_LIBRARY``: respectively the ``MatlabEngine`` - and ``MatlabDataArray`` libraries of Matlab (Matlab 2018a and later) +* ``ENG_LIBRARY`` and ``MAT_LIBRARY``: respectively the ``ENG`` and ``MAT`` + libraries of Matlab * ``MAIN_PROGRAM`` the Matlab binary program. Note that this component is not available on the MCR version, and will yield an error if the MCR is found instead of the regular Matlab installation. @@ -101,8 +99,7 @@ Result variables ``Matlab_MEX_LIBRARY`` library for mex, always available. ``Matlab_MX_LIBRARY`` - mx library of Matlab (arrays). Available only if the component - ``MX_LIBRARY`` has been requested. + mx library of Matlab (arrays), always available. ``Matlab_ENG_LIBRARY`` Matlab engine library. Available only if the component ``ENG_LIBRARY`` is requested. @@ -110,11 +107,9 @@ Result variables Matlab matrix library. Available only if the component ``MAT_LIBRARY`` is requested. ``Matlab_ENGINE_LIBRARY`` - Matlab C++ engine library. Available only if the component ``ENGINE_LIBRARY`` - is requested. + Matlab C++ engine library, always available for R2018a and newer. ``Matlab_DATAARRAY_LIBRARY`` - Matlab C++ data array library. Available only if the component ``DATAARRAY_LIBRARY`` - is requested. + Matlab C++ data array library, always available for R2018a and newer. ``Matlab_LIBRARIES`` the whole set of libraries of Matlab ``Matlab_MEX_COMPILER`` @@ -889,6 +884,7 @@ endfunction() [OUTPUT_NAME output_name] [DOCUMENTATION file.txt] [LINK_TO target1 target2 ...] + [R2017b | R2018a] [...] ) @@ -898,8 +894,7 @@ endfunction() list of source files. ``LINK_TO`` a list of additional link dependencies. The target links to ``libmex`` - by default. If ``Matlab_MX_LIBRARY`` is defined, it also - links to ``libmx``. + and ``libmx`` by default. ``OUTPUT_NAME`` if given, overrides the default name. The default name is the name of the target without any prefix and @@ -910,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``. @@ -939,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) @@ -954,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() @@ -969,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}) + if(Matlab_HAS_CPP_API) + target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY} ${Matlab_DATAARRAY_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}) - 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 "") @@ -1007,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() @@ -1449,6 +1460,7 @@ if(DEFINED Matlab_ROOT_DIR_LAST_CACHED) if(NOT Matlab_ROOT_DIR_LAST_CACHED STREQUAL Matlab_ROOT_DIR) set(_Matlab_cached_vars + Matlab_VERSION_STRING Matlab_INCLUDE_DIRS Matlab_MEX_LIBRARY Matlab_MEX_COMPILER @@ -1466,7 +1478,7 @@ if(DEFINED Matlab_ROOT_DIR_LAST_CACHED) Matlab_MEXEXTENSIONS_PROG Matlab_ROOT_DIR_LAST_CACHED #Matlab_PROG_VERSION_STRING_AUTO_DETECT - Matlab_VERSION_STRING_INTERNAL + #Matlab_VERSION_STRING_INTERNAL ) foreach(_var IN LISTS _Matlab_cached_vars) if(DEFINED ${_var}) @@ -1491,7 +1503,9 @@ if(MATLAB_FIND_DEBUG) message(STATUS "[MATLAB] Current version is ${Matlab_VERSION_STRING} located ${Matlab_ROOT_DIR}") endif() - +if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") # MATLAB 9.4 (R2018a) and newer have a new C++ API + set(Matlab_HAS_CPP_API 1) +endif() if(Matlab_ROOT_DIR) file(TO_CMAKE_PATH ${Matlab_ROOT_DIR} Matlab_ROOT_DIR) @@ -1530,6 +1544,8 @@ set(Matlab_BINARIES_DIR ${Matlab_ROOT_DIR}/bin/${_matlab_bin_prefix}${_matlab_current_suffix}) set(Matlab_EXTERN_LIBRARY_DIR ${Matlab_ROOT_DIR}/extern/lib/${_matlab_bin_prefix}${_matlab_current_suffix}) +set(Matlab_EXTERN_BINARIES_DIR + ${Matlab_ROOT_DIR}/extern/bin/${_matlab_bin_prefix}${_matlab_current_suffix}) if(WIN32) if(MINGW) @@ -1539,7 +1555,7 @@ if(WIN32) endif() set(_matlab_lib_prefix_for_search "lib") else() - set(_matlab_lib_dir_for_search ${Matlab_BINARIES_DIR}) + set(_matlab_lib_dir_for_search ${Matlab_BINARIES_DIR} ${Matlab_EXTERN_BINARIES_DIR}) set(_matlab_lib_prefix_for_search "lib") endif() @@ -1590,7 +1606,6 @@ _Matlab_find_library( PATHS ${_matlab_lib_dir_for_search} NO_DEFAULT_PATH ) - list(APPEND _matlab_required_variables Matlab_MEX_LIBRARY) # the MEX extension is required @@ -1631,21 +1646,18 @@ if(_matlab_find_matlab_program GREATER -1) endif() unset(_matlab_find_matlab_program) -# Component MX library -list(FIND Matlab_FIND_COMPONENTS MX_LIBRARY _matlab_find_mx) -if(_matlab_find_mx GREATER -1) - _Matlab_find_library( - ${_matlab_lib_prefix_for_search} - Matlab_MX_LIBRARY - mx - PATHS ${_matlab_lib_dir_for_search} - NO_DEFAULT_PATH - ) - if(Matlab_MX_LIBRARY) - set(Matlab_MX_LIBRARY_FOUND TRUE) - endif() +# The MX library is required +_Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_MX_LIBRARY + mx + PATHS ${_matlab_lib_dir_for_search} + NO_DEFAULT_PATH +) +list(APPEND _matlab_required_variables Matlab_MX_LIBRARY) +if(Matlab_MX_LIBRARY) + set(Matlab_MX_LIBRARY_FOUND TRUE) endif() -unset(_matlab_find_mx) # Component ENG library list(FIND Matlab_FIND_COMPONENTS ENG_LIBRARY _matlab_find_eng) @@ -1711,9 +1723,9 @@ if(_matlab_find_mcc_compiler GREATER -1) endif() unset(_matlab_find_mcc_compiler) -# component MatlabEngine -list(FIND Matlab_FIND_COMPONENTS ENGINE_LIBRARY _matlab_find_matlab_engine) -if(_matlab_find_matlab_engine GREATER -1) +if(Matlab_HAS_CPP_API) + + # The MatlabEngine library is required for R2018a+ _Matlab_find_library( ${_matlab_lib_prefix_for_search} Matlab_ENGINE_LIBRARY @@ -1722,40 +1734,33 @@ if(_matlab_find_matlab_engine GREATER -1) DOC "MatlabEngine Library" NO_DEFAULT_PATH ) + list(APPEND _matlab_required_variables Matlab_ENGINE_LIBRARY) if(Matlab_ENGINE_LIBRARY) set(Matlab_ENGINE_LIBRARY_FOUND TRUE) endif() -endif() -unset(_matlab_find_matlab_engine) -# component MatlabDataArray -list(FIND Matlab_FIND_COMPONENTS DATAARRAY_LIBRARY _matlab_find_matlab_dataarray) -if(_matlab_find_matlab_dataarray GREATER -1) + # The MatlabDataArray library is required for R2018a+ _Matlab_find_library( - ${_matlab_lib_prefix_for_search} + ${_matlab_lib_prefix_for_search} Matlab_DATAARRAY_LIBRARY MatlabDataArray PATHS ${_matlab_lib_dir_for_search} DOC "MatlabDataArray Library" NO_DEFAULT_PATH ) + list(APPEND _matlab_required_variables Matlab_DATAARRAY_LIBRARY) if(Matlab_DATAARRAY_LIBRARY) set(Matlab_DATAARRAY_LIBRARY_FOUND TRUE) endif() + endif() -unset(_matlab_find_matlab_dataarray) unset(_matlab_lib_dir_for_search) -set(Matlab_LIBRARIES ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${Matlab_ENG_LIBRARY} ${Matlab_MAT_LIBRARY}) - -if(Matlab_DATAARRAY_LIBRARY_FOUND) - set(Matlab_LIBRARIES ${Matlab_LIBRARIES} ${Matlab_DATAARRAY_LIBRARY}) -endif() - -if(Matlab_ENGINE_LIBRARY_FOUND) - set(Matlab_LIBRARIES ${Matlab_LIBRARIES} ${Matlab_ENGINE_LIBRARY}) -endif() +set(Matlab_LIBRARIES + ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} + ${Matlab_ENG_LIBRARY} ${Matlab_MAT_LIBRARY} + ${Matlab_DATAARRAY_LIBRARY} ${Matlab_ENGINE_LIBRARY}) find_package_handle_standard_args( Matlab diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 71928a9..c7cfa86 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1493,13 +1493,18 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release # Matlab module # CMake_TEST_FindMatlab: indicates to look for Matlab (from PATH for Linux) + # CMake_TEST_FindMatlab_ROOT_DIR: indicates an optional root directory for Matlab, allows to select a version. # CMake_TEST_FindMatlab_MCR: indicates the MCR is installed # CMake_TEST_FindMatlab_MCR_ROOT_DIR: indicates an optional root directory for the MCR, required on Linux - if(CMake_TEST_FindMatlab OR CMake_TEST_FindMatlab_MCR OR (NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "")) + if(CMake_TEST_FindMatlab OR (NOT "${CMake_TEST_FindMatlab_ROOT_DIR}" STREQUAL "") OR + CMake_TEST_FindMatlab_MCR OR (NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "")) set(FindMatlab_additional_test_options ) if(CMake_TEST_FindMatlab_MCR OR NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "") set(FindMatlab_additional_test_options -DIS_MCR=TRUE) endif() + if(NOT "${CMake_TEST_FindMatlab_ROOT_DIR}" STREQUAL "") + set(FindMatlab_additional_test_options ${FindMatlab_additional_test_options} "-DMatlab_ROOT_DIR=${CMake_TEST_FindMatlab_ROOT_DIR}") + endif() if(NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "") set(FindMatlab_additional_test_options ${FindMatlab_additional_test_options} "-DMCR_ROOT:FILEPATH=${CMake_TEST_FindMatlab_MCR_ROOT_DIR}") endif() @@ -1511,6 +1516,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release ADD_TEST_MACRO(FindMatlab.components_checks ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) set(FindMatlab.failure_reports_BUILD_OPTIONS ${FindMatlab_additional_test_options}) ADD_TEST_MACRO(FindMatlab.failure_reports ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) + set(FindMatlab.r2018a_check_BUILD_OPTIONS ${FindMatlab_additional_test_options}) + ADD_TEST_MACRO(FindMatlab.r2018a_check ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) endif() find_package(GTK2 QUIET) diff --git a/Tests/FindMatlab/basic_checks/CMakeLists.txt b/Tests/FindMatlab/basic_checks/CMakeLists.txt index 4a74d93..c5be1ea 100644 --- a/Tests/FindMatlab/basic_checks/CMakeLists.txt +++ b/Tests/FindMatlab/basic_checks/CMakeLists.txt @@ -10,11 +10,10 @@ set(MATLAB_FIND_DEBUG TRUE) # - on 64bits builds (cmake is building with 64 bits), it looks for 64 bits Matlab if(IS_MCR) - set(components MX_LIBRARY) set(RUN_UNIT_TESTS FALSE) else() set(RUN_UNIT_TESTS TRUE) - set(components MX_LIBRARY MAIN_PROGRAM) + set(components MAIN_PROGRAM) endif() if(NOT "${MCR_ROOT}" STREQUAL "") @@ -34,7 +33,7 @@ matlab_add_mex( OUTPUT_NAME cmake_matlab_mex1 SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper1.cpp DOCUMENTATION ${CMAKE_CURRENT_SOURCE_DIR}/../help_text1.m.txt - ) + ) if(RUN_UNIT_TESTS) matlab_add_unit_test( diff --git a/Tests/FindMatlab/cmake_matlab_unit_tests4.m b/Tests/FindMatlab/cmake_matlab_unit_tests4.m new file mode 100644 index 0000000..6a7b04d --- /dev/null +++ b/Tests/FindMatlab/cmake_matlab_unit_tests4.m @@ -0,0 +1,28 @@ + +classdef cmake_matlab_unit_tests4 < matlab.unittest.TestCase + % Testing R2017b and R2018a APIs + properties + end + + methods (Test) + function testR2017b(testCase) + ret = cmake_matlab_mex2a(5+6i); + testCase.verifyEqual(ret, 8); + end + + function testR2018a(testCase) + ret = cmake_matlab_mex2b(5+6i); + v = version; + n = find(v=='.'); + v = str2double(v(1:n(2)-1)); + disp(v) + if v>= 9.4 % R2018a + testCase.verifyEqual(ret, 16); + disp('TESTING version >= 9.4') + else + testCase.verifyEqual(ret, 8); + end + end + + end +end diff --git a/Tests/FindMatlab/cmake_matlab_unit_tests5.m b/Tests/FindMatlab/cmake_matlab_unit_tests5.m new file mode 100644 index 0000000..b1936e3 --- /dev/null +++ b/Tests/FindMatlab/cmake_matlab_unit_tests5.m @@ -0,0 +1,20 @@ + +classdef cmake_matlab_unit_tests5 < matlab.unittest.TestCase + % C++ API test + properties + end + + methods (Test) + function testDummyCall(testCase) + % very simple call test + disp('TESTING C++') + ret = cmake_matlab_mex3(162); + testCase.verifyEqual(ret, 162); + end + + function testFailTest(testCase) + testCase.verifyError(@() cmake_matlab_mex3, 'MATLAB:mex:CppMexException'); + end + + end +end diff --git a/Tests/FindMatlab/components_checks/CMakeLists.txt b/Tests/FindMatlab/components_checks/CMakeLists.txt index da6a2b0..f5d4880 100644 --- a/Tests/FindMatlab/components_checks/CMakeLists.txt +++ b/Tests/FindMatlab/components_checks/CMakeLists.txt @@ -15,7 +15,7 @@ endif() # the success of the following command is dependent on the current configuration: # - on 32bits builds (cmake is building with 32 bits), it looks for 32 bits Matlab # - on 64bits builds (cmake is building with 64 bits), it looks for 64 bits Matlab -find_package(Matlab REQUIRED COMPONENTS MX_LIBRARY ENG_LIBRARY MAT_LIBRARY +find_package(Matlab REQUIRED COMPONENTS ENG_LIBRARY MAT_LIBRARY OPTIONAL_COMPONENTS MAIN_PROGRAM) message(STATUS "FindMatlab libraries: ${Matlab_LIBRARIES}") @@ -28,4 +28,4 @@ matlab_add_mex( SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper1.cpp DOCUMENTATION ${CMAKE_CURRENT_SOURCE_DIR}/../help_text1.m.txt LINK_TO ${Matlab_LIBRARIES} - ) + ) diff --git a/Tests/FindMatlab/failure_reports/CMakeLists.txt b/Tests/FindMatlab/failure_reports/CMakeLists.txt index e597a4a..4b092cd 100644 --- a/Tests/FindMatlab/failure_reports/CMakeLists.txt +++ b/Tests/FindMatlab/failure_reports/CMakeLists.txt @@ -8,11 +8,10 @@ project(failure_reports) set(MATLAB_FIND_DEBUG TRUE) if(IS_MCR) - set(components MX_LIBRARY) set(RUN_UNIT_TESTS FALSE) else() set(RUN_UNIT_TESTS TRUE) - set(components MX_LIBRARY MAIN_PROGRAM) + set(components MAIN_PROGRAM) endif() if(NOT "${MCR_ROOT}" STREQUAL "") @@ -32,7 +31,7 @@ matlab_add_mex( OUTPUT_NAME cmake_matlab_mex1 SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper1.cpp DOCUMENTATION ${CMAKE_CURRENT_SOURCE_DIR}/../help_text1.m.txt - ) + ) if(RUN_UNIT_TESTS) # the unit test file does not exist: the failure should be properly reported diff --git a/Tests/FindMatlab/matlab_wrapper2.cpp b/Tests/FindMatlab/matlab_wrapper2.cpp new file mode 100644 index 0000000..e768fbf --- /dev/null +++ b/Tests/FindMatlab/matlab_wrapper2.cpp @@ -0,0 +1,22 @@ + +// simple workaround to some compiler specific problems +// see +// http://stackoverflow.com/questions/22367516/mex-compile-error-unknown-type-name-char16-t/23281916#23281916 +#include <algorithm> + +#include "mex.h" + +// This test uses the new complex-interleaved C API (R2018a and newer) + +// The input should be a complex array (scalar is OK). It returns the number of +// bytes in a matrix element. For the old (R2017b) API, this is 8. For the new +// (R2018a) API, this is 16. + +void mexFunction(const int nlhs, mxArray* plhs[], const int nrhs, + const mxArray* prhs[]) +{ + if (nrhs != 1 || !mxIsComplex(prhs[0])) { + mexErrMsgTxt("Incorrect arguments"); + } + plhs[0] = mxCreateDoubleScalar(mxGetElementSize(prhs[0])); +} diff --git a/Tests/FindMatlab/matlab_wrapper3.cpp b/Tests/FindMatlab/matlab_wrapper3.cpp new file mode 100644 index 0000000..6670815 --- /dev/null +++ b/Tests/FindMatlab/matlab_wrapper3.cpp @@ -0,0 +1,29 @@ +#include "mex.hpp" +#include "mexAdapter.hpp" + +// This test uses the new C++ API (R2018a and newer) + +// The input should be a scalar double array. The output is a copy of that +// array. + +using namespace matlab::data; +using matlab::mex::ArgumentList; + +class MexFunction : public matlab::mex::Function +{ +public: + void operator()(ArgumentList outputs, ArgumentList inputs) + { + std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine(); + ArrayFactory factory; + if (inputs[0].getType() != ArrayType::DOUBLE || + inputs[0].getType() == ArrayType::COMPLEX_DOUBLE || + inputs[0].getNumberOfElements() != 1) { + matlabPtr->feval( + u"error", 0, + std::vector<Array>({ factory.createScalar("Incorrect arguments") })); + } + double a = inputs[0][0]; + outputs[0] = factory.createScalar(a); + } +}; diff --git a/Tests/FindMatlab/r2018a_check/CMakeLists.txt b/Tests/FindMatlab/r2018a_check/CMakeLists.txt new file mode 100644 index 0000000..c732be1 --- /dev/null +++ b/Tests/FindMatlab/r2018a_check/CMakeLists.txt @@ -0,0 +1,84 @@ + +cmake_minimum_required (VERSION 2.8.12) +enable_testing() +project(r2018a_checks) + +set(MATLAB_FIND_DEBUG TRUE) + +# this test doesn't do much if MATLAB version < R2018a + +if(IS_MCR) + set(RUN_UNIT_TESTS FALSE) +else() + set(RUN_UNIT_TESTS TRUE) + set(components MAIN_PROGRAM) +endif() + +if(NOT "${MCR_ROOT}" STREQUAL "") + set(Matlab_ROOT_DIR "${MCR_ROOT}") + if(NOT EXISTS "${MCR_ROOT}") + message(FATAL_ERROR "MCR does not exist ${MCR_ROOT}") + endif() +endif() + +find_package(Matlab REQUIRED COMPONENTS ${components}) + +set(IS_R2018a 1) +if(${Matlab_VERSION_STRING} VERSION_LESS "9.4") + # This is an older version of MATLAB, tests will fail + set(IS_R2018a 0) +endif() + +matlab_add_mex( + # target name + NAME cmake_matlab_test_wrapper2a + # output name + OUTPUT_NAME cmake_matlab_mex2a + SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper2.cpp + R2017b + ) + +matlab_add_mex( + # target name + NAME cmake_matlab_test_wrapper2b + # output name + OUTPUT_NAME cmake_matlab_mex2b + SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper2.cpp + R2018a + ) + +if(IS_R2018a) + matlab_add_mex( + # target name + NAME cmake_matlab_test_wrapper3 + # output name + OUTPUT_NAME cmake_matlab_mex3 + SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper3.cpp + ) + set_target_properties( + cmake_matlab_test_wrapper3 + PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON + ) +endif() + +if(RUN_UNIT_TESTS) + # Check that the R2017b and R2018a APIs work. + matlab_add_unit_test( + NAME ${PROJECT_NAME}_matlabtest-1 + TIMEOUT 300 + UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests4.m + ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper2a> + ) + + # Check that the C++ API works (test run only on R2018a and newer) + if(IS_R2018a) + matlab_add_unit_test( + NAME ${PROJECT_NAME}_matlabtest-3 + TIMEOUT 300 + UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests5.m + ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper3> + ) + endif() +endif() |