2009-03-20 33 views
13

Giả sử tôi đã ba C thư viện tĩnh nói libColor.a mà phụ thuộc vào * libRGB. * A do đó phụ thuộc vào libPixel.a. Thư viện libColor.a được cho là phụ thuộc vào thư viện libRGB.a vì có một số tài liệu tham khảo trong libColor.a đối với một số các biểu tượng quy định tại libRGB.a. Làm cách nào để kết hợp tất cả các thư viện trên với một số mới libNewColor.a độc lập?Kết hợp các thư viện tĩnh

Có nghĩa là thư viện mới phải có tất cả các ký hiệu được xác định. Vì vậy, trong khi liên kết tôi chỉ cần cung cấp cho -lNewColor. Kích thước của thư viện mới sẽ được tối thiểu tức là nó không được chứa bất kỳ biểu tượng trong libRGB.a mà không được sử dụng bởi libColor.a, vv tôi đã cố gắng may mắn của tôi bằng các tùy chọn khác nhau trong ar lệnh (dùng để tạo và cập nhật các thư viện/lưu trữ tĩnh).

+0

Hoặc bạn có thể nhìn vào http: // stackoverflow. com/questions/8170450/kết hợp-static-thư viện/8170851 # 8170851 và sử dụng libt ool – Bruce

+0

Lưu ý rằng bước giảm thiểu thực sự là không cần thiết. Với các thư viện tĩnh, trình liên kết sẽ chỉ lấy các tệp đối tượng mà nó cần, không giống như các thư viện được chia sẻ bao gồm mọi thứ. Có nhiều lý do và lợi thế cho mỗi cách tiếp cận; chúng chỉ khác nhau. Và bạn thực sự không cần phải lo lắng khi đang làm việc với các thư viện tĩnh. –

Trả lời

11

1/trích xuất TẤT CẢ các tệp đối tượng từ mỗi thư viện (sử dụng ar) và cố gắng biên dịch mã của bạn mà không cần thư viện hoặc bất kỳ tệp đối tượng nào. Có thể bạn sẽ nhận được một tải trọng tuyệt đối của các biểu tượng không xác định. Nếu bạn không nhận được biểu tượng không xác định, hãy chuyển đến bước 5.

2/Lấy biểu tượng đầu tiên và tìm ra tệp đối tượng nào đáp ứng biểu tượng đó (sử dụng nm).

3/Ghi lại tệp đối tượng đó rồi biên dịch mã của bạn, bao gồm tệp đối tượng mới. Bạn sẽ nhận được một danh sách mới những biểu tượng không xác định hoặc, nếu không có, đi đến bước 5.

4/Đến bước 2.

5/Kết hợp tất cả các file đối tượng trong danh sách của bạn (nếu có) vào một thư viện duy nhất (một lần nữa với ar).

Bang! Có bạn có nó. Cố gắng liên kết mã của bạn mà không cần bất kỳ đối tượng nào nhưng với thư viện mới.

Toàn bộ điều này có thể tương đối dễ dàng được tự động hóa bằng tập lệnh shell.

+2

Không cần thiết phức tạp, bạn chỉ có thể trích xuất tất cả các tệp .o thành một tệp .a, như khi nó được liên kết với một tệp thực thi, trình liên kết sẽ loại bỏ bất kỳ tệp nào chưa được sử dụng nào, – MarkR

+2

@MarkR, @AIB muốn kích thước của thư viện * tối thiểu, không phải kích thước của tệp thực thi. – paxdiablo

+0

Chấp nhận nó, mặc dù tôi rất thích một oneliner mà làm điều đó. Giống như chuyển một số tùy chọn để ld chỉ liên kết với các biểu tượng cần thiết, v.v ... – AIB

5

Thư viện tĩnh không nhiều hơn lưu trữ của một số tệp đối tượng (.o). Những gì bạn có thể làm là trích xuất tất cả các đối tượng trong hai thư viện (sử dụng "ar x") và sau đó sử dụng "ar" để liên kết chúng với nhau trong một thư viện mới.

15

Một chút tính năng sử dụng của Archiver GNU là kịch bản lưu trữ, nó là một giao diện đơn giản nhưng mạnh mẽ, và nó có thể thực hiện chính xác những gì bạn muốn, ví dụ nếu kịch bản sau đây được gọi là script.ar:

CREATE libNewColor.a 
ADDLIB libColor.a 
ADDLIB libRGB.a 
ADDLIB libPixel.a 
SAVE 
END 

sau đó, bạn có thể gọi ar như sau:

ar -M < script.ar 

và bạn sẽ nhận được libNewColor.a có chứa tất cả các file .o từ libColor.a libRGB.a và libPixel.a.

Ngoài ra, bạn cũng có thể thêm thông thường.o file cũng với lệnh ADDMOD:

CREATE libNewColor.a 
ADDLIB libColor.a 
ADDLIB libRGB.a 
ADDLIB libPixel.a 
ADDMOD someRandomCompiledFile.o 
SAVE 
END 

Hơn nữa nó là siêu dễ dàng để tạo các kịch bản trong Makefiles, vì vậy tôi thường tạo ra một quy tắc makefile hơi chung chung để tạo tài liệu lưu trữ mà thực sự tạo kịch bản và gọi ar trên kịch bản. Một cái gì đó như thế này:

$(OUTARC): $(OBJECTS) 
    $(SILENT)echo "CREATE [email protected]" > $(ODIR)/$(ARSCRIPT) 
    $(SILENT)for a in $(ARCHIVES); do (echo "ADDLIB $$a" >> $(ODIR)/$(ARSCRIPT)); done 
    $(SILENT)echo "ADDMOD $(OBJECTS)" >> $(ODIR)/$(ARSCRIPT) 
    $(SILENT)echo "SAVE" >> $(ODIR)/$(ARSCRIPT) 
    $(SILENT)echo "END" >> $(ODIR)/$(ARSCRIPT) 
    $(SILENT)$(AR) -M < $(ODIR)/$(ARSCRIPT) 

Mặc dù bây giờ mà tôi nhìn vào nó, tôi đoán nó không hoạt động nếu $ (ĐỐI TƯỢNG) là rỗng (tức là nếu bạn chỉ muốn kết hợp tài liệu lưu trữ mà không cần bổ sung thêm các file đối tượng) nhưng tôi sẽ để nó như một tập thể dục cho người đọc để khắc phục vấn đề rằng nếu cần thiết ...: D

Sau đây là các tài liệu cho tính năng này:

https://sourceware.org/binutils/docs/binutils/ar-scripts.html#ar-scripts

+0

Điều này thật tuyệt! Ngoại trừ bất kỳ đường dẫn/lib nào có dấu + trong tên đều phá vỡ tập lệnh. Ví dụ: openssl có libncurses ++. A – Gregory

+0

Gọn gàng! Đây là cách, dễ dàng hơn việc giải nén và tự đóng gói lại các tệp đối tượng. – Thomas

+0

Lưu ý rằng vì một số lý do -D không hoạt động kết hợp với -M. Vì vậy, nếu bạn muốn nhận được kết quả xác định, bạn vẫn cần có đường dẫn giải nén-sau đó. –

Các vấn đề liên quan