Back to List

Compilation Process β€” From Source Code to Executable

Understand the differences between compilers and interpreters, how source code becomes machine code, and the build process step by step.

Beginner
|
10min
|
Verified (2026-07)
compilationinterpretermachine codesource codebuild process
Progress0/23 (0%)

The Compilation Process: From Source Code to Executable

After completing this topic, you will be able to:

  • Explain the difference between compilers and interpreters.
  • Understand the steps involved in converting source code into machine code.
  • Know how Python, JavaScript, and C are executed.

Computers Cannot Read Source Code

The code we write is text for humans.

python
print("Hello, World!")

What the CPU understands is machine code β€” instructions in 0s and 1s.

text
10110000 01001000  (mov al, 'H')
11001101 00100001  (int 21h)

We need to convert source code into machine code. The programs that perform this conversion are called compilers and interpreters.


Compiler vs. Interpreter

CompilerInterpreter
Conversion TimingConverts the entire program at once before execution.Converts and executes line by line.
OutputExecutable file (binary).None (executes immediately).
Error DetectionShows all errors at compile time.Shows errors at the time of executing a specific line.
Execution SpeedFaster (already converted).Relatively slower.
Example LanguagesC, C++, Rust, GoPython, JavaScript, Ruby

Think of it this way: a compiler is like translating a book (translating the whole thing first and then publishing it), and an interpreter is like simultaneous interpretation (translating as you speak).


Compilation Steps: The Case of C

The process of a C code file becoming an executable:

text
Source Code (.c)
    ↓ Preprocessing
Preprocessed Code
    ↓ Compilation
Assembly Code (.s)
    ↓ Assembly
Object File (.o)
    ↓ Linking
Executable File (a.out / .exe)

1. Preprocessing

c
#include <stdio.h>
#define MAX 100

int main() {
    printf("Max is %d\n", MAX);
}

The #include directive is replaced with the actual header file content, and #define is replaced with its value. This step involves text substitution.

2. Compilation

The preprocessed code is analyzed and converted into assembly code. Syntax errors are detected here.

asm
mov    edi, OFFSET FLAT:.LC0
mov    esi, 100
call   printf

3. Assembly

Assembly code is converted into machine code (binary instructions). The result is an object file (.o).

4. Linking

Multiple object files and libraries are combined into a single executable file. The actual implementation of printf is in the C standard library, so the linker connects it.

bash
# GCC performs all these steps in one go
gcc hello.c -o hello
./hello

How Python is Executed

Python is a hybrid of compilation and interpretation.

text
Source Code (.py)
    ↓ Python Compiler
Bytecode (.pyc)
    ↓ Python Virtual Machine (PVM)
Execution Result
python
# Checking the bytecode
import dis
def add(a, b):
return a + b
dis.dis(add)
# LOAD_FAST 0 (a)
# LOAD_FAST 1 (b)
# BINARY_ADD
# RETURN_VALUE

Bytecode is not machine code. The Python Virtual Machine (PVM), which is an interpreter, executes the bytecode line by line. This is slower than the CPU directly executing the code (as in C), but it can run on any operating system.

You may have seen .pyc files appear in the __pycache__/ folder. These are the bytecode caches. If the source code hasn't changed, the cache is used without recompilation.


How JavaScript is Executed

JavaScript engines (V8, SpiderMonkey) use JIT (Just-In-Time) compilation.

text
Source Code (.js)
    ↓ Parsing
AST (Abstract Syntax Tree)
    ↓ Interpreter
Bytecode Execution (slow)
    ↓ JIT Compiler (detects frequently executed code)
Converted to Machine Code (fast)

Initially, it starts executing with an interpreter for quick startup, and when it detects that "this function has been called 1,000 times?", it compiles that part into machine code. Since it compiles during execution, it is called "Just-In-Time".


Java: The Quintessential Hybrid of Compilation and Interpretation

Java is similar to Python, but more complex.

text
Source Code (.java)
    ↓ javac (compilation)
Bytecode (.class)
    ↓ JVM (Java Virtual Machine)
    β”œβ”€β”€ Interpreter (initially)
    └── JIT Compiler (for frequently executed code)
    ↓
Machine Code Execution
java
// Hello.java
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
bash
javac Hello.java # Creates bytecode (.class)
java Hello # JVM executes the bytecode

"Write once, run anywhere" β€” Java bytecode can run anywhere that has a JVM. A .class file compiled on Windows will also work on a Linux JVM.


Static Typing vs. Dynamic Typing

Type systems are closely related to compilation.

c
// C: Static typing - Types are checked at compile time
int x = 42;
x = "hello";  // Compile error!
python
# Python: Dynamic typing - Types are checked at runtime
x = 42
x = "hello" # OK - Type changes during execution
Static TypingDynamic Typing
Type Checking TimeCompile timeRuntime
Error DetectionBefore executionDuring execution
Type SpecificationRequired (int x)Not required (x = 42)
Execution SpeedFasterRelatively slower
Example LanguagesC, Java, TypeScriptPython, JavaScript, Ruby

Practical Implications

text
Why is Python slower than C?
β†’ C: The CPU directly executes machine code.
β†’ Python: The virtual machine interprets and executes bytecode line by line.

Why use TypeScript?
β†’ Adds static typing to JavaScript β†’ Catches errors before execution.
β†’ TypeScript β†’ (tsc compilation) β†’ JavaScript β†’ (V8 execution)

Why do Docker images differ for each OS?
β†’ Compiled binaries are dependent on the CPU architecture (x86, ARM).
β†’ A macOS binary will not run on Linux.

Key Summary

ConceptSummary
CompilerConverts the entire source code into machine code in advance. Faster execution.
InterpreterInterprets and executes line by line. Faster development.
BytecodeAn intermediate format. Executed by a virtual machine (Python, Java).
JITCompiles frequently used parts into machine code during execution (JavaScript).
Static TypingTypes are checked at compile time (C, TypeScript).
Dynamic TypingTypes are checked at runtime (Python, JavaScript).

Build Tools and Transpilers

In modern development, in addition to "pure" compilation/interpretation, there are various other conversion tools.

text
TypeScript β†’ (tsc) β†’ JavaScript β†’ (V8) β†’ Execution
JSX/React  β†’ (Babel) β†’ JavaScript β†’ (V8) β†’ Execution
Sass/SCSS  β†’ (sass) β†’ CSS β†’ Browser Rendering

A transpiler converts code into a code at the same level. If a compiler converts high-level to low-level, a transpiler converts high-level to high-level. TypeScript to JavaScript and ES6 to ES5 are examples.


"Python is an interpreted language" is only half true β€” it compiles to bytecode and then interprets it. "JavaScript is an interpreted language" is also only half true β€” V8 uses JIT compilation. Modern languages mix compilation and interpretation to achieve both development convenience and execution performance.

πŸ’¬ Questions & Comments

0 comments

You can post without signing in. Guest comments cannot be edited or deleted by their author.

0/2000

Loading...