The historical development of compilers and programming languages reveals a fascinating paradox: which came first, the language or the compiler? Early computers relied on punch cards for input, which was highly inefficient. The first programming languages, such as assembly, emerged to simplify machine communication. However, the initial compiler for a new language had to be written in a lower-level language. For instance, the first C compiler was implemented in assembly. Once C stabilized, compilers were rewritten in C itself, enabling self-hosting and continuous evolution.
The translation process consists of two key phases: the translation environment (converting source code to machine code) and the execution environment (running the compiled program).
Translation Environment Stages
Preprocessing: Handles header inclusion, comment removal, and macro expansion. Example command:
gcc -E input.c -o processed.i
The resulting .i file contains expanded headers (e.g., over 700 lines from standard libraries), deleted comments, and substituted preprocessor directives.
Compilation: Validates syntax, semantics, and translates to assembly. Command:
gcc -S input.c -o assembly.s
This stage generates human-readable assembly code with symbol tables for global variables and functions.
Assembly: Converts assembly to binary object code. Command:
gcc -c input.c -o compiled.o
The .o file contains machine code in ELF format. Use readelf -a compiled.o to inspect the ELF structure and symbol tables.
Linking: Merges object files and resolves external references. Two types:
- Static Linking: Embeds libray code directly into the executable. Example:```
gcc -static -o app main.o -L./lib -lstatic
- Dynamic Linking: References shared libraries at runtime. Example:```
gcc -o app main.o -L./lib -ldynamic
Dynamic libraries must be accessible during execution. Solutions include setting LD_LIBRARY_PATH, creating symbolic links in system directories, or updating /etc/ld.so.conf.d configuration.
Libray Creation
Static Library:
gcc -c library.c
ar -rc libcustom.a library.o
Dynamic Library:
gcc -c -fPIC library.c
gcc -shared -o libcustom.so library.o
Execution Environment
Statically linked executables run directly (e.g., ./app). Dynamically linked programs require library paths to be resolved at runtime; otherwise, missing symbol errors occur.