3.CocoaPods的原理

来源:互联网 发布:项目数据分析报告 编辑:程序博客网 时间:2024/05/01 15:08

前言

本文为通识性的文章,并且会不断更新,如果有什么地方不懂的或者有需要补充的以及不太正确之处可以留言,我会补上的,谢谢各位!~

CocoaPods是将所有的依赖库都放到另一个名为Pods的项目中,然后让主项目依赖Pods项目。这样,源码管理工作都从主项目移到了Pods项目中。

  1. Pods项目最终会编译成一个名为lisPods.a的文件,主项目只需要依赖这个.a文件即可。
  2. 对于资源文件,CocoaPods提供了一个名为Pods-resources.sh 的bash脚本,该脚本在每次项目编译的时候都会执行,将第三方库的各种资源文件复制到目标目录中。
  3. CocoaPods通过一个名为Pods.xconfig 的文件来编译时设置所有的依赖和参数。

核心组件

CocoaPods是用ruby写的,并由若干个ruby包(gems)构成。在解析整合的过程中,最终要的几个gems分别是:CocoaPods/CocoaPods、CocoaPods/Core、CocoaPods/Xcodeproj。(CocoaPods是一个依赖管理工具 —— 利用依赖管理进行构建的)

CocoaPods/CocoaPod

这是一个面向用户的组件,每当执行一个pod命令时,这个组件都将被激活。该组件包括了所有使用CocoaPods涉及到的功能,并且还能通过调用左右其他的gems来执行任务。

CocoaPods/Core

Core组件提供支持与CocoaPods相关文件的处理,文件主要是Podfile和podspecs。

podfile

这是一个文件,用于定义项目中所需要使用的第三方库。该文件支持高度定制,你可以根据个人喜好对其作出定制。这里不展开叙述,若想了解更多,可以查看Podfile指南。

Podspec

.podspec也是一个文件,该文件描述了一个库是怎样被添加到工程中的。它支持的功能有:列出源文件、framework、编译选项和某个库所需要的依赖等。

CocosPods/Xcodeproj

这个gem组件负责所有工程文件的整合。它能够对创建修改xcodeproj.xworkspace 文件。它也可以作为一个单独的gem包使用。如果你想要写一个脚本来方便的修改工程文件,那么可以使用这个gem。

运行pod install 命令

当在运行pod install 命令时,会引发很多操作。如果想要深入了解这个命令执行的详细内容,可以运行 pod install --verbose。当运行该命令后,会看到类似以下的内容。

$ pod install --verboseAnalyzing dependencies                      分析依赖Updating spec repositories                  更新spce仓库Updating spec repo `master`                 更新‘master’分支  $ /usr/bin/git pull  Already up-to-date.Finding Podfile changes  - AFNetworking  - HockeySDKResolving dependencies of `Podfile`Resolving dependencies for target `Pods' (iOS 6.0)  - AFNetworking (= 1.2.1)  - SDWebImage (= 3.2)    - SDWebImage/CoreComparing resolved specification to the sandbox manifest  - AFNetworking  - HockeySDKDownloading dependencies-> Using AFNetworking (1.2.1)-> Using HockeySDK (3.0.0)  - Running pre install hooks    - HockeySDKGenerating Pods project  - Creating Pods project  - Adding source files to Pods project  - Adding frameworks to Pods project  - Adding libraries to Pods project  - Adding resources to Pods project  - Linking headers  - Installing libraries    - Installing target `Pods-AFNetworking` iOS 6.0      - Adding Build files      - Adding resource bundles to Pods project      - Generating public xcconfig file at `Pods/Pods-AFNetworking.xcconfig`      - Generating private xcconfig file at `Pods/Pods-AFNetworking-Private.xcconfig`      - Generating prefix header at `Pods/Pods-AFNetworking-prefix.pch`      - Generating dummy source file at `Pods/Pods-AFNetworking-dummy.m`    - Installing target `Pods-HockeySDK` iOS 6.0      - Adding Build files      - Adding resource bundles to Pods project      - Generating public xcconfig file at `Pods/Pods-HockeySDK.xcconfig`      - Generating private xcconfig file at `Pods/Pods-HockeySDK-Private.xcconfig`      - Generating prefix header at `Pods/Pods-HockeySDK-prefix.pch`      - Generating dummy source file at `Pods/Pods-HockeySDK-dummy.m`    - Installing target `Pods` iOS 6.0      - Generating xcconfig file at `Pods/Pods.xcconfig`      - Generating target environment header at `Pods/Pods-environment.h`      - Generating copy resources script at `Pods/Pods-resources.sh`      - Generating acknowledgements at `Pods/Pods-acknowledgements.plist`      - Generating acknowledgements at `Pods/Pods-acknowledgements.markdown`      - Generating dummy source file at `Pods/Pods-dummy.m`  - Running post install hooks  - Writing Xcode project file to `Pods/Pods.xcodeproj`  - Writing Lockfile in `Podfile.lock`  - Writing Manifest in `Pods/Manifest.lock`Integrating client project

可以看到,整个过程执行了很多的操作。把这些操作分解开,可以发现,其实这些操作很简单,以下逐步来分析一下。

1. 读取podfile 文件

你是否觉得podfile的语法格式很奇怪,事实上 ,podfile 中的语言是用ruby写的。相较而言,这要比现有的其他格式更加简单一些。
在安装期间,第一步是要弄清楚显式或隐式的声明了哪些第三方库。在加载podspec的过程中,CocoaPods就建立了包括版本信息在内的所有第三方库的列表。podspec 被存储在本地路径 ~/.cocospods 中。

1.1. 版本控制和冲突

CocosPods使用语义版本控制,命名约定来解决对版本的依赖。由于冲突解决系统建立在非重大变更的补丁版本之间,这样就会让依赖关系变得相对容易一些。

比如,两个不同的pods依赖某个pod库的两个版本,假设一个依赖于2.3.1 ,一个依赖于 2.3.3 ,此时冲突解决系统可以使用最新的版本 2.3.3 ,因为这个可以向后与 2.3.1 兼容。

然而,这样的解决方式并不能解决所有问题,总会有一些冲突需要手动解决。如果一个库依赖1.2.5,另外一个库依赖2.3.1,那么只用最终用户通过明确指定使用某个版本来解决冲突。

在做项目的过程中,会遇到这样的情况,有些项目的源码由于年代稍微有些久远或者其他原因没有使用pod进行管理依赖库,而是把需要引入第三方库的源码

2. 加载源文件

CocoaPods执行的下一步就是加载源码。每个.podspec 文件都包含一个源代码的索引,这些索引一般会包裹一个git地址 或者git tag 。它是以commit SHAs 的方式存储在 ~/Library/Caches/CocoaPods 中的。这个路径中文件的创建由Core gem 负责。
CocoaPods将依照podfile.podspec 和缓存文件的信息将源文件下载到Pods目录中。

3. 生成 Pods.xcodeproj

在每次执行pod install 时,如果检测到了改动,CocosPods会利用xcodeproj 的gem组件对Pods.xcodeproj 进行更新。如果该文件不存在,那么就会用默认配置进行生成。否则,将会把以后的配置项加载到内存中。

4. 安装第三方库

当CocosPods往工程中添加一个第三方库时,不仅仅是添加代码这么简单,还会添加很多的内容。由于每个第三方库有不同的target,因此对于每个库都会有几个文件需要添加,每个target都需要

一个包含编译选项的.xcconfig 文件
一个同时包含编译设置和CocoaPods默认配置的私有.xcconfig 文件
一个编译必须的prefix.pch 文件
另一个编译必须的文件 dummy.m

一旦没有pod的target完成了上面的内容,整个pods 的 target 会被创建。这时,在增加了另外几个文件的同时,还会增加另外几个文件。如果源码中包含有资源bundle,将这个bundle添加到程序target的指令将被添加早Pods-Resoutces.sh文件中。还有个名为Pods-environment.h 的文件,文件中包含了一些宏定义,这些宏可以用来检查某个组件是否来自于pod。最后,将生成的两个认可文件,plistmarkdown 这两个文件用于给最终用户差远相关许可信息。

5. 写入至磁盘

知道现在,许多工作都是在内存中进行的。为了让这些成果能够被重复利用,我们需要将所有的结果保存在一个文件中。因此,会有Pods.xcodeproj ,另外两个非常重要的文件是Podfile.lockManifest.lock.

5.1 Podfile.lock

这是CocoaPods创建的最重要的文件之一。它记录了需要被安装的pod的每个已安装的版本。如果你想知道已安装的pod是哪个版本,可以查看这个文件。

在很多资料中,都会将podfile.lock放入版本控制中,这样可以有助于整个团队工程依赖的一致性,然后,在我的团队开发中,这个文件更多的是放入.ignore 文件中的,这是由于,lock文件如果放入版本控制中,那么在pod update 时,会有可能不成功。
团队中的做法是,将Podfile放入版本管理中,而不是podfile.lock

5.2 Mainfest.lock

此为每次运行Mainfest.lock 时创建的Podfile.lock 文件副本。如果你遇见过这样的错误:

沙盒文件与 Podfile.lock 文件不同步 (The sandbox is not in sync with the Podfile.lock)

这就是由于Manifest.lock 文件和 podfile.lock 文件不一致引起的。由于Pods所在的目录并不总是在版本控制之下(事实上最好不要放在版本控制之下),这样可以保证开发整运行app之前都能更新他们的pods,否则app可能会crash,或者在一些不太明显的地方编译失败。

在开发中,有时候不会将Pods文件夹中的内容放入版本控制中,这也是一种增加pull代码速度、保持工程干净的一种方式。

.xcodeproj

它会对 Pods.xcodeproj 文件执行一下 touch 以将其转换成为旧的 ASCII plist 格式的文件。如果没有 xcproj,你的 Pods.xcodeproj 文件将会以 XML 格式的 plist 文件存储,当你用 Xcode 打开它时,它会被改写,并造成大量的文件改动。

结果

运行pod install 命令的最终结果是许多文被添加到你的工程和系统中。此过程只需要几秒钟时间。

不受版本控制的Pods文件夹
如果你的Pods文件夹不受版本控制,那么你需要做一些额外的步骤来保证持续集成的顺利进行。最起码,正如前文说的,podfile 文件要放入版本控制之中。

0 0