Fichiers d’include

Afin de mieux organiser votre code, il est possible de travailler avec plusieurs fichiers sources. Aussi, cela permet de ne recompiler que les sources qui ont été modifiés.

Nous allons commencer avec un exemple tout simple. Puis au fur et à mesure vous allez trouver les indications nécessaires pour construire des objets autres que des exécutables tels qu’une librairie système ou une bibliothèque partagée.

Ceci permet par exemple de créer un fichier source contenant des fonctions pouvant être utilisées par plusieurs programmes. Cela permet de simplifier la maintenance des programmes.

Mais, avant tout, regardons comment cela fonctionne, comment utiliser le compilateur gcc pour compiler un code source C composé de plusieurs fichiers sources.

Exemple

Voici un premier exemple pour commencer. Il est composé de trois fichiers sources C:

  • prog.c: fichier source principal contenant la fonction main().

  • func.c: fichier source secondaire contenant une fonction appelée par main()

  • func.h: fichier d’en-tête qui sera inclus dans le fichier prog.c

L’image ci-dessous donne un aperçu de la manière dont sera compilé le fichier:

_images/include_illustration01.png

Pour commencer, nous allons d’abord compiler les fichiers sources C en objets.

La commande gcc -c prog.c -o prog.o permet de compiler le code source prog.c en objet. De même gcc -c func.c -o func.o génèrera l’objet func.o.

Ces deux fichiers objets seront liés par commande gcc func.o prog.o -o prog pour construire le fichier exécutable prog.

Sources

Pour commencer voici le fichier func.c:

1
2
3
4
5
6
7
8
9
/*
	Implémentation du fichier à inclure.
*/
#include <stdio.h>

void say_hello()
{
    puts("Hello tout le monde !");
}

Ce fichier contient une fonction toute simple say_hello() qui sera appelée dans le programme principal prog. Il peut être immédiatement compilé en objet avec la commande gcc -c func.c -o func.o.

Le fichier contenant le programme principal prog.c:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/*
	programme principal
*/

#include "func.h"

int main(void)
{
    say_hello();
    return (0);
}

A noter, que la ligne 5 contient une instruction particulière #include "func.h" qui va inclure le fichier func.h ci-dessous:

1
2
3
4
5
/*
	En-tête du fichier à inclure.
*/

void say_hello();

En fait, c’est le précompilateur qui va se charger d’inclure le fichier func.h dans prog.c. La commande gcc -E prog.c -o prog.i permet de mieux comprendre. En fait, elle demande à gcc de générer le résultat de la pré-compilation dans le fichier prog.i.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 1 "prog.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "prog.c"




# 1 "func.h" 1




void say_hello();
# 6 "prog.c" 2

int main(void)
{
    say_hello();
    return (0);
}

On comprend maintenant que le fichier prog.c est transformé avant la compilation afin que celui-ci contienne la déclaration de la fonction say_hello() afin de signaler au compilateur que le code de prog.c fait appel à une fonction dont le code est situé ailleurs. Le compilateur va en tenir compte lors de la construction de l’objet prog.o.

Maintenant, il ne reste plus qu’à assembler les objets prog.o et func.o avec la commande gcc prog.o func.o -o prog.

Voilà, vous savez maintenant comment faire pour écrire vos programmes en plusieurs fichiers.

En complément, voici le contenu du fichier Makefile:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
all: prog.o func.o
	gcc prog.o func.o -o prog

prog.o: prog.c func.h
	gcc -c prog.c -o prog.o

func.o: func.c
	gcc -c func.c -o func.o

.PHONY: clean

clean:
	rm -f func.o prog.o prog