# Chapitre 3 — Outils et chaîne de compilation ## 3.1 Compilateurs : rôle et implémentations Un compilateur transforme du code C en instructions exécutables par le processeur. Le C est un langage compilé. Cela signifie que le programme est transformé avant exécution. ### Compilateurs courants - GCC (GNU Compiler Collection) - Clang (LLVM) - MSVC (Microsoft Visual C) Chaque compilateur : - implémente la norme C - peut ajouter des extensions - produit du code pour une architecture donnée ### Exemple ```bash gcc main.c -o prog ``` --- ## 3.2 Étapes de la chaîne de compilation La compilation est une pipeline. ### Étape 1 — Préprocesseur Traite : - #include - #define - #ifdef Exemple : ```c #include ``` Le contenu du fichier est copié dans le code. ### Étape 2 — Compilation C → assembleur ```bash gcc -S main.c ``` Produit : ``` main.s ``` ### Étape 3 — Assemblage ASM → objet (.o) L’assembleur transforme le code assembleur en code machine. Produit : ``` main.o ``` ### Étape 4 — Linking Objets → binaire final Le linker assemble tous les objets. Il résout les dépendances. --- ## 3.3 Assembleur utilisé selon la toolchain Le compilateur ne génère pas un assembleur universel. Il dépend de la toolchain. - **GCC** : - utilise GAS **(GNU assembler)** - syntaxe par défaut : **AT&T** - **Clang/LLVM** : - utilise un **assembleur intégré LLVM** - peut aussi utiliser GAS - **MSVC** : - utilise son backend interne - eut utiliser **MASM** - **Android (NDK)** : - utilise **Clang + LLVM** ### Exemple GAS ```asm movl $5, %eax ``` ### Exemple Intel ```asm mov eax, 5 ``` Ces syntaxes ne sont pas compatibles directement. --- ## 3.4 Fichiers générés Chaque étape produit un fichier. ### Source ``` main.c ``` ### Assembleur ``` main.s ``` ### Objet ``` main.o ``` ### Exécutable ``` prog ``` ### Exemple — compilation séparée ```bash gcc -c main.c gcc main.o -o prog ``` --- ## 3.5 Warnings et erreurs Le compilateur analyse aussi le code. ### Erreur Empêche la compilation. ### Warning Indique un problème potentiel. ### Exemple — variable non initialisée ```c int main(void) { int x; return x; } ``` ```bash gcc -Wall -Wextra -Werror main.c ``` --- ## 3.6 Options du compilateur Les options contrôlent le comportement. ### Optimistion ```bash gcc -O0 main.c gcc -O2 main.c gcc -O3 main.c ``` ### Debug ```bash gcc -g main.c ``` ### Standard ```bash gcc -std=c11 main.c ``` --- ## 3.7 Informations de debug Les informations de debug permettent : inspection mémoire suivi d’exécution ### Exemple ```bash gdb prog ``` --- ## 3.8 Compilation séparée Permet de compiler fichier par fichier. ### Exemple ```bash gcc -c a.c gcc -c b.c gcc a.o b.o -o prog ``` --- ## 3.9 Compilation croisée Compiler pour une autre architecture. ### Exemple ```bash arm-none-eabi-gcc main.c ``` --- ## 3.10 Linker Le linker combine les objets. Il : - fusionne les sections - résout les symboles - construit le binaire --- ## 3.11 Symboles Un symbole est un nom utilisé par le linker. #### Exemple ```c void f(void) { } ``` ➡ symbole f --- Le linker associe : - déclaration - définition --- ## 3.12 Formats binaires ### Le binaire final a un format. - **ELF** (Linux) - **PE** (Windows) - **Mach-O** (macOS) ### Contenu : - `.text` → code - `.data` → données - `.bss` → mémoire non initialisée ### Rôle du loader Le système : - charge le binaire - mappe les sections - résout les dépendances --- ## 3.13 ABI (introduction) L’ABI définit : - comment appeler une fonction - comment passer les arguments - comment organiser la mémoire ### Exemple Linux x86_64 : - rdi, rsi, rdx Windows x86_64 : - rcx, rdx, r8 **Même CPU ≠ même ABI** --- ## 3.14 Linker script Un linker script contrôle la disposition mémoire. ### Exemple ```ld SECTIONS { .text 0x1000 : { *(.text) } } ``` Utilisation - embarqué - systèmes bas niveau --- ## 3.15 Résumé - le C est compilé en code machine - la compilation est une chaîne - assembleur dépend de la toolchain - linker construit le binaire - format dépend du système - ABI dépend de l’OS