iOS App使用CocoaPod二进制集成

Why?

随着项目中源码越来越多,源码集成形式编译一次需要20+min。

How?

项目组件化后用Pod管理, 然后Pod里面维护的不是源代码,而是静态链接库,通过Cocoapods对zip支持这一特性,对项目进行二进制集成,将项目中所有的pod编译成二进制库(.a)文件。 这样最终编译的时候, 只需要进行部分编译加链接签名,完成打包,以此来加快编译速度。

Benefits

集成方式 编译时间(min)
源码集成 20+
二进制集成 5+

Details

  1. 创建一个 Xcode 工程
  2. 生成 Podfile,进行 Pod Install
  3. 生成静态链接库
  4. 解析原有 PodSpec,修改里面的 sourcecode 为 *.h 并添加静态链接库
  5. 发布到私有cocoapod repo上

创建一个 Xcode 工程

创建一个模板工程,丢到 Git 上

这里需要注意一个问题,工程里面一定要有个类,否则他不会编译的。

生成 Podfile,进行 Pod Install

创建Podfile模板

target 'Template' 
# 可替换内容
end

而可替换内容,应该是脚本的传入参数。例如 AFNetworking ~> 2.4

生成静态链接库

这里我们选择用 xcodebuild 来打包

但这里需要注意个问题。我们目标是生成静态链接库,所以我们要保证 i386、x86_64、armv7、arm64 四个平台都要有。

  • armv7 arm64
1
2
3
4
5
xcodebuild -workspace Template.xcworkspace \
-scheme Template \
-configuration Release \
build \

CONFIGURATION_BUILD_DIR=~/Desktop/workspace/Template/build

注意 CONFIGURATION_BUILD_DIR 需要绝对路径,相对路径会报找不到文件的错误。

  • i386 x86_64
1
2
3
4
5
6
7
8
xcodebuild -workspace Template.xcworkspace \
-scheme Template \
-configuration Release \
clean build \
CONFIGURATION_BUILD_DIR=~/Desktop/workspace/Template/build \
ARCHS='i386 x86_64' \
VALID_ARCHS='i386 x86_64'\
-sdk iphonesimulator

相对于 arm 平台,这个版本多了 clean, ARCHS, VALID_ARCHS, -sdk 这几个参数来保证编译顺利通过。

  • 合并 .a 文件
1
lipo -create libSignatureLibary_armv7.a libSignatureLibary_i368.a -output libSignatureLibary.a

解析原 podspec

把原有的podspec文件通过 Pod 的工具转换成 json。

pod ipc spec xxx.podspec > xxx.podespec.json

修改xxx.podespec.json内容

  1. s.source的更改,原来是指向该pod所对应的git仓库地址,现在则是指向该pod所对应文件服务器上zip包的地址。(这得益于Cocoapods对zip支持的这一特性)
  2. vendored_libraries的更改。vendored_libraries便是指向pod内部所使用的二进制包。
  3. 二进制初,在s.resource中并没有放指定.m文件,如果想要查看二进制之后pod的.m文件只能通过源码全量集成来看,后来为了能够在二进制中查看.m文件,遂把.m文件也放到了s.resource下面,这样既满足二进制,又能够查看响应的.m文件。
  4. 通过递归方法修改s.source_file.source_file中指向该pod的.h文件。
  5. 若该pod中还引用了子pod的相关文件,则要递归修改子pod相关问题。

在给podspec添加vendored_libraries的时候,有的pod自身已经引入了别的二进制包,所以事先要判断原来是否存在二进制包,并且原来的podspec所引入的二进制包可能不止一个。不然容易出现新增的二进制包将原来二进制包替换的情况。

发布

打包.a和.h成zip包, 上传到文件服务器,上传xxx.podespec.json到私有cocoapod repo

项目二进制集成

由于Podfile本身就是用ruby执行的文件,所以可以添加ruby的脚本在里面

  • 拉取远端二进制集成的spec.json文件到本地目录.cache_sdk_specs

  • 在Podfile中导入二进制脚本

require './binary_pod'

  • 对于需要二进制的Pod进行专属二进制pod的指定

binary_pod 'AFNetworking', '2.4.0'

  • 脚本生成专属的Podfile

pod 'AFNetworking', :podspec => './.cache_sdk_specs/AFNetworking/1.0.2.1/AFNetworking.podspec'

对于zip后的pod,在上传到文件服务器后,项目中通过pod install拉去二进制包的过程中,遇到过路径相关问题而无法拉取响应的.a文件。解决方案是在指定vendored_libraries的时候需要在原有路径前新增一层级路径,看过微信和微博的sdk都是在前面包了一层路径,所以仿效来,果然可行。具体原因不明

END