iOS工程04组件二进制

483 阅读3分钟

上一章讲了Xcode内置工具及pods调试。

一、Xcode组件二进制

介绍

  1. Carthage:引入的库需要将Xcode工程文件配置清楚,Carthage会将其打包成xcframework(默认动态,默认组件二进制),同时需要手动copy-frameworks。如果需要静态,可以通过控制工程文件的framework类型实现。Carthage每个阶段都可以手动控制,对工程化的理解要求高。(Swift编写,功能清晰,方便串联)
  2. Cocoapods:属于简单式,只要熟悉Cocoapods内置的Podfile/Podspec内置的DSL,就能上手,不用考虑太多。所引入的库都是按照Cocoapods标准制作,会重新生成工程配置文件,而且需通过验证,使用成本极小。(用的多,Ruby编写,需要先生成工程文件,自己控制编译)

1、组件化

原理图1. image.png 原理图2. image.png

carthage update
brew install carthage //安装carthage
carthage version //查看版本
pod plugins --help //  查看插件命令
bundle gem cocopods-cat-bin

然后用VScode打开cocopods-cat-bin:

编写version.rb 命令:
module CatBin
      VERSION = "0.1.0"
end


修改cocopods-cat-bin.gemspec
require File.expand_path('../lib/cocoapods-cat-bin/version',__FILE__) 引入version
spec.executables   = %w{ pod sandbox-pod } //修改增加 可执行在终端命令

  spec.executables   = %w[ny_bin]
  #spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
  spec.require_paths = ["lib"]

image.png 然后创建launch.json调试文件,在进行配置:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug ny bin",
            "type": "Ruby",
            "request": "launch",
            "debuggerPort": "1236",
            "program": "${workspaceRoot}/main.rb",
            "args": [

            ]
        }
    ]
}

报错1: image.png 解决配置:

  spec.summary       = "bin gen tool"
  spec.description   = "bin gen tool"
  spec.homepage      = "https://github.com/CocoaPods/CocoaPods"

运行成功: image.png 现在基本cocoapods调试框架搭建完毕!

自定义pod命令

在lib目录下创建command专门存放自己定义的命令rb:

//在我们重写nyc.rb
require 'cocoapods'
module Pod
    class Command
        #<代表继承
      class NYC < Command
        self.summary = 'NY bin'
        self.description = 'NY bin'

      def initialize(argv)

        super
      end

      #实际你处理命令的地方
      def run
        p '111'
      end

      #-----------------------------------------------------------------------#
      end
    end
end

//在NY_bin 下引用nyc
if $PROGRAM_NAME == __FILE__
    ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile',__dir__)
    require 'bundler/setup'
end

require "cocoapods-cat-bin/command/nyc"

#pod cat
Pod::Command.run(ARGV)

//nyc.rb  追加
    def self.options
            [
              ['--platforms=ios,macos', 'Lint against specific platforms (defaults to all platforms supported by the ' \
                'podspec). Multiple platforms must be comma-delimited'],
              ['--library', '构建静态产物,默认为true'],
              ['--framework', '构建静态Framework,默认为false'],
              ['--dynamic', '构建动态Framwork,獸认为false'],
              ['--configuration', 'Build the specified configuration. Default to Release'],
              ['--sources', '构建工程需要依赖的sources源']
            ].concat(super).uniq
          end

        def initialize(argv)
          super
          #内置的解析工具
          # ? --> 真 假 Bool
          # 符号 
          @product_type = :framework
          # dynamic framework
          argv.flag?('dynamic', false)
          # .a
          argv.flag?('library', false)
          # static framework
          argv.flag?('framework', false)
          # 组件支持的platfrom
        end

运行结果: image.png [注意:cocoapod 会自动生成一个inckude文件夹来引入头文件,可能会跟实际本地路径重复引入]

查询DSL语法,根据具体DSL语法查看意思。

module Pod
    class Command
        #<代表继承
      class NYC < Command
        class Build < NYC
          self.summary = '制作二进制包'
          self.description = '制作二进制包'

          def self.options
              [
                ['--platforms=ios,macos', 'Lint against specific platforms (defaults to all platforms supported by the ' \
                  'podspec). Multiple platforms must be comma-delimited'],
                ['--library', '构建静态产物,默认为true'],
                ['--framework', '构建静态Framework,默认为false'],
                ['--dynamic', '构建动态Framwork,獸认为false'],
                ['--configuration', 'Build the specified configuration. Default to Release'],
                ['--sources', '构建工程需要依赖的sources源']
              ].concat(super).uniq
            end
            def initialize(argv)
              super
              #内置的解析工具
              # ? --> 真 假 Bool
              # 符号 
              @product_type = :framework
              @product_type = :static_library if argv.flag?('library',false)
              @product_type = :dynamic_framework if argv.flag?('dynamic',false)
              # 组件支持的platfrom - platfrom=ios,macos
              @platforms      = argv.option('platforms','').split(',')
              @configuration  = argv.option('configuration','Release')
              @sources = []
              @podspec_paths = []
          end
          #本地库 -->网络  --> 去下载(拦截(本地)) --> copy Pods clean
          # platfrom --> xcode工程 --> 4Xcode工程(涉及到4文件的copy删除)
          # 实际你处理命令的地方
        def run
          # 1. copy 工程
          # 当前路径的上一层
          copy_path = Pathname.pwd.parent
          name = File.basename(Pathname.pwd)
          # 到
          root_path = root.join(name)
          FileUtils.rm_rf(root_path)
          root.mkpath
          FileUtils.cp_r(Pathname.pwd, root)
          # 2.工程
          generator = ProjectGen::ProjectGenerator.new(podspecs_to_build.first, [], @platforms)
          generator.local = false
          generator.no_clean = false
          generator.allow_warnings = true
          generator.no_subspecs = true
          generator.only_subspec   = false
          generator.use_frameworks = @product_type == :dynamic_framework
          generator.use_static_frameworks = @product_type == :framework
          # generator.use_modular_headers = use_module
          generator.skip_import_validation = true
          # generator.external_podspecs = include_podspecs.drop(1)
          # generator.swift_version = swift_version
          generator.configuration = @configuration
            generator.skip_tests = true
            begin
                generator.generate!(app) do |platform, pod_targets, validated|
                    raise 'Could not generator App.xcodeproj' unless validated

                end
            rescue StandardError => e
                raise Pod::Informative, "The `#{@include_podspecs.join(' ')}` specification does not validate." \
                                "\n\n#{e.message}" 
            end 

        #自动生成工程--》三方库引入

        # 3. 编译 --》
        # 4. xcframework
        end

        def root 
          Pathname.new("/private/tmp/cocoapods-bin")
        end

        def app 
          root.join('App')
        end
        # .podspec
          # .podspec.json
          def podspecs_to_build
            if @podspec_paths.empty?
              @podspec_paths = Pathname.glob(Pathname.pwd + '*.podspec')
              if @podspec_paths.empty?
                raise Informative, 'Unable to find a podspec in the working ' \
                  'directory'
              end
            end
            @podspec_paths
          end
        end
      #-----------------------------------------------------------------------#
      end
    end
end

问题1:

LoadError - cannot load such file – cocoapods/command/gen

gem 'cocoapods-project-gen'  =>gemfile中

bundle install

补充知识

1.xcode索引速度跟xcodeproj 大小有关系,如何让xcode快速索引读取xcodeproj文件呢? image.png COMPILER_ INDEX_ STORE_ ENABLE 如果自己的插件clang编译器使用时,需要关闭此项。

2.xcode配置小知识:gemfile.lock这个文件可以不删错。通过制定更新gem插件来install项目:

bundle install --conservative rake xxx

3.ruby->vscode配置如果port被占用可以在launch.json添加 "debuggerPort": "8888",和"cwd": "${workspaceRoot}",cwd增加工作目录、"useBundler": true,true是需要在gemfile内精确配置Bundler使用版本,env配置当前ruby使用的环境变量: image.png