與java和.net一樣,objc也由類庫的概念,不過在在objc上一般叫庫,庫表示程序代碼集合,可以共享給其他程序使用,庫是編譯后的二進制文件,因此不能看到源代碼,多用於一些開放sdk(如百度地圖sdk),商用庫,這兩天在研究iOS上編譯靜態庫,這里把編譯的過程和中間遇到的一些問題做一下記錄,方便以后查閱
objc上的庫一般分為兩類
靜態庫: .a 和 .framework
.a文件:純二進制文件,需要配合.h文件一起使用,通過.h文件引用庫里面的內容
.framework文件:包含二進制文件
鏈接時,靜態庫會被完整地復制到可執行文件中,例如iOS程序打包的時候會包含所有引用的靜態庫
動態庫: .dylib 和 .framework
iOS項目不支持動態庫,每個APP都是獨立運行的,並且不能直接互相訪問,APP只能訪問系統自帶的動態庫,動態庫系統只加載一次,並可以用於多個程序共享的,一般在用於桌面系統,鏈接時不會被添加到可執行文件,如果動態鏈接庫不存在,程序可能執行失敗
這里只討論靜態鏈接庫,這里只討論.a文件的生成,.framework文件先不討論
1、下面我們創建一個自己的靜態庫(Cocoa Touch Static Library)
2、添加自己的類和category
編譯的時候需要將 頭文件拷貝到生成的庫路徑下,這里的頭文件是用於給外部使用的,一般是把庫里面的文件放在一個頭文件中引用,這樣外部在使用的時候直接引用該頭文件即可
3、設置支持的最低版本和最高版本
Base SDK:是當前類庫是基於哪個版本的SDK開發的,也就是最高支持的SDK
Deployment Target:類庫支持的最低版本
4、配置編譯選項
由於我們編譯的是類庫,在使用的時候需要支持Debug和Release兩種模式下,需要編譯所有的architecture版本
4、編譯(Cmd + B)
我們分別切換到模擬器和真機模式進行編譯,在真機模式下編譯完成后,Products中的文件會變正常(原來為紅色)
注意,需要設置Build Release 版本
5、編譯完成
編譯完成后我們得到很多個.a文件,每個目錄下都對應一個.a文件,從libCalculator.a進入Finder查看
iphoneos是真機用的
iphonesimulator是給模擬器用的
6、使用
我們創建一個iOS項目,吧相關的.a文件和.h文件拖到我們的項目中,拖入后,xcode會自動把靜態庫添加到工程
這里需要注意的是
1、頭文件也要引入到工程里面(不然你怎么用)
2、模擬器和真機對應的.a文件不一樣,根據需要引用.a文件
2、如果靜態庫內有category分類,那么需要在添加 -ObjC 編譯標識,否則可能會報:unrecognized selector sent to instance
3、其他編譯參數
-ObjC:加了這個參數后,鏈接器就會把靜態庫中所有的Objective-C類和分類都加載到最后的可執行文件中
-all_load:會讓鏈接器把所有找到的目標文件都加載到可執行文件中,但是千萬不要隨便使用這個參數!假如你使用了不止一個靜態庫文件,然后又使用了這個參數,那么你很有可能會遇到ld: duplicate symbol錯誤,因為不同的庫文件里面可能會有相同的目標文件,所以建議在遇到-ObjC失效的情況下使用-force_load參數。
-force_load:所做的事情跟-all_load其實是一樣的,但是-force_load需要指定要進行全部加載的庫文件的路徑,這樣的話,你就只是完全加載了一個庫文件,不影響其余庫文件的按需加載
引用自:http://www.cnblogs.com/robinkey/archive/2013/05/27/3101095.html
4、如果靜態庫中采用ObjectC++實現,或者靜態庫使用C/C++寫的,在調用的時候可能出錯,因此需要您保證您工程中至少有一個.mm后綴的源文件(您可以將任意一個.m后綴的文件改名為.mm)
或者在工程屬性中指定編譯方式,即將XCode的Project -> Edit Active Target -> Build -> GCC4.2 - Language -> Compile Sources As設置為"Objective-C++"
引用自:http://blog.csdn.net/zhangkongzhongyun/article/details/8047500
7、合並.a文件
上面看到,編譯后的用於模擬器的靜態庫和用於真機的靜態庫不一樣,每次切換的適合都得重新引用.a文件,這樣顯得特別麻煩,蘋果提供了一個合並多個.a文件的方法,合並后的.a文件真機和模擬器都支持(合並后大小為原來兩個文件大小之和)
在終端通過命令合並
lipo –create Release-iphoneos/libsqlcipher.a Release-iphonesimulator/libsqlcipher.a –output libsqlcipher.a
還有一種方法可以動態的引用靜態庫,就是通過配置工程的庫引用路徑和編譯標示,編譯的適合xcode會根據當前的環境自動找到相關的.a庫,參見:http://www.cnblogs.com/bomo/p/4760791.html
8、Demo
http://files.cnblogs.com/files/bomo/CompileStaticLibrary.zip