2011-09-27 59 views
16

我已經在Xcode中創建了一個新的可可框架,除了支持文件之外,它還刪除了它在開頭包含的所有庫和文件。如何在Xcode 4中使用dylib文件創建工作框架

我有2個文件:

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"); 

} 

在構建階段我添加add.c編譯來源和add.h編譯頭公衆。項目構建沒有問題,但在框架中沒有dylib文件,並且當我將框架拖放到另一個項目時,它表示無法找到dylib文件。

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 

我該如何製作一個簡單的框架並在其中保存dylib文件?

回答

61

我認爲你誤解了錯誤信息。

A .framework可用作動態庫,但在.framework文件夾內不會有任何帶有實際.dylib文件擴展名的Mach-O可加載對象文件。

在運行時,您可能會從dyld(動態鏈接庫加載程序)中收到錯誤消息,其中有幾個原因。首先是你忘記在構建過程中將.frameworks複製到構建的應用程序包中。雖然可以將它們複製到應用程序包內的任何位置,但傳統位置在AppName.app/Contents/Frameworks/中。如果您還沒有這樣做,請選擇「項目」>「新建構建階段」>「新建文件構建階段」。將目標彈出框更改爲框架,如下圖所示。

enter image description here

你會然後拖動該框架的圖標進入文件夾,這樣它在生成過程中複製。

enter image description here

框架不能在運行時發現的第二個也是更可能的原因是你沒有指定爲您的主執行程序的任何運行路徑的搜索路徑。 (這是必要的,因爲正如我們從錯誤消息中看到的,您的框架是使用新版@rpath/樣式安裝名稱(@rpath/add.framework/Versions/A/add)而不是舊樣式@executable_path/@loader_path/樣式構建的。

只要你自定義的框架複製到上面提到的位置,你會添加@loader_path/../Frameworks運行路徑的搜索路徑條目,如下面所示的圖像:

enter image description here

以下摘錄說明如何動態庫在運行時間發現的是從dyld手冊頁:

動態庫LOADING

與許多其他操作系統不同,達爾文未通過它們的葉文件名找到依賴動態庫的 。取而代之的是使用每個dylib的完整路徑(例如 )。 /usr/lib/libSystem.B.dylib)。但是有時候完整的路徑並不合適;例如,可能希望將您的二進制文件安裝在磁盤上的任何位置,即 。爲了支持這一點,有三個可用作路徑前綴的變量 @xxx/。在運行時間dyld@xxx/前綴替代動態生成的路徑。

@executable_path/

此變量被替換爲路徑包含用於處理主可執行文件的目錄 。這對於 加載嵌入在.app目錄中的dylib /框架非常有用。如果 主執行文件是在/some/path/My.app/Contents/MacOS/My 和框架dylib文件是在
/some/path/My.app/Contents/Frameworks/Foo.framework/Versions/A/Foo, 然後框架載荷路徑可被編碼爲 @executable_path/../Frameworks/Foo.framework/Versions/A/Foo和 的.app目錄可能 可以在文件系統和dyld搬來搬去仍然可以通過 加載嵌入式框架。

@loader_path/

此變量被替換爲路徑到包含Mach-O的二進制其包含使用 @loader_path負荷命令的目錄 。因此,在每個二進制文件中,@loader_path解析爲 不同的路徑,而@executable_path總是解析爲相同路徑的 。如果最終文件系統 插件的位置未知(因此不能使用絕對路徑) 或者如果使用該插件,則@loader_path作爲嵌入在插件中的框架/ dylib的加載路徑是有用的通過多個應用程序(因此不能使用 @executable_path)。如果插件在Mach-O的文件是在 /some/path/Myfilter.plugin/Contents/MacOS/Myfilter和 框架dylib文件是在 /some/path/Myfilter.plugin/Contents/Frameworks/Foo.framework/Versions/A/Foo, 然後框架負載路徑 可以編碼爲 @loader_path/../Frameworks/Foo.framework/Versions/A/FooMyfilter.plugin目錄可以是 在文件中四處移動系統和dyld仍然可以通過 加載嵌入式框架。

@rpath/

dyld的維護的路徑當前棧調用運行路徑 名單。遇到@rpath時,它會被運行路徑列表中的每個 路徑替換,直到找到可加載的dylib。 運行路徑堆棧是根據導致當前dylib負載的依賴鏈中的LC_RPATH加載命令構建的。您可以 將LC_RPATH加載命令添加到-rpath選件 到ld(1)的圖像。您甚至可以添加一個LC_RPATH加載命令路徑,該加載命令路徑 以@loader_path/開頭,並且它將在運行 路徑堆棧上推送路徑,該路徑相對於包含LC_RPATH的映像。 當你有一個複雜的 目錄結構的程序和dylibs可以在任何地方安裝 ,但保持其相對位置時,使用@rpath是最有用的。此場景 可以使用@loader_path實現,但每個dylib客戶端都可能需要不同的加載路徑,因爲其在文件系統中的相對位置不同。使用@rpath 引入了簡化事物的間接級別。你 選擇你的目錄結構中的一個位置作爲定位點。 每個dylib都會得到一個以@rpath開頭的安裝路徑,而 是dylib相對於定位點的路徑。每個主 可執行文件與-rpath @loader_path/zzz鏈接,其中zzz是 從可執行文件到定位點的路徑。運行時 dyld將其設置爲定位點的路徑,則每個dylib都是相對於定位點找到的 。

+5

哇!這是一個完整答案,它也解決了我遇到的問題!謝謝!! –

+0

非常徹底和完整的答案...幹得好! –

+0

完美答案!我從不知道如何工作。太好了! – JackPearse