2

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.

Gunter
  • 321
  • 4
  • 13
  • As far as I understand code of [FindMatlab.cmake](https://github.com/Kitware/CMake/blob/master/Modules/FindMatlab.cmake), it is able to select Matlab installations according to version only if this version is listed in the output titled with `Matlab root folders are`. Not sure why it doesn't output other Matlab installations in that list, but for other installations version selection mechanism doesn't work. – Tsyvarev Jul 12 '23 at 13:07
  • 1
    I think you brought me on the right track. It seems that FindMatlab does no searching anymore, because the variable `Matlab_ROOT_DIR` is already set. It is even set before the call to `find_package`, which indicates, that it is retrieved from `CMakeCache.txt`. So after deleting `CMakeCache.txt` or the entry in it, I get the full list of matlab installations and the correct one is chosen. It is still annoying, though. – Gunter Jul 13 '23 at 10:12
  • because of this mechanism, the functionality given [here](https://www.scivision.dev/matlab-version-cmake/) also does not work – Gunter Jul 13 '23 at 11:20
  • 1
    Actually, `find_package` caches its results. With almost any package, if you successfully found some installation, then you need to remove cached value (or remove the whole cache) before being able to search other installation. In that sense, Matlab is not an exception. – Tsyvarev Jul 13 '23 at 12:58
  • So it's an user error after all ;-) – Gunter Jul 13 '23 at 13:00
  • Yes, forgetting to remove the cache before attempt to search **another** installation of the package is a user problem. But if the search works in unexpected way with the clean cache, then the problem is in the package search script. – Tsyvarev Jul 13 '23 at 13:05

1 Answers1

2

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.

Gunter
  • 321
  • 4
  • 13