编程技术记录

世界你好!

一个因为swift name mangled符号不一致导致的错误:

dispatch thunk of Alamofire.MultipartFormData.append(_: Foundation.Data, withName: Swift.String, fileName: Swift.String?, mimeType: Swift.String?) -> ()", referenced from:

先说工程结构
工程A有一个静态framework target a,通过cocoapods以源码方式集成了封装Alamofire,封装Alamofire的一些能力。

 workspace A
              |____ a (源码)
              |____Alamofire (源码)

构建输出静态framework a。

工程B有一个App Target,通过cocoapods以源码方式集成封装Alamofire,以静态库方式集成了 a。

 workspace B
             |___App
                      |____ a (静态库)
                      |____ Alamofire (源码)
 ```

 在同一电脑,用同一个Xcode,设置了相同的swift version,结果App构建失败,找不到Alamofire里的符号。

经过一番观察,发现 "dispatch thunk of Alamofire.MultipartFormData.append(...)"是 Swift 编译器为带有默认参数、可变签名或需要方法桥接的函数生成的“thunk”符号。也就是说静态库a引用了这些由 Alamofire 生成的编译器私有符号,但最终链接器没有在任何被链接的库/框架中找到对应实现。

 检查工程配置,首先排除Alamofire 的实现没有被链接到最终可执行文件(常见:静态库a引用但 App 没把 Alamofire 链接上)。

那么,最有可能的情况就是:工程B的Alamofire 与 工程A  使用不同的 Swift 编译环境/选项,导致 thunk 的名称/生成方式不一致,最终没有可匹配的符号。虽然Alamofire代码一摸一样,但是编译后的符号修饰方式不一样。

示意例子,例如同样是方法 test,
工程A中被修饰为 _$s12Alamofire4testtKF
工程B中被修饰为
$s12Alamofire4test_tKj



有了排查方向,经过对比工程A和工程B的配置,最终发现cocoapods自动生成target Alamofire的配置有些许不一致 

Build Libraries for Distribution 这个配置不一样,一个是YES,一个是NO。
又经实验,发现如果依赖Alamofire的target的 Build Libraries for Distribution 配置为YES,那么cocoapods自动生成的Alamofire对应的配置也是YES。

最后,只要将Alamofire对应Build Libraries for Distribution设置为NO(保持一致)就解决了Undefined symbols问题。

发表回复