What Is a Compiler? Source Code to Machine Code
A compiler is a program that translates source code you write into a lower-level form a computer can execute, usually all at once, before the program runs.
When you write code in a language like C, Rust, or Go, the CPU cannot run that text directly. A compiler reads your source, checks it for errors, and produces an executable (or an intermediate form) that the machine can run. Compilation happens ahead of time, so most mistakes are caught before the program ever starts, and the resulting binary tends to run fast.
What a compiler actually does
A compiler works in phases: it tokenizes the source (lexing), builds a tree that represents structure (parsing), checks types and rules (semantic analysis), and finally emits target code. Each phase can reject your program, which is why a compile step is also a powerful correctness gate.
Compiler vs interpreter
A compiler translates the whole program before it runs, producing a standalone artifact. An interpreter reads and executes code line by line at runtime. Compiled languages usually run faster; interpreted languages usually start faster and are easier to iterate on.
What compilation produces
- Native machine code for a specific CPU architecture (for example x86-64 or ARM).
- Bytecode for a virtual machine, as Java and C# do.
- Another language entirely, in which case the tool is often called a transpiler.
- Diagnostics: errors and warnings that stop a bad build early.
Why compilers matter
Beyond translation, compilers optimize: they inline functions, remove dead code, and rearrange instructions to run faster. They also enforce the language type system, turning whole classes of bugs into compile-time errors instead of production incidents.
A quick example
Running gcc main.c -o app reads main.c, compiles it, and writes an executable named app. If you reference an undeclared variable, the compiler stops and prints an error rather than producing a broken binary.
Compilers in CI
The compile step is often the most expensive part of a build, and it is sensitive to CPU and memory. A large compilation can be slow on small runners and can even be killed if it exhausts memory. Bigger runners (like Latchkey offers) shorten compile times, and transient out-of-memory or toolchain blips can be auto-retried so one bad build does not block a merge.
Key takeaways
- A compiler translates source code into machine code or another lower-level form before the program runs.
- It catches errors early and can optimize the output for speed.
- Compilation is often the heaviest, most CPU- and memory-bound step in a build.