2010-02-20 17 views
29

Tôi có các thư viện tĩnh A, B và C được tổ chức thành các dự án Xcode. A và B phụ thuộc vào C. Khi tôi xây dựng một dự án iPhone phụ thuộc vào A và B, tôi nhận được một lỗi liên kết mà một biểu tượng trùng lặp (từ C) đã được phát hiện trong A và B. Làm thế nào tôi có thể tổ chức ba thư viện tĩnh để tôi có thể bao gồm chúng trong các dự án Xcode khác mà không gặp phải lỗi này?Làm cách nào để tránh lỗi "biểu tượng trùng lặp" trong xcode với các thư viện tĩnh được chia sẻ?

+0

chắc chắn khi xây dựng mục tiêu thư viện cho A và B, bạn chỉ nên bao gồm tiêu đề C. Bạn chỉ liên kết với C khi xây dựng dự án iPhone? –

Trả lời

6

Sự cố này không nhất thiết phải liên quan đến Xcode hoặc Mục tiêu-C. Không liên kết/lưu trữ thư viện vào các thư viện khác. A & B chỉ phụ thuộc vào C tại thời điểm liên kết cuối cùng, không phải khi chúng được tạo. Bạn muốn:

  1. build Một
  2. build B
  3. build C
  4. xây dựng ứng dụng & liên kết

Dưới đây là một dự án ví dụ tôi thực hiện để chứng minh:

Makefile:

app: main.o a.a b.a c.a 
     gcc $^ -o [email protected] 

%.o: %.c 
     gcc -Wall -c $^ 

%.a: %.o 
     ar -r [email protected] $^ 

clean: 
     rm -rf *.o *.a app 

a.c:

#include <stdio.h> 
void c(void); 

void a(void) 
{ 
    printf("a\n"); 
    c(); 
} 

trước Chúa:

#include <stdio.h> 
void c(void); 

void b(void) 
{ 
    printf("b\n"); 
    c(); 
} 

c.c:

#include <stdio.h> 

void c(void) 
{ 
    printf("c\n"); 
} 

main.c:

#include <stdio.h> 

void a(void); 
void b(void); 

int main(int argc, char *argv[]) 
{ 
    a(); 
    b(); 
    return 0; 
} 

xây dựng và chạy đăng nhập:

$ make 
gcc -Wall -c main.c 
gcc -Wall -c a.c 
ar -r a.a a.o 
ar: creating archive a.a 
gcc -Wall -c b.c 
ar -r b.a b.o 
ar: creating archive b.a 
gcc -Wall -c c.c 
ar -r c.a c.o 
ar: creating archive c.a 
gcc main.o a.a b.a c.a -o app 
rm a.o b.o c.o 
$ ./app 
a 
c 
b 
c 
+0

Cho đến khi tôi có thể nói, Xcode không cho phép/hỗ trợ điều này? Nếu có, tôi nghĩ bạn nên sửa câu trả lời của bạn để giải thích cách đạt được nó (xem câu hỏi gốc được gắn thẻ "xcode") - Tôi đến đây từ Google vì tôi không thể nhận Xcode để xử lý thiết lập đơn giản này! Nếu không, câu trả lời này là vô ích, vì nó không có gì để giải quyết câu hỏi. – Adam

25

Câu trả lời của Carl là đúng, nhưng vì những lý do sai: thực sự không có gì sai khi liên kết các thư viện tĩnh với nhau, như chúng ta có thể thấy bằng cách sử dụng mẫu của Carl. Set-up mẫu mã của Carl và sau đó làm như sau: (Tôi sử dụng libtool vì đó là những gì XCode sử dụng)

neutron:libtest jamie$ libtool -o a2.a a.a c.a 
neutron:libtest jamie$ libtool -o b2.a b.a c.a 
neutron:libtest jamie$ gcc main.o a2.a b2.a -o app2 
neutron:libtest jamie$ ./app2 
a 
c 
b 
c 
neutron:libtest jamie$ 

này liên kết a2.a và b2.a với main.o. Theo Carl, đây là nguồn của vấn đề OP, và app2 không nên liên kết. Nhưng tất nhiên là vậy. Trình liên kết đủ thông minh để bỏ qua hai phiên bản của cùng một tệp. Chúng ta có thể thấy rằng cả a2.a và b2.a đều chứa c.o:

neutron:libtest jamie$ ar -t a2.a 
__.SYMDEF SORTED 
a.o 
c.o 
neutron:libtest jamie$ ar -t b2.a 
__.SYMDEF SORTED 
b.o 
c.o 

Tuy nhiên, nó liên kết tốt.

Vấn đề là, tôi tin rằng, được liên kết với Universal Binaries, hoặc nhị phân phổ quát PPC/x86, hoặc armv6/armv7 iPhone phổ nhị phân. Vấn đề ở đây là có một lỗi với categories và sửa chữa (add -all_load thành cờ liên kết) là bản sửa lỗi chỉ hoạt động cho các kiến ​​trúc đơn lẻ. Việc sử dụng -all_load sẽ phá vỡ khả năng liên kết bỏ qua các biểu tượng được xác định cho nhiều kiến ​​trúc và bạn có lỗi biểu tượng trùng lặp của mình.

Tôi đã viết về nó here bao gồm giải pháp tốt hơn so với sử dụng -all_load.

+2

Đây là liên kết hoạt động với mục nhập blog của bạn: http://blog.binaryfinery.com/universal-static-library-problem-in-iphone-sd – ThomasW

+0

Không, liên kết đó cũng bị hỏng. Đó là "k" cuối cùng tiếp tục bị xóa. Lỗi với SO? Thử lại: http://binaryfinery.wordpress.com/2010/06/11/universal-static-library-problem-in-iphone-sdk/ – Adam

6

Cách thay thế để sử dụng -all_load là sử dụng -force_load "path_to_lib" chỉ dành cho thư viện nơi cần. Ví dụ, bạn có thể sử dụng một cái gì đó như: -force_load "$(PROJECT_DIR)/libname".

Điều này tránh những gì bạn cần làm cho giải pháp của Jamie yêu cầu bạn sửa đổi tệp triển khai.

Đây là giải pháp được thông qua bởi các dự án three20: http://groups.google.com/group/three20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df

chỉnh sửa: như của Xcode 4.3 sự cần thiết của -all_load-force_load đã bị xoá. Bây giờ chỉ cần -ObjC. Xem https://stackoverflow.com/a/2615407/211292 để biết thêm chi tiết.

+1

Mọi cập nhật cho Xcode 4.3? – Klaas

+0

'-all_load' và' -force_load' không còn cần thiết, xem tại đây: http://stackoverflow.com/a/2615407/211292 – ThomasW