一、开篇 在QtCreator中使用MSVC编译套件构建项目时,在Kits对话框中编译器一栏会识别出许多MSVC编译套件,实际项目开发中,如何选择这些编译套件呢,本文就这个问题展开,主要内容如下: (1)描述VisualStudio下的命令行工具的环境变量和几种命令提示符。 (2)描述VisualStudio的命令文件。 (3)描述QtCreator对MSVC编译套价的识别。 (注1:本文的前提是已经完成对VisualStudio集成开发工具的安装,如果没有安装,QtCreator将会找不到MSVC相关的编译套件!) (注2:本文基于完整安装的VisualStudio集成开发工具。单独安装MSVC编译套件不在本文讨论范围内!哈哈)二、VisualStudio命令行生成的路径和环境变量 MSVC的命令行工具会使用PATH、TMP、INCLUDE、LIB和LIBPATH环境变量,还会使用一些特定的已安装工具、平台和SDK的环境变量。即使是简单VisualStudio安装,也会设置二十多个或更多的环境变量。这些环境变量非常多,所以如果在Windows环境变量中自行单个添加,可能会把自己折腾惨,哈哈!所以在使用MSVC的命令行工具时,必须使用命令提示符快捷方式或自定义命令文件来设置环境变量。不建议在Windows环境中自行设置环境变量。 在windows的命令行和MSVC命令行下分别输入set命令,可以查看环境变量,如下图所示: 左边是windows的命令行,右边是MSVC命令行,可见在MSVC命令行下新建了许多环境变量(PATH、TMP、INCLUDE、LIB和LIBPATH)且添加了很多值。这些环境变量,在我们使用命令行来构建项目工程时,都会使用到,缺一不可!三、VisualStudio命令提示符 命令提示符本质是对windows命令行的一个脚本。在安装VisualStudio后,命令提示符快捷方式会安装在Windows开始菜单中特定版本的VisualStudio文件夹中,大致结构如下:x86本机工具命令提示符将环境设置为使用32位x86本机工具生成32位x86本机代码。x64本机工具命令提示符将环境设置为使用64位x64本机工具生成64位x64本机代码。x86x64兼容工具命令提示符将环境设置为使用64位x64本机工具生成32位x86本机代码。x64x86兼容工具命令提示符将环境设置为使用64位x64本机工具生成32位x86本机代码。 (注:由于选择的工具负载不同,命令提示符会有所不同,本文选择的是C桌面应用构建相关的负载,且只选择了几种工具套件组合) 安装后,结果如下图所示: 【备注】多个命令行工具或工具选项可能需要管理员权限。如果在使用这些命令行时遇到权限问题,建议使用以管理员身份运行选项打开开发人员命令提示窗口。右键单击以打开命令提示窗口的快捷菜单,然后依次选择更多、以管理员身份运行。四、VisualStudio命令文件位置 对于2019VisualStudio,64位系统上的典型安装位置是位于ProgramFilesMicrosoftVisualStudio2022下,其中可能是Community、Professional、Enterprise、BuildTools或自定义名称。 开发人员的命令提示符命令文件VsDevCmd。bat位于Common7Tools子目录中。如果未指定参数,该命令文件会设置使用x86生成32位x86代码的开发环境。 命令文件将设置默认参数并调用VsDevCmd。bat脚本去设置指定的生成体系结构环境。典型安装可能包括以下命令文件: 注意vcvarsall。bat文件和其他VisualStudio命令文件可能因计算机而异。不要使用另一台计算机中的文件替换已经丢失或损坏的vcvarsall。bat文件。需要重新运行VisualStudio安装程序来替换丢失的文件。vcvarsall。bat文件在不同的版本中也会有所不同。如果安装了当前版本VisualStudio的计算机上也安装了VisualStudio的早期版本,则不要在同一命令提示符窗口中运行不同版本的vcvarsall。bat或其他VisualStudio命令文件。 vcvarsall。bat是Windows下的批处理命令,如下脚本代码所示(不同版本的VisualStudio会有所不同):ifnotVSCMDDEBUGGEQ3echooffREM:parseargssetVCVARSALLSTOREsetVCVARSALLWINSDKsetVCVARSALLPARSEERRORsetVCVARSALLTARGETARCHsetVCVARSALLHOSTARCHsetVCVARSALLVERREMParsecommandlinearguments。ThisimplementationdoesnotcareaboutREMargumentorder。ifVSCMDDEBUGGEQ1(echo〔DEBUG:nx0〕initwitharguments)setVCVARSALLPARSEERROR0setVCVARSALLARGSLISTcall:parseloopsetVCVARSALLARGSLISTifVSCMDDEBUGGEQ1(echo〔DEBUG:nx0〕Commandlineparsecompletedwithvalues:echo〔DEBUG:nx0〕VCVARSALLTARGETARCHVCVARSALLTARGETARCHecho〔DEBUG:nx0〕VCVARSALLHOSTARCHVCVARSALLHOSTARCHecho〔DEBUG:nx0〕VCVARSALLWINSDKVCVARSALLWINSDKecho〔DEBUG:nx0〕VCVARSALLSTOREVCVARSALLSTOREecho〔DEBUG:nx0〕VCVARSALLHELPVCVARSALLHELPecho〔DEBUG:nx0〕VCVARSALLPARSEERRORVCVARSALLPARSEERROR)ifVCVARSALLCLEANENVNEQgoto:callvsdevcmdifVCVARSALLPARSEERRORNEQ0goto:usageerrorifVCVARSALLHELPNEQgoto:usageREM:checkplatformREMThisscriptisinstalledto。。。VCAuxiliaryBuild。REMvsdevcmdisinstalledto。。。Common7Tools。ifnotexistdp0。。。。。。Common7Toolsvsdevcmd。batgotomissingREMAssembletheargumentstopasstovsdevcmd。batifVCVARSALLTARGETARCHgoto:usageerrorifVCVARSALLHOSTARCHgoto:usageerrorsetVCVARSALLVSDEVCMDARGSarchVCVARSALLTARGETARCHhostarchVCVARSALLHOSTARCHifVCVARSALLWINSDKNEQ(setVCVARSALLVSDEVCMDARGSVCVARSALLVSDEVCMDARGSwinsdkVCVARSALLWINSDK)ifVCVARSALLSTORENEQ(setVCVARSALLVSDEVCMDARGSVCVARSALLVSDEVCMDARGSappplatformUWP)ifVCVARSALLVERNEQ(setVCVARSALLVSDEVCMDARGSVCVARSALLVSDEVCMDARGSvcvarsverVCVARSALLVER)ifVCVARSALLSPECTRENEQ(setVCVARSALLVSDEVCMDARGSVCVARSALLVSDEVCMDARGSvcvarsspectrelibsVCVARSALLSPECTRE)goto:callvsdevcmdREMREMCallvsdevcmd。battosetupthecommandpromptenvironment:callvsdevcmdREMThistemporaryenvironmentvariableisusedtocontrolsettingofVCREMcommandpromptspecificenvironmentvariablesthatshouldnotbesetREMbytheVSDeveloperCommandprompt(specificallyvsdevcmdextvcvars。bat)。REMTheknowncasethiseffectsisthePlatformenvironmentvariable,whichREMwilloverrideplatformtargetfor。NETbuilds。setVSCMDVCVARSALLINIT1REMSpecialhandlingforthecleanenvargumentifVCVARSALLCLEANENVNEQ(calldp0。。。。。。Common7Toolsvsdevcmd。batcleanenvgoto:end)calldp0。。。。。。Common7Toolsvsdevcmd。batVCVARSALLVSDEVCMDARGSifERRORLEVEL0(REMPrintthetargetcommandpromptarchitecture。。。ifVCVARSALLHOSTARCHNEQVCVARSALLTARGETARCH(echo〔nx0〕Environmentinitializedfor:VCVARSALLHOSTARCHVCVARSALLTARGETARCH)else(echo〔nx0〕Environmentinitializedfor:VCVARSALLTARGETARCH))goto:end:parseloopforFtokens1,delimsain(VCVARSALLARGSLIST)do(ifVSCMDDEBUGGEQ2(echo〔DEBUG:nx0〕innerargument{a})call:parseargumentasetVCVARSALLARGSLISTbgoto:parseloop)exitB0:parseargumentREMcalledby:parseloopandexpectstheargumentstoeitherbe:REM1。asingleargumentin1REM2。anargumentpairfromthecommandlinespecifiedas12setlocalARGFOUNDREMArchitectureifI1x86(setVCVARSALLTARGETARCHx86setVCVARSALLHOSTARCHx86setlocalARGFOUND1)ifI1x86amd64(setVCVARSALLTARGETARCHx64setVCVARSALLHOSTARCHx86setlocalARGFOUND1)ifI1x86x64(setVCVARSALLTARGETARCHx64setVCVARSALLHOSTARCHx86setlocalARGFOUND1)ifI1x86arm(setVCVARSALLTARGETARCHarmsetVCVARSALLHOSTARCHx86setlocalARGFOUND1)ifI1x86arm64(setVCVARSALLTARGETARCHarm64setVCVARSALLHOSTARCHx86setlocalARGFOUND1)ifI1amd64(setVCVARSALLTARGETARCHx64setVCVARSALLHOSTARCHx64setlocalARGFOUND1)ifI1x64(setVCVARSALLTARGETARCHx64setVCVARSALLHOSTARCHx64setlocalARGFOUND1)ifI1amd64x86(setVCVARSALLTARGETARCHx86setVCVARSALLHOSTARCHx64setlocalARGFOUND1)ifI1x64x86(setVCVARSALLTARGETARCHx86setVCVARSALLHOSTARCHx64setlocalARGFOUND1)ifI1amd64arm(setVCVARSALLTARGETARCHarmsetVCVARSALLHOSTARCHx64setlocalARGFOUND1)ifI1x64arm(setVCVARSALLTARGETARCHarmsetVCVARSALLHOSTARCHx64setlocalARGFOUND1)ifI1amd64arm64(setVCVARSALLTARGETARCHarm64setVCVARSALLHOSTARCHx64setlocalARGFOUND1)ifI1x64arm64(setVCVARSALLTARGETARCHarm64setVCVARSALLHOSTARCHx64setlocalARGFOUND1)ifI1vcvarsver(setVCVARSALLVER2setlocalARGFOUND1)ifI1vcvarsver(setVCVARSALLVER2setlocalARGFOUND1)ifI1vcvarsver(setvcvarsallver2setlocalARGFOUND1)ifI1vcvarsspectrelibs(setVCVARSALLSPECTRE2setlocalARGFOUND1)ifI1vcvarsspectrelibs(setVCVARSALLSPECTRE2setlocalARGFOUND1)ifI1vcvarsspectrelibs(setvcvarsallSPECTRE2setlocalARGFOUND1)ifI1help(setVCVARSALLHELP1setlocalARGFOUND1)ifI1help(setVCVARSALLHELP1setlocalARGFOUND1)ifI1help(setVCVARSALLHELP1setlocalARGFOUND1)ifI1?(setVCVARSALLHELP1setlocalARGFOUND1)ifI1?(setVCVARSALLHELP1setlocalARGFOUND1)REMcleanenvREMMostlyusedforinternaltestingtorestorethestateofREMthecommandlineenvironmenttoitsstatepriortovcvarsall。batREMbeingexecuted。ifI1cleanenv(setVCVARSALLCLEANENVcleanenvsetlocalARGFOUND1)ifI1cleanenv(setVCVARSALLCLEANENVcleanenvsetlocalARGFOUND1)REMWindowsSDKVersionifI18。1(setVCVARSALLWINSDK8。1setlocalARGFOUND1)settemp11ifItemp1:0,310。(setVCVARSALLWINSDK1setlocalARGFOUND1)settemp1REMStoreUWPifI1store(setVCVARSALLSTOREappplatformUWPsetlocalARGFOUND1)ifI1uwp(setVCVARSALLSTOREappplatformUWPsetlocalARGFOUND1)iflocalARGFOUNDNEQ1(setAVCVARSALLPARSEERRORVCVARSALLPARSEERROR1if2(echo〔ERROR:nx0〕Invalidargumentfound:1)else(echo〔ERROR:nx0〕Invalidargumentfound:12))setlocalARGFOUNDexitB0:usageerrorecho〔ERROR:nx0〕Errorinscriptusage。Thecorrectusageis:goto:usage:usageechoSyntax:echonx0〔arch〕〔platformtype〕〔winsdkversion〕〔vcvarsvervcversion〕〔vcvarsspectrelibsspectremode〕echowhere:echo〔arch〕:x86amd64x86amd64x86armx86arm64amd64x86amd64armamd64arm64echo〔platformtype〕:{empty}storeuwpecho〔winsdkversion〕:fullWindows10SDKnumber(e。g。10。0。10240。0)or8。1tousetheWindows8。1SDK。echo〔vcversion〕:{none}forlatestinstalledVCcompilertoolsetecho14。0forVC2015CompilerToolsetecho14。xxforthelatest14。xx。yyyyytoolsetinstalled(e。g。14。11)echo14。xx。yyyyyforaspecificfullversionnumber(e。g。14。11。25503)echo〔spectremode〕:{none}forlibrarieswithoutspectremitigationsechospectreforlibrarieswithspectremitigationsecho:echoThestoreparametersetsenvironmentvariablestosupportUniversalWindowsPlatformapplicationechodevelopmentandisanaliasforuwp。echo:echoForexample:echonx0x86amd64echonx0x86amd6410。0。10240。0echonx0x86armuwp10。0。10240。0echonx0x86armonecore10。0。10240。0vcvarsver14。0echonx0x648。1echonx0x64store8。1echo:echoPleasemakesureeitherVisualStudioorCBuildSKUisinstalled。goto:end:missingechoThespecifiedconfigurationtypeismissing。Thetoolsfortheechoconfigurationmightnotbeinstalled。goto:end:endsetVCVARSALLTARGETARCHsetVCVARSALLHOSTARCHsetVCVARSALLSTOREsetVCVARSALLWINSDKsetVCVARSALLPARSEERRORsetVCVARSALLCLEANENVsetVSCMDVCVARSALLINITsetVCVARSALLVSDEVCMDARGSsetVCVARSALLHELPsetVCVARSALLVERsetVCVARSALLSPECTRE五、QtCreator设置MSVC编译套件分析 QtCreator对MSVC编译套件的识别,是通过VisualStudio的命令文件vcvarsall。bat来实现的。例如下图: 且每一种编译套件都会使用到该命令文件,然后将对应的参数传递给该批处理文件! (注:小生安装了多个版本的VisualStudio,所以在QtCreator自动检测MSVC编译套件时识别到多种不同类型的编译套件) 上图中,每一项后面的括号中的内容,则代表了该种编译套件的运行宿主机和生成程序的目标平台。具体含义参见本文第二小节内容啦。例如:如果我们的平台是x8632位宿主机,生成的代码同样需要运行在x8632位的目标计算机上,故需要选择x86的编译套件。其他编译套件以此类推! 也可以在VisualStudio中搭建Qt的开发环境,但是小生还是比较喜欢QtCreator,工具而已,喜欢就好!