上一章讲了Xcode内置工具及pods调试。
一、Xcode组件二进制
介绍
Carthage:引入的库需要将Xcode工程文件配置清楚,Carthage会将其打包成xcframework(默认动态,默认组件二进制),同时需要手动copy-frameworks。如果需要静态,可以通过控制工程文件的framework类型实现。Carthage每个阶段都可以手动控制,对工程化的理解要求高。(Swift编写,功能清晰,方便串联)Cocoapods:属于简单式,只要熟悉Cocoapods内置的Podfile/Podspec内置的DSL,就能上手,不用考虑太多。所引入的库都是按照Cocoapods标准制作,会重新生成工程配置文件,而且需通过验证,使用成本极小。(用的多,Ruby编写,需要先生成工程文件,自己控制编译)
1、组件化
原理图1.
原理图2.
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"]
然后创建launch.json调试文件,在进行配置:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug ny bin",
"type": "Ruby",
"request": "launch",
"debuggerPort": "1236",
"program": "${workspaceRoot}/main.rb",
"args": [
]
}
]
}
报错1:
解决配置:
spec.summary = "bin gen tool"
spec.description = "bin gen tool"
spec.homepage = "https://github.com/CocoaPods/CocoaPods"
运行成功:
现在基本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
运行结果:
[注意: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文件呢?
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使用的环境变量: