pod lib create 原理

2,299 阅读4分钟

Create by xinyuan 2020/06/12

  • 前言: 我们经常会创建自己的私有库,然而我们经常会使用一个命令行就是 pod lib create ***,这边文章就是简单的介绍他部分源码。

一、步骤简单了解

  • 1、当我们在终端输入 pod lib create ***后,会出现这样的界面
    终端内容
    终端内容
    一般情况我们就会噼里啪啦的往下选择,生成一个我们想要的文件,这是我们一般的常规操作,而此刻我们暂停下来可以看看其提示,我们发现他是执行了一条克隆语句。对的他只是把远端的代码下载下来,然后在进行一系列的操作。
Cloning`https://github.com/CocoaPods/pod-template.git` into `Demo`
  • 2、文件目录结构

    文件目录
    文件目录
    从这个结构上面看,其实最重要的就是在setup里面的这些ruby脚本。只是因为他区分处理了iOS、swift、Mac的,所以脚本才会有这么多。

  • 3、demo工程

    demo工程
    demo工程
    平时的那些就是通过已经现有的demo工程利用脚本进行了简单修改

二、部分代码展示

  • 1、TemplateConfigurator.rb
# 这里算是一个主要的方法了,主要在这里做了语言上的区分以及采用哪个demo的方法。MessageBank.rb这个文件主要是进行一些在终端打印的提示处理类
def run
      @message_bank.welcome_message

      platform = self.ask_with_answers("What platform do you want to use?", ["iOS", "macOS"]).to_sym
	  #这里开始区分语言,因为语言不同,代码不同所以进行调用的脚本也是不同的
      case platform
        when :macos
          ConfigureMacOSSwift.perform(configurator: self)
        when :ios
          framework = self.ask_with_answers("What language do you want to use?", ["Swift", "ObjC"]).to_sym
          case framework
            when :swift
              ConfigureSwift.perform(configurator: self)
			  #假设我们这边进行了oc版本的选择,然后他开始执行ConfigureIOS下的perform方法进行处理
            when :objc
              ConfigureIOS.perform(configurator: self)
          end
      end
	  ....
    end
  • 2、ConfigureiOS.rb
module Pod

  class ConfigureIOS
    attr_reader :configurator

    def self.perform(options)
      new(options).perform
    end

    def initialize(options)
      @configurator = options.fetch(:configurator)
    end

    def perform
	# 这里是选择一些选项,按照我们pod lib create 走下去的话,这些问题都会在命令行进行展示的
      keep_demo = configurator.ask_with_answers("Would you like to include a demo application with your library", ["Yes", "No"]).to_sym

      framework = configurator.ask_with_answers("Which testing frameworks will you use", ["Specta", "Kiwi", "None"]).to_sym
      case framework
        when :specta
          configurator.add_pod_to_podfile "Specta"
          configurator.add_pod_to_podfile "Expecta"

          configurator.add_line_to_pch "@import Specta;"
          configurator.add_line_to_pch "@import Expecta;"

          configurator.set_test_framework("specta", "m", "ios")

        when :kiwi
          configurator.add_pod_to_podfile "Kiwi"
          configurator.add_line_to_pch "@import Kiwi;"
          configurator.set_test_framework("kiwi", "m", "ios")

        when :none
          configurator.set_test_framework("xctest", "m", "ios")
      end

      snapshots = configurator.ask_with_answers("Would you like to do view based testing", ["Yes", "No"]).to_sym
      case snapshots
        when :yes
          configurator.add_pod_to_podfile "FBSnapshotTestCase"
          configurator.add_line_to_pch "@import FBSnapshotTestCase;"

          if keep_demo == :no
              puts " Putting demo application back in, you cannot do view tests without a host application."
              keep_demo = :yes
          end

          if framework == :specta
              configurator.add_pod_to_podfile "Expecta+Snapshots"
              configurator.add_line_to_pch "@import Expecta_Snapshots;"
          end
      end

      prefix = nil

      loop do
        prefix = configurator.ask("What is your class prefix").upcase

        if prefix.include?(' ')
          puts 'Your class prefix cannot contain spaces.'.red
        else
          break
        end
      end
	  
	  #这里需要利用到ProjectManipulator.rb文件进行demo工程上的修改,这里主要是讲部分信息传了过去,然后进行run方便的调用。
      Pod::ProjectManipulator.new({
        :configurator => @configurator,
        :xcodeproj_path => "templates/ios/Example/PROJECT.xcodeproj",
        :platform => :ios,
        :remove_demo_project => (keep_demo == :no),
        :prefix => prefix
      }).run

      # There has to be a single file in the Classes dir
      # or a framework won't be created, which is now default
      `touch Pod/Classes/ReplaceMe.m`

      `mv ./templates/ios/* ./`

      # remove podspec for osx
      `rm ./NAME-osx.podspec`
    end
  end

end

  • 3、ProjectManipulator.rb
#这里主要用到了xcodeproj这个组件,进行对xcode文件的修改,这里应该才是精髓,这里是涉及到对xcodeproj的使用。
def run
      @string_replacements = {
        "PROJECT_OWNER" => @configurator.user_name,
        "TODAYS_DATE" => @configurator.date,
        "TODAYS_YEAR" => @configurator.year,
        "PROJECT" => @configurator.pod_name,
        "CPD" => @prefix
      }
	  #这个方法是拿到了项目的文件,然后进行文件内容的读取替换
      replace_internal_project_settings

      @project = Xcodeproj::Project.open(@xcodeproj_path)
	  #这里是添加.podspec、README.md、LICENSE文件
      add_podspec_metadata
	  #这里是移除了demo工程以及重写Podfile文件
      remove_demo_project if @remove_demo_target
      @project.save
	  #这里是进行一些重命名的方法,这里他写的不太好的地方就是是固定类去改变了,例如,可以看到下面是demo中CPDAppDelegate的类名,如果这里可以改一下还是会好一点
	  # unless @remove_demo_target
      #   # change app file prefixes
      #   ["CPDAppDelegate.h", "CPDAppDelegate.m", "CPDViewController.h", "CPDViewController.m"].each do |file|
      #     before = project_folder + "/PROJECT/" + file
      #     next unless File.exists? before

      #     after = project_folder + "/PROJECT/" + file.gsub("CPD", prefix)
      #     File.rename before, after
      #   end

      #   # rename project related files
      #   ["PROJECT-Info.plist", "PROJECT-Prefix.pch", "PROJECT.entitlements"].each do |file|
      #     before = project_folder + "/PROJECT/" + file
      #     next unless File.exists? before

      #     after = project_folder + "/PROJECT/" + file.gsub("PROJECT", @configurator.pod_name)
      #     File.rename before, after
      #   end
      # end
      rename_files
	  #文件夹的命名修改
      rename_project_folder
    end
	#这里部分细节代码可以尝试跑一下看看实现
  • 4、TemplateConfigurator.rb
def run
      ...
	  #工程进行处理完之后,这里会回到TemplateConfigurator类中run一些公共的方法
	  
	  # POD_LICENSE、POD_README.md、NAME.podspec、.travis.yml 配置修改,例如用户名时间等
      replace_variables_in_files
	  #移除掉一些克隆下来之后没有用的文件,"./**/.gitkeep", "configure", "_CONFIGURE.rb", "README.md", "LICENSE", "templates", "setup", "CODE_OF_CONDUCT.md"
      clean_template_files
	  # 更换README.md、LICENSE以及新的.podspec
      rename_template_files
      add_pods_to_podfile
      customise_prefix
      rename_classes_folder
      ensure_carthage_compatibility
      reinitialize_git_repo
      run_pod_install

      @message_bank.farewell_message
    end
	#这里部分细节代码可以尝试跑一下看看实现

三、结束语

按照cocoapods这一份demo,我们应该也可以实现一份脚本,实现通过脚本通过部分配置然后立刻得出一份具有基础配置的项目工程。这里主要修改的应该是ProjectManipulator.rb文件,由于cocoapods用的demo工程已经是比较老版本的了,所以在替换过程中应该要注意下部分变量是否还存在,例如现在看到的在ProjectManipulator.rbrename_files方法的scheme就是目前新的项目没有的。还有一点要注意的是,他是对就的demo进行修改,而不是新创建。

scheme_path = project_folder + "/PROJECT.xcodeproj/xcshareddata/xcschemes/"