类库间的依赖 - ShenYj/ShenYj.github.io GitHub Wiki
对于项目开发中主程、开发类库、依赖库之间的依赖关系大概分为
-
@loader_path 这是一种模拟动态库嵌套依赖的场景
-
CocoaPods
在
CocoaPods
中使用动态库,这可能会是一种常见的场景,比如同时使用Alamofire
和Moya
,Moya
会对Alamofire
依赖,我们自己的项目中会对Moya
依赖,同时也可以直接使用到Alamofire
使用场景有点类似于
@loader_path
中的示例,但不同点在于使用CocoaPods
管理类库时,类库间的依赖并不会拷贝嵌套,所有CocoaPods
依赖的库都会拷贝到主项目(也就是ipa)的Frameworks
目录内, 参考 Pods-XXX-frameworks.sh在创作类库时,会指定类库的依赖项,
CocoaPods
在集成类库时,会分别对每个库生成xcconfig
配置文件,为其配置链接参数,以动态库为例这是
Moya
在xcconfig
中对Alamofire
库文件路径的配置
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire"
若我们自己开发动态库时,遇到了动态库依赖
- 将依赖库拷贝到对应路径下(可以参考Pods-XXX-frameworks.sh)
- 利用
CocoaPods
在其他Target
下引入- 对环境配置有一定要求,例如
pod lib
那种结构,sdk、demo 被 workspace托管,哪个Target需要依赖库,就pod '被依赖的动态库'
哪怕workspace中包含多个sdk的target,通过Podfile
配置起来也都很方便
- 对环境配置有一定要求,例如
-
sdk(target) 反向依赖 主程序(target)
- 与使用类库本质相同,首先要保证主程序的导出符号对外可见,为sdk(target)配置正确的 header path
此时还无法编译通过,编译链接会去查找符号
- 链接器通过传递参数,可以将符号设置成动态查找,这样编译期找不到也不会报错了
-
-Xlinker undefined -Xlinker 符号名
单纯的将这个符号标记为动态查找 -
-Xlinker undefined -Xlinker dynamic_lookup
风险较大,随意书写的符号将也被忽略掉了
-
按照符号和类库使用的原则,这样就能反向依赖
- 与使用类库本质相同,首先要保证主程序的导出符号对外可见,为sdk(target)配置正确的 header path
在动态库依赖静态库的时候,动态库会将静态库全部代码链接到动态库中,静态库中的导出符号在动态库中仍存在
如果不希望被依赖的静态库api暴露,可以链接时修改静态库的导出符号的可见性
-
-hidden-l + 静态库名称
This is the same as the -lx for locating a static library, but treats all global symbols from the static library as if they are visibility hidden. Useful when building a dynamic library that uses a static library but does not want to export anything from that static library.
看具体应用场景
-
如果都是在一个项目中,比如同一个workspace托管下,库、程序都是以target的形式存在的话:
主程 -> 静态库1 -> 静态库2
,满足三要素,配置齐全即可,此时主程使用静态库2,就要给主程配置静态库的三要素;根据适当的场景,配置主程target的pod依赖也是可以的 -
如果是制作静态库包含了静态库,那么理论上最终的产物应该是一个合集
-
在探索静态库本质前,也从事过开发、维护SDK类项目,但对核心原理并不是很懂,在网上查阅过一些汇总资料,偏向于实战结论或是总结,比如
静态库: 1. framework嵌套framework, 不会被包含, 项目仍需导入被嵌套的framework 2. framework嵌套.a库, 可以, 如果项目也导入了.a库, 会符号表冲突, 处理方案: 加前缀 3. .a嵌套.a, 可以 4. .a嵌套framework, 不会将framework内容link到.a中, 项目仍需导入framework
现在来看我第二条的总结或许有些冲突,比如牵扯到framework,并没有像我分析的是合并
我个人的理解是framework本质上是.a的一层,或许正因为这层包装以及实际运用场景有关,也正是常见的使用场景,当使用的静态库又依赖了另一个framework时,我们的项目中需要手动集成如果自己的理解分析不对,也欢迎及时联系反馈,在此感谢
在这一次从底层探索前,也曾以实战项目的方式来探索,但是当时只实测了
.a
的几种场景: SDK开发-类库嵌套
-
- 如果是同一个workspace托管下,库、程序都是以target的形式存在的话,此情况有点类似于动态库链接动态库
主程链接了静态库-》 合并在一起; 静态库依赖动态库,就相当于主程用了动态库。这样理解就有点类似于动态库链接动态库了,需要集成一次
-
具体到
.a
、.framework
这种常见类型静态库: 1. framework嵌套framework, 不会被包含, 项目仍需导入被嵌套的framework 2. framework嵌套.a库, 可以, 如果项目也导入了.a库, 会符号表冲突, 处理方案: 加前缀 3. .a嵌套.a, 可以 4. .a嵌套framework, 不会将framework内容link到.a中, 项目仍需导入framework 动态库: 1. framework嵌套.a, 可以, .a的内容会被link到framework中 2. framework嵌套静态framework, 可以, 会将静态的framework内容link到动态framework中 3. framwrokd嵌套动态framework, 不会被包含, 项目仍需导入依赖的framework
以上数据主要来源网络资料的汇总,个人实测 Demo 只统计了
.a
: SDK开发-类库嵌套