Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[Debutant] g++ / editeur de lien / compilateur

3 réponses
Avatar
Olivier BURELLI
Bonjour tout le monde,

J'=C3=A9tudie depuis peu le C++, bien qu'ayant un peu programm=C3=A9 plus j=
eune,
je suis rellement debutant.

Mon support de cours est un livre "Le langage C++" de J. Liberty et B.
Jones aux editions Pearson.

Dans ce dernier, il est explique la chose suivante,=20
au lancement du compilateur il se passe :

1- Compilation
2- Editions des liens
3- cr=C3=A9ation de l'ex=C3=A9cutable.

Je travaille sous OpenBSD release 4.9 avec g++ en version 4.2.1

Je ne comprends pas la chose suivante :

lors de la compilation :

g++ source.cpp -o executable

je n'ai pas de fichier objet de cree ex: file.o

si j'utilise un IDE tel que Code::Block, avec le meme fichier source
lors de la compilation ou du build (je ne saisie pas la difference dans
ce cas)

j'obtiens bien un main.o dans l'arborescence du projet.

un man gcc m'indique :

-c Compile or assemble the source files, but do not link. The linking
stage simply is not done. The ultimate output is in the form of=
an
object file for each source file.

By default, the object file name for a source file is made by
replacing the suffix .c, .i, .s, etc., with .o.

Unrecognized input files, not requiring compilation or assembly,
are ignored.


ce qui n'est pas mon cas, de plus mon fichier source est bien : file.cpp

Bref, j'ai compris la theorie, mais ne retrouve pas mes petits dans la
pratique.

Merci pour vos eclaircissements.

Zolive.

3 réponses

Avatar
Pascal J. Bourguignon
Olivier BURELLI writes:

Bonjour tout le monde,

J'étudie depuis peu le C++, bien qu'ayant un peu programmé plus jeune,
je suis rellement debutant.

Mon support de cours est un livre "Le langage C++" de J. Liberty et B.
Jones aux editions Pearson.

Dans ce dernier, il est explique la chose suivante,
au lancement du compilateur il se passe :

1- Compilation
2- Editions des liens
3- création de l'exécutable.

Je travaille sous OpenBSD release 4.9 avec g++ en version 4.2.1

Je ne comprends pas la chose suivante :

lors de la compilation :

g++ source.cpp -o executable

je n'ai pas de fichier objet de cree ex: file.o

si j'utilise un IDE tel que Code::Block, avec le meme fichier source
lors de la compilation ou du build (je ne saisie pas la difference dans
ce cas)

j'obtiens bien un main.o dans l'arborescence du projet.

un man gcc m'indique :

-c Compile or assemble the source files, but do not link. The linking
stage simply is not done. The ultimate output is in the form of an
object file for each source file.

By default, the object file name for a source file is made by
replacing the suffix .c, .i, .s, etc., with .o.

Unrecognized input files, not requiring compilation or assembly,
are ignored.


ce qui n'est pas mon cas, de plus mon fichier source est bien : file.cpp

Bref, j'ai compris la theorie, mais ne retrouve pas mes petits dans la
pratique.

Merci pour vos eclaircissements.



gcc, ou g++, n'est pas le compilateur, mais le pilote du compilateur.


Le compilateur est dans un répertoire comme:

$ /bin/ls /usr/libexec/gcc/x86_64-pc-linux-gnu/4.4.5/
cc1 cc1obj cc1objplus cc1plus collect2 ecj1 f951 jc1 jvgenmain


Le pilote du compilateur, pour C ou C++, appelle d'abord le
préprocesseur /usr/bin/cpp, passe le résultat au compilateur, qui
produit un source assembleur, passe le résultat à l'assembleur
/usr/bin/as qui produit un binaire, passe ce binaire avec les
bibliothèques standard (voir par exemple dans
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/) à l'éditeur de liens
/usr/bin/ld.


On a donc plein de "fichiers intermédiaires", et ça ferait brouillon de
les laisser sur place. Donc gcc fait le ménage et les supprime.

À moins qu'on ne le demande:

-E --> arrêter après cpp, et laisser le source préprocessé.
-S --> arrêter après cc1, cc1plus, et laisser l'assembleur généré.
-c --> arrêter après as, et laisser l'objet généré.


En fait, si on ne passe pas une de ces options, gcc peut faire les
choses de façons plus optimisée, en connectant les commandes via des
pipes, afin d'éviter le passage par des fichiers temporaires, quand on
lui donne l'option -pipe.



Donc, quand on n'a qu'un seul source, où quand la compilation de tous
les sources d'un programme prends moins de temps que taper la commande
de compilation, il ne sert à rien de faire de la compilation séparée, et
on peut utiliser gcc comme tu l'as fait:

gcc a.c b.c d.c -o pgm
gcc *.c -o pgm




Mais si la compilation d'un fichier est longue (par exemple, un source
C++ utilisant beaucoup d'includes avec plein de templates), alors ça
vaut le coup de faire de la compilation séparée, afin de ne pas avoir à
recompiler tous les fichiers quand on n'en modifie qu'un seul. On écrit
alors un Makefile indiquant les depéndences entre les fichiers sources
et les entêtes, et on utilise l'option -c pour arrêter la compilation à
la génération du binaire.


INCLUDES=-I.

a.cpp:a.hpp c.hpp
b.cpp:b.hpp c.hpp
c.cpp:c.hpp

%.o:%.cpp
g++ $(INCLUDES) -c -o %.o %.cpp

pgm:a.o b.o c.o
g++ -o pgm a.o b.o c.o

Ainsi, quand on modifie un source, on ne recompile que celui-ci, et on
effectue une édition de lien, au lieu de compiler tous les sources avant
de faire l'édition de lien.

Mais si on modifie un entête commun, on devra tout recompiler de toutes
façons.

Et comme l'implémentation des classes en C++ doit souvent être écrite
dans les entêtes (champs private et protected, méthodes inline), il
arrive souvent qu'en C++ on doive tout recompiler de toutes façons...



--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Avatar
Marc
"Pascal J. Bourguignon" wrote:

On a donc plein de "fichiers intermédiaires", et ça ferait brouillon de
les laisser sur place. Donc gcc fait le ménage et les supprime.

À moins qu'on ne le demande:

-E --> arrêter après cpp, et laisser le source préprocessé.
-S --> arrêter après cc1, cc1plus, et laisser l'assembleur généré.
-c --> arrêter après as, et laisser l'objet généré.



-save-temps et -v peuvent aussi aider, dans un but pédagogique.
Avatar
Olivier BURELLI
On Mon, 16 May 2011 20:04:33 +0200
"Pascal J. Bourguignon" wrote:

Olivier BURELLI writes:

> Bonjour tout le monde,
>
> J'étudie depuis peu le C++, bien qu'ayant un peu programmé plus
> jeune, je suis rellement debutant.
>
> Mon support de cours est un livre "Le langage C++" de J. Liberty et
> B. Jones aux editions Pearson.
>
> Dans ce dernier, il est explique la chose suivante,
> au lancement du compilateur il se passe :
>
> 1- Compilation
> 2- Editions des liens
> 3- création de l'exécutable.
>
> Je travaille sous OpenBSD release 4.9 avec g++ en version 4.2.1
>
> Je ne comprends pas la chose suivante :
>
> lors de la compilation :
>
> g++ source.cpp -o executable
>
> je n'ai pas de fichier objet de cree ex: file.o
>
> si j'utilise un IDE tel que Code::Block, avec le meme fichier source
> lors de la compilation ou du build (je ne saisie pas la difference
> dans ce cas)
>
> j'obtiens bien un main.o dans l'arborescence du projet.
>
> un man gcc m'indique :
>
> -c Compile or assemble the source files, but do not link. The
> linking stage simply is not done. The ultimate output is in the
> form of an object file for each source file.
>
> By default, the object file name for a source file is
> made by replacing the suffix .c, .i, .s, etc., with .o.
>
> Unrecognized input files, not requiring compilation or
> assembly, are ignored.
>
>
> ce qui n'est pas mon cas, de plus mon fichier source est bien :
> file.cpp
>
> Bref, j'ai compris la theorie, mais ne retrouve pas mes petits dans
> la pratique.
>
> Merci pour vos eclaircissements.

gcc, ou g++, n'est pas le compilateur, mais le pilote du compilateur.


Le compilateur est dans un répertoire comme:

$ /bin/ls /usr/libexec/gcc/x86_64-pc-linux-gnu/4.4.5/
cc1 cc1obj cc1objplus cc1plus collect2 ecj1 f951 jc1
jvgenmain


Le pilote du compilateur, pour C ou C++, appelle d'abord le
préprocesseur /usr/bin/cpp, passe le résultat au compilateur, qui
produit un source assembleur, passe le résultat à l'assembleur
/usr/bin/as qui produit un binaire, passe ce binaire avec les
bibliothèques standard (voir par exemple dans
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/) à l'éditeur de liens
/usr/bin/ld.


On a donc plein de "fichiers intermédiaires", et ça ferait brouillon
de les laisser sur place. Donc gcc fait le ménage et les supprime.

À moins qu'on ne le demande:

-E --> arrêter après cpp, et laisser le source préprocessé.
-S --> arrêter après cc1, cc1plus, et laisser l'assembleur génér é.
-c --> arrêter après as, et laisser l'objet généré.


En fait, si on ne passe pas une de ces options, gcc peut faire les
choses de façons plus optimisée, en connectant les commandes via des
pipes, afin d'éviter le passage par des fichiers temporaires, quand on
lui donne l'option -pipe.



Donc, quand on n'a qu'un seul source, où quand la compilation de tous
les sources d'un programme prends moins de temps que taper la commande
de compilation, il ne sert à rien de faire de la compilation séparé e,
et on peut utiliser gcc comme tu l'as fait:

gcc a.c b.c d.c -o pgm
gcc *.c -o pgm




Mais si la compilation d'un fichier est longue (par exemple, un source
C++ utilisant beaucoup d'includes avec plein de templates), alors ça
vaut le coup de faire de la compilation séparée, afin de ne pas avoir
à recompiler tous les fichiers quand on n'en modifie qu'un seul. On
écrit alors un Makefile indiquant les depéndences entre les fichiers
sources et les entêtes, et on utilise l'option -c pour arrêter la
compilation à la génération du binaire.


INCLUDES=-I.

a.cpp:a.hpp c.hpp
b.cpp:b.hpp c.hpp
c.cpp:c.hpp

%.o:%.cpp
g++ $(INCLUDES) -c -o %.o %.cpp

pgm:a.o b.o c.o
g++ -o pgm a.o b.o c.o

Ainsi, quand on modifie un source, on ne recompile que celui-ci, et on
effectue une édition de lien, au lieu de compiler tous les sources
avant de faire l'édition de lien.

Mais si on modifie un entête commun, on devra tout recompiler de
toutes façons.

Et comme l'implémentation des classes en C++ doit souvent être écri te
dans les entêtes (champs private et protected, méthodes inline), il
arrive souvent qu'en C++ on doive tout recompiler de toutes façons...






Je vous remercie de vos lumières, je pense avoir compris l'essentiel :)

j'aborderai tout cela je pense bien plus tard, je garderai en memoire
le fonctionnement demontre ci-dessus.

Effectivement le compilateur chez moi se trouve ici :

ls -la /usr/lib/gcc-lib/amd64-unknown-openbsd4.9/4.2.1/

drwxr-xr-x 2 root bin 512 May 15 18:15 .
drwxr-xr-x 3 root wheel 512 Mar 2 13:40 ..
-r-xr-xr-x 1 root bin 5979256 May 15 18:14 cc1
-r-xr-xr-x 1 root bin 6047992 May 15 18:15 cc1obj
-r-xr-xr-x 1 root bin 6539776 May 15 18:15 cc1plus
-r-xr-xr-x 1 root bin 109016 May 15 18:15 collect2
-r--r--r-- 1 root bin 555742 May 15 18:15 libgcc.a
-rw-r--r-- 1 root bin 4351 May 15 18:14 specs

et le preprocesseur se trouve la :

/usr/libexec/cpp

le menage a ete fait, et ma tete va exploser -)

Cdt,

Zolive