junho
V2EX  ›  iOS

如何把多个私有的 Pod 打包成一个静态 Framework?

  •  
  •   junho · Sep 4, 2019 · 5189 views
    This topic created in 2519 days ago, the information mentioned may be changed or developed.

    项目工程里已经使用 pod 进行了一部分内容的组件化,但是现在有个需求,需要把若干个组件打包成静态 framework 给别人用,请问如何实现? 我目前新建一个 framework 的工程并 Pod 需要的组件,但是生成的静态 framework 是不包含所依赖的 pod 的内容,如何才能包含所依赖的 pod 组件内容。

    PS: 因为是给别人用的静态 Framework,希望达到放到别人工程里就能直接运行。

    14 replies    2022-12-07 17:45:46 +08:00
    junho
        1
    junho  
    OP
       Sep 4, 2019
    有 SDK 开发经验的 V 友来回答下吗。。。
    junho
        2
    junho  
    OP
       Sep 4, 2019
    自己想了下:
    1.可以用动态库
    2.把这若干个组件打包成 framework 再手动把 .o 文件合并?(未试过)
    3.源码放在一起打包?(这个感觉违反了组件化思路,而且还要处理主项目 import framework,sdk 不需要问题
    ldp940622
        3
    ldp940622  
       Sep 5, 2019
    我使用过一些国产的 SDK 里面有包含了一些类似于 AFN、FMDB 这种第三方组件,他们都是通过直接拖源码 + 修改类名的方式集成的。。
    kingcos
        4
    kingcos  
       Sep 5, 2019 via iPhone
    还要带依赖?那就合并了,在一块也有可能有重复符号的问题……
    junho
        5
    junho  
    OP
       Sep 5, 2019
    @kingcos 怎么理解这个合并的意思?
    troyl
        6
    troyl  
       Sep 5, 2019 via iPhone
    Dynamic Framework 参数会使 Mach-O 文件产生 @rpath 依赖,你需要在编译私有 framework 干预中间 link 过程,这样才可以保证编译出来的 SDK 仍然是 dynamic 的,但所有私有的 object 全部都 statically linked 进你 SDK 的 binary 里。但这只是第一步,你仍然需要保证 SDK 的所有 public interface 全都不会使用私有 framework 中的 public type (return type, parameter type, etc.)。然而这仍然不够,因为,swift 的 interface 文件仍然会产生私有 framework 的 import dependency,而且,这个 interface 文件 (.swiftmodule) 是 binary,不可编辑,所以你需要一个 dummy interface generator 来暴露你希望暴露给第三方用户的接口,这样的好处是你可以控制暴露给第三方和 internal use only 的公有接口。
    这个方法对 Swift 1 以后的 project 都适用。当然,如果你的 project 是 Swift 4 以后的,你可以直接使用 Static Library。但仍需要消除 .swiftmodule 中对私有 framework 的 dependency。

    这是我在全部重写我司 SDK 成 Swift 2 的时候研究出来的,因为 pipeline 的需要,ship 给 3rd party 和 internal team 的 SDK 是一样的,但是 internal team 可以用我们的 private framework,而 3rd party 只会拿到一个包含所有 symbols,但是混淆过的 binary。

    思路就是这样,但是公司原因不能详谈实现。

    祝顺利。
    junho
        7
    junho  
    OP
       Sep 5, 2019
    @troyl 感谢回复
    junho
        8
    junho  
    OP
       Sep 5, 2019
    @troyl

    "Dynamic Framework 参数会使 Mach-O 文件产生 @rpath 依赖,你需要在编译私有 framework 干预中间 link 过程,这样才可以保证编译出来的 SDK 仍然是 dynamic " ===> 这个是怎么理解?因为是我的话会建立一个暴露接口的动态 framework 壳工程,然后 Pod 自己的私有组件(都是源码),这个过程中需要怎样额外处理 @rpath 和 link?
    troyl
        9
    troyl  
       Sep 5, 2019 via iPhone
    你可以用 `otool -l 壳工程的 binary` 来看到所有的 rpath dependency,那里就会暴露你的私有库,而且会让你的壳工程无法脱离私有库来使用,你 #2 楼的想法的第二条我觉得是可行的,你可以试试。
    troyl
        10
    troyl  
       Sep 5, 2019 via iPhone
    @junho #8 其实你倒不必纠结干预 link 这一点,那是因为当时 Swift 还不支持 Static Library,我们只好自己想办法来兼容 CocoaPods。现在支持了,就直接用吧。
    troyl
        11
    troyl  
       Sep 5, 2019 via iPhone
    @kingcos #4 这是个伪命题…… Swift 是支持 namespace 的,所以不同 module 里如果有相同的 symbol,这个是会加上 module 的前缀的,所以不会重复。如果是 Objective-C,那么它只有一层 namespace (实际上是两层,但对开发者来说只有一层),那么如果你的 project 或者你依赖的 library/framework 有相同的 symbol,那么在 link 的时候就会报错,编译是不会通过的。我唯一遇见的一次 duplicate symbol 是有一个 framework 静态链接了一个我们也依赖的第三方库,但是既然是第三方开源库,它就不应该静态链接,它应该声明这个 dependency,让开发者或者包管理软件来负责链接。
    junho
        12
    junho  
    OP
       Sep 25, 2019
    @troyl 谢谢回复哈,今天才发现后面的几条回复居然没有收到提醒
    junho
        13
    junho  
    OP
       Sep 26, 2019
    @troyl 再次请教下,请问如何做到 “需要消除 .swiftmodule 中对私有 framework 的 dependency”

    举个例子,新建了一个动态 Framework 的工程,使用 pod 安装 Snapkit,然后 build 出 framework 后放到空白 App 工程里编译,App 工程就会报错 Cannot load underlying module for 'SnapKit'。就算我把 Framework 改成静态,然后把 libSnapKit 拉到 Link Binray with LIbraries 去,最后 App 工程还是会报一样的错
    xiely
        14
    xiely  
       Dec 7, 2022
    @junho 我也遇到和你相同的问题,想把自己的代码和 pod 引用的第三方库代码一起打成 Framework 以供其它地方使用。这条问答有点年代了,不过还是想了解下在那之后你有没有实现这个功能。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   4369 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 42ms · UTC 05:33 · PVG 13:33 · LAX 22:33 · JFK 01:33
    ♥ Do have faith in what you're doing.