Écrit par David Henry, le 4 juin 2006
Cet article est une introduction à la suite de compilateurs GCC et à son port win32, MinGW. Cet article ne se veut pas être une référence complète, mais plutôt un guide de « démarrage », ou à la limite une petite référence sur les options les plus utilisées de GCC.
Ce document s'adresse plus particulièrement aux programmeurs débutant voulant utiliser le compilateur libre GCC, ou aux développeurs qui veulent apprendre à utiliser GCC pour porter leurs programmes sur une autre platforme.
Je vais traiter ici à la fois de la compilation native avec GCC sous GNU/Linux et sous Windows, ainsi que comment faire de la compilation croisée avec MinGW pour Windows sur des systèmes autres que Windows.
GCC signifie « GNU Compiler Collection ». C'est une suite de compilateurs distribuée par le projet GNU. GCC a été créé par Richard Stallman en 1987 dans le but de fournir un compilateur C libre pour le développement du système d'exploitation GNU. À l'origine, GCC signifiait « GNU C Compiler » (il n'y avait que le compilateur C). GCC est distribué sous les termes de la licence GNU Public Licence (GPL).
GCC est une suite de compilateurs impressionnante, elle supporte 7 langages de programmation (officiellement, des front ends pour d'autres langages existent), permet de compiler pour une large variété d'architectures (environ 50 processeurs !) et a été porté sur un bon nombre de systèmes d'exploitation dont GNU/Linux, MacOS et Windows (les systèmes libres sont d'ailleurs généralement construits avec GCC). Il existe d'autres compilateurs dérivés de GCC visant des architectures plus spécifiques, comme les microcontrôleurs ou les circuits logiques programmables.
Voici la liste des langages supportés « officiellement » (faisant partie du projet GCC) et leur front end (compilateur spécifique au langage) respectif :
GCC est un compilateur en ligne de commande. Il ne fait que ce pour quoi il a été conçu : compiler. Vous pouvez écrire votre code avec n'importe quel éditeur de texte, comme vim, emacs (meilleur), kwrite, ou même avec les bloatwares que sont les IDE tels Kdevelop, Eclipse (ouch!) ou Code::blocks.
Afin d'illustrer les commandes de cet article, je vais utiliser le bien connu programme « hello world », dont voici le code en C :
#include <stdio.h> int main () { printf ("Hello world!\n"); return 0; }
En supposant que ce code a été sauvegardé dans le fichier hello.c, vous pouvez le compiler simplement en invoquant GCC avec le nom du fichier en paramètre. Dans un shell, tappez la commande suivante (le $ indique l'invite de commande, ne la recopiez pas !) :
$ gcc hello.c
Ceci produira un fichier binaire nommé a.out. Vous pouvez l'exécuter avec la commande suivante :
$ ./a.out
Comme prévu, le programme affichera la phrase « Hello world! » dans le shell. Si vous avez plusieurs fichiers source, vous pouvez tous les passer en paramètre à GCC ; ils seront compilés et liés ensemble :
$ gcc hello.c foo.c bar.c
Vous voudrez certainement donner un nom à votre programme autre que « a.out ».
Utilisez l'option -o
suivie du nom que vous souhaitez (notez que vous pouvez
placer cette option n'importe où dans la liste des options, comme toutes les autres
d'ailleurs) :
$ gcc -o hello hello.c
Vous pouvez demander à GCC de seulement compiler un fichier source avec l'option
-c
:
$ gcc -c hello.c
Ceci produira un fichier objet intermédiaire hello.o. Vous devrez alors appeler l'éditeur de liens afin d'obtenir un binaire exécutable. Pour invoquer l'éditeur de liens, appelez simplement GCC avec les fichiers objet en paramètre :
$ gcc -o hello hello.o
Vous pouvez ainsi compiler chaque fichier source de votre programme séparément, et appeler ensuite l'éditeur de liens :
$ gcc -c hello.c $ gcc -c foo.c $ gcc -c bar.c $ gcc -o hello hello.o foo.o bar.o
Par défaut, GCC recherche les fichiers d'en-tête (vous savez, ceux que incluez avec la
directive #include
) dans les dossiers /usr/local/include et
/usr/include.
Vous pouvez spécifier des répertoires d'include additionnels avec l'option
-I
suivie du chemin d'accès relatif ou absolu. Par convention, on ne place pas
d'espace entre l'option -I
et le chemin d'accès. Par exemple, si vous avez
des fichiers d'en-tête dans le dossier /somewhere/include, appelez :
$ gcc -o hello -I/somewhere/include hello.c
Pour lier votre exécutable avec une bibliothèque, utilisez l'option -l
suivie du nom de la bibliothèque sans le préfixe « lib » ni son extension. Par
exemple, imaginons que vous vouliez lier votre programme hello avec la
bibliothèque libpng (parce que votre programme peut sortir un super
smiley dans un fichier PNG). Vous devez avoir le fichier libpng.a (la
bibliothèque statique nécessaire pour la compilation) installé dans le dossier
/usr/lib (le dossier standard des bibliothèques) :
$ gcc -o hello hello.c -lpng
Comme pour les fichiers d'en-tête, GCC recherche les bibliothèques par défaut dans les
dossiers /usr/local/lib et /usr/lib. Vous pouvez spécifier des
répertoires additionnels avec l'option -L
, comme pour les includes :
$ gcc -o hello -L/somewhere/lib hello.c
Vous pouvez définir des macros avec l'option -D
, suivie du nom de la
macro et éventuellement sa valeur (séparés par un signe égal). La commande suivante va
compiler notre fichier source et définir la macro VALUE
avec une valeur de
10 :
$ gcc -o hello hello.c -DVALUE=10
GCC possède des options pour optimiser la compilation. Vous pouvez contrôler
l'optimisation avec cinq options : -O
(ou -O1
),
-O2
, -O3
, -Os
et -O0
(ne pas
optimiser). Chacune d'entre elle active en réalité un groupe d'optimisations individuelles.
Les options pour les optimisations individuelles commencent par la lettre « f »
dans leur nom (voir le manuel pour plus d'infos à leur sujet).
-O
: Premier niveau d'optimisation. Le compilateur tente de réduire
la taille du code et le temps d'exécution tout en limitant le temps de
compilation ;-O2
: Optimise plus. Par comparaison avec -O, cette option
augmente à la fois le temps de compilation et les performances du code généré ;-O3
: Optimise encore plus. -O3 active toutes les optimisations spécifiées
par -O2 plus d'autres ;-Os
: Optimise pour la taille. -Os actives toutes les optimisations de
-O2 qui n'ont pas d'impact négatif sur la taille du code. Elle effectue également d'autres
optimisations conçues pour réduire la taille du code ;-O0
: Ne pas optimiser. C'est le comportement par défaut de GCC.Par défaut, les exécutables produits par GCC gardent leur table de symboles et les
informations de relocation. Ceci a pour conséquence d'alourdir le fichier exécutable. Vous
pouvez retirer ces données en passant l'option -s
(pour « strip »)
à l'éditeur de liens :
$ gcc -o hello hello.o foo.o bar.o -s
La table de symboles est utile lors du déboguage, donc n'utilisez pas cette option si vous comptez ensuite utiliser un débogueur avec votre programme !
Je vous recommande aussi d'activer les messages d'avertissement avec l'option
-Wall
et de distribuer vos programmes compilant sans aucun avertissement.
Les options individuelles contrôlant les avertissement commencent par la lettre
« W » dans leur nom (voir le manuel). Mieux encore, vous pouvez utiliser l'option
-Werror
pour demander à GCC de traîter les avertissements comme des
erreurs ! (il est bon d'être rigoureux quand on programme)
Vous pouvez spécifier à GCC quelle norme (standard ?) vous voulez utiliser avec
l'option -std
, suivie du symbol égal et du nom de la norme. Voir le manuel pour la
liste des normes supportées pour chaque langage. Pour le langage C, vous pouvez utiliser
par exemple c89
pour du C Ansi ou c99
pour du C99. Pour le C
Ansi, vous pouvez également utiliser l'option -ansi
à la place de
-std
:
$ gcc -o hello1 hello.c -ansi $ gcc -o hello2 hello.c -std=c99
L'option -pedantic
affichera tous les avertissements requis par les standards
ISO C et ISO C++, et rejettera tout programme utilisant des extensions de ces langages ou
qui ne suivent pas la norme strictement. L'option -pedantic-errors
génère des
erreurs au lieu d'avertissements.
À présent, peut-être aimeriez vous savoir comment compiler en C++. C'est quasiment la même chose. Voici notre fameux hello world porté en C++ :
#include <iostream> int main () { std::cout << "Hello world!" << std::endl; return 0; }
La compilation est similaire à la compilation du programme en C. Notez qu'on lie l'exécutable avec la bibliothèque libstdc++ (du fait qu'on utilise iostream) :
$ g++ -o hello hello.cpp -lstdc++
Pour finir, je vais vous présenter l'ultime option d'avertissement de g++, teh
-Weffc++
option ! Si vous arrivez à compiler tout un projet avec cette
option activée, combinée avec l'option -Werror
, alors vous êtes un
Jedi :p
(astuce : c'est actuellement impossible avec la bibliothèque standard)
C'est tout pour GCC. Je pense avoir fait le tour des options les plus usuelles. Si vous en voulez plus, je vous recommande de jeter un œil au manuel de GCC.
MinGW est le port natif de GCC sous Windows. MinGW signifie « Minimalist GNU for Windows ». Le projet MinGW — démarré en juillet 1998 — apporte une collection d'outils afin de produire des programmes Windows natifs. Malheureusement, le développement de MinGW est un peu en retard par rapport à GCC.
MinGW inclut les fichiers d'en-tête et bibliothèques nécessaires pour programmer avec
l'API win32. Il fournit
également une implémentation (parfois partielle) de certaines fonctions POSIX qui ne sont
pas présentes sous d'autres compilateurs, comme Microsoft Visual Studio. Les fonctions
opendir
/readdir
pour la lecture des dossiers en sont un
exemple.
L'installation de MinGW est très simple. Vous pouvez l'obtenir sur la page de télécchagrement de MinGW. Téléchargez la dernière version de l'installeur mingw et lancez-le. Par défaut, MinGW sera installé dans C:\MinGW.
Je vous recommande également de télécharger et installer MSYS, un package qui apporte quelques outils très utiles lorsqu'on travaille avec GCC, comme un shell (bash) ou l'outil make.
Votre environnement de développement sous Windows est maintenant prêt. Vous pouvez lancer le shell de MSYS et utiliser GCC comme expliqué dans la section précédente.
MinGW peut également être utilisé sous Linux comme un compilateur croisé, permettant ainsi de construire des exécutables Windows natifs depuis son système préféré ;-)
Certaines distributions comme Debian proposent des paquets pour MinGW. Utilisez
simplement apt-get
(ou les outils de package de votre distro) pour les
installer :
# apt-get install mingw32
Les paquets mingw32-binutils et mingw32-runtime seront également
installé en tant que dépendances. Vous pouvez ensuite invoquer GCC en appelant
i586-mingw32msvc-gcc
, i586-mingw32msvc-g++
, etc., au lieu de
gcc
, g++
, ...
À noter que les programmes C++ seront bien plus gros en taille que ceux produits pour Linux ou par Microsoft Visual Studio. Ceci est dû au fait que la bibliothèque standard doit être liée statiquement avec l'exécutable.
Dans cette section je vais présenter succinctement quelques autres outils souvent utilisés avec GCC. Cependant, leur fonctionnement sort du cadre de cet article et je ne le détaillerai donc pas.
make est l'outil à connaître lorsqu'on veut développer avec GCC !
Il est utilisé afin d'automatiser les compilations. Vous placez vos instructions de
compilation dans un fichier Makefile puis invoquez make
dans votre
shell pour lancer la compilation. make peut également déterminer les portions de votre
programme qui doivent être recompilées, évitant ainsi une recompilation complète à chaque
fois que vous apportez une modification.
gdb est le débogueur GNU. Pour activer le déboguage vous vous devez
compiler avec l'option -g
et désactiver toutes les optimisations.
valgrind est un autre outil excellent pour déboguer les fuites de
mémoire.
colorgcc est un wrapper pour GCC affichant les messages d'erreur et d'avertissement en couleurs. Très pratique !
Voici quelques liens si vous voulez en connaître un peu plus sur GCC et MinGW :
Cet article est mis à disposition sous un contrat Creative Commons (licence CC-BY-ND).