[关闭]
@qidiandasheng 2022-08-07T12:53:28.000000Z 字数 4963 阅读 482

Cocoapods核心组件概览()

Cocoapods


Cocoapods依赖结构

我们下载Cocoapods的源码,然后能看到Gemfile文件,通过这个文件我们能看到cocoapods的gem依赖,这其中就包括了Cocoapods的核心组件依赖。

  1. SKIP_UNRELEASED_VERSIONS = false
  2. # Declares a dependency to the git repo of CocoaPods gem. This declaration is
  3. # compatible with the local git repos feature of Bundler.
  4. #
  5. def cp_gem(name, repo_name, branch = 'master', path: false)
  6. return gem name if SKIP_UNRELEASED_VERSIONS
  7. opts = if path
  8. { :path => "../#{repo_name}" }
  9. else
  10. url = "https://github.com/CocoaPods/#{repo_name}.git"
  11. { :git => url, :branch => branch }
  12. end
  13. gem name, opts
  14. end
  15. source 'https://rubygems.org'
  16. gemspec
  17. group :development do
  18. cp_gem 'claide', 'CLAide'
  19. cp_gem 'cocoapods-core', 'Core', '1-11-stable'
  20. cp_gem 'cocoapods-deintegrate', 'cocoapods-deintegrate'
  21. cp_gem 'cocoapods-downloader', 'cocoapods-downloader'
  22. cp_gem 'cocoapods-plugins', 'cocoapods-plugins'
  23. cp_gem 'cocoapods-search', 'cocoapods-search'
  24. cp_gem 'cocoapods-trunk', 'cocoapods-trunk'
  25. cp_gem 'cocoapods-try', 'cocoapods-try'
  26. cp_gem 'molinillo', 'Molinillo'
  27. cp_gem 'nanaimo', 'Nanaimo'
  28. cp_gem 'xcodeproj', 'Xcodeproj'
  29. gem 'cocoapods-dependencies', '~> 1.0.beta.1'
  30. gem 'activesupport', '> 5', '< 6' # Pinned < 6 because 6 requires Ruby 2.5.0
  31. gem 'bacon', :git => 'https://github.com/leahneukirchen/bacon.git'
  32. gem 'mocha', '< 1.5'
  33. gem 'mocha-on-bacon'
  34. gem 'netrc'
  35. gem 'prettybacon'
  36. gem 'typhoeus'
  37. gem 'webmock'
  38. gem 'bigdecimal', '~> 1.3.0'
  39. gem 'public_suffix'
  40. gem 'ruby-graphviz', '< 1.2.5'
  41. # Integration tests
  42. gem 'diffy'
  43. gem 'clintegracon', :git => 'https://github.com/mrackwitz/CLIntegracon.git'
  44. # Code Quality
  45. gem 'inch_by_inch'
  46. gem 'rubocop', '0.50.0'
  47. gem 'simplecov', '< 0.18'
  48. gem 'danger', '~> 5.3'
  49. end
  50. group :debugging do
  51. gem 'cocoapods_debug'
  52. gem 'rb-fsevent'
  53. gem 'kicker'
  54. gem 'awesome_print'
  55. gem 'ruby-prof', :platforms => [:ruby]
  56. end

Cocoapods源码.png-389.3kB

Pod命令入口(CLAide)

我们在命令行里输入pod命令,最先来到的就是CLAide,通过调用 Pod::Command.run(ARGV),实例化了一个 CLAide::Command 对象,开始我们的 CLAide 命令解析阶段

CLAide中最核心的部分就是command.rb里的Command类,我们之后的一些pod命令的起点都是继承自Command。我们在Cocoapods源码下面的command文件夹能看到这些命令,比如Command::Install类对应的命令为pod install

截屏2021-12-07 上午10.54.05.png-420.4kB

其中运行部分就是其中的run函数:

  1. module Pod
  2. class Command
  3. class Install < Command
  4. # ...
  5. def run
  6. # 判断是否存在 Podfile 文件
  7. verify_podfile_exists!
  8. # 从 Config 中获取一个 Instraller 实例
  9. installer = installer_for_config
  10. # 默认是不执行 update
  11. installer.repo_update = repo_update?(:default => false)
  12. installer.update = false
  13. installer.deployment = @deployment
  14. # 忽略工程中的缓存,直接全量编译,默认为false
  15. installer.clean_install = @clean_install
  16. # install 的真正过程
  17. installer.install!
  18. end
  19. end
  20. end
  21. end

配置文件的解析(CocoaPods-Core)

CocoaPods-Core 用于 CocoaPods 中配置文件的解析,包括 Podfile、Podspec以及解析后的依赖锁存文件,如 Podfile.lock 等。

我们先通过入口文件 lib/cocoapods-core.rb 来一窥 Core 项目的主要文件:

  1. module Pod
  2. require 'cocoapods-core/gem_version'
  3. class PlainInformative < StandardError; end
  4. class Informative < PlainInformative; end
  5. require 'pathname'
  6. require 'cocoapods-core/vendor'
  7. # 用于存储 PodSpec 中的版本号
  8. autoload :Version, 'cocoapods-core/version'
  9. # pod 的版本限制
  10. autoload :Requirement, 'cocoapods-core/requirement'
  11. # 配置 Podfile 或 PodSpec 中的 pod 依赖
  12. autoload :Dependency, 'cocoapods-core/dependency'
  13. # 获取 Github 仓库信息
  14. autoload :GitHub, 'cocoapods-core/github'
  15. # 处理 HTTP 请求
  16. autoload :HTTP, 'cocoapods-core/http'
  17. # 记录最终 pod 的依赖信息
  18. autoload :Lockfile, 'cocoapods-core/lockfile'
  19. # 记录 SDK 的名称和 target 版本
  20. autoload :Platform, 'cocoapods-core/platform'
  21. # 对应 Podfile 文件的 class
  22. autoload :Podfile, 'cocoapods-core/podfile'
  23. # 管理 PodSpec 的集合
  24. autoload :Source, 'cocoapods-core/source'
  25. # 管理基于 CDN 来源的 PodSpec 集合
  26. autoload :CDNSource, 'cocoapods-core/cdn_source'
  27. # 管理基于 Trunk 来源的 PodSpec 集合
  28. autoload :TrunkSource, 'cocoapods-core/trunk_source'
  29. # 对应 PodSpec 文件的 class
  30. autoload :Specification, 'cocoapods-core/specification'
  31. # 将 pod 信息转为 .yml 文件,用于 lockfile 的序列化
  32. autoload :YAMLHelper, 'cocoapods-core/yaml_helper'
  33. # 记录 pod 依赖类型,是静态库/动态库
  34. autoload :BuildType, 'cocoapods-core/build_type'
  35. ...
  36. Spec = Specification
  37. end

podfile文件读取

pod install 命令执行后的 verify_podfile_exists!中读取podfile:

  1. def verify_podfile_exists!
  2. unless config.podfile
  3. raise Informative, "No `Podfile' found in the project directory."
  4. end
  5. end

Podfile文件的读取就是config.podfile里触发的,代码在 CocoaPodsconfig.rb 文件中:

  1. def podfile_path_in_dir(dir)
  2. PODFILE_NAMES.each do |filename|
  3. candidate = dir + filename
  4. if candidate.file?
  5. return candidate
  6. end
  7. end
  8. nil
  9. end
  10. def podfile_path
  11. @podfile_path ||= podfile_path_in_dir(installation_root)
  12. end
  13. def podfile
  14. @podfile ||= Podfile.from_file(podfile_path) if podfile_path
  15. end

最后 Core 里的podfile.rbfrom_file函数将依据目录下的 Podfile 文件类型选择调用 from_yaml 或者 from_ruby

  1. def self.from_file(path)
  2. path = Pathname.new(path)
  3. unless path.exist?
  4. raise Informative, "No Podfile exists at path `#{path}`."
  5. end
  6. case path.extname
  7. when '', '.podfile', '.rb'
  8. Podfile.from_ruby(path)
  9. when '.yaml'
  10. Podfile.from_yaml(path)
  11. else
  12. raise Informative, "Unsupported Podfile format `#{path}`."
  13. end
  14. end

guardia1599993134203-782e510d-c084-4b57-98fe-970f5a38cc79.jpeg-144.7kB

Podfile From Ruby 解析

读取到文件之后我们需要对Podfile内容进行解析,这里主要看Core下面的podfile.rb文件下的from_ruby函数:

  1. def self.from_ruby(path, contents = nil)
  2. contents ||= File.open(path, 'r:utf-8', &:read)
  3. ...
  4. # 生成podfile对象,eval执行自己定义的dsl语句
  5. podfile = Podfile.new(path) do
  6. # rubocop:disable Lint/RescueException
  7. begin
  8. # rubocop:disable Security/Eval
  9. eval(contents, nil, path.to_s)
  10. # rubocop:enable Security/Eval
  11. rescue Exception => e
  12. message = "Invalid `#{path.basename}` file: #{e.message}"
  13. raise DSLError.new(message, path, e, contents)
  14. end
  15. # rubocop:enable Lint/RescueException
  16. end
  17. podfile
  18. end

下载(cocoapods-downloader)

Cocoapods-Downloader 是用于下载源码的小工具,它支持各种类型的版本管理工具,包括 HTTP / SVN / Git / Mercurial。它可以提供 tags、commites,revisions,branches 以及 zips 文件的下载和解压缩操作。

参考

整体把握 CocoaPods 核心组件
Podfile 的解析逻辑

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注