资讯动态

MATLAB GUI打包独立exe:Application Compiler与Runtime部署实战

发布时间:2026/10/5 12:54:15 来源:尧图企业网站定制
每次把做好的MATLAB界面发给同事我都要先补一句你电脑上装MATLAB了吗没装那你先去装个MATLAB再装对应工具箱再把路径配好再把你那个.mlapp拖进运行……这一套下来光教环境就耗掉半小时。更麻烦的是你辛辛苦苦做好的GUI程序交到对方手里明明只是点几个按钮、看几张图的小功能却要让人家为一个工具去安十多个G的开发环境这搁谁都觉得不划算。所以很多工程师做到一定阶段都会主动研究打包把MATLAB程序编译成不带MATLAB环境也能跑的独立exe。这事官方提供了一套挺成熟的东西就是Application Compiler。我在R2020a和R2020b上都实测过完整流程从GUI代码编写、依赖检查、编译打包到拿到一台没有MATLAB的机器上部署运行整个过程跑通之后我最大的感受就是这个功能真的把“开发”和“使用”彻底分开了但这中间坑也确实不少。这篇文章我按自己实际操作的顺序来写从为什么选这套方案、打包前要准备什么到逐个按钮怎么点再到最后一份问题排查清单尽量把每个细节都说到位。用的是2020R系列版本其他版本界面略有差异但核心逻辑是一样的。1. 为什么要把GUI打包成独立exe以及这套方案是怎么工作的1.1 从一次“给同事发程序”说起大概一年多前我给测试组同事做了个信号预览GUI功能不复杂就是从文件夹里批量读数据文件画个波形能缩放能导图。当时我直接把代码发过去让他自己跑。结果他打开MATLAB发现缺工具箱装了半天工具箱又说License不对折腾一上午最后跑起来一看路径里带中文数据文件夹又读不到。那次之后我就下决心以后再给人交东西绝不给源码和MATLAB环境要求只给一个能双击打开的exe。不只是同事之间协作很多场景都有这个需求给甲方做演示工具、给实验室搭数据采集界面、给非技术背景的客户交付算法验证程序、甚至给自己保存一个“以后不用开MATLAB就能用”的版本。这时候一个独立exe的意义就很直接收程序的人不需要知道MATLAB是什么双击图标界面出来事情就结束了。1.2 exe里面到底打包了什么它不是一个自包含的绿色软件这里要先说清楚一个常见误解。用Application Compiler生成的exe并不是把所有MATLAB函数都编译成机器码塞进一个文件里然后这台机器就什么依赖都没有了。它的真实模型是MATLAB的编译工具把你的代码包括GUI里的回调函数、工具箱调用转换成一堆受保护的中间代码再配上你用到的那些工具箱对应的动态库最后放进一个包里。exe本身更像一个“启动器”真正干活的计算引擎是MATLAB Runtime也就是以前叫MCR的东西。Runtime可以理解成一个“只运行、不开发”的MATLAB运行环境体积不小R2020a对应版本是9.8安装完差不多2到3个GB。但它可以在一台机器上装好之后供多个打包程序共用很多公司会给公用电脑装一次Runtime之后所有同事发的exe就都能跑了。这也是为什么同样是打包有些选项要带Runtime一起装有些选项不带后面实操部分我会详细说。正因为有这层结构你在判断“打包成功”的时候也要多一步验证同样的exe在你自己机器上能跑不算数。一定要复制到一台干净、没装过MATLAB的机器上测一遍这步才是真正的验收。1.3 可选方案横向对比其实想把MATLAB程序给别人用思路不止打包exe一种我在确定方案前也对比过几条路。方案目标机器要求交付体积优点明显缺点让对方装完整MATLAB需要完整License10GB以上源码透明方便二次修改安装成本高授权贵看着就不专业打包exe 安装Runtime只需装Runtime无需LicenseRuntime约2-3GB exe包几十MB一次Runtime多次使用运行速度快首次安装Runtime略麻烦打包exe目标机器已有Runtime只需拷贝exe和dll几十MB分发最简单要求对方机器Runtime版本与编译版本兼容Web App ServerR2020b浏览器访问取决于服务器不需要安装任何东西需要一台常驻服务器配置与运维成本高给源码让用户自己处理需要MATLAB环境源码文件很小最省事对接收方极不友好问题最多我自己最后一直是“exe Runtime”这条路。R2020b之后官方还提供Web App Server方案能把GUI发成网页版这适合给多人用的内部工具但如果你只是交付给固定几个人打包exe仍然是最省心、最可控的做法。2. 打包前准备90%的新手都在这一步卡住2.1 先确认你的License和工具链是完整的很多人打开Application Compiler发现按钮是灰的或者打包到一半提示没有Compiler授权问题通常出在MATLAB Compiler工具箱没装。检查方法很简单在MATLAB命令窗口输入license(test, Compiler)返回1就说明授权可用返回0说明当前License不支持编译。R2020a和R2020b对MATLAB Compiler的授权逻辑基本一致就是要确保购买或部署的License里包含这个组件。另外一个很容易被忽略的问题是你代码里用到的工具箱函数编译授权也要覆盖。绝大多数打包失败不是语法错误而是某个函数对应的工具箱虽然在开发机上能用但该工具箱没有被Compiler支持或者License不允许被部署。比如MATLAB Coder、Simulink这类组件Application Compiler是不能直接处理的后者需要的是Simulink Compiler标题里写的“GUI程序打包”一般用不到这些但如果你在GUI里调用了Simulink模型就要特别注意。2.2 学会用代码查看依赖requiredFilesAndProducts我强烈建议不要等到点Package了才发现缺东西。打包之前先跑一条命令让MATLAB自己列出程序依赖的所有文件和工具箱[files, products] matlab.codetools.requiredFilesAndProducts(myApp.m); files products这里的myApp.m换成你的GUI主函数文件名。执行之后files会列出你这个程序真正依赖的.m文件products会列出依赖的工具箱及对应Matlab版本号。如果你发现某个你自己写的辅助函数没有出现在列表里说明你的主程序里没有静态调用它编译器很可能也不会自动带上它这时候就要手动补。这个命令对我们的打包思路是一个很好的体检它告诉我程序“真正需要什么”避免我凭印象猜。我在一次实际项目里就是用它发现GUI里动态加载的一个数据解析脚本没被列进依赖当时要是不查打包出来的exe到别人机器上一跑点按钮就报“未定义函数或变量”那场面很难收场。2.3 把GUI工程整理成适合编译的结构我踩过不少次坑之后总结出一个比较保险的工程目录结构现在每次打包前都先把代码整理成这个形态project_root/ ├── mainApp.m % 主函数入口 ├── helper_funcs/ % 其他自定义函数 │ ├── loadData.m │ ├── plotWave.m │ └── exportFig.m ├── resources/ % 界面用的图标、示例数据、配置文件 │ ├── logo.png │ └── config.ini └── package_out/ % 打包输出目录这个提前建好如果你用的是App Designer主程序是一个.mlapp文件那结构也可以把.mlapp当作入口文件放到根目录手动添加资源文件夹的时候把resources一起加进去就行。为什么这么强调结构因为Application Compiler虽然会自动扫描依赖但它扫描的规则是基于主程序里的“静态引用”——也就是代码里直接写明的那些函数调用。如果代码里用了eval、feval、str2func这种动态调用或者脚本运行时才拼接函数名编译器是没法自动发现并打包的。把这些文件统一放在一个明确目录下打包时手动添加整个目录就不容易漏。2.4 主文件必须是函数不是脚本这是所有新手最容易翻车的一步。Application Compiler接受的主程序需要一个以function开头的文件。如果你习惯写脚本从头到尾只要变量没有函数声明直接添加是没问题的但编译器会提示你主程序必须是一个函数。解决办法很简单套一层壳。比如你的脚本叫process.m那就新建一个run_process.mfunction run_process % 这里直接调用原本的脚本逻辑 process; end这样打包入口就是run_process.m。如果是App Designer设计的GUI本身就是类定义加函数天然满足要求。如果是GUIDE时代的老工程主文件通常也是一对.fig和.m打包时把.m文件作为主程序.fig作为资源一并添加同样能正常编译。但2020R这个时间点GUIDE已经开始被官方标注为“不建议新项目使用”了新项目我建议直接用App Designer。3.Application Compiler完整打包实测过程3.1 打开App和界面导览在MATLAB命令窗口输入applicationCompilerR2020a和R2020b会打开一个独立窗口整个界面左侧主要功能是“打包应用程序”对应的是Standalone Application这正是我们要的。旁边还有“打包库”等选项那是给其他语言调用用的属于MATLAB Compiler SDK的范畴先不用管。进入“打包应用程序”页面后界面从上到下大概是这样的结构主文件区需要指定一个主程序文件不要选多个主程序只能有一个。自定义打包文件区可以手动添加额外的文件夹或文件比如数据文件、图标文件、工具函数。应用程序信息区设置名称、版本号、公司名、图标、附加说明文字。Runtime包含方式这里的问题比较关键我单独在3.3里说。Package按钮最终执行编译。标题里提到“2020R版本实测”有一点需要说明R2020a的Application Compiler窗口相对朴素R2020b在此基础上做了一些界面调整和Web App引导但核心选项位置基本一致。我下面写的步骤是R2020b里实拍的逻辑R2020a用户按相同名称找控件即可。3.2 添加主文件与依赖文件点“添加主文件”选择你的GUI主函数比如mainApp.m。如果入口是.mlapp这里也能直接选。选完主文件后Application Compiler会立刻做一次依赖分析在“包含的包”或“运行时设置”里列出它自动发现的文件。这时候回头打开2.2节里我们跑requiredFilesAndProducts的列表对比一下自动发现的结果有没有漏掉什么。如果漏了就在“自定义打包文件”里手动添加。注意一个细节添加文件夹时编译器默认是“递归添加”也就是把子目录里的文件也包含进去。如果你的工具函数里有一个子目录忘了这一条运行时还是会报找不到文件。资源文件的添加也一样。比如GUI用到了一个图标文件logo.png你就把它加到自定义文件里。之后在代码里引用这个资源的时候需要按打包后实际运行的路径逻辑来写这一块在第5节会展开因为它是运行时最容易出问题的地方。3.3 Runtime分发方式的选择包含还是不包含Application Compiler界面里有一个选项名字类似“运行时下载”或“包含MATLAB Runtime”。它通常有几种选择不包含只生成exe和依赖dll目标机器上必须已经装过同版本的MATLAB Runtime。包含Runtime安装程序输出里会附带一个Runtime安装程序对方可以先装Runtime再运行exe。生成完整安装包/安装器编译器会把exe和Runtime安装程序做成一个安装向导接收方双击后一路“下一步”即可。选哪种取决于接收方的情况。如果接收方是一台公用机器以后会有不少人给他发MATLAB编译程序那第一次选“包含Runtime安装程序”装一次以后别人再给他发exe就可以相互用同一个Runtime了。如果接收方是完全不懂技术的业务人员那就直接生成完整安装包让他一路点下去体验最友好。有一点要提醒R2020a和R2020b的Runtime不能混用版本支撑比如R2020a编译的程序对应的Runtime必须是9.8R2020b对应9.9。不过同一台机器上可以同时装多个版本的Runtime互不干扰。非要图省事的话我就建议所有同学都统一用R2020b或更新版本以后组内互相发程序也方便管理。3.4 点Package之后到底发生了什么上面都填好后点“Package”然后等待。编译过程短则两三分钟长则十几分钟取决于程序规模和机器性能。打包过程中Application Compiler会在背后调用mcc命令把你的代码编译成中间表示把用到的工具箱函数和资源文件统一打包成CTF归档文件再生成exe可执行文件和一组dll。R2020a打包后通常会在输出目录里得到一个exe加一个同名的ctf文件R2020b里这些文件通常被自动组织在输出目录的结构中。注意这些dll和你代码里的函数库不是一回事它们本质上是Runtime组件缺少任何一个都会导致启动失败所以分发时不要只拷exe要把整个输出目录一起拷走。打包过程中如果报错错误信息会出现在MATLAB命令窗口。最常见的错误是“找不到编译器”有时候是这个提示Error using mcc The MATLAB Compiler requires a supported compiler.很多人一看这个就去装Visual Studio其实在R2020a和R2020b里用Application Compiler打包纯MATLAB代码并不需要额外安装C/C编译器只有你的程序里包含MEX函数或外部C代码时才需要。真遇到这个报错先检查一下MATLAB Compiler这个工具箱本身的License是否完整而不是浪费时间装编译器。3.5 输出目录里那三个文件夹分别派什么用场打包完成后输出目录下通常会出现三个文件夹for_testing、for_redistribution、for_redistribution_files_only。很多人第一次看到这三个文件夹就晕了。我解释一下它们各自的实际用途文件夹内容我的使用建议for_testingexe、dll、ctf文件可直接在本地运行打包后第一件事用它做快速自测跑通再说for_redistribution完整的安装包如MyAppInstaller_web.exe交付给技术小白用户时用这个双击安装覆盖Runtimefor_redistribution_files_only只有exe和dll没有Runtime安装器交付给已经装了同版本Runtime的机器拷过去就能跑在实际交付时我一般把for_redistribution_files_only里的东西压缩成一个zip发给对方的同时写清楚一条要求“机器上已经装过MATLAB Runtime R2020a就直接解压运行没装过就先装这里附带的Runtime安装包。”如果对方不是我这种能折腾的人就直接发完整安装包体验最好。补充一个细节for_testing目录下面有个readme.txt我每次都会打开看一眼里面写了这个程序依赖的Runtime版本和运行注意事项。这比自己记靠谱得多建议你也养成习惯。3.6 不想开界面命令行mcc一条龙Application Compiler毕竟是图形界面手动点几个按钮能满足大多数场景。如果你的打包流程要走自动化或者要把打包步骤写进CI脚本那就得用命令行方式。以我的一个工具为例主程序是mainApp.m我想打包成一个叫MyTool的独立exe命令是mcc -e -m -o MyTool -W main:MyTool -T link:exe mainApp.m helper_funcs/loadData.m resources/logo.png参数拆开解释一下-e生成独立应用程序不需要接收方装MATLAB。-m告诉编译器生成的类型是“独立应用”而非库。-o MyTool指定输出文件名。-W main:MyTool设置exe入口主函数名。-T link:exe指定目标类型为exe可执行文件。命令行方式和界面方式的底层一致但命令行方式不会自动帮你把“自定义文件”里的非代码文件如图片、数据文件编排好需要你手动把资源文件加到参数里。所以如果工程里有大量资源文件我还是更推荐用图形界面勾选省得命令行里一长串路径看着头晕。4. 把exe搬到没有MATLAB的机器上4.1 完整部署流程装Runtime再跑exe打包完成后找一台干净机器做验收。这台机器最好是一台没有装过任何MATLAB组件的Windows或者虚拟机也行。部署步骤是这样从for_redistribution目录里拿到完整安装包比如MyAppInstaller_web.exe双击运行。安装程序会先安装MATLAB Runtime按提示选择安装路径默认路径就好不建议改到带空格或中文的目录。安装完成后再把exe和dll文件拷贝到某个固定目录双击exe运行。如果你手里是for_redistribution_files_only那就跳过安装步骤前提是机器上已经有R2020a(Runtime 9.8)或R2020b(Runtime 9.9)。判断机器装没装Runtime最简单的办法是看“控制面板-程序和功能”搜索“MATLAB Runtime”看到对应版本号就说明有。一个很容易踩的误区是把exe拷贝过去了但和它同目录的那几个dll没有一起拷或者只拷了exe而忘记了旁边的ctf文件。结果双击后程序闪退毫无提示。所以我一再强调拷贝时要拷整个for_redistribution_files_only目录里的内容而不是只挑一个exe文件。4.2 在目标机器上的GUI验收清单部署到干净机器上不要只双击一次发现能开界面就算完。GUI程序的验收要多测几个关键点我自己习惯按这个清单来双击exe界面能否正常打开是否有报错弹窗。触发几个主要按钮功能尤其是涉及读文件、写文件、调用外部程序的回调。切换不同工作目录再运行看看程序是否依赖“exe所在目录”才能找到数据文件。看看任务管理器里进程是否正常退出不留下残留进程。其中第三点最常见。很多程序在开发机里直接在代码里写相对路径比如readtable(data.csv)在开发机上跑没问题因为当年当前目录就是工程目录。但打包后双击exe当前工作目录通常是exe所在目录或系统用户目录如果程序恰好在启动时读配置文件就会找错路径。在验收清单里加上这一项能提前发现问题。4.3 Runtime版本冲突与多版本共存一台机器上如果先后装过R2019b、R2020a、R2023b的Runtime它们会各自独立安装互不影响。MATLAB Runtime的安装机制做得还行不会互相覆盖。但有一个麻烦点是如果你编译用的是R2020a而目标机器只有R2020b的Runtime程序是跑不起来的。Runtime版本和编译版本必须严格对应至少对R2020a和R2020b是这样。所以你在给多个同事分发程序时最好在说明文档里写清楚“本程序基于MATLAB R2020a编译需要安装MATLAB Runtime 9.8。”如果不确定对方是否装过可以直接让他安装包里的Runtime安装程序走一遍。不用担心重复安装Runtime如果已经存在安装程序会提示修复或直接跳过不会把系统搞乱。5. 打包与部署阶段最常见的坑以及对应的排查方法5.1 路径问题不是代码的问题是运行时的工作目录变了这个问题压到第一个说因为它影响面太大。打包后的程序和开发机上的MATLAB环境有个本质区别开发时你的当前工作目录是工程目录能直接访问相对路径打包后程序没有“当前脚本目录”这一说它的工作目录取决于你怎么启动它。如果代码里用pwd来定位资源文件打包后十有八九会翻车。正确的做法是编译程序内需要引用的资源文件要在代码里用ctfroot获取打包归档的解压目录resPath fullfile(ctfroot, logo.png);ctfroot是打包后程序运行时MATLAB Runtime把CTF归档内容解压到的临时目录。代码里通过它就能稳定找到打包进去的资源。如果你想定位的是“用户当前在某些GUI里选中的文件”那应该用uigetfile返回的路径而不是猜测相对路径。还要小心一点不要往ctfroot目录里写文件。这个目录对程序来说是只读的每次启动都会临时解压退出后可能清理掉。需要写日志、写配置、写结果的时候应该写到pwd或用户文档目录。5.2 动态函数调用导致的“运行时报错编译时一切正常”Application Compiler的依赖分析是静态的。如果你的代码里写了funcName myFunc; feval(funcName, data);或者用str2func拼接回调函数名编译器在打包时根本看不到myFunc这个名字更不会主动把它加进去。结果就是编译顺利通过但你到目标机器上一跑点某个按钮就报“未定义函数或变量myFunc”。排查方法检查代码里所有eval、feval、str2func、evalin调用凡是动态调用的函数都要在打包时手动添加到自定义文件里或者改用静态调用写法myFunc(data); % 直接调用编译器能识别实在要动态调用就在代码里加一行“假引用”骗过依赖分析比如在文件开头写上if false myFunc(); end这样编译器会把myFunc包含进去且运行时不会真正执行。这个技巧不优雅但好用我把它留在了很多老项目的代码里。5.3 杀毒软件误报与Windows SmartScreen拦截MATLAB编译出来的exe启动时会释放dll、读注册表、链接Runtime行为和很多商业软件的首次启动差不多部分杀毒软件或者Windows SmartScreen会对它产生“不认识”的提示。我在Windows 10和Windows 11上都遇到过“Windows已保护你的电脑”弹窗需要点“更多信息-仍要运行”才能继续。如果你的接收方是业务部门这种弹窗会非常有杀伤力对方可能直接觉得程序有问题不敢点。解决方法是把生成的安装包做代码签名但个人开发者搞到代码签名证书成本不低。折中方案是提前告知接收方这是MATLAB Runtime的常见提示让他放心点“仍要运行”。另外在公司内部杀毒软件的管理后台可以把exe所在目录加白名单但这通常需要IT权限我一般只在文档里提示一下。5.4 常见问题速查表现象原因解决办法打包时提示缺少编译器MATLAB Compiler授权不完整或代码里含MEX文件检查License若有MEX则安装对应C编译器双击exe闪退任务管理器一闪而过缺少dll或ctf文件或Runtime版本不匹配从for_redistribution_files_only整个目录拷贝确认Runtime版本界面能打开点按钮报“未定义函数”动态调用函数没被打包手动添加文件或用静态调用写法读取不到配置文件或图片使用了相对路径改用ctfroot拼路径程序第一次启动慢Runtime首次解压CTF归档属于正常现象后续启动会加快杀毒软件拦截Runtime行为类似商业软件提示接收方放行或做代码签名中文路径下运行异常部分老代码对中文路径支持差建议安装路径和数据路径都避免中文6. 打包之后的日常维护与升级建议打包不是一次性工作程序后续要改Bug、加功能就会涉及重新编译和重新分发。这里有几个经验值得说说。第一建议给每次打包留下“编译记录”。我在工程目录里放了一个build_log.txt每次打包都记一下编译时间、MATLAB版本、Runtime版本、输出目录大小、测试结果。这样过两个月用户报了一个老版本的Bug我能快速知道那个版本是用什么环境打的能复现还是不能复现心里有数。第二升级MATLAB主版本时要重新编译一遍所有已交付的程序。不要把R2020a编译的exe指望到R2023b的Runtime上跑版本对不上绝对跑不了。像从R2020a升到R2020b这种小版本升级也建议重新编译一次旧版Runtime虽然还能装但总归多维护一个版本不是好事。第三新项目建议直接用App Designer而不是GUIDE。GUIDE在R2020a里还能正常用但官方已经逐步淘汰它新版本MATLAB里已经很难找到完整支持。App Designer做的.mlapp不仅能正常被Application Compiler打包界面风格也更现代对高分屏支持也更好。我自己的习惯是每次代码改动后先在开发机上用for_testing里的exe跑一遍确认没问题再重新生成for_redistribution安装包最后把新包发给测试的同事并请他确认是不是干净机器上测试的。这套流程看着多但能避免绝大多数“在我电脑上明明好的”这种尴尬。最后再分享一个小技巧打包完的exe不要直接放在桌面或临时文件夹里就给人家压缩成一个zip再发给对方zip里放一个README.txt把Runtime版本要求、首次运行注意事项写清楚。接收方体验会差很多你后续被问的问题也少很多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑