打开工程的Podfile文件打算学习一下,去除一些cocoapods的版本校验,第一行便是install! 'cocoapods', :deterministic_uuids => false;
为了了解install!
函数,我debug cocoapods的源码,发现pod Insall
命令的的入口是pod文件,下面我们看一下具体的代码,从下面代码我们可以看出,pod命令最后调用Command.rb中的run
函数,在该函数中通过super
函数调到CLAide::Command
,来解析install命令。
#!/usr/bin/env ruby
#1、目的是检测当前的编码是否是UTF-8,如果不是将错误信息输出到stder,用于在命令行中给出提示。
#Encoding.default_external是encoding类的函数返回默认的外部编码
if Encoding.default_external != Encoding::UTF_8
if ARGV.include? '--no-ansi'
STDERR.puts <<-DOC
WARNING: CocoaPods requires your terminal to be using UTF-8 encoding.
Consider adding the following to ~/.profile:
export LANG=en_US.UTF-8
DOC
else
STDERR.puts <<-DOC
\e[33mWARNING: CocoaPods requires your terminal to be using UTF-8 encoding.
Consider adding the following to ~/.profile:
export LANG=en_US.UTF-8
\e[0m
DOC
end
end
#下面逻辑是根据不同的条件从不同的地方导入cocoapods库
if $PROGRAM_NAME == __FILE__ && !ENV['COCOAPODS_NO_BUNDLER']
# 找到 Gemfile 文件,添加到ENV环境变量map中
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
# 导入系统rb库
require 'rubygems'
require 'bundler/setup'
# 将cocoapods源码根目录下的lib目录,添加到$LOAD_PATH记录的加载rb文件的搜索目录集合中
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
elsif ENV['COCOAPODS_NO_BUNDLER']
require 'rubygems'
# 从 https://rubygems.org 共有仓库,下载cocoapods库
gem 'cocoapods'
end
STDOUT.sync = true if ENV['CP_STDOUT_SYNC'] == 'TRUE'
# 导入 cocoapods.rb
require 'cocoapods'
#根据执行pod命令时是否带有COCOAPODS_PROFILE选项,做不同操作
if profile_filename = ENV['COCOAPODS_PROFILE']
#如果有导入'ruby-prof',分析rb代码执行效率
require 'ruby-prof'
reporter =
case (profile_extname = File.extname(profile_filename))
when '.txt'
RubyProf::FlatPrinterWithLineNumbers
when '.html'
RubyProf::GraphHtmlPrinter
when '.callgrind'
RubyProf::CallTreePrinter
else
raise "Unknown profiler format indicated by extension: #{profile_extname}"
end
File.open(profile_filename, 'w') do |io|
#调用 Pod::Command.run(ARGV) 解析命令行参数
reporter.new(RubyProf.profile { Pod::Command.run(ARGV) }).print(io)
end
else
#没有COCOAPODS_PROFILE选项直接 Pod::Command.run(ARGV) 解析命令行参数
Pod::Command.run(ARGV)
end
知识点
1、rubygems是什么
RubyGems 是一个统一安装、管理 Ruby 类库、程序的 Ruby 标准工具。在 RubyGems 中,每个单独的库称为 gem。通过 RubyGems,我们可以搜索 gem,显示 gem 相关的信息,安装 / 卸载 gem,升级旧版本的 gem,以及查看 gem 的安装进度一览表,等等。
2、bundle是什么
Bundler 能够跟踪并安装所需的特定版本的 gem,以此来为 Ruby 项目提供一致的运行环境。
Bundler 管理 Ruby 依赖的,能够跟踪并安装所需的特定版本的 gem,以此来为 Ruby 项目提供一致的运行环境,具体可以浏览官网
具体参考这篇文章
3、ENV[‘COCOAPODS_NO_BUNDLER’]
ENV[‘COCOAPODS_NO_BUNDLER’]定义在sandbox-pod.rb中,sandbox-pod.rb文件确保了CocoaPods对沙盒的控制权,沙盒中的文件夹提供了CocoaPods安装需要使用的Pods projects、支持文件以及相关资源。
# Ensure the `pod` bin doesn’t think it needs to use Bundler.(确保 `pod` bin 认为它不需要使用 Bundler)
ENV['COCOAPODS_NO_BUNDLER'] = '1'
一般沙盒中的文件结构如下
Pods
|
+-- Headers
| +-- Private
| | +-- [Pod Name]
| +-- Public
| +-- [Pod Name]
|
+-- Local Podspecs
| +-- External Sources
| +-- Normal Sources
|
+-- Target Support Files
| +-- [Target Name]
| +-- Pods-acknowledgements.markdown
| +-- Pods-acknowledgements.plist
| +-- Pods-dummy.m
| +-- Pods-prefix.pch
| +-- Pods.xcconfig
|
+-- [Pod Name]
|
+-- Manifest.lock
|
+-- Pods.xcodeproj
(if installation option 'generate_multiple_pod_projects' is enabled)
|
+-- PodTarget1.xcodeproj
|
...
|
+-- PodTargetN.xcodeproj
3、Pod::Command.run(ARGV)
Pod::Command.run(ARGV)
函数内部调用父类CLAide的run函数,父类run
函数如下,解析命令之后,调用到install.rb中的install!
函数
def self.run(argv = [])
plugin_prefixes.each do |plugin_prefix|
PluginManager.load_plugins(plugin_prefix)
end
#将argv强转位ARGV对象
argv = ARGV.coerce(argv)
#解析 argument 生成对应的 command instance,将 run 的类方法转换为实例方法,具体看下面self.parse函数
command = parse(argv)
ANSI.disabled = !command.ansi_output?
unless command.handle_root_options(argv)
command.validate!
command.run
end
rescue Object => exception
handle_exception(command, exception)
end
def self.parse(argv)
# 通过解析 argv 获取到与 cmd 名称
argv = ARGV.coerce(argv)
cmd = argv.arguments.first
# 如果 cmd 对应的 Command 类,则更新 argv,继续解析命令
if cmd && subcommand = find_subcommand(cmd)
argv.shift_argument
subcommand.parse(argv)
# 如果 cmd 为抽象命令且指定了默认命令,则返回默认命令继续解析参数
elsif abstract_command? && default_subcommand
load_default_subcommand(argv)
else
# 初始化真正的 cmd 实例
new(argv)
end
end