จะรวมไลบรารีแบบคงที่“ ar” สองไลบรารีเข้าเป็นหนึ่งเดียวได้อย่างไร


92

ฉันมีห้องสมุดลินุกซ์ 2 คงที่สร้างขึ้นโดยar cr, และlibabc.a ฉันต้องการรวมเข้าเป็นห้องสมุดคงที่เดียว ฉันจะทำสิ่งนี้ได้อย่างไรlibxyz.a
libaz.a

ฉันต้องการสร้างไลบรารีแบบคงที่ที่ผสานไม่ใช่เพื่อให้ทั้งสองไลบรารีไปยังลิงค์สุดท้ายของแอปพลิเคชัน


8
ดูเพิ่มเติม: libtool- วิธีแก้ปัญหา :libtool -static -o new.a old1.a old2.a
osgx

2
มันทำงานได้อย่างสมบูรณ์แบบเพียงแค่สงสัยเล็กน้อยว่าไลบรารีเหล่านั้นมีไฟล์ทั่วไปหรือไม่ (แต่ฟังก์ชันการทำงานต่างกัน) จะยังใช้งานได้หรือไม่
bindingofisaac

libtool -static -o new.a old1.a old2.a ไม่ทำงานบน linux (centos 7)
หยุด

คำตอบ:


62

คุณสามารถแยกออบเจ็กต์จากทั้งสอง.aไฟล์และสร้าง.aไฟล์ของคุณโดยใช้.os:

ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a  *.o

66
อันตราย Will Robinson! สิ่งนี้ใช้ได้เฉพาะเมื่อชื่อของสมาชิกใน libabc.a และ libxyz.a ไม่ทับซ้อนกัน มิฉะนั้นคุณจะเขียนทับหนึ่งรายการและจะสูญหายไป
David Given

7
ยิ่งไปกว่านั้นlibabc.aอาจมีวัตถุที่มีชื่อเดียวกัน (ที่มาจากไดเรกทอรีที่แตกต่างกัน) - การประกอบใหม่จะไม่ทำงาน!
อิกอร์

17
ar -cไม่ได้ผลสำหรับฉัน (Ubuntu 14.04) ฉันar: no operation specifiedเข้าใจแล้ว ฉันทำar -qcแทนและได้ผลดี
สูงสุด

ar t lib.a สามารถใช้เพื่อดูไฟล์ในไลบรารีโดยไม่ต้องแตกไฟล์จริงๆ
raj_gt1

ฉันจะทำแบบนั้นในระบบอัตโนมัติได้อย่างไร
shuva

126

มีอย่างน้อยสามวิธีที่จะทำเช่นนี้โดยกำเนิด วิธีแรกและพกพาสะดวกที่สุดคือใช้ libtool หลังจากสร้างไลบรารีอื่น ๆ ด้วย libtool แล้วคุณสามารถรวมเข้าด้วยกันได้เพียงแค่เพิ่ม. la libs เข้ากับตัวแปรอัตโนมัติ libaz_la_LIBADD หรือโดยตรงจาก Makefile ด้วยสิ่งที่ต้องการ:

libtool --mode=link cc -static -o libaz.la libabc.la libxyz.la

อีกสองรายการเป็นอย่างน้อยเมื่อใช้ GNU ar คุณสามารถใช้สคริปต์ MRI (ชื่อเช่น libaz.mri) เช่น:

create libaz.a
addlib libabc.a
addlib libxyz.a
save
end

จากนั้นดำเนินการ ar เป็น:

ar -M <libaz.mri

หรือคุณสามารถใช้ไฟล์เก็บถาวรแบบบาง (ตัวเลือก-T) ซึ่งจะช่วยให้สามารถเพิ่มไฟล์เก็บถาวรอื่น ๆ ได้โดยไม่ต้องซ้อนอยู่ภายในแม้ว่าข้อเสียคือหากคุณต้องการกระจายไลบรารีแบบคงที่วัตถุที่แยกออกจะหายไป:

ar -rcT libaz.a libabc.a libxyz.a

วิธีการทั้งหมดข้างต้นจัดการชื่อสมาชิกที่ทับซ้อนกันจากไฟล์เก็บถาวรต้นฉบับได้อย่างสง่างาม

มิฉะนั้นคุณจะต้องแตกไฟล์ในไดเรกทอรีอื่นและบรรจุใหม่อีกครั้งเพื่อหลีกเลี่ยงการแทนที่ชื่อสมาชิกที่ทับซ้อนกัน:

mkdir abc; cd abc; ar -x ../libabc.a
mkdir xyz; cd xyz; ar -x ../libxyz.a
ar -qc libaz.a abc xyz

19
สำหรับผู้ที่ต้องการไฟล์เก็บถาวรแบบปกติ (ไม่บาง) สิ่งง่ายๆอย่างหนึ่งที่สามารถทำได้คือสร้างไฟล์เก็บถาวรแบบบางจากนั้นแปลงเป็นไฟล์เก็บถาวรปกติ สิ่งที่ชอบ: ar cqT libaz.a libabc.a libxyz.a && echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M. สิ่งนี้จะสร้างบางชั่วคราวlibaz.aจากนั้นแปลงไฟล์เก็บถาวรแบบบางเป็นไฟล์ปกติ (คุณจึงสามารถย้าย / แจกจ่ายได้) นอกจากนี้ยังจัดการอย่างสง่างามเมื่อชื่อไลบรารีของคุณมีอักขระพิเศษ (เว้นวรรคเครื่องหมายบวกหรือลูกน้ำ) (เช่นar cqT libbundle.a libfoo++.a 'libbar baz.a') แต่ +1 จากฉัน!
Cornstalks

อะไรคือข้อเสียของตัวอย่างสคริปต์ MRI แรกที่ให้มา?
jb

คำตอบที่ดี! ดีที่จะเห็นตัวเลือกบางอย่างที่ไม่ต้องการให้คุณดึงข้อมูลและทำให้สำเร็จ ฉันคิดว่าไอเดีย @Cornstalks นั้นดี อาจจะควรจะเพิ่มคำตอบ?
Lightbulb1

เฮ้เมื่อฉันพยายามใช้คำสั่งเพื่อlibtoolรับข้อผิดพลาดเหล่านี้: มีlibtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' ความคิดอย่างไรในการแก้ไขปัญหานั้น?
Lars Nielsen

@Guillem @Cornstalks คำตอบที่ดี จะเกิดอะไรขึ้นถ้า--Wl,-whole-archiveจำเป็นต้องใช้ตัวเลือกในคำสั่งการลิงก์ดั้งเดิมสำหรับ lib * .a หลายตัวและฉันต้องรวม lib * .a ทั้งหมดเข้าone.aด้วยกัน เมื่อเชื่อมโยงอีกครั้งจะไม่ทำงานกับ--Wl,-whole-archive one.aข้อเสนอแนะของคุณคืออะไร? stackoverflow.com/questions/56323197/…
thinkdeep

10

ถ้าคุณทำมันเป็น:

ar x a.a
ar x b.a
ar c c.a  *.o 

คุณจะสูญเสียไฟล์ออบเจ็กต์บางไฟล์หากมีสมาชิกที่มีชื่อเดียวกันทั้งใน aa และ ba ดังนั้นคุณต้องแยกสมาชิกของไฟล์เก็บถาวรที่แตกต่างกันไปยังโฟลเดอร์อื่น:

ar x a.a && mv *.o a_objs
ar x b.a && mv *.o b_objs
ar c c.a a_objs/*.o b_objs/*.o

ยิ่งไปกว่านั้นเป็นไปได้ว่ามีสมาชิกหลายคนที่มีชื่อเดียวกันในไฟล์เก็บถาวรเดียว (พูดใน aa) หากคุณเรียกใช้ar x aaคุณจะได้รับเพียงหนึ่งเดียวสำหรับสมาชิกที่มีชื่อเดียวกัน

วิธีเดียวที่จะแยกสมาชิกทั้งหมดที่มีชื่อเดียวกันในไฟล์เก็บถาวรเดียวคือระบุหมายเลขสมาชิกโดยใช้ตัวเลือก 'N':

ar xN 1 a.a  xxx.c.o && mv xxx.c.o xxx.c.1.o
ar xN 2 b.a  xxx.c.o && mv xxx.c.o xxx.c.2.o
...

นี่จะเป็นงานที่น่าเบื่อดังนั้นคุณจะต้องเขียนสคริปต์ที่ซับซ้อนมากขึ้นเพื่อทำงานนั้น

ทางเลือกหนึ่งคือคุณสามารถรวมไฟล์เก็บถาวรหลายไฟล์ไว้ในไลบรารีเดียว

g++ -shared -o c.so -Wl,--whole-archive a.a b.a 

วิธีนี้ผู้เชื่อมโยงจะจัดการทุกสิ่งให้คุณ!


1
ซามูเอลขอบคุณ แต่ในการรวมเข้ากับไลบรารีที่ใช้ร่วมกันอ็อบเจ็กต์ทั้งหมดควรถูกคอมไพล์ด้วย-fPIC.
osgx

0

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

คุณทำการเชื่อมโยงบางส่วนกับ

gcc -r --nostdlib

ดังนั้นแทนที่จะสร้างไฟล์เก็บถาวรระดับกลางหรือหลังจากแยกตัวกลับแล้วให้เรียกใช้

gcc -r --nostdlib $CFLAGS $OBJECTS_A -o $LIBNAME_A.o
gcc -r --nostdlib $CFLAGS $OBJECTS_B -o $LIBNAME_B.o

แล้ว

ar -cr $LIBNAME_JOINED.a $LIBNAME_A.o $LIBNAME_B.o

มันไม่ได้ตอบคำถามที่ถามจริงๆ - อย่างที่เขาถามหาห้องสมุด หลายครั้งที่คุณไม่มีแหล่งข้อมูลสำหรับห้องสมุดหรือต้องการเก็บไว้ล่วงหน้าจากเหตุผลอื่น ๆ
pholat


0
ar crsT libaz.a libabc.a libxyz.a

ที่นี่คุณสร้างที่เก็บถาวรของไฟล์เก็บถาวรจากนั้น 'แบน' (การทำให้ผอมบาง) ผลลัพธ์ด้วย T ไม่แน่ใจว่าจะทำงานอย่างไรกับไฟล์. o ชื่อเดียวกันที่อาจมีอยู่ภายใน

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