Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MicrosoftDocs/cpp-docs/llms.txt

Use this file to discover all available pages before exploring further.

The MSVC toolchain can be used entirely from the command line without opening the Visual Studio IDE. This is useful for build servers, CI pipelines, scripted builds, and developers who prefer terminal-based workflows. The key requirement is that the correct environment variables — PATH, INCLUDE, LIB, LIBPATH, and others — must be set before invoking any MSVC tool. Visual Studio installs several batch files and Start menu shortcuts that configure this environment automatically.

Installing the Command-Line Tools

If you have Visual Studio installed with a C++ workload, all command-line tools are already available. If you only need the build tools without the IDE, download the free Build Tools for Visual Studio package from the Visual Studio Downloads page and install the Desktop development with C++ workload.

Setting Up the Environment

The MSVC tools depend on dozens of environment variables. Rather than setting these manually, use one of the provided command files or Start menu shortcuts.

Developer Command Prompt Shortcuts

The Start menu includes pre-configured shortcuts that open a Command Prompt with the correct environment:
ShortcutEnvironment
Developer Command Promptx86 tools → x86 output
x86 Native Tools Command Promptx86 tools → x86 output
x64 Native Tools Command Promptx64 tools → x64 output
x86_x64 Cross Tools Command Promptx86 tools → x64 output
x64_x86 Cross Tools Command Promptx64 tools → x86 output
For Visual Studio 2022, shortcuts are in Start → Programs → Visual Studio 2022 → Visual Studio Tools.

Using vcvarsall.bat

For scripted environments, call vcvarsall.bat from an existing Command Prompt window:
# Typical location for Visual Studio 2022
call "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat" x64
Syntax:
vcvarsall.bat [architecture] [platform_type] [winsdk_version] [-vcvars_ver=vcversion] [spectre_mode]
architectureHostTarget
x86x86 or x64x86 (32-bit)
x64 or amd64x64x64 (64-bit)
x86_x64x86 or x64x64
x86_armx86 or x64ARM
x86_arm64x86 or x64ARM64
amd64_arm64 or x64_arm64x64ARM64
amd64_x86 or x64_x86x64x86
Common examples:
# 64-bit native build (most common on modern machines)
call vcvarsall.bat x64

# Cross-compile for ARM64 from an x64 host
call vcvarsall.bat x64_arm64

# Target UWP with a specific Windows SDK version
call vcvarsall.bat amd64_arm uwp 10.0.19041.0

# Use the VS 2019 toolset even if VS 2022 is installed
call vcvarsall.bat x64 -vcvars_ver=14.29

Using VsDevCmd.bat

VsDevCmd.bat is the primary command file located in the Common7\Tools directory. With no arguments it sets up x86 native tools:
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat"
Do not mix command files from different Visual Studio versions in the same Command Prompt window. Also avoid setting MSVC environment variables in the global Windows environment — use a fresh command window each time.

Compiling with cl.exe

Once the environment is configured, cl.exe is on your PATH.

Basic Usage

# Compile and link a single file into an executable
cl /EHsc hello.cpp

# Compile only (no link) — produces hello.obj
cl /c /EHsc hello.cpp

# Specify the output executable name
cl /EHsc /Fe:myapp.exe main.cpp utils.cpp

# Compile with C++20 and full optimizations
cl /std:c++20 /O2 /EHsc /W4 main.cpp

# Define preprocessor macros
cl /DNDEBUG /DMY_VERSION=2 /EHsc main.cpp

Common cl.exe Options

# Specify include directories
cl /I "C:\libs\boost\include" /I ".\include" /EHsc main.cpp

# Generate a PDB file for debugging
cl /Zi /EHsc main.cpp
link /DEBUG main.obj

# Compile to a named object file
cl /c /Fo:obj\main.obj /EHsc main.cpp

# Use dynamic CRT (recommended for most DLLs and applications)
cl /MD /EHsc main.cpp

# Use static CRT (for self-contained executables)
cl /MT /EHsc main.cpp

Compiling Multiple Files

# Compile a list of source files together
cl /EHsc /std:c++17 /W4 /O2 /MD ^
   src\main.cpp ^
   src\engine.cpp ^
   src\utils.cpp ^
   /Fe:myapp.exe ^
   /I include

# Separate compilation and linking
cl /c /EHsc /std:c++17 /W4 /O2 /MD src\main.cpp src\engine.cpp
link /OUT:myapp.exe main.obj engine.obj msvcrt.lib kernel32.lib

Using a Response File

For long command lines, put options in a response file:
# options.rsp
/EHsc /std:c++17 /W4 /O2 /MD
/I include
/I "C:\libs\boost\include"
src\main.cpp src\engine.cpp
/Fe:myapp.exe
cl @options.rsp
When cl.exe compiles and links in a single step it invokes link.exe automatically. You can call link.exe directly for finer control:
# Link object files into a console executable
link /OUT:myapp.exe /SUBSYSTEM:CONSOLE main.obj engine.obj kernel32.lib

# Create a DLL with an import library
link /DLL /OUT:mylib.dll /IMPLIB:mylib.lib mylib.obj kernel32.lib

# Generate a map file for symbol analysis
link /OUT:myapp.exe /MAP:myapp.map main.obj engine.obj

# Enable link-time code generation (whole-program optimization)
link /LTCG /OPT:REF /OPT:ICF /OUT:myapp.exe main.obj engine.obj

# Create a debug build with full PDB
link /DEBUG /PDB:myapp.pdb /OUT:myapp.exe main.obj engine.obj

Building with MSBuild

MSBuild can drive .vcxproj builds from the command line:
# Build the Release|x64 configuration of a project
msbuild MyApp.vcxproj /p:Configuration=Release /p:Platform=x64

# Build the entire solution
msbuild MySolution.sln /p:Configuration=Release /p:Platform=x64

# Parallel build with 8 worker processes
msbuild MySolution.sln /p:Configuration=Release /p:Platform=x64 /m:8

# Clean only
msbuild MySolution.sln /t:Clean /p:Configuration=Release /p:Platform=x64

# Binary log for later analysis with MSBuild Structured Log Viewer
msbuild MySolution.sln /p:Configuration=Release /p:Platform=x64 /bl:build.binlog

# Override a property (e.g., change output directory)
msbuild MyApp.vcxproj /p:Configuration=Release /p:Platform=x64 ^
        /p:OutDir=C:\CI\Output\

Building with nmake

nmake.exe is the MSVC equivalent of Unix make. It reads a Makefile that describes targets and their build rules:
# Makefile for a simple C++ project
CC = cl
CFLAGS = /EHsc /std:c++17 /W4 /O2 /MD
INCLUDES = /I include
LDFLAGS = /OUT:myapp.exe

OBJS = main.obj engine.obj utils.obj

myapp.exe: $(OBJS)
    link $(LDFLAGS) $(OBJS) kernel32.lib msvcrt.lib

.cpp.obj:
    $(CC) $(CFLAGS) $(INCLUDES) /c $<

clean:
    del *.obj myapp.exe
# Run the default target
nmake

# Run a specific target
nmake clean

# Use a non-default makefile name
nmake /f MyMakefile

# Suppress output banner
nmake /nologo

Building CMake Projects from the Command Line

# Set up environment
call vcvarsall.bat x64

# Configure with a preset
cmake --preset windows-release

# Build
cmake --build --preset windows-release-build

# Or without presets
cmake -S . -B build\release -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build\release

Practical CI Example

A complete CI build script using the command line:
@echo off
setlocal

:: Set up MSVC x64 environment
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
if errorlevel 1 goto :error

:: Build release configuration
msbuild MySolution.sln ^
  /p:Configuration=Release ^
  /p:Platform=x64 ^
  /m:%NUMBER_OF_PROCESSORS% ^
  /bl:build.binlog ^
  /nologo
if errorlevel 1 goto :error

echo Build succeeded.
exit /b 0

:error
echo Build FAILED with error %errorlevel%.
exit /b %errorlevel%
In CI environments, prefer msbuild.exe or cmake --build over the Visual Studio IDE. Both tools are available without a GUI and can run in Docker containers or headless cloud agents.

Environment Variables Reference

VariablePurpose
PATHDirectories containing compiler, linker, and tool executables
INCLUDESemicolon-separated list of directories searched for #include files
LIBSemicolon-separated list of directories searched for .lib files
LIBPATHAdditional library paths searched by the linker
TMPTemporary file directory used by the compiler
CLDefault compiler options applied to every cl.exe invocation
LINKDefault linker options applied to every link.exe invocation

Build docs developers (and LLMs) love