Outils pour utilisateurs

Outils du site


dev:outils:gcc

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
dev:outils:gcc [2012/12/22 11:47] – créée rootdev:outils:gcc [2021/02/01 21:51] (Version actuelle) – modification externe 127.0.0.1
Ligne 1: Ligne 1:
 +{{tag>dev c compilation gcc}}
 +
 ====== GCC ====== ====== GCC ======
  
-Initialiment appelé Gnu C Compiler, il a été renommé Gnu Compiler Collection puisqu'il permet de compiler divers languages tels que:+Initialement appelé Gnu C Compiler, il a été renommé Gnu Compiler Collection puisqu'il permet de compiler divers langages tels que:
   * C/C++   * C/C++
   * Objective C   * Objective C
Ligne 11: Ligne 13:
 Gnu Compiler Collection est l'outil généraliste de compilation du projet GNU. Il s'articule autour de plusieurs outils: Gnu Compiler Collection est l'outil généraliste de compilation du projet GNU. Il s'articule autour de plusieurs outils:
   * Le frontend gcc qui a pour but d'analyser et de traduire les fichiers sources en code assembleur correspondant à la cible.   * Le frontend gcc qui a pour but d'analyser et de traduire les fichiers sources en code assembleur correspondant à la cible.
-  * Le backend constitué par les bin-utils assemble et lie aux biliothèques les fichiers objets pour produire les fichiers executables.+  * Le backend constitué par les bin-utils assemble et lie aux bibliothèques les fichiers objets pour produire les fichiers exécutables. 
 + 
 +La commande gcc est une interface permettant d'appeler de façon unifiée les différentes étapes de compilation. 
 + 
 + 
 +===== Étapes de compilation ===== 
 + 
 +Le compilateur gcc de GNU passe par les étapes suivante pour compiler un fichier C: 
 +  - préprocesseur, 
 +  - compilation, 
 +  - liaison. 
 + 
 +==== préprocesseur ==== 
 + 
 +Dans le fichier source, une ligne commençant par **#** n'est pas du C mais une directive pour le préprocesseur. Les directives telles que **#define** permettent d'augmenter la lisibilité et la maintenabilité du code. Le préprocesseur, appelé cpp (C PreProcessor) traite le fichier source en remplace les directives **#includes**, les commentaires etc. Le fichier obtenu en sortie est un fichier source contenant exclusivement des instructions C. 
 + 
 +Le travail du préprocesseur peut être révélé avec l'argument **-E** de gcc: 
 + 
 +<code c> 
 +/* 
 +######################################### 
 +# hello.c                               # 
 +# Mon premier programme C               # 
 +######################################### 
 +*/ 
 + 
 +#include <stdio.h> 
 +#define carre(a) ((a)*(a)) 
 + 
 +int main(void) 
 +
 +        printf("hello big world!\n"); 
 +        int nb=8; 
 +        printf("nb=%d et %d est son carre.\n", nb, carre(nb) ); 
 +        return 0; 
 +
 +</code> 
 + 
 +<code bash> 
 +gcc -E hello.c  
 +</code> 
 + 
 +<code c> 
 +# 1 "hello.c" 
 +# 1 "<built-in>" 
 +# 1 "<command-line>" 
 +# 1 "hello.c" 
 +... 
 +typedef struct 
 +
 +  int __count; 
 +  union 
 +  { 
 + 
 +    unsigned int __wch; 
 + 
 + 
 + 
 +    char __wchb[4]; 
 +  } __value; 
 +} __mbstate_t; 
 +... 
 +... 
 +... 
 +int main(void) 
 +
 + printf("hello big world!\n"); 
 + int nb=8; 
 + printf("nb=%d et %d est son carre.\n", nb, ((nb)*(nb)) ); 
 + return 0; 
 +
 +</code> 
 + 
 +Pour info, les commandes ci-dessous permettent de comparer les fichiers: 
 + 
 +<code bash> 
 +cat hello.c | wc -l 
 +17 
 +gcc -E hello.c | wc -l 
 +851 
 +</code> 
 + 
 +Notre fichier source hello.c passe de 17 lignes a 851 après traitement du préprocesseur. 
 + 
 +==== compilateur ==== 
 + 
 +Pour demander à gcc de compiler un fichier source la syntaxe est la suivante: 
 +<code bash> 
 +gcc -c monfichier.c -o monfichier.o 
 +</code> 
 + 
 +(gcc génère un fichier assembleur (phase assemblage) puis un fichier objet. On peut demander à gcc de stopper la compilation a la phase de traduction en langage assembleur pour voir le code assembleur produit: 
 + 
 +<code bash> 
 +gcc -S hello.c 
 +</code> 
 + 
 +Et traduire ensuite le code assembleur en code machine 
 +<code bash> 
 +as hello.c -o hello.o 
 +</code> 
 + 
 +==== linker ==== 
 + 
 +Une fois les fichiers objets créés, il faut les fusionner correctement pour créer le fichier exécutable (j’évite ici le terme assembler): c'est la phase d'édition des liens faite par le linker. 
 +la commande permettant d'invoquer le linker: 
 + 
 +<code bash> 
 +gcc monfichier.o -o monfichier 
 +</code> 
 + 
 +Sous Linux la plupart des exécutables sont **liés dynamiquement**, c'est à dire qu'ils n'incluent pas directement le code des fonctions utilisées. Lors de la phase d’édition de liens un code spécifique est ajouté, il est capable d’appeler du code en dehors de l’exécutable. 
 +  
 +Pour voir à quelles bibliothèques un exécutable est lié, utiliser la commande **ldd** 
 +<code bash> 
 +$ ldd hello.exe 
 +        linux-gate.so.1 =>  (0x00915000) 
 +        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00bc4000) 
 +        /lib/ld-linux.so.2 (0x009b9000) 
 +</code> 
 + 
 +On peut faire le choix d'utiliser à la place de la liaison dynamique la liaison statique. Lors de la phase d'édition des liens on utilise l'argument **-static**: 
 + 
 +<code bash> 
 +$ gcc -static monficheir.o -o monfichier 
 +</code> 
 + 
 +On obtient un binaire moins modulaire mais qui inclus le code dont il a besoin. S'il repose sur des bibliothèques qui ont été mises à jour, il faudra recompiler le programme pour qu'il intègre les modifications. 
 + 
 +===== Bibliothèques, liaison statique / dynamique ===== 
 + 
 +Lors de l'édition des liens, des fichiers objets présents dans des bibliothèques peuvent être spécifiés. 
 +Si la bibliothèque n'est pas dans un dossier standard il faut préciser au linker le dossier dans lequel elle est présente ainsi que son nom, c'est que permettent de faire les options **-L** (**%%--library-path=%%**) et **-l** (**%%--library=%%**) : 
 + 
 +<code bash> 
 +gcc -L ~/repertoire -lmalib monfichier.o -o monfichier 
 +</code> 
 + 
 +<note> 
 +A propos de la nomenclature du paramètre suivant l'option **-l**: s'il a la forme d'un nom de fichier, le linker recherche le fichier dans les répertoires des bibliothèques, sinon il considère que la bibliothèque est nommée libxx.so **-ltoto** correspond aux fichier **libtoto.so**   
 +</note> 
 + 
 +  * libmalib.so: bibliothèque contenant des fichiers objets pour liaison dynamique (.so = shared object)). 
 +  * libmalib.a: bibliothèque contenant des fichiers objets pour liaison statique. 
 + 
 +Pour un programme se reposant sur les liaisons dynamiques (libXXX.so), il faudra impérativement indiquer dans quels répertoires sont stockées les bibliothèques. Ceci peut être fait notamment grâce à la variable d'environnement **LD_LIBRARY_PATH** 
 + 
 +===== Créer une bibliothèque ===== 
 + 
 +==== Pour liaison statique ==== 
 + 
 +C'est rassembler plusieurs fichiers objets dans un seul fichier (une archive) avec **ar** (options ur (ajouter et remplace et v verbeux) 
 + 
 +  * On crée les fichiers lib/module1.c lib/module2.c lib/module3.c et malib.h 
 +  * On compile les fichiers sources puis on crée l'archive 
 + 
 +<code bash> 
 +$ ar ruv libmalib.a module*.o 
 +ar: creating libmalib.a 
 +a - module1.o 
 +a - module2.o 
 +a - module3.o 
 +</code> 
 + 
 +Dans le répertoire parent on modifie hello.c pour lui faire utiliser les fonctions. On compile ensuite: 
 + 
 +<code bash> 
 +$ gcc hello.c -Llib -lm -lmalib -o hello 
 +</code> 
 + 
 +==== Pour liaison dynamique ==== 
 + 
 +Pour créer une bibliothèque dynamique, utiliser l'option **-shared** 
 + 
 +<code> 
 +$ gcc -shared module*.o -o libmalib.so 
 +</code> 
 + 
 +Le fichier libmalib.so est créé, il peut être ensuite liée dynamiquement à l’exécutable hello: 
 + 
 +<code bash> 
 +$ gcc hello.o -L./lib -lmalib -lm -o hello.dyn 
 +</code> 
 + 
 +Pour vérifier à quelles bibliothèques dynamiques est lié notre exécutable:
  
-La commande gcc est une interface permettant d'appeler de facon unifiée les différentes étapes de compilation.+<code bash> 
 +$ ldd hello.dyn  
 +        linux-gate.so.1 =>  (0x00fc1000) 
 +        libmalib.so => not found 
 +        libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x00698000) 
 +        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00cb4000) 
 +        /lib/ld-linux.so.2 (0x004f8000) 
 +</code>
  
 +<code bash>
 +$ ./hello.dyn 
 +./hello.dyn: error while loading shared libraries: libmalib.so: cannot open shared object file: No such file or directory
 +</code>
  
 +===== Références =====
  
 +  * https://www.cmi.univ-mrs.fr/~contensi/coursC/index.php?section=env&page=comp
  
dev/outils/gcc.1356176876.txt.gz · Dernière modification : 2021/02/01 21:51 (modification externe)