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)

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