Installs Visual C++ 2008 SP1 (PlatformToolset=v90) for use with Visual Studio 2010-2022.
# Run as Administrator
.\install-vc9.ps1- Downloads Windows SDK 7.0 and installs VC9 SP1 compiler (15.0.30729.1)
- Installs MSBuild v90 toolset files (bundled in this repository)
- Sets up registry keys and environment for MSBuild (works with all VS versions)
- Windows 10/11
- Visual Studio 2010 or later (any edition)
- PowerShell 5.1+
- 7-Zip in PATH (required on headless/Server; desktop falls back to Mount-DiskImage)
- ~1.5 GB free disk space for download (can be cleaned up after)
If you already have the ISO, place it next to the script to skip downloading:
install-vc9.ps1
GRMSDK_EN_DVD.iso (1.48 GB - SDK 7.0)
The script checks for local files first, then cached downloads, then downloads fresh.
| Component | Version | Source | Installed Size |
|---|---|---|---|
| VC9 x86 compiler + tools | 15.0.30729.1 | SDK 7.0 | 25 MB |
| VC9 x64 cross-compiler | 15.0.30729.1 | SDK 7.0 | 7 MB |
| VC9 CRT/STL/TR1 headers | SP1 | SDK 7.0 | 5 MB |
| VC9 libs (x86 + x64) | SP1 | SDK 7.0 | 161 MB |
| Windows SDK 7.0 headers | 7.0 | SDK 7.0 | 91 MB |
| Windows SDK 7.0 libs (x86 + x64) | 7.0 | SDK 7.0 | 53 MB |
| CRT runtime DLLs (release) | 9.0.30729.1 | SDK 7.0 | 2 MB |
| MSBuild v90 toolset | 4.0 | bundled | 8 KB |
| Total (base) | ~343 MB | ||
| Debug CRT libs + DLLs (optional) | SP1 | VS2008 SP1 | 23 MB |
C:\Program Files (x86)\Microsoft Visual Studio 9.0\
├── Common7\Tools\
│ └── vsvars32.bat # Environment setup script
└── VC\
├── bin\cl.exe # Compiler
├── include\ # Headers (with TR1)
└── lib\ # Libraries
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0\
├── Include\ # Windows SDK headers (windows.h, etc.)
└── Lib\ # Windows SDK libs (kernel32.lib, user32.lib, etc.)
MSBuild toolset files are installed to both legacy and modern paths:
# Legacy (VS2010-2015):
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32\PlatformToolsets\v90\
├── Microsoft.Cpp.Win32.v90.props
└── Microsoft.Cpp.Win32.v90.targets
# VS2017+ (per-install, found via vswhere):
<VS Install>\MSBuild\Microsoft\VC\v170\Platforms\Win32\PlatformToolsets\v90\
├── Toolset.props # Generated with v170-specific properties
└── Toolset.targets # Generated with CppCommon.targets import
The script sets:
| Variable | Value |
|---|---|
VS90COMNTOOLS |
C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools\ |
Registry keys for MSBuild:
HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\Setup\VC\ProductDirHKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\Setup\VS\ProductDir
| File | Size | Provides | Download |
|---|---|---|---|
| SDK 7.0 | 1.48 GB | VC9 SP1 compiler, CRT/STL, x64 cross-compiler, WinSDK | Wayback Machine |
| VS2008 SP1 | 832 MB | Debug CRT (optional --include-debug-crt) |
microsoft.com |
| MSBuild v90 | 8 KB | .props + .targets for PlatformToolset=v90 |
bundled in MSBuild/v90/ |
Microsoft's original SDK 7.0 download link is no longer available; the ISO is sourced from the Wayback Machine.
Windows SDK 7.0 bundles the VC9 SP1 compiler (cl.exe 15.0.30729.1) with the full
Windows SDK — headers, libs, x64 cross-compiler, PGO, and OpenMP — all in one
1.48 GB download. The alternative (VS2008 Express SP1, 749 MB) uses the same x86
compiler binary but is missing x64/IA64 cross-compilers, PGO tools, OpenMP, and
ships fewer libs (23 vs 29 in VC/lib). Express also lacks a Windows SDK —
you'd need a second download.
VS2008 SP1 ISO is only needed for debug CRT (/MDd, /MTd). The base SDK
ships release CRT only. The SP1 ISO contains a .msp patch with the debug libs
(msvcrtd.lib, libcmtd.lib, etc.) and debug runtime DLLs (MSVCR90D.dll).
MSBuild v90 toolset files are the stock .props and .targets from Visual
Studio 2010 (byte-identical to the originals in vs_setup.cab, dated 2009-11-11).
These enable MSBuild to locate the VC9 compiler via registry keys when a project
sets <PlatformToolset>v90</PlatformToolset>.
The base install (Windows SDK 7.0) includes the compiler and release CRT libs. The optional debug CRT comes from a single additional download — the VS2008 SP1 ISO (832 MB, see Sources for the URL).
.\install-vc9.ps1 -IncludeDebugCRTAdds debug CRT libs (msvcrtd.lib, libcmtd.lib, etc.) and debug runtime DLLs
(MSVCR90D.dll, MSVCP90D.dll). Enables /MDd and /MTd configurations for
debug heap validation, CRT assertions, and iterator debugging (~23 MB installed).
See CRT configuration.
Re-run install-vc9.ps1 as Administrator.
VC9 not installed correctly. Check that cl.exe exists:
dir "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\cl.exe"cl.exe depends on mspdb80.dll, mspdbcore.dll, msobj80.dll, and mspdbsrv.exe, which the SDK MSI installs to Common7\IDE instead of VC\bin. The install script automatically copies these to VC\bin (Step 2). If you installed VC9 manually, copy them yourself:
copy "%ProgramFiles(x86)%\Microsoft Visual Studio 9.0\Common7\IDE\mspdb80.dll" "%ProgramFiles(x86)%\Microsoft Visual Studio 9.0\VC\bin\"Install 7-Zip and ensure it's in your PATH:
winget install 7zip.7zipFor Linux, macOS, or WSL (no admin rights, no Windows required):
# Prerequisites
sudo apt install p7zip-full msitools # Debian/Ubuntu
# brew install 7-zip msitools # macOS
./extract-vc9.sh ~/vc9sp1This extracts the full toolchain to a portable directory (~343 MB, ~2950 files) and automatically creates case-insensitive symlinks so headers resolve correctly on Linux:
vc9sp1/
├── VC/bin/ cl.exe (15.0.30729.1), link.exe, ml.exe
│ └── x86_amd64/ x64 cross-compiler
├── VC/include/ C++ STL, CRT, TR1 headers
├── VC/lib/ x86 libs (msvcrt.lib, msvcprt.lib, ...)
│ └── amd64/ x64 libs
├── WinSDK/Include/ windows.h, winnt.h, etc.
├── WinSDK/Lib/ kernel32.lib, user32.lib, etc. (x86)
│ └── x64/ x64 SDK libs
└── MSBuild/v90/ .props + .targets for MSBuild
Use with CMake to download and extract at configure time (requires CMake 3.19+):
include(FetchContent)
FetchContent_Declare(vc9_toolset
GIT_REPOSITORY https://github.com/JohnsterID/vc9-toolset.git
GIT_TAG main
)
FetchContent_MakeAvailable(vc9_toolset)
vc9_setup("${CMAKE_BINARY_DIR}/vc9sp1")
# Path variables:
# VC9_ROOT, VC9_BIN_DIR, VC9_INCLUDE_DIRS, VC9_LIB_DIRS,
# WINSDK_INCLUDE_DIR, WINSDK_LIB_DIR
#
# Cross-compilation helpers:
# VC9_COMPAT_HEADER — compat/vc9_compat.h (SAL/driver annotation stubs)
# VC9_RUNTIME_STUBS_SRC — compat/vc9_runtime_stubs.cpp (link-time stubs)
# VC9_CLANG_COMPILE_FLAGS — ready-made flag list for clang cross-compilation
# VC9_CLANG_LINK_LIBS — CRT + kernel32 link libs for selected VC9_CRTThe vc9_setup() function (from vc9-toolset.cmake) runs extract-vc9.sh on first
configure, then caches the result. Subsequent configures skip extraction.
Cross-compile Windows PE32 binaries from Linux using clang + lld-link with the
extracted VC9 headers and libs.
Prerequisites: clang, lld (e.g. apt install clang-19 lld-19)
VC9=~/vc9sp1
COMPAT=/path/to/vc9-toolset/compat
# Compile C
clang --target=i686-pc-windows-msvc \
-fms-compatibility -fms-extensions \
-include "$COMPAT/vc9_compat.h" \
-U_MSC_VER -D_MSC_VER=1500 \
-isystem "$VC9/VC/include" -isystem "$VC9/WinSDK/Include" \
-c myfile.c -o myfile.obj
# Compile C++
clang++ --target=i686-pc-windows-msvc \
-fms-compatibility -fms-extensions -fdelayed-template-parsing \
-include "$COMPAT/vc9_compat.h" \
-U_MSC_VER -D_MSC_VER=1500 \
-isystem "$VC9/VC/include" -isystem "$VC9/WinSDK/Include" \
-c myfile.cpp -o myfile.obj
# Compile runtime stubs (needed for C++ linking)
clang++ --target=i686-pc-windows-msvc \
-fms-compatibility -fms-extensions \
-isystem "$VC9/VC/include" \
-c "$COMPAT/vc9_runtime_stubs.cpp" -o vc9_stubs.obj
# Link (C)
lld-link /OUT:myapp.exe /MACHINE:x86 /SUBSYSTEM:CONSOLE /ENTRY:mainCRTStartup \
/LIBPATH:"$VC9/VC/lib" /LIBPATH:"$VC9/WinSDK/Lib" \
myfile.obj msvcrt.lib kernel32.lib
# Link (C++)
lld-link /OUT:myapp.exe /MACHINE:x86 /SUBSYSTEM:CONSOLE /ENTRY:mainCRTStartup \
/LIBPATH:"$VC9/VC/lib" /LIBPATH:"$VC9/WinSDK/Lib" \
myfile.obj vc9_stubs.obj msvcrt.lib msvcprt.lib kernel32.lib# toolchain-clang-vc9.cmake
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_C_COMPILER_TARGET i686-pc-windows-msvc)
set(CMAKE_CXX_COMPILER_TARGET i686-pc-windows-msvc)
set(CMAKE_LINKER lld-link)
# cmake -DCMAKE_TOOLCHAIN_FILE=toolchain-clang-vc9.cmake \
# -DVC9_ROOT=/path/to/vc9sp1 ..When cross-compiling with clang, the C++ language standard can be set independently of the VC9 library (STL). Clang provides the language features; the VC9 headers provide the standard library.
| Standard | Language features | VC9 STL | Status |
|---|---|---|---|
| C++03 | (baseline) | full | supported |
| C++11 | auto, lambda, nullptr, constexpr, range-for, rvalue refs, scoped enums, variadic templates, ... | full | supported |
| C++14 | generic lambdas, relaxed constexpr, variable templates, binary literals, decltype(auto), ... |
full | supported |
| C++17 | structured bindings, if constexpr, fold expressions, inline variables, nested namespaces, [[nodiscard]], ... |
full | supported |
| C++20 | concepts, consteval, constinit, designated initializers, abbreviated templates, using enum, [[likely]], ... |
full | supported |
| C++23 | deducing this, static operator(), if consteval, multidimensional operator[], auto(x), [[assume]], ... |
full | supported |
| C++26 | fails -- delete of void* became ill-formed (P2593R1), breaks VC9's xlocale header |
All standards from C++03 through C++23 compile and link on both x86 and x64, verified with clang 19 and 22. The generated PE32/PE32+ binaries link against MSVCR90.dll/MSVCP90.dll as expected.
Key constraints:
-
-fdelayed-template-parsingis mandatory. VC9 headers rely on MSVC-style lazy template parsing. Without this flag, templates in<xutility>fail to resolve::stdext::and::_invalid_parameter_noinfo(). The toolchain cmake module sets this automatically. -
Library is C++03 + TR1. Language features are unlimited (up to C++23), but the STL containers, algorithms, and utilities are VC9's C++03 implementations. C++11 library additions (
<thread>,<chrono>,<regex>,<type_traits>,<atomic>, etc.) are not available. TR1 extensions (std::tr1::shared_ptr,std::tr1::unordered_map, etc.) are available via_HAS_TR1. -
-Wno-delayed-template-parsing-in-cxx20is included in the toolchain flags to suppress clang's deprecation warning at C++20+.
CMake:
set(CMAKE_CXX_STANDARD 23) # use C++23 language features
set(CMAKE_CXX_STANDARD_REQUIRED ON)Command line:
clang++ -std=c++23 --target=i686-pc-windows-msvc \
-fms-compatibility -fms-extensions -fdelayed-template-parsing \
-Wno-delayed-template-parsing-in-cxx20 \
-include "$COMPAT/vc9_compat.h" \
-U_MSC_VER -D_MSC_VER=1500 \
-isystem "$VC9/VC/include" -isystem "$VC9/WinSDK/Include" \
-c myfile.cpp -o myfile.objProbe test: test/cpp_std_probe.cpp exercises language features from
each standard level combined with VC9 STL types. Run
test/probe-cpp-std.sh <vc9_root> to test all 6 standards on both
architectures (12 compile+link combinations).
The compat/ directory handles two categories of issues when using VC9/SDK 7.0
headers with clang on Linux:
| File | When needed | What it fixes |
|---|---|---|
vc9_compat.h |
Always (compile-time) | SAL annotation paths, __drv_* driver macros, CRT runtime macros (_DLL, _MT; see CRT configuration), _CRT_SECURE_NO_WARNINGS |
vc9_runtime_stubs.cpp |
C++ linking only | __std_terminate, sized operator delete, magic-static init (_Init_thread_*) |
Use vc9_compat.h via -include compat/vc9_compat.h (one flag) instead of 30+
individual -D flags on the command line.
The compat header defaults to /MD (DLL runtime). To select static CRT,
define VC9_STATIC_CRT:
| Config | Compile flags | Link libs | Runtime |
|---|---|---|---|
/MD (default) |
(none — compat header sets _DLL _MT) |
msvcrt.lib msvcprt.lib |
MSVCR90.dll, MSVCP90.dll |
/MT |
-DVC9_STATIC_CRT |
libcmt.lib libcpmt.lib |
(static, no DLL) |
/MDd |
-D_DEBUG |
msvcrtd.lib msvcprtd.lib |
MSVCR90D.dll, MSVCP90D.dll |
/MTd |
-DVC9_STATIC_CRT -D_DEBUG |
libcmtd.lib libcpmtd.lib |
(static debug) |
Note:
/MDdand/MTdrequire debug libs not included in Windows SDK 7.0. See Optional Add-ons to install them from VS2008 SP1.
/MD and /MT across a
DLL boundary causes cross-heap crashes (memory allocated by one CRT freed by
another). Standalone executables can use either configuration.
CMake (clang cross-compile): set VC9_CRT before calling vc9_setup():
set(VC9_CRT "MT") # /MT — static CRT
vc9_setup("${CMAKE_BINARY_DIR}/vc9sp1")
target_compile_options(mylib PRIVATE ${VC9_CLANG_COMPILE_FLAGS})
target_link_libraries(mylib PRIVATE ${VC9_CLANG_LINK_LIBS})
# VC9_CLANG_LINK_LIBS = libcmt.lib libcpmt.lib kernel32.lib (for MT)Valid values: MD (default), MDd, MT, MTd. The module sets the correct
compile defines and exports matching link libs in VC9_CLANG_LINK_LIBS.
MSBuild / vcxproj (native cl.exe): set <RuntimeLibrary> in your project —
cl.exe handles _DLL/_MT/_DEBUG automatically:
| RuntimeLibrary | cl.exe switch |
|---|---|
MultiThreadedDLL |
/MD |
MultiThreadedDebugDLL |
/MDd |
MultiThreaded |
/MT |
MultiThreadedDebug |
/MTd |
Projects needing specific STL ABI settings (e.g. _SECURE_SCL=0,
_HAS_ITERATOR_DEBUGGING=0) should define those in their own headers —
they are project-specific, not toolchain-universal.
- Community-Patch-DLL - Example project using v90
- archaic-msvc/msvc900 - Pre-extracted VC9 toolchain (RTM, not SP1)