วิธีพิมพ์พา ธ การค้นหา ld (linker)


153

เป็นวิธีการพิมพ์เส้นทางการค้นหาที่ค้นหาโดยldในลำดับที่ค้นหาคืออะไร

คำตอบ:


96

คุณสามารถทำได้โดยการดำเนินการคำสั่งต่อไปนี้:

ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012

gccผ่านเส้นทางพิเศษ -L ไปยัง linker ซึ่งคุณสามารถแสดงรายการด้วยคำสั่งต่อไปนี้:

gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,;  ,g' | tr \; \\012

คำตอบที่แนะนำให้ใช้ ld.so.conf และ ldconfig ไม่ถูกต้องเนื่องจากอ้างถึงเส้นทางที่ค้นหาโดยตัวเชื่อมโยงแบบไดนามิกรันไทม์ (เช่นเมื่อใดก็ตามที่มีการเรียกใช้โปรแกรม) ซึ่งไม่เหมือนกับเส้นทางที่ค้นหาโดยld (เช่นเมื่อใดก็ตามที่ โปรแกรมเชื่อมโยงแล้ว)


2
คุณตีจุด ฉันมีปัญหาการเชื่อมโยงระหว่างการเชื่อมโยงตัวเชื่อมโยงกระบวนการค้นหาไลบรารีที่ติดตั้งด้วยตนเอง/usr/local/..ซึ่งทำให้เกิดข้อผิดพลาดของไลบรารีที่ขาดหายไปและการเชื่อมโยงล้มเหลว ฉันต้องเปลี่ยนชื่อ/usr/localทุกครั้งเพื่อแยกเส้นทางการค้นหานั้น มีวิธีง่าย ๆ ในการแยกหรือแทนที่/usr/localเส้นทางหรือไม่
kenn

1
คุณสามารถลองระบุเส้นทางของห้องสมุดด้วยตัวเลือก -L ถึง GCC ซึ่งฉันคิดว่า (ไม่แน่ใจ) จะแทนที่เส้นทางของไลบรารีระบบ คุณสามารถลองตั้งค่าตัวแปร env LIBRARY_PATH ก่อนที่จะรวบรวม: $ LIBRARY_PATH = / somedir / gcc ...
faken

1
ฉันรู้ว่าการลิงก์ในการคอมไพล์บรรทัดคำสั่ง ฉันหมายถึงวิธีทั่วโลกในการแทนที่ldเส้นทางการค้นหา ยกตัวอย่างเช่นบางครั้งผมต้องรวบรวมรหัสที่มาจากmakefileหรือสร้าง Makefile จากconfigureสคริปต์หรือจากCMakeLists.txtหรือแม้กระทั่งคนที่มีความซับซ้อนมากขึ้นเช่นหรือvala srtฉันยากที่จะแก้ไขldพา ธ การค้นหาในกรณีเช่นนี้
kenn

เมื่อใช้ CMake คุณสามารถเลือกไลบรารีที่แน่นอนซึ่งใช้ในระหว่างขั้นตอนการกำหนดค่า (รายการเหล่านี้บางรายการจะแสดงเฉพาะในโหมดขั้นสูง) สำหรับสคริปต์การกำหนดค่าจาก Autotools ดูคำตอบนี้: stackoverflow.com/questions/7561509/... สิ่งนี้ไม่ตอบคำถามของคุณโดยตรง แต่อาจช่วยคุณทำสิ่งที่คุณต้องการ
นำ

82

บน Linux คุณสามารถใช้ldconfigซึ่งดูแลการกำหนดค่าและแคช ld.so เพื่อพิมพ์การค้นหาไดเรกทอรีld.soด้วย

ldconfig -v 2>/dev/null | grep -v ^$'\t'

ldconfig -vพิมพ์การค้นหาไดเรกทอรีโดย linker (ไม่มีแท็บนำ) และไลบรารีที่ใช้ร่วมกันที่พบในไดเรกทอรีเหล่านั้น (พร้อมแท็บนำ); grepได้รับไดเรกทอรี บนเครื่องของฉันบรรทัดนี้จะพิมพ์ออกมา

/usr/lib64/atlas:
/usr/lib/llvm:
/usr/lib64/llvm:
/usr/lib64/mysql:
/usr/lib64/nvidia:
/usr/lib64/tracker-0.12:
/usr/lib/wine:
/usr/lib64/wine:
/usr/lib64/xulrunner-2:
/lib:
/lib64:
/usr/lib:
/usr/lib64:
/usr/lib64/nvidia/tls: (hwcap: 0x8000000000000000)
/lib/i686: (hwcap: 0x0008000000000000)
/lib64/tls: (hwcap: 0x8000000000000000)
/usr/lib/sse2: (hwcap: 0x0000000004000000)
/usr/lib64/tls: (hwcap: 0x8000000000000000)
/usr/lib64/sse2: (hwcap: 0x0000000004000000)

พา ธ แรกโดยไม่ต้องhwcapอยู่ในบรรทัดอาจเป็นแบบบิวด์อินหรืออ่านจาก /etc/ld.so.conf ตัวลิงก์สามารถค้นหาไดเร็กทอรีเพิ่มเติมภายใต้พา ธ การค้นหาไลบรารีพื้นฐานด้วยชื่อที่sse2สอดคล้องกับความสามารถของ CPU เพิ่มเติม พา ธ เหล่านี้ที่มีhwcapในบรรทัดสามารถมีไลบรารีเพิ่มเติมที่ปรับให้เหมาะกับความสามารถของ CPU เหล่านี้

หมายเหตุสุดท้ายประการหนึ่ง: การใช้-pแทนการ-vค้นหาด้านบนจะทำการld.soแคชแทน


51
เขากำลังถามเกี่ยวกับ linker (ld) และไม่ใช่ loader (ld.so)!
fons

3
เป็นไปได้อย่างไรที่ฉันตั้งค่าexport LD_LIBRARY_PATH=/some/other/dirมันจะไม่ส่งผลกระทบต่อเอาต์พุตของคำสั่งนี้! ดูเหมือนว่ามันจะใช้งานไม่ได้ 100% ใช่ไหม
TMS

3
@fons Funnything คือว่าฉันมาที่นี่เพื่อหาคำตอบนี้ :) เส้นทางลิงค์หรือเวลาทำงาน? ฉันเดาว่าเป็นคำถาม LIBRAY_PATH (เวลาลิงก์) vs LD_LIBRARY_PATH
Daniel Santos

2
ฉันพบในบางแพลตฟอร์ม (เช่น arm กับ Linaro toolchain) ที่ ldconfig ไม่ได้ค้นหาไดเรกทอรีเดียวกันกับ linker เวลาทำงาน คุณสามารถเอามันออกเส้นทางการค้นหาและรวมเส้นทางจากการLD_LIBRARY_PATHเปิดใช้งานการดีบัก เช่นLD_DEBUG=libs /lib/ld-linux.so --list cat(คุณสามารถใช้ไฟล์ปฏิบัติการใดก็ได้ฉันเลือกcatเป็นสิ่งแรกที่ฉันนึกออก) อาจคุ้มค่าสำหรับ " search path" โปรดทราบว่าหากคุณมีสิ่ง/etc/ld.so.cacheที่ตรงกับ libs ที่จำเป็นทั้งหมดคุณจะไม่ได้เห็นเส้นทางการค้นหาระบบในตัวเพราะจะไม่ไปไกล
John O'M

คือgccเส้นทางการค้นหาเดียวกันกับเหล่านี้หรือไม่
nn0p

68

ฉันไม่แน่ใจว่ามีตัวเลือกใด ๆ เพียงพิมพ์เส้นทางการค้นหาที่มีประสิทธิภาพเต็มรูปแบบ

แต่: เส้นทางการค้นหาประกอบด้วยไดเรกทอรีที่ระบุโดย-Lตัวเลือกในบรรทัดคำสั่งตามด้วยไดเรกทอรีที่เพิ่มไปยังเส้นทางการค้นหาโดยSEARCH_DIR("...")คำสั่งในสคริปต์ตัวเชื่อมโยง ดังนั้นคุณสามารถทำงานได้ถ้าคุณเห็นทั้งสองอย่างซึ่งคุณสามารถทำได้ดังนี้

หากคุณกำลังเรียกใช้ldโดยตรง:

  • -Lตัวเลือกคือสิ่งที่คุณได้กล่าวว่าพวกเขาจะ
  • หากต้องการดูสคริปต์ตัวเชื่อมโยงให้เพิ่ม--verboseตัวเลือก มองหาSEARCH_DIR("...")คำสั่งโดยปกติจะอยู่ใกล้กับส่วนบนของเอาต์พุต (โปรดทราบว่าสิ่งเหล่านี้ไม่จำเป็นต้องเหมือนกันสำหรับการเรียกใช้ทุกครั้งld- ตัวเชื่อมโยงมีจำนวนตัวเชื่อมโยงสคริปต์เริ่มต้นในตัวที่แตกต่างกันและเลือกระหว่างตัวเลือกเหล่านั้นตามตัวเลือกตัวเชื่อมโยงอื่น ๆ )

หากคุณกำลังเชื่อมโยงผ่านgcc:

  • คุณสามารถส่ง-vตัวเลือกเพื่อgccให้มันแสดงวิธีเรียกใช้ตัวเชื่อมโยง ในความเป็นจริงก็ปกติไม่ได้เรียกใช้ldโดยตรง แต่ทางอ้อมผ่านทางเครื่องมือที่เรียกว่าcollect2(ซึ่งอาศัยอยู่ในหนึ่งในไดเรกทอรีภายใน) ldซึ่งในทางกลับกันจะเรียก ที่จะแสดงให้คุณเห็นว่า-Lมีการใช้ตัวเลือกใดบ้าง
  • คุณสามารถเพิ่ม-Wl,--verboseไปยังgccตัวเลือกที่จะทำให้มันผ่านไป--verboseผ่านไปยังตัวเชื่อมโยงที่จะเห็นสคริปต์ลิงเกอร์ตามที่อธิบายไว้ข้างต้น

5
ตัวเลือก --verbose สำหรับลิงเกอร์ทำเคล็ดลับ มีประโยชน์มาก!
Ari

ฉันพยายามอย่างหนักที่จะหาว่าตัวเชื่อมโยงนั้นค้นหาที่ไหนและไม่พบ SEARCH_DIR ในผลลัพธ์ ปรากฎว่าฉันใช้-T scriptสคริปต์ของฉันแทนที่สคริปต์เริ่มต้นของ ld อย่างสมบูรณ์และดูเฉพาะที่ฉันชี้เท่านั้น
thomasa88

30

คำสั่งที่เข้ากันได้มากที่สุดที่ฉันพบสำหรับ gcc และ clang บน Linux (ขอบคุณ armando.sano):

$ gcc -m64 -Xlinker --verbose  2>/dev/null | grep SEARCH | sed 's/SEARCH_DIR("=\?\([^"]\+\)"); */\1\n/g'  | grep -vE '^$'

ถ้าคุณให้-m32มันจะส่งออกไดเรกทอรีห้องสมุดที่ถูกต้อง

ตัวอย่างบนเครื่องของฉัน:

สำหรับg++ -m64:

/usr/x86_64-linux-gnu/lib64
/usr/i686-linux-gnu/lib64
/usr/local/lib/x86_64-linux-gnu
/usr/local/lib64
/lib/x86_64-linux-gnu
/lib64
/usr/lib/x86_64-linux-gnu
/usr/lib64
/usr/local/lib
/lib
/usr/lib

สำหรับg++ -m32:

/usr/i686-linux-gnu/lib32
/usr/local/lib32
/lib32
/usr/lib32
/usr/local/lib/i386-linux-gnu
/usr/local/lib
/lib/i386-linux-gnu
/lib
/usr/lib/i386-linux-gnu
/usr/lib

ขอบคุณ! ปรับปรุงเล็ก - กำจัด grep หรือสอง: sed -n 's / SEARCH_DIR ("= \? ([^"] \ +) "); * / \ 1 \ n / gp'
Bruce K

2
ทำไมสิ่งนี้จึงต้องใช้วิธีการที่คลุมเครือ?
bmacnaughton

สิ่งนี้ได้ผลเหมือนมนต์เสน่ห์! เราจะเพิ่มไดเรกทอรีในรายการเส้นทางการค้นหา linker ได้อย่างไร
ปารีส

6

คำถามถูกแท็ก Linux แต่อาจใช้งานได้กับ Linux หรือไม่

gcc -Xlinker -v

ภายใต้ Mac OS X สิ่งนี้จะพิมพ์:

@(#)PROGRAM:ld  PROJECT:ld64-224.1
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 armv6m armv7m armv7em
Library search paths:
    /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/lib
Framework search paths:
    /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/
[...]

-Xlinkerตัวเลือกในการgccดังกล่าวข้างต้นเป็นเพียงแค่ผ่านไป-v ldอย่างไรก็ตาม:

ld -v

ไม่พิมพ์เส้นทางการค้นหา


บน Linux มันพิมพ์ไดเรกทอรีเช่นกัน -Lpathแต่ในรูปแบบของ ดังนั้นคำตอบของ @ Raphaël Londeix ดีกว่า
pevik

2

รุ่น Mac: $ ld -v 2 ไม่ทราบวิธีรับเส้นทางโดยละเอียด เอาท์พุต

Library search paths:
    /usr/lib
    /usr/local/lib
Framework search paths:
    /Library/Frameworks/
    /System/Library/Frameworks/

3
ฉันได้รับ "ไม่สามารถเปิด 2: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว" เล่นld -v 2
แจ็ค

2
คำถามคือแท็กลินุกซ์ไม่ OS X ได้ผมไม่เชื่อว่า OS X ใช้ ldGNU กลุ่ม Binutil ปิดการใช้งานในสคริปต์การสร้าง มันถูกปิดการใช้งานมานานหลายปี
jww
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.