[2026] C++20 Modules: Escape Include Hell and Speed Up Builds with import
이 글의 핵심
C++20 modules: export module, import, partitions, global module fragments, CMake 3.28 FILE_SET MODULES, GCC/Clang/MSVC workflows, common errors, and incremental migration from headers.
Introduction: “Including headers makes builds too slow”
One large header pulls in dozens more; every .cpp parses that text again. Modules parse once and reuse BMIs (e.g. .pcm)—major compile-time wins at scale.
Requirements: C++20, GCC 11+, Clang 13+, MSVC 2019 16.10+; CMake 3.28+ has solid FILE_SET ....MODULES support.
What is a module?
A module is a translation unit with an export module (or implementation module name;) that exposes only exported declarations to import consumers—unlike textual #include paste.
Global module fragment
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.
module;
#include <vector> // only in this preamble
export module mylib;
export int add(int a, int b) { return a + b; }
Header vs module (concept)
| #include | import | |
|---|---|---|
| Unit | Text paste | Parsed BMI cache |
| Duplicate work | Per TU | Once per module |
| Macros | Leak everywhere | Contained |
Partitions
Split large modules: export module mylib:part1;, aggregate with export import mylib:part1; in the primary interface.
Build commands (sketch)
- GCC:
-std=c++20 -fmodules-ts, compile interface units first in dependency order. - Clang: often
-std=c++20 -c file.cppm. - MSVC:
/std:c++20and/interfacefor.ixx.
CMake 3.28+
아래 코드는 cmake를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
target_sources(app PRIVATE FILE_SET all MODULES
math.cppm
geometry.cppm
geometry_impl.cpp
)
Common errors
- Module not found / link order—build interface
.obefore importers. exportinsidemodule;preamble—illegal.- Using non-exported symbols from another module.
- Circular imports—split interfaces or introduce a third module.
#includebeforeimportcan pollute macros—preferimportfirst.- Wrong extension—use .cppm / .ixx for interface units.
- Wrong partition compile order.
exportin implementation unit—only primary/partition interfaces export.
Performance (illustrative)
Large projects often see ~50–75% compile-time reduction versus repeated header parsing—depends on project shape and compiler.
Production patterns
- Migrate new code first; keep
#includewhere needed. - PIMPL + modules for ABI stability.
- Wrap
import stdgaps with thin module shims until the toolchain supports import std. - Cache .pcm paths in CI.