usr / bin / ld: ไม่พบ -l <nameOfTheLibrary>


443

ฉันพยายามรวบรวมโปรแกรมของฉันและมันคืนข้อผิดพลาดนี้:

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

ใน makefile ของฉันฉันใช้คำสั่งg++และลิงก์ไปยังไลบรารีของฉันซึ่งเป็นลิงก์สัญลักษณ์ไปยังไลบรารีของฉันซึ่งอยู่ในไดเรกทอรีอื่น

มีตัวเลือกให้เพิ่มเพื่อใช้งานได้ไหม?


1
ต้องการข้อมูลเพิ่มเติม คุณมีคำสั่งใดในการคอมไพล์โปรแกรมของคุณ? คุณสามารถใช้make -n เป้าหมายของคุณเพื่อสร้างเพียงพิมพ์คำสั่งที่ปกติจะเรียกใช้
djf

โพสต์ makefile หรือคำสั่งที่คุณดำเนินการ
Ortwin Angermeier

คำสั่งของฉันคืออันนี้: g ++ - <options> objetc1.o objetc2.o objetc3.o objetc4.o -L <pathOfTheLibrary> -l <nameOfTheLibrary> -lpthread -o myexe
ZoOo

4
ห้องสมุดที่คุณต้องการเชื่อมโยงสร้างด้วยสถาปัตยกรรมเดียวกัน (เช่น 32/64 บิต) หรือไม่ ห้องสมุดที่คุณต้องการเชื่อมโยงกับห้องสมุดที่กำหนดเองหรือไม่? ชื่อไลบรารีมีความสำคัญเนื่องจากจะต้องเริ่มต้นด้วย lib <name> เมื่อใช้-lสวิตช์ (เช่น libpthread.so คุณเชื่อมโยงแล้ว)
Ortwin Angermeier

1
ปัญหาคือลิงค์สัญลักษณ์ของฉันในห้องสมุดซึ่งไม่ดี! ขอบคุณสำหรับความช่วยเหลือของคุณ !
ZoOo

คำตอบ:


196

หากชื่อห้องสมุดของคุณพูดlibxyz.soและตั้งอยู่บนเส้นทางพูดว่า:

/home/user/myDir

จากนั้นลิงก์ไปยังโปรแกรมของคุณ:

g++ -L/home/user/myDir -lxyz myprog.cpp -o myprog

11
ห้องสมุดของฉันไม่ใช่แบบไดนามิก (.so) แต่เป็นแบบคงที่ (.a) ปัญหาเกิดจากสิ่งนั้นหรือไม่?
ZoOo

3
@ ZoOo ที่ไม่ควรทำตามปกติ linker สามารถทำงานกับทั้งสองได้
djf

7
อีกวิธีหนึ่งในการลิงก์ไลบรารีของคุณคือคุณสามารถระบุชื่อของไลบรารีด้วยพา ธ ที่สมบูรณ์เช่น g ++ .. /path/mylib.a
Saurabh Bhola

2
ใช่ แต่มันยังไม่ทำงาน ห้องสมุดของฉันเป็นลิงก์สัญลักษณ์ฉันคิดว่าปัญหามาจากที่นั่นเพราะเมื่อฉันใช้ห้องสมุดในไดเรกทอรีอื่นมันใช้งานได้!
ZoOo

2
ลิงก์สัญลักษณ์ของคุณชี้ไปที่ห้องสมุดที่ตำแหน่งจริงหรือไม่? คุณสามารถโพสต์เอาต์พุตของ "ll" บนลิงก์สัญลักษณ์
Saurabh Bhola

451

หากต้องการทราบว่าลิงเกอร์ค้นหาอะไรให้เรียกใช้ในโหมด verbose

ตัวอย่างเช่นฉันพบปัญหานี้ขณะพยายามรวบรวม MySQL ด้วยการสนับสนุน ZLIB ฉันได้รับข้อผิดพลาดเช่นนี้ระหว่างการรวบรวม:

/usr/bin/ld: cannot find -lzlib

ฉันทำ Googl'ing แล้วและพบกับปัญหาที่แตกต่างกันซึ่งผู้คนจะพูดเพื่อให้แน่ใจว่าไฟล์. so มีอยู่จริงและหากไม่เป็นเช่นนั้นให้สร้าง symlink ไปยังไฟล์ที่มีเวอร์ชันเช่น zlib so.1.2.8 แต่เมื่อฉันตรวจสอบ zlib.so DID อยู่ ดังนั้นฉันคิดว่าแน่นอนว่าไม่สามารถมีปัญหา

ฉันเจอโพสต์อื่นใน Internets ที่แนะนำให้เรียกใช้ make ด้วย LD_DEBUG = ทั้งหมด:

LD_DEBUG=all make

แม้ว่าฉันจะได้รับการตรวจแก้จุดบกพร่องตันแล้วมันไม่ได้มีประโยชน์ มันเพิ่มความสับสนมากกว่าสิ่งอื่นใด ดังนั้นฉันกำลังจะยอมแพ้

จากนั้นฉันก็มีความศักดิ์สิทธิ์ ฉันคิดว่าจะตรวจสอบข้อความช่วยเหลือจริงสำหรับคำสั่ง ld:

ld --help

จากนั้นฉันหาวิธีใช้ ld ในโหมด verbose (ลองจินตนาการดู):

ld -lzlib --verbose

นี่คือผลลัพธ์ที่ฉันได้รับ:

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

ดังนั้นในที่สุดก็แก้ไขได้ดังนั้นฉันสามารถรวบรวม MySQL กับ ZLIB เวอร์ชันของฉันเอง (แทนที่จะเป็นเวอร์ชั่นที่รวมไว้):

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

Voila!


60
ขอบคุณสิ่งนี้มีประโยชน์ สำหรับผู้อื่นที่ใช้ gcc เพื่อคอมไพล์และลิงก์โปรแกรม (แทนที่จะใช้ ld โดยตรง) คุณสามารถเพิ่ม-Xlinker --verboseอาร์กิวเมนต์บรรทัดคำสั่งของ gcc เพื่อให้มันผ่านตัวเลือกนี้ไปยัง ld

5
สิ่งนี้ช่วยฉันด้วย Makefile -Wl,-Bstaticฉันได้เป็นเพียงการคาดหวังว่าห้องสมุดแบบคงที่ดังนั้นจึงใช้ นี่เป็นการ จำกัด การค้นหาไฟล์. a เท่านั้น ตัวเลือก verbose แสดงสิ่งนี้อย่างชัดเจน เมื่อฉันลบ-Wl,-Bstaticห้องสมุดสาธารณะที่ถูกค้นหาด้วย
micah94

2
ฉันใช้ FreeBSD 10. LLVM Clang cc ใหม่ใช้การโต้เถียงของแบบฟอร์ม-Wl,--verboseและส่งผ่าน--verboseไปยังตัวเชื่อมโยง
Christian Campbell

7
นี่คือสิ่งที่ฉันเรียกว่าคำตอบที่สมบูรณ์แบบ! ขอบคุณมาก. มันประหยัดเวลาได้มาก เพียงเพิ่มเพื่อช่วยคนอย่างฉัน มันสามารถใช้ในการแก้ปัญหาเส้นทางที่เกี่ยวข้องเช่นกัน ตรวจสอบให้แน่ใจว่าคุณตรวจสอบพา ธ ด้วย -L ​​<พา ธ ไปยังไดเร็กทอรี> ด้วยคำสั่ง ld -L <path> -l <ชื่อไลบรารี> --verbose
sbhatt

2
@EdwardBlack ดูคำตอบนี้ เป็นหลักสำหรับ gcc เพียงเพิ่ม-Wl,--verboseผ่าน verbose ไปยังลิงเกอร์
chembrad

46

ดูเหมือนจะไม่มีคำตอบใด ๆ ซึ่งระบุถึงปัญหาเริ่มต้นที่พบบ่อยมากของการไม่สามารถติดตั้งไลบรารีที่ต้องการได้ตั้งแต่แรก

บนแพลตฟอร์ม Debianish หากlibfooหายไปคุณสามารถติดตั้งบ่อยครั้งด้วยสิ่งที่ต้องการ

apt-get install libfoo-dev

-devรุ่นของแพคเกจเป็นสิ่งจำเป็นสำหรับการพัฒนางานแม้การพัฒนางานเล็ก ๆ น้อย ๆ เช่นการรวบรวมรหัสแหล่งที่มาเพื่อเชื่อมโยงไปยังห้องสมุด

ชื่อแพคเกจบางครั้งจะต้องมีการตกแต่งบางส่วน ( libfoo0-dev? foo-devโดยไม่มีlibคำนำหน้า? ฯลฯ ) หรือคุณก็สามารถใช้ distro ของคุณค้นหาแพคเกจที่จะหาอย่างแม่นยำซึ่งเป็นแพคเกจให้ไฟล์โดยเฉพาะอย่างยิ่ง

(หากมีมากกว่าหนึ่งคุณจะต้องค้นหาความแตกต่างของพวกเขาคือการเลือก coolest หรือที่นิยมมากที่สุดคือทางลัดทั่วไป แต่ไม่ใช่ขั้นตอนที่ยอมรับได้สำหรับงานพัฒนาที่ร้ายแรงใด ๆ )

สำหรับสถาปัตยกรรมอื่น ๆ (ที่สะดุดตาที่สุดคือ RPM) จะใช้วิธีการที่คล้ายกัน


3
นี่เพิ่งช่วยฉันด้วยปัญหาที่ฉันมีกับเซิร์ฟเวอร์ใหม่และ Perl apt-get install libperl-devเรียงมันให้ฉัน ขอบคุณ :)
Andrew Newby

1
นี้! ไม่จำเป็นต้องยุ่งกับ Makefile
Byron Whitlock

นี่อาจเป็นทางออกที่พบบ่อยที่สุดและช่วยฉันรวบรวม cacti-spine บน CentOS 7 ได้ง่าย ๆyum install openssl-develแก้มัน
djluko

1
นี่เป็นการแก้ไขที่ดีที่สุดถ้าคุณพบว่า symlink ลงท้ายด้วย. so หายไป แต่คุณมี symlink เช่น libfoo.so.6 -> libfoo.so.6.0.2 (ตัวอย่าง) แทนที่จะทำ symlink ด้วย มือ. (หมายถึงคุณติดตั้งแพคเกจ libfoo แต่ไม่ใช่ libfoo-dev)
dmaestro12

39

เวลารวบรวม

เมื่อ g ++ บอกว่าcannot find -l<nameOfTheLibrary>มันหมายความว่า g ++ มองหาไฟล์lib{nameOfTheLibrary}.soแต่มันหาไม่ได้ในพา ธ การค้นหาไลบรารี่ที่แชร์ซึ่งโดยปกติแล้วจะชี้ไปที่/usr/libและ/usr/local/libอื่น ๆ

เพื่อแก้ไขปัญหานี้คุณควรระบุไฟล์ไลบรารี ( lib{nameOfTheLibrary}.so) ในพา ธ การค้นหาเหล่านั้นหรือใช้-Lตัวเลือกคำสั่ง -L{path}บอก g ++ (จริง ๆld) เพื่อค้นหาไฟล์ไลบรารีในพา ธ{path}นอกเหนือจากพา ธเริ่มต้น

ตัวอย่าง:สมมติว่าคุณมีห้องสมุดที่/home/taylor/libswift.soและคุณต้องการเชื่อมโยงแอพกับห้องสมุดนี้ ในกรณีนี้คุณควรระบุ g ++ ด้วยตัวเลือกต่อไปนี้:

g++ main.cpp -o main -L/home/taylor -lswift
  • หมายเหตุ 1 : -lตัวเลือกรับชื่อไลบรารีโดยไม่มี libและ.soที่จุดเริ่มต้นและสิ้นสุด

  • หมายเหตุ 2 : libswift.so.1.2ในบางกรณีชื่อไฟล์ห้องสมุดตามด้วยรุ่นเช่น ในกรณีเหล่านี้ g ++ ยังไม่สามารถหาไฟล์ไลบรารีได้ การแก้ปัญหาที่ง่ายในการแก้ไขปัญหานี้คือการสร้างการเชื่อมโยงสัญลักษณ์ที่จะเรียกว่าlibswift.so.1.2libswift.so


Runtime

เมื่อคุณเชื่อมโยงแอพของคุณไปยังไลบรารี่ที่แชร์ต้องมีไลบรารี่ที่พร้อมใช้งานทุกครั้งที่คุณเปิดแอพ ในรันไทม์แอปของคุณ (ตัวเชื่อมโยงแบบไดนามิกจริง) ค้นหาไลบรารีLD_LIBRARY_PATHของ มันเป็นตัวแปรสภาพแวดล้อมที่เก็บรายการเส้นทาง

ตัวอย่าง:ในกรณีของเราlibswift.soตัวอย่างเช่นลิงเกอร์แบบไดนามิกไม่สามารถหาlibswift.soในLD_LIBRARY_PATH(ซึ่งชี้ไปยังเส้นทางการค้นหาเริ่มต้น) ในการแก้ไขปัญหาคุณควรผนวกตัวแปรนั้นด้วยพา ธ ที่libswift.soมีอยู่

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/taylor

ขอบคุณสำหรับการโพสต์ของคุณ! ฉันไม่สนใจคำตอบทั้งหมดจนกระทั่งถึงเวลาที่ฉันคัดลอก.soไฟล์ไป/usr/libแต่มันก็น่าสนใจสำหรับฉันว่าexportจะช่วยได้หรือไม่ แม้จะมีกระบวนการติดตั้งmakeอีกต่อไป แต่ก็ยังมีข้อผิดพลาดอื่นเกิดขึ้น เวลา .so.0นี้ไม่พบไฟล์ แต่ทั้งคู่.soและ.so.0ไฟล์อยู่ในไดเรกทอรีที่ฉันได้สร้างแพ็คเกจขึ้นอยู่กับจากแหล่งที่มา คุณช่วยได้ไหม
A.Ametov

33

ระหว่างการคอมไพล์ด้วยการกำหนดg++ผ่านหากอาจไม่เหมาะสมในการเปลี่ยน Makefile ด้วยตัวเลือก ฉันได้ใส่ห้องสมุดเสริมไว้ในนั้นฉันก็:makeLIBRARY_PATH-L/opt/lib

$ export LIBRARY_PATH=/opt/lib/

จากนั้นจึงmakeรวบรวมและเชื่อมโยงสำเร็จ

ในการรันโปรแกรมด้วย shared library ให้กำหนด:

$ export LD_LIBRARY_PATH=/opt/lib/

ก่อนดำเนินการโปรแกรม


14

ก่อนอื่นคุณต้องรู้กฎการตั้งชื่อของlxxx:

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

lcวิธีการlibc.so, lltdlวิธีการlibltdl.so, วิธีการlXtstlibXts.so

ดังนั้นมันจึงเป็นlib+ lib-name+.so


เมื่อเรารู้ชื่อแล้วเราสามารถใช้locateค้นหาพา ธ ของlxxx.soไฟล์นี้

$ 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

หากคุณหาไม่พบคุณต้องติดตั้งโดยyum(ฉันใช้ CentOS) โดยปกติแล้วคุณมีไฟล์นี้ แต่มันไม่ได้ลิงค์ไปยังสถานที่


เชื่อมโยงไปยังสถานที่ที่เหมาะสมมักจะเป็น/lib64หรือ/usr/lib64

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

ทำ!

อ้างอิง: https://i-pogo.blogspot.jp/2010/01/usrbinld-cannot-find-lxxx.html


4
locateใช้งานได้ก็ต่อเมื่อมีการติดตั้งและทำงานเป็นประจำ วิธีแก้ปัญหาแบบหยาบคือการเรียกใช้findบนดิสก์ทั้งหมดของคุณ แต่แน่นอนว่าต้องใช้เวลา หากคุณพบว่าตัวเองทำเช่นนั้นบ่อยครั้งให้พิจารณาติดตั้งlocateเพียงเพื่อลดค่าใช้จ่าย (การโต้ตอบกับมนุษย์) ของการทำงานนี้
tripleee

5

เมื่อคุณคอมไพล์โปรแกรมของคุณคุณจะต้องระบุพา ธ ไปยังไลบรารี ใน g ++ ใช้ตัวเลือก -L:

g++ myprogram.cc -o myprogram -lmylib -L/path/foo/bar

1
คุณสมบัติใดที่เราต้องเปลี่ยนccmakeเพื่อที่Makefileจะถูกสร้างขึ้นด้วยการเชื่อมโยงธง? ฉันต้องการเชื่อมโยง-lARToolkitPlusธงของฉันกับเส้นทาง
Shashwat

2

ข้อผิดพลาดนี้อาจเกิดขึ้นได้หากลิงก์สัญลักษณ์ไปยังไลบรารีแบบไดนามิก. ดังนั้น แต่ด้วยเหตุผลดั้งเดิมที่-staticปรากฏในหมู่แฟล็กลิงก์ หากเป็นเช่นนั้นให้ลองลบออก


2

ตรวจสอบที่ตั้งของห้องสมุดของคุณเช่น lxxx.so:

locate lxxx.so

หากไม่ได้อยู่ใน/usr/libโฟลเดอร์ให้พิมพ์:

sudo cp yourpath/lxxx.so /usr/lib

เสร็จสิ้น


4
คุณต้องใช้ความระมัดระวังในการคัดลอกไลบรารีไปยังไดเรกทอรีระบบ
พอลฟลอยด์

2

นอกเหนือจากคำตอบที่ให้ไปแล้วอาจเป็นกรณีที่ไฟล์ * .so มีอยู่ แต่ตั้งชื่อไม่ถูกต้อง หรืออาจเป็นกรณีที่มีไฟล์ * .so อยู่ แต่เป็นของผู้ใช้ / รูทรายอื่น

ปัญหาที่ 1:ชื่อที่ไม่เหมาะสม

หากคุณกำลังเชื่อมโยงไฟล์ด้วย-l<nameOfLibrary> ชื่อไฟล์ไลบรารีจะต้องอยู่ในรูปแบบlib<nameOfLibrary> หากคุณมี<nameOfLibrary>.soไฟล์ให้เปลี่ยนชื่อ!

ปัญหาที่ 2:เจ้าของผิด

เพื่อตรวจสอบว่านี่ไม่ใช่ปัญหา - ทำ

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

หากไฟล์เป็นเจ้าของโดย root หรือผู้ใช้อื่นคุณต้องทำ

sudo chown yourUserName:yourUserName /path/to/.so/file

1

ห้องสมุดที่ฉันพยายามเชื่อมโยงเพื่อให้เป็นชื่อที่ไม่ได้มาตรฐาน (เช่นไม่ได้ขึ้นต้นด้วย 'lib') ดังนั้นพวกเขาจึงแนะนำให้ใช้คำสั่งเช่นนี้เพื่อรวบรวมมัน -

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


คำนำหน้าด้วย "lib" เท่านั้นที่จะได้รับชื่อมาตรฐานแก้ไขให้ฉัน
el_technic0

1

นี่คือข้อมูล Ubuntu ของแล็ปท็อปของฉัน

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

ฉันใช้ค้นหาเพื่อค้นหาไฟล์. so สำหรับ boost_filesystem และ boost_system

locate libboost_filesystem
locate libboost_system

จากนั้นลิงก์ไฟล์. so ไปยัง / usr / lib และเปลี่ยนชื่อเป็น. 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

ทำ! ติดตั้งแพคเกจ velocyto.R สำเร็จแล้ว!


1

ฉันพบข้อความแสดงข้อผิดพลาดเดียวกัน

ฉันสร้างcmockaเป็นsoและพยายามที่จะเชื่อมโยงไปยังปฏิบัติการของฉัน แต่ldมักจะบ่นด้านล่าง:

/ usr / bin / ld: ไม่พบ-lcmocka

ปรากฎว่ามี 3 ไฟล์ที่สร้างขึ้นหลังจากที่cmockaถูกสร้างขึ้น:

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

1 และ 2 เป็นลิงค์สัญลักษณ์และมีเพียง 3 ไฟล์เท่านั้น

ฉันคัดลอก 1 ไปยังโฟลเดอร์ไลบรารีของฉันซึ่งldไม่พบ 3

หลังจากที่ฉันคัดลอกทั้ง 3 ldงาน


คุณช่วยบอกด้วยสิว่าคุณหมายถึงโฟลเดอร์ใดภายใต้ "โฟลเดอร์ห้องสมุดของฉัน"?
A.Ametov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.