IOS里的库
https://www.jianshu.com/p/b0f58bae27db
https://juejin.cn/post/6950926098595053582
静态库形式: .a和.framework
1.静态库在编译时加载,链接时会完整的复制到可执行文件中。
2.静态库的可执行文件通常会比较大,因为所需的数据都会被整合到目标代码中,因此编译后的执行文件不需要外部库的支持,直接就能使用。
3.有多个app使用就会被复制多份,不能共享且占用更多冗余内存。
4.所有的函数都在库中,因此当修改函数时需要重新编译。
.a 和 .framework 的区别
.a 是单纯的二进制文件,.framework是二进制文件+资源文件。
其中.a 不能直接使用,需要 .h文件配合,而.framework则可以直接使用。
.framework = .a + .h + sorrceFile(资源文件)
动态库
动态库形式: .dylib和.framework
1.动态库在程序运行时由系统动态加载到内存,供程序调用,如果环境缺少动态库或者库的版本不正确,就会导致程序无法运行。
2.动态库的文件会比较小,因为在编译过程中,数据并没有整合到目标代码中,只有在执行到该函数时才去调用库中的函数,所以首次加载时比较耗时。
3.多个程序可以共享内存中同一份库资源,系统只加载一次,多个程序可共用,节省内存空间。
4.库是动态的,因此修改库中函数时,不需要重新编译。
iOS8之前苹果是不允许第三方框架使用动态库方式实现的,但是iOS8之后添加了App Extesion,Extesion 需要与主App共享代码,而且新加入的Swift的语言机制也需要动态库,于是苹果提出了Embedded Framework概念,这种动态库允许App和App Extension共享代码,但是这份动态库的生命被限定在一个App进程内。简单点可以理解为被阉割的动态库。
与系统的动态Framework 不同,使用 Cocoa Touch Framework 制作的动态库 在打包和提交 App 时资源文件会被放到 App main bundle 的根目录文件下,运行在沙盒里,而不是系统中。所以,不同的 App 即使使用了同样的 Framework,仍然需要被分别签名,打包和加载。
iOS 系统下 Framework 分类
Static Framework
静态库,用户生成。
Embedded Framework
允许用户生成的“动态库”类型。
创建一个动态库
添加2个功能文件。
// Adder.h#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN@interface Adder : NSObject/*** 计算两个整数的和。** @param firstNumber 第一个整数。* @param secondNumber 第二个整数。** @return 两个整数的和。*/
- (NSInteger)addFirstNumber:(NSInteger)firstNumber toSecondNumber:(NSInteger)secondNumber;@endNS_ASSUME_NONNULL_END
// Adder.m#import "Adder.h"@implementation Adder- (NSInteger)addFirstNumber:(NSInteger)firstNumber toSecondNumber:(NSInteger)secondNumber {NSInteger sum = firstNumber + secondNumber;NSLog(@"Adding %ld and %ld results in %ld", (long)firstNumber, (long)secondNumber, (long)sum);return sum;
}@end
更改最小版本支持
公开的头文件
如果必须在fworkTest.h这个系统生成的头文件里面import公开的头文件。
生成设置
选择framework类型
3.1 选择framework类型
Skip Install 设置
Skip Install 设置决定了在构建过程中是否生成产品文件。如果此选项设置为 YES,Xcode 不会生成 Framework 文件。
工程其他相关配置
Build Settings中Link下面的Dead Code Stripping设置为NO:先不进行死代码剥离。
Build Settings中Link下面的Link With Standard Libraries设置NO:避免重复链接
Build Settings中Build Active Architecture Only设置为NO, 如果设为YES,会导致其编译时只生成当前机器的框架;将其设置为NO后,发现用模拟器编译后生成的framework同时包含x86_64和i386架构。在 Excluded Architectures里Release模式下排除模拟器Any iOS Simulator SDK。因为xcode12生成的模拟器版本静态库会多包含一个arm64架构,这样会妨碍后面模拟器版本和真机版本合并,这样设置就可让模拟器版本没有arm64架构。
打包
找到路径
cd 路径
cd ..
ls
open 目录名
找到该动态库
测试使用
常用命令
查看支持架构
cd fworkTest.framework
lipo -info fworkTest
输出
Non-fat file: fworkTest is architecture: arm64显示为fat file,则表明是模拟器和真机的聚合包。fat file,顾名思义,胖文件。
相应的,非聚合包就是瘦文件,则输出Non-fat file: fworkTest is architecture: arm64之类的
查看是静态库还是动态库
file fworkTest
fworkTest: Mach-O 64-bit dynamically linked shared library arm64
// dynamically linked shared library表明这是一个动态库fworkTest: current ar archive random library
// archive 表明这是一个静态库
合并动态库
一个模拟器的arm和真机的arm。
使用lipo -create
lipo -create \
Release-iphoneos/fworkTest.framework/fworkTest \
Release-iphonesimulator/fworkTest.framework/fworkTest \
-output fworkTest-universal.framework/fworkTest
报错:
fatal error: /Library/Developer/CommandLineTools/usr/bin/lipo: Release-iphoneos/fworkTest.framework/fworkTest and Release-iphonesimulator/fworkTest.framework/fworkTest have the same architectures (arm64) and can't be in the same fat output file
fworkTest.framework 的架构都是 arm64,这意味着它们实际上是相同的架构,没有必要通过 lipo 合并。
模拟器版本的框架是为 arm64 构建的(适用于 Apple Silicon 芯片的 Mac 上的模拟器)。
真机版本的框架也是 arm64 构建的。
由于它们架构相同,lipo 工具无法合并同一架构的文件。
尽管它们的架构是相同的,但它们的运行环境不同,模拟器版本的动态库无法直接在真机上使用,反之亦然。
XCFramework
xcodebuild -create-xcframework \
-framework Release-iphoneos/fworkTest.framework \
-framework Release-iphonesimulator/fworkTest.framework \
-output fworkTest.xcframework
这样生成的 fworkTest.xcframework 将兼容真机和模拟器,即使它们的架构是一样的,使用时也能避免任何环境问题。
报错 xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
(base) weihangli@weihanglidebijibendiannao Products %
ChatGPT 说:
ChatGPT
这个错误说明你当前的开发者工具路径(Developer Directory)指向了 Command Line Tools,而不是完整的 Xcode 安装路径。要使用 xcodebuild 创建 XCFramework,需要确保开发工具的路径正确指向你的 Xcode 安装目录。
1、检查系统中可用的 Xcode 路径:
xcode-select -p
如果输出的路径是 /Library/Developer/CommandLineTools,说明目前默认的是命令行工具。
2、将开发工具路径更改为完整的 Xcode:
sudo xcode-select -switch /Applications/Xcode.app
这里的路径 /Applications/Xcode.app 是默认的 Xcode 安装路径。如果你的 Xcode 安装在其他位置,请替换为实际路径。
3、验证路径是否已正确切换:
xcode-select -p
正确的输出应该是 /Applications/Xcode.app。
再次尝试创建 XCFramework。
生成成功:
通用 Framework 的标准开发流程
通用 Framework 的标准开发流程
-
明确需求和架构支持
目标是支持两种环境:
模拟器(x86_64 或 arm64,取决于你的 Mac 是 Intel 芯片还是 Apple Silicon 芯片)。
真机(arm64)。 -
生成真机和模拟器的 Framework
使用 Xcode 的 Build Scheme 构建以下两个版本的 Framework:
Release-iphoneos:为真机生成 arm64 的 Framework。
Release-iphonesimulator:为模拟器生成 x86_64(Intel Mac)或 arm64(Apple Silicon)的 Framework。
你可以通过以下步骤生成:
选择 Generic iOS Device 或一个具体的 iOS 设备,然后构建项目,生成 Release-iphoneos 文件。
选择 Any iOS Simulator 或具体的模拟器设备,然后构建项目,生成 Release-iphonesimulator 文件。
生成2个架构的模拟器。
- 创建通用 Framework
从这里有两种选择:Fat Framework 和 XCFramework。推荐使用 XCFramework。
推荐方法:XCFramework
Apple 从 Xcode 11 开始推荐使用 XCFramework,它比传统的 Fat Framework 更灵活,并支持更广泛的平台。
4.1 创建 XCFramework
用以下命令直接生成通用的 XCFramework:
xcodebuild -create-xcframework \
-framework Release-iphoneos/YourFramework.framework \
-framework Release-iphonesimulator/YourFramework.framework \
-output YourFramework.xcframework
生成的 XCFramework 会包含:
真机架构:arm64。
模拟器架构:x86_64 和/或 arm64。
传统方法:Fat Framework
如果你确实想用 Fat Framework(不推荐,因为会增加文件体积),可以通过 lipo 合并真机和模拟器的 Framework:
进入终端,使用以下命令合并:
lipo -create \
Release-iphoneos/YourFramework.framework/YourFramework \
Release-iphonesimulator/YourFramework.framework/YourFramework \
-output YourFramework.framework/YourFramework
用合并后的 Framework 替换原来的 Framework 文件。
重新使用lipo来合并
现在生成了模拟器的arm和x86,真机的arm
(base) weihangli@weihanglidebijibendiannao Products % lipo -create \
Release-iphoneos/fworkTest.framework/fworkTest \
Release-iphonesimulator/fworkTest.framework/fworkTest \
-output fworkTest-universal.framework/fworkTest
fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: Release-iphoneos/fworkTest.framework/fworkTest and Release-iphonesimulator/fworkTest.framework/fworkTest have the same architectures (arm64) and can't be in the same fat output file
(base) weihangli@weihanglidebijibendiannao Products %
当模拟器版本的 Framework 同时包含 arm64 和 x86_64 架构,而真机版本的 Framework 仅包含 arm64 架构时,无法直接用 lipo 合并,因为它们的架构列表不完全匹配。
问题原因
真机版本 (Release-iphoneos) 的 Framework 仅包含 arm64。
模拟器版本 (Release-iphonesimulator) 的 Framework 包含 arm64 和 x86_64。
lipo 在合并时会尝试将所有架构合并到一个二进制文件中,但发现模拟器中有 x86_64,而真机中没有这个架构,因此无法完成合并。
lipo 要求合并的文件必须完全匹配所有架构,或者是独立的架构。
剥离多余架构(让架构完全匹配)
拆分命令:
1、提取 arm64 架构:
lipo -extract arm64 fworkTest.framework/fworkTest -output fworkTest_arm64
2、提取 x86_64 架构:
lipo -extract x86_64 fworkTest.framework/fworkTest -output fworkTest_x86_64
拆分命令:
- lipo -thin
功能:用于提取指定架构的 单一架构文件,并丢弃其他架构。
使用场景:当你只需要保留一个架构时(例如 arm64 或 x86_64),可以使用 lipo -thin。
示例:
从一个包含 arm64 和 x86_64 的 Fat 文件中提取 arm64:
lipo -thin arm64 fworkTest.framework/fworkTest -output fworkTest_arm64
输出的 fworkTest_arm64 文件只包含 arm64 架构。
所有其他架构(如 x86_64)会被完全丢弃。
2. lipo -extract
功能:用于提取指定架构,但不会丢弃其他架构。
使用场景:当你只需要单独操作某个架构,但希望保留原始文件的多架构特性时(如需要提取后重新合并),可以使用 lipo -extract。
示例:
从一个包含 arm64 和 x86_64 的 Fat 文件中提取 arm64:
lipo -extract arm64 fworkTest.framework/fworkTest -output fworkTest_arm64
输出的 fworkTest_arm64 文件只包含 arm64 架构。
原文件中的其他架构(如 x86_64)不会丢失——它只是提取了一份 arm64 的拷贝。