iOS - CocoaPods原理

本文已同步至掘金iOS - CocoaPods原理

CocoaPods将所有的依赖库都放到Pods项目中,让主项目依赖Pods项目,这样源码管理工作都从主项目迁移到了Pods项目中

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

核心组件

CocoaPods是用 Ruby 写的,并由若干个 Ruby 包 (gems) 构成的。在解析整合过程中,最重要的几个 gems 分别是: CocoaPods/CocoaPods, CocoaPods/Core, 和 CocoaPods/Xcodeproj (是的,CocoaPods 是一个依赖管理工具 -- 利用依赖管理进行构建的!)。CocoaPods 是一个 objc 的依赖管理工具,而其本身是利用 ruby 的依赖管理 gem 进行构建的.

  • CocoaPods/CocoaPod
    这是一个面向用户的组件,每当执行一个pod命令时,这个组件都将被激活。该组件包括了所有使用CocoaPods涉及的功能,并且还能通过调用所有其他的gems来执行任务
  • CocoaPods/Core
    Core组件提供支持与CocoaPods相关文件的处理,文件主要是Podfile和podspecs
  • Podfile
    Podfile 是一个文件,用于定义项目所需要使用的第三方库.
  • Podspec
    .podspec 也是一个文件,该文件描述了一个库是怎样被添加到工程中的。它支持的功能有:列出源文件、framework、编译选项和某个库所需要的依赖等.
  • CocoaPods/Xcodeproj
    这个 gem 组件负责所有工程文件的整合。它能够对创建并修改 .xcodeproj 和 .xcworkspace 文件。它也可以作为单独的一个 gem 包使用。如果你想要写一个脚本来方便的修改工程文件,那么可以使用这个 gem

首先我们cd到~/.cocoapods/repos/master/Specs路径下,选择其中一个第三方库,查看其AFNetwork.podspec.json文件(以AFNetwork为例):

{
  "name": "AFNetwork",
  "version": "0.1.0",
  "summary": "Simple request manager about AFNetworking",
  "description": "TODO: Add long description of the pod here.",
  "homepage": "https://github.com/lingyfh/AFNetwork",
  "license": {
    "type": "MIT",
    "file": "LICENSE"
  },
  "authors": {
    "lingyfh": "[email protected]"
  },
  "source": {
    "git": "https://github.com/lingyfh/AFNetwork.git",
    "tag": "0.1.0"
  },
  "platforms": {
    "ios": "8.0"
  },
  "public_header_files": [
    "AFNetwork/*.h",
    "AFNetwork/**/*.h"
  ],
  "source_files": "AFNetwork/Classes/**/*",
  "dependencies": {
    "AFNetworking": [
      "~> 3.0"
    ]
  }
}

可以看到这里包含了所有三方看的信息,包括名字、协议、描述、Github地址、支持平台等

pod install的过程

通常我们在Podfile文件中新增引入第三方库的代码后,执行pod install, 对应的第三方库就安装在Pods项目中了,pod install 这一过程发生了什么呢,我们这个命令后边加上 --verbose, 可以看到如下内容:

xxx@xxxdeMacBook-Pro CocoaPodsDemo % pod install --verbose
  Preparing

Analyzing dependencies

Inspecting targets to integrate
  Using `ARCHS` setting to build architectures of target
  `Pods-defaults-CocoaPodsDemo `: (``)

Finding Podfile changes
  - AFNetworking

Resolving dependencies of `Podfile`
  CDN: trunk Relative path: CocoaPods-version.yml exists! Returning local
  because checking is only perfomed in repo update

Comparing resolved specification to the sandbox manifest
  - AFNetworking

Downloading dependencies

-> Using AFNetworking (3.2.1)
  - Running pre install hooks

Generating Pods project
  - Creating Pods project
  - Installing files into Pods project
    - Adding source files
    - Adding frameworks
    - Adding libraries
    - Adding resources
    - Linking headers
  - Installing Pod Targets
    - Installing target `AFNetworking` iOS 7.0
      - Generating dummy source at `Pods/Target Support
      Files/AFNetworking/AFNetworking-dummy.m`
  - Generating deterministic UUIDs
  - Stabilizing target UUIDs
  - Running post install hooks
    - Podfile
  - Writing Xcode project file to `Pods/Pods.xcodeproj`
  Cleaning up sandbox directory

Integrating client project

Integrating target `Pods-defaults-CocoaPodsDemo ` (`CocoaPodsDemo.xcodeproj` project)
  - Running post integrate hooks
  - Writing Lockfile in `Podfile.lock`
  - Writing Manifest in `Pods/Manifest.lock`
  CDN: trunk Relative path: CocoaPods-version.yml exists! Returning local
  because checking is only perfomed in repo update

-> Pod installation complete! There are 1 dependencies from the Podfile and 1 total pods installed.

分析过程:

  • 读取Podfile文件,分析有哪些第三方依赖库及对应的版本
  • 加载源文件,每个xxx.podspec.json文件都包含一个源代码的索引,这些索引包含一个Git地址和Git tag,它们以commit SHAs的方式存在在~/Library/Caches/CocoaPods中,这个路径中文件的创建是由Core gem负责的,CocoaPods将依照Podfile、.podspec和缓存文件的信息将源文件下载到pods目录中
  • 生成Pods.xcodeproj,每次pod install指向,如果检测到改动时,CocoaPods会利用Xcodeproj gem组件对Pods.xcodeproj进行更新,该文件如果不存在,则用默认配置生成,否则会将已有的配置项加载至内存中
  • 安装第三方库,当CocoaPods往工程中添加一个三方库时,不只是添加代码这么简单,还会添加很多内容,由于每个第三方库有不同的Target,因此对于每个库,都会有几个文件需要添加,每个target都需要:
    • 一个包含编译选项的.xcconfig文件
    • 一个同时包含编译设置和CocoaPods默认配置的私有.xcconfig文件
    • 一个编译所必须的prefix.pch文件
    • 另一个编译必须的文件dummy.m

以AFNetworking为例:


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

  • 写入磁盘,直到现在,许多工作都是在内存中进行的。为了让这些成果能被重复利用,我们需要将所有的结果保存到一个文件夹中,所以Pods.xcodeproj文件被写入磁盘,另外两个非常重要的文件:Podfile.lock和Manifest.lock都将被写入磁盘
    • Podfile.lock,这是CocoaPods创建的最重要的文件之一,它记录了需要被安装的pod的每个已安装的版本。如果你想知道已安装的pod是哪个版本,可以查看这个文件,推荐将Podfile.lock文件加入打版本控制中,这有助于整个团队的一致性
    • Mainfest.loc 这是每次运行pod install命令时创建的Podfile.lock文件的副本,如果你遇到过这样的错误:沙盒文件与Podfile.lock文件不同步(The sandbox is not in sync with the Podfile.lock), 这是因为Manifest.lock文件和Podfile.lock文件不一致所引起。由于Pods所在的目录并不总在版本控制之下,这样可以保证开发者运行app之前都能更新他们的pods,否则app可能会crash,或者在一些地方编译失败
    • xcproj,如果你已经安装我们的建议在系统上安装了xcproj,它会对Pods.xcodeproj文件执行一下touch以将其转换成为旧的ASCII plist格式的文件.为什么要这么做呢?虽然在很久以前就不被其他软件支持了,但是xcode仍然依赖于这种格式。如果没有xcproj,你的Pods.xcodeproj文件将会以XML格式的plist文件存储,当你用Xcode打开它时,它会被改写,并造成大量的文件改动

参考:
CocoaPods 都做了什么?
cocoapods系列教程---原理篇

你可能感兴趣的:(iOS - CocoaPods原理)