2011-09-27 7 views
16

Tôi đã tạo một khung cacao mới trong Xcode, loại bỏ tất cả các thư viện và tệp mà nó bao gồm ngay từ đầu ngoại trừ các tệp hỗ trợ.Làm cách nào để tạo một khung làm việc với các tệp dylib trong Xcode 4

Tôi có 2 file:

add.h 

#ifndef add_add_h 
#define add_add_h 

void add(void); 

#endif 

add.c 
#include <stdio.h> 
#include "add.h" 

void add(void) 
{ 
    printf("adfding"); 

} 

trong xây dựng giai đoạn tôi thêm add.c để biên dịch nguồn và add.h để biên dịch tiêu đề công cộng. Dự án xây dựng mà không có một vấn đề nhưng trong khuôn khổ không có tập tin dylib và khi tôi kéo và thả khuôn khổ cho dự án khác nó nói rằng tập tin dylib không thể được tìm thấy.

dyld: Library not loaded: @rpath/add.framework/Versions/A/add 
    Referenced from: /Users/vjoukov/Desktop/Projects/test/build/Debug/test.app/Contents/MacOS/test 
    Reason: image not found 

Làm cách nào để tạo một khuôn khổ đơn giản và giữ các tệp dylib bên trong?

Trả lời

61

Tôi nghĩ bạn hiểu nhầm thông báo lỗi.

A .framework hoạt động như một thư viện động, nhưng sẽ không có bất kỳ tệp đối tượng có thể tải Mach-O nào có đuôi mở rộng .dylib thực tế bên trong thư mục .framework.

Có một vài lý do khiến bạn có thể nhận được thông báo lỗi đó từ dyld, trình tải thư viện liên kết động, khi chạy. Đầu tiên là bạn quên sao chép .frameworks vào gói ứng dụng được xây dựng trong quá trình xây dựng. Mặc dù chúng có thể được sao chép vào bất kỳ vị trí nào bên trong gói ứng dụng, địa điểm truyền thống nằm trong AppName.app/Contents/Frameworks/. Nếu bạn chưa làm như vậy, hãy chọn Project> New Build Phase> New Copy Files Build Phase. Thay đổi cửa sổ bật lên Đích đến Khung như trong hình bên dưới.

enter image description here

Sau đó bạn sẽ kéo biểu tượng của khuôn khổ này vào thư mục để nó được sao chép trong quá trình xây dựng.

enter image description here

Lý do thứ hai và nhiều khả năng khuôn khổ không thể được tìm thấy trong thời gian chạy là bạn đã không quy định bất kỳ đường dẫn tìm kiếm runpath cho thực thi chính của bạn. (Điều này là cần thiết, bởi vì, như chúng ta đã thấy từ thông báo lỗi của bạn, khung của bạn được tạo bằng tên cài đặt kiểu @rpath/ mới hơn (@rpath/add.framework/Versions/A/add) thay vì kiểu cũ hơn @executable_path/ hoặc @loader_path/).

Miễn là bạn sao chép các khung tùy chỉnh đến vị trí nêu trên, bạn sẽ thêm một mục runpath đường dẫn tìm kiếm các @loader_path/../Frameworks, như thể hiện trong hình dưới đây:

enter image description here

Đoạn trích sau đây giải thích cách thư viện động được tìm thấy trong thời gian chạy là từ manpage của dyld:

THƯ VIỆN nĂNG đỘNG LOADING

Không giống như nhiều hệ điều hành khác, Darwin không xác định vị trí thư viện động phụ thuộc thông qua tên tệp lá của chúng. Thay vào đó, sử dụng đường dẫn đầy đủ cho mỗi dylib được sử dụng (ví dụ: /usr/lib/libSystem.B.dylib). Nhưng đôi khi đường dẫn đầy đủ không phù hợp; ví dụ: có thể muốn các tệp nhị phân của bạn là có thể cài đặt ở mọi nơi trên đĩa. Để hỗ trợ điều đó, có ba biến số @xxx/ có thể được sử dụng làm tiền tố đường dẫn. Khi chạy dyld thay thế đường dẫn được tạo động cho tiền tố @xxx/.

@executable_path/

Biến này được thay thế bằng đường dẫn đến thư mục chứa thực thi chính cho quá trình này. Điều này hữu ích cho việc tải các khung/khung công tác được nhúng trong thư mục .app vào . Nếu tập tin thực thi chính là tại /some/path/My.app/Contents/MacOS/My và một tập tin khuôn khổ dylib là
/some/path/My.app/Contents/Frameworks/Foo.framework/Versions/A/Foo, thì đường dẫn tải khuôn khổ có thể được mã hóa như @executable_path/../Frameworks/Foo.framework/Versions/A/Foo và thư mục .app thể được di chuyển xung quanh trong hệ thống tập tin và dyld vẫn sẽ có thể để tải khung được nhúng.

@loader_path/

Biến này được thay thế bằng đường dẫn đến thư mục chứa các mach-o nhị phân chứa các lệnh tải sử dụng @loader_path. Do đó, trong mọi nhị phân, @loader_path sẽ phân giải thành một đường dẫn khác nhau , trong khi @executable_path luôn phân giải theo đường dẫn tương tự . @loader_path hữu ích như đường dẫn tải cho khung công tác được nhúng trong plugin, nếu hệ thống tệp cuối cùng vị trí của plugin không xác định (không thể sử dụng đường dẫn tuyệt đối) hoặc nếu plugin được sử dụng bởi nhiều ứng dụng (vì vậy không thể sử dụng @executable_path). Nếu các plug-in mach-o tập tin là tại /some/path/Myfilter.plugin/Contents/MacOS/Myfilter và một tập tin dylib khuôn khổ là tại /some/path/Myfilter.plugin/Contents/Frameworks/Foo.framework/Versions/A/Foo, thì đường dẫn tải khung có thể được mã hóa như @loader_path/../Frameworks/Foo.framework/Versions/A/Foo và thư mục Myfilter.plugin có thể di chuyển xung quanh trong file hệ thống và dyld sẽ vẫn có thể tải khung được nhúng.

@rpath/

Dyld duy trì một chồng hiện tại của con đường được gọi là con đường chạy danh sách . Khi gặp phải @rpath, nó được thay thế bằng mỗi đường dẫn trong danh sách đường dẫn chạy cho đến khi có thể tìm thấy dylib có thể tải. Ngăn xếp đường dẫn chạy được xây dựng từ các lệnh tải LC_RPATH trong chuỗi bắt buộc tải xuống dẫn đến tải trọng dylib hiện tại. Bạn có thể thêm lệnh tải LC_RPATH vào hình ảnh có tùy chọn -rpath đến ld (1). Bạn thậm chí có thể thêm đường dẫn lệnh tải LC_RPATH rằng bắt đầu bằng @loader_path/ và nó sẽ đẩy đường dẫn trên ngăn xếp đường dẫn liên quan đến hình ảnh có chứa LC_RPATH. Việc sử dụng @rpath hữu ích nhất khi bạn có cấu trúc thư mục phức tạp của các chương trình và dylib có thể được cài đặt ở bất kỳ đâu, nhưng giữ vị trí tương đối của chúng. Kịch bản này có thể được triển khai bằng cách sử dụng @loader_path, nhưng mỗi khách hàng của dylib có thể cần đường dẫn tải khác vì vị trí tương đối trong hệ thống tệp khác nhau. Việc sử dụng số @rpath giới thiệu mức độ gián tiếp giúp đơn giản hóa mọi thứ. Bạn chọn một vị trí trong cấu trúc thư mục của bạn làm điểm neo. Mỗi dylib sau đó nhận được đường dẫn cài đặt bắt đầu bằng @rpath và là đường dẫn đến dylib tương ứng với điểm neo. Mỗi thực thi chính được liên kết với -rpath @loader_path/zzz, trong đó zzz là đường dẫn từ tệp thực thi đến điểm neo. Khi chạy dyld đặt nó chạy đường dẫn làm điểm neo, sau đó mỗi dylib là được tìm thấy liên quan đến điểm neo.

+5

WOW! Đó là một heck của một câu trả lời hoàn chỉnh, nó cũng giải quyết được một vấn đề tôi đã có! Cảm ơn!! –

+0

Câu trả lời rất kỹ lưỡng và đầy đủ ... Rất tốt! –

+0

Câu trả lời hoàn hảo! Tôi không bao giờ biết làm thế nào dyld làm việc. Tốt đẹp! – JackPearse