web-dev-qa-db-fra.com

Comportement de l'éditeur de liens très étrange

C'est étrange car j'ai réussi à faire disparaître l'erreur ci-dessous en supprimant la référence à libm.

gcc -o example example.o -Wl -L/home/kensey/cdev/lib -L/usr/lib/x86_64-linux-gnu   -lmysqlclient -lpthread -lz -L/usr/lib/x86_64-linux-gnu -lm -lrt -ldl -lcdev -L/home/kensey/www.tools/gplot-lib -lgplot -L/home/kensey/www.tools/Gd1_3ret -lgd -lxml2 -lcurl
/usr/bin/ld: /home/kensey/www.tools/gplot-lib/libgplot.a(set.o): undefined reference to symbol 'floor@@GLIBC_2.2.5'
/usr/bin/ld: note: 'floor@@GLIBC_2.2.5' is defined in DSO /usr/lib/x86_64-linux-gnu/libm.so so try adding it to the linker command line
/usr/lib/x86_64-linux-gnu/libm.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status

Donc, si je supprime le -lm partie de la commande, je ne reçois pas l'erreur. Cependant, je me demande si quelqu'un sait pourquoi la suppression d'une référence à une bibliothèque qui serait nécessaire pourrait résoudre ce problème. Comment l'éditeur de liens sait-il dans quelle bibliothèque chercher? Aussi - existe-t-il un moyen d'interroger un exécutable construit et de dire "quelle bibliothèque avez-vous résolu la référence à" étage "? évidemment, il se passe quelque chose que je ne comprends pas et qui me dérange ...

45
Don Wool

L'explication de ce qui se passe est très simple:

  1. Votre libgplot.a dépend de libm.so, mais l'ordre de -lm et -lgplot sur la ligne de liaison est incorrect. L'ordre des bibliothèques sur la ligne de liaison fait matière . En général, les bibliothèques système (-lpthread, -lm, -lrt, -ldl) devrait suivre tout le reste sur la ligne de liaison.

  2. Lorsque vous supprimez -lm depuis la ligne de liaison, libm.so.6 est toujours tiré dans le lien par une autre bibliothèque qui apparaît plus tard sur la ligne de lien (libgd, libxml2 ou libcurl) car cette bibliothèque dépend de libm.so.6. Mais maintenant libm.so.6 est au bon endroit sur la ligne de liaison, donc tout fonctionne.

si je mets -lm à la fin de la commande link, en le répertoriant comme la dernière bibliothèque, je ne reçois pas l'erreur.

Cela confirme l'explication ci-dessus.

83
Employed Russian

J'ai résolu le même problème avec export LDFLAGS="$LDFLAGS -lm"

8
dmnc

Peut-être que vos chemins de recherche de bibliothèque (/ usr/local/lib/ou/usr/lib /, ...) ne contiennent pas de libm 64 bits, donc gcc ne peut pas le localiser si vous spécifiez avec l'indicateur l. Si vous ne spécifiez que le répertoire, il semble qu'il puisse trouver le bon. Vous pouvez donc essayer:

LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu

et utilise -lm

6
perreal

Dur à dire. Puisqu'il y a des répertoires de bibliothèque personnalisés dans la ligne de commande, il est concevable que -lm relie une version alternative incompatible. Sans pour autant -lm l'éditeur de liens pourrait en extraire une autre version car il est nécessaire à l'une des bibliothèques que vous liez.

Pour vous assurer que strace les deux invocations et voir où libm.so vient dans les deux cas.

BTW, -Wl switch semble ne rien faire et -L/usr/lib/x86_64-linux-gnu est mentionné deux fois.

3
Maxim Egorushkin

Juste pour ajouter à la liste des réponses, http://fedoraproject.org/wiki/UnderstandingDSOLinkChange C'est informatif. Ce n'est pas pertinent pour la question posée ci-dessus, mais l'explication se rapporte au message d'erreur /usr/bin/ld: note: 'some_reference' is defined in DSO some.so so try adding it to the linker command line

2
venkrao

Une explication pourrait être:

Il est possible qu'il y ait une fonction faiblement liée foo définie à l'extérieur de libm qui est remplacée par une version fortement liée de foo définie à l'intérieur de libm, et c'est cette version fortement liée qui appelle la fonction non définie.

Cela expliquerait comment l'ajout d'une bibliothèque peut provoquer une erreur de fonction non définie.

1
Andrew Tomazos

Je viens de rencontrer un problème similaire; Je me souviens que l'ordre des bibliothèques n'avait pas d'importance (du moins pas dans les cas avec lesquels j'ai travaillé) dans le passé pour gcc. Dans cette question ici quelqu'un a remarqué que le comportement semble avoir changé entre 4.4 et 4.5.

Dans mon cas, je me suis débarrassé du message d'erreur en faisant le lien à:

 g++ -Wl,--copy-dt-needed-entries [options] [libraries] [object files] -o executable-file
1
Andre Holzner