matlabcmakecmake-modules

Cmake FindMatlab does not find correct version


I am trying to setup a CMakeLists.txt under Windows to compile matlab-mex-files. But I struggle with find_package(Matlab) to select the correct version.

I am using cmake 3.26.4 under Windows 10. I have matlab versions 8.2, 9.3, 9.12, and 9.13 installed.

My CMakeLists.txt looks as follows

cmake_minimum_required(VERSION 3.26)

project(MatlabMex)

set(MATLAB_FIND_DEBUG ON)

find_package(Matlab 9.3 EXACT REQUIRED)
matlab_extract_all_installed_versions_from_registry(TRUE matlab_versions)
matlab_get_all_valid_matlab_roots_from_registry("${matlab_versions}" matlab_roots)

message("${matlab_roots}")

IF(MATLAB_FOUND)
    matlab_get_release_name_from_version(${Matlab_VERSION_STRING} Matlab_release)
    message(STATUS "Matlab found: ${Matlab_release}")
ELSE(MATLAB_FOUND)
    message("Matlab not found")
ENDIF(MATLAB_FOUND)

The debug output of FindMatlab provides:

-- [MATLAB] Matlab root folders are UNKNOWN;9.13;C:/Program Files/MATLAB/R2022b
-- [MATLAB] Current version is 9.13 located C:/Program Files/MATLAB/R2022b
-- [MATLAB] [DEBUG]_matlab_lib_prefix_for_search = lib | _matlab_lib_dir_for_search = C:/Program Files/MATLAB/R2022b/extern/lib/win64/mingw64

When using the EXACT in find_package I then get the error, that no suitable version can be found:

Could NOT find Matlab: Found unsuitable version "9.13", but required is
  exact version "9.3" (found C:/Program Files/MATLAB/R2022b/extern/include, )

However, when I omit EXACT, it selects 9.13 and runs the two macros to retrieve the information from the registry. This yields the following, which clearly includes all installed versions.

MATLAB;9.13;C:/Program Files/MATLAB/R2022b;MATLAB;9.12;C:/Program Files/MATLAB/R2022a;MATLAB;9.3;C:/Program Files/MATLAB/R2017b;MATLAB;8.2;C:/Program Files/MATLAB/R2013b

So now the question: Why does FindMatlab not find all versions in the first place and selects my desired 9.3?

I came across two issues, which seem to relate, but are solved a long time ago:

For now I consider a user error rather than a cmake issue.


Solution

  • It turned out to be a user error or at least a misunderstanding of how cmake works ;-)

    Thank you @Tsyvarev for bringing me on the right track.

    Tight Scope to original Question

    FindMatlab.cmake only searches for Matlab instances if Matlab_ROOT_DIR is not set. But cmake caches the value as it is the normal behavior of cmake (once again thanks to @Tsyvarev). So after my first tests the value for version 9.13 was in the cache and no subsequent runs of cmake performed a new search during find_package. The other calls still worked fine and thus returned the list of all installed matlab versions.

    So make sure to clear the cache for every new test.

    Extended Thoughts

    If you want to change the matlab version to compile for, the best option I found is to have a specific build directory for each matlab version.

    With a CMakeLists.txt like the following

    cmake_minimum_required(VERSION 3.26)
    
    project(MatlabMex)
    
    find_package(Matlab ${MATLAB_VERSION} EXACT REQUIRED)
    

    one could run

    cmake . -b build_2017b -DMATLAB_VERSION="9.3"
    cmake --build build_2017b
    

    or

    cmake . -b build_2022b -DMATLAB_VERSION="9.13"
    cmake --build build_2022b
    

    Using different versions in one CMakeLists.txt

    This Link suggests the usage of multiple version in the same CMakeLists.txt. But this does not seem to work, because the first call to find_package specifies Matlab_ROOT_DIRĀ“, which will make the next call not work. Even after clearing Matlab_ROOT_DIRin between, did not work for me. The correct matlab version was then found, but cmake complained about multiple targets with the same name. I have to admit that I tested without theforeach`, which might add a new scope. But this topic anyway is not really part of the original question anymore. I only wanted to include some remarks as I brought it up in the comments of the original question.