设为首页 加入收藏

TOP

CocoaPods 在iOS开发中养活了这么多项目,它到底是个啥?(一)
2023-09-23 15:43:32 】 浏览:598
Tags:CocoaPods iOS 项目

对于iOS开发者而言,CocoaPods并不陌生,通过pod相关的命令操作,就可以很方便的将项目中用到的三方依赖库资源集成到项目环境中,大大的提升了开发的效率。CocoaPods作为iOS项目的包管理工具,它在命令行背后做了什么操作?而又是通过什么样的方式将命令指令声明出来供我们使用的?这些实现的背后底层逻辑是什么?都是本文想要探讨挖掘的。

一、Ruby是如何让系统能够识别已经安装的Pods指令的?

我们都知道在使用CocoaPods管理项目三方库之前,需要安装Ruby环境,同时基于Ruby的包管理工具gem再去安装CocoaPods。通过安装过程可以看出来,CocoaPods本质就是Ruby的一个gem包。而安装Cocoapods的时候,使用了以下的安装命令:

sudo gem install cocoapods

安装完成之后,就可以使用基于Cocoapods的 pod xxxx 相关命令了。gem install xxx 到底做了什么也能让 Terminal 正常的识别 pod 命令?gem的工作原理又是什么?了解这些之前,可以先看一下 RubyGems 的环境配置,通过以下的命令:

gem environment

通过以上的命令,可以看到Ruby的版本信息,RubyGem的版本,以及gems包安装的路径,进入安装路径 /Library/Ruby/Gems/2.6.0 后,我们能看到当前的Ruby环境下所安装的扩展包,这里能看到我们熟悉的Cocoapods相关的功能包。除了安装包路径之外,还有一个 EXECUTABLE DIRECTORY 执行目录 /usr/local/bin,可以看到拥有可执行权限的pod文件,如下:

预览一下pod文件内容:

#!/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'cocoapods' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'rubygems'

version = ">= 0.a"

str = ARGV.first
if str
  str = str.b[/\A_(.*)_\z/, 1]
  if str and Gem::Version.correct?(str)
    version = str
    ARGV.shift
  end
end

if Gem.respond_to?(:activate_bin_path)
load Gem.activate_bin_path('cocoapods', 'pod', version)
else
gem "cocoapods", version
load Gem.bin_path("cocoapods", "pod", version)
end

根据文件注释内容可以发现,当前的可执行文件是 RubyGems 在安装 Cocoapods 的时候自动生成的,同时会将当前的执行文件放到系统的环境变量路径中,也即存放到了 /usr/local/bin 中了,这也就解释了为什么我们通过gem安装cocoapods之后,就立马能够识别pod可执行环境了。

虽然能够识别pod可执行文件,但是具体的命令参数是如何进行识别与实现呢?继续看以上的pod的文件源码,会发现最终都指向了 Gemactivate_bin_pathbin_path 方法,为了搞清楚Gem到底做了什么,在官方的RubyGems源码的rubygems.rb 文件中找到了两个方法的相关定义与实现,摘取了主要的几个方法实现,内容如下:

  ##
  # Find the full path to the executable for gem +name+.  If the +exec_name+
  # is not given, an exception will be raised, otherwise the
  # specified executable's path is returned.  +requirements+ allows
  # you to specify specific gem versions.
  #
  # A side effect of this method is that it will activate the gem that
  # contains the executable.
  #
  # This method should *only* be used in bin stub files.
  def self.activate_bin_path(name, exec_name = nil, *requirements) # :nodoc:
    spec = find_spec_for_exe name, exec_name, requirements
    Gem::LOADED_SPECS_MUTEX.synchronize do
      spec.activate
      finish_resolve
    end
    spec.bin_file exec_name
  end

  def self.find_spec_for_exe(name, exec_name, requirements)
	#如果没有提供可执行文件的名称,则抛出异常
    raise ArgumentError, "you must supply exec_name" unless exec_name
    # 创建一个Dependency对象
    dep = Gem::Dependency.new name, requirements
    # 获取已经加载的gem
    loaded = Gem.loaded_specs[name]
    # 存在直接返回
    return loaded if loaded && dep.matches_spec?(loaded)
    # 查找复合条件的gem配置
    specs = dep.matching_specs(true)
    specs = specs.find_all do |spec|
	  # 匹配exec_name 执行名字,如果匹配结束查找
      spec.executables.include? exec_name
    end if exec_name
	# 如果没有找到符合条件的gem,抛出异常
    unless spec = specs.first
      msg = "can't find gem #{dep} with executable #{exec_name}"
      raise Gem::GemNotFoundException, msg
    end
	#返回结果
    spec
  end
  private_class_method :find_spec_for_exe

  ##
  # Find the full path to the executable for gem +name+.  If the +exec_name+
  # is not given, an exception will be raised, otherwise the
  # specified executable's path is returned.  +requirements+ allows
  # you to speci
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/11/11
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇iOS16新特性:实时活动-在锁屏界.. 下一篇iOS代码加固与保护方法详解 - 提..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目