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
c.core.39— multi-file programs and headers.
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
| Stage | Input | Output | Tool (GCC/Clang) |
|---|---|---|---|
| Preprocess | .c | translation unit (text) | cc -E |
| Compile | translation unit | .s assembly | cc -S |
| Assemble | .s | .o object file | as |
| Link | .o + libraries | executable | ld (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
- Confusing "compile" (produce object) with "link" (produce executable).
- Expecting a missing definition to be caught at compile time (it is caught at
link time as "undefined reference").
- Forgetting to recompile after changing a header (see build systems).
Undefined Behavior
- None inherent to the pipeline; a program that compiles and links may still
contain UB.
Portability
- The pipeline stages are universal, but the tools and flags are
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
- Use
-E,-S, and-cto isolate bugs to a stage. - Compile each translation unit to an object, then link once.
- Use build systems (
c.build.7) to manage the pipeline for large projects.
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.
Related Concepts
c.build.2— symbols, relocations, sections.c.build.3— linking and libraries.c.core.1— translation units.
References
- GCC/Clang documentation on
-E,-S,-c, and linking.
Verification
- The pipeline stages and their tools are standard toolchain behavior.
VERIFIED
- No example was executed during generation unless noted. `Execution not
verified.`
Progress
- [ ] Read
- [ ] Understand
- [ ] Complete examples
- [ ] Complete exercises
- [ ] Complete deep challenge
Concept checkboxes
- [ ] Preprocessing stage
- [ ] Compilation proper
- [ ] Assembly
- [ ] Linking
- [ ] Loading
Mastery levels
| Concept | Current level (0–8) | Target level |
|---|---|---|
| c.build.pipeline | 0 | 6 |