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

Liaison statique ou dynamique

21 réponses
Avatar
Lucas Levrel
Bonjour,

Je cross-poste sans FU2 car je ne sais pas quel est le groupe le plus
adapté, et la réponse peut même varier selon l'OS, alors je vous laisse
voir...

J'écris un programme en C++ avec une interface en GTK+ (mais mes questions
sont plus générales). Sous Windows, GTK+ est livré avec des .def, .lib,
.dll.a, et .dll (chaque bibli a un ou plusieurs fichiers avec ces
extensions). Sous Linux j'ai des .so et .la pour certaines biblis,
seulement des .so pour d'autres.

Je compile avec GCC (dans MinGW sous Windows). Je voudrais obtenir un
exécutable qui se suffise à lui-même, c'est-à-dire utilisable sans
installer GTK+ au préalable (donc distribuable sans redistribuer GTK+ à
côté). Je croyais l'obtenir en passant l'option -static à GCC, d'ailleurs
le fichier produit est beaucoup plus gros avec cette option que sans. Mais
patatras : sous Win, si je tente de lancer l'exécutable « statique » sur
une machine n'ayant pas GTK+, j'obtiens une erreur « ne trouve pas
libmachin.dll » ; sous Linux, n'ayant pas de machine sans GTK+ à dispo, je
n'ai pas pu tester (y a-t-il moyen de « cacher » les biblis installées le
temps d'un test ?).

Mes questions sont donc :
- peut-on produire un exécutable qui se suffise à lui-même, et avec
quelles options de compilation ?
- si oui, quels sont les ingrédients nécessaires en termes de
bibliothèques (quel format de fichier) ?
- à défaut, peut-on « dégraisser » des bibliothèques dynamiques pour n'en
garder que les fonctions réellement utilisées par l'application ? (L'idée
étant d'alléger au maximum le paquet exécutable+biblis à distribuer.)

Merci pour votre aide et vos explications.

--
LL

10 réponses

1 2 3
Avatar
JKB
Le Thu, 8 Mar 2012 13:01:49 +0100,
Lucas Levrel écrivait :
Bonjour,



Bonjour,

Je cross-poste sans FU2 car je ne sais pas quel est le groupe le plus
adapté, et la réponse peut même varier selon l'OS, alors je vous laisse
voir...

J'écris un programme en C++ avec une interface en GTK+ (mais mes questions
sont plus générales). Sous Windows, GTK+ est livré avec des .def, .lib,
.dll.a, et .dll (chaque bibli a un ou plusieurs fichiers avec ces
extensions). Sous Linux j'ai des .so et .la pour certaines biblis,
seulement des .so pour d'autres.

Je compile avec GCC (dans MinGW sous Windows). Je voudrais obtenir un
exécutable qui se suffise à lui-même, c'est-à-dire utilisable sans
installer GTK+ au préalable (donc distribuable sans redistribuer GTK+ à
côté). Je croyais l'obtenir en passant l'option -static à GCC, d'ailleurs
le fichier produit est beaucoup plus gros avec cette option que sans. Mais
patatras : sous Win, si je tente de lancer l'exécutable « statique » sur
une machine n'ayant pas GTK+, j'obtiens une erreur « ne trouve pas
libmachin.dll » ; sous Linux, n'ayant pas de machine sans GTK+ à dispo, je
n'ai pas pu tester (y a-t-il moyen de « cacher » les biblis installées le
temps d'un test ?).

Mes questions sont donc :
- peut-on produire un exécutable qui se suffise à lui-même, et avec
quelles options de compilation ?



Sous Linux, oui. C'est ce que je fais pour tout ce qui doit aller
dans des systèmes embarqués lorsque les bibliothèques ne sont pas
réutilisées par ailleurs. --static est là pour cela (la liaison se
fait avec lib*.a, lib*.la est un ajout de libtool dont je préfère me
passer).

Sous Windows, je n'ai jamais compris comment faire une bibliothèque
statique. À l'époque où j'avais creusé la chose, la réponse a été
que c'était impossible d'avoir un vrai exécutable statique (l'idée
était d'inclure la saleté de libc++ dans l'exécutable).

- si oui, quels sont les ingrédients nécessaires en termes de
bibliothèques (quel format de fichier) ?



.a pour Linux.

- à défaut, peut-on « dégraisser » des bibliothèques dynamiques pour n'en
garder que les fonctions réellement utilisées par l'application ? (L'idée
étant d'alléger au maximum le paquet exécutable+biblis à distribuer.)



En fait, lorsque tu lies avec un .a, le linker ne met dans ton
exécutable que ce qui sert réellement. Pour mettre toute la
bibliothèque, il faut préciser une option à ld pour inclure par
exemple du code mort qui pourra être appelé au travers d'une
fonction chargée dynamiquement par dlopen().

Autre chose : lorsque tu lies avec un .so, tu n'as pas à te
préoccuper des dépendances de cette bibliothèque. Lorsque tu lies
avec un .a, il vaut mieux savoir de quoi cette bibliothèque a besoin
parce que c'est à toi de les inclure explicitement.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Luc.Habert.00__arjf
Lucas Levrel :

sous Linux, n'ayant pas de machine sans GTK+ à dispo, je n'ai pas pu
tester (y a-t-il moyen de « cacher » les biblis installées le temps d'un
test ?).



Ne connaissant pas mingw, je réponds surtout à ça. Cacher des libs du
système, je ne sais pas faire, mais tu peux examiner ton exe pour voir de
quoi il dépend. Par exemple, readelf -d (les dépendances sont marquées en
NEEDED) ou ldd qui t'affiche le résultat de la résolution des dépendances
tel qu'il aurait lieu à l'exécution. Ce n'est pas parfait, parce que ça ne
peut pas voir les libs chargées dynamiquement en cours d'exécution (dlopen),
mais c'est déjà une bonne indication.

Mes questions sont donc :
- peut-on produire un exécutable qui se suffise à lui-même, et avec
quelles options de compilation ?



C'est bien -static, mais

- si oui, quels sont les ingrédients nécessaires en termes de
bibliothèques (quel format de fichier) ?



ça ne marche que pour les libs dont tu as une version statique sous la main.
Sous linux, elles ont pour extension .a. Sous windows, il me semble que
c'est .lib, mais est-ce que mingw les supporte? Tu peux essayer de ne mettre
que le .lib visible à mingw.

- à défaut, peut-on « dégraisser » des bibliothèques dynamiques pour n'en
garder que les fonctions réellement utilisées par l'application ? (L'idée
étant d'alléger au maximum le paquet exécutable+biblis à distribuer.)



C'est plus ou moins ce que fait la compilation en statique. La granularité
est le .o, ça ne descend pas jusqu'au niveau des fonctions.
Avatar
Luc.Habert.00__arjf
JKB :

Sous Windows, je n'ai jamais compris comment faire une bibliothèque
statique. À l'époque où j'avais creusé la chose, la réponse a été
que c'était impossible d'avoir un vrai exécutable statique (l'idée
était d'inclure la saleté de libc++ dans l'exécutable).



Je crois y etre arrivé avec VS, en tatonnant. Il faut faire ceci pour chaque
lib et pour l'exe final:
- dans l'explorateur de solution, right click sur le projet, aller dans
Properties (<headdesk>attention, ce n'est pas la même chose que le side panel
Properties<headdesk>)
- descendre dans configuration properties / C/C++ / Code Generation
- pour Runtime Library, choisir Multi Threaded resp. Multi Threaded Debug (il
faut le faire pour la config debug et la config release).

J'ai mis plusieurs jours à comprendre quelque chose à la config des projets
C++ de VS, c'est une horreur super mal documentée. Quand je pense au nombre
de neurones que j'y ai grillés...
Avatar
JKB
Le Thu, 8 Mar 2012 12:30:08 +0000 (UTC),
Luc Habert écrivait :
JKB :

Sous Windows, je n'ai jamais compris comment faire une bibliothèque
statique. À l'époque où j'avais creusé la chose, la réponse a été
que c'était impossible d'avoir un vrai exécutable statique (l'idée
était d'inclure la saleté de libc++ dans l'exécutable).



Je crois y etre arrivé avec VS, en tatonnant. Il faut faire ceci pour chaque
lib et pour l'exe final:
- dans l'explorateur de solution, right click sur le projet, aller dans
Properties (<headdesk>attention, ce n'est pas la même chose que le side panel
Properties<headdesk>)
- descendre dans configuration properties / C/C++ / Code Generation
- pour Runtime Library, choisir Multi Threaded resp. Multi Threaded Debug (il
faut le faire pour la config debug et la config release).

J'ai mis plusieurs jours à comprendre quelque chose à la config des projets
C++ de VS, c'est une horreur super mal documentée. Quand je pense au nombre
de neurones que j'y ai grillés...



Merci pour cette information. Personnellement, j'ai jeté l'éponge,
trop de bugs dans winsock2 et des comportements aberrants entre XP,
W7 et W2008R2 ont fait que la solution a été portée sous Unix.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Lucas Levrel
Le 8 mars 2012, Luc Habert a écrit :

Ne connaissant pas mingw, je réponds surtout à ça. Cacher des libs du
système, je ne sais pas faire, mais tu peux examiner ton exe pour voir de
quoi il dépend. Par exemple, readelf -d (les dépendances sont marquées en
NEEDED) ou ldd qui t'affiche le résultat de la résolution des dépendances
tel qu'il aurait lieu à l'exécution. Ce n'est pas parfait, parce que ça ne
peut pas voir les libs chargées dynamiquement en cours d'exécution (dlopen),
mais c'est déjà une bonne indication.



OK, merci (on m'avait donné Dependency Walker sous Win, maintenant j'ai
l'équivalent sous Linux). Donc si j'utilise ça sur un exécutable compilé
en statique, je devrais obtenir un résultat vide ?

- à défaut, peut-on « dégraisser » des bibliothèques dynamiques pour n'en
garder que les fonctions réellement utilisées par l'application ? (L'idée
étant d'alléger au maximum le paquet exécutable+biblis à distribuer.)



C'est plus ou moins ce que fait la compilation en statique. La granularité
est le .o, ça ne descend pas jusqu'au niveau des fonctions.



D'accord. Mais pour cette question je me demandais plutôt s'il était
possible de dégraisser un .so, pour que la taille du paquet (exécutable
compilé dynamique + biblis partagées nécessaires) à distribuer soit la
plus petite possible.

--
LL
Avatar
Lucas Levrel
Le 8 mars 2012, JKB a écrit :

- peut-on produire un exécutable qui se suffise à lui-même, et avec
quelles options de compilation ?



Sous Linux, oui. C'est ce que je fais pour tout ce qui doit aller
dans des systèmes embarqués lorsque les bibliothèques ne sont pas
réutilisées par ailleurs. --static est là pour cela (la liaison se
fait avec lib*.a, lib*.la est un ajout de libtool dont je préfère me
passer).



Merci. Peux-tu m'en dire plus sur les .la ? Justement sur mon Linux j'ai
(par exemple) libgtk-x11-2.0.la et libgtk-x11-2.0.so, mais pas de .a ...

Sous Windows, je n'ai jamais compris comment faire une bibliothèque
statique.



Ça revient peut-être au même, mais note que je ne cherche qu'à produire un
exécutable statique à partir de bibliothèques statiques préexistantes (si
je les trouve), pas à produire moi-même les bibliothèques statiques.

Ce qui m'épate, c'est que (sous Win) g++ a compilé sans broncher avec
l'option -static, a produit un exécutable d'1,6 Mo (contre 0,2 sans
l'option), mais au lancement Win me dit qu'il lui manque la dll...

Puis-je avoir un diagnostic de ce que fait le linker ? Actuellement mon
Makefile contient « bêtement » :
exe_statique : main.o blabla.o
g++ -o $@ $^ $(shell pkg-config --libs gtk+-2.0) -mwin32 -static

Comment appeler directement le linker (plutôt que g++) et lui demander
d'être bavard ?

En fait, lorsque tu lies avec un .a, le linker ne met dans ton
exécutable que ce qui sert réellement. Pour mettre toute la
bibliothèque, il faut préciser une option à ld pour inclure par
exemple du code mort qui pourra être appelé au travers d'une
fonction chargée dynamiquement par dlopen().



OK.

Autre chose : lorsque tu lies avec un .so, tu n'as pas à te
préoccuper des dépendances de cette bibliothèque. Lorsque tu lies
avec un .a, il vaut mieux savoir de quoi cette bibliothèque a besoin
parce que c'est à toi de les inclure explicitement.



Mais sinon le linker me jette, n'est-ce pas ? (Je suppose qu'il ne
construit pas sans protester un exécutable foireux qui planterait au
lancement.)

--
LL
Avatar
Luc.Habert.00__arjf
Lucas Levrel :

Donc si j'utilise ça sur un exécutable compilé en statique, je devrais
obtenir un résultat vide ?



Oui.

D'accord. Mais pour cette question je me demandais plutôt s'il était
possible de dégraisser un .so, pour que la taille du paquet (exécutable
compilé dynamique + biblis partagées nécessaires) à distribuer soit la
plus petite possible.



Ah zut, j'ai lu de travers. À ma connaissance, non, ce n'est pas possible.
Avatar
JKB
Le Thu, 8 Mar 2012 14:37:35 +0100,
Lucas Levrel écrivait :
Le 8 mars 2012, JKB a écrit :

- peut-on produire un exécutable qui se suffise à lui-même, et avec
quelles options de compilation ?



Sous Linux, oui. C'est ce que je fais pour tout ce qui doit aller
dans des systèmes embarqués lorsque les bibliothèques ne sont pas
réutilisées par ailleurs. --static est là pour cela (la liaison se
fait avec lib*.a, lib*.la est un ajout de libtool dont je préfère me
passer).



Merci. Peux-tu m'en dire plus sur les .la ? Justement sur mon Linux j'ai
(par exemple) libgtk-x11-2.0.la et libgtk-x11-2.0.so, mais pas de .a ...



Le .la est un fichier texte qui est compris par libtool. Il contient
entre autre l'adresse de la bibliothèque .a et ses dépendances.

Sous Windows, je n'ai jamais compris comment faire une bibliothèque
statique.



Ça revient peut-être au même, mais note que je ne cherche qu'à produire un
exécutable statique à partir de bibliothèques statiques préexistantes (si
je les trouve), pas à produire moi-même les bibliothèques statiques.



Euh, erreur de ma part. Il fallait lire comment lier un exécutable
statique.

Ce qui m'épate, c'est que (sous Win) g++ a compilé sans broncher avec
l'option -static, a produit un exécutable d'1,6 Mo (contre 0,2 sans
l'option), mais au lancement Win me dit qu'il lui manque la dll...

Puis-je avoir un diagnostic de ce que fait le linker ? Actuellement mon
Makefile contient « bêtement » :
exe_statique : main.o blabla.o
g++ -o $@ $^ $(shell pkg-config --libs gtk+-2.0) -mwin32 -static

Comment appeler directement le linker (plutôt que g++) et lui demander
d'être bavard ?



Avec la commande ld, mais il ne faut pas se louper dans les modèles
de mémoire. Je commencerais simplement par passer les bonnes options
à g++ pour qu'il soit un peu plus verbeux. Je mettrais aussi
-static en début de ligne. Certains linkers utilisent la position
pour indiquer quelles bibliothèques sont liées dynamiquement et
quelles autres le sont statiquement.

En fait, lorsque tu lies avec un .a, le linker ne met dans ton
exécutable que ce qui sert réellement. Pour mettre toute la
bibliothèque, il faut préciser une option à ld pour inclure par
exemple du code mort qui pourra être appelé au travers d'une
fonction chargée dynamiquement par dlopen().



OK.

Autre chose : lorsque tu lies avec un .so, tu n'as pas à te
préoccuper des dépendances de cette bibliothèque. Lorsque tu lies
avec un .a, il vaut mieux savoir de quoi cette bibliothèque a besoin
parce que c'est à toi de les inclure explicitement.



Mais sinon le linker me jette, n'est-ce pas ? (Je suppose qu'il ne
construit pas sans protester un exécutable foireux qui planterait au
lancement.)



Normalement. Mais il ne faut pas oublier que la gestion des
bibliothèques est un truc particulièrement foireux sous Windows. Il
faudrait que tu regardes avec l'équivalent de nm si les symboles
soi-disant manquant sont dans l'exécutable ou non. Ce serait déjà un
bon début.

Cordialement,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Tonton Th
On 03/08/2012 02:37 PM, Lucas Levrel wrote:

exe_statique : main.o blabla.o
g++ -o $@ $^ $(shell pkg-config --libs gtk+-2.0) -mwin32 -static



Et en mettant le -static avant le pkg_config ?

--

Nous vivons dans un monde étrange/
http://foo.bar.quux.over-blog.com/
Avatar
Fred
"Lucas Levrel" a écrit dans le message de news:

Bonjour,

Je cross-poste sans FU2 car je ne sais pas quel est le groupe le plus
adapté, et la réponse peut même varier selon l'OS, alors je vous laisse
voir...

J'écris un programme en C++ avec une interface en GTK+ (mais mes questions
sont plus générales). Sous Windows, GTK+ est livré avec des .def, .lib,
.dll.a, et .dll (chaque bibli a un ou plusieurs fichiers avec ces
extensions). Sous Linux j'ai des .so et .la pour certaines biblis,
seulement des .so pour d'autres.

Je compile avec GCC (dans MinGW sous Windows).



Les DLL de GTK+ doivent obligatoirement etre présentes si des fonctions de
ces DLL sont utilisées statiquement
Je connais pas GTK (sous Windows, on n'a pas besoin de lib pour les
interfaces, totu est dans l'api) mais si les DLL ne sont pas trop grosses ou
trop nombreuses,
on peut à la rigueur les mettre en resources et les extraire au premier
lancement.
Ou alors appeler toutes les fonctions en dynamique (mais s'il y en a des
dizaines, pas terrible..)
1 2 3