C Mastery / The Compilation Pipeline: Source to Executable
Part 5 — Compilation, Linking, and Building

The Compilation Pipeline: Source to Executable

This chapter traces a C source file through the entire pipeline: preprocessing, compilation, assembly, linking, and loading. Understanding each stage is prerequisite for everything about building and debugging C.

Why This Matters

When you type gcc file.c, several programs run in sequence. Knowing what each stage does — and what artifacts it produces — is how you debug "undefined reference," interpret compiler errors, and reason about object files and libraries.

Prerequisites

Core Concept

The pipeline has these stages:

1. Preprocessing — run the preprocessor (cpp), producing a translation unit (macros expanded, includes inserted, comments removed). 2. Compilation proper — translate the translation unit into assembly. 3. Assembly — assemble to an object file (machine code + symbols + relocations). 4. Linking — combine object files and libraries into an executable. 5. Loading — the OS loads the executable into memory and runs it.

source.c  →  [preprocess]  →  translation unit  →  [compile]  →  .s
   →  [assemble]  →  .o  →  [link]  →  executable  →  [loader]  →  process

How Each Stage Works

StageInputOutputTool (GCC/Clang)
Preprocess.ctranslation unit (text)cc -E
Compiletranslation unit.s assemblycc -S
Assemble.s.o object fileas
Link.o + librariesexecutableld (via cc)

Examples

Inspecting each stage (GCC/Clang)

cc -E file.c -o file.i      # preprocess only
cc -S file.c -o file.s      # compile to assembly
cc -c file.c -o file.o      # compile + assemble to object
cc file.o -o prog           # link

A complete build

cc -c main.c -o main.o
cc -c util.c -o util.o
cc main.o util.o -o app

How It Works

The preprocessor is a textual stage. The compiler proper parses the translation unit, does semantic analysis, and generates assembly (or an intermediate representation). The assembler encodes instructions into machine code and emits a symbol table and relocation records. The linker resolves symbols across objects and produces the final executable.

Variations

Integrated vs. separate

cc file.c runs all stages behind the scenes. -E, -S, and -c stop at intermediate stages. Understanding the separation is what makes cross compilation and custom toolchains tractable.

Intermediate representation (IR)

Modern compilers (Clang/LLVM, GCC) often work through an IR, not literally emitting .s at -O0. The conceptual pipeline is the same; the IR is an internal step.

Common Mistakes

link time as "undefined reference").

Undefined Behavior

contain UB.

Portability

implementation-specific. cc is the portable compiler driver; gcc/clang are specific.

Under the Hood

The object file contains sections (.text, .data, .bss, .rodata), a symbol table, and relocations. The linker merges sections and patches relocations. c.build.2 covers this in depth.

Practical Usage

Exercises

1. Run cc -E, cc -S, and cc -c on a small file and inspect each output. 2. Create two files with a missing definition and observe the linker error. 3. Compile to assembly and identify where a function call and a global access appear.

Deep Challenge

Trace a two-file program through all stages and describe, for each stage, what information is added or resolved. Explain specifically what the linker does with an external function call in one object to a definition in another.

References

Verification

VERIFIED

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.build.pipeline06