上个月帮一位做工业检测的朋友解决了个挺实际的问题:他开发了一套基于 MATLAB 的图像识别算法,算法本身不复杂,但真正让他头疼的是交付环节。现场工程师的电脑上既没有 MATLAB,也不可能因为一个工具脚本去配正版授权和工具箱。折腾到最后,方案落在了 MATLAB Compiler 上,把写好的函数直接打包成独立可执行文件,目标机器只需要装一个 MATLAB Runtime 就能跑。整个过程里踩了不少坑,也总结出一些常规文档里不细说的经验。今天就把这套“正常用 MATLAB Compiler / Application Compiler / mcc 打包独立应用程序”的完整链路梳理一遍,从原理、准备、实操到排查,尽量一次讲透。
这篇文章适合所有要把 MATLAB 代码交付给他人的开发者,不管你是给学生做毕设工具,还是给公司做内部数据处理程序,或者要给客户交付商业算法模块,思路基本一致。读完你不仅能独立完成打包,还能知道打包后文件为什么会运行失败、怎么排查,以及如何避免那些最隐蔽的坑。
1. 为什么要用 MATLAB Compiler 打包独立应用
1.1 没有 MATLAB 环境也能运行,这是最核心的诉求
在没有安装 MATLAB 的机器上,.m 文件是无法直接运行的,这是 MATLAB 这个封闭生态最让人头疼的一点。别人接手你的脚本后,第一件事往往是装一套完整的 MATLAB 环境,然后还要配好路径、装好工具箱、处理版本兼容问题,非常痛苦。
MATLAB Compiler 解决的就是这个问题。它并不是把 MATLAB 程序“翻译”成 C 语言或者机器码,而是把 .m 函数连同其依赖的 MATLAB 运行库一起,打包成一个可在目标平台运行的独立应用程序。这个独立应用运行时,依赖的是一个叫 MATLAB Runtime 的运行环境,你可以把它理解成“精简版 MATLAB 运行时”,免费、可随你的应用一起分发,而且不需要再装完整版 MATLAB。
这里说的“独立”,指的是不再依赖完整 MATLAB 开发环境,而不是指完全不依赖任何外部文件。打包产物在目标机器上运行,仍然需要先安装对应版本的 MATLAB Runtime,只不过对最终用户来说,它只是安装一个运行库,远比安装 MATLAB + 配置路径来得简单。
1.2 不只是 exe:Compiler 还能产出哪些交付形态
很多人一提 MATLAB Compiler,第一反应就是“打包成 exe”。实际上,它能产出好几种交付形态,不同形态对应不同使用场景:
| 交付形态 | 常见产物 | 适用场景 |
|---|---|---|
| 独立应用程序(Standalone Application) | .exe / Linux 可执行文件 | 目标机器无 MATLAB,直接双击或命令行调用 |
| 共享库(Shared Library) | C/C++ DLL、.NET DLL、Java Jar、Python 包 | 在其他语言开发的系统里调用 MATLAB 算法 |
| Excel 加载项 | Excel 插件 | 在 Excel 里直接调用 MATLAB 函数 |
| Hadoop/Spark 组件 | 大数据平台算法模块 | 部署到 Hadoop/Spark 集群 |
比如你有一个矩阵分解算法,不想重写成 Python,又希望 Python 主程序能调用它,那就用mcc -W python:myPkg打成一个 Python 包,然后在 Python 里正常import。这一点在下文会专门演示。很多团队实际落地时并不需要 exe,而是把 MATLAB 算法封装成动态库,嵌入现有系统里,这种方法对系统集成更友好。
1.3 哪些人需要特别注意打包这件事
我接触过的情况里,最需要打包能力的是这几类同学:
第一类是算法工程师和科研人员,写好了算法,要给团队或客户验证效果,不可能让每个人装全套 MATLAB。第二类是桌面应用开发者,用 MATLAB App Designer 做了界面,想以独立程序方式交付,这就是 Application Compiler 最典型的使用场景。第三类是系统集成工程师,需要把 MATLAB 算法嵌入到 Python、Java、C# 写的业务系统里。
如果你只是自己在本地跑跑脚本,不涉及交付,那并不需要打包;但只要你开始考虑“别人怎么用我的代码”这个问题,Compiler 就会成为最高频的工具之一。
2. 打包之前,先把代码做一次全面“体检”
很多人在打包阶段遇到的问题,其实根源不在打包工具本身,而是代码本身的“体质”不适合编译。MATLAB Compiler 对代码有一定的要求,在点击 Package 之前,先按下面四步过一遍,能省掉后面大量的排查时间。
2.1 入口必须是函数,不能是脚本
打包的第一原则:你的主程序必须是一个函数,而不是脚本。MATLAB 脚本是一行行顺序执行的命令,在解释器环境下没问题,但 Compiler 需要一个明确的函数入口来生成 main 函数。
比如最简单的入口函数长这样:
function myApp(varargin) % 程序入口 fprintf('Hello from compiled app\n'); end如果暂时还没有函数化,需要把脚本改造成函数格式。改造时有一个常用的技巧:脚本里引用了工作区变量,改造后这些变量会成为局部变量,所以在函数开头要检查变量是否存在。如果你原来的脚本依赖 base 工作区的变量,编译后这些变量不会自动存在,这里很容易出错。
另外,入口函数最好支持varargin,这样生成的可执行文件才能接收外部传入的命令行参数。function main(varargin)是所有 Standalone App 的标准入口写法。
2.2 资源文件要统一管理,数据文件别裸奔
打包时最隐蔽的坑之一就是附加资源文件。如果你的程序要读取 data.csv、模型文件、配置文件等,请提前把所有这些资源放到同一个目录下,并统一管理。打包时要把这些文件用-a参数或图形界面的“加附加文件”方式一起打进去,否则运行时会找不到。
还有一点需要注意的细节是路径别写死。很多人习惯写data = load('C:\myproject\data\data.csv'),这个写法在本地开发没问题,但打包后的程序运行在目标机器上,那个绝对路径根本不存在,程序必然报错。
另一个容易被忽略的问题:打包后,附加文件会被释放到一个由系统管理的临时目录中,这个目录和 exe 所在目录并不一定相同。直接用相对路径'data.csv'取数据,会以当前工作目录为基准寻找,而目标机器上的工作目录是不可控的,因此同样是隐患。
正确的做法是使用ctfroot函数来定位资源文件的实际位置:
function main(varargin) % 获取打包后附加资源的实际释放根目录 resourceDir = ctfroot; dataFile = fullfile(resourceDir, 'data.csv'); data = readmatrix(dataFile); end这段代码里ctfroot是打包环境中非常重要的函数,返回的是 CTF 归档文件释放后的路径。使用fullfile拼接路径可以避免不同操作系统上的分隔符问题。关于 CTF 归档的原理,在排查章节还会详细展开。
2.3 动态加载、路径操作和交互命令的清理
Compiler 在打包时会做依赖分析,它会静态扫描代码里需要哪些函数和工具箱,但如果代码里有下面这些“动态”行为,静态分析就比较容易漏掉:
- 使用
eval、evalin、feval配合字符串变量调用函数 - 用
addpath在运行时动态添加路径 - 用
load('xxx.mat')加载数据文件,而文件名是在运行时拼接出来的 - 使用
if exist('someFunction', 'file')之类基于函数存在性判断的逻辑
这些动态行为的问题是,打包工具只能根据字面内容做依赖分析,如果函数名是运行时拼出来的,它根本无从知道还要包含哪些文件。
针对这类问题的处理思路是:预先用-a参数把所有可能依赖到的文件都显式包进去,或者把动态调用改为静态调用,比如把feval('myfunc', x)改成switch分支直接调用myfunc(x)。
另外,命令行交互也要处理。如果代码里有input('请输入参数:')这种交互输入,打包成 exe 后仍然可以工作,但只能在命令行窗口里输入,不会有额外的 GUI 输入框。如果你的用户不会用命令行,最好改成通过命令行参数传入,比如myApp.exe 参数1 参数2,这样自动化运行也更方便。
2.4 工具箱依赖的确认与 License 问题
你的代码里用了哪些工具箱,打包时会自动分析并纳入依赖。但这带来两个实际问题:
第一个问题是体积。用了 Image Processing Toolbox、Deep Learning Toolbox 这类大工具箱后,打包产物体积会明显增大,MATLAB Runtime 安装包也很大,这是不可避免的。
第二个问题是 License。打包机需要安装 Compiler 以及程序依赖的各个工具箱的许可。比如你用了 Simulink,就需要 Simulink 的相关授权;工具箱如果用的是试用版,打包出来可能在目标机器上无法正确运行。所以打包前最好先跑一次license('test', 'Statistics_Toolbox')之类的命令确认授权状态正常。
依赖工具箱的具体情况,可以在打包完成后打开readme.txt或者用mcc输出日志查看。图方便的话也可以在命令行里用which myFunction来看这个函数究竟来自哪个工具箱。
3. 两种主流打包方式:图形界面与 mcc 命令行
3.1 用 Application Compiler 图形界面打包,推荐给新手
从 MATLAB 顶部菜单选择“APP”页签,找到“Application Compiler”,或者在命令行输入deploytool,都能打开打包界面。
进入界面后,核心操作分为四步:
第一步,添加主文件。点击“Add Main File”,选择你的主函数 .m 文件。如果程序有多个 .m 文件,只需要选最外层入口文件,因为 Compiler 会自动分析并打包所有依赖的函数。
第二步,添加附加文件。点击“Add Files/Directories”把需要一起打包的资源文件加进去,比如 .csv、.mat、.txt 配置文件、模型权重等。这一步非常关键,前面提到的数据文件读取不到,多半是这一步漏掉了。
第三步,配置应用信息。你可以在右侧填写应用名称、公司名、版本号等元信息,这些会写入最终的可执行文件属性里。同时下拉菜单里要选一个打包类型,默认是 Standalone Application,也可以切换成 Python Package、.NET Assembly 等。
第四步,点击右上角“Package”按钮。等待弹出来的打包进度跑完,它会生成一个压缩包和两个文件夹。打包过程中如果代码有语法错误或者其他问题,这一般是第一个暴露的时刻,所以务必关注输出窗口里的 warning 和 error。
打包完成后,默认会生成for_redistribution、for_testing、for_redistribution_files_only三个目录。其中for_redistribution里是可安装的安装包,一般会生成类似MyAppInstaller_mcr.exe的网络安装器或离线安装器;for_testing里是编译好的 exe 和 ctf 文件,方便你马上在当前机器上测试;for_redistribution_files_only则是纯文件包,不包含安装器,一般用于手动分发。
3.2 用 mcc 命令行打包,更适合自动化构建
如果你的打包操作需要频繁重复,或者要集成到 CI 流水线里,命令行才是正确姿势。mcc是 MATLAB 自带的标准命令,在 MATLAB 命令行窗口里执行,也可以在系统命令行里通过matlab -batch "mcc ..."执行。
最常用的几个参数如下:
| 参数 | 作用 |
|---|---|
-m | 生成独立应用程序,即 Standalone Application |
-W main | 显式指定生成可执行的 main 程序 |
-a 文件 | 添加附加文件/目录,可重复使用 |
-o 名称 | 指定输出文件名 |
-d 目录 | 指定输出目录 |
-R | 传递 Runtime 选项,例如-R -logfile:log.txt |
-C | 不将 CTF 归档嵌入 exe,而是单独生成 .ctf 文件 |
-N | 不使用默认路径下的全部工具箱(配合-p指定路径) |
-p 路径 | 添加指定路径 |
一个很典型的完整打包命令是这样的:
mcc -m -o fitDemo -a data.csv -d ./output main.m这条命令的作用是:把main.m打包成独立应用,输出文件名为fitDemo,把data.csv作为附加资源打包进去,所有产物输出到./output目录。
还有一种更正式的写法对应 Application Compiler 图形界面的全部能力:
mcc -m -W main -o fitDemo -a data.csv -R -logfile:run.log -d ./output main.m其中-R -logfile:run.log让程序运行时生成日志文件,这个对排查运行时问题非常有帮助。如果你的代码对性能要求高,也可以添加-R -singleCompThread之类的参数,不过要注意是否真的需要,因为这会限制多线程能力。
3.3 一个完整示例:从函数到可执行文件
这里用一个简单的回归分析程序走一遍完整流程,方便你对照。假设我们要做一个程序,它读取一个 CSV 文件,文件里有两列数据,然后做一次一次多项式拟合,输出斜率和截距。
写入口函数:
function fitDemo(varargin) % 入口:fitDemo [data.csv] % 处理输入参数 if nargin >= 1 && ischar(varargin{1}) dataFile = varargin{1}; else dataFile = fullfile(ctfroot, 'data.csv'); end % 读取数据 data = readmatrix(dataFile); x = data(:, 1); y = data(:, 2); % 线性拟合 p = polyfit(x, y, 1); slope = p(1); intercept = p(2); % 输出结果 fprintf('拟合结果: y = %.4f * x + %.4f\n', slope, intercept); end然后准备一份测试数据data.csv,内容类似:
1,2.1 2,3.9 3,6.2 4,8.3在 MATLAB 命令行中执行打包命令:
mcc -m -o fitDemo -a data.csv main.m打包完成后,fitDemo.exe会生成在当前目录(如果想指定输出目录,用-d)。在本机测试时可以这样运行:
fitDemo.exe data.csv如果要测试附加资源是否打包正确,可以带上绝对路径运行:
fitDemo.exe因为代码里使用了ctfroot定位data.csv,即使不带参数也能找到资源并正常运行。这个案例虽然简单,但已经覆盖了入口函数、输入参数、附加资源、ctfroot、命令行打包这几个最核心的知识点。
3.4 打包产物解析:exe、ctf 和 readme
打包完成后,你会看到一堆文件,很多人看到这些文件会有点懵,其实核心就三类:
第一类是 exe 本身,也就是你的独立应用,日常分发和运行主要靠它。正常情况下,CTF 归档会嵌入这个 exe 文件内部,所以单个 exe 文件携带了大部分代码和资源逻辑。但要注意,它并不包含 MATLAB Runtime。
第二类是 ctf 文件。CTF 是 Compiler Technology File 的缩写,它本质上是一个归档文件,保存了你全部 .m 文件的编码后形式以及附加资源文件的打包内容。默认情况下它会被嵌入 exe,如果你用了-C参数,它就会作为独立文件出现在 exe 旁边。目标机器运行时,这个 ctf 文件会被解压到临时目录,ctfroot就是指向这个解压目录。
第三类是 readme 文档。它会列出程序依赖的 Runtime 版本、打包时的 MATLAB 版本、包含的文件清单、目标平台要求等信息。这个文件是排查运行时版本问题最重要的参考资料,不要随手删掉。
for_testing目录里的 exe 可以直接运行,但它依赖你本地已经安装的 Runtime;而for_redistribution里的安装器会自动处理 Runtime 安装,更适合交付给其他用户。
4. 目标机器部署:MATLAB Runtime 是绕不开的一环
4.1 Runtime 到底是什么,为什么不能免运行时运行
很多第一次打包的人都有个疑问:我都打包成 exe 了,为什么目标机器还要安装 Runtime?
这里需要澄清一下概念。MATLAB Compiler 做的是“运行时编译”,它会把你的 .m 代码转换成一种中间表示,最后依赖 MATLAB Runtime 里的原生库来解释和调度执行。它不是像 C/C++ 那样把源代码直接编译成完全脱离运行库的机器码。所以,目标机器上必须存在和编译版本匹配的 MATLAB Runtime。
你可以把 MATLAB Runtime 类比成 Java 的 JRE,打包好的程序类似 Java 的 Jar 包,JRE 就是那个公共运行环境。Java 程序不能在没有 JRE 的机器上运行,MATLAB 独立应用也不能在没有 Runtime 的机器上运行。
这个设计让 Compiler 能做到跨机器部署,代价就是首次安装 Runtime 的体验会比较重,包体也比较大。Runtime 本身是免费分发的,可以随你的应用程序安装包一起提供给用户,不会额外产生授权费用。
4.2 Runtime 安装与静默安装参数
Runtime 有很多获取方式。你在图形界面打包时,可以选择让安装器自动下载 Runtime;也可以到 MathWorks 官网的 Runtime 下载页面,选择与打包机 MATLAB 版本完全相同的版本手动下载。
安装过程本身比较简单,就是一步步点击 Next。如果需要批量给很多机器部署,一条静默安装命令会更高效。以 Windows 平台为例,常见的静默安装方式是:
MyAppInstaller_mcr.exe -silent -agreeToLicense yes如果你的安装包不是这个名字,而是下载的完整 Runtime,一般也可以使用类似参数。更通用的做法是先运行一次安装器,查看它的帮助说明,因为不同年份版本的参数略有差异。在 Linux 上,Runtime 解压以后通常有一个install脚本,配合-mode silent -agreeToLicense yes即可完成自动安装。
安装完成后,Runtime 通常会注册到系统路径,Windows 上会写入注册表。正常情况下 exe 运行时会自动找到 Runtime;如果你把安装目录改了名,或者手动移动了 Runtime,就需要手动配置环境变量来指定 Runtime 路径,这一步要特别小心,改名的安装目录经常导致程序找不到运行库。
4.3 版本匹配是一个隐蔽但高发的坑
Runtime 的版本号必须和编译用的 MATLAB 版本匹配。例如你在 R2023a 中打包,目标机器就要安装 R2023a 的 Runtime;如果你安装了 R2022b 的 Runtime,大概率会报出无法找到入口函数、加载 DLL 失败这类错误。
这里的“匹配”在不同 MATLAB 版本里严格程度有差别,旧版本要求完全一致,新版本则要求主版本一致、Update 版本不能低于打包时的版本。保险起见,还是严格遵守“同版本或更高 Update”原则最省心。
判断版本最简单的方法是看打包时生成的 readme.txt。文件里会写明类似MATLAB Runtime R2023a (9.14)这样的版本信息。如果目标机器上已经安装了多个 Runtime 版本,程序也可能因为加载了错误版本而报错,此时可以在命令行手动执行程序,观察报错信息中的 Runtime 路径来判断实际加载的是哪个版本。
5. 打包后运行失败的排查与避坑实录
5.1 高发问题速查表
把我和身边同事踩过的坑整理成一个速查表,遇到问题先对照这个表排查一轮,大概率能省一半时间:
| 现象 | 最常见原因 | 解决方法 |
|---|---|---|
| 启动直接报缺少 DLL | 目标机器没有安装 Runtime,或版本不匹配 | 安装匹配版本的 MATLAB Runtime |
报错Unable to load shared library | Runtime 路径未找到或安装损坏 | 重装 Runtime,检查环境变量 |
| 读取不到数据文件 | 附加资源没有用-a打进包里 | 打包时加入附加文件 |
| 数据文件明明打了包还是读不到 | 代码使用相对路径,未用ctfroot | 改为用ctfroot拼接路径 |
| 中文路径下崩溃 | Runtime 或程序对中文路径兼容不佳 | 全英文路径运行 |
| 杀毒软件拦截或误报 | 编译产物被识别为未知程序 | 加白名单,或对 exe 数字签名 |
| 有 Figure 界面但显示不出来 | 没有图形环境,或 JVM 被禁用 | 确认目标机器有桌面会话,检查-nojvm参数 |
| 运行速度明显慢于 MATLAB 环境 | Runtime 首次解压,或配置低 | 首次运行后观察;再优化算法逻辑 |
5.2 数据文件读取不到的真正原因:理解 ctfroot 解压机制
这是打包场景里最经典的问题,值得单独讲透。当你把data.csv用-a参数打进程序后,这个文件并不是老老实实地躺在 exe 旁边,而是被封装进了 CTF 归档里。程序运行的一瞬间,Runtime 会将这个归档释放到一个临时目录,并在程序结束时按需清理。
这个临时目录的绝对路径,就要通过ctfroot获取。所以正确读取打包资源的方式是:
resourcePath = fullfile(ctfroot, 'data.csv');而不是:
resourcePath = 'data.csv';相对路径的解析取决于程序的当前工作目录,而工作目录在不同机器、不同启动方式下完全不同。我在实际项目中见过有人双击 exe 能成功,但在命令行下运行就找不到文件的案例,原因就是工作目录不同导致的。
如果你希望同时支持“从外部传入文件”和“使用包内默认文件”两种模式,可以参考前面示例代码的写法——有外部参数就用外部参数,没有就用ctfroot拼默认文件,这样兼顾灵活性和稳定性。
5.3 启动慢、杀毒误报、中文路径等实战心得
实际交付时,启动速度是用户感知最强的部分之一。打包后的程序首次启动通常比 MATLAB 环境慢,因为 Runtime 要初始化、CTF 要解压到临时目录。这个解压过程在后续运行时会因为临时目录已有缓存而变快。
如果程序不需要图形界面、只做计算,可以尝试在编译时加-R -nojvm这样的参数来减少 JVM 相关的初始化开销,从而缩短启动时间。但要注意:如果程序里有绘图、GUI、Java 相关功能,就不能禁用 JVM,否则相关功能会直接不可用。
杀毒软件误报是另一个高频问题。MATLAB Compiler 生成的 exe 结构特殊,经常被某些杀毒软件识别为未知或可疑程序。这不是代码问题,但会直接影响用户体验。解决办法包括:给 exe 做代码签名、向目标机器杀毒软件添加白名单、或者提前在说明文档里告知用户。如果 client 的安全策略不接受非签名程序,签名这一步基本没法省。
中文路径和中文用户名的兼容性,在 Windows 平台上尤其值得留意。MATLAB Runtime 对纯英文路径的兼容性是最好的,建议在部署文档里明确要求程序必须放在全英文路径下运行。这块在你本地开发时往往没问题,但在客户现场就是噩梦,因为客户的用户名可能直接是中文。
5.4 代码安全:编译不等于绝对加密,配合 pcode 更稳
最后一个不少人关心的问题:打包后的代码,别人能不能还原出来?
坦白说,MATLAB Compiler 对代码的“保护”是有限的。它会把 .m 文件转换成中间表示并嵌入 CTF 归档,普通用户无法直接查看源代码,但 CTF 文件本身可以被逆向分析。如果算法真的非常核心,需要更高强度的保护,最常用的补强措施是用pcode先生成加密的 .p 文件,再把 .p 文件作为输入参与打包。
不过要提醒的是,.p的加密也不是绝对不可破解的,它只是大幅提高逆向成本,让绝大多数人望而却步。对绝大多数应用场景,Compiler 加 pcode 的双重保护已经足够了。如果你需要银行级、军工级的代码安全,那根本不建议用任何解释型语言方案,而是应该用 C/C++ 重写核心算法,这已经不是打包工具能解决的范畴了。
另外还要注意一点:打包不是“一劳永逸”的。你在 R2023a 上打的包,如果目标机器是 Linux,那需要使用 Linux 版 MATLAB 打包;如果目标是 macOS,也要用 macOS 版打包。跨平台不能交叉编译,这一点经常有人忽略。设计交付方案时,最好一开始就明确目标平台,别等打包完才发现平台不对。
6. 进阶技巧:把 MATLAB 算法封装成其他语言可调用的组件
前面提到的都是独立应用,但实际集成时,很多系统根本不需要一个 exe 界面,而是希望 MATLAB 算法作为一个函数被其他语言调用。这种场景下,MATLAB Compiler 的共享库模式就更合适。
以打包成 Python 包为例。在 Application Compiler 里,把打包类型从 Standalone Application 换成 Python Package,或者用命令行:
mcc -W python:pyFit -T link:lib -o fitDemo -a data.csv main.m打包完成后,会生成一个 Python 包结构。你可以把它安装到目标机器,然后像使用普通 Python 模块一样调用 MATLAB 算法:
import pyFit result = pyFit.initialize() data_file = 'data.csv' slope, intercept = pyFit.main(data_file)这里的核心是,MATLAB 函数以 Python 函数的形式暴露给了 Python 环境,整个调用过程对上层 Python 代码完全透明。类似的还有 .NET、Java、C 共享库的封装方式,命令格式大同小异,主要变化在-W参数的类型上。
在开发这类集成方案时,我给的建议是:把 MATLAB 函数设计成纯计算、无界面的形式,输入输出都用标准数据类型,比如数字、字符串、数组,而不要在 MATLAB 代码里弹窗、输出 GUI。这样跨语言调用时最不容易出兼容性问题。
7. 绕不开的自动化与持续集成小建议
如果打包是偶尔一次的工作,图形界面完全够用。但如果你负责的算法会频繁更新,比如每周都要给测试团队出一个新版本,那就值得把mcc打包命令写进自动化脚本里。以下是我常用的一个自动化思路:
在 MATLAB 中写好入口函数和资源文件后,用一个批处理脚本来完成全链路操作:
matlab -batch "mcc -m -o fitDemo -a data.csv -d ./output main.m"这样,在持续集成服务器上,只要你修改了代码并触发构建,就可以自动完成打包、把for_redistribution产物上传、甚至自动发送给测试人员。整个流程不用打开 MATLAB,也不用手工点击任何按钮。
这样做还能顺便解决一个常见问题:多人开发时,不同人打包出来的结果可能因为 MATLAB 版本、工具箱路径差异而“在 A 机器上正常、在 B 机器上报错”。用统一的构建脚本和构建机器,能在很大程度消除这种环境不一致带来的麻烦。
我个人的体会是,MATLAB Compiler 这项能力最大的价值,不是把 .m 变成 .exe 这个动作本身,而是彻底改变了 MATLAB 代码的交付模式。以前你交付一段算法,对方要先装 MATLAB 再学怎么配路径;现在你交付一个独立程序,对方只需要双击运行。对于算法工程师来说,这意味着你写的每一行代码,都有可能真正被生产环境用起来,而不仅仅停留在实验验证阶段。
最后再分享一个小技巧:打包好的 exe 在给外部用户之前,自己一定要在一台“干净”的机器上测试一次。所谓干净,就是没有安装 MATLAB、没有安装任意版本 Runtime。很多开发者在自己的电脑上测试一切正常,交付到客户那里就各种问题,根源往往就是开发机上有完整 MATLAB 环境,掩盖了 Runtime 依赖、资源路径这些隐患。只有干净环境跑通了,交付才算真正完成。