Làm thế nào để hợp nhất hai thư viện tĩnh “ar” thành một?


90

Tôi có 2 tĩnh thư viện Linux, được tạo ra bởi ar cr, libabc.alibxyz.a.
Tôi muốn hợp nhất chúng thành một thư viện tĩnh libaz.a.
Tôi có thể làm cái này như thế nào.

Tôi muốn tạo một thư viện tĩnh hợp nhất, không phải cung cấp cho cả hai thư viện vào liên kết cuối cùng của các ứng dụng.


7
Xem thêm: libtoolgiải pháp dựa trên :libtool -static -o new.a old1.a old2.a
osgx.

2
nó hoạt động hoàn hảo, chỉ có một chút nghi ngờ nếu những thư viện đó có chung file.o (nhưng chức năng khôn ngoan thì chúng khác nhau) liệu nó có còn hoạt động không?
bindingofisaac

libtool -static -o new.a old1.a old2.a dosen không hoạt động trên linux (centos 7)
trống

Câu trả lời:


60

Bạn có thể trích xuất đối tượng từ cả hai .atệp và tạo .atệp của mình bằng cách sử dụng .os:

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

63
Nguy hiểm, Will Robinson! Điều này chỉ hoạt động nếu tên của các thành viên trong libabc.a và libxyz.a không trùng nhau. Nếu không, bạn sẽ ghi đè lên một và nó sẽ bị mất.
David Given

6
Hơn nữa, libabc.acó thể chứa các đối tượng có cùng tên (có nguồn gốc từ các thư mục khác nhau) - khi đó việc lắp ráp lại sẽ không hoạt động!
Igor R.

16
ar -ckhông hoạt động với tôi (Ubuntu 14.04). Tôi hiểu ar: no operation specified. Tôi đã làm ar -qcthay thế và điều đó hoạt động tốt.
Tối đa

ar t lib.a có thể được sử dụng để xem các tệp trong thư viện mà không cần thực sự giải nén tệp.
raj_gt1

làm thế nào tôi có thể làm điều đó trong tự động?
shuva

120

Có ít nhất ba cách để làm điều này nguyên bản . Cách đầu tiên và dễ di chuyển nhất là sử dụng libtool. Sau khi đã xây dựng các thư viện khác cũng bằng libtool, bạn có thể kết hợp chúng chỉ bằng cách thêm các lib .la vào biến automake libaz_la_LIBADD hoặc trực tiếp từ Makefile với một cái gì đó như:

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

Hai phần còn lại ít nhất có sẵn khi sử dụng GNU ar. Bạn có thể sử dụng tập lệnh MRI (được đặt tên là libaz.mri chẳng hạn), chẳng hạn như:

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

và sau đó thực thi ar dưới dạng:

ar -M <libaz.mri

Hoặc bạn có thể sử dụng một kho lưu trữ mỏng (tùy chọn -T), cho phép thêm các kho lưu trữ khác mà không làm chúng lồng vào bên trong, mặc dù nhược điểm là nếu bạn muốn phân phối thư viện tĩnh, đối tượng tách rời sẽ bị thiếu:

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

Tất cả các phương pháp trên đều xử lý các tên thành viên chồng chéo từ các kho lưu trữ ban đầu.

Nếu không, bạn phải giải nén vào các thư mục khác nhau và đóng gói lại, để tránh thay thế các tên thành viên trùng lặp:

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

19
Đối với những người muốn có một kho lưu trữ bình thường (không mỏng), một điều đơn giản có thể làm là tạo một kho lưu trữ mỏng, sau đó chuyển đổi nó thành một kho lưu trữ bình thường. Một cái gì đó như: ar cqT libaz.a libabc.a libxyz.a && echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M. Điều này tạo ra một libaz.atệp mỏng tạm thời và sau đó chuyển đổi tệp lưu trữ mỏng thành một tệp bình thường (vì vậy bạn có thể di chuyển / phân phối nó). Điều này cũng xử lý một cách duyên dáng khi tên thư viện của bạn có các ký tự đặc biệt (khoảng cách, dấu cộng hoặc dấu phẩy) (tức là ar cqT libbundle.a libfoo++.a 'libbar baz.a'). Nhưng +1 từ tôi!
Cornstalks

Nhược điểm của ví dụ kịch bản MRI đầu tiên được đưa ra là gì?
jb

Câu trả lời rất hay! Thật tốt khi thấy một số tùy chọn không yêu cầu bạn giải nén và khai thác lại. Ngoài ra, tôi nghĩ ý tưởng @Cornstalks là tốt. Có lẽ nên được thêm vào câu trả lời?
Lightbulb

Này khi tôi cố gắng sử dụng lệnh cho libtooltôi nhận được những lỗi này: libtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' Bất kỳ ý tưởng nào về cách khắc phục điều đó?
Lars Nielsen

@Guillem @Cornstalks Câu trả lời tuyệt vời. Điều gì sẽ xảy ra nếu --Wl,-whole-archivetùy chọn được yêu cầu trong lệnh liên kết ban đầu cho nhiều lib * .a và tôi cần kết hợp tất cả lib * .a thành one.a. Khi liên kết lại, --Wl,-whole-archivesẽ không hoạt động với one.a. Gợi ý của bạn là gì? stackoverflow.com/questions/56323197/…
thinkdeep

10

Nếu bạn chỉ làm như sau:

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

bạn sẽ mất một số tệp đối tượng nếu có các thành viên trùng tên trong cả aa và ba vì vậy, bạn cần giải nén các thành viên của các tệp lưu trữ khác nhau vào thư mục khác nhau:

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

hơn nữa, có thể có nhiều thành viên cùng tên trong một kho lưu trữ (giả sử trong aa), nếu bạn chạy ar x aa , bạn sẽ chỉ nhận được một cho các thành viên cùng tên đó.

Cách duy nhất để trích xuất tất cả các thành viên có cùng tên trong một kho lưu trữ là chỉ định số thành viên theo tùy chọn '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
...

đây sẽ là một công việc tẻ nhạt, vì vậy bạn sẽ phải viết một kịch bản tinh vi hơn để thực hiện công việc đó.

Một giải pháp tùy chọn là bạn có thể kết hợp nhiều kho lưu trữ thành một thư viện được chia sẻ:

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

theo cách này, trình liên kết sẽ xử lý mọi thứ cho bạn!


1
Samuel, cảm ơn bạn. Nhưng khi kết hợp vào thư viện chia sẻ, tất cả các đối tượng nên được biên dịch với -fPIC.
osgx

0

Tốt hơn nữa là bạn thực hiện liên kết từng phần trên mỗi thư viện và chúng tạo một kho lưu trữ của hai tệp đối tượng kết quả. Theo cách đó, nó hoạt động giống như các thư viện được chia sẻ

Bạn thực hiện liên kết một phần với

gcc -r --nostdlib

vì vậy, thay vì tạo kho lưu trữ trung gian hoặc sau khi trích xuất lại, hãy chạy

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

sau đó

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

Nó không thực sự trả lời câu hỏi được hỏi - như anh ta yêu cầu thư viện. Nhiều khi bạn thậm chí không có nguồn cho các thư viện được cung cấp, hoặc muốn giữ chúng được tạo sẵn vì những lý do khác.
pholat

0
ar -x libx264.a
mkdir sub && cd sub
ar -m ../libx264.a `ar -t ../libx264.a |sort|uniq|grep "\.o"`
ar -x ../libx264.a

bây giờ bạn có hai phiên bản "macroblock-10.o"


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

Tại đây, bạn tạo kho lưu trữ và sau đó kết quả 'làm phẳng' (làm mỏng) bằng cờ T. Không chắc nó sẽ hoạt động như thế nào với các tệp .o cùng tên có thể chứa bên trong.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.