usr / bin / ld: impossible de trouver -l <nameOfTheLibrary>

444

J'essaie de compiler mon programme et il renvoie cette erreur:

usr/bin/ld: cannot find -l<nameOfTheLibrary>

dans mon makefile j'utilise la commande g++et le lien vers ma bibliothèque qui est un lien symbolique vers ma bibliothèque située sur un autre répertoire.

Y a-t-il une option à ajouter pour le faire fonctionner s'il vous plaît?

ZoOo
la source
1
Besoin de plus d'informations. Quelle commande avez-vous émise pour compiler votre programme? Vous pouvez utiliser make -n votre-cible pour faire simplement imprimer les commandes qu'il invoquerait normalement
djf
Publiez le makefile ou la commande que vous exécutez.
Ortwin Angermeier
ma commande est celle-ci: g ++ - <options> objetc1.o objetc2.o objetc3.o objetc4.o -L <pathOfTheLibrary> -l <nameOfTheLibrary> -lpthread -o myexe
ZoOo
4
La bibliothèque avec laquelle vous souhaitez créer un lien est-elle construite avec la même architecture (par exemple, 32/64 bits)? La bibliothèque que vous souhaitez associer à une bibliothèque personnalisée est-elle? Le nom de la bibliothèque est important, car il doit commencer par lib <name> lors de l'utilisation du -lcommutateur (par exemple. Libpthread.so vous êtes déjà en liaison avec).
Ortwin Angermeier
1
Le problème était sur mon lien symbolique sur la bibliothèque qui n'était pas bon! Merci de votre aide !
ZoOo

Réponses:

196

Si le nom de votre bibliothèque est say libxyz.soet qu'il se trouve sur le chemin, dites:

/home/user/myDir

puis pour le lier à votre programme:

g++ -L/home/user/myDir -lxyz myprog.cpp -o myprog
Saurabh Bhola
la source
11
ma bibliothèque n'est pas dynamique (.so) mais statique (.a). Le problème vient-il de cela?
ZoOo
3
@ZoOo qui ne devrait normalement pas avoir d'importance, l'éditeur de liens peut fonctionner avec l'un ou l'autre
djf
7
une autre façon de lier votre bibliothèque est que vous pouvez spécifier directement le nom de la bibliothèque avec le chemin complet, comme g ++ .. /path/mylib.a
Saurabh Bhola
2
Oui mais ça ne marche toujours pas. Ma bibliothèque est un lien symbolique, je pense que le problème vient de cela car quand j'utilise la bibliothèque dans l'autre répertoire ça marche!
ZoOo
2
Votre lien symbolique pointe-t-il correctement vers la bibliothèque à l'emplacement réel ??. pouvez-vous publier la sortie de "ll" sur le lien symbolique.
Saurabh Bhola
452

Pour comprendre ce que l'éditeur de liens recherche, exécutez-le en mode détaillé.

Par exemple, j'ai rencontré ce problème en essayant de compiler MySQL avec le support ZLIB. Je recevais une erreur comme celle-ci lors de la compilation:

/usr/bin/ld: cannot find -lzlib

J'ai fait un peu de Googl et j'ai continué à rencontrer différents problèmes du même genre où les gens disaient pour s'assurer que le fichier .so existe réellement et si ce n'est pas le cas, puis créer un lien symbolique vers le fichier versionné, par exemple, zlib. donc.1.2.8. Mais, quand j'ai vérifié, zlib.so DID existait. Donc, je pensais que ça ne pouvait pas être le problème.

Je suis tombé sur un autre post sur les Internets qui a suggéré d'exécuter make avec LD_DEBUG = all:

LD_DEBUG=all make

Bien que j'aie eu une tonne de sortie de débogage, ce n'était pas vraiment utile. Cela a ajouté plus de confusion qu'autre chose. J'étais sur le point d'abandonner.

Ensuite, j'ai eu une révélation. J'ai pensé à vérifier le texte d'aide de la commande ld:

ld --help

À partir de cela, j'ai compris comment exécuter ld en mode verbeux (imaginez cela):

ld -lzlib --verbose

Voici la sortie que j'ai obtenue:

==================================================
attempt to open /usr/x86_64-linux-gnu/lib64/libzlib.so failed
attempt to open /usr/x86_64-linux-gnu/lib64/libzlib.a failed
attempt to open /usr/local/lib64/libzlib.so failed
attempt to open /usr/local/lib64/libzlib.a failed
attempt to open /lib64/libzlib.so failed
attempt to open /lib64/libzlib.a failed
attempt to open /usr/lib64/libzlib.so failed
attempt to open /usr/lib64/libzlib.a failed
attempt to open /usr/x86_64-linux-gnu/lib/libzlib.so failed
attempt to open /usr/x86_64-linux-gnu/lib/libzlib.a failed
attempt to open /usr/local/lib/libzlib.so failed
attempt to open /usr/local/lib/libzlib.a failed
attempt to open /lib/libzlib.so failed
attempt to open /lib/libzlib.a failed
attempt to open /usr/lib/libzlib.so failed
attempt to open /usr/lib/libzlib.a failed
/usr/bin/ld.bfd.real: cannot find -lzlib

Ding, ding, ding ...

Donc, pour enfin le corriger afin que je puisse compiler MySQL avec ma propre version de ZLIB (plutôt que la version fournie):

sudo ln -s /usr/lib/libz.so.1.2.8 /usr/lib/libzlib.so

Voila!

dcarrith
la source
60
Merci, cela a été utile. Pour ceux qui utilisent gcc pour compiler et lier leur programme (plutôt que d'utiliser directement ld), vous pouvez ajouter -Xlinker --verboseaux arguments de la ligne de commande de gcc pour qu'il passe cette option à ld.
5
Cela m'a également aidé. Le Makefile que j'avais n'attendait que des bibliothèques statiques, donc il a été utilisé -Wl,-Bstatic. Cela limite la recherche aux fichiers .a uniquement. L'option verbeuse l'a clairement montré. Une fois que j'ai supprimé -Wl,-Bstaticles bibliothèques partagées, les recherches ont également été effectuées.
micah94
2
Je suis sur FreeBSD 10. Le nouveau LLVM Clang cc prend un argument du formulaire -Wl,--verboseet passe --verboseà l'éditeur de liens.
Christian Campbell
7
Voilà ce que j'appelle une réponse parfaite! Merci beaucoup. Cela a fait gagner beaucoup de temps. Juste pour ajouter à aider quelqu'un comme moi. Il peut également être utilisé pour déboguer les problèmes liés au chemin. Assurez-vous de vérifier le chemin avec -L <chemin vers le répertoire> avec la commande, ld -L <path> -l <nom de la bibliothèque> --verbose
sbhatt
2
@EdwardBlack Voir cette réponse . Essentiellement, pour gcc, ajoutez simplement -Wl,--verbosepour passer verbeux à l'éditeur de liens.
chembrad
46

Il ne semble pas y avoir de réponse qui résout le problème très courant des débutants de ne pas installer la bibliothèque requise en premier lieu.

Sur les plateformes Debianish, s'il libfooest manquant, vous pouvez fréquemment l'installer avec quelque chose comme

apt-get install libfoo-dev

La -devversion du package est requise pour les travaux de développement, même les travaux de développement triviaux tels que la compilation du code source à lier à la bibliothèque.

Le nom du package nécessitera parfois quelques décorations ( libfoo0-dev? foo-devSans le libpréfixe? Etc), ou vous pouvez simplement utiliser la recherche de package de votre distribution pour savoir précisément quels packages fournissent un fichier particulier.

(S'il y en a plus d'un, vous devrez découvrir leurs différences. Choisir le plus cool ou le plus populaire est un raccourci commun, mais pas une procédure acceptable pour tout travail de développement sérieux.)

Pour d'autres architectures (notamment RPM), des procédures similaires s'appliquent, bien que les détails soient différents.

tripleee
la source
3
Cela m'a juste aidé avec un problème que je rencontrais avec un nouveau serveur et Perl. apt-get install libperl-devtrié pour moi. Merci :)
Andrew Newby
1
Cette! Pas besoin de jouer avec le Makefile
Byron Whitlock
C'est probablement la solution la plus courante et m'a aidé à compiler cacti-spine sur CentOS 7. Un simple a yum install openssl-develrésolu le problème.
djluko
1
C'est le meilleur correctif si vous trouvez que le lien symbolique se terminant par .so est manquant, mais vous avez un lien symbolique tel que libfoo.so.6 -> libfoo.so.6.0.2 (par exemple), plutôt que de créer le lien symbolique par main. (ce qui signifie que le paquet libfoo est installé, mais pas libfoo-dev)
dmaestro12
39

Compiler le temps

Lorsque g ++ le dit cannot find -l<nameOfTheLibrary>, cela signifie que g ++ a recherché le fichier lib{nameOfTheLibrary}.so, mais il ne l'a pas trouvé dans le chemin de recherche de la bibliothèque partagée, qui par défaut pointe vers /usr/libet /usr/local/libet ailleurs peut-être.

Pour résoudre ce problème, vous devez fournir le fichier de bibliothèque ( lib{nameOfTheLibrary}.so) dans ces chemins de recherche ou utiliser l' -Loption de commande. -L{path}indique au g ++ (en fait ld) de trouver les fichiers de bibliothèque dans le chemin {path}en plus des chemins par défaut.

Exemple: en supposant que vous avez une bibliothèque sur /home/taylor/libswift.soet que vous souhaitez lier votre application à cette bibliothèque. Dans ce cas, vous devez fournir au g ++ les options suivantes:

g++ main.cpp -o main -L/home/taylor -lswift
  • Remarque 1 : l' -loption obtient le nom de la bibliothèque sans lib et .soà ses début et fin.

  • Remarque 2 : Dans certains cas, le nom du fichier de bibliothèque est suivi de sa version, par exemple libswift.so.1.2. Dans ces cas, g ++ ne peut pas non plus trouver le fichier de bibliothèque. Une solution simple pour résoudre ce problème consiste à créer un lien symbolique vers libswift.so.1.2appelé libswift.so.


Durée

Lorsque vous liez votre application à une bibliothèque partagée, il est nécessaire que la bibliothèque reste disponible chaque fois que vous exécutez l'application. Lors de l'exécution, votre application (en fait un éditeur de liens dynamique) recherche ses bibliothèques dans LD_LIBRARY_PATH. C'est une variable d'environnement qui stocke une liste de chemins.

Exemple: Dans notre libswift.soexemple, l'éditeur de liens dynamique ne peut pas trouver libswift.sodans LD_LIBRARY_PATH(qui pointe vers des chemins de recherche par défaut). Pour résoudre le problème, vous devez ajouter cette variable avec le chemin d'accès libswift.so.

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/taylor
grenouille
la source
Merci pour votre message! J'ai ignoré toutes les réponses jusqu'au moment où j'ai copié les .sofichiers /usr/lib, mais il est devenu intéressant pour moi de savoir si exportcela pourrait aider. Malgré le processus d'installation qui s'est makepoursuivi plus longtemps, une autre erreur s'est produite. Cette fois, le .so.0fichier n'a pas été trouvé, mais les deux fichiers .soet se .so.0trouvaient dans le répertoire où j'ai construit le package dépendant de la source. Pourriez-vous m'aider?
A.Ametov
33

Lors de la compilation avec g++via, makedéfinissez LIBRARY_PATHs'il ne convient pas de modifier le Makefile avec l' -Loption. J'avais mis ma bibliothèque supplémentaire /opt/libalors j'ai fait:

$ export LIBRARY_PATH=/opt/lib/

puis couru makepour une compilation et une liaison réussies.

Pour exécuter le programme avec une bibliothèque partagée, définissez:

$ export LD_LIBRARY_PATH=/opt/lib/

avant d'exécuter le programme.

Finn Årup Nielsen
la source
14

Tout d'abord, vous devez connaître la règle de dénomination de lxxx:

/usr/bin/ld: cannot find -lc
/usr/bin/ld: cannot find -lltdl
/usr/bin/ld: cannot find -lXtst

lcsignifie libc.so, lltdlsignifie libltdl.so, lXtstsignifie libXts.so.

Donc, c'est lib+ lib-name+.so


Une fois que nous connaissons le nom, nous pouvons utiliser locatepour trouver le chemin de ce lxxx.sofichier.

$ locate libiconv.so
/home/user/anaconda3/lib/libiconv.so   # <-- right here
/home/user/anaconda3/lib/libiconv.so.2
/home/user/anaconda3/lib/libiconv.so.2.5.1
/home/user/anaconda3/lib/preloadable_libiconv.so
/home/user/anaconda3/pkgs/libiconv-1.14-0/lib/libiconv.so
/home/user/anaconda3/pkgs/libiconv-1.14-0/lib/libiconv.so.2
/home/user/anaconda3/pkgs/libiconv-1.14-0/lib/libiconv.so.2.5.1
/home/user/anaconda3/pkgs/libiconv-1.14-0/lib/preloadable_libiconv.so

Si vous ne le trouvez pas, vous devez l'installer par yum(j'utilise CentOS). Habituellement, vous avez ce fichier, mais il n'est pas lié au bon endroit.


Reliez-le au bon endroit, généralement c'est /lib64ou/usr/lib64

$ sudo ln -s /home/user/anaconda3/lib/libiconv.so /usr/lib64/

Terminé!

réf: https://i-pogo.blogspot.jp/2010/01/usrbinld-cannot-find-lxxx.html

Belter
la source
4
locatene fonctionne que s'il est installé et fonctionne régulièrement. Une solution de contournement grossière consiste à s'exécuter findsur l'intégralité de votre disque, mais bien sûr, cela prendra du temps. Si vous vous trouvez à le faire fréquemment, envisagez d'installer locatejuste pour réduire le coût (interactif, humain) de cette opération.
tripleee
5

Lorsque vous compilez votre programme, vous devez fournir le chemin d'accès à la bibliothèque; dans g ++, utilisez l'option -L:

g++ myprogram.cc -o myprogram -lmylib -L/path/foo/bar
koan
la source
1
Dans quelle propriété devons-nous changer ccmakepour que le Makefilesoit créé avec l'indicateur lié? Je veux lier mon -lARToolkitPlusdrapeau à un chemin.
Shashwat
2

Cette erreur peut également se produire si le lien symbolique est vers une bibliothèque dynamique, .so, mais pour des raisons héritées -staticapparaît parmi les indicateurs de lien. Si oui, essayez de le retirer.

Vzbux
la source
2

Vérifiez l'emplacement de votre bibliothèque, par exemple lxxx.so:

locate lxxx.so

S'il ne se trouve pas dans le /usr/libdossier, tapez ceci:

sudo cp yourpath/lxxx.so /usr/lib

Terminé.

hua
la source
4
Vous devez faire preuve de prudence lors de la copie des bibliothèques dans les répertoires système.
Paul Floyd
2

Outre les réponses déjà données, il se peut également que le fichier * .so existe mais ne soit pas nommé correctement. Ou il se peut que le fichier * .so existe mais qu'il appartient à un autre utilisateur / racine.

Problème 1: nom incorrect

Si vous liez le fichier car -l<nameOfLibrary> le nom du fichier de bibliothèque DOIT être de la forme lib<nameOfLibrary> Si vous n'avez qu'un <nameOfLibrary>.sofichier, renommez-le!

Problème 2: mauvais propriétaire

Pour vérifier que ce n'est pas le problème - faites

ls -l /path/to/.so/file

Si le fichier appartient à root ou à un autre utilisateur, vous devez faire

sudo chown yourUserName:yourUserName /path/to/.so/file
user13107
la source
1

La bibliothèque que j'essayais de lier s'est avérée avoir un nom non standard (c'est-à-dire qu'elle n'était pas préfixée par «lib»), alors ils ont recommandé d'utiliser une commande comme celle-ci pour la compiler -

gcc test.c -Iinclude lib/cspice.a -lm

Brian Burns
la source
Seul le préfixe avec "lib" pour obtenir un nom standard l'a corrigé pour moi
el_technic0
1

Voici les informations Ubuntu de mon ordinateur portable.

lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.2 LTS
Release:    18.04
Codename:   bionic

J'utilise Locate pour trouver les fichiers .so pour boost_filesystem et boost_system

locate libboost_filesystem
locate libboost_system

Liez ensuite les fichiers .so à / usr / lib et renommez-les en .so

sudo ln -s /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1 /usr/lib/libboost_filesystem.so
sudo ln -s /usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1 /usr/lib/libboost_system.so

Terminé! Le package R velocyto.R a été installé avec succès!

Shicheng Guo
la source
1

J'ai rencontré le même message d'erreur.

J'ai construit le en cmockatant que soet essayé de le lier à mon exécutable. Mais se ldplaint toujours ci-dessous:

/ usr / bin / ld: impossible de trouver -lcmocka

Il s'avère qu'il y a 3 fichiers générés après la cmockaconstruction:

  1. libcmocka.so
  2. libcmocka.so.0
  3. libcmocka.so.0.7.0

1 et 2 sont des liens symboliques et seulement 3 est le vrai fichier.

J'ai seulement copié le 1 dans mon dossier de bibliothèque, où je n'ai ldpas trouvé le 3.

Après avoir copié tous les 3, ldfonctionne.

smwikipedia
la source
Pouvez-vous indiquer, s'il vous plaît, quel dossier voulez-vous dire sous «mon dossier de bibliothèque»?
A.Ametov