FindMatlab

查找 Matlab 或 Matlab 编译器运行时 (MCR) 并为 CMake 提供 Matlab 工具、库和编译器。

find_package(Matlab [<version>] [COMPONENTS <components>...] [...])

此包的主要目的是查找与 Matlab 或 MCR 相关的库,以便能够构建 Matlab 扩展(mex 文件)。它还可以用于

  • 在 Matlab 可用时在 Matlab 中运行特定命令。

  • 声明 Matlab 单元测试。

  • 从 Matlab(mex 扩展、版本和发行查询等)检索各种信息。

版本 3.12 中添加: 添加了 Matlab 编译器运行时 (MCR) 支持。

模块支持以下组件:

  • ENG_LIBRARYMAT_LIBRARY:分别为 Matlab 的 ENGMAT 库。

  • MAIN_PROGRAM:Matlab 二进制程序。请注意,此组件在 MCR 版本中不可用,如果找到 MCR 而非常规 Matlab 安装,则会产生错误。

  • MEX_COMPILER:MEX 编译器。

  • MCC_COMPILER:MCC 编译器,包含在 Matlab 编译器附加组件中。

  • SIMULINK:Simulink 环境。

版本 3.7 中添加: 添加了 MAT_LIBRARY 组件。

版本 3.13 中添加: 添加了 ENGINE_LIBRARYDATAARRAY_LIBRARYMCC_COMPILER 组件。

版本 3.14 中更改: 删除了 MX_LIBRARYENGINE_LIBRARYDATAARRAY_LIBRARY 组件。这些库是无条件找到的。

版本 3.30 中添加: find_package() 添加了指定版本范围的支持,并为 find_package()matlab_extract_all_installed_versions_from_registry()matlab_get_all_valid_matlab_roots_from_registry() 添加了指定 REGISTRY_VIEW 的支持。默认行为保持不变,使用注册表视图 TARGET

注意

提供给 find_package() 指令的版本是 Matlab 的**版本**,不应与 Matlab 的发行版名称(例如 R2023b)混淆。matlab_get_version_from_release_name()matlab_get_release_name_from_version() 提供了发行版名称和版本之间的映射。

变量 Matlab_ROOT_DIR 可以被指定,以提供所需 Matlab 版本的路径。否则,行为是平台特定的。

  • Windows:已安装的 Matlab/MCR 版本从 Windows 注册表中检索。REGISTRY_VIEW 参数可选择指定,以手动控制是搜索 32 位还是 64 位版本。

  • macOS:已安装的 Matlab/MCR 版本由 $HOME/Applications/Applications 下的 MATLAB 默认安装路径给出。如果找不到此类应用程序,则回退到可能从 PATH 访问的应用程序。

  • Unix:所需的 Matlab 应可从 PATH 访问。这对 MCR 安装无效,在此平台上应指定 Matlab_ROOT_DIR

当设置 MATLAB_FIND_DEBUG 时,将提供额外信息。当自动找到 Matlab/MCR 安装且未给出 MATLAB_VERSION 时,版本将直接从 Matlab(在 Windows 上这可能会弹出 Matlab 窗口)或从 MCR 安装中查询。

Matlab 的发行版名称和版本的映射是通过定义(名称,版本)对来实现的。变量 MATLAB_ADDITIONAL_VERSIONS 可以在调用 find_package() 之前提供,以处理其他版本。

可以使用 matlab_add_unit_test() 将 Matlab 脚本添加到测试集中。默认情况下,将使用 Matlab 单元测试框架(>= 2013a)来运行此脚本,但也可以使用常规的返回退出码的 .m 文件(0 表示成功)。

模块输入变量

用户或项目可以设置以下变量来配置模块行为。

Matlab_ROOT

在 3.25 版本中新增。

Matlab 安装根目录的默认值,即 Matlab_ROOT_DIR

Matlab_ROOT_DIR

Matlab 安装的根目录。

MATLAB_FIND_DEBUG

输出调试信息。

MATLAB_ADDITIONAL_VERSIONS

用于自动检索已安装版本的 Matlab 的其他版本。

导入的目标

3.22 版本新增。

此模块定义了以下IMPORTED 目标:

Matlab::mex

MEX 库,对于 MATLAB 安装始终可用。如果 MCR 提供,则对于 MCR 安装也可用。

Matlab::mx

Matlab 的 mx 库(数组),对于 MATLAB 安装始终可用。如果 MCR 提供,则对于 MCR 安装也可用。

Matlab::eng

Matlab 引擎库。仅当请求 ENG_LIBRARY 组件时可用。

Matlab::mat

Matlab 矩阵库。仅当请求 MAT_LIBRARY 组件时可用。

Matlab::MatlabEngine

Matlab C++ 引擎库,对于 MATLAB R2018a 及更高版本始终可用。如果 MCR 提供,则对于 MCR 安装也可用。

Matlab::MatlabDataArray

Matlab C++ 数据数组库,对于 MATLAB R2018a 及更高版本始终可用。如果 MCR 提供,则对于 MCR 安装也可用。

模块定义的变量

结果变量

Matlab_FOUND

3.3 版本中新增。

一个布尔值,指示是否找到了(请求版本的)Matlab 安装。以下所有变量都在找到 Matlab 时定义。

Matlab_VERSION

在 3.27 版本中新增。

找到的 Matlab 的数值版本(例如 23.2.0)。不应与 Matlab 发行版名称(例如 R2023b)混淆,后者可以通过 matlab_get_release_name_from_version() 获取。

Matlab_ROOT_DIR

FindMatlab 模块确定的 Matlab 安装的最终根目录。

Matlab_MAIN_PROGRAM

Matlab 二进制程序。仅当在 find_package() 指令中指定了 MAIN_PROGRAM 组件时可用。

Matlab_INCLUDE_DIRS

Matlab 库头文件的路径。

Matlab_MEX_LIBRARY

mex 库,对于 MATLAB 安装始终可用。如果 MCR 提供,则对于 MCR 安装也可用。

Matlab_MX_LIBRARY

Matlab 的 mx 库(数组),对于 MATLAB 安装始终可用。如果 MCR 提供,则对于 MCR 安装也可用。

Matlab_ENG_LIBRARY

Matlab 引擎库。仅当请求 ENG_LIBRARY 组件时可用。

Matlab_MAT_LIBRARY

Matlab 矩阵库。仅当请求 MAT_LIBRARY 组件时可用。

Matlab_ENGINE_LIBRARY

3.13 版本新增。

Matlab C++ 引擎库,对于 MATLAB R2018a 及更高版本始终可用。如果 MCR 提供,则对于 MCR 安装也可用。

Matlab_DATAARRAY_LIBRARY

3.13 版本新增。

Matlab C++ 数据数组库,对于 MATLAB R2018a 及更高版本始终可用。如果 MCR 提供,则对于 MCR 安装也可用。

Matlab_LIBRARIES

Matlab 的全部库集合。

Matlab_MEX_COMPILER

Matlab 的 mex 编译器。目前未使用。仅当请求 MEX_COMPILER 组件时可用。

Matlab_MCC_COMPILER

3.13 版本新增。

Matlab 的 mcc 编译器。包含在 Matlab 编译器附加组件中。仅当请求 MCC_COMPILER 组件时可用。

缓存变量

Matlab_MEX_EXTENSION

当前平台(由 Matlab 提供)的 mex 文件的扩展名。

Matlab_ROOT_DIR

找到的 Matlab 安装根目录的位置。如果用户更改此值,结果变量将被重新计算。

提供的命令

matlab_get_version_from_release_name()

从 Matlab 发行版名称返回版本。

matlab_get_release_name_from_version()

从 Matlab 版本返回发行版名称。

matlab_add_mex()

添加一个编译 MEX 文件的目标。

matlab_add_unit_test()

将 Matlab 单元测试文件添加为项目的测试。

matlab_extract_all_installed_versions_from_registry()

解析注册表以获取所有 Matlab 版本。仅在 Windows 上可用。解析的注册表部分取决于主机处理器。

matlab_get_all_valid_matlab_roots_from_registry()

根据先前给定的列表,返回所有可能的 Matlab 或 MCR 路径。仅保留存在的/可访问的路径。这主要用于搜索所有可能的 Matlab 安装。

matlab_get_mex_suffix()

返回 mex 文件的后缀(平台/架构相关)。

matlab_get_version_from_matlab_run()

给定 Matlab/MCR 安装路径的完整目录,返回 Matlab/MCR 的版本。

已知问题

MEX 目标中的符号冲突

默认情况下,使用 matlab_add_mex() 命令定义的 MEX 文件中的所有符号都具有隐藏可见性,入口点除外。这是 MEX 编译器的默认行为,可以降低 Matlab 附带库与 MEX 文件链接到的库之间符号冲突的风险。在 Windows 平台上也是如此。

但是,在某些情况下,例如您的 MEX 文件链接的库已经由 Matlab 加载,即使这些库具有不同的 SONAME,这也不够。一种可能的解决方案是隐藏 MEX 目标链接到的库的符号。在 GNU GCC 编译器中,可以使用链接器选项 -Wl,--exclude-libs,ALL 来实现。

使用 GPU 资源的测试

如果您的 MEX 文件使用 GPU 并且能够在此 MEX 文件上运行单元测试,则应由 Matlab 正确释放 GPU 资源。一种可能的解决方案是使 Matlab 了解会话中 GPU 资源的使用情况,这可以通过在测试脚本(或通过夹具)开头执行类似 D = gpuDevice() 的命令来完成。

参考

Matlab_ROOT_DIR

Matlab 安装的根文件夹。如果在此调用 find_package() 之前设置,模块将在该路径中查找组件。如果未设置,则将执行自动搜索 Matlab。如果设置了,它应指向一个有效的 Matlab 版本。

MATLAB_FIND_DEBUG

如果设置,则 Matlab 的查找和中间配置步骤将被输出到控制台。

MATLAB_ADDITIONAL_VERSIONS

如果设置,则指定可能要查找的其他 Matlab 版本。该变量应为一个字符串列表,按发行版名称和版本对进行组织,如下所示:

set(MATLAB_ADDITIONAL_VERSIONS
    "release_name1=corresponding_version1"
    "release_name2=corresponding_version2"
    ...
    )

示例

set(MATLAB_ADDITIONAL_VERSIONS
    "R2013b=8.2"
    "R2013a=8.1"
    "R2012b=8.0")

当安装了多个 Matlab 版本时,此列表中的条目顺序很重要。优先级根据此列表中的顺序设置。

matlab_get_version_from_release_name
matlab_get_version_from_release_name(release version)
  • 输入:release 是发行版名称(例如 R2023b)。

  • 输出:version 是 Matlab 的版本(例如 23.2.0)。

从发行版名称返回 Matlab 的版本。

注意

此命令提供 Matlab 的正确版本映射,但不提供 MCR 的。

matlab_get_release_name_from_version
matlab_get_release_name_from_version(version release_name)
  • 输入:version 是 Matlab 的版本(例如 23.2.0)。

  • 输出:release_name 是发行版名称(R2023b)。

从 Matlab 版本返回发行版名称。

注意

此命令提供 Matlab 的正确版本映射,但不提供 MCR 的。

matlab_extract_all_installed_versions_from_registry

此函数解析 Windows 注册表并查找已安装的 Matlab 版本。找到的版本存储在给定的 <versions-var> 中。

matlab_extract_all_installed_versions_from_registry(<versions-var> [REGISTRY_VIEW view])

3.30 版本新增。

  • 输出:<versions-var> 是找到的所有 Matlab 版本的列表。

  • 输入:REGISTRY_VIEW 可选注册表视图,用于与注册表交互。参数将传递(或省略)给 cmake_host_system_information(),不经进一步检查或修改。

matlab_extract_all_installed_versions_from_registry(<win64> <versions-var>)
  • 输入:win64 是一个布尔值,用于搜索 64 位版本的 Matlab。设置为 ON 使用 64 位注册表视图,或设置为 OFF 使用 32 位注册表视图。如果需要更精细控制,请参阅上面的签名。

  • 输出:<versions-var> 是找到的所有 Matlab 版本的列表。

返回的列表包含 HKLM\SOFTWARE\Mathworks\MATLABHKLM\SOFTWARE\Mathworks\MATLAB RuntimeHKLM\SOFTWARE\Mathworks\MATLAB Compiler Runtime 下的所有版本,如果发生错误(或未找到任何内容),则返回空列表。

注意

仅提供版本。不检查注册表中引用的安装是否存在。

matlab_get_all_valid_matlab_roots_from_registry

使用有效的 Matlab 或 Matlab 运行时 (MCR) 版本填充 Matlab 根目录。返回的 matlab_roots 按三元组组织:(type,version_number,matlab_root_path),其中 type 表示 MATLABMCR

matlab_get_all_valid_matlab_roots_from_registry(matlab_versions matlab_roots [REGISTRY_VIEW view])
  • 输入:matlab_versions:Matlab 或 MCR 安装的每个版本。

  • 输出:matlab_roots:Matlab 或 MCR 安装的每个位置。

  • 输入:REGISTRY_VIEW 可选注册表视图,用于与注册表交互。参数将传递(或省略)给 cmake_host_system_information(),不经进一步检查或修改。

版本 3.30 中添加: 添加了可选的 REGISTRY_VIEW 参数,以提供更精确的接口来与 Windows 注册表交互。

matlab_get_mex_suffix

返回 mex 文件的扩展名(后缀)。此函数不应在找到相应的 Matlab 根目录之前调用。

matlab_get_mex_suffix(matlab_root mex_suffix)
  • 输入:matlab_root:Matlab/MCR 安装的根目录,例如 Matlab_ROOT_DIR

  • 输出:mex_suffix:后缀将返回到的变量名。

matlab_get_version_from_matlab_run

此函数运行参数中指定的 Matlab 程序并提取其版本。如果提供的 Matlab 安装路径指向 MCR 安装,则版本将从已安装的文件中提取。

matlab_get_version_from_matlab_run(matlab_binary_path matlab_list_versions)
  • 输入:matlab_binary_pathmatlab 二进制可执行文件的路径。

  • 输出:matlab_list_versions:从 Matlab 提取的版本。

matlab_add_unit_test

将 Matlab 单元测试添加到 cmake/ctest 的测试集中。此命令需要 MAIN_PROGRAM 组件,因此对于 MCR 安装不可用。

单元测试使用 Matlab 单元测试框架(默认,从 Matlab 2013b+ 开始可用),除非提供了 NO_UNITTEST_FRAMEWORK 选项。

该函数期望提供一个 Matlab 测试脚本文件。在提供 NO_UNITTEST_FRAMEWORK 的情况下,单元测试脚本文件应包含要运行的脚本,加上一个带退出值的 exit 命令。此退出值将传递给 ctest 框架(0 表示成功,非 0 表示失败)。可以通过 TEST_ARGS 传递 add_test() 接受的附加参数(例如 CONFIGURATION <config> ...)。

matlab_add_unit_test(
    NAME <name>
    UNITTEST_FILE matlab_file_containing_unittest.m
    [CUSTOM_TEST_COMMAND matlab_command_to_run_as_test]
    [UNITTEST_PRECOMMAND matlab_command_to_run]
    [TIMEOUT timeout]
    [ADDITIONAL_PATH path1 [path2 ...]]
    [MATLAB_ADDITIONAL_STARTUP_OPTIONS option1 [option2 ...]]
    [TEST_ARGS arg1 [arg2 ...]]
    [NO_UNITTEST_FRAMEWORK]
    )

函数参数

名称

ctest 中单元测试的名称。

UNITTEST_FILE

matlab 单元测试文件。其路径将自动添加到 Matlab 路径中。

CUSTOM_TEST_COMMAND

要作为测试运行的 Matlab 脚本命令。如果未设置此项,则运行:runtests('matlab_file_name'), exit(max([ans(1,:).Failed])),其中 matlab_file_nameUNITTEST_FILE 去掉扩展名后的名称。

UNITTEST_PRECOMMAND

在包含测试的文件之前运行的 Matlab 脚本命令(例如,基于 CMake 变量的 GPU 设备初始化)。

TIMEOUT

测试超时(以秒为单位)。默认为 180 秒,因为 Matlab 单元测试可能会挂起。

ADDITIONAL_PATH

在运行单元测试之前添加到 Matlab 路径的路径列表。

MATLAB_ADDITIONAL_STARTUP_OPTIONS

用于从命令行运行 Matlab 的附加选项列表。-nosplash -nodesktop -nodisplay 始终添加。

TEST_ARGS

提供给 add_test 命令的附加选项。这些选项会添加到默认选项(例如,“CONFIGURATIONS Release”)中。

NO_UNITTEST_FRAMEWORK

如果设置,则表示测试不应使用 Matlab 的单元测试框架(适用于版本 >= R2013a)。

WORKING_DIRECTORY

这将是测试的工作目录。如果指定,它也将用作测试运行日志文件的输出目录。如果未指定,将使用临时目录 ${CMAKE_BINARY_DIR}/Matlab 作为工作目录和日志位置。

matlab_add_mex

添加 Matlab MEX 目标。此命令使用当前工具链编译给定的源文件,以生成 MEX 文件。可以指定生成的输出的最终名称,以及其他链接库,以及 MEX 文件的文档条目。调用中的其余参数将传递给 add_library()add_executable() 命令。

matlab_add_mex(
    NAME <name>
    [EXECUTABLE | MODULE | SHARED]
    SRC src1 [src2 ...]
    [OUTPUT_NAME output_name]
    [DOCUMENTATION file.txt]
    [LINK_TO target1 target2 ...]
    [R2017b | R2018a]
    [EXCLUDE_FROM_ALL]
    [NO_IMPLICIT_LINK_TO_MATLAB_LIBRARIES]
    [...]
)

函数参数

名称

目标的名称。

SRC

源文件列表。

LINK_TO

附加链接依赖项列表。目标默认链接到 libmexlibmx,除非传递了 NO_IMPLICIT_LINK_TO_MATLAB_LIBRARIES 选项。

OUTPUT_NAME

如果给定,则覆盖默认名称。默认名称是目标名称,不带任何前缀,并带有 Matlab_MEX_EXTENSION 后缀。

DOCUMENTATION

如果给定,文件 file.txt 将被视为 MEX 文件的文档文件。此文件将被复制到同一文件夹中,无需任何处理,名称与最终 mex 文件相同,扩展名为 .m。在这种情况下,在 Matlab 中键入 help <name> 将打印此文件中的文档。

R2017bR2018a

3.14 版新增。

可用于指定 C API 的版本:R2017b 指定传统的(分离复数)C API,对应于 mex 命令的 -R2017b 标志。R2018a 指定新的交错复数 C API,对应于 mex 命令的 -R2018a 标志。如果 MATLAB 版本早于 R2018a,则忽略。默认为 R2017b

MODULESHARED

3.7 版本中新增。

可用于指定要创建的库的类型。

EXECUTABLE

3.7 版本中新增。

可用于创建可执行文件而不是库。如果未明确指定类型,则类型为 SHARED

EXCLUDE_FROM_ALL

此选项的含义与 EXCLUDE_FROM_ALL 相同,并且会转发给 add_library()add_executable() 命令。

NO_IMPLICIT_LINK_TO_MATLAB_LIBRARIES

在 3.24 版本中添加。

此选项允许禁用对 MATLAB 库的自动链接,以便仅通过 LINK_TO 选项链接实际需要的库。

文档文件未经处理,应采用以下格式:

% This is the documentation
function ret = mex_target_output_name(input1)