gcc
Accès rapide :
Rappels sur le processus de construction d'un programme C.
Options d'arrêt au terme d'une étape du cycle de construction d'un programme
Arrêt après la phase du pré-processeur.
Arrêt après l'étape de génération du code assembleur
Arrêt après la phase d'assemblage
Lancement de la phase d'édition des liens
Récapitulatif
Options relatives à la gestion des warnings
Compiler en mode « Debug »
Options relatives à des demandes d'optimisations
Obtention de l'aide
Le processus de construction d'un programme C (on parle aussi de processus de build), passe par plusieurs étapes : le préprocesseur, la compilation et la phase d'édition des liens.
L'étape de compilation peut elle-même être découpée en sous-parties : le contrôle du typage, la génération du code assembleur, puis celle du code machine.
Via diverses options, vous pouvez demander à gcc de s'arrêter au terme de n'importe quelle étape du processus de build.
Considérons le programme C suivant : il va nous servir à tester certaines des options proposées.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <stdio.h> #include <stdlib.h> #define a 10 #define b 20 #define min(x,y) ( (x)<(y) ? (x) : (y) ) int main() { int result = min( a, b ) + 2; printf( "Hello World with %d\n", result ); return EXIT_SUCCESS; } |
Pour demander un arrêt de gcc après la phase de pré-processeur, il faut utiliser l'option -E
.
$> gcc -E essai.c 1> temp.c
1> temp.c
.
Le fichier produit étant très conséquent (tous les fichiers inclus via la directive #include
ont été injectés dans le fichier final),
je me permets de vous en afficher que les dernières lignes.
$> cat temp.c ... Début du fichier produit ... # 8 "essai.c" int main() { int result = ( (10)<(20) ? (10) : (20) ) + 2; printf( "Hello World with %d\n", result ); return # 13 "essai.c" 3 4 0 # 13 "essai.c" ; }
EXIT_SUCCESS
).
Les plus curieux d'entre vous pourraient jeter un coup d'oeil sur le code assembleur produit. Pour ce faire, il faut utiliser l'option
-S
. Naturellement, le code ne sera pas assemblé pour produire le code machine.
$> gcc -S essai.c -o essai.ass
Et voici le contenu du fichier de code assembleur ainsi produit.
$> cat essai.asscat essai.ass .file "essai.c" .text .section .rodata .LC0: .string "Hello World with %d\n" .text .globl main .type main, @function main: .LFB6: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl $12, -4(%rbp) movl -4(%rbp), %eax movl %eax, %esi movl $.LC0, %edi movl $0, %eax call printf movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE6: .size main, .-main .ident "GCC: (GNU) 9.2.1 20190827 (Red Hat 9.2.1-1)" .section .note.GNU-stack,"",@progbits $>
C'est une étape que, normalement, vous connaissez bien : il suffit d'ajouter l'option -c
pour s'arrêter à ce niveau.
On se situe juste avant la phase d'édition des liens. Un fichier d'extension .o
(pour objet) sera produit.
$> gcc -c essai.c $> ls essai.c essai.o $>
Pour lancer la dernière phase du « build » de votre programme, il ne faut pas mettre d'option d'arrêt du processus de construction.
(-E
, -S
, -c
, ...). Il faut alors utiliser l'option -o
si vous souhaitez contrôler le
nom du fichier finalement produit. On peut envisager deux cas classiques.
Soit on lance un build complet à partir du code source original :
$> gcc essai.c -o essai
Soit on lance que la phase d'édition des liens à partir de fichiers .o
déjà produits.
$> gcc essai.o -o essai
Au terme de cette étape, vous avez normalement produit un exécutable.
$> ls -l -rwxrwxr-x. 1 dominique dominique 21976 27 nov. 16:42 essai -rw-rw-r--. 1 dominique dominique 231 27 nov. 16:42 essai.c -rw-rw-r--. 1 dominique dominique 1528 27 nov. 16:43 essai.o $> ./essai Hello World with 12 $>
-E : permet de stopper le processus de construction après la phase du pré-processeur.
-S : permet de stopper le processus de construction après l'étape de production du code assembleur.
-c : permet de stopper le processus de construction après la phase de compilation (ie, production du code assembleur, puis du code machine).
-o : permet de spécifier le nom du fichier produit, quelle que soit sa nature (code assembleur, code machine ou exécutable).
-Wall : affiche tous les types de warnings. Par exemple, avec cette option, les variables déclarées mais non utilisées produiront des warnings.
-Wconversion : affiche des warnings en cas de cast implicit et de perte de précision. Je vous recommande l'emploi systématique de cette
option. Attention, elle ne fait pas partie du périmètre de l'option -Wall
.
-Werror : demande au compilateur de traiter les warnings affichés en tant qu'erreurs. D'un certain point de vue, on peut juger cette possibilité comme étant très contraignante, mais d'un autre point de vue, cette option permet de mieux maîtriser la qualité des codes produits. Je vous recommande aussi l'emploi systématique de cette option.
-g : pour compiler votre programme en mode « Debug » et ainsi pouvoir y faire du pas à pas (via gdb, pourquoi pas).
Par défaut le compilateur ne cherche pas à jouer toutes les optimisations possibles. Si vous souhaitez contrôler l'optimisation de votre programme, il faudra utiliser l'une des options suivantes.
-O0 : aucune optimisation demandée.
-O1 : un premier niveau d'optimisation qui conserve une taille de l'exécutable minimale.
-O2 : un niveau d'optimisation intermédiaire avec un bon compromis sur la taille du fichier.
-O3 : toutes les optimisations sont demandées, quelles qu'en soient les conséquences sur la taille de l'exécutable.
Pour clore ce chapitre, notez que vous pouvez aussi obtenir de l'aide à propos de l'utilisation de votre compilateur gcc.
La manière la plus simple consiste à lancer la commande gcc
avec l'option --help
: une aide succincte
devrait apparaître.
$> gcc --help Usage : gcc [options] fichier... Options : -pass-exit-codes Quitter avec le plus grand code d'erreur d'une phase. --help Afficher cette aide. --target-help Afficher les options de ligne de commande spécifiques à la cible. --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]. Afficher les types spécifiques des options de la ligne de commande. (Utilisez " -v --help " pour afficher les options de la ligne de commande des sous-processus). --version Afficher des informations sur la version du compilateur. -dumpspecs Afficher toutes les chaînes de specs internes. -dumpversion Afficher la version du compilateur. -dumpmachine Afficher le processeur ciblé par le compilateur. -print-search-dirs Afficher les répertoires du chemin de recherche du compilateur. -print-libgcc-file-name Afficher le nom de la bibliothèque accompagnant le compilateur. -print-file-name=<lib> Afficher le chemin complet vers la bibliothèque <lib>. -print-prog-name=<prog> Afficher le chemin complet vers le composant <prog> du compilateur. -print-multiarch Afficher le triplet GNU normalisé de la cible, utilisé comme un composant dans le chemin d'accès de la bibliothèque. -print-multi-directory Afficher la racine du répertoire des versions de libgcc. -print-multi-lib Afficher la table de correspondance entre les options de la ligne de commande et les multiples répertoires de recherche des bibliothèques. -print-multi-os-directory Afficher le chemin relatif vers les bibliothèques de l'OS. -print-sysroot Afficher le répertoire des bibliothèques de la cible. -print-sysroot-headers-suffix Afficher le suffixe de la racine système utilisé pour trouver les en-têtes. -Wa,<options> Passer les <options> séparées par des virgules à l'assembleur. -Wp,<options> Passer les <options> séparées par des virgules au préprocesseur. -Wl,<options> Passer les <options> séparées par des virgules à l'éditeur de liens. -Xassembler <argument> Passer l'<argument> à l'assembleur. -Xpreprocessor <argument>Passer l'<argument> au préprocesseur. -Xlinker <argument> Passer l'<argument> à l'éditeur de liens. -save-temps Ne pas détruire les fichiers intermédiaires. -save-temps=<arg> Ne pas effacer les fichiers intermédiaires. -no-canonical-prefixes Ne pas normaliser les chemins lors de la compilation de préfixes relatifs à d'autres composants de gcc. -pipe Utiliser des pipes au lieu de fichiers intermédiaires. -time Mesurer le temps d'exécution de chaque sous-processus. -specs=<fichier> Remplacer les specs internes par le contenu du <fichier>. -std=<standard> Supposer que les fichiers sources respectent le <standard>. --sysroot=<répertoire> Utiliser <répertoire> comme répertoire racine pour les en-têtes et les bibliothèques. -B <répertoire> Ajouter le <répertoire> aux chemins de recherche du compilateur. -v Afficher les programmes invoqués par le compilateur. -### Identique à -v mais les options et les commandes entre guillemets ne sont pas exécutées. -E Pré-traitement seul ; ne pas compiler, assembler ou éditer les liens. -S Compilation seule ; ne pas assembler ou éditer les liens. -c Compiler et assembler, mais ne pas éditer les liens. -o <fichier> Placer la sortie dans le <fichier>. -pie Créer un exécutable indépendant de la position en mémoire (PIE) lié dynamiquement. -shared Créer une bibliothèque partagée. -x <langage> Spécifier le langage des fichiers d'entrée suivants. Les langages permis sont: c c++ assembler none "none" signifiant d'utiliser le comportement par défaut en tentant d'identifier le langage par l'extension du fichier. Options débutant par -g, -f, -m, -O, -W, ou --param sont automatiquement passées aux divers sous-processus invoqués par gcc. Afin de passer les autres options à ces processus l'option -W<lettre> doit être utilisé. Pour les instructions afin de rapporter des anomalies, consultez : <http://bugzilla.redhat.com/bugzilla>.
Pour obtenir une aide bien plus détaillée, lancez la commande man
sur le compilateur gcc.
$> man gcc
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :