JHHK

欢迎来到我的个人网站
行者常至 为者常成

6.组件二进制(下)

目录

快速开始

插件介绍部分仅做了解(第一段视频)

组件二进制的这三节课信息量很大,命令行工具、cocoapods插件,最终怎么使用也没太明白 需要静下心来好好研究老师的ruby代码,编译部分根据第二段视频讲解的思路去一点一点的研究

二进制制作的思路:
1、生成app工程
2、获取多平台多架构的编译产物
3、制作xcframework
4、制作和使用二进制源

插件介绍

一、插件如何调试

cocoapods在执行命令的时候,比如 pod install
内部会加载插件,同时会扫描gems目录下安装的gem,在每个gem里边会去查找cocoapods_plugin.rb文件
如果存在就进行加载,就会作为cocoapods的三方插件

launch.json文件如下:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug Cat Bin",
            "type": "rdbg",
            "request": "launch",
            "script": "${workspaceRoot}/bin/cat_bin",
            "args":[
                "install", "--project-directory=${workspaceRoot}/../TestApp"
            ]
        }
    ]
}

cat_bin文件内的代码

# 打印所有 gem 的最新版本的规范
Gem::Specification.latest_specs(true).map do |spec|
  puts spec.full_name
end


# 这一行的条件检查是在确保当前文件是直接被执行而不是被其他文件引用时才执行以下的代码块
# $PROGRAM_NAME 是 Ruby 程序当前运行的文件名
# __FILE__ 是当前文件的路径
if $PROGRAM_NAME == __FILE__

  # ENV['BUNDLE_GEMFILE'] 是一个环境变量,用于指定 Bundler 应该使用的 Gemfile 路径。
  ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', __dir__)

  # require 'bundler/setup' 是加载 Bundler 的设置文件,它通常用于确保项目的 Gemfile 中列出的依赖被正确加载和设置。
  # 这一行的作用是确保在运行当前脚本时,Bundler 能够加载并设置项目的 gem 环境,以及正确解析和加载 Gemfile 中的依赖项。
  require 'bundler/setup'
end

# 可以对比下再bundler/setup之后跟之前有什么区别
Gem::Specification.latest_specs(true).map do |spec|
  puts spec.full_name
end

Pod::Command.run(ARGV)

cocoapods_plugin.rb文件内的代码,插件的hook方法调用

module Pod
    module CocoaPodsCatBinHook
      HooksManager.register('cocoapods-cat-bin', :pre_install) do |context, option|
        #
        puts "lxy:pre_install"
        # p context, option
      end
      HooksManager.register('cocoapods-cat-bin', :pre_integrate) do |context, option|
        #
        puts "lxy:pre_integrate"
        # p context, option
      end
      HooksManager.register('cocoapods-cat-bin', :post_install) do |context, option|
        #
        puts "lxy:post_install"
        # p context, option
      end
      HooksManager.register('cocoapods-cat-bin', :post_integrate) do |context, option|
        #
        puts "lxy:post_integrate"
        p context, option
      end
    end
end

TestApp工程内的podfile文件

platform :ios, '9.0'

plugin 'cocoapods-cat-bin'
target 'TestApp' do
  use_frameworks!
  pod 'SDWebImage'
end

在vscode中进行调试时,会进入cocoapods_plugin.rb文件内注册的插件回调
在回调内我们可以调用我们gem工程中的命令

pre_install:Pod下载之后但在安装之前对Pod进行任何更改 

pre_integrate:将生成的Xcode项目写入磁盘之前 

post_install:生成的 Xcode 项目写入磁盘之前对其进行任何最后更改 

post_integrate:在项目写入磁盘后进行更改

二、讲解过程中的截图

咱也不知道老师到底在讲啥,先做记录吧

大概意思是不会采用这种插件方式,这里只是介绍下插件,要采用命令的方式

先往后听课。。。

rake install:local 命令会将开发中的gem安装到本地进行调试

编译

一、选择使用Build还是Archive去编译?

  1. Build产物目录不能直接控制,Archive可直接控制
  2. Build动态库的调试符号放在framework下,Archive 放在指定目录下
  3. Archive对xcframework格式支持的更好
    所以选择 Archive 进行编译

二、关于swift的 BUILD_LIBRARY_FOR_DISTRIBUTION 选项

app工程 + 使用了swift库
访问swift库内的Teacher.kody=1

当swift库的代码Teacher.kody=2修改编译后,app工程不编译直接运行,这时会打印Teacher.kody=2
因为访问内存的位置没有变,但内存内存放的内容变了

但当swift库的代码Teacher.kody=”工程化”修改编译后,app工程不编译直接运行
因为访问内存的位置没有变,但内存内存放的内容变了,而且数据类型也变了
所以这时打印的内容就变成Teacher.kody=1765893737

BUILD_LIBRARY_FOR_DISTRIBUTION选项打开后就不会出现上面的问题,库的加载会推迟到运行时确定,但会增加性能的消耗

OC自动就能做上边的事情

swift中 @frozen的用法:让代码冻住,不要推到运行时才去决定

在调试阶段,我们应该打开这个选项,可以避免因为swift库的版本更新和编译器版本的不同,造成的错误。

扩展说明

1、修改产物路径:参考cocoapods是如何修改产物路径的,前边的工程化的文章也提到过,可以翻翻前边的文章
CONFIGURATION_BUILD_DIR

2、
稳定的ABI,也就是mach-o的格式已经固定了,可以按照固定的格式去解析mach-o文件了

三、编译命令

# 打开swift的 BUILD_LIBRARY_FOR_DISTRIBUTION 这个选项
xcodebuild clean archive BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
# 如果不指定configration默认是release,一般也都是编译release的产物
-project 'Pods/Pods.xcodeproj' \
# 在这里指定Pods-App就不用单独指定某一个了,比如像realm-swift-master这个三方库有realm和realmSwift,就不用单独指定某一个了
-scheme 'Pods-App' \
# generic/ 代表一个通用的机型,我就不指定了你帮我找一个就行 
-destination "generic/platform=iOS Simulator" -sdk ‘iphonesimulator’ \
-archivePath './archive/Pods-App.xcarchive' \

# SKIP_INSTALL=NO 这个关掉,产物才会放到archive的目录里
SKIP_INSTALL=NO -showBuildTimingSummary
# 按照默认的架构进行编译
-destination "generic/platform=iOS Simulator" \

# 执行下面指令
xcodebuild clean archive BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
-project 'Pods/Pods.xcodeproj' \
-scheme 'Pods-App' \
-destination "generic/platform=iOS Simulator" \
-showBuildSettings

# 查看下ARCHS这个变量指定的架构
# 这两个选项都指定了,就可以按照三方库指定的架构进行编译
-destination "generic/platform=iOS Simulator" -sdk ‘iphonesimulator’ \

xcodebuild clean archive BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
-project 'Pods/Pods.xcodeproj' \
-scheme 'Pods-App' \
-destination "generic/platform=iOS Simulator" -sdk 'iphonesimulator' \
-showBuildSettings

# showbuildsetting后查看ARCHS,就可以知道当前编译的是什么架构    

四、头文件处理

.a库和.framework的头文件的处理要注意下

.a库:关掉useframework选项后,去观察下Pods-LGApp.debug.config文件内指定的头文件的搜索路径
就知道cocoapods对.a的库的头文件是如何处理的:会放在指定的目录下,一个private目录,一个public目录

.framework:打开useframework选项后,去观察下Pods-LGApp.debug.config文件内指定的头文件的搜索路径
.framework的头问件是放在内部打包在一起的,没有单独的目录

cocoapods项目中的:def link_headers 是相关的处理方法

如果是swift库的头文件的处理比较复杂
module文件和xxx-swift.h等等都需要放在一个文件夹内提供出去

五、编译的产物放到一个目录里

制作xcframwork

创建私有库使用二进制源

要使用podspec.json的格式

podspec内,xcframework只能使用:vendored_frameworks


行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.