Outils pour utilisateurs

Outils du site


dev:outils:gcc

Ceci est une ancienne révision du document !


GCC

Initialiment appelé Gnu C Compiler, il a été renommé Gnu Compiler Collection puisqu'il permet de compiler divers languages tels que:

  • C/C++
  • Objective C
  • Ada
  • Java
  • VHDL
  • etc

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 backend constitué par les bin-utils assemble et lie aux biliothèques les fichiers objets pour produire les fichiers executables.

La commande gcc est une interface permettant d'appeler de facon unifiée les différentes étapes de compilation.

Etapes de compilation

Le compilateur gcc de GNU passe par les étapes suivante pour compiler un fichier C:

  1. preprocesseur,
  2. compilation,
  3. liaison.

préprocesseur

Dans le fichier source, une ligne commencant 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 preprocesseur, 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 preprocesseur peut être révelé avec l'argument -E de gcc

exemple hello.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;
}
gcc -E hello.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;
}

A titre d'info:

cat hello.c | wc -l
17
gcc -E hello.c | wc -l
851

Notre fichier source hello.c passe de 17 lignes a 851 apres traitement via le préprocesseur

compilateur

pour demander a gcc de compiler un fichier source la syntaxe est la suivante:

gcc -c monfichier.c -o monfichier.o

(gcc genere un fichier assembleur (phase assemblage) puis un fichier objet) on peut demander a gcc de stopper la compilation a la phase de traduction en language assembleur pour voir le code assembleur intermediaire:

gcc -S hello.c

et traduire ensuite le code assembleur en code machine

as hello.c -o hello.o

Bibliothèques, liaison statique / dynamique

Une fois les fichiers objets créés, il faut les fusioner correctement pour creer le fichier executable (j'evite ici le terme assembler): c'est la phase d'édition des liens faite par le linker. la commande permettant d'invoquer le linker:

gcc monfichier.o -o monfichier

Sous Linux la plupart des executables sont liés dynamiquement, c'est a dire qu'ils n'incluent pas directement le code des fonctions utilisées. Lors de la phase d'edition de liens un code spécifique est ajouté, il est capable d'appeller du code en dehors de l'executable. pour voir a quelles bibliothèques un executable est lié commande ldd yoann@hermes:/tmp/helloWorld$ 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)

pour forcer le linker a faire une liaison statique: gcc -static monficheir.o -o monfichier

Utiliser des bibliothèque Si bibliothèque n'est pas dans un dossier standard il faut preciser au linker le dossier dans lequel elle est présente et son nom gcc -L ~/repertoire -lmalib monfichier.o -o monfichier

libmalib.so: dynamique (.so = shared object)) libmalib.a: statique

S'il s'agit d'une bibliothèque dynamique (libXXX.so), il faudra impérativement indiquer au programme chargeant les bibliothèques dynamiques ou elle se trouve. ceci peut etre fait grace a la variable d'environnement LD_LIBRARY_PATH

Creer une bibliothèque Pour liaison statique c'est rassembler plusieurs ficheirs 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

ar ruv libmalib.a module*.o ar: creating libmalib.a a - module1.o a - module2.o a - module3.o

dans le repertoire parent on modifie hello.c pour lui faire utiliser les fonctions on compile ensuite gcc hello.c -Llib -lm -lmalib -o hello

Pour liaison dynamique pour creer une bibliothèque dynamique gcc -shared module*.o -o libmalib.so le fichier libmalib.so est créé, il peut etre ensuite liée dynamiquement a l'executable hello gcc hello.o -L./lib -lmalib -lm -o hello.dyn

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)

yoann@hermes:/tmp/helloWorld$ ./hello.dyn ./hello.dyn: error while loading shared libraries: libmalib.so: cannot open shared object file: No such file or directory

dev/outils/gcc.1442590351.txt.gz · Dernière modification : 2021/02/01 21:51 (modification externe)