说实话,在MATLAB 2019a里和Visual Studio 2017较劲,是不少搞科研、跑仿真、写算法的人迟早要遇到的一天。装好MATLAB,想写个MEX调用C++代码,或者某个工具箱需要本地编译,敲下mex -setup,屏幕却给你回一句“找不到受支持的编译器”——那一刻的心情,我太熟悉了。明明VS2017就好好装在电脑上,MATLAB怎么就是看不见它?
这篇文章就把“MATLAB 2019a中添加Visual Studio 2017作为编译器”这件事,从原理、前期准备、完整操作到常见的坑,一次讲清楚。不管是刚接触MEX的新手,还是已经被这个问题折腾了一晚上的老伙计,照着步骤走,基本都能解决。
1. 为什么MATLAB 2019a需要“额外”寻找VS2017
1.1 MEX机制决定了编译器不能内置
先搞清楚一个最基本的问题:MATLAB本身是用C++写的,但它发布时不会自带一套完整的C/C++编译器工具链。你可能觉得奇怪,既然MATLAB自己就是用C++开发的,为什么不把MSVC那一套东西直接打包进来?答案是体积和授权都不允许,更重要的一点是,MEX文件的本质是动态链接库(在Windows上就是.mexw64文件),它必须和MATLAB进程内部的运行时符号兼容,这要求编译它的人和MATLAB官方构建使用的编译器体系尽量一致。
所以你需要在系统里先具备一个受支持的编译器,再用MATLAB的mex命令把它“认领”过来。这个过程说白了就是:告诉MATLAB“外部编译器在哪、怎么调用、有哪些参数”。MEX文件编译完成后,能在MATLAB里像普通函数一样被调用,性能比纯.m脚本高不少。
1.2 版本匹配表上的“官方指定”
MathWorks对每个MATLAB版本都有一张“受支持编译器”清单,R2019a在Windows平台上正式支持的C/C++编译器主要有:
- Microsoft Visual Studio 2017(15.x系列)
- Microsoft Visual Studio 2015
- MinGW-w64(GCC的Windows移植版)
注意,Visual Studio 2019并不在这张表里。那个版本是R2019b开始才正式支持的,很多人在2019a里装上VS2019配不上,原因就是版本太高,MATLAB的检测脚本根本不认。所以标题里选VS2017,其实是R2019a最稳妥的组合。若你问我VS2015行不行?也行,但VS2017的C++标准支持和第三方库兼容性明显更好,既然能装新的,就没必要迁就旧工具链。
顺带提醒一句,VS2017自己也有版本差异。Visual Studio 2017的更新推进到15.9之后,工具集版本是14.16系列。R2019a对这些更新都能正确识别,但如果你的VS2017停在15.0或者15.3这种老版本,个别情况下会出现兼容性毛病。有条件的话,尽量把VS2017更新到15.9。
1.3 为什么明明安装了却“消失”了
很多人的疑惑集中在这一点:VS2017我装了啊,凭什么认不出来?根据我折腾过的若干台电脑,原因无外乎以下三种:
- SQL数据库 / 组件缺失。安装VS2017时没有勾选“使用C++的桌面开发”工作负载,导致整个MSVC工具链压根没被安装,只有个空壳IDE。这种情况最普遍。
- 注册表检测失败。MATLAB扫描已安装编译器时,很大程度依赖Windows注册表里的安装信息,而不是简单查找安装目录。VS2017的一些定制安装、卸载残留、注册表清理工具,会把这些信息弄丢,于是MATLAB就像瞎子一样看不到VS。
- 位数不匹配。R2019a基本都是64位程序,它会去寻找64位版本的MSVC主机工具。如果只装了32位版本的工具集或者只留下了32位组件,检测同样会失败。
搞懂了这三个根源,接下来配置的时候思路就很清晰:先消除这些导致“看不见”的因素,再运行标准检测流程。
2. 动手前的自检清单:让VS2017现出原形
2.1 第一步,核实VS2017到底装了哪些组件
打开Visual Studio Installer(VS安装器),点击“修改”,在“工作负载”标签页里找到“使用C++的桌面开发”这一项,确认它是勾选状态。
勾选之后,还要看右侧“安装详细信息”里至少包含这两个子组件:
- 适用于v141生成工具的C++编译器(也就是MSVC v141编译工具集)
- Windows 10 SDK(或者Windows 8.1 SDK)
如果这两个子组件没被勾选,光是勾了工作负载也不保险。全部确认没问题后,点“修改”执行安装。这一步可能会让你重启系统,别嫌麻烦,编译器工具链安装不完整,后面只会浪费更多时间。
2.2 第二步,直接去文件系统里验证工具链
组件勾没勾对,嘴上说了不算,直接在资源管理器里看文件最踏实。VS2017的默认安装目录一般是:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC进去之后应该能看到一个类似14.16.27023的版本号目录。再往下一层,确认这个文件存在:
...\MSVC\14.16.27023\bin\Hostx64\x64\cl.execl.exe就是MSVC的C/C++编译器本体,如果你能看到这个文件,说明编译器本体是装了。再看Hostx64\x64这个路径,它代表64位主机下的64位目标工具,正是MATLAB R2019a需要的。如果你只看到bin\x86这种32位路径,那64位MATLAB大概率是找不到的。
Windows SDK的验证类似,默认路径通常在:
C:\Program Files (x86)\Windows Kits\10里面应该存在Include、Lib两个目录,分别放着SDK的头文件和库文件。
2.3 第三步,不要急着改环境变量
网上流传着一种做法:把MSVC的bin目录和SDK目录手动塞进系统Path环境变量,然后重启MATLAB再试。这种做法的初衷是让MATLAB“顺藤摸瓜”找到编译器,但我实测下来效果很不稳定,有时候反而导致检测逻辑出问题。
我的建议是:先不要动Path,把前面两步的自检做好,直接去跑mex -setup试试自动检测。绝大多数的机器,只要组件齐全、注册表信息完好,MATLAB自己就能找到VS2017,不需要你干预环境变量。改Path这类操作留到后面手动指定方案里再说,作为备选手段而不是第一步。
2.4 第四步,记录下你的版本号信息
这一步很多人忽略,却是排查时最省事的一步。在命令行窗口里依次执行:
"cmd /k set"不,不用那么复杂,MATLAB里直接运行:
matlabroot它会打印出MATLAB的安装根目录。这个路径很重要,因为后面手动指定配置文件、查看mexopts目录都要用到。同时把VS2017里看到的工具集版本号(如14.16.27023)记下来。后面凡是跟路径打交道的地方,都用这个真实版本号,别拿别人教程里的版本号照抄,不然路径对不上又会卡住。
3. 核心操作:把VS2017配置为MATLAB默认编译器
3.1 标准流程:一条命令搞定
先别想复杂了,最标准的做法其实就几行命令。以管理员身份启动MATLAB(右键→以管理员身份运行),在命令窗口输入:
mex -setupMATLAB会扫描系统里已安装且受支持的C编译器,并在命令窗口里列出可选项。正常情况下会出现类似:
MEX 配置为使用 'Microsoft Visual C++ 2017' 以进行 C 语言编译。如果系统里装了多个编译器,它会列出编号让你选。输入对应的编号,回车,就完成C编译器的配置。
紧接着,再把C++编译器也配置一次:
mex -setup C++为什么还要单独配C++?因为mex -setup默认只配C语言编译器,而很多MEX文件其实是C++写的,两者需要分别指定。这是新手最容易忽略的细节,漏掉这一步,后面编译.cpp文件时会提示找不到C++编译器。
3.2 列表里没有VS2017,怎么办
如果运行mex -setup后根本没有列出VS2017,甚至提示“没有找到支持的编译器”,先别急着用偏门方法,按顺序处理:
第一步,确认前文的自检清单全部通过。第二步,使用Visual Studio Installer对VS2017执行“修复”。修复会重新写入损坏或缺失的注册表信息,还能把漏掉的组件补齐,这一步能解决大半问题。第三步,修复完成后重启电脑,再打开MATLAB重新执行mex -setup。注意,不是重启VS,是重启整个系统,注册表层面的改动需要干净的环境才能生效。
如果走到这里仍然不行,试试用mex -setup -v查看详细日志:
mex -setup -v它会打印很多调试信息,包括MATLAB在扫描哪些注册表位置、寻找哪些编译器名称。你可以从中看到MATLAB期望的注册表路径到底在哪。对照日志你会明白,MATLAB对VS2017的检测其实依赖注册表HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\15.0这类位置的安装信息,一旦缺失,文件就算存在也白搭。
3.3 手动指定配置文件的兜底方案
前面的修复手段用遍还是不出现,那就轮到最直接的手动指定方案。R2019a的安装目录里自带了一份VS2017的编译配置文件,路径类似:
C:\Program Files\MATLAB\R2019a\bin\win64\mexopts\msvc2017.xml注意,前面的C:\Program Files\MATLAB\R2019a要以你实际的matlabroot结果为准。如果这个文件存在,直接在MATLAB里执行:
mex -setup:C:\Program Files\MATLAB\R2019a\bin\win64\mexopts\msvc2017.xmlMATLAB会读取该配置文件里的编译器路径和链接参数,并把它设为默认。如果提示文件不存在,用这个命令列一下实际有哪些配置文件:
dir(fullfile(matlabroot, 'bin', 'win64', 'mexopts', '*.xml'))看到msvc2017相关的文件名,把路径替换成真实的文件名再执行即可。
手动指定方案还有一个变体,通过设置环境变量来给MATLAB提供路径线索。新建系统环境变量VCToolsInstallDir,值设为你的MSVC工具集目录,例如:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023再建一个WindowsSdkDir,指向:
C:\Program Files (x86)\Windows Kits\10设置好之后重启MATLAB,再运行mex -setup。这个方法我在一些注册表信息丢失但又无法重装VS的机器上试过,有效果。不过要强调:环境变量里的版本号必须和你实际安装的完全一致,14.16.27023里的每个数字都不能错,拼错了等于白设,MATLAB照样找不到。
3.4 配置成功后最好再验证一遍
别以为看到“MEX配置为使用...”就万事大吉了。配置一个编译器,和真正编译出一个MEX文件,中间还隔着一整条工具链。最直接的验证方式是编译MATLAB自带的示例:
cd(fullfile(matlabroot, 'extern', 'examples', 'mex')) mex yprime.c如果这条命令能顺利执行,并在当前目录生成yprime.mexw64,说明VS2017与MATLAB的链路完全打通。这时再运行一下:
yprime(1, 1:4)能看到数值结果输出,就说明这个MEX函数不仅编译成功,运行也正常。走到这一步,你的“添加VS2017为编译器”才算真正完成。
4. 常见报错与排查技巧实录
配置编译器这件事,坑不浅。我把这几年在各种机器上遇到的典型报错和排查思路整理成一张速查表,不一定覆盖所有场景,但大概率能保住你的头发。
| 现象 | 根本原因 | 解决办法 |
|---|---|---|
mex -setup列出0个编译器 | MSVC工具集没装,或注册表信息被破坏 | 在VS Installer中补装C++桌面开发组件,执行修复 |
| 提示“找不到受支持的编译器” | VS版本太高(如2019)或太低,不在R2019a支持范围内 | 换装VS2017,或升级MATLAB到R2019b以上 |
编译时报未找到Windows SDK | VS安装时SDK组件缺失 | VS Installer里勾选Windows 10 SDK并安装 |
编译时报LNK1104: 无法打开文件 vcruntime.lib | mexopts.xml里的库路径指向了错误的VC工具集版本 | 重新运行mex -setup C++,确认版本号路径正确 |
编译时报'cl.exe' 不是内部或外部命令 | 环境变量Path里没包含MSVC工具集 | 设置VS相关环境变量,或使用“开发人员命令提示符”编译 |
| 配置成功但每次重启MATLAB丢失 | 配置文件只对当前会话生效 | 确认配置文件被写入prefdir下的mexopts目录,并设为默认 |
| 编译成功但调用时MATLAB崩溃 | MEX文件用了不同运行时库 | 检查MEX编译选项是否使用了-R2017b或对应API版本,统一运行时库 |
重点解释一下LNK1104这个错误。它很具迷惑性,因为配置阶段一切正常,mex -setup也认了VS2017,可一到编译链接阶段就报“打不开vcruntime.lib”。这其实是因为VS2017在升级到15.9之后,工具集版本目录变了,而MATLAB加载的配置文件里还残留着旧版本号路径。解决办法很简单:重新执行一次mex -setup C++,让MATLAB重新解析一遍当前编译器信息。
还有一个实例很典型。某同学的电脑上同时装了VS2015和VS2017,mex -setup默认选了VS2015,虽然能编译,但某个第三方库要求必须使用VS2017生成的MEX。这种多版本共存的情况很好处理,重新运行mex -setup,在列出的多个编译器中手动选VS2017对应的编号即可。真正容易忽略的是,如果C和C++编译器设置了不同的工具链(比如C用VS2015、C++用VS2017),编译一些混合代码时会莫名其妙报错,所以一定要保证C和C++都指向同一个VS2017。
还有一类我遇到过多次的情况:配好之后一切正常,但过了几天重开MATLAB,又回到了“没有找到编译器”的状态。多数原因是VS2017偷偷做了更新,更新过程会重写自身注册表和文件结构,导致MATLAB缓存的配置失效。解决办法是重新执行mex -setup,很快就能恢复。如果不想频繁出问题,可以在VS安装器里把更新策略改成手动更新,至少别让它在后台自动升级。
5. 配置完成后的稳定性和扩展建议
编译器配置好了,不代表永远不碰它。我在实际项目里发现几条值得养成的习惯:
一是严格区分“配置”和“编译”两个阶段。配置成功只是说明mex -setup能识别编译器,真正编译MEX时可能还会遇到头文件路径、库路径问题。遇到编译失败时,先看mex -setup -v输出的详细路径,确认每个-I、-L参数指向的目录都是真实存在的。二是在项目文件夹里保留一份编译说明,记清楚你的MATLAB版本、VS版本、工具集版本号和SDK版本。这些东西一旦换机器,几乎必出问题,留个记录能少走很多弯路。
另外,如果你只是偶尔编几个MEX文件,实在不想装完整的Visual Studio IDE,可以考虑使用Visual Studio Build Tools 2017。这个版本不包含图形界面编辑器,只提供编译工具链,体积小得多,同样能提供MSVC v141工具集和Windows SDK,R2019a也能识别它。我曾在配置相对精简的机器上用过这个方案,功能上没觉得有缺,适合对IDE没需求的人。
第三个小建议,可能有点偏,但很实用:把mex -setup的运行结果和yprime.c的编译测试写成一两行脚本,每次配置完自动执行一遍。比如写一个checkMexSetup.m:
mex -setup mex -setup C++ cd(fullfile(matlabroot, 'extern', 'examples', 'mex')) mex yprime.c disp('Compiler setup OK');以后换机器、重装系统、升级VS,跑一遍这个脚本,几秒钟就能确认整个工具链是否正常。我被坑过太多次,现在每在一台新机器上配好环境,第一件事就是跑这个脚本,确认没问题再开始干活。
最后再分享一个个人习惯:我会在记事本里记下每个环境的编译器版本号组合,比如某台老机器用的是R2019a + VS2017 15.9.7 + MSVC 14.16.27023 + Windows SDK 10.0.17763.0。下次再配类似的机器,直接按这个组合选版本,比临时摸索高效得多。编译环境这种东西,版本匹配永远是第一位的,一个数字不对,后面全是坑。配过一次VS2017和R2019a的组合,再遇到其他版本的MATLAB配编译器,套路就熟了:先看支持列表,再查组件完整性,最后走mex -setup,三步走下来,基本没有搞不定的。