Introduction
How does a compiler work? That is the question. A Compiler’s main task if to turn your source code into an executable file that computer understands. To achieve this, a compiler has to undergo several stages to build the final executable. The picture below describes difference compilation stages:

Preprocessor Stage
- The first stage in the compilation process.
- Expand preprocessor directives starting with a ‘#’ symbol and include commands like
#include
,#define
, and#ifdef
. See more details about preprocessor clauses here. - Performs text substitutions, file inclusions, and conditional compilation…etc
- Removes comments, resolves macros, and expands header files included via
#include
. - The output of the preprocessor is an expanded source code file.
Compilation Stage
- The compiler takes the preprocessed source code as input and translates it into assembly code or an intermediate representation.
- It performs lexical analysis (tokenizing), syntax analysis (parsing), and semantic analysis (type checking).
- The compiler generates machine-independent assembly code.
- Some compilers may perform optimizations at this stage to improve the efficiency of the generated code.
- The output of this stage is typically in the form of assembly code (which is still human readable).
Assembly Stage
- Responsible for translating assembly code into machine code. (This is what a CPU understands).
- It performs assembly-level optimizations, such as instruction scheduling for a particular CPU type.
- The assembler generates an object file containing the machine code and information about program sections (data, text, etc.).
- The object file is typically in a (.o) format on Unix-based operating system.
Linker Stage
- The final stage of compilation, responsible for combining multiple object files and libraries into a single executable program.
- It resolves references between different object files and ensures that functions and variables declared in one file are correctly linked to their definitions in other files.
- The linker also resolves dependencies on external libraries and system functions.
- It produces the final
executable binary
orshared library
. - Additionally, the linker can perform optimizations and generate debug information for a debugger to trace. See more about using a debugger like GDB here.
Quick Summary
See below picture for a quick summary that answers question: “how does a compiler work”.
