MATLAB R2023b配置Fortran编译器
- 引言
 - 1. 安装Visual Studio 2019
 - 2. 安装Intel API2024
 - 3. 配置xml文件文件
 - 4. 设置环境变量
 - 5. MATLAB编译Fortran
 
引言
当我们需要用到MATLAB编译Fortran代码后进行调用计算时,整个配置流程较繁琐。下面以MATLAB R2023b为例,介绍配置Fortran编译器的流程以及中间可能遇到的问题。
 我的版本:
 MATLAB R2023b:”https://mp.weixin.qq.com/s/KclU24GCUQj70j1s_cqE2g“
 Visual Studio 2019:”https://mp.weixin.qq.com/s/Pc5U7lBrhUq06MYj6hSJWw“,(或:”https://learn.microsoft.com/zh-cn/visualstudio/releases/2019/release-notes”)
 w_BaseKit_p_2024.2.1.101_offline.exe:”https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit-download.html“
 w_BaseKit_p_2024.2.1.101_offline.exe:”https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit-download.html“
1. 安装Visual Studio 2019
我尝试了使用Visual Studio 2022进行配置,但是出现了在MATLAB中使用MEX -setup命令,能够正常显示编译器,但是在使用MEX编译Fortran代码时出现了“错误使用 mex ‘ifx’ 不是内部或外部命令,也不是可运行的程序 或批处理文件”的提示,具体原因可能是”G:\Program Files (x86)\Intel\oneAPI\compiler\2024.2\bin“文件夹中的ifx.exe不能识别,未找到解决办法。因此就选择卸载VS2022,重新安装VS2019。
VS2019安装包在如下链接可以下载:https://mp.weixin.qq.com/s/Pc5U7lBrhUq06MYj6hSJWw
但是在下载的过程中又出现了下载速度贼慢的问题。后来按照网上检索的一个修改hosts的办法,亲测有效,如果没有遇到这个问题可直接跳过,进行第2步。
 1.使用DNS查找工具网站”https://tool.chinaz.com/dns/?type=1&host=download.visualstudio.microsoft.com&ip=“,查询微软的下载网站的域名 download.visualstudio.microsoft.com 找到TTL最低的那个节点。
 
 2.找到TTL值最小的那个节点,复制IP地址,在我这里对应的最小IP就是 103.208.44.30。如下所示:
 
 3.以记事本形式,打开”C:\Windows\System32\drivers\etc“文件夹下的hosts文件,在hosts里加入 IP地址+微软的下载网站的域名
 
 这里可能需要另存后,再复制粘贴进这个文件夹里。
 
 3.打开cmd,刷新dns,然后在ping一下微软的下载地址,查看hosts文件有没有生效。具体步骤如下:
 (1)在cmd中输入ipconfig /flushdns 刷新dns
 (2)ping微软的下载地址,在cmd中输入:
 ping download.visualstudio.microsoft.com
 (3)若没有丢包,且往返时间很小,则说明我们的hosts文件生效。
 
 经过上述操作,VS2019的下载速度会非常快。
 安装流程完全按照”https://mp.weixin.qq.com/s/Pc5U7lBrhUq06MYj6hSJWw“所提供的步骤来就行了。
2. 安装Intel API2024
- 先安装the Intel® oneAPI Base Toolkit:”https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit-download.html“
 - 再安装the Intel® HPC Toolkit:”https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit-download.html“
 - 安装步骤很简单,修改安装路径,其他默认即可。
 - 最后打开Visual Studio 2019,看到Fortran一项即说明安装配置成果。

 
3. 配置xml文件文件
然后,需要添加intel_fortran_24_vs2019.xml文件。由于我用的是Intel API2024+visual studio 2019,所以在我的MATLAB安装路径”G:\MATLAB R2023b\bin\win64\mexopts“下需要有intel_fortran_24_vs2019.xml文件,这个文件matlab2023b是没有的。可将下面代码复制粘贴到记事本,再重命名为”intel_fortran_24_vs2019.xml“即可:
<?xml version="1.0" encoding="UTF-8" ?>
<config
    Name="Intel oneAPI 2024 for Fortran with Microsoft Visual Studio 2019"
    ShortName="INTELF24MSVS2019"
    Manufacturer="Intel"
    Version="24.0"
    Language="FORTRAN"
    Priority="X"
    Location="$FORTRANROOT" >
    <Details
        CompilerExecutable="$COMPILER"
        CompilerDefines="$COMPDEFINES"
        CompilerFlags="$COMPFLAGS"
        OptimizationFlags="$OPTIMFLAGS"
        DebugFlags="$DEBUGFLAGS"
        IncludeFlags="$INCLUDE"
        LinkerExecutable="$LINKER"
        LinkerFlags="$LINKFLAGS"
        LinkerLibraries="$LINKLIBS"
        LinkerDebugFlags="$LINKDEBUGFLAGS"
        LinkerOptimizationFlags="$LINKOPTIMFLAGS"
        CommandLineShell="$FORTRANROOT\env\vars.bat "
        CommandLineShellArg="intel64"
        CompilerDefineFormatter="/D%s"
        LinkerLibrarySwitchFormatter="lib%s.lib;%s.lib"
        LinkerPathFormatter="/LIBPATH:%s"
        LibrarySearchPath="$$LIB;$$LIBPATH;$$PATH;$$INCLUDE;$MATLABROOT\extern\lib\$ARCH\microsoft"
        />
    <!-- Switch guide: http://msdn.microsoft.com/en-us/library/fwkeyyhe(v=vs.71).aspx -->
    <vars
        CMDLINE100="$COMPILER /c $COMPFLAGS $OPTIM $SRC /Fo$OBJ"
        CMDLINE200="$LINKER $LINKFLAGS $LINKTYPE $LINKOPTIM $LINKEXPORTVER $OBJS $LINKLIBS /out:$EXE"
        CMDLINE300="del $EXP $LIB $ILK"
FORTRANROOT="$ONE_API_ROOT/compiler/$ONE_API_VERSION"
COMPILER="ifx.exe"
COMPFLAGS="/nologo /fpp /fixed /MD /fp:source /assume:bscc $INCLUDE  $COMPDEFINES"
COMPDEFINES="/DMATLAB_MEX_FILE"
MATLABMEX=" /DMATLAB_MEX_FILE"
OPTIMFLAGS="/O2 /DNDEBUG"
INCLUDE="-I"$MATLABROOT\extern\include""
DEBUGFLAGS="/Z7"
 
LINKER="link"
LINKFLAGS=" /nologo  /INCREMENTAL:NO"
LINKTYPE="/DLL"
LINKEXPORT="/EXPORT:MEXFUNCTION"
LINKEXPORTVER="/EXPORT:MEXFUNCTION /EXPORT:MEXFILEREQUIREDAPIVERSION"
LINKLIBS="/LIBPATH:"$MATLABROOT\extern\lib\$ARCH\microsoft" libmx.lib libmex.lib libmat.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
LINKDEBUGFLAGS="/debug /PDB:"$TEMPNAME$LDEXT.pdb""
LINKOPTIMFLAGS=""
 
OBJEXT=".obj"
LDEXT=".mexw64"
SETENV="set COMPILER=$COMPILER
        set COMPFLAGS=/c $COMPFLAGS $COMPDEFINES $MATLABMEX
        set OPTIMFLAGS=$OPTIMFLAGS
        set DEBUGFLAGS=$DEBUGFLAGS
        set LINKER=$LINKER
        set LINKFLAGS=$LINKFLAGS /export:%ENTRYPOINT% $LINKTYPE $LINKLIBS $LINKEXPORT
        set LINKDEBUGFLAGS=/debug /PDB:"%OUTDIR%%MEX_NAME%$LDEXT.pdb"
        set NAME_OUTPUT=/out:"%OUTDIR%%MEX_NAME%%MEX_EXT%""
/>
    <client>
        <engine
            CMDLINE300="if exist $ILK del $ILK"
            LINKLIBS="$LINKLIBS libeng.lib"
            LINKEXPORT="/subsystem:console"
            LINKEXPORTVER="/subsystem:console"
            LDEXT=".exe"
            LINKTYPE=""
            MATLABMEX=""
            />
    </client>
    <locationFinder>
        
        <ONE_API_ROOT>
            <envVarExists name="ONEAPI_ROOT" />
        </ONE_API_ROOT>
        <ONE_API_VERSION>
            <and>
                <envVarExists name="ONEAPI_ROOT" />
                <cmdReturns name ="echo off & (for /f %a IN ('dir "$$\compiler\2024*" /b /ad /on') do (@if exist "$$\compiler\%a\bin\ifx.exe" set "oneapiVer=%a")) & (@if defined oneapiVer call echo %oneapiVer%)"/>
            </and>
        </ONE_API_VERSION>
        <VCROOT>
            <or>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
                    <cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%" />
                </and>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
                    <cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%" />
                </and>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
                    <cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%" />
                </and>
            </or>
        </VCROOT>
        <SDKROOT>
            <or>
                <hklmExists path="SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
                <hkcuExists path="SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
                <hklmExists path="SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
                <hkcuExists path="SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
            </or>
        </SDKROOT>
        <VSINSTALLDIR>
            <or>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
                </and>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
                </and>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
                </and>
            </or>
        </VSINSTALLDIR>
        <VCINSTALLDIR>
            <or>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
                    <cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%\VC\Tools\MSVC\%a" />
                </and>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
                    <cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%\VC\Tools\MSVC\%a" />
                </and>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
                    <cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%\VC\Tools\MSVC\%a" />
                </and>
            </or>
        </VCINSTALLDIR>
        <VCVARSALLDIR>
            <or>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
                    <fileExists name="$$\VC\Auxiliary\Build\vcvarsall.bat" />
                    <dirExists name="$$"/>
                </and>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
                    <fileExists name="$$\VC\Auxiliary\Build\vcvarsall.bat" />
                    <dirExists name="$$"/>
                </and>
                <and>
                    <envVarExists name="ProgramFiles(x86)" />
                    <fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
                    <cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
                    <fileExists name="$$\VC\Auxiliary\Build\vcvarsall.bat" />
                    <dirExists name="$$"/>
                </and>
            </or>
        </VCVARSALLDIR>
        <KITSROOT>
            <or>
                <hklmExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
                <hkcuExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
                <hklmExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
                <hkcuExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
 
            </or>
        </KITSROOT>
        <SDKVERSION>
            <and>
                <or>
                    <hklmExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
                    <hkcuExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
                    <hklmExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
                    <hkcuExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
 
                </or>
                <!-- For each folder inside '<KITSROOT>\include' check for 'ucrt' and if exists return that folder name -->
                <cmdReturns name="echo off&set "sdkversion="&(for /f %a IN ('dir "$$\include\" /b /ad-h /on') do ( @if exist "$$\include\%a\ucrt\" set "sdkversion=%a" ))&call echo %sdkversion%" />
            </and>
        </SDKVERSION>
    </locationFinder>
    <env
        PATH="$FORTRANROOT\bin;$VCINSTALLDIR\bin\HostX64\x64\;$VCROOT\Common7\IDE\VC\vcpackages;$VCROOT\Common7\IDE;$VCROOT\Common7\Tools;$SDKROOT\Bin\$SDKVERSION\x64;$SDKROOT\Bin\$SDKVERSION\x86;$SDKROOT\Bin\x64;$SDKROOT\Bin\x86;"
        INCLUDE="$FORTRANROOT\include;$VCINSTALLDIR\include;$VCINSTALLDIR\atlmfc\include;$KITSROOT\include\$SDKVERSION\ucrt;$KITSROOT\include\$SDKVERSION\shared;$KITSROOT\include\$SDKVERSION\um;$KITSROOT\include\$SDKVERSION\winrt;$MATLABROOT\extern\include"
        LIB="$FORTRANROOT\lib;$VCINSTALLDIR\lib\x64;$VCINSTALLDIR\atlmfc\lib\x64;$KITSROOT\Lib\$SDKVERSION\ucrt\x64;$KITSROOT\lib\$SDKVERSION\um\x64;$MATLABROOT\lib\$ARCH"
        LIBPATH="$FORTRANROOT\lib;$VCINSTALLDIR\lib\x64;$VCINSTALLDIR\atlmfc\lib\x64"
        />
</config>
 
4. 设置环境变量
变量值是安装oneAPI地址
 
5. MATLAB编译Fortran
输入命令:mex -setup FORTRAN
 输入编译的Fortran代码:mex ‘DC3D0wrapper.F’
 
 在文件夹中生成了一个后缀”.mexw64“的文件,即表示编译成功!



















