ios如何製作自己的靜態庫及遇到的問題

iOS如何製作自己的靜態庫

前言

之前一直在做的SDK,SDK的項目結構是項目工程下 有工作空間A,A工作空間又SDK靜態庫工程frameworkB,有靜態庫工程Frameworkdemo測試工程。其中使用pod管理需要引用的第三方SDK,之前一直是這樣的結構打包出來的framework給第三方使用,沒有出現什麼問題,最近一個第三方使用時出現大量warnings users/username//library/developer/xcode/deriveddata/ no such file or directory

搜了大量的解決辦法,大多都是像這位大神說的一樣:https://nixwang.com/2016/05/09/kill-debug-symbol-warnings/

但這種方法對我的項目並不起效果。

最後根據warnings的目錄,是靜態庫工程鏈接到測試demo工程的一些目錄,最終決定將靜態庫工程與demo工程區分兩個工程。(雖然最終覺得意義並不大。。。。)

靜態庫與動態庫

我們平時使用的第三方SDK或者系統的framework,其實就是庫,庫就是將代碼封裝爲一段編譯好的二進制文件,對外提供頭文件供外界使用功能。而這些庫中又區分靜態庫(Static Library )與動態庫(Dynamic Frameworks).

靜態庫

我們平時使用的第三方SDK一般都屬於靜態庫,靜態庫的形式有.a 和 .framwork,靜態庫具備如下特點:

  1. 靜態庫中不可以包含其他靜態庫,所以在引入靜態庫A的時候,如果靜態庫A包含了靜態庫B需要導入靜態庫B,這個特點也體現了靜態庫的減少耦合,因爲每一個靜態庫都是獨立的,不會重複引用。
  2. 在APP編譯的時候,會拷貝一份靜態庫編譯到目標程序中,相當於靜態庫嵌入,所以得到的APP二進制文件會變大。
  3. 在使用的時候需要手動添加靜態庫到項目中,並手動添加靜態庫依賴的其他第三方靜態庫,

動態庫

我們平時使用的系統庫大多都是動態庫,比如UIKit.framework ,動態庫的形式有 .framework 和 .tbd,.dylib。所有 .tbd、.dylib形式的庫都是動態庫。動態庫的特點:

  1. 系統的動態庫在編譯的時候不會拷貝到目標項目裏,而是在使用的時候動態加載。因此動態庫具有共享性
  2. 動態庫可以包含靜態庫,也能自動link需要的依賴庫。
  3. 動態庫不需要單獨link依賴庫

.a 和 .framework 的區別

  1. .a 是靜態庫文件,不包含頭文件,提供 .a 形式的時候需要同時提供頭文件
  2. .framework 文件,包含 Headers :暴露出去的頭文件,binary:二進制文件,bundle:資源文案,另外還有info.lipst和modules ,主要記錄framework的版本信息,一般刪除掉。提供framework不用單獨提供頭文件,將需要暴露的頭文件設置爲public即可。依賴的第三方文件需要單獨引入。

Framework的製作

  1. 創建靜態庫項目

    File-New-選擇【iOS】選項下Framework & Library下的 【Cocoa Touch Framework】創建項目

  2. 修改配置
    1. 設置framework最低支持iOS 系統版本:選擇target—build settings—ios Deployment Target 選擇支持的最低版本;
    2. 設置支持的Architecture:Build Settings —Archeitectures—選擇Standard architectures, Buidl Active Architecture Only 設置爲 NO
    3. 設置靜態庫模式:.Build Setting 搜索linking 設置Dead Code Stripping 爲NO是編譯選項優化,包瘦身,(可不改) Mach-O Type 選中StaticLibrary (靜態庫) Xcode默認是動態庫.
  3. 開始code ,添加.h文件和.m 文件,按自己的需求
  4. 將需要暴露的.h 文件設置爲public

    Targets—Build Phases 將需要暴露的.h 文件拖拽到 public區域中。

  5. 在編譯前設置release模式

    菜單欄選擇product–scheme—Edit Scheme(或使用快捷鍵 command+<),在info 下 build configuration 選擇release模式。

  6. 開始打包framework
    1. 選擇模擬器,快捷鍵build(command+b)

    2. 選擇真機測試機,快捷鍵build

    3. 在項目結構中Products 下生成.framework(比如叫test.framework),

    4. 右鍵test.framework --show in finder,

    5. 打開終端,建議先檢查 二進制文件是否符合要求,比如

      在終端輸入命令: lipo -info test.framework的目錄/test  
      以上命令也可以cd到test.framework下, lipo -info test 查看
      真機的結果是:armv7  arm64 
      模擬器的結果是: i386 x86_64
      
    6. 合併兩個framework的二進制文件:使用如下命令

      lipo -create 真機編譯的test.framewrok/test 路徑 模擬器編譯的test.framework/test -output 新的路徑
      

      獲取到新的二進制文件後複製到真機下的test.framewrok 裏,獲取最終的framework。

pod 管理第三方SDK

  1. 確認cocoapod已經安裝,如未安裝,可按照鏈接安裝CocoaPods,https://guides.cocoapods.org/using/getting-started.html#getting-started

  2. 如果還沒有 Podfile文件,使用以下命令創建一個

  3. cd 項目目錄
    pod init
    
  4. 添加想要安裝的第三方SDK

    target 項目名稱 do
    // 添加需要添加的第三方SDK,比如
    pod 'AFNetworking 3.2.1'
    end
    
  5. 執行 pod install命令。安裝成功後打開.xcworkspace 。

測試靜態庫

  1. 新建一個Signle App項目,將打包好的test.framework添加到項目target-build phase-link binary with libraries目錄下。
  2. 如果test.framework依賴了其他第三方靜態庫,同時需要將其他第三方靜態庫添加到測試工程中,添加方法同上。
  3. 如果項目依賴了其他動態庫,比如AFNetworking,需要添加到 target-build phase-Emabed Frameworks 目錄下。

重新構建項目結構過程中出現的問題

1、運行時提示找不到AFNetworking 相關的類

原因:在靜態庫使用pod管理第三方工程,編譯的時候沒有將pod的第三方庫打包到自己的靜態庫工程中

解決:需要在引入自己的靜態庫的同時 ,在target-build phase-Emabed Frameworks 中添加AFN

2、添加阿里SDK的時候出現 openssl <XXX/XXX.h>類型.h not found,但項目目錄中有該.h文件
  1. 不要將文件夾都拖拽過來,新建文件夾,確認文件夾的顏色是黃色的,並有件使用:Add Files to XXX添加文件
  2. 在target -build setting-headers search paths :添加 $(SRCROOT)/項目名稱$(SRCROOT)/項目名稱/ssl所在文件夾
3、將現有項目拖拽過來後,framework可以編譯通過,但是無法使用。提示:​ Undefined symbol: OBJC_CLASS$_類名。
  1. 檢查所需Framework是否已經添加到項目裏,可以使用引入頭文件是否可以正常編譯,而不會找不到檢查靜態庫是否已經添加。
  2. 確認靜態庫已經添加後,考慮是靜態庫本身問題,沒有將靜態庫本身的源碼(.m)文件打包成framework。可以通過檢查: 靜態庫target-build phases-Headers裏是否包含了項目中應有的.h文件,在 靜態庫target-build phases-Compile Sources 中已添加了對應的.m文件。
  3. 不要把項目都拖拽到新的項目,文件可能鏈接不對,重新創建項目,然後複製文件。文件夾的顏色爲 黃色
4、添加了某些資源,編譯時報錯:XXX:bundle format unrecognized, invalid ,or unsuitable in subcomponent . command Codesign failed with a nonzero exist code.
  1. 嘗試一下方法:Select Podsinthe navigation -->TARGETS -->your FDTakeResources -->Signing(Enable Development Signing) -->Identity(Choose Info.plist File).
  2. 檢查項目裏 靜態庫 target - build phase–Copy Bundle Resource下是否正確鏈接的bundle資源文件,而不是源碼裏的文件夾。
  3. 如有源碼裏的文件夾,刪除掉即可。查看framework的大小可以觀察framework是否正常。
5、can’t locate file for:XXX 某個靜態庫Libtool failed with a nonzero exit code

原因:沒有鏈接到某一個靜態庫

解決:在target -build setting-library search paths : 中添加這個.a 文件的目錄,記得使用相對鏈接,比如使用$(inherited)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章