Commmande Unix g++

Compilateur g++ projet GNU Egcs-1.1.2 release

© D. Mathieu     mathieu@romarin.univ-aix.fr
I.U.T.d'Aix en Provence - Département Informatique
Créé le 04/08/2000 - Dernière mise à jour : 17/10/2001

Sommaire

Introduction
Options
option -o : choix du nom de l'exécutable
option -c : suppression de l'édition de liens
option -I : répertoire(s) des fichiers inclus
option -D : positionnement de macros
option -s : suppression d'informations pour le débogueur
option -W : messages "warning"
option -l : utilisation de bibliothèque(s)
option -L : répertoire(s) des bibliothèque(s)
Conclusions

Remarques préliminaires :

    Ce document ne constitue pas un cours sur la commande Unix de compilation (C ou C++, quel que soit le compilateur, ici compilateur g++ : projet GNU Egcs-1.1.2 release). Il se contente de rappeler quelques éléments fondamentaux et indispensables à l'utilisation de ces compilateurs.

    On pourra trouver dans le document "Tests effectués sur le compilateur g++" des remarques personnelles et des essais sur des bugs détectés dans cette version, des améliorations constatees par rapport à la version précédente, des points non conformes à la norme C++, etc...

Introduction

    Sous sa forme la plus simple, la commande g++ peut être utilisée ainsi sur le fichier source simple.cxx :
 
g++ simple.cxx

    Elle s'exécute en plusieurs phases :

Remarque : l'édition de liens détecte une erreur si le fichier simple.cxx ne comporte pas la définition de la fonction main().

    Lorsque le code est scindé dans plusieurs fichiers source, par exemple complexe.cxx, Part1.cxx et Part2.cxx, la production de l'exécutable peut être obtenue par :
 
g++ complexe.cxx Part1.cxx Part2.cxx

quel que soit l'ordre des fichiers .cxx dans la commande. Cela n'a pas toujours été le cas et, pour éviter tout désagrément avec un ancien compilateur, il est préférable de les mettre dans l'ordre des dépendances, de même que pour l'édition des liens.

    Après compilation, le répertoire courant contient le fichier exécutable a.out.

Sommaire

Options

    Les options présentées ici le sont par ordre chronologique : les premières sont immédiatement nécessaires, les dernières peuvent être ignorées dans un premier temps.

option -o

    Sauf pour de petits essais, il est maladroit d'utiliser comme nom de commande l'identificateur par défaut a.out. Au contraire, il est habituel (et conseillé) de donner à la commande le nom du fichier source qui contient la fonction main(), dépourvu d'extension (pour les TPs de système, c'est le nom du fichier qui contient la fonction ppal() qui doit être utilisé). Ici, l'exécutable sera donc simple. C'est l'option -o, suivie d'un espace et du nom d'exécutable choisi, qui permet d'obtenir ce résultat :
 
g++ simple.cxx -o simple

    La place de l'option dans la ligne est indifférente :
 
g++ -o simple simple.cxx 
ou, pour le deuxième exemple :
 
g++ -o complexe complexe.cxx Part1.cxx Part2.cxx

Sommaire

option -c

    Il est peu efficace de recompiler la totalité des fichiers sources lorsqu'un seul a été modifié. Il faut alors faire de la compilation séparée, et dissocier les deux dernières phases : compilation et édition de liens. Pour reprendre l'exemple ci-dessus, il faut compiler en trois fois les fichiers sources complexe.cxx, Part1.cxx et Part2.cxx, pour obtenir les fichiers objets .o correspondants, puis faire l'édition de liens de ces derniers. L'arrêt de la compilation après obtention du fichier objet (.o), est réalisé grâce à l'option -c :
 
g++ -c complexe.cxx 
g++ -c Part1.cxx 
g++ -c Part2.cxx

l'édition de liens est obtenue par :
 
g++ -o complexe complexe.o Part1.o Part2.o

    Si par exemple le  fichier Part1.cxx doit être recompilé, la commande suivante peut alors être utilisée :
 
g++ -o complexe complexe.o Part1.cxx Part2.o

Remarque : l'option -c n'a de sens qu'utilisée dans la phase de compilation.

Sommaire

option -I

    Le C/C++ distingue deux sortes de fichiers entête (fichiers inclus)

    L'utilisation de chemins pour inclure des fichiers des utilisateurs est aussi à proscrire, car toute modification de l'arborescence des répertoires nécessite une mise à jour des fichiers sources, ce qui représente un grand risque d'erreur (oublis, utilisation d'une mauvaise version du fichier inclus, etc...). C'est pourquoi l'option -I permet d'indiquer à la compilation dans quel(s) répertoire(s) le compilateur doit aller chercher les fichiers inclus des utilisateurs. Le répertoire doit suivre immédiatement l'option -I (sans espace).

    Supposons que les fichiers locaux.h, nsSysteme.h et nsNet.h soient respectivement (à partir du noeud /users/etud2/taralf/tp/), dans les répertoires tpsys/dirfile, tpsys/include et tpnet/include. En utilisant la commande suivante :
 
g++ -o complexe.cxx -I/users/etud2/taralf/tp/tpsys/dirfile     \
                    -I/users/etud2/taralf/tp/tpsys/include     \
                    -I/users/etud2/taralf/tp/tpnet/include

avec :
 
// fichier complexe.cxx
//
#include "locaux.h"
#include "nsSysteme.h"
#include "nsNet.h"
// ...

le compilateur va chercher chacun des trois fichiers inclus successivement :

    La seule difficulté se présente lorsque un fichier est présent dans plusieurs des répertoires explorés : le compilateur utilise la première instance rencontrée.

Remarques :

Sommaire

option -D

    Les macros destinées au préprocesseur sont très souvent utilisées pour effectuer de la compilation conditionnelle. Ainsi, la séquence suivante n'est compilée que si le préprocesseur a rencontré dans la même phase de compilation, la définition de la macro _DEBUG :
 
// fichier complexe.cxx
//
...
#define _DEBUG
...
#ifdef _DEBUG
    #include "nsSystemeDbg.hxx" // contient les mêmes fonctions que nsSysteme.hxx, 
                                // avec des informations de débogage en plus
#else
    #include "nsSysteme.hxx"
#endif 

    Dans l'exemple suivant :
 
// fichier Part1.cxx
//
...
#define _DEBUG
...
 
// fichier complexe.cxx
//
...
#ifdef _DEBUG
    #include "nsSystemeDbg.hxx" // contient les mêmes fonctions que nsSysteme.hxx, 
                                // avec des informations de débogage en plus
#else
    #include "nsSysteme.hxx"
#endif 

la macro _DEBUG  n'est pas déclarée lorsque le compilateur compile le fichier complexe.cxx par la commande :
 
g++ -o complexe Part1.cxx Part2.cxx complexe.cxx

car il s'agit d'unités de compilation différentes : elles donnent lieu à trois fichiers objets.

    Les macros peuvent être définies au lancement de la commande g++, grâce à l'option -D suivie (sans espace) de la macro définie (autant d'options -D que de macros à définir). Par exemple :
 
g++ -c -D_DEBUG complexe.cxx

Sommaire

option -s

    L'option -s (strip) permet de diminuer de façon sensible la taille du code généré à l'édition de liens. Elle supprime en effet une table de références croisées, dans laquelle sont conservées de nombreuses informations permettant le débogage, en particulier la liste des identificateurs du code source et les numéros de ligne où ils apparaissent.

Remarques :

Sommaire

option -W

    L'option -W permet d'afficher tout ou partie des messages d'avertissement (warning). De très nombreuses possibilités sont offertes au développeur. Nous ne conserverons que la plus complète, qui affiche tous les messages :
 
g++ -c complexe.cxx -Wall

    Nous vous conseillons vivement de ne pas supprimer cette option, même si les messages sont parfois nombreux et peuvent être négligés : ils font souvent apparaître des petites erreurs qui peuvent avoir de grandes conséquences ...

Remarque : il est absurde d'utiliser cette option pour la phase d'édition de liens !

Sommaire

option -l

    Lorsque le nombre de fichiers objets .o devient important, la commande d'édition de liens devient elle aussi trop longue et illisible. De plus peuvent y figurer des fichiers inutiles pour certaines compilations, mais utiles pour d'autres. C'est le cas lorsqu'on utilise des fichiers Makefile. Il est alors préférable de stocker les différents fichiers objets dans une bibliothèque (Library) d'où l'éditeur de liens n'extrait que les modules qui lui sont nécessaires. La taille de l'exécutable en est en général sensiblement réduite, et la ligne de commande très simplifiée.

    Outre les bibliothèques standard qu'il est inutile de signaler (libc.a par exemple, qui est la bibliothèque standard du C), plusieurs bibliothèques peuvent être utilisées, comme par exemple libgcc.a, libg++.a. Il est aussi possible d'ajouter à la ligne de compilation (pour l'édition de liens) la liste des bibliothèques personnelles.

    L'identificateur d'une bibliothèque doit commencer par lib et avoir pour extension .a. Ces deux parties ne sont jamais indiquées dans la ligne de commande. Une bibliothèque peut être créée et gérée par la commande ar. Par exemple, s'il existe deux bibliothèques libSys.a et libNet.a, elles peuvent être utilisées dans la ligne de compilation de la façon suivante :
 
g++ -s -o exo_01 exo_01.o -lSys -lNet

Sommaire

option -L

    L'option -L peut être utilisée pour indiquer le(s) répertoire(s) dans le(s)quel(s) le compilateur doit aller chercher les bibliothèques utilisées, par exemple :
 
g++ -s -o exo_01 exo_01.o -L$(HOME)/tp/tpsys -lSys -L$(HOME)/tp/tpnet -lNet

Sommaire

Conclusions

     Le compilateur g++ offre d'innombrables autres possibilités, dont certaines assez intéressantes, mais vous avez la possibilité de les découvrir en consultant le manuel de référence (man 1 g++, ou xman). Elle signale d'ailleurs qu'elle est incomplète et mal entretenue, donc il est certainement intéressant d'aller fureter dans des livres spécialisés ou sur Internet !

    Les commandes de compilation étant longues et répétitives, nous vous engageons à utiliser les possibilités des alias, et surtout de la commande make.

Sommaire

© D. Mathieu     mathieu@romarin.univ-aix.fr
I.U.T.d'Aix en Provence - Département Informatique