usr / bin / ld: nie można znaleźć -l <nazwaBiblioteki>

443

Próbuję skompilować mój program, który zwraca ten błąd:

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

w moim makefile używam polecenia g++i linku do mojej biblioteki, która jest symbolicznym linkiem do mojej biblioteki znajdującej się w innym katalogu.

Czy istnieje opcja dodania, aby działała, proszę?

ZoOo
źródło
1
Potrzebujesz więcej informacji. Jakie polecenie wydałeś, aby skompilować swój program? Możesz użyć make -n jako twój cel , aby po prostu wypisać polecenia, które normalnie by wywoływał
djf
Opublikuj plik makefile lub wykonane polecenie.
Ortwin Angermeier
moje polecenie jest następujące: g ++ - <options> objetc1.o objetc2.o objetc3.o objetc4.o -L <ścieżkaOfTheLibrary> -l <nazwaOfTheLibrary> -lpthread -o myexe
ZoOo
4
Czy biblioteka, z którą chcesz się połączyć, ma tę samą architekturę (np. 32/64 bit)? Czy biblioteka, którą chcesz połączyć z biblioteką niestandardową? Nazwa biblioteki ma znaczenie, ponieważ musi zaczynać się od lib <nazwa> podczas używania -lprzełącznika (np. Libpthread.so, więc już łączysz się).
Ortwin Angermeier
1
Problem dotyczył mojego symbolicznego linku w bibliotece, co nie było dobre! Dzięki za pomoc !
ZoOo

Odpowiedzi:

196

Jeśli nazwa Twojej biblioteki to say libxyz.soi znajduje się na ścieżce, powiedz:

/home/user/myDir

następnie, aby połączyć go z programem:

g++ -L/home/user/myDir -lxyz myprog.cpp -o myprog
Saurabh Bhola
źródło
11
moja biblioteka nie jest biblioteką dynamiczną (.so), ale statyczną (.a). Czy z tego wynika problem?
ZoOo
3
@ZoOo, co normalnie nie powinno mieć znaczenia, linker może współpracować z jednym z nich
djf
7
innym sposobem na połączenie biblioteki jest to, że możesz bezpośrednio określić nazwę biblioteki za pomocą pełnej ścieżki, np. g ++ .. /path/mylib.a
Saurabh Bhola
2
Tak, ale nadal nie działa. Moja biblioteka jest dowiązaniem symbolicznym, myślę, że z tego wynika problem, ponieważ kiedy korzystam z biblioteki w innym katalogu, działa!
ZoOo
2
Czy Twój symboliczny link poprawnie wskazuje bibliotekę w rzeczywistej lokalizacji? czy możesz zamieścić wynik „ll” na dowiązaniu symbolicznym?
Saurabh Bhola
451

Aby dowiedzieć się, czego szuka linker, uruchom go w trybie pełnym.

Na przykład ten problem napotkałem podczas próby kompilacji MySQL z obsługą ZLIB. Podczas kompilacji otrzymałem taki błąd:

/usr/bin/ld: cannot find -lzlib

Zrobiłem trochę Googl'ingu i ciągle napotykałem różne problemy tego samego rodzaju, w których ludzie mówili, aby upewnić się, że plik .so faktycznie istnieje, a jeśli nie, to utwórz dowiązanie symboliczne do pliku z wersją, na przykład zlib. 1.2.1. Ale kiedy sprawdziłem, Zlib.so DID istnieje. Pomyślałem więc, że to nie może być problem.

Natknąłem się na inny post w Internecie, który sugerował uruchomienie make z LD_DEBUG = all:

LD_DEBUG=all make

Chociaż dostałem TONę danych wyjściowych do debugowania, w rzeczywistości nie było to pomocne. To spowodowało więcej zamieszania niż cokolwiek innego. Więc miałem się poddać.

Potem miałem objawienie. Pomyślałem, żeby sprawdzić tekst pomocy dla polecenia ld:

ld --help

Na tej podstawie wymyśliłem, jak uruchomić ld w trybie pełnym (wyobraź to sobie):

ld -lzlib --verbose

Oto wynik, który otrzymałem:

==================================================
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 ...

Tak więc, aby w końcu to naprawić, abym mógł skompilować MySQL z moją własną wersją ZLIB (zamiast wersji dołączonej):

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

Voila!

dcarrith
źródło
60
Dzięki, to było pomocne. Dla innych używających gcc do kompilacji i łączenia swojego programu (zamiast bezpośredniego korzystania z ld), możesz dodać -Xlinker --verboseargumenty wiersza poleceń gcc, aby przekazać tę opcję do ld.
5
To mi też pomogło. Makefile, którego miałem, spodziewał się tylko bibliotek statycznych, więc go użyłem -Wl,-Bstatic. Ogranicza to wyszukiwanie tylko do plików .a. Pełna opcja pokazała to wyraźnie. Po usunięciu -Wl,-Bstaticprzeszukiwano również biblioteki współdzielone.
micah94
2
Korzystam z FreeBSD 10. Nowy LLVM Clang cc przyjmuje argument formularza -Wl,--verbosei przekazuje --verboselinkerowi.
Christian Campbell
7
To właśnie nazywam idealną odpowiedzią! Wielkie dzięki. Oszczędzało to dużo czasu. Wystarczy dodać, aby pomóc komuś takiemu jak ja. Można go również użyć do debugowania problemów związanych ze ścieżką. Upewnij się, że sprawdziłeś ścieżkę za pomocą polecenia -L <ścieżka do katalogu> za pomocą polecenia, ld -L <ścieżka> -l <nazwa biblioteki> --verbose
sbhatt
2
@EdwardBlack Zobacz tę odpowiedź . Zasadniczo, dla gcc, po prostu dodaj, -Wl,--verboseaby przekazać pełny linker.
chembrad
46

Wydaje się, że nie ma żadnej odpowiedzi, która rozwiązałaby bardzo powszechny problem początkujących polegający na tym, że nie udało się zainstalować wymaganej biblioteki.

Na platformach Debianish, jeśli go libfoobrakuje, możesz często zainstalować go za pomocą czegoś takiego

apt-get install libfoo-dev

-devWersja pakietu jest wymagane w przypadku prac rozwojowych, nawet trywialne prac rozwojowych, takich jak kompilacji kodu źródłowego do linku do biblioteki.

Nazwa pakietu czasami wymaga pewnych dekoracji ( libfoo0-dev? foo-devBez libprefiksu? Itp.), Lub możesz po prostu użyć wyszukiwania pakietu swojej dystrybucji, aby dowiedzieć się dokładnie, które pakiety zapewniają konkretny plik.

(Jeśli jest ich więcej, musisz dowiedzieć się, jakie są ich różnice. Wybranie najfajniejszego lub najpopularniejszego jest powszechnym skrótem, ale nie do przyjęcia w przypadku poważnych prac programistycznych.)

W przypadku innych architektur (zwłaszcza RPM) obowiązują podobne procedury, choć szczegóły będą inne.

potrójny
źródło
3
To tylko pomogło mi z problemem, który miałem ze świeżym serwerem i Perlem. apt-get install libperl-devposortowałem to dla mnie. Dzięki :)
Andrew Newby,
1
To! Nie musisz zadzierać z Makefile
Byron Whitlock
Jest to prawdopodobnie najczęstsze rozwiązanie i pomogło mi skompilować kaktus kręgosłupa na CentOS 7. Proste yum install openssl-develrozwiązanie.
djluko
1
Jest to najlepsza poprawka, jeśli zauważysz brak dowiązania symbolicznego kończącego się na .so, ale masz dowiązanie symboliczne takie jak libfoo.so.6 -> libfoo.so.6.0.2 (na przykład), zamiast tworzenia dowiązania symbolicznego przez dłoń. (co oznacza, że ​​masz zainstalowany pakiet libfoo, ale nie libfoo-dev)
dmaestro12
39

Czas kompilacji

Kiedy g ++ mówi cannot find -l<nameOfTheLibrary>, to znaczy, że g ++ wyglądał dla pliku lib{nameOfTheLibrary}.so, ale nie mógł go znaleźć w udostępnionej biblioteki wyszukiwania ścieżki, która przez punkty do domyślnych /usr/libi /usr/local/libgdzieś indziej może.

Aby rozwiązać ten problem, należy albo podać plik biblioteki ( lib{nameOfTheLibrary}.so) w tych ścieżkach wyszukiwania, albo użyć -Lopcji polecenia. -L{path}mówi g ++ (właściwie ld), aby {path}oprócz plików domyślnych odnalazł pliki bibliotek w ścieżce .

Przykład: Zakładając, że masz bibliotekę /home/taylor/libswift.soi chcesz połączyć swoją aplikację z tą biblioteką. W takim przypadku powinieneś podać g ++ następujące opcje:

g++ main.cpp -o main -L/home/taylor -lswift
  • Uwaga 1 : -lopcja pobiera nazwę biblioteki bez lib i .sona początku i na końcu.

  • Uwaga 2 : W niektórych przypadkach po nazwie pliku biblioteki następuje na przykład jego wersja libswift.so.1.2. W takich przypadkach g ++ również nie może znaleźć pliku biblioteki. Prostym obejściem tego problemu jest utworzenie dowiązania symbolicznego do libswift.so.1.2wywołania libswift.so.


Środowisko wykonawcze

Po połączeniu aplikacji z biblioteką udostępnioną biblioteka musi być dostępna za każdym razem, gdy uruchomisz aplikację. W czasie wykonywania aplikacja (właściwie dynamiczny linker) szuka bibliotek w LD_LIBRARY_PATH. Jest to zmienna środowiskowa, która przechowuje listę ścieżek.

Przykład: W przypadku naszego libswift.soprzykładu, dynamiczny linker nie może znaleźć libswift.sow LD_LIBRARY_PATH(co wskazuje na ścieżki domyślne wyszukiwania). Aby rozwiązać problem, należy dołączyć tę zmienną do ścieżki, libswift.sow której się znajduje.

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/taylor
frogatto
źródło
Dzięki za twój post! Ignorowałem wszystkie odpowiedzi do momentu, kiedy skopiowałem .sopliki /usr/lib, ale stało się dla mnie interesujące, czy exportto pomoże. Mimo makekontynuowania instalacji po dłuższym czasie wystąpił kolejny błąd. Tym razem .so.0plik nie został znaleziony, ale zarówno plik , jak .soi .so.0plik znajdowały się w katalogu, w którym mam pakiet zależny od kompilacji ze źródła. Czy mógłbyś w tym pomóc?
A.Ametov
33

Podczas kompilacji z g++poprzez makeokreślenie LIBRARY_PATH, jeżeli nie mogą być odpowiednie, aby zmienić Makefile z -Lopcją. Umieściłem swoją dodatkową bibliotekę, /opt/libwięc:

$ export LIBRARY_PATH=/opt/lib/

a następnie pobiegł makedo udanej kompilacji i łączenia.

Aby uruchomić program z biblioteką współdzieloną, zdefiniuj:

$ export LD_LIBRARY_PATH=/opt/lib/

przed uruchomieniem programu.

Finn Årup Nielsen
źródło
14

Najpierw musisz znać zasadę nazewnictwa lxxx:

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

lcoznacza libc.so, lltdlznaczy libltdl.so, lXtstznaczy libXts.so.

To jest lib+ lib-name+.so


Po poznaniu nazwy możemy użyć locateścieżki do tego lxxx.sopliku.

$ 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

Jeśli nie możesz go znaleźć, musisz go zainstalować yum(używam CentOS). Zwykle masz ten plik, ale nie prowadzi on do odpowiedniego miejsca.


Połącz go z właściwym miejscem, zwykle jest to /lib64lub/usr/lib64

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

Gotowy!

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

Belter
źródło
4
locatedziała tylko, jeśli jest zainstalowany i działa regularnie. Prymitywnym obejściem jest uruchomienie findna całym dysku, ale oczywiście zajmie to trochę czasu. Jeśli często to robisz, rozważ zainstalowanie, locateaby obniżyć (interaktywny, ludzki) koszt tej operacji.
tripleee
5

Podczas kompilacji programu musisz podać ścieżkę do biblioteki; w g ++ użyj opcji -L:

g++ myprogram.cc -o myprogram -lmylib -L/path/foo/bar
koan
źródło
1
Którą właściwość musimy zmienić, ccmakeaby Makefilezostała utworzona z połączoną flagą? Chcę połączyć moją -lARToolkitPlusflagę ze ścieżką.
Shashwat
2

Ten błąd może być również spowodowany, jeśli dowiązanie symboliczne jest do biblioteki dynamicznej, .so, ale z przyczyn starszych -staticpojawia się wśród flag łącza. Jeśli tak, spróbuj go usunąć.

Vzbux
źródło
2

Sprawdź lokalizację swojej biblioteki, na przykład lxxx.so:

locate lxxx.so

Jeśli nie ma go w /usr/libfolderze, wpisz:

sudo cp yourpath/lxxx.so /usr/lib

Gotowy.

Hua
źródło
4
Należy zachować ostrożność podczas kopiowania bibliotek do katalogów systemowych.
Paul Floyd
2

Oprócz podanych już odpowiedzi może się zdarzyć, że plik * .so istnieje, ale nie ma odpowiedniej nazwy. Może się zdarzyć, że plik * .so istnieje, ale jest własnością innego użytkownika / root.

Problem 1: Niepoprawna nazwa

Jeśli łączysz plik w ten sposób -l<nameOfLibrary> , nazwa pliku biblioteki MUSI mieć formę lib<nameOfLibrary> Jeśli masz tylko <nameOfLibrary>.soplik, zmień jego nazwę!

Problem 2: Niewłaściwy właściciel

Aby sprawdzić, czy to nie problem - zrób

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

Jeśli plik należy do użytkownika root lub innego użytkownika, musisz to zrobić

sudo chown yourUserName:yourUserName /path/to/.so/file
użytkownik13107
źródło
1

Okazało się, że biblioteka, do której próbowałem utworzyć łącze, ma niestandardową nazwę (tj. Nie była poprzedzona literą „lib”), więc zalecili użycie takiej komendy do jej skompilowania -

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

Brian Burns
źródło
Naprawiono dla mnie tylko prefiks „lib”, aby uzyskać standardową nazwę
el_technic0
1

Oto informacje o Ubuntu mojego laptopa.

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

Używam locate, aby znaleźć pliki .so dla boost_filesystem i boost_system

locate libboost_filesystem
locate libboost_system

Następnie połącz pliki .so do / usr / lib i zmień nazwę na .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

Gotowy! Pakiet R velocyto.R został pomyślnie zainstalowany!

Shicheng Guo
źródło
1

Napotkałem ten sam komunikat o błędzie.

Zbudowałem cmockajako a soi próbowałem połączyć go z moim plikiem wykonywalnym. Ale ldzawsze narzeka poniżej:

/ usr / bin / ld: nie można znaleźć -lcmocka

Okazuje się, że po cmockaskompilowaniu generowane są 3 pliki :

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

1 i 2 są linkami symboli, a tylko 3 to prawdziwy plik.

Skopiowałem tylko 1 do folderu biblioteki, w którym ldnie udało się znaleźć 3.

Po skopiowaniu wszystkich 3 lddziała.

smwikipedia
źródło
Czy możesz podać, powiedz proszę, jaki folder masz na myśli w „folderze mojej biblioteki”?
A.Ametov