项目工程里已经使用 pod 进行了一部分内容的组件化,但是现在有个需求,需要把若干个组件打包成静态 framework 给别人用,请问如何实现? 我目前新建一个 framework 的工程并 Pod 需要的组件,但是生成的静态 framework 是不包含所依赖的 pod 的内容,如何才能包含所依赖的 pod 组件内容。
PS: 因为是给别人用的静态 Framework,希望达到放到别人工程里就能直接运行。
1
junho OP 有 SDK 开发经验的 V 友来回答下吗。。。
|
2
junho OP 自己想了下:
1.可以用动态库 2.把这若干个组件打包成 framework 再手动把 .o 文件合并?(未试过) 3.源码放在一起打包?(这个感觉违反了组件化思路,而且还要处理主项目 import framework,sdk 不需要问题 |
3
ldp940622 2019-09-05 01:49:21 +08:00
我使用过一些国产的 SDK 里面有包含了一些类似于 AFN、FMDB 这种第三方组件,他们都是通过直接拖源码 + 修改类名的方式集成的。。
|
4
kingcos 2019-09-05 09:07:27 +08:00 via iPhone
还要带依赖?那就合并了,在一块也有可能有重复符号的问题……
|
6
troyl 2019-09-05 16:09:30 +08:00 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。 思路就是这样,但是公司原因不能详谈实现。 祝顺利。 |
8
junho OP |
9
troyl 2019-09-05 20:09:38 +08:00 via iPhone
你可以用 `otool -l 壳工程的 binary` 来看到所有的 rpath dependency,那里就会暴露你的私有库,而且会让你的壳工程无法脱离私有库来使用,你 #2 楼的想法的第二条我觉得是可行的,你可以试试。
|
10
troyl 2019-09-05 20:14:08 +08:00 via iPhone
@junho #8 其实你倒不必纠结干预 link 这一点,那是因为当时 Swift 还不支持 Static Library,我们只好自己想办法来兼容 CocoaPods。现在支持了,就直接用吧。
|
11
troyl 2019-09-05 21:59:37 +08:00 via iPhone
@kingcos #4 这是个伪命题…… Swift 是支持 namespace 的,所以不同 module 里如果有相同的 symbol,这个是会加上 module 的前缀的,所以不会重复。如果是 Objective-C,那么它只有一层 namespace (实际上是两层,但对开发者来说只有一层),那么如果你的 project 或者你依赖的 library/framework 有相同的 symbol,那么在 link 的时候就会报错,编译是不会通过的。我唯一遇见的一次 duplicate symbol 是有一个 framework 静态链接了一个我们也依赖的第三方库,但是既然是第三方开源库,它就不应该静态链接,它应该声明这个 dependency,让开发者或者包管理软件来负责链接。
|
13
junho OP @troyl 再次请教下,请问如何做到 “需要消除 .swiftmodule 中对私有 framework 的 dependency”
举个例子,新建了一个动态 Framework 的工程,使用 pod 安装 Snapkit,然后 build 出 framework 后放到空白 App 工程里编译,App 工程就会报错 Cannot load underlying module for 'SnapKit'。就算我把 Framework 改成静态,然后把 libSnapKit 拉到 Link Binray with LIbraries 去,最后 App 工程还是会报一样的错 |