Files
Cours-C/ch003-ctools.md

4.2 KiB
Raw Blame History

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

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 :

#include <stdio.h>

Le contenu du fichier est copié dans le code.

Étape 2 — Compilation

C → assembleur

gcc -S main.c

Produit :

main.s

Étape 3 — Assemblage

ASM → objet (.o) Lassembleur 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

movl $5, %eax

Exemple Intel

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

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

int main(void)
{
    int x;
    return x;
}
gcc -Wall -Wextra -Werror main.c

3.6 Options du compilateur

Les options contrôlent le comportement.

Optimistion

gcc -O0 main.c
gcc -O2 main.c
gcc -O3 main.c

Debug

gcc -g main.c

Standard

gcc -std=c11 main.c

3.7 Informations de debug

Les informations de debug permettent :

inspection mémoire suivi dexécution

Exemple

gdb prog

3.8 Compilation séparée

Permet de compiler fichier par fichier.

Exemple

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

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

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)

LABI 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

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 lOS