Ch6.7: Translation Units
Overview
C++ programs are often split across multiple files. Each file is compiled separately into a translation unit, and the linker combines all translation units into a final executable.
Modern C++ also introduces modules, which are compiled translation units that replace many uses of header files.
In this chapter, you will learn:
- what a translation unit is
- how declarations and definitions are organized
- how separate compilation works
- how C++ modules relate to translation units
- how to write and compile a simple module
1. What is a translation unit?
A translation unit is the result of taking a single
.cpp file, applying the preprocessor (#include,
#define, etc.), and producing one large file that the compiler
actually compiles.
main.cpp → translation unit A
math.cpp → translation unit B
io.cpp → translation unit C
Each translation unit is compiled independently into an object file:
main.cpp → main.o
math.cpp → math.o
io.cpp → io.o
The linker then combines all object files into a single executable.
2. Declarations vs. definitions
When working with multiple translation units, it is essential to separate declarations from definitions.
- Declarations tell the compiler that something exists.
- Definitions provide the full body or allocate storage.
Declarations belong in header files (.hpp).
Definitions belong in source files (.cpp).
// math.hpp (declaration)
int square(int x);
// math.cpp (definition)
int square(int x)
{
return x * x;
}
// main.cpp
#include "math.hpp"
int main()
{
::fast_io::println(square(5));
}
3. Compiling multiple files
You can compile and link multiple translation units in one command:
clang++ -std=c++23 main.cpp math.cpp -o program
or with g++:
g++ -std=c++23 main.cpp math.cpp -o program
Or compile each translation unit separately and link later:
clang++ -std=c++23 -c main.cpp # produces main.o
clang++ -std=c++23 -c math.cpp # produces math.o
clang++ main.o math.o -o program
4. Modules as translation units
A C++ module interface file (.cppm) is also a translation unit.
Instead of using #include to copy text, modules use
export and import to share compiled
declarations.
math.cppm → translation unit (module interface)
main.cpp → translation unit (imports the module)
The compiler produces a PCM (precompiled module) from the module interface, and other translation units import it.
5. Writing and compiling a simple module
A module interface declares a module and exports the functions or types you want other translation units to use.
// math.cppm — module interface
export module math;
export int square(int x)
{
return x * x;
}
A separate translation unit can import the module:
// main.cpp
import math;
import fast_io;
int main()
{
::fast_io::println(square(7));
}
Compiling the module with Clang
Step 1 — Compile the module interface
clang++ -std=c++26 --precompile math.cppm -o math.pcm
Step 2 — Compile your program and import the PCM
clang++ -std=c++26 -fmodule-file=math=math.pcm -c main.cpp -o main.o
Step 3 — Link the final executable
clang++ main.o -o program
Optional: Compiling the fast_io module
clang++ -std=c++26 --precompile \
$HOME/libraries/fast_io/share/fast_io/fast_io.cppm \
-I$HOME/libraries/fast_io/include \
-o fast_io.pcm
clang++ -std=c++26 \
-fmodule-file=math=math.pcm \
-fmodule-file=fast_io=fast_io.pcm \
-c main.cpp -o main.o
clang++ main.o -o program
Key takeaways
- Each
.cppfile becomes a separate translation unit. - Module interface files (
.cppm) are also translation units. - The compiler compiles each translation unit independently.
- The linker combines object files into a final executable.
- Modules replace textual inclusion with compiled interfaces.
- Clang uses PCMs (
.pcm) to represent compiled modules.