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:

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 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