动态库下(5)
XCFramework
XCFramework: 是苹果官方推荐的, 支持的, 可以更方便的表示一个多个平台和架构的分发二进制库的格式.
需要Xcode11以上支持.
是为更好的支持Mac Catalyst和ARM芯片的macOS.专门在2019年提出的framework的另一种先进格式.
平时开发中会设计到的一些架构
- iOS/iPad: arm64
- iOS/iPad Simulator: x86_64 arm64
- Mac Catalyst: x86_64 arm64
- Mac: x86_64 arm64
和传统的framework相比
- 可以用单个.xcframework文件提供多个平台的分发二进制文件.
- 与Fat Header相比, 可以按照平台划分, 可以包含相同架构的不同平台文件.
- 在使用时, 不需要再通过脚本去剥离不需要的架构体系.
多架构合并
- SYTimer -> 编译生成几个不同的需要的架构
- xcodebuild archive -project 'SYTimer.xcodeproj' \ //指定project-scheme 'SYTimer' \ //指定scheme-configuration Release \ //指定编译的环境-destination 'generic/platform=iOS Simulator' //指定分发的架构平台-archivePath '../archives/SYTimer.framework-iphonesimulator.xcarchive' //指定输出路径SIKP_INSTALL=NO //只有指定为NO的时候才会进行拷贝,方便我们查看最终的编译产物
- xcodebuild -> 正常开发过程中使用的构建
- archive -> 代表打包
- 进行真机的架构打包
- xcodebuild archive -project 'SYTimer.xcodeproj'
-scheme 'SYTimer'
-configuration Release
-destination 'generic/platform=iOS'
-archivePath '../archives/SYTimer.framework-iphoneos.xcarchive'
SKIP_INSTALL=NO - SYTimer
- xcodebuild archive -project 'SYTimer.xcodeproj'
- 通过lipo命令合并
- 注意库文件的合并,支持放在一起,进行压缩,并不是真正意义上的合并
- lipo命令最大的问题就是相同的架构不能合并. 例如:两个库都有同一种架构
- lipo
- xcFramework
- xcFramework的使用
- 直接将生产的xcframework拖拽到 -> targets/general/frameworks
- 引入头文件 #import <SYTimer/SYTimer.h>
- XCode编译器,会根据你的程序编译对象,自动选择相应的架构
动静态实战
weak_import
- 项目链接SYTimer
// 2. -F: frmaework 所在的目录
FRAMEWORK_SEARCH_PATHS = $(inherited) ${SRCROOT}
// 1. -I :头文件
HEADER_SEARCH_PATHS = $(inherited) ${SRCROOT}/SYTimer.framework/Headers
// 路径
// "/Users/ws/Desktop/VIP课程/第五节、动态库与静态库实战/完成代码/动态库与静态库实战/weak_import/LGApp"
LD_RUNPATH_SEARCH_PATHS = $(inherited)
// 3. 名称
// null -》 runtime -〉 nil
// weak_import
// library
OTHER_LDFLAGS = $(inherited) -Xlinker -weak_framework -Xlinker "SYTimer"
静态库冲突
- APP 链接 AFNetworking静态库
//-I
HEADER_SEARCH_PATHS = $(inherited) "${SRCROOT}/AFNetworking" "${SRCROOT}/AFNetworking2"
//-L
LIBRARY_SEARCH_PATHS = $(inherited) "${SRCROOT}/AFNetworking" "${SRCROOT}/AFNetworking2"
//-l
// 冲突
// all_load
// -ObjC
// 两个静态库 -》 库
OTHER_LDFLAGS = $(inherited) -l"AFNetworking" -l"AFNetworking2" -Xlinker -force_load -Xlinker "${SRCROOT}/AFNetworking/libAFNetworking.a"
- 编译的时候并没有冲突, 是因为专门为静态库设计的 -noall_load
- 这时使用all_load,以及-ObjC都不行, 都会将冲突暴露出来
- 使用-force_load 来只链接其中一个
- 将其中一个链接生成为动态库.也可以解决
SDK建议:
- 一个成熟的SDK,没有理由用了一堆其他的SDK
- SDK -> 基本上都是动态库
动动
- App -> 使用自己的动态库 -> 自己的动态库使用了其他的动态库.例:AFNetworking
- 两种解决方案
- 脚本copy,参考cocoapods的sh脚本
- 注意,cocoapods提供动态库的时候,支持提供了链接参数,并没有将动态库copy,只不过最后通过脚本进行了copy
-
cocoapods, 重新引入其他的动态库到APP
image.png
- 脚本copy,参考cocoapods的sh脚本
- 反依赖的情况, 动态库 -> APP
- 需要APP将需要的头文件暴露出来
- Build Phases -> Headers -> project -> 添加需要暴露的头文件 -> 移动到Public
- xcconfig -> HEADER_SEARCH_PATH 的头文件暴露
- 导入头文件
- 编译报错 -> 让APP运行起来,dyld就能找到 -> -undefined
- OTHER_LDFLAGS = ... -Xlinker -undefined -Xlinker dynamic_lookup -> 这种写法风险比较大,不建议
- OTHER_LDFLAGS = ... -Xlinker -U -Xlinker OBJC_CLASS
_LGAppObject为动态库查找的符号
- 此时已经反依赖成功.
- 需要APP将需要的头文件暴露出来
动静
-
关闭cocoapods的user_frameworks! -> 表明引入的是静态库
image.png
- 动态库会将所引用的静态库代码链接
- 静态库所有的导出符号相对于动态库来说,还全是导出符号
- 问题: 给别人提供动态库的时候,不想暴露静态库
- OTHER_LDFLAGS = $(inherited) -ObjC -Xlinker -hidden-l "AFNetworking" -> 可以达到符号的可见性
静静
- 关闭 use_framerworks -> 表明拉取的是静态库
- app + 静态库 没问题
- 组件静态库 + 组件链接的静态库 -> 有问题,组件链接的静态库相对于APP没有告诉APP链接的三要素
- 手动配置三要素,头文件不用了, 需要配置静态库路径,以及静态库名称
静动
- APP = APP + 静态库 -> 相当于APP直接使用动态库
- 静态库 -> 动态库
- 配置framework路径
- 进行一个跟上面一样的动动配置.脚本直接使用cocoapods提供的动态库的脚本就可以
- APP -> Build Phases -> Run Script -> 执行脚本就可以
- 执行脚本的作用就是,进行framework的拷贝
cocoapods即导入静态库又导入动态库
- use_frameworks! -> 来控制动静态库
- 以下代码达成的效果, 数组里面的都是静态库,不包含的还是默认动态库
target :'LGNetworkManager' do
use_frameworks!
# 静态库、动态库
# 指定需要被编译成static_framework的库
$static_framework = ['AFNetworking']
pre_install do |installer|
installer.pod_targets.each do |pod|
if $static_framework.include?(pod.name)
def pod.build_type;
Pod::Target::BuildType.static_framework
end
end
end
end
pod 'SDWebImage'
end
cocoapod 往不同的workspace以及target里面导入动态库的写法
platform :ios, '9.0'
#workspace '../MulitProject.xcworkspace'
target 'LGFramework' do
use_frameworks!
pod 'AFNetworking'
end
#target 'LGApp' do
# project '../LGApp/LGApp.xcodeproj'
#
# use_frameworks!
#
# pod 'AFNetworking'
#
#end
总结
- XCFramerwork的优点
- 解决头文件问题
- 解决调试符号问题
- 解决相同架构的处理
- 实战
- weak_import: 动态库 运行时不知道这个动态库是否存在 -> 可以使用weak_import来声明一下
- 静态库冲突 -> APP -> 不存在二级命名空间,并且all_load/-ObjC
- APP -> 动 动2 -> pod/脚本复制(比较推荐)
- reexport重新暴露动2的符号
- APP反向依赖
- APP -> 动 静 -> 静态库不想暴露 -> hidden-l
- APP -> 静 静2 -> 不知道静2的所在位置
- APP -> 静 动 -> 编辑就会报错 -> 不知道动态库的位置
- 运行时也会报错 -> 动rpath -> pod/脚本复制(比较推荐)
- 组件/库 -> 依赖不要太多,最好一个都没有 -> AFN做个封装
网友评论