ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

VS编译环境命令窗口:命令行编译与自动化构建实战指南

VS编译环境命令窗口:命令行编译与自动化构建实战指南

1. 被忽视的效率利器:VS编译环境命令窗口

很多人装了Visual Studio之后,日常操作就是打开IDE、点按钮、等编译、看输出,一套流程走下来行云流水,但一旦离开那个图形界面,就不知道该怎么办了。其实VS安装包里藏着一个非常实用的工具——VS编译环境命令窗口(也叫开发者命令提示符),它能让你在纯命令行环境下调用MSVC编译器、链接器、构建工具以及各种SDK工具,不需要打开庞大的IDE就能完成编译、调试、部署等一系列操作。

我第一次认真用这个工具,是因为要做一个自动化构建脚本。当时项目需要在多台机器上批量编译,如果每台都打开IDE手动操作,效率低得让人抓狂。后来发现VS自带的命令行环境可以直接调用cl.exe、link.exe、msbuild.exe这些工具,配合批处理脚本,整个流程从半小时压缩到了几分钟。从那以后,这个命令窗口就成了我工具箱里的常客。

这篇文章适合几类人看:一是想了解VS命令行编译原理的开发者;二是需要做自动化构建、持续集成的工程师;三是日常用IDE但想拓展技能边界的技术爱好者。我会从环境配置、核心命令、实操流程、常见问题几个维度展开,把踩过的坑和总结的技巧都分享出来。不管你是刚接触命令行编译的新手,还是有一定经验的老手,应该都能从中找到有用的东西。

2. 环境搭建与工具链解析

2.1 命令窗口的几种打开方式与区别

VS编译环境命令窗口并不是一个独立的可执行文件,而是一组批处理脚本,它们的作用是设置环境变量,让系统能找到编译器、链接器、头文件和库文件。不同版本的VS、不同的目标架构,对应的脚本也不一样。

常见的打开方式有这几种:

  • 开始菜单快捷方式:在Windows开始菜单里搜索“Developer Command Prompt”或“开发者命令提示符”,能找到对应VS版本的快捷方式。点击后会打开一个已经配置好环境的cmd窗口。
  • 从VS IDE内部打开:在VS菜单栏选择“工具”→“命令行”→“开发者命令提示符”,可以直接在IDE里打开一个配置好的命令行窗口。
  • 手动调用批处理脚本:在任意cmd窗口中运行VS安装目录下的VsDevCmd.bat或vcvarsall.bat,手动初始化环境。这种方式最灵活,适合集成到自定义脚本中。

这几种方式的核心区别在于环境变量的作用范围。快捷方式打开的窗口,环境变量只在当前窗口有效;手动调用脚本的方式,可以在同一个cmd会话中切换不同的目标架构,比如先配置x64环境编译64位程序,再切换到x86环境编译32位程序。

注意:如果你在同一个cmd窗口里多次调用vcvarsall.bat切换架构,后一次调用会覆盖前一次的环境变量,但不会清除之前设置的路径。这可能导致路径冲突,建议每次切换架构时开一个新的cmd窗口。

2.2 vcvarsall.bat 参数详解与架构选择

vcvarsall.bat是环境配置的核心脚本,它接受多个参数来指定目标平台和工具集版本。基本语法是:

vcvarsall.bat [architecture] [platform_type] [winsdk_version] [-vcvars_ver=vc_version]

其中architecture参数决定了编译目标架构,常用的取值包括:

参数值含义适用场景
x8632位x86架构编译32位程序,兼容性最好
x6464位x64架构编译64位程序,主流选择
x86_amd64交叉编译:在32位主机上编译64位程序旧机器上编译64位程序
x86_arm交叉编译:x86主机编译ARM程序嵌入式开发
x64_arm64交叉编译:x64主机编译ARM64程序新一代ARM平台开发
arm64原生ARM64编译ARM64设备上的原生开发

platform_type参数用于指定Windows SDK的版本,一般不需要手动指定,脚本会自动选择最新版本。-vcvars_ver参数可以指定使用特定版本的编译器工具集,比如-vcvars_ver=14.29会使用VS2019的编译器。

我个人的习惯是:日常开发用x64,需要兼容老系统时用x86,做跨平台项目时根据目标平台选择对应的交叉编译参数。如果你不确定该用哪个,先用x64试试,大部分现代项目都支持64位。

2.3 环境变量背后的逻辑

调用vcvarsall.bat之后,脚本会设置一系列环境变量,这些变量是编译器正常工作的基础。理解它们的作用,能帮你在遇到问题时快速定位。

核心环境变量包括:

  • PATH:添加编译器、链接器、构建工具的路径,让系统能找到cl.exe、link.exe、msbuild.exe等可执行文件。
  • INCLUDE:头文件搜索路径,编译器在预处理阶段会按顺序在这些目录中查找#include引用的头文件。
  • LIB:库文件搜索路径,链接器在链接阶段会在这里查找.lib文件。
  • LIBPATH:额外的库搜索路径,通常用于.NET程序集。
  • WindowsSdkDir:Windows SDK的安装根目录。
  • VCToolsInstallDir:VC编译器工具集的安装目录。

这些变量的值取决于你选择的架构和VS版本。比如选择x64架构时,INCLUDE会包含VC\Tools\MSVC\<版本>\include和Windows Kits\10\Include\<SDK版本>\ucrt等目录。

实操心得:如果你在命令行编译时遇到“找不到xxx.h”或“无法打开xxx.lib”的错误,第一反应应该是检查INCLUDE和LIB变量是否正确设置。可以用echo %INCLUDE%和echo %LIB%查看当前值,对比正常环境下的输出,很快就能发现问题。

3. 核心命令与编译流程拆解

3.1 cl.exe 编译器命令的常用参数

cl.exe是MSVC的编译器前端,负责把C/C++源代码编译成目标文件(.obj)。它的参数非常多,但日常用到的就那么几十个。我按功能分类整理了一下:

输出控制类:

  • /c:只编译不链接,生成.obj文件。这是最常用的选项,配合link.exe分步构建。
  • /Fo<path>:指定目标文件的输出路径或文件名。
  • /Fe<path>:指定可执行文件的输出路径或文件名(需要配合链接选项)。
  • /Fd<path>:指定程序数据库(PDB)文件的路径。

优化类:

  • /O1:最小化空间。
  • /O2:最大化速度,Release构建的常用选项。
  • /Od:禁用优化,Debug构建的默认选项。
  • /Ox:最大优化,可能增加代码体积。
  • /Oi:启用内建函数,比如用memcpy替代循环拷贝。

调试类:

  • /Zi:生成完整的调试信息,配合/DEBUG链接选项使用。
  • /ZI:生成支持“编辑并继续”的调试信息,仅32位支持。
  • /Zd:只生成行号信息,不生成完整调试信息。

预处理类:

  • /D<macro>:定义宏,等价于源代码中的#define。
  • /U<macro>:取消宏定义。
  • /I<path>:添加头文件搜索路径。
  • /E:只预处理,输出到标准输出。
  • /P:只预处理,输出到.i文件。

语言标准类:

  • /std:c++14、/std:c++17、/std:c++20、/std:c++latest:指定C++标准版本。
  • /std:c11、/std:c17:指定C标准版本。

一个典型的编译命令长这样:

cl /c /O2 /Zi /std:c++17 /I"C:\project\include" /DNDEBUG /Fo"build\main.obj" src\main.cpp

这条命令的含义是:编译src\main.cpp,启用速度优化和调试信息,使用C++17标准,添加头文件搜索路径,定义NDEBUG宏,输出目标文件到build\main.obj。

3.2 link.exe 链接器命令与库依赖处理

编译生成.obj文件后,需要用link.exe把它们链接成可执行文件或动态库。链接器的核心任务是解析符号引用,把多个目标文件和库文件合并成一个完整的二进制。

常用参数包括:

  • /OUT:<path>:指定输出文件名。
  • /SUBSYSTEM:CONSOLE或/SUBSYSTEM:WINDOWS:指定子系统类型,控制台程序用CONSOLE,窗口程序用WINDOWS。
  • /DEBUG:生成调试信息,配合编译时的/Zi使用。
  • /LIBPATH:<path>:添加库文件搜索路径。
  • /DYNAMICBASE:启用地址空间布局随机化(ASLR)。
  • /NXCOMPAT:启用数据执行保护(DEP)。
  • /MACHINE:X64或/MACHINE:X86:指定目标架构。

链接时最常见的坑是库依赖顺序。MSVC的链接器对库文件的顺序敏感,如果库A依赖库B,那么A必须出现在B之前。比如:

link /OUT:app.exe main.obj utils.obj /LIBPATH:"C:\libs" mylib.lib kernel32.lib user32.lib

这里mylib.lib如果依赖kernel32.lib中的符号,那么mylib.lib必须放在kernel32.lib前面。顺序反了就会报“无法解析的外部符号”错误。

注意:如果你用cl.exe直接编译并链接(不加/c选项),编译器会自动调用链接器,并传入默认的库文件。但这种方式不够灵活,大型项目建议分步执行,便于排查问题。

3.3 msbuild 与 nmake 的定位差异

除了直接调用编译器和链接器,VS还提供了两个构建工具:msbuild.exe和nmake.exe。它们的定位不同,适用场景也不一样。

msbuild.exe是VS的官方构建引擎,它读取.vcxproj项目文件或.sln解决方案文件,按照其中定义的配置和依赖关系执行构建。它的优势是:

  • 与VS IDE使用同一套构建逻辑,结果一致。
  • 支持增量构建,只重新编译修改过的文件。
  • 支持多配置(Debug/Release)和多平台(x86/x64/ARM)。
  • 可以通过命令行参数覆盖项目设置,比如/p:Configuration=Release。

一个典型的msbuild命令:

msbuild MyProject.sln /p:Configuration=Release /p:Platform=x64 /m /v:minimal

其中/m启用多核并行构建,/v:minimal控制输出详细程度。

nmake.exe是一个传统的Make工具,它读取Makefile文件,按照其中定义的规则执行命令。它的优势是:

  • 轻量级,不依赖VS项目文件。
  • 灵活,可以定义任意构建规则。
  • 适合小型项目或需要精细控制构建流程的场景。

nmake的Makefile语法比较古老,但功能强大。一个简单的Makefile示例:

CC = cl CFLAGS = /c /O2 /Zi LINK = link LFLAGS = /DEBUG /SUBSYSTEM:CONSOLE app.exe: main.obj utils.obj $(LINK) $(LFLAGS) /OUT:app.exe main.obj utils.obj main.obj: src/main.cpp $(CC) $(CFLAGS) /Fo:main.obj src/main.cpp utils.obj: src/utils.cpp $(CC) $(CFLAGS) /Fo:utils.obj src/utils.cpp clean: del *.obj *.exe *.pdb

选择哪个工具,取决于你的项目规模和构建需求。大型项目用msbuild,小型项目或需要精细控制时用nmake,直接调用cl/link则适合快速验证和调试。

4. 完整实操流程与自动化构建

4.1 从零开始编译一个多文件项目

假设我们有一个简单的C++项目,包含三个源文件:main.cpp、math_utils.cpp、string_utils.cpp,以及对应的头文件。项目结构如下:

project/ ├── src/ │ ├── main.cpp │ ├── math_utils.cpp │ ├── math_utils.h │ ├── string_utils.cpp │ └── string_utils.h ├── build/ └── bin/

第一步,打开VS开发者命令提示符,切换到项目根目录:

cd /d C:\project

第二步,创建构建目录:

mkdir build mkdir bin

第三步,逐个编译源文件:

cl /c /O2 /Zi /std:c++17 /I"src" /Fo"build\main.obj" src\main.cpp cl /c /O2 /Zi /std:c++17 /I"src" /Fo"build\math_utils.obj" src\math_utils.cpp cl /c /O2 /Zi /std:c++17 /I"src" /Fo"build\string_utils.obj" src\string_utils.cpp

第四步,链接生成可执行文件:

link /OUT:"bin\app.exe" /DEBUG /SUBSYSTEM:CONSOLE /MACHINE:X64 build\main.obj build\math_utils.obj build\string_utils.obj kernel32.lib user32.lib

第五步,运行验证:

bin\app.exe

这套流程看起来简单,但实际操作中容易在几个地方翻车。比如头文件路径写错、库文件顺序不对、目标文件路径包含空格没加引号等。我建议把编译和链接命令写到一个批处理文件里,每次修改代码后直接运行脚本,省去重复输入命令的麻烦。

4.2 用批处理脚本封装构建流程

手动敲命令只适合验证阶段,真正做项目还是要靠脚本。下面是一个实用的构建脚本示例:

@echo off setlocal enabledelayedexpansion set PROJECT_ROOT=%~dp0 set SRC_DIR=%PROJECT_ROOT%src set BUILD_DIR=%PROJECT_ROOT%build set BIN_DIR=%PROJECT_ROOT%bin set CXXFLAGS=/c /O2 /Zi /std:c++17 /I"%SRC_DIR%" set LDFLAGS=/DEBUG /SUBSYSTEM:CONSOLE /MACHINE:X64 set LIBS=kernel32.lib user32.lib if not exist "%BUILD_DIR%" mkdir "%BUILD_DIR%" if not exist "%BIN_DIR%" mkdir "%BIN_DIR%" echo [1/3] Compiling main.cpp... cl %CXXFLAGS% /Fo"%BUILD_DIR%\main.obj" "%SRC_DIR%\main.cpp" if errorlevel 1 goto :error echo [2/3] Compiling math_utils.cpp... cl %CXXFLAGS% /Fo"%BUILD_DIR%\math_utils.obj" "%SRC_DIR%\math_utils.cpp" if errorlevel 1 goto :error echo [3/3] Compiling string_utils.cpp... cl %CXXFLAGS% /Fo"%BUILD_DIR%\string_utils.obj" "%SRC_DIR%\string_utils.cpp" if errorlevel 1 goto :error echo Linking... link %LDFLAGS% /OUT:"%BIN_DIR%\app.exe" "%BUILD_DIR%\main.obj" "%BUILD_DIR%\math_utils.obj" "%BUILD_DIR%\string_utils.obj" %LIBS% if errorlevel 1 goto :error echo Build succeeded! goto :eof :error echo Build failed with error code %errorlevel% exit /b %errorlevel%

这个脚本做了几件事:自动创建输出目录、逐个编译源文件、检查每一步的错误码、链接生成可执行文件。if errorlevel 1是批处理中判断命令是否失败的标准写法,配合goto :error可以在出错时立即终止并输出错误信息。

实操心得:批处理脚本中路径包含空格时,一定要用引号包裹。比如/Fo"%BUILD_DIR%\main.obj",如果写成/Fo%BUILD_DIR%\main.obj,当路径中有空格时就会解析错误。这个坑我踩过不止一次。

4.3 增量构建的实现思路

每次全量编译所有文件很浪费时间,尤其是项目大了之后。增量构建的核心思路是:只重新编译修改过的源文件。实现方式有两种:

第一种是用msbuild,它内置了增量构建支持,会自动比较源文件和目标文件的时间戳,只编译过期的文件。这是最省事的方式,推荐优先使用。

第二种是自己在脚本中实现时间戳比较。批处理的for循环配合%~t修饰符可以获取文件修改时间,但比较时间戳的逻辑写起来比较繁琐。更实用的做法是用nmake,它的Makefile规则天然支持依赖检查:

app.exe: main.obj math_utils.obj string_utils.obj link /OUT:app.exe /DEBUG /SUBSYSTEM:CONSOLE main.obj math_utils.obj string_utils.obj kernel32.lib main.obj: src/main.cpp src/math_utils.h src/string_utils.h cl /c /O2 /Zi /std:c++17 /I"src" /Fo:main.obj src/main.cpp math_utils.obj: src/math_utils.cpp src/math_utils.h cl /c /O2 /Zi /std:c++17 /I"src" /Fo:math_utils.obj src/math_utils.cpp string_utils.obj: src/string_utils.cpp src/string_utils.h cl /c /O2 /Zi /std:c++17 /I"src" /Fo:string_utils.obj src/string_utils.cpp

nmake会检查每个目标文件的依赖项,如果依赖的源文件或头文件比目标文件新,就重新执行对应的命令。这样修改一个源文件时,只会重新编译它和依赖它的文件,其他文件保持不变。

4.4 环境切换与多架构构建

实际项目中经常需要同时构建32位和64位版本。用vcvarsall.bat可以在同一个脚本中切换环境,但要注意每次切换后环境变量会覆盖,所以需要为每个架构单独开一个cmd进程。

一个实用的多架构构建脚本:

@echo off setlocal set PROJECT_ROOT=%~dp0 set VS_PATH="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build" echo Building x64... call %VS_PATH%\vcvarsall.bat x64 call :build_project x64 echo Building x86... call %VS_PATH%\vcvarsall.bat x86 call :build_project x86 goto :eof :build_project set ARCH=%1 set BUILD_DIR=%PROJECT_ROOT%build\%ARCH% set BIN_DIR=%PROJECT_ROOT%bin\%ARCH% if not exist "%BUILD_DIR%" mkdir "%BUILD_DIR%" if not exist "%BIN_DIR%" mkdir "%BIN_DIR%" cl /c /O2 /Zi /std:c++17 /I"%PROJECT_ROOT%src" /Fo"%BUILD_DIR%\main.obj" "%PROJECT_ROOT%src\main.cpp" link /OUT:"%BIN_DIR%\app.exe" /DEBUG /SUBSYSTEM:CONSOLE /MACHINE:%ARCH% "%BUILD_DIR%\main.obj" kernel32.lib user32.lib goto :eof

这个脚本先切换到x64环境构建64位版本,再切换到x86环境构建32位版本,输出文件分别放在不同的目录中。call命令用于调用另一个批处理脚本并在返回后继续执行当前脚本,这是批处理中实现“函数调用”的标准方式。

注意:vcvarsall.bat的路径取决于VS的安装位置和版本。VS2022社区版的默认路径是C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build,其他版本和版本可能不同。如果不确定,可以在开始菜单的开发者命令提示符快捷方式上右键查看属性,找到目标路径。

5. 常见问题与排查技巧实录

5.1 编译链接错误速查表

命令行编译时遇到的错误,大部分都有固定的排查套路。我整理了一份速查表,覆盖了最常见的几类问题:

错误信息可能原因排查方法
无法打开源文件“xxx.h”头文件路径未设置或拼写错误检查/I参数,用dir确认文件存在
无法解析的外部符号“xxx”库文件缺失或顺序不对检查/LIBPATH和库文件顺序,确认符号所属的库
LNK1104: 无法打开文件“xxx.lib”库文件路径错误或文件不存在用dir /s xxx.lib搜索文件位置
C1083: 无法打开包括文件INCLUDE环境变量未设置运行vcvarsall.bat重新配置环境
LNK2005: xxx已经在xxx.obj中定义符号重复定义检查是否有重复的全局变量或函数定义
C2143: 语法错误,缺少“;”头文件包含顺序问题或宏定义冲突检查包含顺序,用/E预处理查看展开结果
LNK1112: 模块计算机类型“x64”与目标计算机类型“x86”冲突目标文件架构不一致确认所有.obj文件和库文件都是同一架构
C4996: xxx被声明为已弃用使用了不安全的CRT函数定义_CRT_SECURE_NO_WARNINGS宏或改用安全版本

这张表覆盖了日常开发中80%以上的编译链接问题。遇到错误时,先查表定位方向,再根据具体信息深入排查。

5.2 环境变量冲突与路径问题

环境变量冲突是命令行编译中最隐蔽的问题之一。典型场景是:机器上装了多个版本的VS,或者装了其他编译器(如MinGW、Clang),PATH中混入了不同版本的工具,导致调用的编译器版本不对。

排查方法:

where cl where link where msbuild

where命令会列出PATH中所有匹配的可执行文件。如果输出的第一个路径不是你期望的VS版本,说明PATH顺序有问题。解决方法是在调用vcvarsall.bat之前,先清理PATH中的编译器路径,或者直接用绝对路径调用编译器。

另一个常见问题是路径中包含空格或中文。MSVC的工具链对路径中的空格支持还算好,但对中文路径的支持不稳定。如果项目路径中有中文,可能会遇到各种奇怪的错误。建议项目路径全部用英文,且不要有空格。

实操心得:我习惯在项目根目录放一个env.bat脚本,内容就是调用vcvarsall.bat并设置项目相关的环境变量。每次打开cmd后先运行这个脚本,确保环境一致。这样即使换了机器,只要VS版本相同,构建结果就是可复现的。

5.3 调试信息与PDB文件处理

命令行编译时,调试信息的生成和控制需要特别注意。/Zi选项让编译器生成PDB文件,/DEBUG选项让链接器生成调试信息。两者配合使用,才能在调试器中正常查看变量和调用栈。

PDB文件的管理有几个要点:

  • 编译时的PDB:/Zi生成的PDB文件默认放在当前目录或/Fd指定的路径。多个源文件编译时,如果都输出到同一个PDB文件,编译器会自动合并调试信息。
  • 链接时的PDB:/DEBUG选项让链接器生成一个包含链接信息的PDB文件,通常和可执行文件同名。
  • PDB路径:可以用/PDB:<path>指定链接器PDB的输出路径。

如果调试时提示“找不到调试信息”或“PDB文件不匹配”,通常是因为可执行文件和PDB文件不是同一次构建生成的。解决方法是清理所有中间文件,重新完整构建一次。

5.4 性能优化与构建加速

命令行构建的一个优势是可以精细控制优化选项。除了前面提到的/O1、/O2、/Ox,还有几个实用的优化参数:

  • /GL:全程序优化,允许编译器跨目标文件优化。需要配合链接器的/LTCG选项。
  • /arch:AVX2:启用AVX2指令集,适合数值计算密集型程序。
  • /fp:fast:快速浮点运算,牺牲精度换取速度。
  • /Ob2:积极内联,可能增加代码体积但提升速度。

构建加速方面,msbuild的/m选项可以启用多核并行构建,显著缩短大型项目的构建时间。如果项目有多个独立的目标,也可以用start命令并行执行多个编译任务:

start /b cl /c /O2 /Fo"build\a.obj" src\a.cpp start /b cl /c /O2 /Fo"build\b.obj" src\b.cpp start /b cl /c /O2 /Fo"build\c.obj" src\c.cpp wait

但这种方式需要自己管理依赖关系,适合源文件之间没有编译期依赖的场景。

5.5 从IDE到命令行的迁移经验

很多人习惯了IDE的“一键编译”,迁移到命令行时会有各种不适应。我总结了几条经验,能帮你平滑过渡:

第一,先用IDE生成项目文件,再用msbuild构建。VS的.vcxproj文件包含了完整的构建配置,用msbuild直接构建可以保证和IDE结果一致。等熟悉了之后再尝试手写编译命令。

第二,把IDE的输出窗口当成学习材料。VS在编译时会输出完整的命令行,你可以在“工具”→“选项”→“项目和解决方案”→“生成并运行”中把“MSBuild项目生成输出详细程度”设为“详细”,然后查看输出窗口中的命令行,照着抄就行。

第三,逐步替换,不要一步到位。先尝试用命令行做完整构建,熟悉之后再尝试增量构建、多架构构建、自动化测试等高级用法。每一步都验证结果,确保和IDE构建一致。

第四,善用/showIncludes选项。这个选项让编译器输出所有被包含的头文件,帮你理清头文件依赖关系,排查包含路径问题非常有用。

注意:/showIncludes的输出会混在正常编译输出中,建议配合/E或/P选项单独使用,或者把输出重定向到文件再分析。

6. 个人实操体会与进阶建议

命令行编译这件事,入门门槛确实比点IDE按钮高一些,但一旦跨过那个坎,你会发现它能做的事情比想象中多得多。我现在做项目,基本流程是:用IDE写代码和调试,用命令行做自动化构建和持续集成。两者配合,效率比纯IDE或纯命令行都高。

如果你刚开始接触,我的建议是从小项目练手,先把单文件编译链接跑通,再逐步增加文件数量、引入库依赖、尝试多架构构建。遇到报错不要慌,大部分问题都能通过检查环境变量、确认文件路径、调整库顺序解决。实在搞不定的时候,用/E预处理看看展开结果,或者用/showIncludes检查头文件包含链,往往能发现问题的根源。

另外,VS的版本更新比较快,不同版本的vcvarsall.bat路径和参数可能有细微差异。如果你在脚本中硬编码了VS路径,升级VS后记得同步更新。更稳妥的做法是用vswhere.exe动态查找VS安装路径,这个工具在C:\Program Files (x86)\Microsoft Visual Studio\Installer目录下,可以查询已安装的VS实例和组件信息。

最后分享一个我常用的小技巧:在项目根目录放一个build.bat,内容就是调用vcvarsall.bat并执行构建脚本。这样无论在哪台机器上,只要装了对应版本的VS,双击这个脚本就能完成构建,不需要手动配置环境。对于团队协作来说,这能省去大量“在我机器上能编译”的扯皮时间。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进