Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Compilation

En gros, la compilation est le processus qui prend un ou plusieurs fichiers sources et produit un exécutable. En fait, comme on le verra, c’est une synecdoque particularisante (figure de style où on parle du tout en utilisant un terme pour une partie seulement). Pour éviter cette figure de style malheureuse, on peut parler de génération d’un exécutable (build en anglais).

Voici les étapes de la génération.

Préprocessing

Le préprocessing consiste à appliquer un prétraitement simple à un code source. En C, les mots-clés commençant par un # correspondent à un traitement de préprocessing.

Exemple : traitement des `#define’

Par exemple #define X 32 remplace les occurrences de X par 32.

#define X 32

int main() {
    int a = X + 2;
    int b = X;
}
🡳 (préprocessing)
    int main() {
        int a = 32 + 2;
        int b = 32;
    }int x

Exemple : traitement des `#include’

La ligne #include "bloup.h" insère le contenu du fichier bloup.h :

#include "bloup.h"

int main() {
    bloup_create();
    bloup_inform(3);
}
🡳 (préprocessing)
void bloup_create();
void bloup_inform(int x);
void bloup_extract(int x, int y);
void bloup_free();

int main() {
    bloup_create();
    bloup_inform(3);
}

Exécuter le préprocesseur

Pour n’exécuter QUE le préprocesseur, il faut utiliser l’option -E (Expand macros) :

    gcc -E main.c -o mainresultat.c

Exécuter gcc -E sur un fichier source de votre choix.

Compiler le projet en un coup

Voici une commande pour construire un exécutable :

gcc myotherCfile.c main.c -o main -Wall

où le flag -o veut dire output.

  • Quel défaut y-a-t-il de compiler tout ?

L’ajout d’une toute petite instruction dans main.c demande de compiler tout depuis le début, le compilateur doit relire myotherCfile.c en entier aussi, alors que ce fichier n’a pas été modifié.

Compiler un projet fichier par fichier

La solution pour avoir une compilation plus rapide est de compiler uniquement les fichiers sources qui ont été modifiés.

Un fichier objet contient du code machine, mais également des “trous” pour les fonctions où l’implémentation est ailleurs.

Pour obtenir un fichier objet à partir d’un fichier source, on exécute gcc -c où le flag -c signifie que l’on ne fait compiler :

gcc -c -o main.o main.c

Je contiens du code exécutable mais à trous… mais je ne connais pas dynarray, dynarray_create, etc.

Avec

gcc -c -o dynarray.o dynarray.c

Haha, moi je connais tout.

La compilation transforme un fichier source .c en fichier objet (du code machine) .o mais en laissant des “trous” pour les fonctions qui sont définies ailleurs.

Mais on est rendu, où est donc l’exécutable que l’on peut lancer ?

Liaison

gcc -o main main.o dynarray.o

Stp, donne moi dynarray, dynarray_create, etc.

Ah... tiens !

Puis :


Je suis un exécutable !

La liaison (ou édition des liens, linking) transforme tous les fichiers .o en un seul fichier exécutable.

Ainsi, les fichiers .o contiennent des trous et la liaison les remplit. Plus précisément :

  • la liaison lie les différents fichiers objet entre eux.
  • la liaison lie les fonctions de la libc utilisées dans les fichiers objet avec le code exécutable correspondant
  • la liaison s’occupe de lier avec du code exécutable dans des bibliothèques (voir plus bas)

Résumé

En fait, on peut compiler chaque fichier source séparemment puis tout lier à la fin :

gcc -c -o dynarray.o dynarray.c
gcc -c -o main.o main.c
gcc -o main main.o dynarray.o

Chaîne de compilation

La chaîne de compilation désigne toutes les étapes durant la génération (abusivement appelée aussi compilation).

     C Source Code 
            |
            v
    +----------------+
    |  Preprocessor  |
    +----------------+
            |
            v
    +----------------+
    |    Compiler    |
    +----------------+
            |
            v
    +----------------+
    |    Linker      |
    +----------------+
            |
            v
       Executable

Compiler votre projet fichier par fichier.

Bibliothèques

Si votre projet utilise des bibliothèques, autres que la libc, par exemple raylib, pthread, etc. alors il faut l’indiquer au compilateur. Par exemple :

    gcc main.c -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 -o mon_programme

La liaison va alors rappatrier le code exécutable des bibliothèques pour construire votre exécutable. On parle de liaison statique (statique = fait à la compilation). Le code exécutable des bibliothèques se trouve dans des fichiers .a (pour archive de code objet statique).

Stp, j’ai besoin de la fonction DrawRectangle…

Ah... tiens j'ai ça !

Liaison dynamique

On peut aussi utiliser des librairies, sans mettre le code exécutable dans notre programme exécutable. On parle de liaison dynamique (on fera ça plus tard, ou… jamais). Le programme, à l’exécution, va lire un fichier .so (shared object) pour y trouver le code exécutable.