Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
dev:outils:gcc [2012/12/22 11:47] – créée root | dev:outils:gcc [2021/02/01 21:51] (Version actuelle) – modification externe 127.0.0.1 | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | {{tag> | ||
+ | |||
====== GCC ====== | ====== GCC ====== | ||
- | Initialiment | + | Initialement |
* C/C++ | * C/C++ | ||
* Objective C | * Objective C | ||
Ligne 11: | Ligne 13: | ||
Gnu Compiler Collection est l' | Gnu Compiler Collection est l' | ||
* Le frontend gcc qui a pour but d' | * Le frontend gcc qui a pour but d' | ||
- | * Le backend constitué par les bin-utils assemble et lie aux biliothèques | + | * Le backend constitué par les bin-utils assemble et lie aux bibliothèques |
+ | |||
+ | La commande gcc est une interface permettant d' | ||
+ | |||
+ | |||
+ | ===== É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' | ||
+ | |||
+ | Le travail du préprocesseur peut être révélé avec l' | ||
+ | |||
+ | <code c> | ||
+ | /* | ||
+ | ######################################### | ||
+ | # hello.c | ||
+ | # Mon premier programme C # | ||
+ | ######################################### | ||
+ | */ | ||
+ | |||
+ | #include < | ||
+ | #define carre(a) ((a)*(a)) | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | printf(" | ||
+ | int nb=8; | ||
+ | printf(" | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | gcc -E hello.c | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | # 1 " | ||
+ | # 1 "< | ||
+ | # 1 "< | ||
+ | # 1 " | ||
+ | ... | ||
+ | typedef struct | ||
+ | { | ||
+ | int __count; | ||
+ | union | ||
+ | { | ||
+ | |||
+ | unsigned int __wch; | ||
+ | |||
+ | |||
+ | |||
+ | char __wchb[4]; | ||
+ | } __value; | ||
+ | } __mbstate_t; | ||
+ | ... | ||
+ | ... | ||
+ | ... | ||
+ | int main(void) | ||
+ | { | ||
+ | | ||
+ | int nb=8; | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 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 | ||
+ | </ | ||
+ | |||
+ | 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 | ||
+ | </ | ||
+ | |||
+ | (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 | ||
+ | </ | ||
+ | |||
+ | Et traduire ensuite le code assembleur en code machine | ||
+ | <code bash> | ||
+ | as hello.c -o hello.o | ||
+ | </ | ||
+ | |||
+ | ==== 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' | ||
+ | la commande permettant d' | ||
+ | |||
+ | <code bash> | ||
+ | gcc monfichier.o -o monfichier | ||
+ | </ | ||
+ | |||
+ | Sous Linux la plupart des exécutables sont **liés dynamiquement**, | ||
+ | |||
+ | 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 => / | ||
+ | / | ||
+ | </ | ||
+ | |||
+ | On peut faire le choix d' | ||
+ | |||
+ | <code bash> | ||
+ | $ gcc -static monficheir.o -o monfichier | ||
+ | </ | ||
+ | |||
+ | 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, | ||
+ | |||
+ | Lors de l' | ||
+ | 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 ~/ | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | A propos de la nomenclature du paramètre suivant l' | ||
+ | </ | ||
+ | |||
+ | * libmalib.so: | ||
+ | * libmalib.a: bibliothèque contenant des fichiers objets pour liaison statique. | ||
+ | |||
+ | Pour un programme se reposant sur les liaisons dynamiques (libXXX.so), | ||
+ | |||
+ | ===== 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/ | ||
+ | * On compile les fichiers sources puis on crée l' | ||
+ | |||
+ | <code bash> | ||
+ | $ ar ruv libmalib.a module*.o | ||
+ | ar: creating libmalib.a | ||
+ | a - module1.o | ||
+ | a - module2.o | ||
+ | a - module3.o | ||
+ | </ | ||
+ | |||
+ | 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 | ||
+ | </ | ||
+ | |||
+ | ==== Pour liaison dynamique ==== | ||
+ | |||
+ | Pour créer une bibliothèque dynamique, utiliser l' | ||
+ | |||
+ | < | ||
+ | $ gcc -shared module*.o -o libmalib.so | ||
+ | </ | ||
+ | |||
+ | 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 | ||
+ | </ | ||
+ | |||
+ | Pour vérifier à quelles bibliothèques dynamiques est lié notre exécutable: | ||
- | La commande gcc est une interface permettant d' | + | <code bash> |
+ | $ ldd hello.dyn | ||
+ | linux-gate.so.1 => (0x00fc1000) | ||
+ | libmalib.so => not found | ||
+ | libm.so.6 => / | ||
+ | libc.so.6 => / | ||
+ | / | ||
+ | </ | ||
+ | <code bash> | ||
+ | $ ./ | ||
+ | ./ | ||
+ | </ | ||
+ | ===== Références ===== | ||
+ | * https:// | ||