美文网首页
cocoapods源码5.2 - command/init.rb

cocoapods源码5.2 - command/init.rb

作者: xiongzenghui | 来源:发表于2018-08-12 14:02 被阅读17次

    1、CocoaPods/lib/cocoapods/command/init.rb

    require 'xcodeproj'
    require 'active_support/core_ext/string/strip'
    
    module Pod
      class Command
        # init child command => pod init
        class Init < Command
          # 1、command 基本描述
          self.summary = 'Generate a Podfile for the current directory'
          self.description = <<-DESC
            Creates a Podfile for the current directory if none currently exists. If
            an `XCODEPROJ` project file is specified or if there is only a single
            project file in the current directory, targets will be automatically
            generated based on targets defined in the project.
    
            It is possible to specify a list of dependencies which will be used by
            the template in the `Podfile.default` (normal targets) `Podfile.test`
            (test targets) files which should be stored in the
            `~/.cocoapods/templates` folder.
          DESC
    
          # 2、参数 XCODEPROJ 指定为 xxx.xcodeproj 文件所在的路径
          self.arguments = [
            CLAide::Argument.new('XCODEPROJ', :false),
          ]
          
          # 3、init
          def initialize(argv)
            #puts "initialize():"
            #puts "Pathname.pwd = #{Pathname.pwd}"
            #puts "argv = #{argv}"
            
            # 3.1、获取 Podfile 文件的路径
            @podfile_path = Pathname.pwd + 'Podfile'
            #puts "@podfile_path = #{@podfile_path}"
    
            # 3.2 
            @project_path = argv.shift_argument
            #puts "@project_path = #{@project_path}"
    
            # 3.3、遍历获取所有的 xxx.xcodeproj
            @project_paths = Pathname.pwd.children.select { |pn| pn.extname == '.xcodeproj' }
            #puts "@project_paths = #{@project_paths}"
    
            # 3.4、
            super
          end
    
          # 4、命令行参数校验
          def validate!
            super
            
            # 1、config.podfile_path_in_dir(Pathname.pwd) != nil 时,抛出异常提示:【Podfile已经存在】
            # raise Informative, 'Existing Podfile found in directory' unless config.podfile_path_in_dir(Pathname.pwd).nil?
            
            # 2、找到合法的 xxx.xcodeproj 文件路径
            if @project_path
              help! "Xcode project at #{@project_path} does not exist" unless File.exist? @project_path
              project_path = @project_path
            else
              raise Informative, 'No Xcode project found, please specify one' unless @project_paths.length > 0
              raise Informative, 'Multiple Xcode projects found, please specify one' unless @project_paths.length == 1
              project_path = @project_paths.first
            end
    
            # 3、调用Xcodeproj打开xxx.xcodeproj
            @xcode_project = Xcodeproj::Project.open(project_path)
          end
    
          # 5、
          def run
            # 打开Podfile文件,输入预先的模板内容
            @podfile_path.open('w') { |f| 
              f << podfile_template(@xcode_project)
            }
          end
    
          # ------------------------------- private ------------------------------- 
          private
    
          # 1、创建Podfile文件内容模板
          # @param  [Xcodeproj::Project] project
          #         The xcode project to generate a podfile for.
          #
          # @return [String] the text of the Podfile for the provided project
          #
          def podfile_template(project)
            # 1.1、
            podfile = ''
    
            # 1.2、如果存在 @project_path ,则拼接 "project ..... "
            podfile << "project '#{@project_path}'\n\n" if @project_path
    
            # 1.3、platform :ios, '9.0'
            podfile << <<-PLATFORM.strip_heredoc
              # Uncomment the next line to define a global platform for your project
              # platform :ios, '9.0'
            PLATFORM
    
            # 1.4、遍历xcode工程所有的target,分为test与app两种类型的target
            test_targets, app_targets = project
                                        .native_targets()
                                        .sort_by() { |t| t.name.downcase }
                                        .partition(&:test_target_type?)
            # puts test_targets
            # puts app_targets
    
            # 1.5、app target + test app target
            app_targets.each do |app_target|
              # app => test_app 
              test_targets_for_app = test_targets.select do |target|
                target.name.downcase.start_with?(app_target.name.downcase)
              end
    
              # target_module([app], [test_app])
              podfile << target_module(app_target, test_targets_for_app)
            end
            
            # 1.6 return 
            podfile
          end
    
          # 2、组织 pod target 内容
          def target_module(app, tests)
            # 2.1、app.name 中的【'】单引号 =转义=>【\\'】
            target_module = "\ntarget '#{app.name.gsub(/'/, "\\\\\'")}' do\n"
              
            # 2.2、判断是否构建swift代码,如果是,则添加【use_frameworks!】
            target_module << if app.resolved_build_setting('SWIFT_OPTIMIZATION_LEVEL').values.any?
              <<-RUBY
              # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
              use_frameworks!
              RUBY
            else
              <<-RUBY
              # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
              # use_frameworks!
    
             RUBY
            end
    
            # 2.3、添加 "# Pods for App"
            # => config.default_podfile_path
            # => puts config.default_podfile_path
            # => /Users/xiongzenghui/.cocoapods/templates/Podfile.default
            # => 默认 .cocoapods 目录下,不存在【templates目录】,也就不存在【Podfile.default】
            # => 可通过手动添加【Podfile.default】,定制Podfile的模板内容
            target_module << template_contents(config.default_podfile_path, '  ', "Pods for #{app.name}\n")
            
            # 到此为止,构造Podfile文件内容如下:
            # Uncomment the next line to define a global platform for your project
            # platform :ios, '9.0'
            # 
            # target 'App' do
            #   # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
            #   # use_frameworks!
            #   # Pods for App
            # 
            # end
    
            # 2.4、继续构造 test target list
            # target test_app do 
            #   inherit! :search_paths
            #   # Pods for testing
            # 
            # end
            tests.each do |test|
              target_module << "\n  target '#{test.name.gsub(/'/, "\\\\\'")}' do\n"
              target_module << "    inherit! :search_paths\n"
              target_module << template_contents(config.default_test_podfile_path, '    ', 'Pods for testing')
              target_module << "\n  end\n"
            end
    
            # 2.5 对应【app target】末尾的 "end"
            target_module << "\nend\n"
          end
    
          # @param  [[Xcodeproj::PBXTarget]] targets
          #         An array which always has a target as its first item
          #         and may optionally contain a second target as its test target
          #
          # @return [String] the text for the target module
          #
          def template_contents(path, prefix, fallback)
            if path.exist?
              # String#chomp() => 去掉字符串末尾的\n或\r
              path.read.chomp.lines.map { |line| 
                "#{prefix}#{line}" # 每一行内容为:[prefix][Podfile.default文件每一行的内容]
              }.join("\n") # Podfile.default文件末尾追加\n换行
            else
              "#{prefix}# #{fallback}"
            end
          end
        end
      end
    end
    

    2、pod init

    ➜  App ls -l
    total 0
    drwxr-xr-x  28 xiongzenghui  staff  896  7 29 11:24 App
    drwxr-xr-x@  5 xiongzenghui  staff  160  7 24 16:50 App.xcodeproj
    ➜  App 
    
    ➜  App pod init
    
    ➜  App cat Podfile
    # Uncomment the next line to define a global platform for your project
    # platform :ios, '9.0'
    
    target 'App' do
              # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
              # use_frameworks!
    
      # Pods for App
    
    end
    ➜  App
    

    3、pod init XCODEPROJ

    ➜  App tree
    .
    └── path1
        └── path2
            ├── App
            ├── App.xcodeproj
            └── Podfile
    
    ➜  App
    
    ➜  App pod init ./path1/path2/App.xcodeproj
    
    ➜  App cat Podfile
    project './path1/path2/App.xcodeproj'
    
    # Uncomment the next line to define a global platform for your project
    # platform :ios, '9.0'
    
    target 'App' do
              # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
              # use_frameworks!
    
      # Pods for App
    
    end
    ➜  App
    

    比上面的pod init生成的podfile开始位置多一行project:

    project './path1/path2/App.xcodeproj'
    

    相关文章

      网友评论

          本文标题:cocoapods源码5.2 - command/init.rb

          本文链接:https://www.haomeiwen.com/subject/vjesbftx.html