Visual Studio C++ Slow Build | '10-Minute Build' to 2 Minutes with PCH·/MP
이 글의 핵심
Visual Studio C++ slow build Visual, Studio, C++, Introduction: "10-minute build...
Introduction: “10-Minute Build…Coffee Break”
When building C++ projects in Visual Studio, compilation time increases exponentially as files grow. Especially when header files have many templates/inline functions or deeply nested #include, full builds can take minutes to tens of minutes. This guide organizes 10 practical methods to improve Visual Studio C++ compilation speed.
What This Guide Covers:
- Precompiled Header (PCH): Pre-compile frequently used headers
- Parallel Build (/MP): Utilize multiple CPU cores
- Incremental Link: Re-link only changed parts
- Forward Declaration: Remove unnecessary includes
- C++20 Modules: Replace headers with
import - ccache: Accelerate rebuilds with compilation cache
- Other project setting optimizations
Required Environment: Visual Studio 2019/2022 (Windows). PCH·/MP·incremental link applied in VS project/CMake settings. C++20 modules·ccache are optional, guided based on respective tools.
Reality in Production
When learning development, everything is clean and theoretical. But production is different. You wrestle with legacy code, chase tight deadlines, and face unexpected bugs. The content covered in this guide was initially learned as theory, but I realized “ah, that’s why it’s designed this way” while applying it to actual projects.
What stands out in my memory is the trial and error from my first project. I did it as I learned from books but spent days not knowing why it didn’t work. Eventually, I found the problem through a senior developer’s code review and learned a lot in the process. This guide covers not only theory but also pitfalls you may encounter in practice and their solutions.
1. Use Precompiled Header (PCH)
What is PCH?
Precompiled Header (PCH) is a technique that pre-compiles frequently used but unchanging headers (e.g., <iostream>, <vector>, <boost/asio.hpp>) and reuses them in each .cpp file. Saves time parsing and compiling same headers repeatedly.
Why is it so effective?
C++ header files have many nested includes. For example, including <iostream> internally includes dozens of other headers. If project has 100 .cpp files and each includes <iostream>, same header is parsed 100 times. With PCH, parse once and reuse result.
Concrete Effects:
- Boost.Asio include: 2-3 seconds per file → 0.1 seconds with PCH
- Qt include: 5-10 seconds per file → 0.2 seconds with PCH
- 100-file project: 5 minutes → 2 minutes (60% reduction)
Caution:
Only include rarely changed headers in PCH. Including frequently modified project headers can make it slower as PCH must be regenerated.
Setup in Visual Studio
1. Create pch.h file:
Here is detailed implementation code using C++. Import the necessary modules. Understand the role of each part while examining the code.
// pch.h
#ifndef PCH_H
#define PCH_H
// Frequently used standard library
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <algorithm>
// External libraries
#include <boost/asio.hpp>
#include <fmt/core.h>
#endif
2. Create pch.cpp file:
// pch.cpp
#include "pch.h"
3. Project property settings:
- pch.cpp: Properties → C/C++ → Precompiled Headers → Create Precompiled Header (/Yc)
- All other .cpp: Properties → C/C++ → Precompiled Headers → Use Precompiled Header (/Yu), Precompiled Header File:
pch.h
4. Include at top of each .cpp file:
#include "pch.h" // ✅ Always first line
#include "myheader.h"
// ...
Effect
Depending on project size, 30-70% compilation time reduction is possible. Especially effective when using heavy header libraries like Boost, Qt.
2. Enable Parallel Build (/MP)
/MP Option
By default, Visual Studio compiles one .cpp file at a time. Enabling /MP option uses multiple CPU cores for parallel compilation.
Why not default?
Historical reasons. Old days had mostly single-core CPUs, and parallel compilation consumes much memory. Nowadays most have 4+ cores, so enabling /MP is almost always beneficial.
How much faster?
Theoretically scales with core count, but in practice:
- 4 cores: 2-3x
- 8 cores: 3-5x
- 16 cores: 4-7x
Not perfectly linear because link stage is not parallelized and some files take much longer creating bottlenecks.
Setup Method
Project properties:
- C/C++ → General → Multi-processor Compilation → Yes (/MP)
Or command line:
msbuild MyProject.sln /p:CL_MPCount=8
CMake:
if(MSVC)
add_compile_options(/MP)
endif()
Effect
2-4x build speed improvement possible on 4+ core CPUs. However, memory usage also increases, so can become slower if RAM is insufficient.
3. Enable Incremental Link (/INCREMENTAL)
What is Incremental Link?
Incremental Linking is a technique that re-links only changed object files. Link time greatly reduced by not re-linking entire program.
Setup Method
Project properties:
- Linker → General → Enable Incremental Linking → Yes (/INCREMENTAL)
CMake:
if(MSVC)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /INCREMENTAL")
endif()
Caution
- Recommended only for debug builds. For release builds, better to do full link for optimization.
- Sometimes incremental link info gets corrupted causing strange errors. In this case, Clean Solution then rebuild.
4. Reduce includes with Forward Declaration
Problem Situation
Header (MyClass.h):
Below is an implementation example using C++. Import the necessary modules and define a class to encapsulate data and functionality. Try running the code directly to check its operation.
#include "HeavyClass.h" // ❌ Include entire HeavyClass definition
class MyClass {
HeavyClass* member; // Only using pointer, don't need full definition
};
If HeavyClass.h is heavy and many files include it, compilation time increases.
Solution: Forward Declaration
Below is an implementation example using C++. Define a class to encapsulate data and functionality. Try running the code directly to check its operation.
// MyClass.h
class HeavyClass; // ✅ Forward declaration
class MyClass {
HeavyClass* member; // Pointer/reference OK with just forward declaration
};
Include actual definition only in MyClass.cpp:
Below is an implementation example using C++. Import the necessary modules. Try running the code directly to check its operation.
// MyClass.cpp
#include "MyClass.h"
#include "HeavyClass.h" // Include here
void MyClass::someMethod() {
member->doSomething(); // OK
}
Summary
Key Points
- PCH: Pre-compile frequently used headers
- Parallel build (/MP): Use multiple cores
- Incremental link: Re-link only changes
- Forward declaration: Reduce includes
- Unity build: Combine multiple files
- C++20 modules: Modern alternative to headers
Build Time Reduction
| Method | Effect | Difficulty |
|---|---|---|
| PCH | 30-70% | Easy |
| /MP | 2-4x | Very Easy |
| Incremental link | 50-80% | Easy |
| Forward declaration | 10-30% | Medium |
| Unity build | 50-90% | Medium |
| C++20 modules | 70-90% | Hard |
Best Practices
- ✅ Always enable PCH and /MP
- ✅ Use incremental link in debug builds
- ✅ Use forward declarations when possible
- ❌ Don’t put changing headers in PCH
- ❌ Don’t ignore RAM usage with /MP
Related Articles
- C++ Compile-Time Optimization
- C++ LNK2019 Error
Master build optimization for faster C++ development! 🚀