ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

MATLAB程序打包成exe全攻略:从Compiler到Runtime部署排错

MATLAB程序打包成exe全攻略:从Compiler到Runtime部署排错 把辛辛苦苦写好的 MATLAB 程序交付给同事、客户或者放到实验室别人电脑上跑最头疼的就是对方没有 MATLAB 环境。装一个完整版 MATLAB 又贵又重很多人第一反应就是能不能把 MATLAB 程序打包成 .exe 独立可执行程序让对方双击就能跑这件事完全可行而且是 MATLAB 官方早就提供的标准能力。这次我就把从环境准备、图形化打包、命令行自动化到部署排错的全过程一次性讲清楚全程都是我自己实际操作过的经验照着做基本不会踩大坑。我最早接触 MATLAB 打包是在给一个课题组做算法交付的时候对方机器上既没有 MATLAB 也没有 License项目又要求在验收现场直接跑演示。折腾了几天踩了版本不匹配、依赖丢失、运行库报错一堆坑之后才把整个流程理顺。这篇文章主要适合这几类人准备把 MATLAB 算法或小工具做成 exe 发给别人的工程师、需要给毕设做演示界面的学生、以及想在服务器上批量产出可执行程序的开发同学。内容以 MATLAB Compiler 和 MATLAB Runtime 为主线从原理讲到实战最后附上我整理过无数次的排错清单。1. 打包前先想清楚这件事原理、环境与方案选型1.1 打包成 exe 到底做了什么很多人第一次听到“把 MATLAB 程序打包成 exe”会觉得神奇以为 MATLAB 像 C 一样把源代码直接编译成了机器码。实际上 MATLAB Compiler 做的事情更接近 Python 打包成 exe 的原理它把 .m 文件转换成 C/C 代码再编译成可执行文件但这个可执行文件并不包含 MATLAB 的全部功能它依赖一个叫 MATLAB Runtime 的免费运行时环境。MATLAB Runtime 可以理解成一个“精简版 MATLAB 引擎库”它里面有所有数学库、绘图库和基础解释器但不需要 License可以随你的 exe 一起分发。你的 exe 加上 Runtime组合起来就是一个完整可运行的系统。这也是“独立可执行程序”的含义对最终用户来说他不需要安装 MATLAB只需要装一个 Runtime然后双击你的 exe 就能跑。这里有个重要的认知必须提前建立用 MATLAB Compiler 打包出的 exe不是完全脱离环境的绿色单文件。它要么依赖目标机器上已经安装的 MATLAB Runtime要么依赖你通过安装包帮他装好的 Runtime。理解了这一点你后面就不会对“为什么打包后还要装一个 2GB 多的运行库”感到意外。1.2 动手前必须确认的四件事我见过太多人没做检查就急着点打包结果包出来一运行就报错。在点下打包按钮之前请务必确认以下四件事第一确认你的 MATLAB 里装了 MATLAB Compiler 工具箱。这是打包功能的基础没有它部署工具栏都是灰的。在命令窗口运行ver(Compiler)能看到版本信息就说明已安装如果报错就需要先补装该工具箱并确保 License 支持。第二确认你的代码所依赖的工具箱都在 MATLAB Compiler 的支持列表里。绝大多数常用工具箱都没问题但有少数工具箱不支持直接编译部署比如 Simulink 本身就需要 Simulink Compiler 或者其他方案。建议提前查一下你 using 到的那几个工具箱是否在 Compiler 支持范围内否则打出来的包运行时会报“Toolbox not supported”之类的错误。第三确认你本机 MATLAB 版本号。打包后的 exe 要求目标机器安装的 MATLAB Runtime 主版本与打包机一致。比如你在 R2023b 上打包目标机器就最好装 R2023b 对应的 Runtime。版本不一致是运行时各种灵异报错的最大来源没有之一。第四确认目标机器的操作系统和位数。虽然大多数情况都是 Windows x64但如果你要发给 32 位系统用户就得用 32 位 MATLAB 打包。提前问清楚比事后白折腾强得多。1.3 deploytool、mcc、Application Compiler 到底什么关系新手第一次接触打包会在教程里看到三种叫法deploytool、mcc、Application Compiler。其实它们本质上是同一套东西只是入口不同。deploytool 是 MATLAB 里的图形化部署工具运行后会出现打包向导。Application Compiler 是这个向导里专门负责“把 MATLAB 程序做成独立桌面应用”的模块。mcc 则是底层命令行工具deploytool 做的所有事情最终都是调用 mcc 来完成的。所以选择很简单如果你只是偶尔打包一次或者对命令行不熟直接用 deploytool 图形界面最省事如果你需要频繁重新打包或者要把打包过程写进自动化脚本、集成到 CI 里那就用 mcc 命令行。我自己的习惯是第一次用 deploytool 把工程配置摸索清楚之后全部改用 mcc因为命令行可以复制、可以记录、可以重复执行效率高很多。2. deploytool 图形化打包全流程实操2.1 从创建工程到添加文件的完整步骤首先打开你的 MATLAB确认主程序能正常运行最好先跑一遍把工作区里乱七八糟的变量清掉免得打包时把测试数据也带进去。然后在命令窗口输入deploytool界面会弹出打包功能选择面板这一步要选择“Application Compiler”部分版本显示为“Windows Standalone Application”。进入后你会看到一个工程配置界面里面有几个关键区域主文件Main files区域添加你程序的主入口脚本也就是那个能启动整个流程的 .m 文件。如果你有多个相互独立的程序可以点 Add 同时加入多个主文件每个主文件会生成一个对应的 exe。但大多数项目其实只有一个主入口加多了反而容易混淆。文件区域Files to package for your application / 附加文件这里用来添加程序运行时需要的非代码资源比如配置文件、数据文件、图片、字体、dll 等。这些文件会一并打包进部署档案目标机器不需要手动放置它们程序运行时也会在自动解压的目录里找到。在最下方可以设置“Application name”最终 exe 的名字和输出目录。“Application name”建议用英文不要带空格和特殊字符因为后续生成的安装包、路径处理都跟它有关用英文最保险。填完后点 Package 按钮MATLAB 就会开始编译。首次打包会慢一些因为要生成 C 代码、调用编译器做编译、再打部署包。编译过程中如果报错大多是因为代码里用了 Compiler 不支持的语法或函数错误信息里会告诉你具体是哪个表达式或函数出了问题。2.2 运行设置和 Runtime 下载方式怎么配置在 deploytool 界面的“Additional runtime settings”里有几个容易被忽略但很关键的选项。第一个是生成程序的控制台窗口行为。mcc默认生成的 exe 是带一个黑色控制台窗口的 console 程序如果你的 MATLAB 程序本身有 figure 界面那个黑窗口会一直杵在后面很碍眼。解决办法是在“Additional parameters”里加上-W WinMain这样生成的就是 Windows 桌面 GUI 程序不会再弹控制台黑窗。这个参数非常实用我几乎每个交付项目都会加。第二个是 Runtime 的获取方式。打包完成后MATLAB 会给出三个子文件夹后面详细讲其中 for_redistribution 里有一个安装引导程序。这个安装器可以选择“从网络下载 Runtime”或“使用本地 Runtime”。如果目标机器能联网选择网络下载方式生成的安装包很小如果目标环境是完全离线的就要选择包含完整 Runtime 的本地安装器这个安装器体积会达到 2GB 以上但拿到任何机器都能离线装完。第三个是生成格式。Application Compiler 默认会生成独立可执行程序所需的全部产物包括 exe、ctf 部署档案和说明文档。除非你有特殊需求比如要生成 MATLAB Compiler SDK 的库或 Excel 插件否则保持默认即可。2.3 打包完成后那一堆文件夹怎么区分点完 Package 后MATLAB 会在你的输出目录里生成四个东西为主的文件夹很多人第一次看到会懵。我逐个解释for_redistribution这是最终给用户分发用的文件夹。里面有一个以你的应用名命名的安装包通常是MyAppInstaller_mcr.exe或MyAppInstaller_web.exe。_mcr版本是完整自包含安装器里面包含了 MATLAB Runtime 安装程序_web版本需要联网下载 Runtime。目标用户双击这个安装包就可以一路 Next 完成安装桌面上会生成快捷方式。这是最省心的交付方式。for_redistribution_files_only这个文件夹里是精简的部署文件一般就是你的应用名.exe和你的应用名.ctf再加一个 readme。如果目标机器已经装好了匹配版本的 MATLAB Runtime直接把这两个文件拷过去就能双击运行不需要再跑一遍安装器。for_testing这是编译测试时生成的目录包含 exe 和 ctf通常是给开发者本机做冒烟测试用的不要在正式分发时给客户用这个目录。PackagingLog.txt记录打包过程的日志文件。如果打包后有任何问题先翻这个日志里有没有 Warning很多隐患在那就能查出来。给客户的最终交付物只需要两样for_redistribution里的安装包或者for_redistribution_files_only里的 exe 加 ctf。二选一不要给一堆文件夹否则用户根本不知道跑哪个。2.4 目标机器部署Runtime 到底怎么装、装哪个版本这是整个流程里最容易出问题的环节。如果你选择的是完整安装包交付用户双击安装包后安装程序会自动检测系统里有没有匹配的 MATLAB Runtime如果没有就一起装整个过程不需要手动干预。如果你选择的是“只给 exe ctf”这种轻量交付那目标机器就必须先手动安装 MATLAB Runtime。Runtime 去哪里找在 MATLAB 官网的 Runtime 下载页面选择与你本机版本一致的那一版比如 R2023b 就选 R2023b 对应的 Runtime下载 Windows 版本后安装。安装的时候需要管理员权限安装路径默认在C:\Program Files\MATLAB\MATLAB Runtime\下面装完不需要打开任何东西它会注册到系统里。我强烈建议在真正交付前找一台完全干净的机器最好是没有装过 MATLAB 和 Runtime 的虚拟机做一次全流程验证装 Runtime、拷 exe 和 ctf、双击运行、跑一遍核心功能。我见过太多“在我电脑上好好的拿到对方那就崩”的案例几乎都是部署验证没做。干净的机器能帮你发现各种隐藏依赖问题这一步省不得。3. mcc 命令行打包批量与自动化的唯一正解3.1 mcc 的核心参数逐个拆解当你需要反复出包或者要把打包动作写进自动构建流程时deploytool 每回都要打开界面点鼠标效率太低。mcc 命令才是真正的生产力工具。我常用的几个参数如下-m表示生成独立可执行程序。加上这个参数mcc 会输出 Windows 平台下的可执行文件以及配套的 ctf 档案。如果不要控制台黑窗就额外加-W WinMain。-o指定输出文件的名字。注意这里不用带.exe后缀mcc 会自动给你加上。-a用来添加附加文件。程序运行时要读取的配置文件、模型文件、图片等资源都可以用这个参数加进去它会被打进 ctf 部署档案里。注意-a后面跟的是文件路径不是文件夹路径如果要把整个文件夹加进去需要用通配符或者单独列出所有文件。-I指定额外搜索路径。如果你的程序引用了其他文件夹里的函数需要把那个文件夹通过-I加进来否则依赖分析阶段就会漏掉。-d指定输出目录。不加的话文件会生成到 MATLAB 当前工作目录里容易把项目目录搞乱建议每次都用-d单独指定一个 build 目录。-R用来传递运行时选项比如写日志、指定启动参数等。日志调试时非常有用比如-R -logfile:app.log可以把运行日志输出到文件里程序闪退时看日志比猜原因高效多了。3.2 一个可以直接抄的打包脚本我自己项目里会放一个 build.bat或 build.m每次更新版本后双击就完成出包。核心命令长这样mcc -m main.m -W WinMain -o MyApp ^ -a config.ini -a resources/logo.png -a data/model.mat ^ -I ./src -I ./lib ^ -d ./build拆开看就是把main.m作为主入口编译生成一个没有控制台黑窗的MyApp.exe打包时把配置文件、logo 图片、模型数据一起塞进 ctf搜索路径包含 src 和 lib 两个目录最终成品输出到 build 文件夹。如果你的代码非常依赖于某个工具箱还可以加一句依赖检查matlab.codetools.requiredFilesAndProducts(main.m)这行命令会在打包前把 main.m 里所有依赖的文件和工具箱列出来。我每次都拿这个清单跟 mcc 的产物做对比确认没有漏掉自写的子函数。如果你想把打包过程整合到 MATLAB 脚本里可以直接用 system 调用status system(mcc -m main.m -o MyApp -a config.ini -d ./build);然后根据 status 判断打包是否成功失败了就自动发邮件告警。配合 CI 工具就能实现“代码提交后自动出包”的完整流程。3.3 命令行模式最容易踩的隐藏坑用了很长时间 mcc 之后我总结了三个命令行模式下特别容易翻车的点。第一个是eval和feval动态调用。如果你的代码里有形如eval([result_, num2str(i)])或者通过字符串变量调用函数依赖分析器是看不到这些动态调用的打包时这些函数就不会被包含进去。运行时会报“Undefined function or variable”。解决办法是在代码里加一行让 Compiler 知道有这些函数存在比如%#function myFunction1 myFunction2或者在文件尾部写一个永远不执行但引用了这些函数的函数。我自己更推荐干脆重构成不用 eval 的写法一劳永逸。第二个是 ctf 文件的更新问题。打包生成的新 ctf 如果和旧 ctf 同名会覆盖掉但有些情况下目标机器上的旧缓存会导致新程序读取到旧内容。重新打包后我建议删掉 build 目录再重建不要在原目录上反复覆盖。第三个是路径里带中文或空格。mcc 命令在某些版本下对中文路径处理有问题可能打出来的包运行时报一堆奇怪的错误。命令行模式下尽量把项目放在全英文路径里这是最稳妥的做法。4. 打包与部署常见问题排查技巧实录4.1 运行期报错速查表我把这几年遇到的典型报错整理成了下表按频率排序现象真正原因解决方法提示找不到 MATLAB Runtime 或版本不对目标机器没有安装 Runtime或版本与打包机不一致安装与打包机主版本号完全一致的 Runtime报 libmwmclmcrrt.dll 缺失Runtime 未正确安装或被安全软件隔离删除重装 Runtime并检查杀毒软件隔离区双击 exe 没有反应、闪退ctf 文件没和 exe 放在一起或路径中文冲突或安全软件拦截确认 exe 和 ctf 在同一目录换英文路径加白名单报 Undefined function 或某工具箱缺失打包时漏了动态依赖或依赖了不支持的函数用 requiredFilesAndProducts 检查加-a补文件打包成功但运行时读不到数据文件配置文件或数据文件没打进 ctf用-a把资源文件加进部署档案杀毒软件报警并删除 exe未签名的 exe 容易被误判对 exe 做代码签名或提交安全软件白名单程序运行慢尤其是启动阶段Runtime 首次加载耗时读取大数据过多优化启动逻辑数据延迟加载详细见 4.2这张表基本覆盖了 90% 的部署问题。遇到闪退类问题我的标准做法是在控制台里手动运行 exe如果你生成的是带控制台的版本或者加上-R -logfile参数把日志输出到文件先看报错内容再动手改不要瞎猜。4.2 为什么打包后的程序启动这么慢你的 MATLAB 程序在 MATLAB 里跑时环境是热备好的打包成 exe 后每次双击启动都相当于经历一个“小型 MATLAB 冷启动”加载 Runtime、初始化运行时环境、解压并读取 ctf 里的依赖、初始化图形系统等。这一套下来慢的机器上花十几秒是很正常的事第一次启动尤其明显。解决思路有两个方向。第一个是优化代码把启动阶段不需要的耗时操作后移。最常见的问题是主函数开头load了一个几十 MB 的 mat 文件还没显示界面就先卡几秒。改成界面先弹出来再异步加载数据体验会好很多。第二个是接受这个现象并从产品角度缓解比如在程序入口显示一个启动画面或者在 README 里说明首次启动需要加载运行时。另外注意如果 ctf 文件很大比如打进去几十 MB 的资源每次启动解压也会拖慢速度。能通过外部文件读取的资源尽量不要塞进 ctf运行时让用户把资源放在 exe 旁边既能减小 ctf 体积也能让启动更快。4.3 打包后体积太大怎么瘦身一个打包出来的安装包动辄 2GB 以上很多人第一反应是懵。这 2GB 里其实绝大部分是 MATLAB Runtime这部分是没法裁剪的无论你的程序多简单只要用了 Runtime 就必须带着它。真正能优化的是你的 exe 和 ctf 部分。第一个检查项是 ctf 里有没有混入不必要的大文件。我见过有人在工程配置里不小心把整个数据文件夹打进 ctf里面全是几个 GB 的测试数据和中间结果完全没必要。正确做法是数据文件单独分发程序用相对路径读取。第二个检查项是用到的工具箱。如果你的程序只是做简单的数据读取和图表显示却因为某个函数不小心用了某个重型工具箱打包时可能会把整个工具箱依赖都拉进来体积和启动时间都会上涨。用matlab.codetools.requiredFilesAndProducts检查依赖清单看看有没有意外引入的大工具箱。第三个思路是把纯计算部分的代码用 MATLAB Coder 生成 C/C 再编译。这种方法不依赖 MATLAB Runtime生成的 exe 只有几 MB启动速度和资源占用都大幅改进。代价是 Coder 对代码限制比较多不是所有 MATLAB 语法都支持。如果你的程序主体是数值计算、控制算法且 UI 很轻这个替代方案值得考虑。4.4 杀软误报、中文路径、ctf 丢失这些部署细节最后讲几个部署时非常影响体验的细节。杀毒软件误报是我在交付 Windows 程序时碰到的最高频问题。未签名的 exe加上它运行时要解压 ctf、写缓存文件行为模式在某些杀毒软件眼里很“可疑”。最彻底的解决办法是申请代码签名证书对 exe 签名但这对个人开发者来说成本不低。临时方案是把 exe 添加进安全软件的白名单并在 README 里写清楚如果被杀软提示应该如何操作。ctf 文件丢失是另一个常见问题。很多用户拷贝 exe 时不注意旁边的 ctf 文件只带走了 exe结果双击直接报错。最稳妥的做法是用 for_redistribution 里的安装包交付安装器会把文件放到正确位置用户平时只需要使用桌面快捷方式不用手动处理 exe 和 ctf 的对应关系。中文路径问题属于“出现概率不一定高但一出现就极难排查”的坑。我遇到过 exe 在英文路径下正常放进中文文件夹里就找不到 Runtime 环境的情况。所以无论是安装 Runtime 还是放置程序都尽量使用全英文路径包括 Windows 用户名也尽量是英文。国际惯例省心。结尾最后再分享一个我自己的心得体会打包这个动作本身不复杂真正考验人的是“交付后不出问题”的保障能力。我后来形成了固定的发布流程每次打包前用requiredFilesAndProducts检查依赖用mcc命令行统一出包在干净虚拟机里完整跑一遍部署流程最后写一份简单的部署说明文档。这个流程看着繁琐但正是它让我从“给别人发程序就紧张”变成了“发出去基本不用管”。你现在如果正准备把 MATLAB 程序变成 exe建议把这个流程也复制走能省掉很多后半夜查 bug 的苦日子。
返回列表