静态库SDK开发的事项以及思考
最近完成了百度音乐音频广告联盟SDK的开发。下面总结一下iOS平台SDK开发过程中的事项,以及我个人的一些思考。
前言
这里谈到的SDK开发是指静态库.a形式的SDK。动态framework形式的SDK开发(比如rollout)不在本文讨论的范围
交付内容
SDK完整交付时,通常要包括:
- 通用.a文件。支持在模拟器和真机上使用。即支持arm64, armv7, armv7s,x86_64, i386架构
- include文件夹。存放SDK对外提供的头文件
- Resources文件夹. 存放SDK中使用到的资源文件
- Documents文件夹。存放使用appledoc生成的代码文档
- 接入文档
- 一个demo
开发过程
关于如何开发SDK, 苹果的官方文档给出了很好的指导。但是,官方文档是从从application中抽取SDK的角度来描述的, 与先SDK后demo的思路不太一样。本文讨论的是先SDK,后demo的开发方式;但苹果的官方文档仍然具有很好的指导意义。
按照先SDK后demo的方式开始时,通常SDK工程和demo工程是在同一个workspace下的两个独立工程。原因很简单,SDK工程无法单独运行和调试。
这里只列出几点需要注意的事项:
- SDK工程
- 头文件导出
SDK需要对外提供的头文件,可以通过在Build Phases中增加Copy Files,把需要导出的头文件导出到Products/include路径下。一来方便SDK交付时提供,二来方便在demo工程中引用。苹果指出,对于静态库而言,Copy Headers在Archive时失效。这一点有待验证 - 资源文件
- 首先,资源文件是无法打包在生成的.a文件中的(这一点与.framework不同)。将Resources文件夹添加到工程中(不需要添加到SDK target中),只是为了示意在SDK交付时应该提供哪些资源文件
- 即使通过编译阶段的Copy Files将资源文件拷贝到Products目录下,在demo中仍然无法直接访问。原因很简单,app只能直接访问打包在.app里的资源文件。另外,经过测试,无论在Copy Files中设置将资源文件拷贝到其他哪个目录下,最终资源文件都只会在Products目录下。
- 依赖的系统库
SDK的依赖的系统库不需要在SDK工程中设置,只需在demo工程中设置 - 依赖的第三方SDK
与普通app开发一致,需将第三方SDK的.a静态库和include文件夹添加到工程和target中。 - 文档
利用appledoc,为需要导出的头文件提供文档。具体参见唐巧的这篇文章
- 头文件导出
- 同一workspace中的demo工程
-
在编译阶段的Link Binary With Libraries中添加workspace中的.a静态库。同一个workspace中的project共享同一个Products路径;由于SDK工程中设置了将头文件导出到Products/include路径下,而该路径自动在demo工程的Header Search Paths中,因此不需要向demo工程中添加include文件夹
-
添加资源文件(详见下节)
-
添加SDK依赖的系统库(详见下节)
-
修改编译设置中的Other linker flags(详见下节)
-
第三方app使用SDK
app中使用SDK时,不可能是把SDK工程添加到app所在的workspace中。通常要做以下几个设置:
- 将.a文件、include文件夹和Resources文件夹添加到工程中
- 添加SDK依赖的系统库库。这包括SDK源码本身需要的系统库,以及SDK使用的第三方库依赖的系统库。比如广告联盟SDK本身使用了MessuageUI.framework, 而SDK自身使用到了第三方库ASI,ASI本身依赖的系统库有SystemConfiguration.framework等,因此app中需要添加这两者依赖的系统库
- 如果SDK中使用到了category, 那么需要修改demo的编译设置,在Other linker flags中添加-ObjC选项。据说友盟SDK为了减少用户的设置,把category替换成了工具类。这也是个不错的办法。
关于这一点,可以参见stackoverflow上的一篇帖子
我的思考
- 由于.a本身无法包含include和Resources, 因此.framework的确是一种更适合的方式。可惜目前苹果没有放开对自定义framework的控制
- 开发SDK过程中使用的demo是无法直接对外提供的。