类库间的依赖 - ShenYj/ShenYj.github.io GitHub Wiki

类库间的依赖

对于项目开发中主程、开发类库、依赖库之间的依赖关系大概分为

动态库依赖动态库

  • @loader_path 这是一种模拟动态库嵌套依赖的场景

  • CocoaPods

    CocoaPods 中使用动态库,这可能会是一种常见的场景,比如同时使用 AlamofireMoya, Moya 会对 Alamofire 依赖,我们自己的项目中会对 Moya 依赖,同时也可以直接使用到 Alamofire

    使用场景有点类似于 @loader_path 中的示例,但不同点在于使用 CocoaPods管理类库时,类库间的依赖并不会拷贝嵌套,所有 CocoaPods依赖的库都会拷贝到主项目(也就是ipa)的 Frameworks 目录内, 参考 Pods-XXX-frameworks.sh

    在创作类库时,会指定类库的依赖项,CocoaPods在集成类库时,会分别对每个库生成 xcconfig 配置文件,为其配置链接参数,以动态库为例

    这是 Moyaxcconfig 中对 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 风险较大,随意书写的符号将也被忽略掉了

    按照符号和类库使用的原则,这样就能反向依赖

动态库依赖静态库

在动态库依赖静态库的时候,动态库会将静态库全部代码链接到动态库中,静态库中的导出符号在动态库中仍存在

如果不希望被依赖的静态库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开发-类库嵌套

⚠️ **GitHub.com Fallback** ⚠️