561 votes

L'éditeur de liens afin que GCC

Pourquoi l'ordre dans lequel les bibliothèques sont liées parfois provoquer des erreurs?

661voto

Résumé

Si tout [statique] la bibliothèque dépend de symboles définis dans la bibliothèque de B, puis à la bibliothèque doit apparaître en premier dans la liste fournie à l'éditeur de liens.

+- prog.o -----+   +- libA.a -----+   +- libB.a -----+   
|   U funcA  --|---|-> T funcA    |   |              |    U : undefined/used
|              |   |   U funcB  --|---|-> T funcB    |    T : defined
|   T main     |   |              |   |              |   
+--------------+   +--------------+   +--------------+

Doit être lié à

gcc prog.o libA.a libB.a -o prog.x
       \___^  \___^

ou, bien sûr,

gcc prog.o -lA -lB -o prog.x

ce qui laisse le compilateur ouvert à choisir les dynamiques libA.so et libB.so variante, si disponible.

Bibliothèques Dynamiques

Il n'y a pas d'exigences sur les liens entre l'ordre des fichiers de l'objet ou de la dynamique des bibliothèques. Bien sûr, un programme qui contient un comportement indéfini ou dépend d'un comportement non spécifié pourraient être touchés par cette ordonnance. Par exemple, si le constructeur invocations dépend de l'ordre de liaison de fichiers de l'objet, et le programme accède à des objets à travers l'unité de traduction des frontières, alors il peut accéder a pas encore construit de l'objet en raison de son traduit de l'unité de traduction est liée après un autre objet fichier, qui contient les autres, pas encore construit de l'objet. Ces effets, cependant, montrent jusqu'à défaut des programmes - un programme correct ne devrait pas dépendre de l'ordre.

Symbole de la résolution dynamique librarries

Il n'y a pas d'exigences concernant la résolution de symboles qui pourraient être touchées par le lien afin de bibliothèques dynamiques ou les fichiers objet. D'exécution des effets qui dépendent du lien de commande, comme dans l'exemple ci-dessus, pourrait se produire, mais ne devrait pas affecter valide les programmes. Les programmes devraient utiliser les outils de la suite d'outils pour s'assurer qu'ils se comportent correctement. Par exemple GCC a la possibilité de contrôler quand un constructeur s'exécute et, par conséquent, de l'ordre de la priorité du constructeur appelle à le temps d'initialisation des objets.

Le problème avec les Bibliothèques Statiques

De toute façon, statiques des bibliothèques doivent être liés dans cet ordre - dans le cas contraire, les références apparaissent avec GNU ld:

Si une bibliothèque A dépend de symboles définis dans la bibliothèque de B, puis à la bibliothèque devrait apparaître en premier dans la liste fournie à l'éditeur de liens

Ce qui peut parfois causer des problèmes dans l'accumulation de scripts qui peuvent être configurés pour le lien.

La résolution des dépendances cycliques (avec éditeur de liens gnu)

L'éditeur de liens GNU a une option qui provoque à résoudre cyclique références entre A et B:

-( archives -) ou --start-group archives --end-group Les archives devraient être une liste de fichiers d'archive. Ils peuvent être soit explicite des noms de fichiers, ou l options.

Le spécifiée archives sont recherchés à plusieurs reprises jusqu'à ce qu'aucune nouvelle undefined références sont créés. Normalement, une archive est cherché une seule fois dans l'ordre dans lequel il est spécifié sur la ligne de commande. Si un symbole dans cette archive est nécessaire pour les résoudre un symbole non défini visé par un objet dans une archive qui apparaît plus tard sur la ligne de commande, l'éditeur de liens ne serait pas en mesure de résoudre cette référence. Par le regroupement des services d'archives, ils ont tous cherché à plusieurs reprises jusqu'à ce que toutes les références possibles sont résolu.

L'utilisation de cette option a une importante incidence sur les performances. Il est préférable de l'utiliser seulement quand il y a des inévitables références circulaires entre deux ou plus d'archives.

Notez que archives dans cette description, reportez-vous aux bibliothèques statiques. Je l'ai pris à partir de la page de manuel de GNU ld (man ld).

Cas particulier avec la norme libs

Une occasion qui pourrait être utile est de réunir la bibliothèque runtime c avec gcc faible niveau de soutien des bibliothèques. Voici ce que mon port de gcc utilise pour passer à l'éditeur de liens:

"-lgcc" "-lc" "-lsyscalls" "-lgcc"

Parce que les fonctions en libgcc peut se référer à des fonctions définies dans la bibliothèque C, mais les fonctions de la bibliothèque C peut se référer à des fonctions définies en libgcc (il contient des fonctions telles que la virgule flottante d'émulation de code). Une autre façon de résoudre ce problème aurait pu être l'utilisation de la start-groupe et de fin de groupe mécanisme.

135voto

casualcoder Points 1727

La GNU ld de l'éditeur de liens est un soi-disant intelligente de l'éditeur de liens. Il assurera le suivi des fonctions utilisées par le précédent bibliothèques statiques, définitivement jeter ces fonctions qui ne sont pas utilisés à partir de son tables de recherche. Le résultat est que si vous liez une bibliothèque statique trop tôt, puis les fonctions de cette bibliothèque ne sont plus disponibles aux bibliothèques statiques plus tard sur la ligne de liaison.

Le typique UNIX linker fonctionne à partir de la gauche vers la droite, donc de mettre tous vos bibliothèques dépendantes sur la gauche, et ceux qui répondent à ces dépendances sur la droite de la ligne de liaison. Vous pouvez trouver que certaines bibliothèques dépendent des autres et en même temps d'autres bibliothèques en dépendent. C'est là que ça devient compliqué. Quand il s'agit de références circulaires, corriger votre code!

62voto

Lumi Points 6399

Voici un exemple pour bien comprendre comment les choses fonctionnent à l'aide de GCC lors de la statique des bibliothèques sont impliqués. Donc, nous allons supposer que nous avons le scénario suivant:

  • myprog.o - contenant de l' main() fonction, dépend libmysqlclient
  • libmysqlclient - statique, pour le bien de l'exemple (vous préférez la bibliothèque partagée, bien sûr, que l' libmysqlclient est énorme); en /usr/local/lib; et dépendant du stuff de libz
  • libz (dynamique)

Comment faire le lien? (Note: les exemples à partir de la compilation sur Cygwin en utilisant gcc 4.3.4)

gcc -L/usr/local/lib -lmysqlclient myprog.o
# undefined reference to `_mysql_init'
# myprog depends on libmysqlclient
# so myprog has to come earlier on the command line

gcc myprog.o -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# we have to link with libz, too

gcc myprog.o -lz -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# libz is needed by libmysqlclient
# so it has to appear *after* it on the command line

gcc myprog.o -L/usr/local/lib -lmysqlclient -lz
# this works

8voto

Matt McNabb Points 14273

Une astuce qui a déclenché moi: si vous êtes en invoquant l'éditeur de liens comme "gcc" ou "g++", puis à l'aide de "--start-groupe" et "--fin de groupe" ne pas répercuter ces options par le biais de l'éditeur de liens -- ni signaler une erreur. Il sera simplement de ne pas le lien avec les symboles non définis, si vous avez eu l'ordre de la bibliothèque de mal.

Vous avez besoin d'écrire "-Wl,--start-groupe" etc. pour demander à GCC de passer l'argument par le biais de l'éditeur de liens.

6voto

yundorri Points 41

Vous pouvez vous pouvez utiliser -Xlinker option.

g++ -o foobar  -Xlinker -start-group  -Xlinker libA.a -Xlinker libB.a -Xlinker libC.a  -Xlinker -end-group 

est PRESQUE égale à

g++ -o foobar  -Xlinker -start-group  -Xlinker libC.a -Xlinker libB.a -Xlinker libA.a  -Xlinker -end-group 

Attention !

  1. L'ordre au sein d'un groupe, c'est important ! Voici un exemple: une version de débogage de la bibliothèque dispose d'un debug routine, mais le non-debug la bibliothèque a une version faible de la même chose. Vous devez placer le débogage de la bibliothèque D'ABORD dans le groupe ou vous permettra de résoudre à la non-version de débogage.
  2. Vous avez besoin de les faire précéder chaque bibliothèque dans la liste des groupes avec -Xlinker

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X