ลิงก์คงที่ของฟังก์ชั่นไลบรารีที่ใช้ร่วมกันใน gcc


138

ฉันจะลิงก์ฟังก์ชันไลบรารีที่แบ่งใช้แบบคงที่ใน gcc ได้อย่างไร?


14
คุณหมายถึงอะไรโดยการเชื่อมโยงแบบคงที่? คุณต้องการให้ไฟล์ปฏิบัติการของคุณถูกรบกวนโดยไม่ต้องใช้. so?
Emiliano

คำตอบ:


108

อ้างถึง:

http://www.linuxquestions.org/questions/linux-newbie-8/forcing-static-linking-of-shared-libraries-696714/

http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2004-05/0436.html

คุณต้องใช้ไลบรารีเวอร์ชันคงที่เพื่อเชื่อมโยง

จริง ๆ แล้วไลบรารี่ที่ใช้ร่วมกันนั้นสามารถเรียกใช้งานได้ในรูปแบบพิเศษโดยมีจุดเข้าใช้งานที่ระบุ มันไม่ได้มีข้อมูลทั้งหมดที่จำเป็นในการเชื่อมโยงแบบคงที่

คุณไม่สามารถเชื่อมโยงไลบรารีที่ใช้ร่วมกันแบบคงที่ (หรือลิงก์แบบคงที่แบบไดนามิก)

ธง -staticจะบังคับให้ตัวเชื่อมโยงใช้ไลบรารีแบบคงที่ (.a) แทนการใช้ร่วมกัน (.so) คน แต่ไลบรารีแบบคงที่จะไม่ติดตั้งตามค่าเริ่มต้นเสมอดังนั้นคุณอาจต้องติดตั้งไลบรารีแบบคงที่ด้วยตัวเอง

อีกวิธีที่เป็นไปได้คือการใช้statifierหรือแมวน้ำ เครื่องมือทั้งสองใช้เป็นอินพุตในการปฏิบัติการที่เชื่อมโยงแบบไดนามิกและในขณะที่เอาท์พุทสร้างปฏิบัติการที่มีอยู่ในตัวเองพร้อมกับไลบรารีที่แชร์ทั้งหมดที่ฝังตัว


11
ไลบรารีแบบสแตติกมีข้อมูลใดบ้างเพื่อให้สามารถเชื่อมโยงแบบคงที่ซึ่งไลบรารีแบบไดนามิกไม่มี
kbolino

75

หากคุณต้องการเชื่อมโยงพูดlibapplejuiceแบบคงที่ แต่ไม่ใช่พูดliborangejuiceคุณสามารถลิงก์เช่นนี้:

gcc object1.o object2.o -Wl,-Bstatic -lapplejuice -Wl,-Bdynamic -lorangejuice -o binary

มีข้อแม้ - ถ้าliborangejuiceใช้libapplejuiceแล้วlibapplejuiceจะมีการเชื่อมโยงแบบไดนามิกเช่นกัน

คุณจะต้องเชื่อมโยงliborangejuiceแบบคงที่พร้อมกับที่libapplejuiceจะได้รับlibapplejuiceแบบคงที่

และอย่าลืมที่จะเก็บไว้เป็น-Wl,-Bdynamicอย่างอื่นคุณจะสิ้นสุดการเชื่อมโยงทุกอย่างคงที่รวมถึงlibc(ซึ่งไม่ใช่สิ่งที่ดีที่จะทำ)


2
ไม่มีวิธีบอก gcc โดยตรงว่าจะเชื่อมโยงแบบสแตติกหรือไม่และหลีกเลี่ยงเขาและคุยกับลิงเกอร์
Elazar Leibovich

1
@ElazarLeibovich คุณไม่สามารถรับชุดค่าผสมของแบบคงที่และแบบไดนามิกได้
Haozhun

@EugeneBujak: ข้อแม้ใช้ไม่ได้กับระบบของฉัน ตัวอย่าง: gcc -o main main.cc -Wl,-rpath=. -Wl,-Bdynamic -lB -Wl,-Bstatic -lA -Wl,-Bdynamic -L. libBใช้LIBAมันเชื่อมโยงและlddไม่ได้แสดงการอ้างอิงถึงLIBA ปฏิบัติการสามารถทำงานได้ดี ทดสอบกับ g ++ 4.7.3
radix

ทางอ้อม (ซ้อน), คงที่, การพึ่งพาโดยตรง, แบบไดนามิก, การพึ่งพาไม่ได้กลายเป็นตัวเชื่อมโยงแบบไดนามิก
Vinny

พิจารณาสิ่งต่อไปนี้: binA ขึ้นอยู่กับ libB.so ซึ่งขึ้นอยู่กับ libC.a ตามที่คนอื่น ๆ ได้ระบุไว้แล้ว. ดังนั้นจึงเป็น executables ของตัวเองดังนั้นเมื่อมีการเชื่อมโยงวัตถุที่ใช้ร่วมกันผู้อ้างอิงไลบรารีแบบคงที่ใด ๆ ปฏิบัติการที่ถูกเชื่อมโยง: สัญลักษณ์เดียวที่ดึงเข้ามาจาก lib แบบคงที่. a คือสิ่งที่ถูกอ้างถึง (และยังไม่ได้แก้ไข) โดย. so ซึ่งหมายความว่าหาก binA อ้างถึงสัญลักษณ์ใน libC.a ไม่ได้อ้างอิงที่ใดก็ได้ใน libB.so ดังนั้นแม้ว่า binA จะเชื่อมโยงไปยัง libB.so สัญลักษณ์นั้นจะไม่ได้กำหนดไว้ (ยกเว้น -Wl, - ทั้งไฟล์เก็บถาวรจะถูกใช้เมื่อทำการลิงก์ libB.so)
Vinny

18

หากคุณมีไฟล์. a ของไลบรารีที่แชร์ของคุณ (.so) คุณสามารถรวมไฟล์ด้วยพา ธ เต็มของไฟล์ราวกับว่าเป็นไฟล์วัตถุเช่นนี้:

สิ่งนี้สร้าง main.o เพียงรวบรวม:

gcc -c main.c

ลิงก์นี้ไฟล์อ็อบเจ็กต์ที่มีไลบรารีสแตติกที่สอดคล้องกันและสร้างไฟล์ปฏิบัติการ (ชื่อ "main")

gcc main.o mylibrary.a -o main

หรือในคำสั่งเดียว:

gcc main.c mylibrary.a -o main

มันอาจเป็นเส้นทางที่สมบูรณ์หรือสัมพัทธ์:

gcc main.c /usr/local/mylibs/mylibrary.a -o main

12

ใช่ฉันรู้ว่านี่เป็นคำถามอายุ 8 ปี แต่ฉันบอกว่ามันเป็นไปได้ที่จะเชื่อมโยงกับห้องสมุดวัตถุที่ใช้ร่วมกันแบบคงที่และนี่เป็นสิ่งที่ฮิตที่สุดเมื่อฉันค้นหาข้อมูลเพิ่มเติมเกี่ยวกับมัน

เพื่อแสดงให้เห็นจริงว่าการเชื่อมโยงไลบรารีวัตถุที่ใช้ร่วมกันแบบคงที่เป็นไปไม่ได้ด้วยld( gcc's linker) - ซึ่งต่างจากผู้คนจำนวนมากที่ยืนยันว่าไม่สามารถทำได้ - ใช้gccคำสั่งต่อไปนี้:

gcc -o executablename objectname.o -Wl,-Bstatic -l:libnamespec.so

(แน่นอนคุณจะต้องรวบรวมobjectname.oจากsourcename.cและคุณควรสร้างห้องสมุดวัตถุที่ใช้ร่วมกันของคุณเองเช่นกันหากคุณใช้-Wl,--library-path,.ให้ใช้ld เพื่อหาห้องสมุดของคุณในไดเรกทอรีท้องถิ่น)

ข้อผิดพลาดจริงที่คุณได้รับคือ:

/usr/bin/ld: attempted static link of dynamic object `libnamespec.so'
collect2: error: ld returned 1 exit status

หวังว่าจะช่วย


10

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

CDE: สร้างแอปพลิเคชัน Linux แบบพกพาโดยอัตโนมัติ

http://www.pgbovine.net/cde.html

  • เพียงดาวน์โหลดโปรแกรม
  • ดำเนินการผ่านไบนารีเป็นอาร์กิวเมนต์ชื่อของไบนารีที่คุณต้องการให้พกพาตัวอย่างเช่น: nmap

    ./cde_2011-08-15_64bit nmap

โปรแกรมจะอ่าน libs ทั้งหมดที่เชื่อมโยงกับ nmap และ dependencias ของมันและมันจะบันทึกพวกมันทั้งหมดในโฟลเดอร์ที่เรียกว่าcde-package / (ในไดเรกทอรีเดียวกันกับที่คุณเป็น)

  • ในที่สุดคุณสามารถบีบอัดโฟลเดอร์และปรับใช้ไบนารีแบบพกพาในระบบใดก็ได้

จำไว้ว่าในการเรียกใช้โปรแกรมพกพาคุณจะต้องดำเนินการไบนารีที่อยู่ในcde-package / nmap.cde

ขอแสดงความนับถืออย่างสูง


2
ในขณะที่ไม่ได้ให้คำตอบสำหรับคำถาม - มันเป็นวิธีการแก้ปัญหาที่น่าทึ่ง
razong

ลิงค์ดูเหมือนจะตายแล้ว
sinan

0

ใน gcc สิ่งนี้ไม่ได้รับการสนับสนุน อันที่จริงแล้วสิ่งนี้ไม่ได้รับการสนับสนุนในคอมไพเลอร์ / ลิงเกอร์ที่ฉันมีอยู่


4
คุณช่วยอธิบายว่าคอมไพเลอร์ใด ๆ ที่มีอยู่ไม่สนับสนุนการเชื่อมโยงสแตติกได้อย่างไร
jww

5
@noloader, การเชื่อมโยงคงที่ของไลบรารีแบบไดนามิก?
รอ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.